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