wgpu icon indicating copy to clipboard operation
wgpu copied to clipboard

`Device::create_texture_with_data` is not possible to use correctly with mipmapped non-block aligned textures.

Open atlv24 opened this issue 7 months ago • 3 comments

create_texture_with_data is not possible to use correctly with mip-mapped non-power-of-two textures:

the mip sizes are calculated from the texture dimensions, assuming that the provided dimensions are logical dimensions (e.g. not necessarily a multiple of blocksize). this is correct. but the validation step requires that the texture dimensions be physical dimensions (e.g. a multiple of blocksize).

this creates a dilemma where if you have a nPOT texture with mips stored (for example, ktx2) and try to give it to wgpu, you either

  1. tell wgpu the true logical dimensions of the texture and give it the data, so that it can correctly calculate the mip sizes to read from the data block. except wgpu immediately sees that the dimensions are not a multiple of blocksize and rejects it
  2. lie to wgpu and round to physical dimensions, and give it the data. wgpu happily calculates the wrong mip sizes based off of the physical dimensions, which inevitably end up larger than they should be, and tries to index into data that doesnt exist, panicking.

In bevy, we currently do option 2 by just calling .physical_size(texture_format); before passing it in: https://github.com/bevyengine/bevy/blob/main/crates/bevy_image/src/ktx2.rs#L280

I believe the fix is to remove the validation and handle the conversion to physical dimensions somewhere internally, but i dont know all the places that would be affected by this.

This is causing bevy users crashes: https://github.com/bevyengine/bevy/issues/13289 https://github.com/bevyengine/bevy/issues/19124

atlv24 avatar May 08 '25 07:05 atlv24

except wgpu immediately sees that the dimensions are not a multiple of blocksize and rejects it

Note that "not multiple of blocksize" and "NPOT" are two different constraints. e.g. 48x48 is fine for BC1, but is not NPOT.

If you are running into "not multiple of blocksize", this constraint comes from the core WebGPU spec.

It's there because of D3D12 which at one time required that textures have a toplevel size that aligns with the blocksize. This constraint was lifted with the release of D3D12_FEATURE_DATA_D3D12_OPTIONS8, which requires a new enough Agility SDK (no new GPU support is required for this feature, only a new Agility SDK / D3D12 runtime).

wgpu should make an extension to lift the constraints if UnalignedBlockTexturesSupported comes back true. Vulkan and Metal do not have any constraints here.

If you are encountering issues with NPOT textures that are blocksize aligned, then ignore the above; wgpu has another bug somewhere :)

magcius avatar May 10 '25 03:05 magcius

I realized that and was kinda gruntled by the lack of a neat acronym for the notion.

Anyhow, is the proposed fix i PRed not correct? DX would never see an actual texture with weird dimensions, i believe, but it would allow loading weird dimension texture mips.

atlv24 avatar May 16 '25 07:05 atlv24

No, the proposed pull request is not correct. Besides the main issue that a texture of size 39x39 is just a different size than a texture of 40x40 and will sample differently, the “pad to blocksize” happens after the divide by the mip level, and can result in a differently sized mipchain. e.g. a texture with width 717 will see a mip level 4 of 48 instead of 44 since it was padded at mip 0.

The only way to correctly handle this is to provide a capability bit, set it on the right platforms, and ignore the validation. Any padding done for the user is incorrect.

Jasper

On Fri, May 16, 2025 at 4:18 PM atlv @.***> wrote:

atlv24 left a comment (gfx-rs/wgpu#7677) https://github.com/gfx-rs/wgpu/issues/7677#issuecomment-2885864471

I realized that and was kinda gruntled by the lack of a neat acronym for the notion.

Anyhow, is the proposed fix i PRed not correct? DX would never see an actual texture with weird dimensions, i believe, but it would allow loading weird dimension texture mips.

— Reply to this email directly, view it on GitHub https://github.com/gfx-rs/wgpu/issues/7677#issuecomment-2885864471, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAJ7OVDSCCMLNASS3QBK4L26WGNRAVCNFSM6AAAAAB4VYOGE6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDQOBVHA3DINBXGE . You are receiving this because you commented.Message ID: @.***>

magcius avatar May 23 '25 13:05 magcius