Skip to content

Commit 010ba7b

Browse files
committed
Split capabilities tests into categorized submodules
Break the monolithic 3500-line capabilities.rs test file into logical subfiles under a capabilities/ directory: - env_allowlist.rs: environment allows/rejects capability tests - versions.rs: SPIR-V version requirement tests - extensions.rs: extension handling and vendor allowlist tests - env_restrictions.rs: capability rejected outside Vulkan tests - extension_requirements.rs: capabilities requiring extensions - implicit_declarations.rs: implicit capability declaration tests - opencl.rs: OpenCL-specific capability tests - conditional.rs: spec conditional / function variants tests - misc.rs: caching and other tests
1 parent b871ebc commit 010ba7b

File tree

11 files changed

+3531
-3514
lines changed

11 files changed

+3531
-3514
lines changed

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

Lines changed: 0 additions & 3514 deletions
This file was deleted.
Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
use super::super::*;
2+
3+
#[test]
4+
fn spec_conditional_capability_requires_extension() {
5+
let text = [
6+
"OpCapability Kernel",
7+
"OpCapability Linkage",
8+
"OpCapability SpecConditionalINTEL",
9+
"OpMemoryModel Logical OpenCL",
10+
]
11+
.join("\n");
12+
let error = text
13+
.as_str()
14+
.validate(TargetEnv::Universal1_6)
15+
.expect_err("SpecConditionalINTEL requires SPV_INTEL_function_variants");
16+
assert_eq!(
17+
error,
18+
ValidationError::DisallowedCapabilityMissingExtension {
19+
capability: rspirv::spirv::Capability::SpecConditionalINTEL,
20+
required_extension: "SPV_INTEL_function_variants".to_string()
21+
}
22+
);
23+
}
24+
25+
#[test]
26+
fn function_variants_capability_accepts_extension_and_dependency() {
27+
let text = [
28+
"OpCapability Kernel",
29+
"OpCapability Linkage",
30+
"OpCapability SpecConditionalINTEL",
31+
"OpCapability FunctionVariantsINTEL",
32+
"OpExtension \"SPV_INTEL_function_variants\"",
33+
"OpMemoryModel Logical OpenCL",
34+
]
35+
.join("\n");
36+
text.as_str()
37+
.validate(TargetEnv::Universal1_6)
38+
.expect("FunctionVariantsINTEL should be accepted with required extension and capability");
39+
}
40+
41+
#[test]
42+
fn function_variants_extension_rejected_for_vulkan() {
43+
let text = [
44+
"OpCapability Shader",
45+
"OpCapability SpecConditionalINTEL",
46+
"OpCapability FunctionVariantsINTEL",
47+
"OpExtension \"SPV_INTEL_function_variants\"",
48+
"OpMemoryModel Logical GLSL450",
49+
"%void = OpTypeVoid",
50+
"%fn = OpTypeFunction %void",
51+
"%main = OpFunction %void None %fn",
52+
"%entry = OpLabel",
53+
"OpReturn",
54+
"OpFunctionEnd",
55+
]
56+
.join("\n");
57+
let error = text
58+
.as_str()
59+
.validate(TargetEnv::Vulkan1_2)
60+
.expect_err("Intel function variants extension should be rejected for Vulkan");
61+
assert_eq!(
62+
error,
63+
ValidationError::DisallowedExtension {
64+
extension: ExtensionName::from("SPV_INTEL_function_variants"),
65+
env: TargetEnv::Vulkan1_2
66+
}
67+
);
68+
text.as_str()
69+
.validate(TargetEnv::Universal1_6)
70+
.expect("Universal environment should accept vendor extensions");
71+
}
72+
73+
#[test]
74+
fn conditional_entry_point_accepts_execution_modes() {
75+
let intel_function_variants_ext = [
76+
1599492179, 1163152969, 1969643340, 1769235310, 1985965679, 1634300513, 7566446,
77+
];
78+
let binary = vec![
79+
0x07230203, // magic
80+
0x00010000, // version
81+
0, // generator
82+
9, // bound (ids up to 8)
83+
0, // schema
84+
op(2, 17), // OpCapability Shader
85+
rspirv::spirv::Capability::Shader as u32,
86+
op(2, 17), // OpCapability SpecConditionalINTEL
87+
rspirv::spirv::Capability::SpecConditionalINTEL as u32,
88+
0x0008_000a, // OpExtension "SPV_INTEL_function_variants"
89+
intel_function_variants_ext[0],
90+
intel_function_variants_ext[1],
91+
intel_function_variants_ext[2],
92+
intel_function_variants_ext[3],
93+
intel_function_variants_ext[4],
94+
intel_function_variants_ext[5],
95+
intel_function_variants_ext[6],
96+
op(3, 14), // OpMemoryModel Logical GLSL450
97+
0,
98+
1,
99+
op(6, 6249), // OpConditionalEntryPointINTEL %5 Fragment %7 "main"
100+
5,
101+
rspirv::spirv::ExecutionModel::Fragment as u32,
102+
7,
103+
0x6e69_616d,
104+
0,
105+
op(3, 16), // OpExecutionMode %7 OriginUpperLeft
106+
7,
107+
rspirv::spirv::ExecutionMode::OriginUpperLeft as u32,
108+
op(2, 19), // OpTypeVoid %1
109+
1,
110+
op(3, 33), // OpTypeFunction %2 %1
111+
2,
112+
1,
113+
op(2, 20), // OpTypeBool %3
114+
3,
115+
op(3, 41), // OpConstantTrue %3 %5
116+
3,
117+
5,
118+
op(5, 54), // OpFunction %1 %7 None %2
119+
1,
120+
7,
121+
0,
122+
2,
123+
op(2, 248), // OpLabel %8
124+
8,
125+
op(1, 253), // OpReturn
126+
op(1, 56), // OpFunctionEnd
127+
];
128+
binary
129+
.as_slice()
130+
.validate(TargetEnv::Universal1_6)
131+
.expect("conditional entry points should participate in execution-mode validation");
132+
}
133+
134+
#[test]
135+
fn intel_function_variants_allowed_for_opencl_and_universal_only() {
136+
let opencl_text = opencl_module_with_extension("SPV_INTEL_function_variants");
137+
opencl_text
138+
.as_str()
139+
.validate(TargetEnv::OpenCl2_2)
140+
.expect("INTEL function variants should be accepted for OpenCL targets");
141+
let universal_text = module_with_extension("SPV_INTEL_function_variants");
142+
universal_text
143+
.as_str()
144+
.validate(TargetEnv::Universal1_6)
145+
.expect("INTEL function variants should be accepted for universal targets");
146+
for env in [TargetEnv::Vulkan1_2, TargetEnv::OpenGl4_5] {
147+
let error = universal_text
148+
.as_str()
149+
.validate(env)
150+
.expect_err("INTEL function variants should be rejected outside OpenCL/Universal");
151+
assert_eq!(
152+
error,
153+
ValidationError::DisallowedExtension {
154+
extension: ExtensionName::from("SPV_INTEL_function_variants"),
155+
env
156+
}
157+
);
158+
}
159+
}
160+
161+
#[test]
162+
fn validate_module_rejects_duplicate_conditional_extension() {
163+
// Duplicate OpConditionalExtensionINTEL instructions should be rejected.
164+
let binary = vec![
165+
0x07230203, // magic
166+
0x00010000, // version
167+
0, // generator
168+
3, // bound (ids up to 2)
169+
0, // schema
170+
op(2, 17), // OpCapability Shader
171+
rspirv::spirv::Capability::Shader as u32,
172+
op(8, 6248), // OpConditionalExtensionINTEL "SPV_GOOGLE_decorate_string"
173+
0x5f56_5053,
174+
0x474f_4f47,
175+
0x645f_454c,
176+
0x726f_6365,
177+
0x5f65_7461,
178+
0x6972_7473,
179+
0x0000_676e,
180+
op(8, 6248), // duplicate
181+
0x5f56_5053,
182+
0x474f_4f47,
183+
0x645f_454c,
184+
0x726f_6365,
185+
0x5f65_7461,
186+
0x6972_7473,
187+
0x0000_676e,
188+
op(3, 14), // OpMemoryModel Logical GLSL450
189+
0,
190+
1,
191+
];
192+
let error = validate_module(&binary, TargetEnv::Vulkan1_2).unwrap_err();
193+
assert_eq!(
194+
error,
195+
ValidationError::DuplicateExtension {
196+
extension: ExtensionName::from("GOOGLE_decorate_string")
197+
}
198+
);
199+
}
200+
201+
#[test]
202+
fn conditional_extension_rejected_in_non_vulkan_env() {
203+
// Vulkan-only conditional extensions must be rejected for non-Vulkan targets.
204+
let binary = vec![
205+
0x07230203, // magic
206+
0x00010000, // version
207+
0, // generator
208+
6, // bound (ids up to 5)
209+
0, // schema
210+
op(2, 17), // OpCapability Shader
211+
rspirv::spirv::Capability::Shader as u32,
212+
0x0009_1868, // OpConditionalExtensionINTEL %1 "SPV_KHR_vulkan_memory_model"
213+
1, // condition id (non-zero to satisfy parsing)
214+
0x5f56_5053, // "SPV_"
215+
0x5f52_484b, // "KHR_"
216+
0x6b6c_7576, // "vulk"
217+
0x6d5f_6e61, // "an_m"
218+
0x726f_6d65, // "emor"
219+
0x6f6d_5f79, // "y_mo"
220+
0x006c_6564, // "del\0"
221+
op(3, 14), // OpMemoryModel Logical GLSL450
222+
0,
223+
1,
224+
op(2, 19), // OpTypeVoid %2
225+
2,
226+
op(3, 33), // OpTypeFunction %3 %2
227+
3,
228+
2,
229+
op(5, 54), // OpFunction %2 %4 None %3
230+
2,
231+
4,
232+
0,
233+
3,
234+
op(2, 248), // OpLabel %5
235+
5,
236+
op(1, 253), // OpReturn
237+
op(1, 56), // OpFunctionEnd
238+
];
239+
let error = validate_module(&binary, TargetEnv::OpenCl2_2).unwrap_err();
240+
assert_eq!(
241+
error,
242+
ValidationError::DisallowedExtension {
243+
extension: ExtensionName::from("SPV_KHR_vulkan_memory_model"),
244+
env: TargetEnv::OpenCl2_2
245+
}
246+
);
247+
}
248+
249+
#[test]
250+
fn conditional_extension_rejected_in_webgpu() {
251+
// WebGPU forbids all extensions, including conditional ones.
252+
let binary = vec![
253+
0x07230203, // magic
254+
0x00010000, // version
255+
0, // generator
256+
6, // bound (ids up to 5)
257+
0, // schema
258+
op(2, 17), // OpCapability Shader
259+
rspirv::spirv::Capability::Shader as u32,
260+
0x0008_1868, // OpConditionalExtensionINTEL %1 "SPV_KHR_shader_clock"
261+
1, // condition id
262+
0x5f56_5053, // "SPV_"
263+
0x5f52_484b, // "KHR_"
264+
0x6461_6873, // "shad"
265+
0x635f_7265, // "er_c"
266+
0x6b63_6f6c, // "lock"
267+
0x0000_0000, // null terminator padding
268+
op(3, 14), // OpMemoryModel Logical GLSL450
269+
0,
270+
1,
271+
op(2, 19), // OpTypeVoid %2
272+
2,
273+
op(3, 33), // OpTypeFunction %3 %2
274+
3,
275+
2,
276+
op(5, 54), // OpFunction %2 %4 None %3
277+
2,
278+
4,
279+
0,
280+
3,
281+
op(2, 248), // OpLabel %5
282+
5,
283+
op(1, 253), // OpReturn
284+
op(1, 56), // OpFunctionEnd
285+
];
286+
let error = validate_module(&binary, TargetEnv::WebGpu0).unwrap_err();
287+
assert_eq!(
288+
error,
289+
ValidationError::DisallowedExtension {
290+
extension: ExtensionName::from("SPV_KHR_shader_clock"),
291+
env: TargetEnv::WebGpu0
292+
}
293+
);
294+
}
295+
296+
#[test]
297+
fn conditional_capability_requires_extension() {
298+
// Extension dependencies apply to conditional capabilities.
299+
let binary = vec![
300+
0x07230203, // magic
301+
0x00010000, // version
302+
0, // generator
303+
6, // bound
304+
0, // schema
305+
op(3, 6250), // OpConditionalCapabilityINTEL %1 SpecConditionalINTEL
306+
1,
307+
rspirv::spirv::Capability::SpecConditionalINTEL as u32,
308+
op(3, 14), // OpMemoryModel Logical OpenCL
309+
2, // OpenCL
310+
0,
311+
op(2, 19), // OpTypeVoid %2
312+
2,
313+
op(3, 33), // OpTypeFunction %3 %2
314+
3,
315+
2,
316+
op(5, 54), // OpFunction %2 %4 None %3
317+
2,
318+
4,
319+
0,
320+
3,
321+
op(2, 248), // OpLabel %5
322+
5,
323+
op(1, 253), // OpReturn
324+
op(1, 56), // OpFunctionEnd
325+
];
326+
let error = validate_module(&binary, TargetEnv::Universal1_6).unwrap_err();
327+
assert_eq!(
328+
error,
329+
ValidationError::DisallowedCapabilityMissingExtension {
330+
capability: rspirv::spirv::Capability::SpecConditionalINTEL,
331+
required_extension: "SPV_INTEL_function_variants".to_string()
332+
}
333+
);
334+
}

0 commit comments

Comments
 (0)