1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 Google LLC
6 * Copyright (c) 2019 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Test new features in SPIR-V 1.4.
23 *//*--------------------------------------------------------------------*/
24
25 #include <string>
26 #include <vector>
27 #include <amber/amber.h>
28
29 #include "tcuDefs.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vktTestGroupUtil.hpp"
33 #include "vktAmberTestCase.hpp"
34 #include "vktSpvAsmSpirvVersion1p4Tests.hpp"
35 #include "vktTestGroupUtil.hpp"
36
37 namespace vkt
38 {
39 namespace SpirVAssembly
40 {
41 namespace
42 {
43
44 struct Case
45 {
Casevkt::SpirVAssembly::__anonda3c2bc80111::Case46 Case(const char *b) : basename(b), requirements()
47 {
48 }
Casevkt::SpirVAssembly::__anonda3c2bc80111::Case49 Case(const char *b, const std::vector<std::string> &e) : basename(b), requirements(e)
50 {
51 }
52 const char *basename;
53 // Additional Vulkan requirements, if any.
54 std::vector<std::string> requirements;
55 };
56 struct CaseGroup
57 {
CaseGroupvkt::SpirVAssembly::__anonda3c2bc80111::CaseGroup58 CaseGroup(const char *the_data_dir, const char *the_subdir) : data_dir(the_data_dir), subdir(the_subdir)
59 {
60 }
addvkt::SpirVAssembly::__anonda3c2bc80111::CaseGroup61 void add(const char *basename)
62 {
63 cases.push_back(Case(basename));
64 }
addvkt::SpirVAssembly::__anonda3c2bc80111::CaseGroup65 void add(const char *basename, const std::vector<std::string> &requirements)
66 {
67 cases.push_back(Case(basename, requirements));
68 }
69
70 const char *data_dir;
71 const char *subdir;
72 std::vector<Case> cases;
73 };
74
addTestsForAmberFiles(tcu::TestCaseGroup * tests,CaseGroup group)75 void addTestsForAmberFiles(tcu::TestCaseGroup *tests, CaseGroup group)
76 {
77 #ifndef CTS_USES_VULKANSC
78 tcu::TestContext &testCtx = tests->getTestContext();
79 const std::string data_dir(group.data_dir);
80 const std::string subdir(group.subdir);
81 const std::string category = data_dir + "/" + subdir;
82 std::vector<Case> cases(group.cases);
83 vk::SpirVAsmBuildOptions asm_options(VK_MAKE_API_VERSION(0, 1, 1, 0), vk::SPIRV_VERSION_1_4);
84 asm_options.supports_VK_KHR_spirv_1_4 = true;
85
86 for (unsigned i = 0; i < cases.size(); ++i)
87 {
88
89 const std::string file = std::string(cases[i].basename) + ".amber";
90 cts_amber::AmberTestCase *testCase =
91 cts_amber::createAmberTestCase(testCtx, cases[i].basename, category.c_str(), file);
92 DE_ASSERT(testCase != DE_NULL);
93 // Add Vulkan extension requirements.
94 // VK_KHR_spirv_1_4 requires Vulkan 1.1, which includes many common extensions.
95 // So for, example, these tests never have to request VK_KHR_storage_buffer_storage_class,
96 // or VK_KHR_variable_pointers since those extensions were promoted to core features
97 // in Vulkan 1.1. Note that feature bits may still be optional.
98 testCase->addRequirement("VK_KHR_spirv_1_4");
99 // The tests often use StorageBuffer storage class.
100 // We do not have to request VK_KHR_storage_buffer_storage_class because that extension
101 // is about enabling use of SPV_KHR_storage_buffer_storage_class. But SPIR-V 1.4 allows
102 // use of StorageBuffer storage class without any further declarations of extensions
103 // or capabilities. This will also hold for tests that use features introduced by
104 // extensions folded into SPIR-V 1.4 or earlier, and which don't require extra capabilities
105 // to be enabled by Vulkan. Other examples are functionality in SPV_GOOGLE_decorate_string,
106 // SPV_GOOGLE_hlsl_functionality1, and SPV_KHR_no_integer_wrap_decoration.
107 const std::vector<std::string> &reqmts = cases[i].requirements;
108 for (size_t r = 0; r < reqmts.size(); ++r)
109 {
110 testCase->addRequirement(reqmts[r]);
111 }
112
113 testCase->setSpirVAsmBuildOptions(asm_options);
114 tests->addChild(testCase);
115 }
116 #else
117 DE_UNREF(tests);
118 DE_UNREF(group);
119 #endif
120 }
121
122 } // namespace
123
createSpirvVersion1p4Group(tcu::TestContext & testCtx)124 tcu::TestCaseGroup *createSpirvVersion1p4Group(tcu::TestContext &testCtx)
125 {
126 // SPIR-V 1.4 new features
127 de::MovePtr<tcu::TestCaseGroup> spirv1p4Tests(new tcu::TestCaseGroup(testCtx, "spirv1p4"));
128
129 // Location of the Amber script files under the data/vulkan/amber source tree.
130 const char *data_dir = "spirv_assembly/instruction/spirv1p4";
131
132 // Set up features used for various tests.
133 std::vector<std::string> Geom;
134 Geom.push_back("Features.geometryShader");
135
136 std::vector<std::string> Tess;
137 Tess.push_back("Features.tessellationShader");
138
139 std::vector<std::string> Varptr_ssbo;
140 Varptr_ssbo.push_back("VariablePointerFeatures.variablePointersStorageBuffer");
141
142 std::vector<std::string> Varptr_full = Varptr_ssbo;
143 Varptr_full.push_back("VariablePointerFeatures.variablePointers");
144
145 std::vector<std::string> Int16;
146 Int16.push_back("Features.shaderInt16");
147
148 std::vector<std::string> Int16_storage = Int16;
149 Int16_storage.push_back("VK_KHR_16bit_storage");
150 Int16_storage.push_back("Storage16BitFeatures.storageBuffer16BitAccess");
151
152 std::vector<std::string> Int64;
153 Int64.push_back("Features.shaderInt64");
154
155 // Define test groups
156
157 CaseGroup group(data_dir, "opcopylogical");
158 // different matrix layout
159 group.add("different_matrix_layout");
160 // different matrix strides
161 group.add("different_matrix_strides");
162 // nested_arrays_different_inner_stride
163 group.add("nested_arrays_different_inner_stride");
164 // nested_arrays_different_inner_stride
165 group.add("nested_arrays_different_outer_stride");
166 // nested_arrays_different_strides
167 group.add("nested_arrays_different_strides");
168 // same array two ids
169 group.add("same_array_two_ids");
170 // same struct two ids
171 group.add("same_struct_two_ids");
172 // ssbo_to_ubo
173 group.add("ssbo_to_ubo");
174 // two_arrays_different_stride_1
175 group.add("two_arrays_different_stride_1");
176 // two_arrays_different_stride_2
177 group.add("two_arrays_different_stride_2");
178 // ubo_to_ssbo
179 group.add("ubo_to_ssbo");
180 spirv1p4Tests->addChild(createTestGroup(testCtx, "opcopylogical", addTestsForAmberFiles, group));
181
182 group = CaseGroup(data_dir, "opptrdiff");
183 // pointer diff within an SSBO
184 group.add("ssbo_comparisons_diff", Varptr_ssbo);
185 // pointer diff in SSBO with full VariablePointers
186 group.add("variable_pointers_vars_ssbo_2_diff", Varptr_ssbo);
187 // pointer diff in SSBO, stored in private var
188 group.add("variable_pointers_vars_ssbo_diff", Varptr_ssbo);
189 // pointer diff in workgroup storage, stored in private var
190 group.add("variable_pointers_vars_wg_diff", Varptr_full);
191 // pointer diff in workgroup storage
192 group.add("wg_comparisons_diff", Varptr_full);
193 spirv1p4Tests->addChild(createTestGroup(testCtx, "opptrdiff", addTestsForAmberFiles, group));
194
195 group = CaseGroup(data_dir, "opptrequal");
196 // ptr equal against different SSBO variables
197 group.add("different_ssbos_equal", Varptr_full);
198 // ptr equal against different WG variables
199 group.add("different_wgs_equal", Varptr_full);
200 // ptr equal null in SSBO
201 group.add("null_comparisons_ssbo_equal", Varptr_ssbo);
202 // ptr equal null in Workgrop
203 group.add("null_comparisons_wg_equal", Varptr_full);
204 // ptr equal in SSBO
205 group.add("ssbo_comparisons_equal", Varptr_ssbo);
206 // ptr equal in SSBO, store pointers in Function var
207 group.add("variable_pointers_ssbo_2_equal", Varptr_full);
208 // ptr equal in SSBO
209 group.add("variable_pointers_ssbo_equal", Varptr_ssbo);
210 // ptr equal in SSBO, store pointers in Private var
211 group.add("variable_pointers_vars_ssbo_equal", Varptr_ssbo);
212 // ptr equal between simple data primitives in SSBOs
213 group.add("simple_variable_pointers_ptr_equal", Varptr_ssbo);
214 // ptr equal in Workgrop, store pointers in Private var
215 group.add("variable_pointers_vars_wg_equal", Varptr_full);
216 // ptr equal in Workgrop
217 group.add("variable_pointers_wg_equal", Varptr_full);
218 // ptr equal in Workgrop
219 group.add("wg_comparisons_equal", Varptr_full);
220 spirv1p4Tests->addChild(createTestGroup(testCtx, "opptrequal", addTestsForAmberFiles, group));
221
222 group = CaseGroup(data_dir, "opptrnotequal");
223 // ptr not equal against different SSBO variables
224 group.add("different_ssbos_not_equal", Varptr_full);
225 // ptr not equal against different WG variables
226 group.add("different_wgs_not_equal", Varptr_full);
227 // ptr not equal null SSBO
228 group.add("null_comparisons_ssbo_not_equal", Varptr_ssbo);
229 // ptr not equal null SSBO
230 group.add("null_comparisons_wg_not_equal", Varptr_full);
231 // ptr not equal SSBO
232 group.add("ssbo_comparisons_not_equal", Varptr_ssbo);
233 // ptr not equal SSBO, store pointer in Function var
234 group.add("variable_pointers_ssbo_2_not_equal", Varptr_full);
235 // ptr not equal SSBO, pointer from function return
236 group.add("variable_pointers_ssbo_not_equal", Varptr_ssbo);
237 // ptr not equal between simple data primitives in SSBOs
238 group.add("simple_variable_pointers_ptr_not_equal", Varptr_ssbo);
239 // ptr not equal SSBO, store pointer in Private var
240 group.add("variable_pointers_vars_ssbo_not_equal", Varptr_ssbo);
241 // ptr not equal Workgroup, store pointer in Private var
242 group.add("variable_pointers_vars_wg_not_equal", Varptr_full);
243 // ptr not equal Workgroup
244 group.add("variable_pointers_wg_not_equal", Varptr_full);
245 // ptr not equal Workgroup
246 group.add("wg_comparisons_not_equal", Varptr_full);
247 spirv1p4Tests->addChild(createTestGroup(testCtx, "opptrnotequal", addTestsForAmberFiles, group));
248
249 group = CaseGroup(data_dir, "opcopymemory");
250 // different alignments
251 group.add("different_alignments");
252 // no source access operands
253 group.add("no_source_access_operands");
254 // no target access operands
255 group.add("no_target_access_operands");
256 spirv1p4Tests->addChild(createTestGroup(testCtx, "opcopymemory", addTestsForAmberFiles, group));
257
258 group = CaseGroup(data_dir, "uniformid");
259 // workgroup uniform load result at consumption, in nonuniform control flow
260 group.add("partially_active_uniform_id");
261 // subgroup uniform compare result inside control flow
262 group.add("subgroup_cfg_uniform_id"); // Assumes subgroup size <= LocalSize of 8
263 // subgroup uniform load result
264 group.add("subgroup_uniform"); // Assumes subgroup size <= LocalSize 8
265 // workgroup uniform compare result
266 group.add("workgroup_cfg_uniform_id");
267 // workgroup uniform load result
268 group.add("workgroup_uniform");
269 spirv1p4Tests->addChild(createTestGroup(testCtx, "uniformid", addTestsForAmberFiles, group));
270
271 group = CaseGroup(data_dir, "nonwritable");
272 // NonWritable decorates Function variables
273 group.add("function_2_nonwritable");
274 // NonWritable decorates 2 Function variables
275 group.add("function_nonwritable");
276 // NonWritable decorates Function variable in non-entrypoint function
277 group.add("non_main_function_nonwritable");
278 // NonWritable decorates Private variables
279 group.add("private_2_nonwritable");
280 // NonWritable decorates 2 Private variables
281 group.add("private_nonwritable");
282 spirv1p4Tests->addChild(createTestGroup(testCtx, "nonwritable", addTestsForAmberFiles, group));
283
284 group = CaseGroup(data_dir, "entrypoint");
285 // push constant on compute shader entry point
286 group.add("comp_pc_entry_point");
287 // SSBO on compute shader entry point
288 group.add("comp_ssbo_entry_point");
289 // UBO on compute shader entry point
290 group.add("comp_ubo_entry_point");
291 // Workgroup var on compute shader entry point
292 group.add("comp_workgroup_entry_point");
293 // push constant on fragment shader entry point
294 group.add("frag_pc_entry_point");
295 // SSBO on fragment shader entry point
296 group.add("frag_ssbo_entry_point");
297 // UBO on fragment shader entry point
298 group.add("frag_ubo_entry_point");
299 // push constant on geometry shader entry point
300 group.add("geom_pc_entry_point", Geom);
301 // SSBO on geometry shader entry point
302 group.add("geom_ssbo_entry_point", Geom);
303 // UBO on geometry shader entry point
304 group.add("geom_ubo_entry_point", Geom);
305 // push constant on tess control shader entry point
306 group.add("tess_con_pc_entry_point", Tess);
307 // SSBO on tess control shader entry point
308 group.add("tess_con_ssbo_entry_point", Tess);
309 // UBO on tess control shader entry point
310 group.add("tess_con_ubo_entry_point", Tess);
311 // push constant on tess eval shader entry point
312 group.add("tess_eval_pc_entry_point", Tess);
313 // SSBO on tess eval shader entry point
314 group.add("tess_eval_ssbo_entry_point", Tess);
315 // UBO on tess eval shader entry point
316 group.add("tess_eval_ubo_entry_point", Tess);
317 // push constant on vertex shader entry point
318 group.add("vert_pc_entry_point");
319 // SSBO on vertex shader entry point
320 group.add("vert_ssbo_entry_point");
321 // UBO on vertex shader entry point
322 group.add("vert_ubo_entry_point");
323 // EntryPoint lists all module-scope variables
324 spirv1p4Tests->addChild(createTestGroup(testCtx, "entrypoint", addTestsForAmberFiles, group));
325
326 group = CaseGroup(data_dir, "hlsl_functionality1");
327 // CounterBuffer decoration
328 group.add("counter_buffer");
329 // OpDecorateString
330 group.add("decorate_string");
331 // OpMemberDecorateString
332 group.add("member_decorate_string");
333 // Features in SPV_GOOGLE_hlsl_functionality1 in SPIR-V 1.4
334 spirv1p4Tests->addChild(createTestGroup(testCtx, "hlsl_functionality1", addTestsForAmberFiles, group));
335
336 group = CaseGroup(data_dir, "loop_control");
337 // Loop control IterationMultiple
338 group.add("iteration_multiple");
339 // Loop control MaxIterations
340 group.add("max_iterations");
341 // Loop control MinIterations
342 group.add("min_iterations");
343 // Loop control PartialCount
344 group.add("partial_count");
345 // Loop control PeelCount
346 group.add("peel_count");
347 // SPIR-V 1.4 loop controls
348 spirv1p4Tests->addChild(createTestGroup(testCtx, "loop_control", addTestsForAmberFiles, group));
349
350 group = CaseGroup(data_dir, "opselect");
351 // OpSelect arrays, new in SPIR-V 1.4
352 group.add("array_select");
353 // OpSelect arrays with non-standard strides, new in SPIR-V 1.4
354 group.add("array_stride_select");
355 // OpSelect structs with nested arrays, new in SPIR-V 1.4
356 group.add("nested_array_select");
357 // OpSelect structs with nested structs, new in SPIR-V 1.4
358 group.add("nested_struct_select");
359 // OpSelect scalars, verify SPIR-V 1.0
360 group.add("scalar_select");
361 // OpSelect SSBO pointers to different buffers, verify SPIR-V 1.0
362 group.add("ssbo_pointers_2_select", Varptr_full);
363 // OpSelect SSBO pointers to same buffer, verify SPIR-V 1.0
364 group.add("ssbo_pointers_select", Varptr_ssbo);
365 // OpSelect structs, new in SPIR-V 1.4
366 group.add("struct_select");
367 // OpSelect vector with vector selector, verify SPIR-V 1.0
368 group.add("vector_element_select");
369 // OpSelect vector with scalar selector, new in SPIR-V 1.4
370 group.add("vector_select");
371 // OpSelect Workgroup pointers to different buffers, verify SPIR-V 1.0
372 group.add("wg_pointers_2_select", Varptr_full);
373 // OpSelect Workgroup pointers to same buffer, verify SPIR-V 1.0
374 group.add("wg_pointers_select", Varptr_full);
375 // SPIR-V 1.4 OpSelect more cases
376 spirv1p4Tests->addChild(createTestGroup(testCtx, "opselect", addTestsForAmberFiles, group));
377
378 group = CaseGroup(data_dir, "uconvert");
379 // uconvert small to int64
380 group.add("spec_const_opt_extend_16_64_bit", Int64);
381 // uconvert from int16
382 group.add("spec_const_opt_extend_16", Int16);
383 // uconvert large to int64
384 group.add("spec_const_opt_extend_251658240_64_bits", Int64);
385 // uconvert large from int16
386 group.add("spec_const_opt_extend_61440", Int16);
387 // uconvert from int64
388 group.add("spec_const_opt_truncate_16_64_bit", Int64);
389 // uconvert small to int16
390 group.add("spec_const_opt_truncate_16", Int16_storage);
391 // uconvert large to int16
392 group.add("spec_const_opt_truncate_983040", Int16_storage);
393 // uconvert negative from int16
394 group.add("spec_const_opt_zero_extend_n4096", Int16);
395 // SPIR-V 1.4 UConvert in OpSpecConstantOp
396 spirv1p4Tests->addChild(createTestGroup(testCtx, "uconvert", addTestsForAmberFiles, group));
397
398 group = CaseGroup(data_dir, "wrap");
399 // Accept NoSignedWrap decoration
400 group.add("no_signed_wrap");
401 // Accept NoUnsignedWrap decoration
402 group.add("no_unsigned_wrap");
403 // SPIR-V 1.4 integer wrap decorations
404 spirv1p4Tests->addChild(createTestGroup(testCtx, "wrap", addTestsForAmberFiles, group));
405
406 return spirv1p4Tests.release();
407 }
408
409 } // namespace SpirVAssembly
410 } // namespace vkt
411