Fix SGD image desc indexing for 3D UASTC HDR 6x6i textures - #1237
Merged
MarkCallow merged 1 commit intoAug 7, 2026
Merged
Conversation
SashaRX
force-pushed
the
fix/hdr6x6i-3d-sgd-descriptor-index
branch
from
August 5, 2026 14:54
c06cc69 to
1737c68
Compare
SashaRX
marked this pull request as ready for review
August 5, 2026 14:59
Collaborator
|
Excellent catch. Thanks. As with PR #1236 , please sign the CLA. It should be sufficient to do it in just one PR. |
SashaRX
force-pushed
the
fix/hdr6x6i-3d-sgd-descriptor-index
branch
from
August 6, 2026 11:46
1737c68 to
9907965
Compare
MarkCallow
reviewed
Aug 6, 2026
SashaRX
force-pushed
the
fix/hdr6x6i-3d-sgd-descriptor-index
branch
from
August 6, 2026 13:17
9907965 to
96a144e
Compare
Contributor
Author
|
Done — switched the accumulation to the same |
MarkCallow
reviewed
Aug 6, 2026
The encoder writes the ktxUASTCHDR6x6IntermediateImageDesc table in level order, level 0 first, with each level contributing numLayers * numFaces * depth(level) image descriptions. The transcoder indexed it with level * levelImageCount + image using the current level's image count, which only matches that layout while every level has the same image count. For 3D textures depth halves with each level, so wrong descriptions - whose slice offsets are relative to a different level's data - were used and transcoding failed (or could read wrong slices). Accumulate per-level first-image indices instead, as transcodeEtc1s already does with its firstImages table. Since firstImages[numLevels] is the image count implied by the texture's dimensions, also validate the descriptor table size up front: a table that is not exactly that many descriptions, or not a whole number of them, is rejected with KTX_FILE_DATA_ERROR before any level is processed. Encoding a 24x24x8 3D texture with 4 mip levels to UASTC HDR 6x6 intermediate and transcoding it to ASTC_HDR_6x6_RGBA failed with KTX_TRANSCODE_FAILED before this change and succeeds after it; a 2D texture with identical parameters passes both before and after. Both cases are added to transcodetests as generated round-trip tests with no new binary test resources. Per review, both cumulative tables use the single-increment loop form (firstImages[l + 1] = firstImages[l] + ...); the ETC1S transcoder's existing table is restyled to match.
SashaRX
force-pushed
the
fix/hdr6x6i-3d-sgd-descriptor-index
branch
from
August 6, 2026 13:53
96a144e to
51be9de
Compare
MarkCallow
approved these changes
Aug 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes transcoding of 3D textures encoded to UASTC HDR 6x6 intermediate.
Problem
transcodeUastcHDR6x6_intermediateindexes the SGD image description table withusing the current level's image count. The encoder (
basis_encode.cpp) writes thektxUASTCHDR6x6IntermediateImageDescentries in level order, level 0 first, with each level contributingnumLayers × numFaces × depth(level)descriptions. The two agree only while every level has the same image count. For 3D textures depth halves with each mip level, so the transcoder selects descriptions belonging to other levels; since slice offsets are relative to their own level's data, transcoding fails withKTX_TRANSCODE_FAILED(or could silently read wrong slices when the offsets happen to stay in range).This reproduces with libktx's own encoder output: encode a 24×24×8
VK_FORMAT_R16G16B16A16_SFLOATtexture with 4 mip levels viaktxTexture2_CompressBasisExwithKTX_BASIS_CODEC_UASTC_HDR_6x6_INTERMEDIATE, thenktxTexture2_TranscodeBasis(..., KTX_TTF_ASTC_HDR_6x6_RGBA, 0)fails. A 2D texture with otherwise identical parameters transcodes fine — presumably why this hasn't been noticed.Fix
Accumulate per-level first-image indices before the level loop and index with
firstImages[level] + image— the same approachtranscodeEtc1salready uses with itsfirstImagestable. No behavior change for textures where every level has the same image count (2D, arrays, cubemaps): for thosefirstImages[level] == level * levelImageCount.Since
firstImages[numLevels]is the image count implied by the texture's dimensions, the descriptor table size is now also validated up front: a table that is not exactly that many descriptions, or not a whole number of them, is rejected withKTX_FILE_DATA_ERRORbefore any level is processed, instead of surfacing asKTX_TRANSCODE_FAILEDper image.Tests
Adds generated 2D control and 3D multi-mip round-trip regression tests to
transcodetests(in-process encode → transcode), with no new binary test resources. The 3D case fails without the fix and passes with it; both verify the post-transcode state (vkFormat, supercompression scheme, image data present).Found while studying the transcoder for the per-level streaming work discussed in #1224.