Repository navigation
Image store parameters are invalid - Not a global variable #522
Description
Activity
Since
spirv-valsucceeds, it's more likely that naga is just failing to parse that spirv. Which is not surprising, there's quite a lot of spirv naga can't parse. (See pipelines in #493 failing cause naga can't understand some spirv)You can try to use
type=f32instead offormat = rgba32f, like in this alias?
rust-gpu/crates/spirv-std/src/image.rs
Line 68 in ba15d4c
pub type StorageImage2d = crate::Image!(2D, type=f32, sampled=false, __crate_root=crate); You may also need these extra capabilities, set them via
SpirvBuilder.capability:Capability::StorageImageExtendedFormats, Capability::StorageImageReadWithoutFormat, Capability::StorageImageWriteWithoutFormat,
Thanks for the fast response! I guess in
bevycase (it usesnaga) I should compile it to something naga understands. Using unknown format for texture and setting capabilities yields the same result (with couple of warnings about unrecognized caps):[2026-02-03T15:36:47Z INFO naga::front::spv] Generated by 983040 version 10600 [2026-02-03T15:36:47Z WARN naga::front::spv] Unknown capability StorageImageReadWithoutFormat [2026-02-03T15:36:47Z WARN naga::front::spv] Unknown capability StorageImageWriteWithoutFormat [2026-02-03T15:36:47Z INFO naga::front::spv] Patching... Function [0] '' is invalid: Image store parameters are invalid Not a global variableJust double checked our compiletest, and while we have one that passes for texel fetches (just make sure to fetch with a lod level, don't use
fetchuntil #490 is merged), none of the image write tests do actually pass for one reason or another. All of my use-cases with naga transpilation to wgsl were only fragment shaders, so never had to write texels either.Can confirm it has exactly the same error here: https://github.com/Rust-GPU/rust-gpu/actions/runs/20504878075/job/58917828710?pr=493#step:6:3598
I wonder if it's
nagas responsibility, as rust-gpu emits valid spir-v and naga strays to have first class support for it?It does indeed sound like a
nagaissue..file one and link it here and we'll discuss?While I generally agree that this is technically a naga problem of not parsing valid spirv, I also like to look at the spirv we're emitting vs spirv emitted by glslc, to figure out what weird thing we're doing that may be breaking naga. And indeed, we are kinda weird.
Here I've transpiled the output of a compiletest just writing an image to glsl with
spirv-cross -V:#version 450 layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; layout(set = 0, binding = 0, std430) readonly buffer fill_color { vec4 _m0; } fill_color_1; layout(set = 0, binding = 1) uniform readonly writeonly image2D image; void _spirv_std_image_Image_f32_1_2_0_0_2_0_4_write_u32_glam_u32_uvec2_UVec2_(writeonly image2D _32, uvec2 _33, vec4 _34) { imageStore(_32, ivec2(uvec2(_33)), _34); } void main() { vec4 _29 = fill_color_1._m0; _spirv_std_image_Image_f32_1_2_0_0_2_0_4_write_u32_glam_u32_uvec2_UVec2_(image, uvec2(gl_GlobalInvocationID.xy), _29); }
First, it'll fail to compile cause our image is both
read_onlyandwrite_only. Removingread_only, you'll notice that ourimageStoredoes indeed not operate on a global variable but on a parameter passed to the function. If we inline that function call, it works.So yea... the fix is to add
#[inline]to all the image instrinsics on our side: #523Did some more digging to potentially file a naga bug report (probably won't) by translating it to glsl:
#version 450 layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; layout (set = 0, binding = 0, std430) readonly buffer FillColorBuffer { vec4 fillColor; } fill_color_buffer; layout (set = 0, binding = 1) uniform writeonly image2D image; void indirection(writeonly image2D image, ivec2 texel, vec4 color) { imageStore(image, texel, color); } void main() { indirection(image, ivec2(gl_GlobalInvocationID.xy), fill_color_buffer.fillColor); }
This is valid glsl according to
glslcandspirv-val, but uses theOpCapability StorageImageWriteWithoutFormatwhich is not yet supported by naga.Usually we can get rid of that capability by adding
layout(..., rgba32f)to the image uniform declaration. If we manually inline theindirectionfunction, it will also get rid of that capability. But due to that function passing an image without explicit format, the capability stays.Now you say let's just add
layout(rgba32f)to the paramter, butimage_write_fail.comp:11: error: '' : cannot use layout qualifiers on a function parameterSo you can't even declare images in function parameters to have an explicit image layout.
Even worse, the emitted spv is invalid, and glslc doesn't even verify it's own output:
error: line 71: OpFunctionCall Argument <id> '25[%image_0]'s type does not match Function <id> '8[%_ptr_UniformConstant_7]'s parameter type. %43 = OpFunctionCall %void %indirection_I21_vi2_vf4_ %image_0 %param %param_0So I can't even write glsl that generates spv similar to what we generate.
Thank you @Firestar99 for looking into this!
Reacted by Firestar99
Expected Behaviour
Naga validation to succeed, shader to be executed by bevy
Example & Steps To Reproduce
naga /../shader/path.spv(or use it in bevy_render)I'm using rust-gpu
mainbranch,spirv-unknown-vulkan1.4as a target in build.rs, but the error is the same for any target as far as I can tell.Not sure if bevy reproduction set up is needed, as it fails with same error naga validation does. Something makes me think it is related to incorrect spv gen
System Info
Backtrace