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
29 namespace spvtools {
30 namespace {
31
32 using spvtest::Concatenate;
33 using spvtest::MakeInstruction;
34 using utils::MakeVector;
35 using spvtest::TextToBinaryTest;
36 using ::testing::Combine;
37 using ::testing::Eq;
38 using ::testing::Values;
39 using ::testing::ValuesIn;
40
41 // Returns a generator of common Vulkan environment values to be tested.
CommonVulkanEnvs()42 std::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
TEST_F(TextToBinaryTest,InvalidExtInstImportName)47 TEST_F(TextToBinaryTest, InvalidExtInstImportName) {
48 EXPECT_THAT(CompileFailure("%1 = OpExtInstImport \"Haskell.std\""),
49 Eq("Invalid extended instruction import 'Haskell.std'"));
50 }
51
TEST_F(TextToBinaryTest,InvalidImportId)52 TEST_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
TEST_F(TextToBinaryTest,InvalidImportInstruction)58 TEST_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
TEST_F(TextToBinaryTest,MultiImport)66 TEST_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
TEST_F(TextToBinaryTest,TooManyArguments)73 TEST_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
79 TEST_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.
106 struct AssemblyCase {
107 std::string input;
108 std::vector<uint32_t> expected;
109 };
110
111 using ExtensionAssemblyTest = spvtest::TextToBinaryTestBase<
112 ::testing::TestWithParam<std::tuple<spv_target_env, AssemblyCase>>>;
113
114 TEST_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
122 using ExtensionRoundTripTest = spvtest::TextToBinaryTestBase<
123 ::testing::TestWithParam<std::tuple<spv_target_env, AssemblyCase>>>;
124
125 TEST_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
141 INSTANTIATE_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
178 INSTANTIATE_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.
216 INSTANTIATE_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
246 INSTANTIATE_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
271 INSTANTIATE_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
290 INSTANTIATE_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
323 INSTANTIATE_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
341 INSTANTIATE_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
358 INSTANTIATE_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
381 INSTANTIATE_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"
401 INSTANTIATE_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"
421 INSTANTIATE_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"
480 INSTANTIATE_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"
508 INSTANTIATE_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
542 INSTANTIATE_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
561 INSTANTIATE_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
728 INSTANTIATE_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
754 INSTANTIATE_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.
778 INSTANTIATE_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
797 INSTANTIATE_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
815 INSTANTIATE_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
846 INSTANTIATE_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
894 INSTANTIATE_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
990 INSTANTIATE_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
1009 INSTANTIATE_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
1021 INSTANTIATE_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
1038 INSTANTIATE_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
1115 INSTANTIATE_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
1130 INSTANTIATE_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
1180 INSTANTIATE_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
1203 INSTANTIATE_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 // SPV_KHR_maximal_reconvergence
1251
1252 INSTANTIATE_TEST_SUITE_P(
1253 SPV_KHR_maximal_reconvergence, ExtensionRoundTripTest,
1254 Combine(
1255 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_0,
1256 SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_3),
1257 ValuesIn(std::vector<AssemblyCase>{
1258 {"OpExtension \"SPV_KHR_maximal_reconvergence\"\n",
1259 MakeInstruction(spv::Op::OpExtension,
1260 MakeVector("SPV_KHR_maximal_reconvergence"))},
1261 {"OpExecutionMode %1 MaximallyReconvergesKHR\n",
1262 MakeInstruction(
1263 spv::Op::OpExecutionMode,
1264 {1, (uint32_t)spv::ExecutionMode::MaximallyReconvergesKHR})},
1265 })));
1266
1267 // SPV_KHR_float_controls2
1268
1269 INSTANTIATE_TEST_SUITE_P(
1270 SPV_KHR_float_controls2, ExtensionRoundTripTest,
1271 Combine(
1272 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_0,
1273 SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_3),
1274 ValuesIn(std::vector<AssemblyCase>{
1275 {"OpExtension \"SPV_KHR_float_controls2\"\n",
1276 MakeInstruction(spv::Op::OpExtension,
1277 MakeVector("SPV_KHR_float_controls2"))},
1278 {"OpCapability FloatControls2\n",
1279 MakeInstruction(spv::Op::OpCapability,
1280 {(uint32_t)spv::Capability::FloatControls2})},
1281 {"OpExecutionMode %1 FPFastMathDefault %2 %3\n",
1282 // The operands are: target type, flags constant
1283 MakeInstruction(
1284 spv::Op::OpExecutionMode,
1285 {1, (uint32_t)spv::ExecutionMode::FPFastMathDefault, 2, 3})},
1286 {"OpDecorate %1 FPFastMathMode AllowContract\n",
1287 MakeInstruction(
1288 spv::Op::OpDecorate,
1289 {1, (uint32_t)spv::Decoration::FPFastMathMode,
1290 (uint32_t)spv::FPFastMathModeMask::AllowContract})},
1291 {"OpDecorate %1 FPFastMathMode AllowReassoc\n",
1292 MakeInstruction(
1293 spv::Op::OpDecorate,
1294 {1, (uint32_t)spv::Decoration::FPFastMathMode,
1295 (uint32_t)spv::FPFastMathModeMask::AllowReassoc})},
1296 {"OpDecorate %1 FPFastMathMode AllowTransform\n",
1297 MakeInstruction(
1298 spv::Op::OpDecorate,
1299 {1, (uint32_t)spv::Decoration::FPFastMathMode,
1300 (uint32_t)spv::FPFastMathModeMask::AllowTransform})},
1301 })));
1302
1303 } // namespace
1304 } // namespace spvtools
1305