Closed Vecvec closed 5 months ago
We shouldn't emit the decoration if base
is a struct containing a runtime sized array.
Wouldn't it be better to handle the general case? Something like this (decorated_ids is a hashmap)
pub(super) fn decorate(&mut self, id: Word, decoration: spirv::Decoration, operands: &[Word]) {
match self.decorated_ids.get(&(id, decoration)) {
None => {
self.annotations
.push(Instruction::decorate(id, decoration, operands));
self.decorated_ids.insert((id, decoration), ());
}
Some(_) => (),
}
}
could probably fix this too, and the function could be modified to warn/panic/error if there are operands and there is already a duplicate id.
In most cases we don't decorate things in multiple places with the same decoration. Runtime arrays are an edge case where SPIR-V's validation wants us to always decorate the struct even if it's unused.
So something closer to this
let ty = &ir_module.types[base];
let mut should_decorate = true;
// Check if the type has a runtime array.
// A normal runtime array gets validated out,
// so only structs can be with runtime arrays
if let crate::TypeInner::Struct { members, .. } = &ty.inner {
// only the last member in a struct can be dynamically sized
if let Some(last_member) = members.last() {
if let crate::TypeInner::Array { size: ArraySize::Dynamic, .. } = &ir_module.types[last_member.ty].inner {
should_decorate = false;
}
}
}
if should_decorate {
let decorated_id = self.get_type_id(LookupType::Handle(base));
self.decorate(decorated_id, Decoration::Block, &[]);
}
Yeah, I think that would do it.
Description When converting a wgsl shader with a binding array that contains a struct with a runtime array causes the spirv to have two
OpDecorate Block
s. This is against the spirv specification https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Decoration and a similar (but much longer) piece of code causes a validation errorRepro steps converting this shader to spirv causes invalid spirv to generate
Expected vs observed behavior Naga should not generate invalid spirv
Extra materials seems to be caused by https://github.com/gfx-rs/wgpu/blob/60a14c67fb43e68b7e64bee45ab3fac3f4253e72/naga/src/back/spv/writer.rs#L1045-L1047 and https://github.com/gfx-rs/wgpu/blob/60a14c67fb43e68b7e64bee45ab3fac3f4253e72/naga/src/back/spv/writer.rs#L1762-L1765
The invalid spirv generated
I'm not sure how this could be fixed, possibly with a hash-map of the id or a marker on the type id?
Platform trunk as of 60a14c67fb43e68b7e64bee45ab3fac3f4253e72