1// Copyright (c) 2015-2016 The Khronos Group Inc. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// Assembler tests for instructions in the "Extension Instruction" section 16// of the SPIR-V spec. 17 18#include <string> 19#include <tuple> 20#include <vector> 21 22#include "gmock/gmock.h" 23#include "source/latest_version_glsl_std_450_header.h" 24#include "source/latest_version_opencl_std_header.h" 25#include "source/util/string_utils.h" 26#include "test/test_fixture.h" 27#include "test/unit_spirv.h" 28 29namespace spvtools { 30namespace { 31 32using spvtest::Concatenate; 33using spvtest::MakeInstruction; 34using utils::MakeVector; 35using spvtest::TextToBinaryTest; 36using ::testing::Combine; 37using ::testing::Eq; 38using ::testing::Values; 39using ::testing::ValuesIn; 40 41// Returns a generator of common Vulkan environment values to be tested. 42std::vector<spv_target_env> CommonVulkanEnvs() { 43 return {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2, 44 SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1}; 45} 46 47TEST_F(TextToBinaryTest, InvalidExtInstImportName) { 48 EXPECT_THAT(CompileFailure("%1 = OpExtInstImport \"Haskell.std\""), 49 Eq("Invalid extended instruction import 'Haskell.std'")); 50} 51 52TEST_F(TextToBinaryTest, InvalidImportId) { 53 EXPECT_THAT(CompileFailure("%1 = OpTypeVoid\n" 54 "%2 = OpExtInst %1 %1"), 55 Eq("Invalid extended instruction import Id 2")); 56} 57 58TEST_F(TextToBinaryTest, InvalidImportInstruction) { 59 const std::string input = R"(%1 = OpTypeVoid 60 %2 = OpExtInstImport "OpenCL.std" 61 %3 = OpExtInst %1 %2 not_in_the_opencl)"; 62 EXPECT_THAT(CompileFailure(input), 63 Eq("Invalid extended instruction name 'not_in_the_opencl'.")); 64} 65 66TEST_F(TextToBinaryTest, MultiImport) { 67 const std::string input = R"(%2 = OpExtInstImport "OpenCL.std" 68 %2 = OpExtInstImport "OpenCL.std")"; 69 EXPECT_THAT(CompileFailure(input), 70 Eq("Import Id is being defined a second time")); 71} 72 73TEST_F(TextToBinaryTest, TooManyArguments) { 74 const std::string input = R"(%opencl = OpExtInstImport "OpenCL.std" 75 %2 = OpExtInst %float %opencl cos %x %oops")"; 76 EXPECT_THAT(CompileFailure(input), Eq("Expected '=', found end of stream.")); 77} 78 79TEST_F(TextToBinaryTest, ExtInstFromTwoDifferentImports) { 80 const std::string input = R"(%1 = OpExtInstImport "OpenCL.std" 81%2 = OpExtInstImport "GLSL.std.450" 82%4 = OpExtInst %3 %1 native_sqrt %5 83%7 = OpExtInst %6 %2 MatrixInverse %8 84)"; 85 86 // Make sure it assembles correctly. 87 EXPECT_THAT( 88 CompiledInstructions(input), 89 Eq(Concatenate({ 90 MakeInstruction(spv::Op::OpExtInstImport, {1}, 91 MakeVector("OpenCL.std")), 92 MakeInstruction(spv::Op::OpExtInstImport, {2}, 93 MakeVector("GLSL.std.450")), 94 MakeInstruction( 95 spv::Op::OpExtInst, 96 {3, 4, 1, uint32_t(OpenCLLIB::Entrypoints::Native_sqrt), 5}), 97 MakeInstruction(spv::Op::OpExtInst, 98 {6, 7, 2, uint32_t(GLSLstd450MatrixInverse), 8}), 99 }))); 100 101 // Make sure it disassembles correctly. 102 EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input)); 103} 104 105// A test case for assembling into words in an instruction. 106struct AssemblyCase { 107 std::string input; 108 std::vector<uint32_t> expected; 109}; 110 111using ExtensionAssemblyTest = spvtest::TextToBinaryTestBase< 112 ::testing::TestWithParam<std::tuple<spv_target_env, AssemblyCase>>>; 113 114TEST_P(ExtensionAssemblyTest, Samples) { 115 const spv_target_env& env = std::get<0>(GetParam()); 116 const AssemblyCase& ac = std::get<1>(GetParam()); 117 118 // Check that it assembles correctly. 119 EXPECT_THAT(CompiledInstructions(ac.input, env), Eq(ac.expected)); 120} 121 122using ExtensionRoundTripTest = spvtest::TextToBinaryTestBase< 123 ::testing::TestWithParam<std::tuple<spv_target_env, AssemblyCase>>>; 124 125TEST_P(ExtensionRoundTripTest, Samples) { 126 const spv_target_env& env = std::get<0>(GetParam()); 127 const AssemblyCase& ac = std::get<1>(GetParam()); 128 129 // Check that it assembles correctly. 130 EXPECT_THAT(CompiledInstructions(ac.input, env), Eq(ac.expected)); 131 132 // Check round trip through the disassembler. 133 EXPECT_THAT(EncodeAndDecodeSuccessfully(ac.input, 134 SPV_BINARY_TO_TEXT_OPTION_NONE, env), 135 Eq(ac.input)) 136 << "target env: " << spvTargetEnvDescription(env) << "\n"; 137} 138 139// SPV_KHR_shader_ballot 140 141INSTANTIATE_TEST_SUITE_P( 142 SPV_KHR_shader_ballot, ExtensionRoundTripTest, 143 // We'll get coverage over operand tables by trying the universal 144 // environments, and at least one specific environment. 145 Combine( 146 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 147 SPV_ENV_VULKAN_1_0), 148 ValuesIn(std::vector<AssemblyCase>{ 149 {"OpCapability SubgroupBallotKHR\n", 150 MakeInstruction(spv::Op::OpCapability, 151 {uint32_t(spv::Capability::SubgroupBallotKHR)})}, 152 {"%2 = OpSubgroupBallotKHR %1 %3\n", 153 MakeInstruction(spv::Op::OpSubgroupBallotKHR, {1, 2, 3})}, 154 {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n", 155 MakeInstruction(spv::Op::OpSubgroupFirstInvocationKHR, {1, 2, 3})}, 156 {"OpDecorate %1 BuiltIn SubgroupEqMask\n", 157 MakeInstruction(spv::Op::OpDecorate, 158 {1, uint32_t(spv::Decoration::BuiltIn), 159 uint32_t(spv::BuiltIn::SubgroupEqMaskKHR)})}, 160 {"OpDecorate %1 BuiltIn SubgroupGeMask\n", 161 MakeInstruction(spv::Op::OpDecorate, 162 {1, uint32_t(spv::Decoration::BuiltIn), 163 uint32_t(spv::BuiltIn::SubgroupGeMaskKHR)})}, 164 {"OpDecorate %1 BuiltIn SubgroupGtMask\n", 165 MakeInstruction(spv::Op::OpDecorate, 166 {1, uint32_t(spv::Decoration::BuiltIn), 167 uint32_t(spv::BuiltIn::SubgroupGtMaskKHR)})}, 168 {"OpDecorate %1 BuiltIn SubgroupLeMask\n", 169 MakeInstruction(spv::Op::OpDecorate, 170 {1, uint32_t(spv::Decoration::BuiltIn), 171 uint32_t(spv::BuiltIn::SubgroupLeMaskKHR)})}, 172 {"OpDecorate %1 BuiltIn SubgroupLtMask\n", 173 MakeInstruction(spv::Op::OpDecorate, 174 {1, uint32_t(spv::Decoration::BuiltIn), 175 uint32_t(spv::BuiltIn::SubgroupLtMaskKHR)})}, 176 }))); 177 178INSTANTIATE_TEST_SUITE_P( 179 SPV_KHR_shader_ballot_vulkan_1_1, ExtensionRoundTripTest, 180 // In SPIR-V 1.3 and Vulkan 1.1 we can drop the KHR suffix on the 181 // builtin enums. 182 Combine( 183 Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1), 184 ValuesIn(std::vector<AssemblyCase>{ 185 {"OpCapability SubgroupBallotKHR\n", 186 MakeInstruction(spv::Op::OpCapability, 187 {(uint32_t)spv::Capability::SubgroupBallotKHR})}, 188 {"%2 = OpSubgroupBallotKHR %1 %3\n", 189 MakeInstruction(spv::Op::OpSubgroupBallotKHR, {1, 2, 3})}, 190 {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n", 191 MakeInstruction(spv::Op::OpSubgroupFirstInvocationKHR, {1, 2, 3})}, 192 {"OpDecorate %1 BuiltIn SubgroupEqMask\n", 193 MakeInstruction(spv::Op::OpDecorate, 194 {1, uint32_t(spv::Decoration::BuiltIn), 195 uint32_t(spv::BuiltIn::SubgroupEqMask)})}, 196 {"OpDecorate %1 BuiltIn SubgroupGeMask\n", 197 MakeInstruction(spv::Op::OpDecorate, 198 {1, uint32_t(spv::Decoration::BuiltIn), 199 uint32_t(spv::BuiltIn::SubgroupGeMask)})}, 200 {"OpDecorate %1 BuiltIn SubgroupGtMask\n", 201 MakeInstruction(spv::Op::OpDecorate, 202 {1, uint32_t(spv::Decoration::BuiltIn), 203 uint32_t(spv::BuiltIn::SubgroupGtMask)})}, 204 {"OpDecorate %1 BuiltIn SubgroupLeMask\n", 205 MakeInstruction(spv::Op::OpDecorate, 206 {1, uint32_t(spv::Decoration::BuiltIn), 207 uint32_t(spv::BuiltIn::SubgroupLeMask)})}, 208 {"OpDecorate %1 BuiltIn SubgroupLtMask\n", 209 MakeInstruction(spv::Op::OpDecorate, 210 {1, uint32_t(spv::Decoration::BuiltIn), 211 uint32_t(spv::BuiltIn::SubgroupLtMask)})}, 212 }))); 213 214// The old builtin names (with KHR suffix) still work in the assembler, and 215// map to the enums without the KHR. 216INSTANTIATE_TEST_SUITE_P( 217 SPV_KHR_shader_ballot_vulkan_1_1_alias_check, ExtensionAssemblyTest, 218 // In SPIR-V 1.3 and Vulkan 1.1 we can drop the KHR suffix on the 219 // builtin enums. 220 Combine(Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1), 221 ValuesIn(std::vector<AssemblyCase>{ 222 {"OpDecorate %1 BuiltIn SubgroupEqMaskKHR\n", 223 MakeInstruction(spv::Op::OpDecorate, 224 {1, (uint32_t)spv::Decoration::BuiltIn, 225 (uint32_t)spv::BuiltIn::SubgroupEqMask})}, 226 {"OpDecorate %1 BuiltIn SubgroupGeMaskKHR\n", 227 MakeInstruction(spv::Op::OpDecorate, 228 {1, (uint32_t)spv::Decoration::BuiltIn, 229 (uint32_t)spv::BuiltIn::SubgroupGeMask})}, 230 {"OpDecorate %1 BuiltIn SubgroupGtMaskKHR\n", 231 MakeInstruction(spv::Op::OpDecorate, 232 {1, (uint32_t)spv::Decoration::BuiltIn, 233 (uint32_t)spv::BuiltIn::SubgroupGtMask})}, 234 {"OpDecorate %1 BuiltIn SubgroupLeMaskKHR\n", 235 MakeInstruction(spv::Op::OpDecorate, 236 {1, (uint32_t)spv::Decoration::BuiltIn, 237 (uint32_t)spv::BuiltIn::SubgroupLeMask})}, 238 {"OpDecorate %1 BuiltIn SubgroupLtMaskKHR\n", 239 MakeInstruction(spv::Op::OpDecorate, 240 {1, (uint32_t)spv::Decoration::BuiltIn, 241 (uint32_t)spv::BuiltIn::SubgroupLtMask})}, 242 }))); 243 244// SPV_KHR_shader_draw_parameters 245 246INSTANTIATE_TEST_SUITE_P( 247 SPV_KHR_shader_draw_parameters, ExtensionRoundTripTest, 248 // We'll get coverage over operand tables by trying the universal 249 // environments, and at least one specific environment. 250 Combine(ValuesIn(CommonVulkanEnvs()), 251 ValuesIn(std::vector<AssemblyCase>{ 252 {"OpCapability DrawParameters\n", 253 MakeInstruction(spv::Op::OpCapability, 254 {(uint32_t)spv::Capability::DrawParameters})}, 255 {"OpDecorate %1 BuiltIn BaseVertex\n", 256 MakeInstruction(spv::Op::OpDecorate, 257 {1, (uint32_t)spv::Decoration::BuiltIn, 258 (uint32_t)spv::BuiltIn::BaseVertex})}, 259 {"OpDecorate %1 BuiltIn BaseInstance\n", 260 MakeInstruction(spv::Op::OpDecorate, 261 {1, (uint32_t)spv::Decoration::BuiltIn, 262 (uint32_t)spv::BuiltIn::BaseInstance})}, 263 {"OpDecorate %1 BuiltIn DrawIndex\n", 264 MakeInstruction(spv::Op::OpDecorate, 265 {1, (uint32_t)spv::Decoration::BuiltIn, 266 (uint32_t)spv::BuiltIn::DrawIndex})}, 267 }))); 268 269// SPV_KHR_subgroup_vote 270 271INSTANTIATE_TEST_SUITE_P( 272 SPV_KHR_subgroup_vote, ExtensionRoundTripTest, 273 // We'll get coverage over operand tables by trying the universal 274 // environments, and at least one specific environment. 275 Combine(ValuesIn(CommonVulkanEnvs()), 276 ValuesIn(std::vector<AssemblyCase>{ 277 {"OpCapability SubgroupVoteKHR\n", 278 MakeInstruction(spv::Op::OpCapability, 279 {(uint32_t)spv::Capability::SubgroupVoteKHR})}, 280 {"%2 = OpSubgroupAnyKHR %1 %3\n", 281 MakeInstruction(spv::Op::OpSubgroupAnyKHR, {1, 2, 3})}, 282 {"%2 = OpSubgroupAllKHR %1 %3\n", 283 MakeInstruction(spv::Op::OpSubgroupAllKHR, {1, 2, 3})}, 284 {"%2 = OpSubgroupAllEqualKHR %1 %3\n", 285 MakeInstruction(spv::Op::OpSubgroupAllEqualKHR, {1, 2, 3})}, 286 }))); 287 288// SPV_KHR_16bit_storage 289 290INSTANTIATE_TEST_SUITE_P( 291 SPV_KHR_16bit_storage, ExtensionRoundTripTest, 292 // We'll get coverage over operand tables by trying the universal 293 // environments, and at least one specific environment. 294 Combine( 295 ValuesIn(CommonVulkanEnvs()), 296 ValuesIn(std::vector<AssemblyCase>{ 297 {"OpCapability StorageBuffer16BitAccess\n", 298 MakeInstruction( 299 spv::Op::OpCapability, 300 {(uint32_t)spv::Capability::StorageUniformBufferBlock16})}, 301 {"OpCapability StorageBuffer16BitAccess\n", 302 MakeInstruction( 303 spv::Op::OpCapability, 304 {(uint32_t)spv::Capability::StorageBuffer16BitAccess})}, 305 {"OpCapability UniformAndStorageBuffer16BitAccess\n", 306 MakeInstruction( 307 spv::Op::OpCapability, 308 {(uint32_t) 309 spv::Capability::UniformAndStorageBuffer16BitAccess})}, 310 {"OpCapability UniformAndStorageBuffer16BitAccess\n", 311 MakeInstruction(spv::Op::OpCapability, 312 {(uint32_t)spv::Capability::StorageUniform16})}, 313 {"OpCapability StoragePushConstant16\n", 314 MakeInstruction( 315 spv::Op::OpCapability, 316 {(uint32_t)spv::Capability::StoragePushConstant16})}, 317 {"OpCapability StorageInputOutput16\n", 318 MakeInstruction( 319 spv::Op::OpCapability, 320 {(uint32_t)spv::Capability::StorageInputOutput16})}, 321 }))); 322 323INSTANTIATE_TEST_SUITE_P( 324 SPV_KHR_16bit_storage_alias_check, ExtensionAssemblyTest, 325 Combine( 326 ValuesIn(CommonVulkanEnvs()), 327 ValuesIn(std::vector<AssemblyCase>{ 328 // The old name maps to the new enum. 329 {"OpCapability StorageUniformBufferBlock16\n", 330 MakeInstruction( 331 spv::Op::OpCapability, 332 {(uint32_t)spv::Capability::StorageBuffer16BitAccess})}, 333 // The new name maps to the old enum. 334 {"OpCapability UniformAndStorageBuffer16BitAccess\n", 335 MakeInstruction(spv::Op::OpCapability, 336 {(uint32_t)spv::Capability::StorageUniform16})}, 337 }))); 338 339// SPV_KHR_device_group 340 341INSTANTIATE_TEST_SUITE_P( 342 SPV_KHR_device_group, ExtensionRoundTripTest, 343 // We'll get coverage over operand tables by trying the universal 344 // environments, and at least one specific environment. 345 Combine(ValuesIn(CommonVulkanEnvs()), 346 ValuesIn(std::vector<AssemblyCase>{ 347 {"OpCapability DeviceGroup\n", 348 MakeInstruction(spv::Op::OpCapability, 349 {(uint32_t)spv::Capability::DeviceGroup})}, 350 {"OpDecorate %1 BuiltIn DeviceIndex\n", 351 MakeInstruction(spv::Op::OpDecorate, 352 {1, (uint32_t)spv::Decoration::BuiltIn, 353 (uint32_t)spv::BuiltIn::DeviceIndex})}, 354 }))); 355 356// SPV_KHR_8bit_storage 357 358INSTANTIATE_TEST_SUITE_P( 359 SPV_KHR_8bit_storage, ExtensionRoundTripTest, 360 // We'll get coverage over operand tables by trying the universal 361 // environments, and at least one specific environment. 362 Combine(ValuesIn(CommonVulkanEnvs()), 363 ValuesIn(std::vector<AssemblyCase>{ 364 {"OpCapability StorageBuffer8BitAccess\n", 365 MakeInstruction( 366 spv::Op::OpCapability, 367 {(uint32_t)spv::Capability::StorageBuffer8BitAccess})}, 368 {"OpCapability UniformAndStorageBuffer8BitAccess\n", 369 MakeInstruction( 370 spv::Op::OpCapability, 371 {(uint32_t) 372 spv::Capability::UniformAndStorageBuffer8BitAccess})}, 373 {"OpCapability StoragePushConstant8\n", 374 MakeInstruction( 375 spv::Op::OpCapability, 376 {(uint32_t)spv::Capability::StoragePushConstant8})}, 377 }))); 378 379// SPV_KHR_multiview 380 381INSTANTIATE_TEST_SUITE_P( 382 SPV_KHR_multiview, ExtensionRoundTripTest, 383 // We'll get coverage over operand tables by trying the universal 384 // environments, and at least one specific environment. 385 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 386 SPV_ENV_VULKAN_1_0), 387 ValuesIn(std::vector<AssemblyCase>{ 388 {"OpCapability MultiView\n", 389 MakeInstruction(spv::Op::OpCapability, 390 {(uint32_t)spv::Capability::MultiView})}, 391 {"OpDecorate %1 BuiltIn ViewIndex\n", 392 MakeInstruction(spv::Op::OpDecorate, 393 {1, (uint32_t)spv::Decoration::BuiltIn, 394 (uint32_t)spv::BuiltIn::ViewIndex})}, 395 }))); 396 397// SPV_AMD_shader_explicit_vertex_parameter 398 399#define PREAMBLE \ 400 "%1 = OpExtInstImport \"SPV_AMD_shader_explicit_vertex_parameter\"\n" 401INSTANTIATE_TEST_SUITE_P( 402 SPV_AMD_shader_explicit_vertex_parameter, ExtensionRoundTripTest, 403 // We'll get coverage over operand tables by trying the universal 404 // environments, and at least one specific environment. 405 Combine( 406 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 407 SPV_ENV_VULKAN_1_0), 408 ValuesIn(std::vector<AssemblyCase>{ 409 {PREAMBLE "%3 = OpExtInst %2 %1 InterpolateAtVertexAMD %4 %5\n", 410 Concatenate( 411 {MakeInstruction( 412 spv::Op::OpExtInstImport, {1}, 413 MakeVector("SPV_AMD_shader_explicit_vertex_parameter")), 414 MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 1, 4, 5})})}, 415 }))); 416#undef PREAMBLE 417 418// SPV_AMD_shader_trinary_minmax 419 420#define PREAMBLE "%1 = OpExtInstImport \"SPV_AMD_shader_trinary_minmax\"\n" 421INSTANTIATE_TEST_SUITE_P( 422 SPV_AMD_shader_trinary_minmax, ExtensionRoundTripTest, 423 // We'll get coverage over operand tables by trying the universal 424 // environments, and at least one specific environment. 425 Combine( 426 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 427 SPV_ENV_VULKAN_1_0), 428 ValuesIn(std::vector<AssemblyCase>{ 429 {PREAMBLE "%3 = OpExtInst %2 %1 FMin3AMD %4 %5 %6\n", 430 Concatenate( 431 {MakeInstruction(spv::Op::OpExtInstImport, {1}, 432 MakeVector("SPV_AMD_shader_trinary_minmax")), 433 MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 1, 4, 5, 6})})}, 434 {PREAMBLE "%3 = OpExtInst %2 %1 UMin3AMD %4 %5 %6\n", 435 Concatenate( 436 {MakeInstruction(spv::Op::OpExtInstImport, {1}, 437 MakeVector("SPV_AMD_shader_trinary_minmax")), 438 MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 2, 4, 5, 6})})}, 439 {PREAMBLE "%3 = OpExtInst %2 %1 SMin3AMD %4 %5 %6\n", 440 Concatenate( 441 {MakeInstruction(spv::Op::OpExtInstImport, {1}, 442 MakeVector("SPV_AMD_shader_trinary_minmax")), 443 MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 3, 4, 5, 6})})}, 444 {PREAMBLE "%3 = OpExtInst %2 %1 FMax3AMD %4 %5 %6\n", 445 Concatenate( 446 {MakeInstruction(spv::Op::OpExtInstImport, {1}, 447 MakeVector("SPV_AMD_shader_trinary_minmax")), 448 MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 4, 4, 5, 6})})}, 449 {PREAMBLE "%3 = OpExtInst %2 %1 UMax3AMD %4 %5 %6\n", 450 Concatenate( 451 {MakeInstruction(spv::Op::OpExtInstImport, {1}, 452 MakeVector("SPV_AMD_shader_trinary_minmax")), 453 MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 5, 4, 5, 6})})}, 454 {PREAMBLE "%3 = OpExtInst %2 %1 SMax3AMD %4 %5 %6\n", 455 Concatenate( 456 {MakeInstruction(spv::Op::OpExtInstImport, {1}, 457 MakeVector("SPV_AMD_shader_trinary_minmax")), 458 MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 6, 4, 5, 6})})}, 459 {PREAMBLE "%3 = OpExtInst %2 %1 FMid3AMD %4 %5 %6\n", 460 Concatenate( 461 {MakeInstruction(spv::Op::OpExtInstImport, {1}, 462 MakeVector("SPV_AMD_shader_trinary_minmax")), 463 MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 7, 4, 5, 6})})}, 464 {PREAMBLE "%3 = OpExtInst %2 %1 UMid3AMD %4 %5 %6\n", 465 Concatenate( 466 {MakeInstruction(spv::Op::OpExtInstImport, {1}, 467 MakeVector("SPV_AMD_shader_trinary_minmax")), 468 MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 8, 4, 5, 6})})}, 469 {PREAMBLE "%3 = OpExtInst %2 %1 SMid3AMD %4 %5 %6\n", 470 Concatenate( 471 {MakeInstruction(spv::Op::OpExtInstImport, {1}, 472 MakeVector("SPV_AMD_shader_trinary_minmax")), 473 MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 9, 4, 5, 6})})}, 474 }))); 475#undef PREAMBLE 476 477// SPV_AMD_gcn_shader 478 479#define PREAMBLE "%1 = OpExtInstImport \"SPV_AMD_gcn_shader\"\n" 480INSTANTIATE_TEST_SUITE_P( 481 SPV_AMD_gcn_shader, ExtensionRoundTripTest, 482 // We'll get coverage over operand tables by trying the universal 483 // environments, and at least one specific environment. 484 Combine( 485 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 486 SPV_ENV_VULKAN_1_0), 487 ValuesIn(std::vector<AssemblyCase>{ 488 {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceIndexAMD %4\n", 489 Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1}, 490 MakeVector("SPV_AMD_gcn_shader")), 491 MakeInstruction(spv::Op::OpExtInst, 492 {2, 3, 1, 1, 4})})}, 493 {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceCoordAMD %4\n", 494 Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1}, 495 MakeVector("SPV_AMD_gcn_shader")), 496 MakeInstruction(spv::Op::OpExtInst, 497 {2, 3, 1, 2, 4})})}, 498 {PREAMBLE "%3 = OpExtInst %2 %1 TimeAMD\n", 499 Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1}, 500 MakeVector("SPV_AMD_gcn_shader")), 501 MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 3})})}, 502 }))); 503#undef PREAMBLE 504 505// SPV_AMD_shader_ballot 506 507#define PREAMBLE "%1 = OpExtInstImport \"SPV_AMD_shader_ballot\"\n" 508INSTANTIATE_TEST_SUITE_P( 509 SPV_AMD_shader_ballot, ExtensionRoundTripTest, 510 // We'll get coverage over operand tables by trying the universal 511 // environments, and at least one specific environment. 512 Combine( 513 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 514 SPV_ENV_VULKAN_1_0), 515 ValuesIn(std::vector<AssemblyCase>{ 516 {PREAMBLE "%3 = OpExtInst %2 %1 SwizzleInvocationsAMD %4 %5\n", 517 Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1}, 518 MakeVector("SPV_AMD_shader_ballot")), 519 MakeInstruction(spv::Op::OpExtInst, 520 {2, 3, 1, 1, 4, 5})})}, 521 {PREAMBLE 522 "%3 = OpExtInst %2 %1 SwizzleInvocationsMaskedAMD %4 %5\n", 523 Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1}, 524 MakeVector("SPV_AMD_shader_ballot")), 525 MakeInstruction(spv::Op::OpExtInst, 526 {2, 3, 1, 2, 4, 5})})}, 527 {PREAMBLE "%3 = OpExtInst %2 %1 WriteInvocationAMD %4 %5 %6\n", 528 Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1}, 529 MakeVector("SPV_AMD_shader_ballot")), 530 MakeInstruction(spv::Op::OpExtInst, 531 {2, 3, 1, 3, 4, 5, 6})})}, 532 {PREAMBLE "%3 = OpExtInst %2 %1 MbcntAMD %4\n", 533 Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1}, 534 MakeVector("SPV_AMD_shader_ballot")), 535 MakeInstruction(spv::Op::OpExtInst, 536 {2, 3, 1, 4, 4})})}, 537 }))); 538#undef PREAMBLE 539 540// SPV_KHR_variable_pointers 541 542INSTANTIATE_TEST_SUITE_P( 543 SPV_KHR_variable_pointers, ExtensionRoundTripTest, 544 // We'll get coverage over operand tables by trying the universal 545 // environments, and at least one specific environment. 546 Combine( 547 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 548 SPV_ENV_VULKAN_1_0), 549 ValuesIn(std::vector<AssemblyCase>{ 550 {"OpCapability VariablePointers\n", 551 MakeInstruction(spv::Op::OpCapability, 552 {(uint32_t)spv::Capability::VariablePointers})}, 553 {"OpCapability VariablePointersStorageBuffer\n", 554 MakeInstruction( 555 spv::Op::OpCapability, 556 {(uint32_t)spv::Capability::VariablePointersStorageBuffer})}, 557 }))); 558 559// SPV_KHR_vulkan_memory_model 560 561INSTANTIATE_TEST_SUITE_P( 562 SPV_KHR_vulkan_memory_model, ExtensionRoundTripTest, 563 // We'll get coverage over operand tables by trying the universal 564 // environments, and at least one specific environment. 565 // 566 // Note: SPV_KHR_vulkan_memory_model adds scope enum value QueueFamilyKHR. 567 // Scope enums are used in ID definitions elsewhere, that don't know they 568 // are using particular enums. So the assembler doesn't support assembling 569 // those enums names into the corresponding values. So there is no asm/dis 570 // tests for those enums. 571 Combine( 572 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 573 SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1), 574 ValuesIn(std::vector<AssemblyCase>{ 575 {"OpCapability VulkanMemoryModel\n", 576 MakeInstruction( 577 spv::Op::OpCapability, 578 {(uint32_t)spv::Capability::VulkanMemoryModelKHR})}, 579 {"OpCapability VulkanMemoryModelDeviceScope\n", 580 MakeInstruction( 581 spv::Op::OpCapability, 582 {(uint32_t)spv::Capability::VulkanMemoryModelDeviceScopeKHR})}, 583 {"OpMemoryModel Logical Vulkan\n", 584 MakeInstruction(spv::Op::OpMemoryModel, 585 {(uint32_t)spv::AddressingModel::Logical, 586 (uint32_t)spv::MemoryModel::VulkanKHR})}, 587 {"OpStore %1 %2 MakePointerAvailable %3\n", 588 MakeInstruction( 589 spv::Op::OpStore, 590 {1, 2, 591 (uint32_t)spv::MemoryAccessMask::MakePointerAvailableKHR, 592 3})}, 593 {"OpStore %1 %2 Volatile|MakePointerAvailable %3\n", 594 MakeInstruction( 595 spv::Op::OpStore, 596 {1, 2, 597 int(spv::MemoryAccessMask::MakePointerAvailableKHR) | 598 int(spv::MemoryAccessMask::Volatile), 599 3})}, 600 {"OpStore %1 %2 Aligned|MakePointerAvailable 4 %3\n", 601 MakeInstruction( 602 spv::Op::OpStore, 603 {1, 2, 604 int(spv::MemoryAccessMask::MakePointerAvailableKHR) | 605 int(spv::MemoryAccessMask::Aligned), 606 4, 3})}, 607 {"OpStore %1 %2 MakePointerAvailable|NonPrivatePointer %3\n", 608 MakeInstruction( 609 spv::Op::OpStore, 610 {1, 2, 611 int(spv::MemoryAccessMask::MakePointerAvailableKHR) | 612 int(spv::MemoryAccessMask::NonPrivatePointerKHR), 613 3})}, 614 {"%2 = OpLoad %1 %3 MakePointerVisible %4\n", 615 MakeInstruction( 616 spv::Op::OpLoad, 617 {1, 2, 3, 618 (uint32_t)spv::MemoryAccessMask::MakePointerVisibleKHR, 4})}, 619 {"%2 = OpLoad %1 %3 Volatile|MakePointerVisible %4\n", 620 MakeInstruction( 621 spv::Op::OpLoad, 622 {1, 2, 3, 623 int(spv::MemoryAccessMask::MakePointerVisibleKHR) | 624 int(spv::MemoryAccessMask::Volatile), 625 4})}, 626 {"%2 = OpLoad %1 %3 Aligned|MakePointerVisible 8 %4\n", 627 MakeInstruction( 628 spv::Op::OpLoad, 629 {1, 2, 3, 630 int(spv::MemoryAccessMask::MakePointerVisibleKHR) | 631 int(spv::MemoryAccessMask::Aligned), 632 8, 4})}, 633 {"%2 = OpLoad %1 %3 MakePointerVisible|NonPrivatePointer " 634 "%4\n", 635 MakeInstruction( 636 spv::Op::OpLoad, 637 {1, 2, 3, 638 int(spv::MemoryAccessMask::MakePointerVisibleKHR) | 639 int(spv::MemoryAccessMask::NonPrivatePointerKHR), 640 4})}, 641 {"OpCopyMemory %1 %2 " 642 "MakePointerAvailable|" 643 "MakePointerVisible|" 644 "NonPrivatePointer " 645 "%3 %4\n", 646 MakeInstruction( 647 spv::Op::OpCopyMemory, 648 {1, 2, 649 (int(spv::MemoryAccessMask::MakePointerVisibleKHR) | 650 int(spv::MemoryAccessMask::MakePointerAvailableKHR) | 651 int(spv::MemoryAccessMask::NonPrivatePointerKHR)), 652 3, 4})}, 653 {"OpCopyMemorySized %1 %2 %3 " 654 "MakePointerAvailable|" 655 "MakePointerVisible|" 656 "NonPrivatePointer " 657 "%4 %5\n", 658 MakeInstruction( 659 spv::Op::OpCopyMemorySized, 660 {1, 2, 3, 661 (int(spv::MemoryAccessMask::MakePointerVisibleKHR) | 662 int(spv::MemoryAccessMask::MakePointerAvailableKHR) | 663 int(spv::MemoryAccessMask::NonPrivatePointerKHR)), 664 4, 5})}, 665 // Image operands 666 {"OpImageWrite %1 %2 %3 MakeTexelAvailable " 667 "%4\n", 668 MakeInstruction( 669 spv::Op::OpImageWrite, 670 {1, 2, 3, int(spv::ImageOperandsMask::MakeTexelAvailableKHR), 671 4})}, 672 {"OpImageWrite %1 %2 %3 MakeTexelAvailable|NonPrivateTexel " 673 "%4\n", 674 MakeInstruction( 675 spv::Op::OpImageWrite, 676 {1, 2, 3, 677 int(spv::ImageOperandsMask::MakeTexelAvailableKHR) | 678 int(spv::ImageOperandsMask::NonPrivateTexelKHR), 679 4})}, 680 {"OpImageWrite %1 %2 %3 " 681 "MakeTexelAvailable|NonPrivateTexel|VolatileTexel " 682 "%4\n", 683 MakeInstruction( 684 spv::Op::OpImageWrite, 685 {1, 2, 3, 686 int(spv::ImageOperandsMask::MakeTexelAvailableKHR) | 687 int(spv::ImageOperandsMask::NonPrivateTexelKHR) | 688 int(spv::ImageOperandsMask::VolatileTexelKHR), 689 4})}, 690 {"%2 = OpImageRead %1 %3 %4 MakeTexelVisible " 691 "%5\n", 692 MakeInstruction(spv::Op::OpImageRead, 693 {1, 2, 3, 4, 694 int(spv::ImageOperandsMask::MakeTexelVisibleKHR), 695 5})}, 696 {"%2 = OpImageRead %1 %3 %4 " 697 "MakeTexelVisible|NonPrivateTexel " 698 "%5\n", 699 MakeInstruction( 700 spv::Op::OpImageRead, 701 {1, 2, 3, 4, 702 int(spv::ImageOperandsMask::MakeTexelVisibleKHR) | 703 int(spv::ImageOperandsMask::NonPrivateTexelKHR), 704 5})}, 705 {"%2 = OpImageRead %1 %3 %4 " 706 "MakeTexelVisible|NonPrivateTexel|VolatileTexel " 707 "%5\n", 708 MakeInstruction( 709 spv::Op::OpImageRead, 710 {1, 2, 3, 4, 711 int(spv::ImageOperandsMask::MakeTexelVisibleKHR) | 712 int(spv::ImageOperandsMask::NonPrivateTexelKHR) | 713 int(spv::ImageOperandsMask::VolatileTexelKHR), 714 5})}, 715 716 // Memory semantics ID values are numbers put into a SPIR-V 717 // constant integer referenced by Id. There is no token for 718 // them, and so no assembler or disassembler support required. 719 // Similar for Scope ID. 720 }))); 721 722// SPV_GOOGLE_decorate_string 723 724// Now that OpDecorateString is the preferred spelling for 725// OpDecorateStringGOOGLE use that name in round trip tests, and the GOOGLE 726// name in an assembly-only test. 727 728INSTANTIATE_TEST_SUITE_P( 729 SPV_GOOGLE_decorate_string, ExtensionRoundTripTest, 730 Combine( 731 // We'll get coverage over operand tables by trying the universal 732 // environments, and at least one specific environment. 733 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 734 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0), 735 ValuesIn(std::vector<AssemblyCase>{ 736 {"OpDecorateString %1 UserSemantic \"ABC\"\n", 737 MakeInstruction(spv::Op::OpDecorateStringGOOGLE, 738 {1, (uint32_t)spv::Decoration::HlslSemanticGOOGLE}, 739 MakeVector("ABC"))}, 740 {"OpDecorateString %1 UserSemantic \"ABC\"\n", 741 MakeInstruction(spv::Op::OpDecorateString, 742 {1, (uint32_t)spv::Decoration::UserSemantic}, 743 MakeVector("ABC"))}, 744 {"OpMemberDecorateString %1 3 UserSemantic \"DEF\"\n", 745 MakeInstruction(spv::Op::OpMemberDecorateStringGOOGLE, 746 {1, 3, (uint32_t)spv::Decoration::UserSemantic}, 747 MakeVector("DEF"))}, 748 {"OpMemberDecorateString %1 3 UserSemantic \"DEF\"\n", 749 MakeInstruction(spv::Op::OpMemberDecorateString, 750 {1, 3, (uint32_t)spv::Decoration::UserSemantic}, 751 MakeVector("DEF"))}, 752 }))); 753 754INSTANTIATE_TEST_SUITE_P( 755 SPV_GOOGLE_decorate_string, ExtensionAssemblyTest, 756 Combine( 757 // We'll get coverage over operand tables by trying the universal 758 // environments, and at least one specific environment. 759 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 760 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0), 761 ValuesIn(std::vector<AssemblyCase>{ 762 {"OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE \"ABC\"\n", 763 MakeInstruction(spv::Op::OpDecorateStringGOOGLE, 764 {1, (uint32_t)spv::Decoration::HlslSemanticGOOGLE}, 765 MakeVector("ABC"))}, 766 {"OpMemberDecorateStringGOOGLE %1 3 HlslSemanticGOOGLE \"DEF\"\n", 767 MakeInstruction(spv::Op::OpMemberDecorateStringGOOGLE, 768 {1, 3, 769 (uint32_t)spv::Decoration::HlslSemanticGOOGLE}, 770 MakeVector("DEF"))}, 771 }))); 772 773// SPV_GOOGLE_hlsl_functionality1 774 775// Now that CounterBuffer is the preferred spelling for HlslCounterBufferGOOGLE, 776// use that name in round trip tests, and the GOOGLE name in an assembly-only 777// test. 778INSTANTIATE_TEST_SUITE_P( 779 SPV_GOOGLE_hlsl_functionality1, ExtensionRoundTripTest, 780 Combine( 781 // We'll get coverage over operand tables by trying the universal 782 // environments, and at least one specific environment. 783 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 784 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0), 785 // HlslSemanticGOOGLE is tested in SPV_GOOGLE_decorate_string, since 786 // they are coupled together. 787 ValuesIn(std::vector<AssemblyCase>{ 788 {"OpDecorateId %1 CounterBuffer %2\n", 789 MakeInstruction( 790 spv::Op::OpDecorateId, 791 {1, (uint32_t)spv::Decoration::HlslCounterBufferGOOGLE, 2})}, 792 {"OpDecorateId %1 CounterBuffer %2\n", 793 MakeInstruction(spv::Op::OpDecorateId, 794 {1, (uint32_t)spv::Decoration::CounterBuffer, 2})}, 795 }))); 796 797INSTANTIATE_TEST_SUITE_P( 798 SPV_GOOGLE_hlsl_functionality1, ExtensionAssemblyTest, 799 Combine( 800 // We'll get coverage over operand tables by trying the universal 801 // environments, and at least one specific environment. 802 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 803 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0), 804 // HlslSemanticGOOGLE is tested in SPV_GOOGLE_decorate_string, since 805 // they are coupled together. 806 ValuesIn(std::vector<AssemblyCase>{ 807 {"OpDecorateId %1 HlslCounterBufferGOOGLE %2\n", 808 MakeInstruction( 809 spv::Op::OpDecorateId, 810 {1, (uint32_t)spv::Decoration::HlslCounterBufferGOOGLE, 2})}, 811 }))); 812 813// SPV_NV_viewport_array2 814 815INSTANTIATE_TEST_SUITE_P( 816 SPV_NV_viewport_array2, ExtensionRoundTripTest, 817 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 818 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3, 819 SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1), 820 ValuesIn(std::vector<AssemblyCase>{ 821 {"OpExtension \"SPV_NV_viewport_array2\"\n", 822 MakeInstruction(spv::Op::OpExtension, 823 MakeVector("SPV_NV_viewport_array2"))}, 824 // The EXT and NV extensions have the same token number for this 825 // capability. 826 {"OpCapability ShaderViewportIndexLayerEXT\n", 827 MakeInstruction( 828 spv::Op::OpCapability, 829 {(uint32_t)spv::Capability::ShaderViewportIndexLayerNV})}, 830 // Check the new capability's token number 831 {"OpCapability ShaderViewportIndexLayerEXT\n", 832 MakeInstruction(spv::Op::OpCapability, {5254})}, 833 // Decorations 834 {"OpDecorate %1 ViewportRelativeNV\n", 835 MakeInstruction( 836 spv::Op::OpDecorate, 837 {1, (uint32_t)spv::Decoration::ViewportRelativeNV})}, 838 {"OpDecorate %1 BuiltIn ViewportMaskNV\n", 839 MakeInstruction(spv::Op::OpDecorate, 840 {1, (uint32_t)spv::Decoration::BuiltIn, 841 (uint32_t)spv::BuiltIn::ViewportMaskNV})}, 842 }))); 843 844// SPV_NV_shader_subgroup_partitioned 845 846INSTANTIATE_TEST_SUITE_P( 847 SPV_NV_shader_subgroup_partitioned, ExtensionRoundTripTest, 848 Combine( 849 Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1), 850 ValuesIn(std::vector<AssemblyCase>{ 851 {"OpExtension \"SPV_NV_shader_subgroup_partitioned\"\n", 852 MakeInstruction(spv::Op::OpExtension, 853 MakeVector("SPV_NV_shader_subgroup_partitioned"))}, 854 {"OpCapability GroupNonUniformPartitionedNV\n", 855 MakeInstruction( 856 spv::Op::OpCapability, 857 {(uint32_t)spv::Capability::GroupNonUniformPartitionedNV})}, 858 // Check the new capability's token number 859 {"OpCapability GroupNonUniformPartitionedNV\n", 860 MakeInstruction(spv::Op::OpCapability, {5297})}, 861 {"%2 = OpGroupNonUniformPartitionNV %1 %3\n", 862 MakeInstruction(spv::Op::OpGroupNonUniformPartitionNV, {1, 2, 3})}, 863 // Check the new instruction's token number 864 {"%2 = OpGroupNonUniformPartitionNV %1 %3\n", 865 MakeInstruction(static_cast<spv::Op>(5296), {1, 2, 3})}, 866 // Check the new group operations 867 {"%2 = OpGroupIAdd %1 %3 PartitionedReduceNV %4\n", 868 MakeInstruction( 869 spv::Op::OpGroupIAdd, 870 {1, 2, 3, (uint32_t)spv::GroupOperation::PartitionedReduceNV, 871 4})}, 872 {"%2 = OpGroupIAdd %1 %3 PartitionedReduceNV %4\n", 873 MakeInstruction(spv::Op::OpGroupIAdd, {1, 2, 3, 6, 4})}, 874 {"%2 = OpGroupIAdd %1 %3 PartitionedInclusiveScanNV %4\n", 875 MakeInstruction( 876 spv::Op::OpGroupIAdd, 877 {1, 2, 3, 878 (uint32_t)spv::GroupOperation::PartitionedInclusiveScanNV, 879 4})}, 880 {"%2 = OpGroupIAdd %1 %3 PartitionedInclusiveScanNV %4\n", 881 MakeInstruction(spv::Op::OpGroupIAdd, {1, 2, 3, 7, 4})}, 882 {"%2 = OpGroupIAdd %1 %3 PartitionedExclusiveScanNV %4\n", 883 MakeInstruction( 884 spv::Op::OpGroupIAdd, 885 {1, 2, 3, 886 (uint32_t)spv::GroupOperation::PartitionedExclusiveScanNV, 887 4})}, 888 {"%2 = OpGroupIAdd %1 %3 PartitionedExclusiveScanNV %4\n", 889 MakeInstruction(spv::Op::OpGroupIAdd, {1, 2, 3, 8, 4})}, 890 }))); 891 892// SPV_EXT_descriptor_indexing 893 894INSTANTIATE_TEST_SUITE_P( 895 SPV_EXT_descriptor_indexing, ExtensionRoundTripTest, 896 Combine( 897 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, 898 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, 899 SPV_ENV_VULKAN_1_1), 900 ValuesIn(std::vector<AssemblyCase>{ 901 {"OpExtension \"SPV_EXT_descriptor_indexing\"\n", 902 MakeInstruction(spv::Op::OpExtension, 903 MakeVector("SPV_EXT_descriptor_indexing"))}, 904 // Check capabilities, by name 905 {"OpCapability ShaderNonUniform\n", 906 MakeInstruction(spv::Op::OpCapability, 907 {(uint32_t)spv::Capability::ShaderNonUniformEXT})}, 908 {"OpCapability RuntimeDescriptorArray\n", 909 MakeInstruction( 910 spv::Op::OpCapability, 911 {(uint32_t)spv::Capability::RuntimeDescriptorArrayEXT})}, 912 {"OpCapability InputAttachmentArrayDynamicIndexing\n", 913 MakeInstruction(spv::Op::OpCapability, 914 {(uint32_t)spv::Capability:: 915 InputAttachmentArrayDynamicIndexingEXT})}, 916 {"OpCapability UniformTexelBufferArrayDynamicIndexing\n", 917 MakeInstruction(spv::Op::OpCapability, 918 {(uint32_t)spv::Capability:: 919 UniformTexelBufferArrayDynamicIndexingEXT})}, 920 {"OpCapability StorageTexelBufferArrayDynamicIndexing\n", 921 MakeInstruction(spv::Op::OpCapability, 922 {(uint32_t)spv::Capability:: 923 StorageTexelBufferArrayDynamicIndexingEXT})}, 924 {"OpCapability UniformBufferArrayNonUniformIndexing\n", 925 MakeInstruction(spv::Op::OpCapability, 926 {(uint32_t)spv::Capability:: 927 UniformBufferArrayNonUniformIndexingEXT})}, 928 {"OpCapability SampledImageArrayNonUniformIndexing\n", 929 MakeInstruction(spv::Op::OpCapability, 930 {(uint32_t)spv::Capability:: 931 SampledImageArrayNonUniformIndexingEXT})}, 932 {"OpCapability StorageBufferArrayNonUniformIndexing\n", 933 MakeInstruction(spv::Op::OpCapability, 934 {(uint32_t)spv::Capability:: 935 StorageBufferArrayNonUniformIndexingEXT})}, 936 {"OpCapability StorageImageArrayNonUniformIndexing\n", 937 MakeInstruction(spv::Op::OpCapability, 938 {(uint32_t)spv::Capability:: 939 StorageImageArrayNonUniformIndexingEXT})}, 940 {"OpCapability InputAttachmentArrayNonUniformIndexing\n", 941 MakeInstruction(spv::Op::OpCapability, 942 {(uint32_t)spv::Capability:: 943 InputAttachmentArrayNonUniformIndexingEXT})}, 944 {"OpCapability UniformTexelBufferArrayNonUniformIndexing\n", 945 MakeInstruction( 946 spv::Op::OpCapability, 947 {(uint32_t)spv::Capability:: 948 UniformTexelBufferArrayNonUniformIndexingEXT})}, 949 {"OpCapability StorageTexelBufferArrayNonUniformIndexing\n", 950 MakeInstruction( 951 spv::Op::OpCapability, 952 {(uint32_t)spv::Capability:: 953 StorageTexelBufferArrayNonUniformIndexingEXT})}, 954 // Check capabilities, by number 955 {"OpCapability ShaderNonUniform\n", 956 MakeInstruction(spv::Op::OpCapability, {5301})}, 957 {"OpCapability RuntimeDescriptorArray\n", 958 MakeInstruction(spv::Op::OpCapability, {5302})}, 959 {"OpCapability InputAttachmentArrayDynamicIndexing\n", 960 MakeInstruction(spv::Op::OpCapability, {5303})}, 961 {"OpCapability UniformTexelBufferArrayDynamicIndexing\n", 962 MakeInstruction(spv::Op::OpCapability, {5304})}, 963 {"OpCapability StorageTexelBufferArrayDynamicIndexing\n", 964 MakeInstruction(spv::Op::OpCapability, {5305})}, 965 {"OpCapability UniformBufferArrayNonUniformIndexing\n", 966 MakeInstruction(spv::Op::OpCapability, {5306})}, 967 {"OpCapability SampledImageArrayNonUniformIndexing\n", 968 MakeInstruction(spv::Op::OpCapability, {5307})}, 969 {"OpCapability StorageBufferArrayNonUniformIndexing\n", 970 MakeInstruction(spv::Op::OpCapability, {5308})}, 971 {"OpCapability StorageImageArrayNonUniformIndexing\n", 972 MakeInstruction(spv::Op::OpCapability, {5309})}, 973 {"OpCapability InputAttachmentArrayNonUniformIndexing\n", 974 MakeInstruction(spv::Op::OpCapability, {5310})}, 975 {"OpCapability UniformTexelBufferArrayNonUniformIndexing\n", 976 MakeInstruction(spv::Op::OpCapability, {5311})}, 977 {"OpCapability StorageTexelBufferArrayNonUniformIndexing\n", 978 MakeInstruction(spv::Op::OpCapability, {5312})}, 979 980 // Check the decoration token 981 {"OpDecorate %1 NonUniform\n", 982 MakeInstruction(spv::Op::OpDecorate, 983 {1, (uint32_t)spv::Decoration::NonUniformEXT})}, 984 {"OpDecorate %1 NonUniform\n", 985 MakeInstruction(spv::Op::OpDecorate, {1, 5300})}, 986 }))); 987 988// SPV_KHR_linkonce_odr 989 990INSTANTIATE_TEST_SUITE_P( 991 SPV_KHR_linkonce_odr, ExtensionRoundTripTest, 992 Combine( 993 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, 994 SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2), 995 ValuesIn(std::vector<AssemblyCase>{ 996 {"OpExtension \"SPV_KHR_linkonce_odr\"\n", 997 MakeInstruction(spv::Op::OpExtension, 998 MakeVector("SPV_KHR_linkonce_odr"))}, 999 {"OpDecorate %1 LinkageAttributes \"foobar\" LinkOnceODR\n", 1000 MakeInstruction( 1001 spv::Op::OpDecorate, 1002 Concatenate({{1, (uint32_t)spv::Decoration::LinkageAttributes}, 1003 MakeVector("foobar"), 1004 {(uint32_t)spv::LinkageType::LinkOnceODR}}))}, 1005 }))); 1006 1007// SPV_KHR_expect_assume 1008 1009INSTANTIATE_TEST_SUITE_P( 1010 SPV_KHR_expect_assume, ExtensionRoundTripTest, 1011 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_3, 1012 SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2), 1013 ValuesIn(std::vector<AssemblyCase>{ 1014 {"OpExtension \"SPV_KHR_expect_assume\"\n", 1015 MakeInstruction(spv::Op::OpExtension, 1016 MakeVector("SPV_KHR_expect_assume"))}, 1017 {"OpAssumeTrueKHR %1\n", 1018 MakeInstruction(spv::Op::OpAssumeTrueKHR, {1})}}))); 1019// SPV_KHR_subgroup_uniform_control_flow 1020 1021INSTANTIATE_TEST_SUITE_P( 1022 SPV_KHR_subgroup_uniform_control_flow, ExtensionRoundTripTest, 1023 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_3, 1024 SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2), 1025 ValuesIn(std::vector<AssemblyCase>{ 1026 {"OpExtension \"SPV_KHR_subgroup_uniform_control_flow\"\n", 1027 MakeInstruction( 1028 spv::Op::OpExtension, 1029 MakeVector("SPV_KHR_subgroup_uniform_control_flow"))}, 1030 {"OpExecutionMode %1 SubgroupUniformControlFlowKHR\n", 1031 MakeInstruction(spv::Op::OpExecutionMode, 1032 {1, (uint32_t)spv::ExecutionMode:: 1033 SubgroupUniformControlFlowKHR})}, 1034 }))); 1035 1036// SPV_KHR_integer_dot_product 1037 1038INSTANTIATE_TEST_SUITE_P( 1039 SPV_KHR_integer_dot_product, ExtensionRoundTripTest, 1040 Combine( 1041 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_5, 1042 SPV_ENV_UNIVERSAL_1_6, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, 1043 SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_3), 1044 ValuesIn(std::vector<AssemblyCase>{ 1045 {"OpExtension \"SPV_KHR_integer_dot_product\"\n", 1046 MakeInstruction(spv::Op::OpExtension, 1047 MakeVector("SPV_KHR_integer_dot_product"))}, 1048 {"OpCapability DotProductInputAll\n", 1049 MakeInstruction( 1050 spv::Op::OpCapability, 1051 {(uint32_t)spv::Capability::DotProductInputAllKHR})}, 1052 {"OpCapability DotProductInput4x8Bit\n", 1053 MakeInstruction( 1054 spv::Op::OpCapability, 1055 {(uint32_t)spv::Capability::DotProductInput4x8BitKHR})}, 1056 {"OpCapability DotProductInput4x8BitPacked\n", 1057 MakeInstruction( 1058 spv::Op::OpCapability, 1059 {(uint32_t)spv::Capability::DotProductInput4x8BitPackedKHR})}, 1060 {"OpCapability DotProduct\n", 1061 MakeInstruction(spv::Op::OpCapability, 1062 {(uint32_t)spv::Capability::DotProductKHR})}, 1063 {"%2 = OpSDot %1 %3 %4\n", 1064 MakeInstruction(spv::Op::OpSDotKHR, {1, 2, 3, 4})}, 1065 {"%2 = OpSDot %1 %3 %4 PackedVectorFormat4x8Bit\n", 1066 MakeInstruction( 1067 spv::Op::OpSDotKHR, 1068 {1, 2, 3, 4, 1069 (uint32_t) 1070 spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})}, 1071 {"%2 = OpUDot %1 %3 %4\n", 1072 MakeInstruction(spv::Op::OpUDotKHR, {1, 2, 3, 4})}, 1073 {"%2 = OpUDot %1 %3 %4 PackedVectorFormat4x8Bit\n", 1074 MakeInstruction( 1075 spv::Op::OpUDotKHR, 1076 {1, 2, 3, 4, 1077 (uint32_t) 1078 spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})}, 1079 {"%2 = OpSUDot %1 %3 %4\n", 1080 MakeInstruction(spv::Op::OpSUDotKHR, {1, 2, 3, 4})}, 1081 {"%2 = OpSUDot %1 %3 %4 PackedVectorFormat4x8Bit\n", 1082 MakeInstruction( 1083 spv::Op::OpSUDotKHR, 1084 {1, 2, 3, 4, 1085 (uint32_t) 1086 spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})}, 1087 {"%2 = OpSDotAccSat %1 %3 %4 %5\n", 1088 MakeInstruction(spv::Op::OpSDotAccSatKHR, {1, 2, 3, 4, 5})}, 1089 {"%2 = OpSDotAccSat %1 %3 %4 %5 PackedVectorFormat4x8Bit\n", 1090 MakeInstruction( 1091 spv::Op::OpSDotAccSatKHR, 1092 {1, 2, 3, 4, 5, 1093 (uint32_t) 1094 spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})}, 1095 {"%2 = OpUDotAccSat %1 %3 %4 %5\n", 1096 MakeInstruction(spv::Op::OpUDotAccSatKHR, {1, 2, 3, 4, 5})}, 1097 {"%2 = OpUDotAccSat %1 %3 %4 %5 PackedVectorFormat4x8Bit\n", 1098 MakeInstruction( 1099 spv::Op::OpUDotAccSatKHR, 1100 {1, 2, 3, 4, 5, 1101 (uint32_t) 1102 spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})}, 1103 {"%2 = OpSUDotAccSat %1 %3 %4 %5\n", 1104 MakeInstruction(spv::Op::OpSUDotAccSatKHR, {1, 2, 3, 4, 5})}, 1105 {"%2 = OpSUDotAccSat %1 %3 %4 %5 PackedVectorFormat4x8Bit\n", 1106 MakeInstruction( 1107 spv::Op::OpSUDotAccSatKHR, 1108 {1, 2, 3, 4, 5, 1109 (uint32_t) 1110 spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})}, 1111 }))); 1112 1113// SPV_KHR_bit_instructions 1114 1115INSTANTIATE_TEST_SUITE_P( 1116 SPV_KHR_bit_instructions, ExtensionRoundTripTest, 1117 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_5, 1118 SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2), 1119 ValuesIn(std::vector<AssemblyCase>{ 1120 {"OpExtension \"SPV_KHR_bit_instructions\"\n", 1121 MakeInstruction(spv::Op::OpExtension, 1122 MakeVector("SPV_KHR_bit_instructions"))}, 1123 {"OpCapability BitInstructions\n", 1124 MakeInstruction(spv::Op::OpCapability, 1125 {(uint32_t)spv::Capability::BitInstructions})}, 1126 }))); 1127 1128// SPV_KHR_uniform_group_instructions 1129 1130INSTANTIATE_TEST_SUITE_P( 1131 SPV_KHR_uniform_group_instructions, ExtensionRoundTripTest, 1132 Combine( 1133 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_5, 1134 SPV_ENV_UNIVERSAL_1_6, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, 1135 SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_3), 1136 ValuesIn(std::vector<AssemblyCase>{ 1137 {"OpExtension \"SPV_KHR_uniform_group_instructions\"\n", 1138 MakeInstruction(spv::Op::OpExtension, 1139 MakeVector("SPV_KHR_uniform_group_instructions"))}, 1140 {"OpCapability GroupUniformArithmeticKHR\n", 1141 MakeInstruction( 1142 spv::Op::OpCapability, 1143 {(uint32_t)spv::Capability::GroupUniformArithmeticKHR})}, 1144 {"%2 = OpGroupIMulKHR %1 %3 Reduce %4\n", 1145 MakeInstruction(spv::Op::OpGroupIMulKHR, 1146 {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce, 1147 4})}, 1148 {"%2 = OpGroupFMulKHR %1 %3 Reduce %4\n", 1149 MakeInstruction(spv::Op::OpGroupFMulKHR, 1150 {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce, 1151 4})}, 1152 {"%2 = OpGroupBitwiseAndKHR %1 %3 Reduce %4\n", 1153 MakeInstruction(spv::Op::OpGroupBitwiseAndKHR, 1154 {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce, 1155 4})}, 1156 {"%2 = OpGroupBitwiseOrKHR %1 %3 Reduce %4\n", 1157 MakeInstruction(spv::Op::OpGroupBitwiseOrKHR, 1158 {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce, 1159 4})}, 1160 {"%2 = OpGroupBitwiseXorKHR %1 %3 Reduce %4\n", 1161 MakeInstruction(spv::Op::OpGroupBitwiseXorKHR, 1162 {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce, 1163 4})}, 1164 {"%2 = OpGroupLogicalAndKHR %1 %3 Reduce %4\n", 1165 MakeInstruction(spv::Op::OpGroupLogicalAndKHR, 1166 {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce, 1167 4})}, 1168 {"%2 = OpGroupLogicalOrKHR %1 %3 Reduce %4\n", 1169 MakeInstruction(spv::Op::OpGroupLogicalOrKHR, 1170 {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce, 1171 4})}, 1172 {"%2 = OpGroupLogicalXorKHR %1 %3 Reduce %4\n", 1173 MakeInstruction(spv::Op::OpGroupLogicalXorKHR, 1174 {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce, 1175 4})}, 1176 }))); 1177 1178// SPV_KHR_subgroup_rotate 1179 1180INSTANTIATE_TEST_SUITE_P( 1181 SPV_KHR_subgroup_rotate, ExtensionRoundTripTest, 1182 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_6, 1183 SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2, 1184 SPV_ENV_VULKAN_1_3, SPV_ENV_OPENCL_2_1), 1185 ValuesIn(std::vector<AssemblyCase>{ 1186 {"OpExtension \"SPV_KHR_subgroup_rotate\"\n", 1187 MakeInstruction(spv::Op::OpExtension, 1188 MakeVector("SPV_KHR_subgroup_rotate"))}, 1189 {"OpCapability GroupNonUniformRotateKHR\n", 1190 MakeInstruction( 1191 spv::Op::OpCapability, 1192 {(uint32_t)spv::Capability::GroupNonUniformRotateKHR})}, 1193 {"%2 = OpGroupNonUniformRotateKHR %1 %3 %4 %5\n", 1194 MakeInstruction(spv::Op::OpGroupNonUniformRotateKHR, 1195 {1, 2, 3, 4, 5})}, 1196 {"%2 = OpGroupNonUniformRotateKHR %1 %3 %4 %5 %6\n", 1197 MakeInstruction(spv::Op::OpGroupNonUniformRotateKHR, 1198 {1, 2, 3, 4, 5, 6})}, 1199 }))); 1200 1201// SPV_EXT_shader_tile_image 1202 1203INSTANTIATE_TEST_SUITE_P( 1204 SPV_EXT_shader_tile_image, ExtensionRoundTripTest, 1205 Combine( 1206 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_0, 1207 SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_3), 1208 ValuesIn(std::vector<AssemblyCase>{ 1209 {"OpExtension \"SPV_EXT_shader_tile_image\"\n", 1210 MakeInstruction(spv::Op::OpExtension, 1211 MakeVector("SPV_EXT_shader_tile_image"))}, 1212 {"OpCapability TileImageColorReadAccessEXT\n", 1213 MakeInstruction( 1214 spv::Op::OpCapability, 1215 {(uint32_t)spv::Capability::TileImageColorReadAccessEXT})}, 1216 {"OpCapability TileImageDepthReadAccessEXT\n", 1217 MakeInstruction( 1218 spv::Op::OpCapability, 1219 {(uint32_t)spv::Capability::TileImageDepthReadAccessEXT})}, 1220 {"OpCapability TileImageStencilReadAccessEXT\n", 1221 MakeInstruction( 1222 spv::Op::OpCapability, 1223 {(uint32_t)spv::Capability::TileImageStencilReadAccessEXT})}, 1224 {"OpExecutionMode %1 NonCoherentColorAttachmentReadEXT\n", 1225 MakeInstruction(spv::Op::OpExecutionMode, 1226 {1, (uint32_t)spv::ExecutionMode:: 1227 NonCoherentColorAttachmentReadEXT})}, 1228 {"OpExecutionMode %1 NonCoherentDepthAttachmentReadEXT\n", 1229 MakeInstruction(spv::Op::OpExecutionMode, 1230 {1, (uint32_t)spv::ExecutionMode:: 1231 NonCoherentDepthAttachmentReadEXT})}, 1232 {"OpExecutionMode %1 NonCoherentStencilAttachmentReadEXT\n", 1233 MakeInstruction(spv::Op::OpExecutionMode, 1234 {1, (uint32_t)spv::ExecutionMode:: 1235 NonCoherentStencilAttachmentReadEXT})}, 1236 {"%2 = OpColorAttachmentReadEXT %1 %3\n", 1237 MakeInstruction(spv::Op::OpColorAttachmentReadEXT, {1, 2, 3})}, 1238 {"%2 = OpColorAttachmentReadEXT %1 %3 %4\n", 1239 MakeInstruction(spv::Op::OpColorAttachmentReadEXT, {1, 2, 3, 4})}, 1240 {"%2 = OpDepthAttachmentReadEXT %1\n", 1241 MakeInstruction(spv::Op::OpDepthAttachmentReadEXT, {1, 2})}, 1242 {"%2 = OpDepthAttachmentReadEXT %1 %3\n", 1243 MakeInstruction(spv::Op::OpDepthAttachmentReadEXT, {1, 2, 3})}, 1244 {"%2 = OpStencilAttachmentReadEXT %1\n", 1245 MakeInstruction(spv::Op::OpStencilAttachmentReadEXT, {1, 2})}, 1246 {"%2 = OpStencilAttachmentReadEXT %1 %3\n", 1247 MakeInstruction(spv::Op::OpStencilAttachmentReadEXT, {1, 2, 3})}, 1248 }))); 1249 1250} // namespace 1251} // namespace spvtools 1252