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(SpvOpExtInstImport, {1}, MakeVector("OpenCL.std")),
91 MakeInstruction(SpvOpExtInstImport, {2}, MakeVector("GLSL.std.450")),
92 MakeInstruction(
93 SpvOpExtInst,
94 {3, 4, 1, uint32_t(OpenCLLIB::Entrypoints::Native_sqrt), 5}),
95 MakeInstruction(SpvOpExtInst,
96 {6, 7, 2, uint32_t(GLSLstd450MatrixInverse), 8}),
97 })));
98
99 // Make sure it disassembles correctly.
100 EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
101 }
102
103 // A test case for assembling into words in an instruction.
104 struct AssemblyCase {
105 std::string input;
106 std::vector<uint32_t> expected;
107 };
108
109 using ExtensionAssemblyTest = spvtest::TextToBinaryTestBase<
110 ::testing::TestWithParam<std::tuple<spv_target_env, AssemblyCase>>>;
111
112 TEST_P(ExtensionAssemblyTest, Samples) {
113 const spv_target_env& env = std::get<0>(GetParam());
114 const AssemblyCase& ac = std::get<1>(GetParam());
115
116 // Check that it assembles correctly.
117 EXPECT_THAT(CompiledInstructions(ac.input, env), Eq(ac.expected));
118 }
119
120 using ExtensionRoundTripTest = spvtest::TextToBinaryTestBase<
121 ::testing::TestWithParam<std::tuple<spv_target_env, AssemblyCase>>>;
122
123 TEST_P(ExtensionRoundTripTest, Samples) {
124 const spv_target_env& env = std::get<0>(GetParam());
125 const AssemblyCase& ac = std::get<1>(GetParam());
126
127 // Check that it assembles correctly.
128 EXPECT_THAT(CompiledInstructions(ac.input, env), Eq(ac.expected));
129
130 // Check round trip through the disassembler.
131 EXPECT_THAT(EncodeAndDecodeSuccessfully(ac.input,
132 SPV_BINARY_TO_TEXT_OPTION_NONE, env),
133 Eq(ac.input))
134 << "target env: " << spvTargetEnvDescription(env) << "\n";
135 }
136
137 // SPV_KHR_shader_ballot
138
139 INSTANTIATE_TEST_SUITE_P(
140 SPV_KHR_shader_ballot, ExtensionRoundTripTest,
141 // We'll get coverage over operand tables by trying the universal
142 // environments, and at least one specific environment.
143 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
144 SPV_ENV_VULKAN_1_0),
145 ValuesIn(std::vector<AssemblyCase>{
146 {"OpCapability SubgroupBallotKHR\n",
147 MakeInstruction(SpvOpCapability,
148 {SpvCapabilitySubgroupBallotKHR})},
149 {"%2 = OpSubgroupBallotKHR %1 %3\n",
150 MakeInstruction(SpvOpSubgroupBallotKHR, {1, 2, 3})},
151 {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n",
152 MakeInstruction(SpvOpSubgroupFirstInvocationKHR, {1, 2, 3})},
153 {"OpDecorate %1 BuiltIn SubgroupEqMask\n",
154 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
155 SpvBuiltInSubgroupEqMaskKHR})},
156 {"OpDecorate %1 BuiltIn SubgroupGeMask\n",
157 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
158 SpvBuiltInSubgroupGeMaskKHR})},
159 {"OpDecorate %1 BuiltIn SubgroupGtMask\n",
160 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
161 SpvBuiltInSubgroupGtMaskKHR})},
162 {"OpDecorate %1 BuiltIn SubgroupLeMask\n",
163 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
164 SpvBuiltInSubgroupLeMaskKHR})},
165 {"OpDecorate %1 BuiltIn SubgroupLtMask\n",
166 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
167 SpvBuiltInSubgroupLtMaskKHR})},
168 })));
169
170 INSTANTIATE_TEST_SUITE_P(
171 SPV_KHR_shader_ballot_vulkan_1_1, ExtensionRoundTripTest,
172 // In SPIR-V 1.3 and Vulkan 1.1 we can drop the KHR suffix on the
173 // builtin enums.
174 Combine(Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
175 ValuesIn(std::vector<AssemblyCase>{
176 {"OpCapability SubgroupBallotKHR\n",
177 MakeInstruction(SpvOpCapability,
178 {SpvCapabilitySubgroupBallotKHR})},
179 {"%2 = OpSubgroupBallotKHR %1 %3\n",
180 MakeInstruction(SpvOpSubgroupBallotKHR, {1, 2, 3})},
181 {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n",
182 MakeInstruction(SpvOpSubgroupFirstInvocationKHR, {1, 2, 3})},
183 {"OpDecorate %1 BuiltIn SubgroupEqMask\n",
184 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
185 SpvBuiltInSubgroupEqMask})},
186 {"OpDecorate %1 BuiltIn SubgroupGeMask\n",
187 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
188 SpvBuiltInSubgroupGeMask})},
189 {"OpDecorate %1 BuiltIn SubgroupGtMask\n",
190 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
191 SpvBuiltInSubgroupGtMask})},
192 {"OpDecorate %1 BuiltIn SubgroupLeMask\n",
193 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
194 SpvBuiltInSubgroupLeMask})},
195 {"OpDecorate %1 BuiltIn SubgroupLtMask\n",
196 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
197 SpvBuiltInSubgroupLtMask})},
198 })));
199
200 // The old builtin names (with KHR suffix) still work in the assmebler, and
201 // map to the enums without the KHR.
202 INSTANTIATE_TEST_SUITE_P(
203 SPV_KHR_shader_ballot_vulkan_1_1_alias_check, ExtensionAssemblyTest,
204 // In SPIR-V 1.3 and Vulkan 1.1 we can drop the KHR suffix on the
205 // builtin enums.
206 Combine(Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
207 ValuesIn(std::vector<AssemblyCase>{
208 {"OpDecorate %1 BuiltIn SubgroupEqMaskKHR\n",
209 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
210 SpvBuiltInSubgroupEqMask})},
211 {"OpDecorate %1 BuiltIn SubgroupGeMaskKHR\n",
212 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
213 SpvBuiltInSubgroupGeMask})},
214 {"OpDecorate %1 BuiltIn SubgroupGtMaskKHR\n",
215 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
216 SpvBuiltInSubgroupGtMask})},
217 {"OpDecorate %1 BuiltIn SubgroupLeMaskKHR\n",
218 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
219 SpvBuiltInSubgroupLeMask})},
220 {"OpDecorate %1 BuiltIn SubgroupLtMaskKHR\n",
221 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
222 SpvBuiltInSubgroupLtMask})},
223 })));
224
225 // SPV_KHR_shader_draw_parameters
226
227 INSTANTIATE_TEST_SUITE_P(
228 SPV_KHR_shader_draw_parameters, ExtensionRoundTripTest,
229 // We'll get coverage over operand tables by trying the universal
230 // environments, and at least one specific environment.
231 Combine(
232 ValuesIn(CommonVulkanEnvs()),
233 ValuesIn(std::vector<AssemblyCase>{
234 {"OpCapability DrawParameters\n",
235 MakeInstruction(SpvOpCapability, {SpvCapabilityDrawParameters})},
236 {"OpDecorate %1 BuiltIn BaseVertex\n",
237 MakeInstruction(SpvOpDecorate,
238 {1, SpvDecorationBuiltIn, SpvBuiltInBaseVertex})},
239 {"OpDecorate %1 BuiltIn BaseInstance\n",
240 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
241 SpvBuiltInBaseInstance})},
242 {"OpDecorate %1 BuiltIn DrawIndex\n",
243 MakeInstruction(SpvOpDecorate,
244 {1, SpvDecorationBuiltIn, SpvBuiltInDrawIndex})},
245 })));
246
247 // SPV_KHR_subgroup_vote
248
249 INSTANTIATE_TEST_SUITE_P(
250 SPV_KHR_subgroup_vote, ExtensionRoundTripTest,
251 // We'll get coverage over operand tables by trying the universal
252 // environments, and at least one specific environment.
253 Combine(ValuesIn(CommonVulkanEnvs()),
254 ValuesIn(std::vector<AssemblyCase>{
255 {"OpCapability SubgroupVoteKHR\n",
256 MakeInstruction(SpvOpCapability,
257 {SpvCapabilitySubgroupVoteKHR})},
258 {"%2 = OpSubgroupAnyKHR %1 %3\n",
259 MakeInstruction(SpvOpSubgroupAnyKHR, {1, 2, 3})},
260 {"%2 = OpSubgroupAllKHR %1 %3\n",
261 MakeInstruction(SpvOpSubgroupAllKHR, {1, 2, 3})},
262 {"%2 = OpSubgroupAllEqualKHR %1 %3\n",
263 MakeInstruction(SpvOpSubgroupAllEqualKHR, {1, 2, 3})},
264 })));
265
266 // SPV_KHR_16bit_storage
267
268 INSTANTIATE_TEST_SUITE_P(
269 SPV_KHR_16bit_storage, ExtensionRoundTripTest,
270 // We'll get coverage over operand tables by trying the universal
271 // environments, and at least one specific environment.
272 Combine(ValuesIn(CommonVulkanEnvs()),
273 ValuesIn(std::vector<AssemblyCase>{
274 {"OpCapability StorageBuffer16BitAccess\n",
275 MakeInstruction(SpvOpCapability,
276 {SpvCapabilityStorageUniformBufferBlock16})},
277 {"OpCapability StorageBuffer16BitAccess\n",
278 MakeInstruction(SpvOpCapability,
279 {SpvCapabilityStorageBuffer16BitAccess})},
280 {"OpCapability UniformAndStorageBuffer16BitAccess\n",
281 MakeInstruction(
282 SpvOpCapability,
283 {SpvCapabilityUniformAndStorageBuffer16BitAccess})},
284 {"OpCapability UniformAndStorageBuffer16BitAccess\n",
285 MakeInstruction(SpvOpCapability,
286 {SpvCapabilityStorageUniform16})},
287 {"OpCapability StoragePushConstant16\n",
288 MakeInstruction(SpvOpCapability,
289 {SpvCapabilityStoragePushConstant16})},
290 {"OpCapability StorageInputOutput16\n",
291 MakeInstruction(SpvOpCapability,
292 {SpvCapabilityStorageInputOutput16})},
293 })));
294
295 INSTANTIATE_TEST_SUITE_P(
296 SPV_KHR_16bit_storage_alias_check, ExtensionAssemblyTest,
297 Combine(ValuesIn(CommonVulkanEnvs()),
298 ValuesIn(std::vector<AssemblyCase>{
299 // The old name maps to the new enum.
300 {"OpCapability StorageUniformBufferBlock16\n",
301 MakeInstruction(SpvOpCapability,
302 {SpvCapabilityStorageBuffer16BitAccess})},
303 // The new name maps to the old enum.
304 {"OpCapability UniformAndStorageBuffer16BitAccess\n",
305 MakeInstruction(SpvOpCapability,
306 {SpvCapabilityStorageUniform16})},
307 })));
308
309 // SPV_KHR_device_group
310
311 INSTANTIATE_TEST_SUITE_P(
312 SPV_KHR_device_group, ExtensionRoundTripTest,
313 // We'll get coverage over operand tables by trying the universal
314 // environments, and at least one specific environment.
315 Combine(ValuesIn(CommonVulkanEnvs()),
316 ValuesIn(std::vector<AssemblyCase>{
317 {"OpCapability DeviceGroup\n",
318 MakeInstruction(SpvOpCapability, {SpvCapabilityDeviceGroup})},
319 {"OpDecorate %1 BuiltIn DeviceIndex\n",
320 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
321 SpvBuiltInDeviceIndex})},
322 })));
323
324 // SPV_KHR_8bit_storage
325
326 INSTANTIATE_TEST_SUITE_P(
327 SPV_KHR_8bit_storage, ExtensionRoundTripTest,
328 // We'll get coverage over operand tables by trying the universal
329 // environments, and at least one specific environment.
330 Combine(
331 ValuesIn(CommonVulkanEnvs()),
332 ValuesIn(std::vector<AssemblyCase>{
333 {"OpCapability StorageBuffer8BitAccess\n",
334 MakeInstruction(SpvOpCapability,
335 {SpvCapabilityStorageBuffer8BitAccess})},
336 {"OpCapability UniformAndStorageBuffer8BitAccess\n",
337 MakeInstruction(SpvOpCapability,
338 {SpvCapabilityUniformAndStorageBuffer8BitAccess})},
339 {"OpCapability StoragePushConstant8\n",
340 MakeInstruction(SpvOpCapability,
341 {SpvCapabilityStoragePushConstant8})},
342 })));
343
344 // SPV_KHR_multiview
345
346 INSTANTIATE_TEST_SUITE_P(
347 SPV_KHR_multiview, ExtensionRoundTripTest,
348 // We'll get coverage over operand tables by trying the universal
349 // environments, and at least one specific environment.
350 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
351 SPV_ENV_VULKAN_1_0),
352 ValuesIn(std::vector<AssemblyCase>{
353 {"OpCapability MultiView\n",
354 MakeInstruction(SpvOpCapability, {SpvCapabilityMultiView})},
355 {"OpDecorate %1 BuiltIn ViewIndex\n",
356 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
357 SpvBuiltInViewIndex})},
358 })));
359
360 // SPV_AMD_shader_explicit_vertex_parameter
361
362 #define PREAMBLE \
363 "%1 = OpExtInstImport \"SPV_AMD_shader_explicit_vertex_parameter\"\n"
364 INSTANTIATE_TEST_SUITE_P(
365 SPV_AMD_shader_explicit_vertex_parameter, ExtensionRoundTripTest,
366 // We'll get coverage over operand tables by trying the universal
367 // environments, and at least one specific environment.
368 Combine(
369 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
370 SPV_ENV_VULKAN_1_0),
371 ValuesIn(std::vector<AssemblyCase>{
372 {PREAMBLE "%3 = OpExtInst %2 %1 InterpolateAtVertexAMD %4 %5\n",
373 Concatenate(
374 {MakeInstruction(
375 SpvOpExtInstImport, {1},
376 MakeVector("SPV_AMD_shader_explicit_vertex_parameter")),
377 MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5})})},
378 })));
379 #undef PREAMBLE
380
381 // SPV_AMD_shader_trinary_minmax
382
383 #define PREAMBLE "%1 = OpExtInstImport \"SPV_AMD_shader_trinary_minmax\"\n"
384 INSTANTIATE_TEST_SUITE_P(
385 SPV_AMD_shader_trinary_minmax, ExtensionRoundTripTest,
386 // We'll get coverage over operand tables by trying the universal
387 // environments, and at least one specific environment.
388 Combine(
389 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
390 SPV_ENV_VULKAN_1_0),
391 ValuesIn(std::vector<AssemblyCase>{
392 {PREAMBLE "%3 = OpExtInst %2 %1 FMin3AMD %4 %5 %6\n",
393 Concatenate(
394 {MakeInstruction(SpvOpExtInstImport, {1},
395 MakeVector("SPV_AMD_shader_trinary_minmax")),
396 MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5, 6})})},
397 {PREAMBLE "%3 = OpExtInst %2 %1 UMin3AMD %4 %5 %6\n",
398 Concatenate(
399 {MakeInstruction(SpvOpExtInstImport, {1},
400 MakeVector("SPV_AMD_shader_trinary_minmax")),
401 MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4, 5, 6})})},
402 {PREAMBLE "%3 = OpExtInst %2 %1 SMin3AMD %4 %5 %6\n",
403 Concatenate(
404 {MakeInstruction(SpvOpExtInstImport, {1},
405 MakeVector("SPV_AMD_shader_trinary_minmax")),
406 MakeInstruction(SpvOpExtInst, {2, 3, 1, 3, 4, 5, 6})})},
407 {PREAMBLE "%3 = OpExtInst %2 %1 FMax3AMD %4 %5 %6\n",
408 Concatenate(
409 {MakeInstruction(SpvOpExtInstImport, {1},
410 MakeVector("SPV_AMD_shader_trinary_minmax")),
411 MakeInstruction(SpvOpExtInst, {2, 3, 1, 4, 4, 5, 6})})},
412 {PREAMBLE "%3 = OpExtInst %2 %1 UMax3AMD %4 %5 %6\n",
413 Concatenate(
414 {MakeInstruction(SpvOpExtInstImport, {1},
415 MakeVector("SPV_AMD_shader_trinary_minmax")),
416 MakeInstruction(SpvOpExtInst, {2, 3, 1, 5, 4, 5, 6})})},
417 {PREAMBLE "%3 = OpExtInst %2 %1 SMax3AMD %4 %5 %6\n",
418 Concatenate(
419 {MakeInstruction(SpvOpExtInstImport, {1},
420 MakeVector("SPV_AMD_shader_trinary_minmax")),
421 MakeInstruction(SpvOpExtInst, {2, 3, 1, 6, 4, 5, 6})})},
422 {PREAMBLE "%3 = OpExtInst %2 %1 FMid3AMD %4 %5 %6\n",
423 Concatenate(
424 {MakeInstruction(SpvOpExtInstImport, {1},
425 MakeVector("SPV_AMD_shader_trinary_minmax")),
426 MakeInstruction(SpvOpExtInst, {2, 3, 1, 7, 4, 5, 6})})},
427 {PREAMBLE "%3 = OpExtInst %2 %1 UMid3AMD %4 %5 %6\n",
428 Concatenate(
429 {MakeInstruction(SpvOpExtInstImport, {1},
430 MakeVector("SPV_AMD_shader_trinary_minmax")),
431 MakeInstruction(SpvOpExtInst, {2, 3, 1, 8, 4, 5, 6})})},
432 {PREAMBLE "%3 = OpExtInst %2 %1 SMid3AMD %4 %5 %6\n",
433 Concatenate(
434 {MakeInstruction(SpvOpExtInstImport, {1},
435 MakeVector("SPV_AMD_shader_trinary_minmax")),
436 MakeInstruction(SpvOpExtInst, {2, 3, 1, 9, 4, 5, 6})})},
437 })));
438 #undef PREAMBLE
439
440 // SPV_AMD_gcn_shader
441
442 #define PREAMBLE "%1 = OpExtInstImport \"SPV_AMD_gcn_shader\"\n"
443 INSTANTIATE_TEST_SUITE_P(
444 SPV_AMD_gcn_shader, ExtensionRoundTripTest,
445 // We'll get coverage over operand tables by trying the universal
446 // environments, and at least one specific environment.
447 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
448 SPV_ENV_VULKAN_1_0),
449 ValuesIn(std::vector<AssemblyCase>{
450 {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceIndexAMD %4\n",
451 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
452 MakeVector("SPV_AMD_gcn_shader")),
453 MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4})})},
454 {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceCoordAMD %4\n",
455 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
456 MakeVector("SPV_AMD_gcn_shader")),
457 MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4})})},
458 {PREAMBLE "%3 = OpExtInst %2 %1 TimeAMD\n",
459 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
460 MakeVector("SPV_AMD_gcn_shader")),
461 MakeInstruction(SpvOpExtInst, {2, 3, 1, 3})})},
462 })));
463 #undef PREAMBLE
464
465 // SPV_AMD_shader_ballot
466
467 #define PREAMBLE "%1 = OpExtInstImport \"SPV_AMD_shader_ballot\"\n"
468 INSTANTIATE_TEST_SUITE_P(
469 SPV_AMD_shader_ballot, ExtensionRoundTripTest,
470 // We'll get coverage over operand tables by trying the universal
471 // environments, and at least one specific environment.
472 Combine(
473 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
474 SPV_ENV_VULKAN_1_0),
475 ValuesIn(std::vector<AssemblyCase>{
476 {PREAMBLE "%3 = OpExtInst %2 %1 SwizzleInvocationsAMD %4 %5\n",
477 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
478 MakeVector("SPV_AMD_shader_ballot")),
479 MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5})})},
480 {PREAMBLE
481 "%3 = OpExtInst %2 %1 SwizzleInvocationsMaskedAMD %4 %5\n",
482 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
483 MakeVector("SPV_AMD_shader_ballot")),
484 MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4, 5})})},
485 {PREAMBLE "%3 = OpExtInst %2 %1 WriteInvocationAMD %4 %5 %6\n",
486 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
487 MakeVector("SPV_AMD_shader_ballot")),
488 MakeInstruction(SpvOpExtInst,
489 {2, 3, 1, 3, 4, 5, 6})})},
490 {PREAMBLE "%3 = OpExtInst %2 %1 MbcntAMD %4\n",
491 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
492 MakeVector("SPV_AMD_shader_ballot")),
493 MakeInstruction(SpvOpExtInst, {2, 3, 1, 4, 4})})},
494 })));
495 #undef PREAMBLE
496
497 // SPV_KHR_variable_pointers
498
499 INSTANTIATE_TEST_SUITE_P(
500 SPV_KHR_variable_pointers, ExtensionRoundTripTest,
501 // We'll get coverage over operand tables by trying the universal
502 // environments, and at least one specific environment.
503 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
504 SPV_ENV_VULKAN_1_0),
505 ValuesIn(std::vector<AssemblyCase>{
506 {"OpCapability VariablePointers\n",
507 MakeInstruction(SpvOpCapability,
508 {SpvCapabilityVariablePointers})},
509 {"OpCapability VariablePointersStorageBuffer\n",
510 MakeInstruction(SpvOpCapability,
511 {SpvCapabilityVariablePointersStorageBuffer})},
512 })));
513
514 // SPV_KHR_vulkan_memory_model
515
516 INSTANTIATE_TEST_SUITE_P(
517 SPV_KHR_vulkan_memory_model, ExtensionRoundTripTest,
518 // We'll get coverage over operand tables by trying the universal
519 // environments, and at least one specific environment.
520 //
521 // Note: SPV_KHR_vulkan_memory_model adds scope enum value QueueFamilyKHR.
522 // Scope enums are used in ID definitions elsewhere, that don't know they
523 // are using particular enums. So the assembler doesn't support assembling
524 // those enums names into the corresponding values. So there is no asm/dis
525 // tests for those enums.
526 Combine(
527 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
528 SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1),
529 ValuesIn(std::vector<AssemblyCase>{
530 {"OpCapability VulkanMemoryModel\n",
531 MakeInstruction(SpvOpCapability,
532 {SpvCapabilityVulkanMemoryModelKHR})},
533 {"OpCapability VulkanMemoryModelDeviceScope\n",
534 MakeInstruction(SpvOpCapability,
535 {SpvCapabilityVulkanMemoryModelDeviceScopeKHR})},
536 {"OpMemoryModel Logical Vulkan\n",
537 MakeInstruction(SpvOpMemoryModel, {SpvAddressingModelLogical,
538 SpvMemoryModelVulkanKHR})},
539 {"OpStore %1 %2 MakePointerAvailable %3\n",
540 MakeInstruction(SpvOpStore,
541 {1, 2, SpvMemoryAccessMakePointerAvailableKHRMask,
542 3})},
543 {"OpStore %1 %2 Volatile|MakePointerAvailable %3\n",
544 MakeInstruction(SpvOpStore,
545 {1, 2,
546 int(SpvMemoryAccessMakePointerAvailableKHRMask) |
547 int(SpvMemoryAccessVolatileMask),
548 3})},
549 {"OpStore %1 %2 Aligned|MakePointerAvailable 4 %3\n",
550 MakeInstruction(SpvOpStore,
551 {1, 2,
552 int(SpvMemoryAccessMakePointerAvailableKHRMask) |
553 int(SpvMemoryAccessAlignedMask),
554 4, 3})},
555 {"OpStore %1 %2 MakePointerAvailable|NonPrivatePointer %3\n",
556 MakeInstruction(SpvOpStore,
557 {1, 2,
558 int(SpvMemoryAccessMakePointerAvailableKHRMask) |
559 int(SpvMemoryAccessNonPrivatePointerKHRMask),
560 3})},
561 {"%2 = OpLoad %1 %3 MakePointerVisible %4\n",
562 MakeInstruction(SpvOpLoad,
563 {1, 2, 3, SpvMemoryAccessMakePointerVisibleKHRMask,
564 4})},
565 {"%2 = OpLoad %1 %3 Volatile|MakePointerVisible %4\n",
566 MakeInstruction(SpvOpLoad,
567 {1, 2, 3,
568 int(SpvMemoryAccessMakePointerVisibleKHRMask) |
569 int(SpvMemoryAccessVolatileMask),
570 4})},
571 {"%2 = OpLoad %1 %3 Aligned|MakePointerVisible 8 %4\n",
572 MakeInstruction(SpvOpLoad,
573 {1, 2, 3,
574 int(SpvMemoryAccessMakePointerVisibleKHRMask) |
575 int(SpvMemoryAccessAlignedMask),
576 8, 4})},
577 {"%2 = OpLoad %1 %3 MakePointerVisible|NonPrivatePointer "
578 "%4\n",
579 MakeInstruction(SpvOpLoad,
580 {1, 2, 3,
581 int(SpvMemoryAccessMakePointerVisibleKHRMask) |
582 int(SpvMemoryAccessNonPrivatePointerKHRMask),
583 4})},
584 {"OpCopyMemory %1 %2 "
585 "MakePointerAvailable|"
586 "MakePointerVisible|"
587 "NonPrivatePointer "
588 "%3 %4\n",
589 MakeInstruction(SpvOpCopyMemory,
590 {1, 2,
591 (int(SpvMemoryAccessMakePointerVisibleKHRMask) |
592 int(SpvMemoryAccessMakePointerAvailableKHRMask) |
593 int(SpvMemoryAccessNonPrivatePointerKHRMask)),
594 3, 4})},
595 {"OpCopyMemorySized %1 %2 %3 "
596 "MakePointerAvailable|"
597 "MakePointerVisible|"
598 "NonPrivatePointer "
599 "%4 %5\n",
600 MakeInstruction(SpvOpCopyMemorySized,
601 {1, 2, 3,
602 (int(SpvMemoryAccessMakePointerVisibleKHRMask) |
603 int(SpvMemoryAccessMakePointerAvailableKHRMask) |
604 int(SpvMemoryAccessNonPrivatePointerKHRMask)),
605 4, 5})},
606 // Image operands
607 {"OpImageWrite %1 %2 %3 MakeTexelAvailable "
608 "%4\n",
609 MakeInstruction(
610 SpvOpImageWrite,
611 {1, 2, 3, int(SpvImageOperandsMakeTexelAvailableKHRMask), 4})},
612 {"OpImageWrite %1 %2 %3 MakeTexelAvailable|NonPrivateTexel "
613 "%4\n",
614 MakeInstruction(SpvOpImageWrite,
615 {1, 2, 3,
616 int(SpvImageOperandsMakeTexelAvailableKHRMask) |
617 int(SpvImageOperandsNonPrivateTexelKHRMask),
618 4})},
619 {"OpImageWrite %1 %2 %3 "
620 "MakeTexelAvailable|NonPrivateTexel|VolatileTexel "
621 "%4\n",
622 MakeInstruction(SpvOpImageWrite,
623 {1, 2, 3,
624 int(SpvImageOperandsMakeTexelAvailableKHRMask) |
625 int(SpvImageOperandsNonPrivateTexelKHRMask) |
626 int(SpvImageOperandsVolatileTexelKHRMask),
627 4})},
628 {"%2 = OpImageRead %1 %3 %4 MakeTexelVisible "
629 "%5\n",
630 MakeInstruction(SpvOpImageRead,
631 {1, 2, 3, 4,
632 int(SpvImageOperandsMakeTexelVisibleKHRMask),
633 5})},
634 {"%2 = OpImageRead %1 %3 %4 "
635 "MakeTexelVisible|NonPrivateTexel "
636 "%5\n",
637 MakeInstruction(SpvOpImageRead,
638 {1, 2, 3, 4,
639 int(SpvImageOperandsMakeTexelVisibleKHRMask) |
640 int(SpvImageOperandsNonPrivateTexelKHRMask),
641 5})},
642 {"%2 = OpImageRead %1 %3 %4 "
643 "MakeTexelVisible|NonPrivateTexel|VolatileTexel "
644 "%5\n",
645 MakeInstruction(SpvOpImageRead,
646 {1, 2, 3, 4,
647 int(SpvImageOperandsMakeTexelVisibleKHRMask) |
648 int(SpvImageOperandsNonPrivateTexelKHRMask) |
649 int(SpvImageOperandsVolatileTexelKHRMask),
650 5})},
651
652 // Memory semantics ID values are numbers put into a SPIR-V
653 // constant integer referenced by Id. There is no token for
654 // them, and so no assembler or disassembler support required.
655 // Similar for Scope ID.
656 })));
657
658 // SPV_GOOGLE_decorate_string
659
660 // Now that OpDecorateString is the preferred spelling for
661 // OpDecorateStringGOOGLE use that name in round trip tests, and the GOOGLE
662 // name in an assembly-only test.
663
664 INSTANTIATE_TEST_SUITE_P(
665 SPV_GOOGLE_decorate_string, ExtensionRoundTripTest,
666 Combine(
667 // We'll get coverage over operand tables by trying the universal
668 // environments, and at least one specific environment.
669 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
670 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0),
671 ValuesIn(std::vector<AssemblyCase>{
672 {"OpDecorateString %1 UserSemantic \"ABC\"\n",
673 MakeInstruction(SpvOpDecorateStringGOOGLE,
674 {1, SpvDecorationHlslSemanticGOOGLE},
675 MakeVector("ABC"))},
676 {"OpDecorateString %1 UserSemantic \"ABC\"\n",
677 MakeInstruction(SpvOpDecorateString,
678 {1, SpvDecorationUserSemantic},
679 MakeVector("ABC"))},
680 {"OpMemberDecorateString %1 3 UserSemantic \"DEF\"\n",
681 MakeInstruction(SpvOpMemberDecorateStringGOOGLE,
682 {1, 3, SpvDecorationUserSemantic},
683 MakeVector("DEF"))},
684 {"OpMemberDecorateString %1 3 UserSemantic \"DEF\"\n",
685 MakeInstruction(SpvOpMemberDecorateString,
686 {1, 3, SpvDecorationUserSemantic},
687 MakeVector("DEF"))},
688 })));
689
690 INSTANTIATE_TEST_SUITE_P(
691 SPV_GOOGLE_decorate_string, ExtensionAssemblyTest,
692 Combine(
693 // We'll get coverage over operand tables by trying the universal
694 // environments, and at least one specific environment.
695 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
696 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0),
697 ValuesIn(std::vector<AssemblyCase>{
698 {"OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE \"ABC\"\n",
699 MakeInstruction(SpvOpDecorateStringGOOGLE,
700 {1, SpvDecorationHlslSemanticGOOGLE},
701 MakeVector("ABC"))},
702 {"OpMemberDecorateStringGOOGLE %1 3 HlslSemanticGOOGLE \"DEF\"\n",
703 MakeInstruction(SpvOpMemberDecorateStringGOOGLE,
704 {1, 3, SpvDecorationHlslSemanticGOOGLE},
705 MakeVector("DEF"))},
706 })));
707
708 // SPV_GOOGLE_hlsl_functionality1
709
710 // Now that CounterBuffer is the preferred spelling for HlslCounterBufferGOOGLE,
711 // use that name in round trip tests, and the GOOGLE name in an assembly-only
712 // test.
713 INSTANTIATE_TEST_SUITE_P(
714 SPV_GOOGLE_hlsl_functionality1, ExtensionRoundTripTest,
715 Combine(
716 // We'll get coverage over operand tables by trying the universal
717 // environments, and at least one specific environment.
718 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
719 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0),
720 // HlslSemanticGOOGLE is tested in SPV_GOOGLE_decorate_string, since
721 // they are coupled together.
722 ValuesIn(std::vector<AssemblyCase>{
723 {"OpDecorateId %1 CounterBuffer %2\n",
724 MakeInstruction(SpvOpDecorateId,
725 {1, SpvDecorationHlslCounterBufferGOOGLE, 2})},
726 {"OpDecorateId %1 CounterBuffer %2\n",
727 MakeInstruction(SpvOpDecorateId,
728 {1, SpvDecorationCounterBuffer, 2})},
729 })));
730
731 INSTANTIATE_TEST_SUITE_P(
732 SPV_GOOGLE_hlsl_functionality1, ExtensionAssemblyTest,
733 Combine(
734 // We'll get coverage over operand tables by trying the universal
735 // environments, and at least one specific environment.
736 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
737 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0),
738 // HlslSemanticGOOGLE is tested in SPV_GOOGLE_decorate_string, since
739 // they are coupled together.
740 ValuesIn(std::vector<AssemblyCase>{
741 {"OpDecorateId %1 HlslCounterBufferGOOGLE %2\n",
742 MakeInstruction(SpvOpDecorateId,
743 {1, SpvDecorationHlslCounterBufferGOOGLE, 2})},
744 })));
745
746 // SPV_NV_viewport_array2
747
748 INSTANTIATE_TEST_SUITE_P(
749 SPV_NV_viewport_array2, ExtensionRoundTripTest,
750 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
751 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3,
752 SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1),
753 ValuesIn(std::vector<AssemblyCase>{
754 {"OpExtension \"SPV_NV_viewport_array2\"\n",
755 MakeInstruction(SpvOpExtension,
756 MakeVector("SPV_NV_viewport_array2"))},
757 // The EXT and NV extensions have the same token number for this
758 // capability.
759 {"OpCapability ShaderViewportIndexLayerEXT\n",
760 MakeInstruction(SpvOpCapability,
761 {SpvCapabilityShaderViewportIndexLayerNV})},
762 // Check the new capability's token number
763 {"OpCapability ShaderViewportIndexLayerEXT\n",
764 MakeInstruction(SpvOpCapability, {5254})},
765 // Decorations
766 {"OpDecorate %1 ViewportRelativeNV\n",
767 MakeInstruction(SpvOpDecorate,
768 {1, SpvDecorationViewportRelativeNV})},
769 {"OpDecorate %1 BuiltIn ViewportMaskNV\n",
770 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
771 SpvBuiltInViewportMaskNV})},
772 })));
773
774 // SPV_NV_shader_subgroup_partitioned
775
776 INSTANTIATE_TEST_SUITE_P(
777 SPV_NV_shader_subgroup_partitioned, ExtensionRoundTripTest,
778 Combine(
779 Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
780 ValuesIn(std::vector<AssemblyCase>{
781 {"OpExtension \"SPV_NV_shader_subgroup_partitioned\"\n",
782 MakeInstruction(SpvOpExtension,
783 MakeVector("SPV_NV_shader_subgroup_partitioned"))},
784 {"OpCapability GroupNonUniformPartitionedNV\n",
785 MakeInstruction(SpvOpCapability,
786 {SpvCapabilityGroupNonUniformPartitionedNV})},
787 // Check the new capability's token number
788 {"OpCapability GroupNonUniformPartitionedNV\n",
789 MakeInstruction(SpvOpCapability, {5297})},
790 {"%2 = OpGroupNonUniformPartitionNV %1 %3\n",
791 MakeInstruction(SpvOpGroupNonUniformPartitionNV, {1, 2, 3})},
792 // Check the new instruction's token number
793 {"%2 = OpGroupNonUniformPartitionNV %1 %3\n",
794 MakeInstruction(static_cast<SpvOp>(5296), {1, 2, 3})},
795 // Check the new group operations
796 {"%2 = OpGroupIAdd %1 %3 PartitionedReduceNV %4\n",
797 MakeInstruction(SpvOpGroupIAdd,
798 {1, 2, 3, SpvGroupOperationPartitionedReduceNV,
799 4})},
800 {"%2 = OpGroupIAdd %1 %3 PartitionedReduceNV %4\n",
801 MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 6, 4})},
802 {"%2 = OpGroupIAdd %1 %3 PartitionedInclusiveScanNV %4\n",
803 MakeInstruction(SpvOpGroupIAdd,
804 {1, 2, 3,
805 SpvGroupOperationPartitionedInclusiveScanNV, 4})},
806 {"%2 = OpGroupIAdd %1 %3 PartitionedInclusiveScanNV %4\n",
807 MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 7, 4})},
808 {"%2 = OpGroupIAdd %1 %3 PartitionedExclusiveScanNV %4\n",
809 MakeInstruction(SpvOpGroupIAdd,
810 {1, 2, 3,
811 SpvGroupOperationPartitionedExclusiveScanNV, 4})},
812 {"%2 = OpGroupIAdd %1 %3 PartitionedExclusiveScanNV %4\n",
813 MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 8, 4})},
814 })));
815
816 // SPV_EXT_descriptor_indexing
817
818 INSTANTIATE_TEST_SUITE_P(
819 SPV_EXT_descriptor_indexing, ExtensionRoundTripTest,
820 Combine(
821 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
822 SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0,
823 SPV_ENV_VULKAN_1_1),
824 ValuesIn(std::vector<AssemblyCase>{
825 {"OpExtension \"SPV_EXT_descriptor_indexing\"\n",
826 MakeInstruction(SpvOpExtension,
827 MakeVector("SPV_EXT_descriptor_indexing"))},
828 // Check capabilities, by name
829 {"OpCapability ShaderNonUniform\n",
830 MakeInstruction(SpvOpCapability,
831 {SpvCapabilityShaderNonUniformEXT})},
832 {"OpCapability RuntimeDescriptorArray\n",
833 MakeInstruction(SpvOpCapability,
834 {SpvCapabilityRuntimeDescriptorArrayEXT})},
835 {"OpCapability InputAttachmentArrayDynamicIndexing\n",
836 MakeInstruction(
837 SpvOpCapability,
838 {SpvCapabilityInputAttachmentArrayDynamicIndexingEXT})},
839 {"OpCapability UniformTexelBufferArrayDynamicIndexing\n",
840 MakeInstruction(
841 SpvOpCapability,
842 {SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT})},
843 {"OpCapability StorageTexelBufferArrayDynamicIndexing\n",
844 MakeInstruction(
845 SpvOpCapability,
846 {SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT})},
847 {"OpCapability UniformBufferArrayNonUniformIndexing\n",
848 MakeInstruction(
849 SpvOpCapability,
850 {SpvCapabilityUniformBufferArrayNonUniformIndexingEXT})},
851 {"OpCapability SampledImageArrayNonUniformIndexing\n",
852 MakeInstruction(
853 SpvOpCapability,
854 {SpvCapabilitySampledImageArrayNonUniformIndexingEXT})},
855 {"OpCapability StorageBufferArrayNonUniformIndexing\n",
856 MakeInstruction(
857 SpvOpCapability,
858 {SpvCapabilityStorageBufferArrayNonUniformIndexingEXT})},
859 {"OpCapability StorageImageArrayNonUniformIndexing\n",
860 MakeInstruction(
861 SpvOpCapability,
862 {SpvCapabilityStorageImageArrayNonUniformIndexingEXT})},
863 {"OpCapability InputAttachmentArrayNonUniformIndexing\n",
864 MakeInstruction(
865 SpvOpCapability,
866 {SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT})},
867 {"OpCapability UniformTexelBufferArrayNonUniformIndexing\n",
868 MakeInstruction(
869 SpvOpCapability,
870 {SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT})},
871 {"OpCapability StorageTexelBufferArrayNonUniformIndexing\n",
872 MakeInstruction(
873 SpvOpCapability,
874 {SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT})},
875 // Check capabilities, by number
876 {"OpCapability ShaderNonUniform\n",
877 MakeInstruction(SpvOpCapability, {5301})},
878 {"OpCapability RuntimeDescriptorArray\n",
879 MakeInstruction(SpvOpCapability, {5302})},
880 {"OpCapability InputAttachmentArrayDynamicIndexing\n",
881 MakeInstruction(SpvOpCapability, {5303})},
882 {"OpCapability UniformTexelBufferArrayDynamicIndexing\n",
883 MakeInstruction(SpvOpCapability, {5304})},
884 {"OpCapability StorageTexelBufferArrayDynamicIndexing\n",
885 MakeInstruction(SpvOpCapability, {5305})},
886 {"OpCapability UniformBufferArrayNonUniformIndexing\n",
887 MakeInstruction(SpvOpCapability, {5306})},
888 {"OpCapability SampledImageArrayNonUniformIndexing\n",
889 MakeInstruction(SpvOpCapability, {5307})},
890 {"OpCapability StorageBufferArrayNonUniformIndexing\n",
891 MakeInstruction(SpvOpCapability, {5308})},
892 {"OpCapability StorageImageArrayNonUniformIndexing\n",
893 MakeInstruction(SpvOpCapability, {5309})},
894 {"OpCapability InputAttachmentArrayNonUniformIndexing\n",
895 MakeInstruction(SpvOpCapability, {5310})},
896 {"OpCapability UniformTexelBufferArrayNonUniformIndexing\n",
897 MakeInstruction(SpvOpCapability, {5311})},
898 {"OpCapability StorageTexelBufferArrayNonUniformIndexing\n",
899 MakeInstruction(SpvOpCapability, {5312})},
900
901 // Check the decoration token
902 {"OpDecorate %1 NonUniform\n",
903 MakeInstruction(SpvOpDecorate, {1, SpvDecorationNonUniformEXT})},
904 {"OpDecorate %1 NonUniform\n",
905 MakeInstruction(SpvOpDecorate, {1, 5300})},
906 })));
907
908 // SPV_KHR_linkonce_odr
909
910 INSTANTIATE_TEST_SUITE_P(
911 SPV_KHR_linkonce_odr, ExtensionRoundTripTest,
912 Combine(
913 Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0,
914 SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2),
915 ValuesIn(std::vector<AssemblyCase>{
916 {"OpExtension \"SPV_KHR_linkonce_odr\"\n",
917 MakeInstruction(SpvOpExtension,
918 MakeVector("SPV_KHR_linkonce_odr"))},
919 {"OpDecorate %1 LinkageAttributes \"foobar\" LinkOnceODR\n",
920 MakeInstruction(SpvOpDecorate,
921 Concatenate({{1, SpvDecorationLinkageAttributes},
922 MakeVector("foobar"),
923 {SpvLinkageTypeLinkOnceODR}}))},
924 })));
925
926 // SPV_KHR_expect_assume
927
928 INSTANTIATE_TEST_SUITE_P(
929 SPV_KHR_expect_assume, ExtensionRoundTripTest,
930 Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_3,
931 SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2),
932 ValuesIn(std::vector<AssemblyCase>{
933 {"OpExtension \"SPV_KHR_expect_assume\"\n",
934 MakeInstruction(SpvOpExtension,
935 MakeVector("SPV_KHR_expect_assume"))},
936 {"OpAssumeTrueKHR %1\n",
937 MakeInstruction(SpvOpAssumeTrueKHR, {1})}})));
938
939 } // namespace
940 } // namespace spvtools
941