From 477665f61fb983bd135fc133ef5a7bcf00897877 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 29 Dec 2025 19:16:12 +0000 Subject: [PATCH] oops bcn format --- externals/bc_decoder/bc_decoder.cpp | 172 +++++++++------------ src/video_core/texture_cache/decode_bc.cpp | 3 - 2 files changed, 71 insertions(+), 104 deletions(-) diff --git a/externals/bc_decoder/bc_decoder.cpp b/externals/bc_decoder/bc_decoder.cpp index 4edc2ab117..3b48afc322 100644 --- a/externals/bc_decoder/bc_decoder.cpp +++ b/externals/bc_decoder/bc_decoder.cpp @@ -168,88 +168,6 @@ namespace { namespace BC6H { static constexpr int32_t MaxPartitions = 64; - // @fmt:off - - static constexpr uint8_t PartitionTable2[MaxPartitions][16] = { - { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, - { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 }, - { 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 }, - { 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1 }, - { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 }, - { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1 }, - { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 }, - { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 }, - { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 }, - { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 }, - { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0 }, - { 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0 }, - { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 }, - { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, - { 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0 }, - { 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 }, - { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, - { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 }, - { 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0 }, - { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0 }, - { 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 }, - { 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 }, - { 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 }, - { 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 }, - { 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0 }, - { 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 }, - { 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 }, - { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0 }, - { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }, - { 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 }, - { 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 }, - { 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, - { 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0 }, - { 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0 }, - { 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 }, - { 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1 }, - { 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0 }, - { 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0 }, - { 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 }, - { 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1 }, - { 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 }, - { 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1 }, - { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, - { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, - { 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0 }, - { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1 }, - }; - - static constexpr uint8_t AnchorTable2[MaxPartitions] = { - 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, - 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, - 0xf, 0x2, 0x8, 0x2, 0x2, 0x8, 0x8, 0xf, - 0x2, 0x8, 0x2, 0x2, 0x8, 0x8, 0x2, 0x2, - 0xf, 0xf, 0x6, 0x8, 0x2, 0x8, 0xf, 0xf, - 0x2, 0x8, 0x2, 0x2, 0x2, 0xf, 0xf, 0x6, - 0x6, 0x2, 0x6, 0x8, 0xf, 0xf, 0x2, 0x2, - 0xf, 0xf, 0xf, 0xf, 0xf, 0x2, 0x2, 0xf, - }; - - // @fmt:on - // 1.0f in half-precision floating point format static constexpr uint16_t halfFloat1 = 0x3C00; union Color { @@ -793,15 +711,56 @@ namespace { uint64_t high64; void decode(uint8_t *dst, size_t dstX, size_t dstY, size_t dstWidth, size_t dstHeight, size_t dstPitch, size_t dstBpp, bool isSigned) const { - uint8_t mode = 0; + // @fmt:off + static const uint32_t p_table[MaxPartitions] = { + 0b01010000010100000101000001010000, 0b01000000010000000100000001000000, + 0b01010100010101000101010001010100, 0b01010100010100000101000001000000, + 0b01010000010000000100000000000000, 0b01010101010101000101010001010000, + 0b01010101010101000101000001000000, 0b01010100010100000100000000000000, + 0b01010000010000000000000000000000, 0b01010101010101010101010001010000, + 0b01010101010101000100000000000000, 0b01010100010000000000000000000000, + 0b01010101010101010101010001000000, 0b01010101010101010000000000000000, + 0b01010101010101010101010100000000, 0b01010101000000000000000000000000, + 0b01010101000101010000000100000000, 0b00000000000000000100000001010100, + 0b00010101000000010000000000000000, 0b00000000010000000101000001010100, + 0b00000000000000000100000001010000, 0b00010101000001010000000100000000, + 0b00000101000000010000000000000000, 0b01000000010100000101000001010100, + 0b00000000010000000100000001010000, 0b00000101000000010000000100000000, + 0b00010100000101000001010000010100, 0b00000101000101000001010001010000, + 0b00000001000101010101010001000000, 0b00000000010101010101010100000000, + 0b00010101000000010100000001010100, 0b00000101010000010100000101010000, + 0b01000100010001000100010001000100, 0b01010101000000000101010100000000, + 0b00010001010001000001000101000100, 0b00000101000001010101000001010000, + 0b00000101010100000000010101010000, 0b00010001000100010100010001000100, + 0b01000001000101000100000100010100, 0b01000100000100010001000101000100, + 0b00010101000001010101000001010100, 0b00000001000001010101000001000000, + 0b00000101000001000001000001010000, 0b00000101010001010101000101010000, + 0b00010100010000010100000100010100, 0b01010000000001010000010101010000, + 0b01000001010000010001010000010100, 0b00000000000101000001010000000000, + 0b00000000000001000001010100000100, 0b00000000000100000101010000010000, + 0b00010000010101000001000000000000, 0b00000100000101010000010000000000, + 0b01010000010000010000010100010100, 0b01000001000001010001010001010000, + 0b00000101010000010101000000010100, 0b00010100000001010100000101010000, + 0b01000001000001010000010100010100, 0b01000001010100000101000000010100, + 0b01000000000000010001010101010100, 0b01010100000101010000000101000000, + 0b01010000010100000101010100000000, 0b00000000010101010101000001010000, + 0b00010101000101010001000000010000, 0b01010100010101000000010000000100, + }; + static const uint8_t AnchorTable2[MaxPartitions] = { + 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, + 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, + 0xf, 0x2, 0x8, 0x2, 0x2, 0x8, 0x8, 0xf, + 0x2, 0x8, 0x2, 0x2, 0x8, 0x8, 0x2, 0x2, + 0xf, 0xf, 0x6, 0x8, 0x2, 0x8, 0xf, 0xf, + 0x2, 0x8, 0x2, 0x2, 0x2, 0xf, 0xf, 0x6, + 0x6, 0x2, 0x6, 0x8, 0xf, 0xf, 0x2, 0x2, + 0xf, 0xf, 0xf, 0xf, 0xf, 0x2, 0x2, 0xf, + }; + // @fmt:on + Data data(low64, high64); assert(dstBpp == sizeof(Color)); - - if ((data.low64 & 0x2) == 0) { - mode = data.consumeBits(1, 0); - } else { - mode = data.consumeBits(4, 0); - } + uint8_t mode = data.consumeBits((data.low64 & 0x2) == 0 ? 1 : 4, 0); int32_t blockIndex = modeToIndex(mode); // Handle illegal or reserved mode @@ -894,7 +853,7 @@ namespace { idx.num_bits = 3; // There are 2 indices with implicit leading 0-bits. isAnchor = ((pixelNum == 0) || (pixelNum == AnchorTable2[partition])); - firstEndpoint = PartitionTable2[partition][pixelNum] * 2; + firstEndpoint = ((p_table[partition] >> pixelNum) & 0x03) * 2; } idx.value = data.consumeBits(idx.num_bits - isAnchor - 1, 0); @@ -931,7 +890,7 @@ namespace { }; struct Mode { - const uint32_t IDX; // Mode index + const int32_t IDX; // Mode index const uint32_t NS; // Number of subsets in each partition const uint32_t PB; // Partition bits const uint32_t RB; // Rotation bits @@ -946,7 +905,7 @@ namespace { constexpr uint32_t NumColors() const { return NS * 2; } - constexpr Bitfield Partition() const { return {IDX + 1, PB}; } + constexpr Bitfield Partition() const { return {uint32_t(IDX) + 1, PB}; } constexpr Bitfield Rotation() const { return Partition().Then(RB); } @@ -1028,7 +987,7 @@ namespace { } Mode const& mode() const { - static const Mode m_table[8] = { + static const Mode m_table[8 + 1] = { // IDX NS PB RB ISB CB AB EPB SPB IB IBC, IB2 /**/ {0x0, 0x3, 0x4, 0x0, 0x0, 0x4, 0x0, 0x1, 0x0, 0x3, 0x2d, 0x0}, /**/ {0x1, 0x2, 0x6, 0x0, 0x0, 0x6, 0x0, 0x0, 0x1, 0x3, 0x2e, 0x0}, @@ -1038,6 +997,7 @@ namespace { /**/ {0x5, 0x1, 0x0, 0x2, 0x0, 0x7, 0x8, 0x0, 0x0, 0x2, 0x1f, 0x2}, /**/ {0x6, 0x1, 0x0, 0x0, 0x0, 0x7, 0x7, 0x1, 0x0, 0x4, 0x3f, 0x0}, /**/ {0x7, 0x2, 0x6, 0x0, 0x0, 0x5, 0x5, 0x1, 0x0, 0x2, 0x1e, 0x0}, + /**/ {-1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x00, 0x0}, }; // Fun historical fact: this is basically ffs(), however, windows does NOT have ffs() // This is because ffs() comes from VAX which had an instruction for ffs(), but @@ -1053,21 +1013,20 @@ namespace { else if ((low & 0b00100000) != 0) return m_table[5]; else if ((low & 0b01000000) != 0) return m_table[6]; else if ((low & 0b10000000) != 0) return m_table[7]; - return m_table[0]; //invalid but pretend it's fine + return m_table[8]; //invalid but pretend it's fine } struct IndexInfo { uint64_t value; - int64_t num_bits; + uint32_t num_bits; }; uint8_t interpolate(uint8_t e0, uint8_t e1, const IndexInfo &index) const { - static const uint16_t weightsN[5][16] = { - { 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0 }, - {0, 21, 43, 64}, // {0, 21, 43, 64} = (21 * n) + 1 - {0, 9, 18, 27, 37, 46, 55, 64}, - {0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64} + static constexpr uint16_t weights2[] = {0, 21, 43, 64}; + static constexpr uint16_t weights3[] = {0, 9, 18, 27, 37, 46, 55, 64}; + static constexpr uint16_t weights4[] = {0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64}; + static constexpr uint16_t const *weightsN[] = { + nullptr, nullptr, weights2, weights3, weights4 }; auto weights = weightsN[index.num_bits]; assert(weights != nullptr); @@ -1077,6 +1036,17 @@ namespace { void decode(uint8_t *dst, size_t dstX, size_t dstY, size_t dstWidth, size_t dstHeight, size_t dstPitch) const { assert(low <= 0b11111111); auto const& mode = this->mode(); + if (mode.IDX < 0) { + for (size_t y = 0; y < 4 && y + dstY < dstHeight; y++) { + for (size_t x = 0; x < 4 && x + dstX < dstWidth; x++) { + auto out = reinterpret_cast(dst + sizeof(Color) * x + dstPitch * y); + out->rgb = {0, 0, 0}; + out->a = 0; + } + } + return; + } + std::array, 3> subsets; for (size_t i = 0; i < mode.NS; i++) { auto& subset = subsets[i]; diff --git a/src/video_core/texture_cache/decode_bc.cpp b/src/video_core/texture_cache/decode_bc.cpp index 37f67d0cd7..7e18937667 100644 --- a/src/video_core/texture_cache/decode_bc.cpp +++ b/src/video_core/texture_cache/decode_bc.cpp @@ -23,11 +23,8 @@ using VideoCore::Surface::PixelFormat; constexpr bool IsSigned(PixelFormat pixel_format) { switch (pixel_format) { case PixelFormat::BC4_SNORM: - case PixelFormat::BC4_UNORM: case PixelFormat::BC5_SNORM: - case PixelFormat::BC5_UNORM: case PixelFormat::BC6H_SFLOAT: - case PixelFormat::BC6H_UFLOAT: return true; default: return false;