Skip to content

Fix: block-aligned mip extents for non-power-of-2 and non-square ASTC blocks - #293

Merged
dzhdanNV merged 1 commit into
NVIDIA-RTX:mainfrom
MaxFreedomPollard:fix/astc-block-extents
Oct 23, 2026
Merged

dzhdanNV merged 1 commit into
NVIDIA-RTX:mainfrom
MaxFreedomPollard:fix/astc-block-extents

Conversation

@MaxFreedomPollard

Copy link
Copy Markdown
Contributor

GetDimension (Source/Shared/SharedExternal.h) rounds the width and height of non-VK textures up to the block size with Align. Align only works for power-of-2 alignments, and the height was rounded with blockWidth as well. For 24 of the 28 ASTC formats (all except 4x4 and 8x8) the result is not a multiple of the block size and is often larger than the mip itself. For example, Align(30, 5) is (30 + 4) & ~4, which is 34:

Format Texture Mip Before After
ASTC_5X5_UNORM 30x30 0 34x34 30x30
ASTC_6X6_UNORM 60x60 0 64x64 60x60
ASTC_6X6_UNORM 60x60 2 16x16 18x18
ASTC_8X5_UNORM 40x45 0 40x48 40x45
ASTC_10X10_UNORM 120x120 0 128x128 120x120
ASTC_12X12_UNORM 12x12 0 20x20 12x12

The WGPU backend exposes these formats when features.textureCompressionASTC is set. It uses GetDimension as the copy extent of WHOLE_SIZE regions in GetCopySize, which serves CmdUploadBufferToTexture, CmdReadbackTextureToBuffer and CmdCopyTexture, and therefore UploadData too. DeviceWGPU::GetHostCopyLayout, used by UploadHostMemoryToTexture and ReadbackTextureToHostMemory, rounds its extent with the same Align. WebGPU rejects these copies: the extent of a compressed copy must be a multiple of the block size and must fit in the block-rounded mip (see "validating texture copy range" in the WebGPU spec). On non-VK backends, StreamTextureData also takes its WHOLE_SIZE staging size from GetDimension.

Fix: in both GetDimension and GetHostCopyLayout, round up with an integer division per axis (blockWidth for x, blockHeight for y). CommandBufferMetal::CmdCopyTexture already does it this way. Results don't change for the depth axis, for VK, or for any non-ASTC format, so D3D11 and D3D12 behave as before.

Verification was host-side only. No GPU or WebGPU device is available here, so none of this ran on a driver.

  • I compared GetDimension(WGPU, ...) from the real SharedExternal.h/.hpp with ceil(max(size >> mip, 1) / block) * block. This covered all formats, block-multiple sizes up to 48 blocks, and all mips. Before the fix, 8062 of 31260 results were wrong, all in the 24 formats above. After the fix, none are.
  • I compared the old and new GetDimension over all formats, all 6 GraphicsAPI values, sizes 1..300, 10 mips and 3 axes (5,832,000 cases). The only differences are in those 24 ASTC formats on non-VK APIs. Results for BC, ETC2, ASTC 4x4/8x8, NV12/P010/P016, uncompressed formats and VK are identical.
  • I called the real DeviceWGPU::GetHostCopyLayout and GetCopySize on texture descs for all ASTC formats and mips. Both were compiled from each tree's ImplWGPU.cpp, and no WebGPU device was created. Before the fix, 6970 of 9088 host copy layouts and 3584 of 4544 copy sizes were wrong. After the fix, none are.
  • I built on macOS with AppleClang 21 (-Wextra -Werror, Release and Debug) with NRI_ENABLE_WGPU_SUPPORT=ON. VK was off because this machine has no Vulkan SDK, and D3D11/D3D12 were not built. clang-format 19.1.7 leaves both files unchanged.

🤖 Generated with Claude Code

… blocks

GetDimension rounded the width and height up with Align, which only works for power-of-2 alignments, and used blockWidth for the height too. For 24 of the 28 ASTC formats (all but 4x4 and 8x8) it returned extents that are not block multiples and often exceed the mip, e.g. 34x34 for a 30x30 ASTC_5X5 texture or 40x48 for a 40x45 ASTC_8X5 one. The WGPU backend uses these extents for WHOLE_SIZE copies (GetCopySize, which also serves UploadData) and for host copies, where GetHostCopyLayout had the same Align rounding.

Round up with an integer division per axis, as the Metal backend already does. Results for all other formats, and for VK, are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dzhdanNV

Copy link
Copy Markdown
Collaborator

Thanks a lot. Merged!

@dzhdanNV
dzhdanNV merged commit dbe4bac into NVIDIA-RTX:main Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants