Skip to content

Commit 8d91683

Browse files
committed
Fix FragSizeEXT builtin type to require vec2<i32> not vec2<f32>
FragSizeEXT is a two-component vector of integers per the SPV_EXT_fragment_invocation_density spec. The validation was incorrectly requiring vec2<f32>.
1 parent db3da9b commit 8d91683

2 files changed

Lines changed: 74 additions & 3 deletions

File tree

rust/spirv-tools-core/src/validation/rules/builtins.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ fn validate_builtin_type(
539539
}
540540

541541
// === vec2<f32> builtins ===
542-
BuiltIn::PointCoord | BuiltIn::SamplePosition | BuiltIn::FragSizeEXT => {
542+
BuiltIn::PointCoord | BuiltIn::SamplePosition => {
543543
if !is_vec2_f32(pointee, definitions) {
544544
return Some(ValidationError::InvalidBuiltInType {
545545
builtin,
@@ -548,6 +548,16 @@ fn validate_builtin_type(
548548
}
549549
}
550550

551+
// === vec2<i32/u32> builtins ===
552+
BuiltIn::FragSizeEXT => {
553+
if !is_vec2_i32(pointee, definitions) {
554+
return Some(ValidationError::InvalidBuiltInType {
555+
builtin,
556+
expected: "vec2<i32>",
557+
});
558+
}
559+
}
560+
551561
// === vec3<i32/u32> builtins ===
552562
BuiltIn::GlobalInvocationId
553563
| BuiltIn::LocalInvocationId
@@ -841,8 +851,6 @@ fn is_vec4_i32(ty: &Instruction, definitions: &HashMap<ResultId, Instruction>) -
841851
is_vec_of(ty, definitions, 4, Op::TypeInt, 32)
842852
}
843853

844-
// Helper functions for mesh shader type validation
845-
#[allow(dead_code)]
846854
fn is_vec2_i32(ty: &Instruction, definitions: &HashMap<ResultId, Instruction>) -> bool {
847855
is_vec_of(ty, definitions, 2, Op::TypeInt, 32)
848856
}

rust/spirv-tools-core/src/validation/tests/mod.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30486,3 +30486,66 @@ fn clip_distance_input_accepted_in_fragment_with_separate_vertex_entry() {
3048630486
.validate(TargetEnv::Vulkan1_1)
3048730487
.expect("ClipDistance Input should be accepted in Fragment shader");
3048830488
}
30489+
30490+
#[test]
30491+
fn frag_size_ext_rejects_float_type() {
30492+
// FragSizeEXT must be vec2<i32>, not vec2<f32>
30493+
let text = [
30494+
"OpCapability Shader",
30495+
"OpCapability FragmentDensityEXT",
30496+
"OpExtension \"SPV_EXT_fragment_invocation_density\"",
30497+
"OpMemoryModel Logical GLSL450",
30498+
"OpEntryPoint Fragment %main \"main\" %fs",
30499+
"OpExecutionMode %main OriginUpperLeft",
30500+
"%void = OpTypeVoid",
30501+
"%float = OpTypeFloat 32",
30502+
"%v2f = OpTypeVector %float 2",
30503+
"%ptr_input_v2f = OpTypePointer Input %v2f",
30504+
"%fs = OpVariable %ptr_input_v2f Input",
30505+
"OpDecorate %fs BuiltIn FragSizeEXT",
30506+
"OpDecorate %fs Flat",
30507+
"%fn = OpTypeFunction %void",
30508+
"%main = OpFunction %void None %fn",
30509+
"%entry = OpLabel",
30510+
"OpReturn",
30511+
"OpFunctionEnd",
30512+
]
30513+
.join("\n");
30514+
let error = text
30515+
.as_str()
30516+
.validate(TargetEnv::Vulkan1_1)
30517+
.expect_err("FragSizeEXT with vec2<f32> should be rejected");
30518+
assert!(
30519+
matches!(error, ValidationError::InvalidBuiltInType { .. }),
30520+
"Expected InvalidBuiltInType, got: {error:?}"
30521+
);
30522+
}
30523+
30524+
#[test]
30525+
fn frag_size_ext_accepts_integer_vec2_type() {
30526+
// FragSizeEXT must be vec2<i32/u32>
30527+
let text = [
30528+
"OpCapability Shader",
30529+
"OpCapability FragmentDensityEXT",
30530+
"OpExtension \"SPV_EXT_fragment_invocation_density\"",
30531+
"OpMemoryModel Logical GLSL450",
30532+
"OpEntryPoint Fragment %main \"main\" %fs",
30533+
"OpExecutionMode %main OriginUpperLeft",
30534+
"%void = OpTypeVoid",
30535+
"%uint = OpTypeInt 32 0",
30536+
"%v2u = OpTypeVector %uint 2",
30537+
"%ptr_input_v2u = OpTypePointer Input %v2u",
30538+
"%fs = OpVariable %ptr_input_v2u Input",
30539+
"OpDecorate %fs BuiltIn FragSizeEXT",
30540+
"OpDecorate %fs Flat",
30541+
"%fn = OpTypeFunction %void",
30542+
"%main = OpFunction %void None %fn",
30543+
"%entry = OpLabel",
30544+
"OpReturn",
30545+
"OpFunctionEnd",
30546+
]
30547+
.join("\n");
30548+
text.as_str()
30549+
.validate(TargetEnv::Vulkan1_1)
30550+
.expect("FragSizeEXT with vec2<u32> should be accepted");
30551+
}

0 commit comments

Comments
 (0)