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