1 // Copyright (c) 2017 Google 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 #include <sstream>
16 #include <string>
17
18 #include "gmock/gmock.h"
19 #include "test/unit_spirv.h"
20 #include "test/val/val_code_generator.h"
21 #include "test/val/val_fixtures.h"
22
23 namespace spvtools {
24 namespace val {
25 namespace {
26
27 using ::testing::HasSubstr;
28 using ::testing::Not;
29 using ::testing::Values;
30
31 using ValidateComposites = spvtest::ValidateBase<bool>;
32
GenerateShaderCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & execution_model="Fragment")33 std::string GenerateShaderCode(
34 const std::string& body,
35 const std::string& capabilities_and_extensions = "",
36 const std::string& execution_model = "Fragment") {
37 std::ostringstream ss;
38 ss << R"(
39 OpCapability Shader
40 OpCapability Float64
41 )";
42
43 ss << capabilities_and_extensions;
44 ss << "OpMemoryModel Logical GLSL450\n";
45 ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
46 if (execution_model == "Fragment") {
47 ss << "OpExecutionMode %main OriginUpperLeft\n";
48 }
49
50 ss << R"(
51 %void = OpTypeVoid
52 %func = OpTypeFunction %void
53 %bool = OpTypeBool
54 %f32 = OpTypeFloat 32
55 %f64 = OpTypeFloat 64
56 %u32 = OpTypeInt 32 0
57 %s32 = OpTypeInt 32 1
58 %f32vec2 = OpTypeVector %f32 2
59 %f32vec3 = OpTypeVector %f32 3
60 %f32vec4 = OpTypeVector %f32 4
61 %f64vec2 = OpTypeVector %f64 2
62 %u32vec2 = OpTypeVector %u32 2
63 %u32vec4 = OpTypeVector %u32 4
64 %f64mat22 = OpTypeMatrix %f64vec2 2
65 %f32mat22 = OpTypeMatrix %f32vec2 2
66 %f32mat23 = OpTypeMatrix %f32vec2 3
67 %f32mat32 = OpTypeMatrix %f32vec3 2
68
69 %f32_0 = OpConstant %f32 0
70 %f32_1 = OpConstant %f32 1
71 %f32_2 = OpConstant %f32 2
72 %f32_3 = OpConstant %f32 3
73 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
74 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
75 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
76
77 %u32_0 = OpConstant %u32 0
78 %u32_1 = OpConstant %u32 1
79 %u32_2 = OpConstant %u32 2
80 %u32_3 = OpConstant %u32 3
81
82 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
83 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
84
85 %f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12
86 %f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
87
88 %f32vec2arr3 = OpTypeArray %f32vec2 %u32_3
89 %f32vec2arr2 = OpTypeArray %f32vec2 %u32_2
90
91 %f32u32struct = OpTypeStruct %f32 %u32
92 %big_struct = OpTypeStruct %f32 %f32vec4 %f32mat23 %f32vec2arr3 %f32vec2arr2 %f32u32struct
93
94 %ptr_big_struct = OpTypePointer Uniform %big_struct
95 %var_big_struct = OpVariable %ptr_big_struct Uniform
96
97 %main = OpFunction %void None %func
98 %main_entry = OpLabel
99 )";
100
101 ss << body;
102
103 ss << R"(
104 OpReturn
105 OpFunctionEnd)";
106
107 return ss.str();
108 }
109
110 // Returns header for legacy tests taken from val_id_test.cpp.
GetHeaderForTestsFromValId()111 std::string GetHeaderForTestsFromValId() {
112 return R"(
113 OpCapability Shader
114 OpCapability Linkage
115 OpCapability Addresses
116 OpCapability Pipes
117 OpCapability LiteralSampler
118 OpCapability DeviceEnqueue
119 OpCapability Vector16
120 OpCapability Int8
121 OpCapability Int16
122 OpCapability Int64
123 OpCapability Float64
124 OpMemoryModel Logical GLSL450
125 %void = OpTypeVoid
126 %void_f = OpTypeFunction %void
127 %int = OpTypeInt 32 0
128 %float = OpTypeFloat 32
129 %v3float = OpTypeVector %float 3
130 %mat4x3 = OpTypeMatrix %v3float 4
131 %_ptr_Private_mat4x3 = OpTypePointer Private %mat4x3
132 %_ptr_Private_float = OpTypePointer Private %float
133 %my_matrix = OpVariable %_ptr_Private_mat4x3 Private
134 %my_float_var = OpVariable %_ptr_Private_float Private
135 %_ptr_Function_float = OpTypePointer Function %float
136 %int_0 = OpConstant %int 0
137 %int_1 = OpConstant %int 1
138 %int_2 = OpConstant %int 2
139 %int_3 = OpConstant %int 3
140 %int_5 = OpConstant %int 5
141
142 ; Making the following nested structures.
143 ;
144 ; struct S {
145 ; bool b;
146 ; vec4 v[5];
147 ; int i;
148 ; mat4x3 m[5];
149 ; }
150 ; uniform blockName {
151 ; S s;
152 ; bool cond;
153 ; }
154
155 %f32arr = OpTypeRuntimeArray %float
156 %v4float = OpTypeVector %float 4
157 %array5_mat4x3 = OpTypeArray %mat4x3 %int_5
158 %array5_vec4 = OpTypeArray %v4float %int_5
159 %_ptr_Uniform_float = OpTypePointer Uniform %float
160 %_ptr_Function_vec4 = OpTypePointer Function %v4float
161 %_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float
162 %struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3
163 %struct_blockName = OpTypeStruct %struct_s %int
164 %_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName
165 %_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s
166 %_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3
167 %_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3
168 %_ptr_Uniform_v3float = OpTypePointer Uniform %v3float
169 %blockName_var = OpVariable %_ptr_Uniform_blockName Uniform
170 %spec_int = OpSpecConstant %int 2
171 %func = OpFunction %void None %void_f
172 %my_label = OpLabel
173 )";
174 }
175
TEST_F(ValidateComposites,VectorExtractDynamicSuccess)176 TEST_F(ValidateComposites, VectorExtractDynamicSuccess) {
177 const std::string body = R"(
178 %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %u32_0
179 )";
180
181 CompileSuccessfully(GenerateShaderCode(body).c_str());
182 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
183 }
184
TEST_F(ValidateComposites,VectorExtractDynamicWrongResultType)185 TEST_F(ValidateComposites, VectorExtractDynamicWrongResultType) {
186 const std::string body = R"(
187 %val1 = OpVectorExtractDynamic %f32vec4 %f32vec4_0123 %u32_0
188 )";
189
190 CompileSuccessfully(GenerateShaderCode(body).c_str());
191 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
192 EXPECT_THAT(getDiagnosticString(),
193 HasSubstr("Expected Result Type to be a scalar type"));
194 }
195
TEST_F(ValidateComposites,VectorExtractDynamicNotVector)196 TEST_F(ValidateComposites, VectorExtractDynamicNotVector) {
197 const std::string body = R"(
198 %val1 = OpVectorExtractDynamic %f32 %f32mat22_1212 %u32_0
199 )";
200
201 CompileSuccessfully(GenerateShaderCode(body).c_str());
202 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
203 EXPECT_THAT(getDiagnosticString(),
204 HasSubstr("Expected Vector type to be OpTypeVector"));
205 }
206
TEST_F(ValidateComposites,VectorExtractDynamicWrongVectorComponent)207 TEST_F(ValidateComposites, VectorExtractDynamicWrongVectorComponent) {
208 const std::string body = R"(
209 %val1 = OpVectorExtractDynamic %f32 %u32vec4_0123 %u32_0
210 )";
211
212 CompileSuccessfully(GenerateShaderCode(body).c_str());
213 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
214 EXPECT_THAT(
215 getDiagnosticString(),
216 HasSubstr("Expected Vector component type to be equal to Result Type"));
217 }
218
TEST_F(ValidateComposites,VectorExtractDynamicWrongIndexType)219 TEST_F(ValidateComposites, VectorExtractDynamicWrongIndexType) {
220 const std::string body = R"(
221 %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %f32_0
222 )";
223
224 CompileSuccessfully(GenerateShaderCode(body).c_str());
225 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
226 EXPECT_THAT(getDiagnosticString(),
227 HasSubstr("Expected Index to be int scalar"));
228 }
229
TEST_F(ValidateComposites,VectorInsertDynamicSuccess)230 TEST_F(ValidateComposites, VectorInsertDynamicSuccess) {
231 const std::string body = R"(
232 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %u32_0
233 )";
234
235 CompileSuccessfully(GenerateShaderCode(body).c_str());
236 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
237 }
238
TEST_F(ValidateComposites,VectorInsertDynamicWrongResultType)239 TEST_F(ValidateComposites, VectorInsertDynamicWrongResultType) {
240 const std::string body = R"(
241 %val1 = OpVectorInsertDynamic %f32 %f32vec4_0123 %f32_1 %u32_0
242 )";
243
244 CompileSuccessfully(GenerateShaderCode(body).c_str());
245 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
246 EXPECT_THAT(getDiagnosticString(),
247 HasSubstr("Expected Result Type to be OpTypeVector"));
248 }
249
TEST_F(ValidateComposites,VectorInsertDynamicNotVector)250 TEST_F(ValidateComposites, VectorInsertDynamicNotVector) {
251 const std::string body = R"(
252 %val1 = OpVectorInsertDynamic %f32vec4 %f32mat22_1212 %f32_1 %u32_0
253 )";
254
255 CompileSuccessfully(GenerateShaderCode(body).c_str());
256 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
257 EXPECT_THAT(getDiagnosticString(),
258 HasSubstr("Expected Vector type to be equal to Result Type"));
259 }
260
TEST_F(ValidateComposites,VectorInsertDynamicWrongComponentType)261 TEST_F(ValidateComposites, VectorInsertDynamicWrongComponentType) {
262 const std::string body = R"(
263 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %u32_1 %u32_0
264 )";
265
266 CompileSuccessfully(GenerateShaderCode(body).c_str());
267 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
268 EXPECT_THAT(getDiagnosticString(),
269 HasSubstr("Expected Component type to be equal to Result Type "
270 "component type"));
271 }
272
TEST_F(ValidateComposites,VectorInsertDynamicWrongIndexType)273 TEST_F(ValidateComposites, VectorInsertDynamicWrongIndexType) {
274 const std::string body = R"(
275 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %f32_0
276 )";
277
278 CompileSuccessfully(GenerateShaderCode(body).c_str());
279 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
280 EXPECT_THAT(getDiagnosticString(),
281 HasSubstr("Expected Index to be int scalar"));
282 }
283
TEST_F(ValidateComposites,CompositeConstructNotComposite)284 TEST_F(ValidateComposites, CompositeConstructNotComposite) {
285 const std::string body = R"(
286 %val1 = OpCompositeConstruct %f32 %f32_1
287 )";
288
289 CompileSuccessfully(GenerateShaderCode(body).c_str());
290 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
291 EXPECT_THAT(getDiagnosticString(),
292 HasSubstr("Expected Result Type to be a composite type"));
293 }
294
TEST_F(ValidateComposites,CompositeConstructVectorSuccess)295 TEST_F(ValidateComposites, CompositeConstructVectorSuccess) {
296 const std::string body = R"(
297 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12
298 %val2 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0 %f32_0
299 %val3 = OpCompositeConstruct %f32vec4 %f32_0 %f32_0 %f32vec2_12
300 %val4 = OpCompositeConstruct %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
301 )";
302
303 CompileSuccessfully(GenerateShaderCode(body).c_str());
304 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
305 }
306
TEST_F(ValidateComposites,CompositeConstructVectorOnlyOneConstituent)307 TEST_F(ValidateComposites, CompositeConstructVectorOnlyOneConstituent) {
308 const std::string body = R"(
309 %val1 = OpCompositeConstruct %f32vec4 %f32vec4_0123
310 )";
311
312 CompileSuccessfully(GenerateShaderCode(body).c_str());
313 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
314 EXPECT_THAT(getDiagnosticString(),
315 HasSubstr("Expected number of constituents to be at least 2"));
316 }
317
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituent1)318 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent1) {
319 const std::string body = R"(
320 %val1 = OpCompositeConstruct %f32vec4 %f32 %f32vec2_12
321 )";
322
323 CompileSuccessfully(GenerateShaderCode(body).c_str());
324 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
325 EXPECT_THAT(getDiagnosticString(),
326 HasSubstr("Operand '5[%float]' cannot be a "
327 "type"));
328 }
329
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituent2)330 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent2) {
331 const std::string body = R"(
332 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32vec2_01
333 )";
334
335 CompileSuccessfully(GenerateShaderCode(body).c_str());
336 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
337 EXPECT_THAT(
338 getDiagnosticString(),
339 HasSubstr("Expected Constituents to be scalars or vectors of the same "
340 "type as Result Type components"));
341 }
342
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituent3)343 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent3) {
344 const std::string body = R"(
345 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32_0 %f32_0
346 )";
347
348 CompileSuccessfully(GenerateShaderCode(body).c_str());
349 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
350 EXPECT_THAT(
351 getDiagnosticString(),
352 HasSubstr("Expected Constituents to be scalars or vectors of the same "
353 "type as Result Type components"));
354 }
355
TEST_F(ValidateComposites,CompositeConstructVectorWrongComponentNumber1)356 TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber1) {
357 const std::string body = R"(
358 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0
359 )";
360
361 CompileSuccessfully(GenerateShaderCode(body).c_str());
362 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
363 EXPECT_THAT(
364 getDiagnosticString(),
365 HasSubstr("Expected total number of given components to be equal to the "
366 "size of Result Type vector"));
367 }
368
TEST_F(ValidateComposites,CompositeConstructVectorWrongComponentNumber2)369 TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber2) {
370 const std::string body = R"(
371 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12 %f32_0
372 )";
373
374 CompileSuccessfully(GenerateShaderCode(body).c_str());
375 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
376 EXPECT_THAT(
377 getDiagnosticString(),
378 HasSubstr("Expected total number of given components to be equal to the "
379 "size of Result Type vector"));
380 }
381
TEST_F(ValidateComposites,CompositeConstructMatrixSuccess)382 TEST_F(ValidateComposites, CompositeConstructMatrixSuccess) {
383 const std::string body = R"(
384 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12
385 %val2 = OpCompositeConstruct %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
386 )";
387
388 CompileSuccessfully(GenerateShaderCode(body).c_str());
389 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
390 }
391
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituentNumber1)392 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber1) {
393 const std::string body = R"(
394 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12
395 )";
396
397 CompileSuccessfully(GenerateShaderCode(body).c_str());
398 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
399 EXPECT_THAT(
400 getDiagnosticString(),
401 HasSubstr("Expected total number of Constituents to be equal to the "
402 "number of columns of Result Type matrix"));
403 }
404
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituentNumber2)405 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber2) {
406 const std::string body = R"(
407 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12 %f32vec2_12
408 )";
409
410 CompileSuccessfully(GenerateShaderCode(body).c_str());
411 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
412 EXPECT_THAT(
413 getDiagnosticString(),
414 HasSubstr("Expected total number of Constituents to be equal to the "
415 "number of columns of Result Type matrix"));
416 }
417
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituent)418 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent) {
419 const std::string body = R"(
420 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %u32vec2_01
421 )";
422
423 CompileSuccessfully(GenerateShaderCode(body).c_str());
424 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
425 EXPECT_THAT(
426 getDiagnosticString(),
427 HasSubstr("Expected Constituent type to be equal to the column type "
428 "Result Type matrix"));
429 }
430
TEST_F(ValidateComposites,CompositeConstructArraySuccess)431 TEST_F(ValidateComposites, CompositeConstructArraySuccess) {
432 const std::string body = R"(
433 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
434 )";
435
436 CompileSuccessfully(GenerateShaderCode(body).c_str());
437 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
438 }
439
TEST_F(ValidateComposites,CompositeConstructArrayWrongConsituentNumber1)440 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber1) {
441 const std::string body = R"(
442 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12
443 )";
444
445 CompileSuccessfully(GenerateShaderCode(body).c_str());
446 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
447 EXPECT_THAT(
448 getDiagnosticString(),
449 HasSubstr("Expected total number of Constituents to be equal to the "
450 "number of elements of Result Type array"));
451 }
452
TEST_F(ValidateComposites,CompositeConstructArrayWrongConsituentNumber2)453 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber2) {
454 const std::string body = R"(
455 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 %f32vec2_12
456 )";
457
458 CompileSuccessfully(GenerateShaderCode(body).c_str());
459 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
460 EXPECT_THAT(
461 getDiagnosticString(),
462 HasSubstr("Expected total number of Constituents to be equal to the "
463 "number of elements of Result Type array"));
464 }
465
TEST_F(ValidateComposites,CompositeConstructArrayWrongConsituent)466 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituent) {
467 const std::string body = R"(
468 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %u32vec2_01 %f32vec2_12
469 )";
470
471 CompileSuccessfully(GenerateShaderCode(body).c_str());
472 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
473 EXPECT_THAT(
474 getDiagnosticString(),
475 HasSubstr("Expected Constituent type to be equal to the column type "
476 "Result Type array"));
477 }
478
TEST_F(ValidateComposites,CompositeConstructStructSuccess)479 TEST_F(ValidateComposites, CompositeConstructStructSuccess) {
480 const std::string body = R"(
481 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1
482 )";
483
484 CompileSuccessfully(GenerateShaderCode(body).c_str());
485 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
486 }
487
TEST_F(ValidateComposites,CompositeConstructStructWrongConstituentNumber1)488 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber1) {
489 const std::string body = R"(
490 %val1 = OpCompositeConstruct %f32u32struct %f32_0
491 )";
492
493 CompileSuccessfully(GenerateShaderCode(body).c_str());
494 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
495 EXPECT_THAT(
496 getDiagnosticString(),
497 HasSubstr("Expected total number of Constituents to be equal to the "
498 "number of members of Result Type struct"));
499 }
500
TEST_F(ValidateComposites,CompositeConstructStructWrongConstituentNumber2)501 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber2) {
502 const std::string body = R"(
503 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1 %u32_1
504 )";
505
506 CompileSuccessfully(GenerateShaderCode(body).c_str());
507 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
508 EXPECT_THAT(
509 getDiagnosticString(),
510 HasSubstr("Expected total number of Constituents to be equal to the "
511 "number of members of Result Type struct"));
512 }
513
TEST_F(ValidateComposites,CompositeConstructStructWrongConstituent)514 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituent) {
515 const std::string body = R"(
516 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %f32_1
517 )";
518
519 CompileSuccessfully(GenerateShaderCode(body).c_str());
520 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
521 EXPECT_THAT(getDiagnosticString(),
522 HasSubstr("Expected Constituent type to be equal to the "
523 "corresponding member type of Result Type struct"));
524 }
525
TEST_F(ValidateComposites,CopyObjectSuccess)526 TEST_F(ValidateComposites, CopyObjectSuccess) {
527 const std::string body = R"(
528 %val1 = OpCopyObject %f32 %f32_0
529 %val2 = OpCopyObject %f32vec4 %f32vec4_0123
530 )";
531
532 CompileSuccessfully(GenerateShaderCode(body).c_str());
533 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
534 }
535
TEST_F(ValidateComposites,CopyObjectResultTypeNotType)536 TEST_F(ValidateComposites, CopyObjectResultTypeNotType) {
537 const std::string body = R"(
538 %val1 = OpCopyObject %f32_0 %f32_0
539 )";
540
541 CompileSuccessfully(GenerateShaderCode(body).c_str());
542 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
543 EXPECT_THAT(getDiagnosticString(),
544 HasSubstr("ID '19[%float_0]' is not a type id"));
545 }
546
TEST_F(ValidateComposites,CopyObjectWrongOperandType)547 TEST_F(ValidateComposites, CopyObjectWrongOperandType) {
548 const std::string body = R"(
549 %val1 = OpCopyObject %f32 %u32_0
550 )";
551
552 CompileSuccessfully(GenerateShaderCode(body).c_str());
553 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
554 EXPECT_THAT(
555 getDiagnosticString(),
556 HasSubstr("Expected Result Type and Operand type to be the same"));
557 }
558
TEST_F(ValidateComposites,TransposeSuccess)559 TEST_F(ValidateComposites, TransposeSuccess) {
560 const std::string body = R"(
561 %val1 = OpTranspose %f32mat32 %f32mat23_121212
562 %val2 = OpTranspose %f32mat22 %f32mat22_1212
563 )";
564
565 CompileSuccessfully(GenerateShaderCode(body).c_str());
566 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
567 }
568
TEST_F(ValidateComposites,TransposeResultTypeNotMatrix)569 TEST_F(ValidateComposites, TransposeResultTypeNotMatrix) {
570 const std::string body = R"(
571 %val1 = OpTranspose %f32vec4 %f32mat22_1212
572 )";
573
574 CompileSuccessfully(GenerateShaderCode(body).c_str());
575 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
576 EXPECT_THAT(getDiagnosticString(),
577 HasSubstr("Expected Result Type to be a matrix type"));
578 }
579
TEST_F(ValidateComposites,TransposeDifferentComponentTypes)580 TEST_F(ValidateComposites, TransposeDifferentComponentTypes) {
581 const std::string body = R"(
582 %val1 = OpTranspose %f64mat22 %f32mat22_1212
583 )";
584
585 CompileSuccessfully(GenerateShaderCode(body).c_str());
586 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
587 EXPECT_THAT(
588 getDiagnosticString(),
589 HasSubstr("Expected component types of Matrix and Result Type to be "
590 "identical"));
591 }
592
TEST_F(ValidateComposites,TransposeIncompatibleDimensions1)593 TEST_F(ValidateComposites, TransposeIncompatibleDimensions1) {
594 const std::string body = R"(
595 %val1 = OpTranspose %f32mat23 %f32mat22_1212
596 )";
597
598 CompileSuccessfully(GenerateShaderCode(body).c_str());
599 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
600 EXPECT_THAT(getDiagnosticString(),
601 HasSubstr("Expected number of columns and the column size "
602 "of Matrix to be the reverse of those of Result Type"));
603 }
604
TEST_F(ValidateComposites,TransposeIncompatibleDimensions2)605 TEST_F(ValidateComposites, TransposeIncompatibleDimensions2) {
606 const std::string body = R"(
607 %val1 = OpTranspose %f32mat32 %f32mat22_1212
608 )";
609
610 CompileSuccessfully(GenerateShaderCode(body).c_str());
611 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
612 EXPECT_THAT(getDiagnosticString(),
613 HasSubstr("Expected number of columns and the column size "
614 "of Matrix to be the reverse of those of Result Type"));
615 }
616
TEST_F(ValidateComposites,TransposeIncompatibleDimensions3)617 TEST_F(ValidateComposites, TransposeIncompatibleDimensions3) {
618 const std::string body = R"(
619 %val1 = OpTranspose %f32mat23 %f32mat23_121212
620 )";
621
622 CompileSuccessfully(GenerateShaderCode(body).c_str());
623 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
624 EXPECT_THAT(getDiagnosticString(),
625 HasSubstr("Expected number of columns and the column size "
626 "of Matrix to be the reverse of those of Result Type"));
627 }
628
TEST_F(ValidateComposites,CompositeExtractSuccess)629 TEST_F(ValidateComposites, CompositeExtractSuccess) {
630 const std::string body = R"(
631 %val1 = OpCompositeExtract %f32 %f32vec4_0123 1
632 %val2 = OpCompositeExtract %u32 %u32vec4_0123 0
633 %val3 = OpCompositeExtract %f32 %f32mat22_1212 0 1
634 %val4 = OpCompositeExtract %f32vec2 %f32mat22_1212 0
635 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
636 %val5 = OpCompositeExtract %f32vec2 %array 2
637 %val6 = OpCompositeExtract %f32 %array 2 1
638 %struct = OpLoad %big_struct %var_big_struct
639 %val7 = OpCompositeExtract %f32 %struct 0
640 %val8 = OpCompositeExtract %f32vec4 %struct 1
641 %val9 = OpCompositeExtract %f32 %struct 1 2
642 %val10 = OpCompositeExtract %f32mat23 %struct 2
643 %val11 = OpCompositeExtract %f32vec2 %struct 2 2
644 %val12 = OpCompositeExtract %f32 %struct 2 2 1
645 %val13 = OpCompositeExtract %f32vec2 %struct 3 2
646 %val14 = OpCompositeExtract %f32 %struct 3 2 1
647 %val15 = OpCompositeExtract %f32vec2 %struct 4 1
648 %val16 = OpCompositeExtract %f32 %struct 4 0 1
649 %val17 = OpCompositeExtract %f32 %struct 5 0
650 %val18 = OpCompositeExtract %u32 %struct 5 1
651 )";
652
653 CompileSuccessfully(GenerateShaderCode(body));
654 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
655 }
656
TEST_F(ValidateComposites,CompositeExtractNotObject)657 TEST_F(ValidateComposites, CompositeExtractNotObject) {
658 const std::string body = R"(
659 %val1 = OpCompositeExtract %f32 %f32vec4 1
660 )";
661
662 CompileSuccessfully(GenerateShaderCode(body));
663 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
664 EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '11[%v4float]' cannot "
665 "be a type"));
666 }
667
TEST_F(ValidateComposites,CompositeExtractNotComposite)668 TEST_F(ValidateComposites, CompositeExtractNotComposite) {
669 const std::string body = R"(
670 %val1 = OpCompositeExtract %f32 %f32_1 0
671 )";
672
673 CompileSuccessfully(GenerateShaderCode(body));
674 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
675 EXPECT_THAT(getDiagnosticString(),
676 HasSubstr("Reached non-composite type while indexes still remain "
677 "to be traversed."));
678 }
679
TEST_F(ValidateComposites,CompositeExtractVectorOutOfBounds)680 TEST_F(ValidateComposites, CompositeExtractVectorOutOfBounds) {
681 const std::string body = R"(
682 %val1 = OpCompositeExtract %f32 %f32vec4_0123 4
683 )";
684
685 CompileSuccessfully(GenerateShaderCode(body));
686 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
687 EXPECT_THAT(getDiagnosticString(),
688 HasSubstr("Vector access is out of bounds, "
689 "vector size is 4, but access index is 4"));
690 }
691
TEST_F(ValidateComposites,CompositeExtractMatrixOutOfCols)692 TEST_F(ValidateComposites, CompositeExtractMatrixOutOfCols) {
693 const std::string body = R"(
694 %val1 = OpCompositeExtract %f32 %f32mat23_121212 3 1
695 )";
696
697 CompileSuccessfully(GenerateShaderCode(body));
698 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
699 EXPECT_THAT(getDiagnosticString(),
700 HasSubstr("Matrix access is out of bounds, "
701 "matrix has 3 columns, but access index is 3"));
702 }
703
TEST_F(ValidateComposites,CompositeExtractMatrixOutOfRows)704 TEST_F(ValidateComposites, CompositeExtractMatrixOutOfRows) {
705 const std::string body = R"(
706 %val1 = OpCompositeExtract %f32 %f32mat23_121212 2 5
707 )";
708
709 CompileSuccessfully(GenerateShaderCode(body));
710 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
711 EXPECT_THAT(getDiagnosticString(),
712 HasSubstr("Vector access is out of bounds, "
713 "vector size is 2, but access index is 5"));
714 }
715
TEST_F(ValidateComposites,CompositeExtractArrayOutOfBounds)716 TEST_F(ValidateComposites, CompositeExtractArrayOutOfBounds) {
717 const std::string body = R"(
718 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
719 %val1 = OpCompositeExtract %f32vec2 %array 3
720 )";
721
722 CompileSuccessfully(GenerateShaderCode(body));
723 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
724 EXPECT_THAT(getDiagnosticString(),
725 HasSubstr("Array access is out of bounds, "
726 "array size is 3, but access index is 3"));
727 }
728
TEST_F(ValidateComposites,CompositeExtractStructOutOfBounds)729 TEST_F(ValidateComposites, CompositeExtractStructOutOfBounds) {
730 const std::string body = R"(
731 %struct = OpLoad %big_struct %var_big_struct
732 %val1 = OpCompositeExtract %f32 %struct 6
733 )";
734
735 CompileSuccessfully(GenerateShaderCode(body));
736 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
737 EXPECT_THAT(getDiagnosticString(),
738 HasSubstr("Index is out of bounds, can not find index 6 in the "
739 "structure <id> '37'. This structure has 6 members. "
740 "Largest valid index is 5."));
741 }
742
TEST_F(ValidateComposites,CompositeExtractNestedVectorOutOfBounds)743 TEST_F(ValidateComposites, CompositeExtractNestedVectorOutOfBounds) {
744 const std::string body = R"(
745 %struct = OpLoad %big_struct %var_big_struct
746 %val1 = OpCompositeExtract %f32 %struct 3 1 5
747 )";
748
749 CompileSuccessfully(GenerateShaderCode(body));
750 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
751 EXPECT_THAT(getDiagnosticString(),
752 HasSubstr("Vector access is out of bounds, "
753 "vector size is 2, but access index is 5"));
754 }
755
TEST_F(ValidateComposites,CompositeExtractTooManyIndices)756 TEST_F(ValidateComposites, CompositeExtractTooManyIndices) {
757 const std::string body = R"(
758 %struct = OpLoad %big_struct %var_big_struct
759 %val1 = OpCompositeExtract %f32 %struct 3 1 1 2
760 )";
761
762 CompileSuccessfully(GenerateShaderCode(body));
763 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
764 EXPECT_THAT(getDiagnosticString(),
765 HasSubstr("Reached non-composite type while "
766 "indexes still remain to be traversed."));
767 }
768
TEST_F(ValidateComposites,CompositeExtractNoIndices)769 TEST_F(ValidateComposites, CompositeExtractNoIndices) {
770 const std::string body = R"(
771 %struct = OpLoad %big_struct %var_big_struct
772 %val1 = OpCompositeExtract %big_struct %struct
773 )";
774
775 CompileSuccessfully(GenerateShaderCode(body));
776 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
777 EXPECT_THAT(getDiagnosticString(),
778 HasSubstr("Expected at least one index to OpCompositeExtract"));
779 }
780
TEST_F(ValidateComposites,CompositeExtractWrongType1)781 TEST_F(ValidateComposites, CompositeExtractWrongType1) {
782 const std::string body = R"(
783 %struct = OpLoad %big_struct %var_big_struct
784 %val1 = OpCompositeExtract %f32vec2 %struct 3 1 1
785 )";
786
787 CompileSuccessfully(GenerateShaderCode(body));
788 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
789 EXPECT_THAT(
790 getDiagnosticString(),
791 HasSubstr(
792 "Result type (OpTypeVector) does not match the type that results "
793 "from indexing into the composite (OpTypeFloat)."));
794 }
795
TEST_F(ValidateComposites,CompositeExtractWrongType2)796 TEST_F(ValidateComposites, CompositeExtractWrongType2) {
797 const std::string body = R"(
798 %struct = OpLoad %big_struct %var_big_struct
799 %val1 = OpCompositeExtract %f32 %struct 3 1
800 )";
801
802 CompileSuccessfully(GenerateShaderCode(body));
803 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
804 EXPECT_THAT(getDiagnosticString(),
805 HasSubstr("Result type (OpTypeFloat) does not match the type "
806 "that results from indexing into the composite "
807 "(OpTypeVector)."));
808 }
809
TEST_F(ValidateComposites,CompositeExtractWrongType3)810 TEST_F(ValidateComposites, CompositeExtractWrongType3) {
811 const std::string body = R"(
812 %struct = OpLoad %big_struct %var_big_struct
813 %val1 = OpCompositeExtract %f32 %struct 2 1
814 )";
815
816 CompileSuccessfully(GenerateShaderCode(body));
817 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
818 EXPECT_THAT(getDiagnosticString(),
819 HasSubstr("Result type (OpTypeFloat) does not match the type "
820 "that results from indexing into the composite "
821 "(OpTypeVector)."));
822 }
823
TEST_F(ValidateComposites,CompositeExtractWrongType4)824 TEST_F(ValidateComposites, CompositeExtractWrongType4) {
825 const std::string body = R"(
826 %struct = OpLoad %big_struct %var_big_struct
827 %val1 = OpCompositeExtract %f32 %struct 4 1
828 )";
829
830 CompileSuccessfully(GenerateShaderCode(body));
831 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
832 EXPECT_THAT(getDiagnosticString(),
833 HasSubstr("Result type (OpTypeFloat) does not match the type "
834 "that results from indexing into the composite "
835 "(OpTypeVector)."));
836 }
837
TEST_F(ValidateComposites,CompositeExtractWrongType5)838 TEST_F(ValidateComposites, CompositeExtractWrongType5) {
839 const std::string body = R"(
840 %struct = OpLoad %big_struct %var_big_struct
841 %val1 = OpCompositeExtract %f32 %struct 5 1
842 )";
843
844 CompileSuccessfully(GenerateShaderCode(body));
845 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
846 EXPECT_THAT(
847 getDiagnosticString(),
848 HasSubstr(
849 "Result type (OpTypeFloat) does not match the "
850 "type that results from indexing into the composite (OpTypeInt)."));
851 }
852
TEST_F(ValidateComposites,CompositeInsertSuccess)853 TEST_F(ValidateComposites, CompositeInsertSuccess) {
854 const std::string body = R"(
855 %val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 0
856 %val2 = OpCompositeInsert %u32vec4 %u32_1 %u32vec4_0123 0
857 %val3 = OpCompositeInsert %f32mat22 %f32_2 %f32mat22_1212 0 1
858 %val4 = OpCompositeInsert %f32mat22 %f32vec2_01 %f32mat22_1212 0
859 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
860 %val5 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 2
861 %val6 = OpCompositeInsert %f32vec2arr3 %f32_3 %array 2 1
862 %struct = OpLoad %big_struct %var_big_struct
863 %val7 = OpCompositeInsert %big_struct %f32_3 %struct 0
864 %val8 = OpCompositeInsert %big_struct %f32vec4_0123 %struct 1
865 %val9 = OpCompositeInsert %big_struct %f32_3 %struct 1 2
866 %val10 = OpCompositeInsert %big_struct %f32mat23_121212 %struct 2
867 %val11 = OpCompositeInsert %big_struct %f32vec2_01 %struct 2 2
868 %val12 = OpCompositeInsert %big_struct %f32_3 %struct 2 2 1
869 %val13 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 2
870 %val14 = OpCompositeInsert %big_struct %f32_3 %struct 3 2 1
871 %val15 = OpCompositeInsert %big_struct %f32vec2_01 %struct 4 1
872 %val16 = OpCompositeInsert %big_struct %f32_3 %struct 4 0 1
873 %val17 = OpCompositeInsert %big_struct %f32_3 %struct 5 0
874 %val18 = OpCompositeInsert %big_struct %u32_3 %struct 5 1
875 )";
876
877 CompileSuccessfully(GenerateShaderCode(body));
878 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
879 }
880
TEST_F(ValidateComposites,CompositeInsertResultTypeDifferentFromComposite)881 TEST_F(ValidateComposites, CompositeInsertResultTypeDifferentFromComposite) {
882 const std::string body = R"(
883 %val1 = OpCompositeInsert %f32 %f32_1 %f32vec4_0123 0
884 )";
885
886 CompileSuccessfully(GenerateShaderCode(body));
887 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
888 EXPECT_THAT(getDiagnosticString(),
889 HasSubstr("The Result Type must be the same as Composite type in "
890 "OpCompositeInsert yielding Result Id 5."));
891 }
892
TEST_F(ValidateComposites,CompositeInsertNotComposite)893 TEST_F(ValidateComposites, CompositeInsertNotComposite) {
894 const std::string body = R"(
895 %val1 = OpCompositeInsert %f32 %f32_1 %f32_0 0
896 )";
897
898 CompileSuccessfully(GenerateShaderCode(body));
899 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
900 EXPECT_THAT(getDiagnosticString(),
901 HasSubstr("Reached non-composite type while indexes still remain "
902 "to be traversed."));
903 }
904
TEST_F(ValidateComposites,CompositeInsertVectorOutOfBounds)905 TEST_F(ValidateComposites, CompositeInsertVectorOutOfBounds) {
906 const std::string body = R"(
907 %val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 4
908 )";
909
910 CompileSuccessfully(GenerateShaderCode(body));
911 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
912 EXPECT_THAT(getDiagnosticString(),
913 HasSubstr("Vector access is out of bounds, "
914 "vector size is 4, but access index is 4"));
915 }
916
TEST_F(ValidateComposites,CompositeInsertMatrixOutOfCols)917 TEST_F(ValidateComposites, CompositeInsertMatrixOutOfCols) {
918 const std::string body = R"(
919 %val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 3 1
920 )";
921
922 CompileSuccessfully(GenerateShaderCode(body));
923 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
924 EXPECT_THAT(getDiagnosticString(),
925 HasSubstr("Matrix access is out of bounds, "
926 "matrix has 3 columns, but access index is 3"));
927 }
928
TEST_F(ValidateComposites,CompositeInsertMatrixOutOfRows)929 TEST_F(ValidateComposites, CompositeInsertMatrixOutOfRows) {
930 const std::string body = R"(
931 %val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 2 5
932 )";
933
934 CompileSuccessfully(GenerateShaderCode(body));
935 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
936 EXPECT_THAT(getDiagnosticString(),
937 HasSubstr("Vector access is out of bounds, "
938 "vector size is 2, but access index is 5"));
939 }
940
TEST_F(ValidateComposites,CompositeInsertArrayOutOfBounds)941 TEST_F(ValidateComposites, CompositeInsertArrayOutOfBounds) {
942 const std::string body = R"(
943 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
944 %val1 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 3
945 )";
946
947 CompileSuccessfully(GenerateShaderCode(body));
948 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
949 EXPECT_THAT(getDiagnosticString(),
950 HasSubstr("Array access is out of bounds, array "
951 "size is 3, but access index is 3"));
952 }
953
TEST_F(ValidateComposites,CompositeInsertStructOutOfBounds)954 TEST_F(ValidateComposites, CompositeInsertStructOutOfBounds) {
955 const std::string body = R"(
956 %struct = OpLoad %big_struct %var_big_struct
957 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 6
958 )";
959
960 CompileSuccessfully(GenerateShaderCode(body));
961 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
962 EXPECT_THAT(getDiagnosticString(),
963 HasSubstr("Index is out of bounds, can not find index 6 in the "
964 "structure <id> '37'. This structure has 6 members. "
965 "Largest valid index is 5."));
966 }
967
TEST_F(ValidateComposites,CompositeInsertNestedVectorOutOfBounds)968 TEST_F(ValidateComposites, CompositeInsertNestedVectorOutOfBounds) {
969 const std::string body = R"(
970 %struct = OpLoad %big_struct %var_big_struct
971 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 5
972 )";
973
974 CompileSuccessfully(GenerateShaderCode(body));
975 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
976 EXPECT_THAT(getDiagnosticString(),
977 HasSubstr("Vector access is out of bounds, "
978 "vector size is 2, but access index is 5"));
979 }
980
TEST_F(ValidateComposites,CompositeInsertTooManyIndices)981 TEST_F(ValidateComposites, CompositeInsertTooManyIndices) {
982 const std::string body = R"(
983 %struct = OpLoad %big_struct %var_big_struct
984 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 1 2
985 )";
986
987 CompileSuccessfully(GenerateShaderCode(body));
988 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
989 EXPECT_THAT(getDiagnosticString(),
990 HasSubstr("Reached non-composite type while indexes still remain "
991 "to be traversed."));
992 }
993
TEST_F(ValidateComposites,CompositeInsertWrongType1)994 TEST_F(ValidateComposites, CompositeInsertWrongType1) {
995 const std::string body = R"(
996 %struct = OpLoad %big_struct %var_big_struct
997 %val1 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 1 1
998 )";
999
1000 CompileSuccessfully(GenerateShaderCode(body));
1001 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1002 EXPECT_THAT(getDiagnosticString(),
1003 HasSubstr("The Object type (OpTypeVector) does not match the "
1004 "type that results from indexing into the Composite "
1005 "(OpTypeFloat)."));
1006 }
1007
TEST_F(ValidateComposites,CompositeInsertWrongType2)1008 TEST_F(ValidateComposites, CompositeInsertWrongType2) {
1009 const std::string body = R"(
1010 %struct = OpLoad %big_struct %var_big_struct
1011 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1
1012 )";
1013
1014 CompileSuccessfully(GenerateShaderCode(body));
1015 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1016 EXPECT_THAT(getDiagnosticString(),
1017 HasSubstr("The Object type (OpTypeFloat) does not match the type "
1018 "that results from indexing into the Composite "
1019 "(OpTypeVector)."));
1020 }
1021
TEST_F(ValidateComposites,CompositeInsertWrongType3)1022 TEST_F(ValidateComposites, CompositeInsertWrongType3) {
1023 const std::string body = R"(
1024 %struct = OpLoad %big_struct %var_big_struct
1025 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 2 1
1026 )";
1027
1028 CompileSuccessfully(GenerateShaderCode(body));
1029 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1030 EXPECT_THAT(getDiagnosticString(),
1031 HasSubstr("The Object type (OpTypeFloat) does not match the type "
1032 "that results from indexing into the Composite "
1033 "(OpTypeVector)."));
1034 }
1035
TEST_F(ValidateComposites,CompositeInsertWrongType4)1036 TEST_F(ValidateComposites, CompositeInsertWrongType4) {
1037 const std::string body = R"(
1038 %struct = OpLoad %big_struct %var_big_struct
1039 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 4 1
1040 )";
1041
1042 CompileSuccessfully(GenerateShaderCode(body));
1043 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1044 EXPECT_THAT(getDiagnosticString(),
1045 HasSubstr("The Object type (OpTypeFloat) does not match the type "
1046 "that results from indexing into the Composite "
1047 "(OpTypeVector)."));
1048 }
1049
TEST_F(ValidateComposites,CompositeInsertWrongType5)1050 TEST_F(ValidateComposites, CompositeInsertWrongType5) {
1051 const std::string body = R"(
1052 %struct = OpLoad %big_struct %var_big_struct
1053 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 5 1
1054 )";
1055
1056 CompileSuccessfully(GenerateShaderCode(body));
1057 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1058 EXPECT_THAT(getDiagnosticString(),
1059 HasSubstr("The Object type (OpTypeFloat) does not match the type "
1060 "that results from indexing into the Composite "
1061 "(OpTypeInt)."));
1062 }
1063
1064 // Tests ported from val_id_test.cpp.
1065
1066 // Valid. Tests both CompositeExtract and CompositeInsert with 255 indexes.
TEST_F(ValidateComposites,CompositeExtractInsertLimitsGood)1067 TEST_F(ValidateComposites, CompositeExtractInsertLimitsGood) {
1068 int depth = 255;
1069 std::string header = GetHeaderForTestsFromValId();
1070 header.erase(header.find("%func"));
1071 std::ostringstream spirv;
1072 spirv << header << std::endl;
1073
1074 // Build nested structures. Struct 'i' contains struct 'i-1'
1075 spirv << "%s_depth_1 = OpTypeStruct %float\n";
1076 for (int i = 2; i <= depth; ++i) {
1077 spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n";
1078 }
1079
1080 // Define Pointer and Variable to use for CompositeExtract/Insert.
1081 spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_"
1082 << depth << "\n";
1083 spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n";
1084
1085 // Function Start
1086 spirv << R"(
1087 %func = OpFunction %void None %void_f
1088 %my_label = OpLabel
1089 )";
1090
1091 // OpCompositeExtract/Insert with 'n' indexes (n = depth)
1092 spirv << "%deep = OpLoad %s_depth_" << depth << " %deep_var" << std::endl;
1093 spirv << "%entry = OpCompositeExtract %float %deep";
1094 for (int i = 0; i < depth; ++i) {
1095 spirv << " 0";
1096 }
1097 spirv << std::endl;
1098 spirv << "%new_composite = OpCompositeInsert %s_depth_" << depth
1099 << " %entry %deep";
1100 for (int i = 0; i < depth; ++i) {
1101 spirv << " 0";
1102 }
1103 spirv << std::endl;
1104
1105 // Function end
1106 spirv << R"(
1107 OpReturn
1108 OpFunctionEnd
1109 )";
1110 CompileSuccessfully(spirv.str());
1111 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1112 }
1113
1114 // Invalid: 256 indexes passed to OpCompositeExtract. Limit is 255.
TEST_F(ValidateComposites,CompositeExtractArgCountExceededLimitBad)1115 TEST_F(ValidateComposites, CompositeExtractArgCountExceededLimitBad) {
1116 std::ostringstream spirv;
1117 spirv << GetHeaderForTestsFromValId() << std::endl;
1118 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1119 spirv << "%entry = OpCompositeExtract %float %matrix";
1120 for (int i = 0; i < 256; ++i) {
1121 spirv << " 0";
1122 }
1123 spirv << R"(
1124 OpReturn
1125 OpFunctionEnd
1126 )";
1127 CompileSuccessfully(spirv.str());
1128 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1129 EXPECT_THAT(getDiagnosticString(),
1130 HasSubstr("The number of indexes in OpCompositeExtract may not "
1131 "exceed 255. Found 256 indexes."));
1132 }
1133
1134 // Invalid: 256 indexes passed to OpCompositeInsert. Limit is 255.
TEST_F(ValidateComposites,CompositeInsertArgCountExceededLimitBad)1135 TEST_F(ValidateComposites, CompositeInsertArgCountExceededLimitBad) {
1136 std::ostringstream spirv;
1137 spirv << GetHeaderForTestsFromValId() << std::endl;
1138 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1139 spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix";
1140 for (int i = 0; i < 256; ++i) {
1141 spirv << " 0";
1142 }
1143 spirv << R"(
1144 OpReturn
1145 OpFunctionEnd
1146 )";
1147 CompileSuccessfully(spirv.str());
1148 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1149 EXPECT_THAT(getDiagnosticString(),
1150 HasSubstr("The number of indexes in OpCompositeInsert may not "
1151 "exceed 255. Found 256 indexes."));
1152 }
1153
1154 // Invalid: In OpCompositeInsert, result type must be the same as composite type
TEST_F(ValidateComposites,CompositeInsertWrongResultTypeBad)1155 TEST_F(ValidateComposites, CompositeInsertWrongResultTypeBad) {
1156 std::ostringstream spirv;
1157 spirv << GetHeaderForTestsFromValId() << std::endl;
1158 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1159 spirv << "%float_entry = OpCompositeExtract %float %matrix 0 1" << std::endl;
1160 spirv << "%new_composite = OpCompositeInsert %float %float_entry %matrix 0 1"
1161 << std::endl;
1162 spirv << R"(OpReturn
1163 OpFunctionEnd)";
1164 CompileSuccessfully(spirv.str());
1165 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1166 EXPECT_THAT(getDiagnosticString(),
1167 HasSubstr("The Result Type must be the same as Composite type"));
1168 }
1169
1170 // Invalid: No Indexes were passed to OpCompositeExtract.
TEST_F(ValidateComposites,CompositeExtractNoIndices2)1171 TEST_F(ValidateComposites, CompositeExtractNoIndices2) {
1172 std::ostringstream spirv;
1173 spirv << GetHeaderForTestsFromValId() << std::endl;
1174 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1175 spirv << "%float_entry = OpCompositeExtract %mat4x3 %matrix" << std::endl;
1176 spirv << R"(OpReturn
1177 OpFunctionEnd)";
1178 CompileSuccessfully(spirv.str());
1179 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1180 EXPECT_THAT(
1181 getDiagnosticString(),
1182 HasSubstr(
1183 "Expected at least one index to OpCompositeExtract, zero found"));
1184 }
1185
1186 // Invalid: No Indexes were passed to OpCompositeExtract.
TEST_F(ValidateComposites,CompositeExtractNoIndicesWrongResultType)1187 TEST_F(ValidateComposites, CompositeExtractNoIndicesWrongResultType) {
1188 std::ostringstream spirv;
1189 spirv << GetHeaderForTestsFromValId() << std::endl;
1190 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1191 spirv << "%float_entry = OpCompositeExtract %float %matrix" << std::endl;
1192 spirv << R"(OpReturn
1193 OpFunctionEnd)";
1194 CompileSuccessfully(spirv.str());
1195 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1196 EXPECT_THAT(
1197 getDiagnosticString(),
1198 HasSubstr(
1199 "Expected at least one index to OpCompositeExtract, zero found"));
1200 }
1201
1202 // Invalid: No Indices were passed to OpCompositeInsert, and the type of the
1203 // Object<id> argument matches the Composite type.
TEST_F(ValidateComposites,CompositeInsertMissingIndices)1204 TEST_F(ValidateComposites, CompositeInsertMissingIndices) {
1205 std::ostringstream spirv;
1206 spirv << GetHeaderForTestsFromValId() << std::endl;
1207 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1208 spirv << "%matrix_2 = OpLoad %mat4x3 %my_matrix" << std::endl;
1209 spirv << "%new_composite = OpCompositeInsert %mat4x3 %matrix_2 %matrix";
1210 spirv << R"(
1211 OpReturn
1212 OpFunctionEnd)";
1213 CompileSuccessfully(spirv.str());
1214 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1215 EXPECT_THAT(
1216 getDiagnosticString(),
1217 HasSubstr(
1218 "Expected at least one index to OpCompositeInsert, zero found"));
1219 }
1220
1221 // Invalid: No Indices were passed to OpCompositeInsert, but the type of the
1222 // Object<id> argument does not match the Composite type.
TEST_F(ValidateComposites,CompositeInsertMissingIndices2)1223 TEST_F(ValidateComposites, CompositeInsertMissingIndices2) {
1224 std::ostringstream spirv;
1225 spirv << GetHeaderForTestsFromValId() << std::endl;
1226 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1227 spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix";
1228 spirv << R"(
1229 OpReturn
1230 OpFunctionEnd)";
1231 CompileSuccessfully(spirv.str());
1232 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1233 EXPECT_THAT(
1234 getDiagnosticString(),
1235 HasSubstr(
1236 "Expected at least one index to OpCompositeInsert, zero found"));
1237 }
1238
1239 // Valid: Tests that we can index into Struct, Array, Matrix, and Vector!
TEST_F(ValidateComposites,CompositeExtractInsertIndexIntoAllTypesGood)1240 TEST_F(ValidateComposites, CompositeExtractInsertIndexIntoAllTypesGood) {
1241 // indexes that we are passing are: 0, 3, 1, 2, 0
1242 // 0 will select the struct_s within the base struct (blockName)
1243 // 3 will select the Array that contains 5 matrices
1244 // 1 will select the Matrix that is at index 1 of the array
1245 // 2 will select the column (which is a vector) within the matrix at index 2
1246 // 0 will select the element at the index 0 of the vector. (which is a float).
1247 std::ostringstream spirv;
1248 spirv << GetHeaderForTestsFromValId() << R"(
1249 %myblock = OpLoad %struct_blockName %blockName_var
1250 %ss = OpCompositeExtract %struct_s %myblock 0
1251 %sa = OpCompositeExtract %array5_mat4x3 %myblock 0 3
1252 %sm = OpCompositeExtract %mat4x3 %myblock 0 3 1
1253 %sc = OpCompositeExtract %v3float %myblock 0 3 1 2
1254 %fl = OpCompositeExtract %float %myblock 0 3 1 2 0
1255 ;
1256 ; Now let's insert back at different levels...
1257 ;
1258 %b1 = OpCompositeInsert %struct_blockName %ss %myblock 0
1259 %b2 = OpCompositeInsert %struct_blockName %sa %myblock 0 3
1260 %b3 = OpCompositeInsert %struct_blockName %sm %myblock 0 3 1
1261 %b4 = OpCompositeInsert %struct_blockName %sc %myblock 0 3 1 2
1262 %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0
1263 OpReturn
1264 OpFunctionEnd
1265 )";
1266
1267 CompileSuccessfully(spirv.str());
1268 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1269 }
1270
1271 // Invalid. More indexes are provided than needed for OpCompositeExtract.
TEST_F(ValidateComposites,CompositeExtractReachedScalarBad)1272 TEST_F(ValidateComposites, CompositeExtractReachedScalarBad) {
1273 // indexes that we are passing are: 0, 3, 1, 2, 0
1274 // 0 will select the struct_s within the base struct (blockName)
1275 // 3 will select the Array that contains 5 matrices
1276 // 1 will select the Matrix that is at index 1 of the array
1277 // 2 will select the column (which is a vector) within the matrix at index 2
1278 // 0 will select the element at the index 0 of the vector. (which is a float).
1279 std::ostringstream spirv;
1280 spirv << GetHeaderForTestsFromValId() << R"(
1281 %myblock = OpLoad %struct_blockName %blockName_var
1282 %fl = OpCompositeExtract %float %myblock 0 3 1 2 0 1
1283 OpReturn
1284 OpFunctionEnd
1285 )";
1286
1287 CompileSuccessfully(spirv.str());
1288 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1289 EXPECT_THAT(getDiagnosticString(),
1290 HasSubstr("Reached non-composite type while indexes still remain "
1291 "to be traversed."));
1292 }
1293
1294 // Invalid. More indexes are provided than needed for OpCompositeInsert.
TEST_F(ValidateComposites,CompositeInsertReachedScalarBad)1295 TEST_F(ValidateComposites, CompositeInsertReachedScalarBad) {
1296 // indexes that we are passing are: 0, 3, 1, 2, 0
1297 // 0 will select the struct_s within the base struct (blockName)
1298 // 3 will select the Array that contains 5 matrices
1299 // 1 will select the Matrix that is at index 1 of the array
1300 // 2 will select the column (which is a vector) within the matrix at index 2
1301 // 0 will select the element at the index 0 of the vector. (which is a float).
1302 std::ostringstream spirv;
1303 spirv << GetHeaderForTestsFromValId() << R"(
1304 %myblock = OpLoad %struct_blockName %blockName_var
1305 %fl = OpCompositeExtract %float %myblock 0 3 1 2 0
1306 %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0 1
1307 OpReturn
1308 OpFunctionEnd
1309 )";
1310
1311 CompileSuccessfully(spirv.str());
1312 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1313 EXPECT_THAT(getDiagnosticString(),
1314 HasSubstr("Reached non-composite type while indexes still remain "
1315 "to be traversed."));
1316 }
1317
1318 // Invalid. Result type doesn't match the type we get from indexing into
1319 // the composite.
TEST_F(ValidateComposites,CompositeExtractResultTypeDoesntMatchIndexedTypeBad)1320 TEST_F(ValidateComposites,
1321 CompositeExtractResultTypeDoesntMatchIndexedTypeBad) {
1322 // indexes that we are passing are: 0, 3, 1, 2, 0
1323 // 0 will select the struct_s within the base struct (blockName)
1324 // 3 will select the Array that contains 5 matrices
1325 // 1 will select the Matrix that is at index 1 of the array
1326 // 2 will select the column (which is a vector) within the matrix at index 2
1327 // 0 will select the element at the index 0 of the vector. (which is a float).
1328 std::ostringstream spirv;
1329 spirv << GetHeaderForTestsFromValId() << R"(
1330 %myblock = OpLoad %struct_blockName %blockName_var
1331 %fl = OpCompositeExtract %int %myblock 0 3 1 2 0
1332 OpReturn
1333 OpFunctionEnd
1334 )";
1335
1336 CompileSuccessfully(spirv.str());
1337 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1338 EXPECT_THAT(getDiagnosticString(),
1339 HasSubstr("Result type (OpTypeInt) does not match the type that "
1340 "results from indexing into the composite "
1341 "(OpTypeFloat)."));
1342 }
1343
1344 // Invalid. Given object type doesn't match the type we get from indexing into
1345 // the composite.
TEST_F(ValidateComposites,CompositeInsertObjectTypeDoesntMatchIndexedTypeBad)1346 TEST_F(ValidateComposites, CompositeInsertObjectTypeDoesntMatchIndexedTypeBad) {
1347 // indexes that we are passing are: 0, 3, 1, 2, 0
1348 // 0 will select the struct_s within the base struct (blockName)
1349 // 3 will select the Array that contains 5 matrices
1350 // 1 will select the Matrix that is at index 1 of the array
1351 // 2 will select the column (which is a vector) within the matrix at index 2
1352 // 0 will select the element at the index 0 of the vector. (which is a float).
1353 // We are trying to insert an integer where we should be inserting a float.
1354 std::ostringstream spirv;
1355 spirv << GetHeaderForTestsFromValId() << R"(
1356 %myblock = OpLoad %struct_blockName %blockName_var
1357 %b5 = OpCompositeInsert %struct_blockName %int_0 %myblock 0 3 1 2 0
1358 OpReturn
1359 OpFunctionEnd
1360 )";
1361
1362 CompileSuccessfully(spirv.str());
1363 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1364 EXPECT_THAT(getDiagnosticString(),
1365 HasSubstr("The Object type (OpTypeInt) does not match the type "
1366 "that results from indexing into the Composite "
1367 "(OpTypeFloat)."));
1368 }
1369
1370 // Invalid. Index into a struct is larger than the number of struct members.
TEST_F(ValidateComposites,CompositeExtractStructIndexOutOfBoundBad)1371 TEST_F(ValidateComposites, CompositeExtractStructIndexOutOfBoundBad) {
1372 // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3.
1373 std::ostringstream spirv;
1374 spirv << GetHeaderForTestsFromValId() << R"(
1375 %myblock = OpLoad %struct_blockName %blockName_var
1376 %ss = OpCompositeExtract %struct_s %myblock 3
1377 OpReturn
1378 OpFunctionEnd
1379 )";
1380
1381 CompileSuccessfully(spirv.str());
1382 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1383 EXPECT_THAT(getDiagnosticString(),
1384 HasSubstr("Index is out of bounds, can not find index 3 in the "
1385 "structure <id> '25'. This structure has 2 members. "
1386 "Largest valid index is 1."));
1387 }
1388
1389 // Invalid. Index into a struct is larger than the number of struct members.
TEST_F(ValidateComposites,CompositeInsertStructIndexOutOfBoundBad)1390 TEST_F(ValidateComposites, CompositeInsertStructIndexOutOfBoundBad) {
1391 // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3.
1392 std::ostringstream spirv;
1393 spirv << GetHeaderForTestsFromValId() << R"(
1394 %myblock = OpLoad %struct_blockName %blockName_var
1395 %ss = OpCompositeExtract %struct_s %myblock 0
1396 %new_composite = OpCompositeInsert %struct_blockName %ss %myblock 3
1397 OpReturn
1398 OpFunctionEnd
1399 )";
1400
1401 CompileSuccessfully(spirv.str());
1402 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1403 EXPECT_THAT(
1404 getDiagnosticString(),
1405 HasSubstr("Index is out of bounds, can not find index 3 in the structure "
1406 "<id> '25'. This structure has 2 members. Largest valid index "
1407 "is 1."));
1408 }
1409
1410 // #1403: Ensure that the default spec constant value is not used to check the
1411 // extract index.
TEST_F(ValidateComposites,ExtractFromSpecConstantSizedArray)1412 TEST_F(ValidateComposites, ExtractFromSpecConstantSizedArray) {
1413 std::string spirv = R"(
1414 OpCapability Kernel
1415 OpCapability Linkage
1416 OpMemoryModel Logical OpenCL
1417 OpDecorate %spec_const SpecId 1
1418 %void = OpTypeVoid
1419 %uint = OpTypeInt 32 0
1420 %spec_const = OpSpecConstant %uint 3
1421 %uint_array = OpTypeArray %uint %spec_const
1422 %undef = OpUndef %uint_array
1423 %voidf = OpTypeFunction %void
1424 %func = OpFunction %void None %voidf
1425 %1 = OpLabel
1426 %2 = OpCompositeExtract %uint %undef 4
1427 OpReturn
1428 OpFunctionEnd
1429 )";
1430
1431 CompileSuccessfully(spirv);
1432 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1433 }
1434
1435 // #1403: Ensure that spec constant ops do not produce false positives.
TEST_F(ValidateComposites,ExtractFromSpecConstantOpSizedArray)1436 TEST_F(ValidateComposites, ExtractFromSpecConstantOpSizedArray) {
1437 std::string spirv = R"(
1438 OpCapability Kernel
1439 OpCapability Linkage
1440 OpMemoryModel Logical OpenCL
1441 OpDecorate %spec_const SpecId 1
1442 %void = OpTypeVoid
1443 %uint = OpTypeInt 32 0
1444 %const = OpConstant %uint 1
1445 %spec_const = OpSpecConstant %uint 3
1446 %spec_const_op = OpSpecConstantOp %uint IAdd %spec_const %const
1447 %uint_array = OpTypeArray %uint %spec_const_op
1448 %undef = OpUndef %uint_array
1449 %voidf = OpTypeFunction %void
1450 %func = OpFunction %void None %voidf
1451 %1 = OpLabel
1452 %2 = OpCompositeExtract %uint %undef 4
1453 OpReturn
1454 OpFunctionEnd
1455 )";
1456
1457 CompileSuccessfully(spirv);
1458 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1459 }
1460
1461 // #1403: Ensure that the default spec constant value is not used to check the
1462 // size of the array for a composite construct. This code has limited actual
1463 // value as it is incorrect unless the specialization constant is assigned the
1464 // value of 2, but it is still a valid module.
TEST_F(ValidateComposites,CompositeConstructSpecConstantSizedArray)1465 TEST_F(ValidateComposites, CompositeConstructSpecConstantSizedArray) {
1466 std::string spirv = R"(
1467 OpCapability Kernel
1468 OpCapability Linkage
1469 OpMemoryModel Logical OpenCL
1470 OpDecorate %spec_const SpecId 1
1471 %void = OpTypeVoid
1472 %uint = OpTypeInt 32 0
1473 %uint_0 = OpConstant %uint 0
1474 %spec_const = OpSpecConstant %uint 3
1475 %uint_array = OpTypeArray %uint %spec_const
1476 %voidf = OpTypeFunction %void
1477 %func = OpFunction %void None %voidf
1478 %1 = OpLabel
1479 %2 = OpCompositeConstruct %uint_array %uint_0 %uint_0
1480 OpReturn
1481 OpFunctionEnd
1482 )";
1483
1484 CompileSuccessfully(spirv);
1485 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1486 }
1487
TEST_F(ValidateComposites,CoopMatConstantCompositeMismatchFail)1488 TEST_F(ValidateComposites, CoopMatConstantCompositeMismatchFail) {
1489 const std::string body = R"(
1490 OpCapability Shader
1491 OpCapability Float16
1492 OpCapability CooperativeMatrixNV
1493 OpExtension "SPV_NV_cooperative_matrix"
1494 OpMemoryModel Logical GLSL450
1495 OpEntryPoint GLCompute %main "main"
1496 %void = OpTypeVoid
1497 %func = OpTypeFunction %void
1498 %bool = OpTypeBool
1499 %f16 = OpTypeFloat 16
1500 %f32 = OpTypeFloat 32
1501 %u32 = OpTypeInt 32 0
1502
1503 %u32_8 = OpConstant %u32 8
1504 %subgroup = OpConstant %u32 3
1505
1506 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1507
1508 %f32_1 = OpConstant %f32 1
1509
1510 %f16mat_1 = OpConstantComposite %f16mat %f32_1
1511
1512 %main = OpFunction %void None %func
1513 %main_entry = OpLabel
1514
1515 OpReturn
1516 OpFunctionEnd)";
1517
1518 CompileSuccessfully(body.c_str());
1519 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1520 EXPECT_THAT(
1521 getDiagnosticString(),
1522 HasSubstr("OpConstantComposite Constituent <id> '11[%float_1]' type does "
1523 "not match the Result Type <id> '10[%10]'s component type."));
1524 }
1525
TEST_F(ValidateComposites,CoopMatCompositeConstructMismatchFail)1526 TEST_F(ValidateComposites, CoopMatCompositeConstructMismatchFail) {
1527 const std::string body = R"(
1528 OpCapability Shader
1529 OpCapability Float16
1530 OpCapability CooperativeMatrixNV
1531 OpExtension "SPV_NV_cooperative_matrix"
1532 OpMemoryModel Logical GLSL450
1533 OpEntryPoint GLCompute %main "main"
1534 %void = OpTypeVoid
1535 %func = OpTypeFunction %void
1536 %bool = OpTypeBool
1537 %f16 = OpTypeFloat 16
1538 %f32 = OpTypeFloat 32
1539 %u32 = OpTypeInt 32 0
1540
1541 %u32_8 = OpConstant %u32 8
1542 %subgroup = OpConstant %u32 3
1543
1544 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1545
1546 %f32_1 = OpConstant %f32 1
1547
1548 %main = OpFunction %void None %func
1549 %main_entry = OpLabel
1550
1551 %f16mat_1 = OpCompositeConstruct %f16mat %f32_1
1552
1553 OpReturn
1554 OpFunctionEnd)";
1555
1556 CompileSuccessfully(body.c_str());
1557 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1558 EXPECT_THAT(
1559 getDiagnosticString(),
1560 HasSubstr("Expected Constituent type to be equal to the component type"));
1561 }
1562
TEST_F(ValidateComposites,CoopMatKHRConstantCompositeMismatchFail)1563 TEST_F(ValidateComposites, CoopMatKHRConstantCompositeMismatchFail) {
1564 const std::string body = R"(
1565 OpCapability Shader
1566 OpCapability Float16
1567 OpCapability CooperativeMatrixKHR
1568 OpExtension "SPV_KHR_cooperative_matrix"
1569 OpExtension "SPV_KHR_vulkan_memory_model"
1570 OpMemoryModel Logical GLSL450
1571 OpEntryPoint GLCompute %main "main"
1572 %void = OpTypeVoid
1573 %func = OpTypeFunction %void
1574 %bool = OpTypeBool
1575 %f16 = OpTypeFloat 16
1576 %f32 = OpTypeFloat 32
1577 %u32 = OpTypeInt 32 0
1578
1579 %u32_16 = OpConstant %u32 16
1580 %useA = OpConstant %u32 0
1581 %subgroup = OpConstant %u32 3
1582
1583 %f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_16 %u32_16 %useA
1584
1585 %f32_1 = OpConstant %f32 1
1586
1587 %f16mat_1 = OpConstantComposite %f16mat %f32_1
1588
1589 %main = OpFunction %void None %func
1590 %main_entry = OpLabel
1591
1592 OpReturn
1593 OpFunctionEnd)";
1594
1595 CompileSuccessfully(body.c_str());
1596 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1597 EXPECT_THAT(
1598 getDiagnosticString(),
1599 HasSubstr(
1600 "OpConstantComposite Constituent <id> '12[%float_1]' type "
1601 "does not match the Result Type <id> '11[%11]'s component type."));
1602 }
1603
TEST_F(ValidateComposites,CoopMatKHRCompositeConstructMismatchFail)1604 TEST_F(ValidateComposites, CoopMatKHRCompositeConstructMismatchFail) {
1605 const std::string body = R"(
1606 OpCapability Shader
1607 OpCapability Float16
1608 OpCapability CooperativeMatrixKHR
1609 OpExtension "SPV_KHR_cooperative_matrix"
1610 OpExtension "SPV_KHR_vulkan_memory_model"
1611 OpMemoryModel Logical GLSL450
1612 OpEntryPoint GLCompute %main "main"
1613 %void = OpTypeVoid
1614 %func = OpTypeFunction %void
1615 %bool = OpTypeBool
1616 %f16 = OpTypeFloat 16
1617 %f32 = OpTypeFloat 32
1618 %u32 = OpTypeInt 32 0
1619
1620 %u32_16 = OpConstant %u32 16
1621 %useA = OpConstant %u32 0
1622 %subgroup = OpConstant %u32 3
1623
1624 %f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_16 %u32_16 %useA
1625
1626 %f32_1 = OpConstant %f32 1
1627
1628 %main = OpFunction %void None %func
1629 %main_entry = OpLabel
1630
1631 %f16mat_1 = OpCompositeConstruct %f16mat %f32_1
1632
1633 OpReturn
1634 OpFunctionEnd)";
1635
1636 CompileSuccessfully(body.c_str());
1637 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1638 EXPECT_THAT(
1639 getDiagnosticString(),
1640 HasSubstr("Expected Constituent type to be equal to the component type"));
1641 }
1642
TEST_F(ValidateComposites,ExtractDynamicLabelIndex)1643 TEST_F(ValidateComposites, ExtractDynamicLabelIndex) {
1644 const std::string spirv = R"(
1645 OpCapability Shader
1646 OpCapability Linkage
1647 OpMemoryModel Logical GLSL450
1648 %void = OpTypeVoid
1649 %float = OpTypeFloat 32
1650 %v4float = OpTypeVector %float 4
1651 %void_fn = OpTypeFunction %void
1652 %float_0 = OpConstant %float 0
1653 %v4float_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1654 %func = OpFunction %void None %void_fn
1655 %1 = OpLabel
1656 %ex = OpVectorExtractDynamic %float %v4float_0 %v4float_0
1657 OpReturn
1658 OpFunctionEnd
1659 )";
1660
1661 CompileSuccessfully(spirv);
1662 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1663 EXPECT_THAT(getDiagnosticString(),
1664 HasSubstr("Expected Index to be int scalar"));
1665 }
1666
TEST_F(ValidateComposites,CopyLogicalSameType)1667 TEST_F(ValidateComposites, CopyLogicalSameType) {
1668 const std::string spirv = R"(
1669 OpCapability Shader
1670 OpCapability Linkage
1671 OpMemoryModel Logical GLSL450
1672 %void = OpTypeVoid
1673 %struct = OpTypeStruct
1674 %const_struct = OpConstantComposite %struct
1675 %void_fn = OpTypeFunction %void
1676 %func = OpFunction %void None %void_fn
1677 %1 = OpLabel
1678 %copy = OpCopyLogical %struct %const_struct
1679 OpReturn
1680 OpFunctionEnd
1681 )";
1682
1683 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1684 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1685 EXPECT_THAT(getDiagnosticString(),
1686 HasSubstr("Result Type must not equal the Operand type"));
1687 }
1688
TEST_F(ValidateComposites,CopyLogicalSameStructDifferentId)1689 TEST_F(ValidateComposites, CopyLogicalSameStructDifferentId) {
1690 const std::string spirv = R"(
1691 OpCapability Shader
1692 OpCapability Linkage
1693 OpMemoryModel Logical GLSL450
1694 %void = OpTypeVoid
1695 %struct1 = OpTypeStruct
1696 %struct2 = OpTypeStruct
1697 %const_struct = OpConstantComposite %struct1
1698 %void_fn = OpTypeFunction %void
1699 %func = OpFunction %void None %void_fn
1700 %1 = OpLabel
1701 %copy = OpCopyLogical %struct2 %const_struct
1702 OpReturn
1703 OpFunctionEnd
1704 )";
1705
1706 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1707 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1708 }
1709
TEST_F(ValidateComposites,CopyLogicalArrayDifferentLength)1710 TEST_F(ValidateComposites, CopyLogicalArrayDifferentLength) {
1711 const std::string spirv = R"(
1712 OpCapability Shader
1713 OpCapability Linkage
1714 OpMemoryModel Logical GLSL450
1715 %void = OpTypeVoid
1716 %int = OpTypeInt 32 0
1717 %int_4 = OpConstant %int 4
1718 %int_5 = OpConstant %int 5
1719 %array1 = OpTypeArray %int %int_4
1720 %array2 = OpTypeArray %int %int_5
1721 %const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4
1722 %void_fn = OpTypeFunction %void
1723 %func = OpFunction %void None %void_fn
1724 %1 = OpLabel
1725 %copy = OpCopyLogical %array2 %const_array
1726 OpReturn
1727 OpFunctionEnd
1728 )";
1729
1730 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1731 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1732 EXPECT_THAT(
1733 getDiagnosticString(),
1734 HasSubstr("Result Type does not logically match the Operand type"));
1735 }
1736
TEST_F(ValidateComposites,CopyLogicalArrayDifferentElement)1737 TEST_F(ValidateComposites, CopyLogicalArrayDifferentElement) {
1738 const std::string spirv = R"(
1739 OpCapability Shader
1740 OpCapability Linkage
1741 OpMemoryModel Logical GLSL450
1742 %void = OpTypeVoid
1743 %float = OpTypeFloat 32
1744 %int = OpTypeInt 32 0
1745 %int_4 = OpConstant %int 4
1746 %array1 = OpTypeArray %int %int_4
1747 %array2 = OpTypeArray %float %int_4
1748 %const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4
1749 %void_fn = OpTypeFunction %void
1750 %func = OpFunction %void None %void_fn
1751 %1 = OpLabel
1752 %copy = OpCopyLogical %array2 %const_array
1753 OpReturn
1754 OpFunctionEnd
1755 )";
1756
1757 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1758 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1759 EXPECT_THAT(
1760 getDiagnosticString(),
1761 HasSubstr("Result Type does not logically match the Operand type"));
1762 }
1763
TEST_F(ValidateComposites,CopyLogicalArrayLogicallyMatchedElement)1764 TEST_F(ValidateComposites, CopyLogicalArrayLogicallyMatchedElement) {
1765 const std::string spirv = R"(
1766 OpCapability Shader
1767 OpCapability Linkage
1768 OpMemoryModel Logical GLSL450
1769 %void = OpTypeVoid
1770 %float = OpTypeFloat 32
1771 %int = OpTypeInt 32 0
1772 %int_1 = OpConstant %int 1
1773 %inner1 = OpTypeArray %int %int_1
1774 %inner2 = OpTypeArray %int %int_1
1775 %array1 = OpTypeArray %inner1 %int_1
1776 %array2 = OpTypeArray %inner2 %int_1
1777 %const_inner = OpConstantComposite %inner1 %int_1
1778 %const_array = OpConstantComposite %array1 %const_inner
1779 %void_fn = OpTypeFunction %void
1780 %func = OpFunction %void None %void_fn
1781 %1 = OpLabel
1782 %copy = OpCopyLogical %array2 %const_array
1783 OpReturn
1784 OpFunctionEnd
1785 )";
1786
1787 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1788 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1789 }
1790
TEST_F(ValidateComposites,CopyLogicalStructDifferentNumberElements)1791 TEST_F(ValidateComposites, CopyLogicalStructDifferentNumberElements) {
1792 const std::string spirv = R"(
1793 OpCapability Shader
1794 OpCapability Linkage
1795 OpMemoryModel Logical GLSL450
1796 %void = OpTypeVoid
1797 %int = OpTypeInt 32 0
1798 %struct1 = OpTypeStruct
1799 %struct2 = OpTypeStruct %int
1800 %const_struct = OpConstantComposite %struct1
1801 %void_fn = OpTypeFunction %void
1802 %func = OpFunction %void None %void_fn
1803 %1 = OpLabel
1804 %copy = OpCopyLogical %struct2 %const_struct
1805 OpReturn
1806 OpFunctionEnd
1807 )";
1808
1809 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1810 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1811 EXPECT_THAT(
1812 getDiagnosticString(),
1813 HasSubstr("Result Type does not logically match the Operand type"));
1814 }
1815
TEST_F(ValidateComposites,CopyLogicalStructDifferentElement)1816 TEST_F(ValidateComposites, CopyLogicalStructDifferentElement) {
1817 const std::string spirv = R"(
1818 OpCapability Shader
1819 OpCapability Linkage
1820 OpMemoryModel Logical GLSL450
1821 %void = OpTypeVoid
1822 %uint = OpTypeInt 32 0
1823 %int = OpTypeInt 32 1
1824 %int_0 = OpConstant %int 0
1825 %uint_0 = OpConstant %uint 0
1826 %struct1 = OpTypeStruct %int %uint
1827 %struct2 = OpTypeStruct %int %int
1828 %const_struct = OpConstantComposite %struct1 %int_0 %uint_0
1829 %void_fn = OpTypeFunction %void
1830 %func = OpFunction %void None %void_fn
1831 %1 = OpLabel
1832 %copy = OpCopyLogical %struct2 %const_struct
1833 OpReturn
1834 OpFunctionEnd
1835 )";
1836
1837 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1838 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1839 EXPECT_THAT(
1840 getDiagnosticString(),
1841 HasSubstr("Result Type does not logically match the Operand type"));
1842 }
1843
TEST_F(ValidateComposites,CopyLogicalStructLogicallyMatch)1844 TEST_F(ValidateComposites, CopyLogicalStructLogicallyMatch) {
1845 const std::string spirv = R"(
1846 OpCapability Shader
1847 OpCapability Linkage
1848 OpMemoryModel Logical GLSL450
1849 %void = OpTypeVoid
1850 %int = OpTypeInt 32 0
1851 %int_1 = OpConstant %int 1
1852 %array1 = OpTypeArray %int %int_1
1853 %array2 = OpTypeArray %int %int_1
1854 %struct1 = OpTypeStruct %int %array1
1855 %struct2 = OpTypeStruct %int %array2
1856 %const_array = OpConstantComposite %array1 %int_1
1857 %const_struct = OpConstantComposite %struct1 %int_1 %const_array
1858 %void_fn = OpTypeFunction %void
1859 %func = OpFunction %void None %void_fn
1860 %1 = OpLabel
1861 %copy = OpCopyLogical %struct2 %const_struct
1862 OpReturn
1863 OpFunctionEnd
1864 )";
1865
1866 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1867 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1868 }
1869
1870 using ValidateSmallComposites = spvtest::ValidateBase<std::string>;
1871
GetSmallCompositesCodeGenerator()1872 CodeGenerator GetSmallCompositesCodeGenerator() {
1873 CodeGenerator generator;
1874 generator.capabilities_ = R"(
1875 OpCapability Shader
1876 OpCapability Linkage
1877 OpCapability UniformAndStorageBuffer16BitAccess
1878 OpCapability UniformAndStorageBuffer8BitAccess
1879 )";
1880 generator.extensions_ = R"(
1881 OpExtension "SPV_KHR_16bit_storage"
1882 OpExtension "SPV_KHR_8bit_storage"
1883 )";
1884 generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
1885 generator.before_types_ = R"(
1886 OpDecorate %char_block Block
1887 OpMemberDecorate %char_block 0 Offset 0
1888 OpDecorate %short_block Block
1889 OpMemberDecorate %short_block 0 Offset 0
1890 OpDecorate %half_block Block
1891 OpMemberDecorate %half_block 0 Offset 0
1892 )";
1893 generator.types_ = R"(
1894 %void = OpTypeVoid
1895 %int = OpTypeInt 32 0
1896 %int_0 = OpConstant %int 0
1897 %int_1 = OpConstant %int 1
1898 %char = OpTypeInt 8 0
1899 %char2 = OpTypeVector %char 2
1900 %short = OpTypeInt 16 0
1901 %short2 = OpTypeVector %short 2
1902 %half = OpTypeFloat 16
1903 %half2 = OpTypeVector %half 2
1904 %char_block = OpTypeStruct %char2
1905 %short_block = OpTypeStruct %short2
1906 %half_block = OpTypeStruct %half2
1907 %ptr_ssbo_char_block = OpTypePointer StorageBuffer %char_block
1908 %ptr_ssbo_char2 = OpTypePointer StorageBuffer %char2
1909 %ptr_ssbo_char = OpTypePointer StorageBuffer %char
1910 %ptr_ssbo_short_block = OpTypePointer StorageBuffer %short_block
1911 %ptr_ssbo_short2 = OpTypePointer StorageBuffer %short2
1912 %ptr_ssbo_short = OpTypePointer StorageBuffer %short
1913 %ptr_ssbo_half_block = OpTypePointer StorageBuffer %half_block
1914 %ptr_ssbo_half2 = OpTypePointer StorageBuffer %half2
1915 %ptr_ssbo_half = OpTypePointer StorageBuffer %half
1916 %void_fn = OpTypeFunction %void
1917 %char_var = OpVariable %ptr_ssbo_char_block StorageBuffer
1918 %short_var = OpVariable %ptr_ssbo_short_block StorageBuffer
1919 %half_var = OpVariable %ptr_ssbo_half_block StorageBuffer
1920 )";
1921 generator.after_types_ = R"(
1922 %func = OpFunction %void None %void_fn
1923 %entry = OpLabel
1924 %char2_gep = OpAccessChain %ptr_ssbo_char2 %char_var %int_0
1925 %ld_char2 = OpLoad %char2 %char2_gep
1926 %char_gep = OpAccessChain %ptr_ssbo_char %char_var %int_0 %int_0
1927 %ld_char = OpLoad %char %char_gep
1928 %short2_gep = OpAccessChain %ptr_ssbo_short2 %short_var %int_0
1929 %ld_short2 = OpLoad %short2 %short2_gep
1930 %short_gep = OpAccessChain %ptr_ssbo_short %short_var %int_0 %int_0
1931 %ld_short = OpLoad %short %short_gep
1932 %half2_gep = OpAccessChain %ptr_ssbo_half2 %half_var %int_0
1933 %ld_half2 = OpLoad %half2 %half2_gep
1934 %half_gep = OpAccessChain %ptr_ssbo_half %half_var %int_0 %int_0
1935 %ld_half = OpLoad %half %half_gep
1936 )";
1937 generator.add_at_the_end_ = R"(
1938 OpReturn
1939 OpFunctionEnd
1940 )";
1941 return generator;
1942 }
1943
TEST_P(ValidateSmallComposites,VectorExtractDynamic)1944 TEST_P(ValidateSmallComposites, VectorExtractDynamic) {
1945 std::string type = GetParam();
1946 CodeGenerator generator = GetSmallCompositesCodeGenerator();
1947 std::string inst =
1948 "%inst = OpVectorExtractDynamic %" + type + " %ld_" + type + "2 %int_0\n";
1949 generator.after_types_ += inst;
1950 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1951 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1952 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1953 EXPECT_THAT(getDiagnosticString(),
1954 HasSubstr("Cannot extract from a vector of 8- or 16-bit types"));
1955 }
1956
TEST_P(ValidateSmallComposites,VectorInsertDynamic)1957 TEST_P(ValidateSmallComposites, VectorInsertDynamic) {
1958 std::string type = GetParam();
1959 CodeGenerator generator = GetSmallCompositesCodeGenerator();
1960 std::string inst = "%inst = OpVectorInsertDynamic %" + type + "2 %ld_" +
1961 type + "2 %ld_" + type + " %int_0\n";
1962 generator.after_types_ += inst;
1963 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1964 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1965 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1966 EXPECT_THAT(getDiagnosticString(),
1967 HasSubstr("Cannot insert into a vector of 8- or 16-bit types"));
1968 }
1969
TEST_P(ValidateSmallComposites,VectorShuffle)1970 TEST_P(ValidateSmallComposites, VectorShuffle) {
1971 std::string type = GetParam();
1972 CodeGenerator generator = GetSmallCompositesCodeGenerator();
1973 std::string inst = "%inst = OpVectorShuffle %" + type + "2 %ld_" + type +
1974 "2 %ld_" + type + "2 0 0\n";
1975 generator.after_types_ += inst;
1976 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1977 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1978 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1979 EXPECT_THAT(getDiagnosticString(),
1980 HasSubstr("Cannot shuffle a vector of 8- or 16-bit types"));
1981 }
1982
TEST_P(ValidateSmallComposites,CompositeConstruct)1983 TEST_P(ValidateSmallComposites, CompositeConstruct) {
1984 std::string type = GetParam();
1985 CodeGenerator generator = GetSmallCompositesCodeGenerator();
1986 std::string inst = "%inst = OpCompositeConstruct %" + type + "2 %ld_" + type +
1987 " %ld_" + type + "\n";
1988 generator.after_types_ += inst;
1989 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1990 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1991 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1992 EXPECT_THAT(
1993 getDiagnosticString(),
1994 HasSubstr("Cannot create a composite containing 8- or 16-bit types"));
1995 }
1996
TEST_P(ValidateSmallComposites,CompositeExtract)1997 TEST_P(ValidateSmallComposites, CompositeExtract) {
1998 std::string type = GetParam();
1999 CodeGenerator generator = GetSmallCompositesCodeGenerator();
2000 std::string inst =
2001 "%inst = OpCompositeExtract %" + type + " %ld_" + type + "2 0\n";
2002 generator.after_types_ += inst;
2003 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
2004 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2005 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2006 EXPECT_THAT(
2007 getDiagnosticString(),
2008 HasSubstr("Cannot extract from a composite of 8- or 16-bit types"));
2009 }
2010
TEST_P(ValidateSmallComposites,CompositeInsert)2011 TEST_P(ValidateSmallComposites, CompositeInsert) {
2012 std::string type = GetParam();
2013 CodeGenerator generator = GetSmallCompositesCodeGenerator();
2014 std::string inst = "%inst = OpCompositeInsert %" + type + "2 %ld_" + type +
2015 " %ld_" + type + "2 0\n";
2016 generator.after_types_ += inst;
2017 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
2018 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2019 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2020 EXPECT_THAT(
2021 getDiagnosticString(),
2022 HasSubstr("Cannot insert into a composite of 8- or 16-bit types"));
2023 }
2024
TEST_P(ValidateSmallComposites,CopyObject)2025 TEST_P(ValidateSmallComposites, CopyObject) {
2026 std::string type = GetParam();
2027 CodeGenerator generator = GetSmallCompositesCodeGenerator();
2028 std::string inst = "%inst = OpCopyObject %" + type + "2 %ld_" + type + "2\n";
2029 generator.after_types_ += inst;
2030 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
2031 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2032 }
2033
2034 INSTANTIATE_TEST_SUITE_P(SmallCompositeInstructions, ValidateSmallComposites,
2035 Values("char", "short", "half"));
2036
TEST_F(ValidateComposites,HalfMatrixCannotTranspose)2037 TEST_F(ValidateComposites, HalfMatrixCannotTranspose) {
2038 const std::string spirv = R"(
2039 OpCapability Shader
2040 OpCapability Linkage
2041 OpCapability UniformAndStorageBuffer16BitAccess
2042 OpExtension "SPV_KHR_16bit_storage"
2043 OpMemoryModel Logical GLSL450
2044 OpDecorate %block Block
2045 OpMemberDecorate %block 0 Offset 0
2046 OpMemberDecorate %block 0 RowMajor
2047 OpMemberDecorate %block 0 MatrixStride 8
2048 %void = OpTypeVoid
2049 %int = OpTypeInt 32 0
2050 %int_0 = OpConstant %int 0
2051 %float = OpTypeFloat 16
2052 %float2 = OpTypeVector %float 2
2053 %mat2x2 = OpTypeMatrix %float2 2
2054 %block = OpTypeStruct %mat2x2
2055 %ptr_ssbo_block = OpTypePointer StorageBuffer %block
2056 %ptr_ssbo_mat2x2 = OpTypePointer StorageBuffer %mat2x2
2057 %var = OpVariable %ptr_ssbo_block StorageBuffer
2058 %void_fn = OpTypeFunction %void
2059 %func = OpFunction %void None %void_fn
2060 %entry = OpLabel
2061 %gep = OpAccessChain %ptr_ssbo_mat2x2 %var %int_0
2062 %ld = OpLoad %mat2x2 %gep
2063 %inst = OpTranspose %mat2x2 %ld
2064 OpReturn
2065 OpFunctionEnd
2066 )";
2067
2068 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
2069 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2070 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2071 EXPECT_THAT(getDiagnosticString(),
2072 HasSubstr("Cannot transpose matrices of 16-bit floats"));
2073 }
2074
TEST_F(ValidateComposites,CopyObjectVoid)2075 TEST_F(ValidateComposites, CopyObjectVoid) {
2076 const std::string spirv = R"(
2077 OpCapability Shader
2078 %1 = OpExtInstImport "GLSL.std.450"
2079 OpMemoryModel Logical GLSL450
2080 OpEntryPoint Fragment %4 "main"
2081 OpExecutionMode %4 OriginUpperLeft
2082 OpSource ESSL 320
2083 OpName %4 "main"
2084 OpName %6 "foo("
2085 %2 = OpTypeVoid
2086 %3 = OpTypeFunction %2
2087 %4 = OpFunction %2 None %3
2088 %5 = OpLabel
2089 %8 = OpFunctionCall %2 %6
2090 %20 = OpCopyObject %2 %8
2091 OpReturn
2092 OpFunctionEnd
2093 %6 = OpFunction %2 None %3
2094 %7 = OpLabel
2095 OpReturn
2096 OpFunctionEnd
2097 )";
2098
2099 CompileSuccessfully(spirv);
2100 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2101 EXPECT_THAT(getDiagnosticString(),
2102 HasSubstr("OpCopyObject cannot have void result type"));
2103 }
2104
2105 } // namespace
2106 } // namespace val
2107 } // namespace spvtools
2108