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 37namespace vkt 38{ 39namespace SpirVAssembly 40{ 41namespace 42{ 43 44struct Case 45{ 46 Case(const char* b) : basename(b), requirements() { } 47 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}; 52struct CaseGroup 53{ 54 CaseGroup(const char* the_data_dir, const char* the_subdir) : data_dir(the_data_dir), subdir(the_subdir) { } 55 void add(const char* basename) 56 { 57 cases.push_back(Case(basename)); 58 } 59 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 70void 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 121tcu::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