hglm / detex

Low-level library for decompression and manipulation of texture blocks compressed using formats such as BC1/DXT1/S3TC, BC2-BC3, BC4/RGTC1, BC5/RGTC2, BC6 (BPTC_FLOAT), BC7 (BPTC), ETC1 and the ETC2 family, loading of KTX and DDS files, and conversion between pixel formats
ISC License
155 stars 38 forks source link

serious BC7 decoder bugs #12

Open richgel999 opened 6 years ago

richgel999 commented 6 years ago

The BC7 encoder has a couple easily fixed bugs that cause it to fail on some blocks:

detexGetBits64() fails when bit1 is 63 (when built with VS2015 x64). I believe the original implementation relied on undefined behavior (shift left of 1 by 64 bits != 0 on some platforms). Here's the fix:

static DETEX_INLINE_ONLY uint32_t detexGetBits64(uint64_t data, int bit0, int bit1) 
{
    uint64_t mask;
    if (bit1 == 63)
    mask = UINT64_MAX;
    else
    mask = ((uint64_t)1 << (bit1 + 1)) - 1;

    return (data & mask) >> bit0;
}   

The other bug is in FullyDecodeEndpoints() - sometimes the endpoints do across between the two 64-bit values in a block:

static void FullyDecodeEndpoints(uint8_t DETEX_RESTRICT endpoint_array, int nu_subsets, int mode, detexBlock128 DETEX_RESTRICT block) { if (mode_has_p_bits[mode]) { // Mode 1 (shared P-bits) handled elsewhere. // Extract end-point P-bits. uint32_t bits; if (block->index < 64) { bits = block->data0 >> block->index; // Bugfix! if ((block->index + nu_subsets * 2) > 64) { bits |= (block->data1 << (64 - block->index)); } }

Once these 2 fixes are made this decoder outputs the same pixels as DirectXTex's.

moonfast commented 1 year ago

Confirm, i even made a pull request for it https://github.com/hglm/detex/pull/19