BC3 re-encode of ASTC arrays: one layer a run (Hyrule Field grid lines) #956
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
No milestone
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!956
Loading…
Reference in a new issue
No description provided.
Delete branch "bc3-array-layers"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Hyrule Field's ground shows its tiles outlined in dark lines when seen from a distance; up close the lines go away. Seen on an RX 6600 (Windows 11), likely part of #468.
Cause
When the BC3 path re-encodes an ASTC texture array,
upload_astc_gpudecodes and encodes up tokBcLayers(8) consecutive layers in one run. In the smaller mip levels, every layer after the run's first comes out wrong; single-layer textures are unaffected. The terrain's material arrays (1365 x 1365 x 90, ASTC 8x8) are sampled at those levels from a distance, hence the lines.How it was isolated (RX 6600): the lines went away
Fix
One layer a run by default. The arrays stay BC3, so there is no VRAM cost (RGBA8 cost ~1.3 GB, too much for an 8 GB card).
RX_VK_BC_LAYERS=<n>allows up to n layers a run (8: as before).I couldn't read
bc_encoder.comp(only its SPIR-V header is in the tree), so this works around the multi-layer path rather than fixing its addressing. If you have the shader source, the per-layer output offset for levels smaller than the first is probably what's off; with that fixed, runs could go back to 8.Tested: RX 6600 + Ryzen 5 5600G, Windows 11: lines gone in Hyrule Field, no other texture changes seen in Kokiri. Builds on current main (
32df58e). Not tested on NVIDIA/Intel/Linux; the change applies to every GPU that takes the BC3 path.🤖 Generated with Claude Code
Thanks for isolating this. I wrote #705 (the AMD resize these arrays go through), so I checked your theory against the shaders: the encoder's addressing is fine, and the multi-layer step that goes wrong is most likely driver-side.
The shaders handle layers correctly. I disassembled both SPIR-V headers with spirv-cross (Vulkan SDK):
bc_encoder_comp_spv.hwrites layer z at block(z * blocks_y + y) * blocks_x + x(16 bytes each,out_offset0). That's the tight packingbc_encode_into'sVkBufferImageCopyexpects (rowLength/imageHeight 0), at every level size.astc_decoder_comp_spv.hreads layer z atz * layer_stride=tail, the strideupload_astc_gpustages with.What changes with n > 1 is driver-side. On AMD both terrain arrays are resized (#705), so each run does:
vkCmdBlitImagewithlayerCount = n(bc_encode_resized)vkCmdCopyBufferToImagewithlayerCount = ninto the BC3 levelAMD packs small levels into a mip tail. A driver issue with multi-layer blits or copies there would match what you saw: only the small levels, only the layers after the first. Same family as the AMD BC level bug #705 works around.
Suggested narrower fix: keep runs of 8 and split only those two calls into one region per layer (no extra dispatches or barriers):
Testing them one at a time (copy only, then blit only) would show which call it is.
Why this over 1 layer a run:
full_barriers: ~1,440 runs for the two arrays. #900 is trying to keep that same rebuild under Windows' 2 s TDR.texture_copy_into_bcalso does multi-layer runs and isn't covered by #956; fixing it inbc_encode_into/bc_encode_resizedcovers it too.Heads-up: this and #900 edit the same run loop, so whichever merges second needs a rebase.