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