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 %f32vec2rarr = OpTypeRuntimeArray %f32vec2
90
91 %f32u32struct = OpTypeStruct %f32 %u32
92 %big_struct = OpTypeStruct %f32 %f32vec4 %f32mat23 %f32vec2arr3 %f32vec2rarr %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 ; RunTimeArray arr;
154 ; }
155
156 %f32arr = OpTypeRuntimeArray %float
157 %v4float = OpTypeVector %float 4
158 %array5_mat4x3 = OpTypeArray %mat4x3 %int_5
159 %array5_vec4 = OpTypeArray %v4float %int_5
160 %_ptr_Uniform_float = OpTypePointer Uniform %float
161 %_ptr_Function_vec4 = OpTypePointer Function %v4float
162 %_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float
163 %struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3
164 %struct_blockName = OpTypeStruct %struct_s %int %f32arr
165 %_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName
166 %_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s
167 %_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3
168 %_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3
169 %_ptr_Uniform_v3float = OpTypePointer Uniform %v3float
170 %blockName_var = OpVariable %_ptr_Uniform_blockName Uniform
171 %spec_int = OpSpecConstant %int 2
172 %func = OpFunction %void None %void_f
173 %my_label = OpLabel
174 )";
175 }
176
TEST_F(ValidateComposites,VectorExtractDynamicSuccess)177 TEST_F(ValidateComposites, VectorExtractDynamicSuccess) {
178 const std::string body = R"(
179 %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %u32_0
180 )";
181
182 CompileSuccessfully(GenerateShaderCode(body).c_str());
183 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
184 }
185
TEST_F(ValidateComposites,VectorExtractDynamicWrongResultType)186 TEST_F(ValidateComposites, VectorExtractDynamicWrongResultType) {
187 const std::string body = R"(
188 %val1 = OpVectorExtractDynamic %f32vec4 %f32vec4_0123 %u32_0
189 )";
190
191 CompileSuccessfully(GenerateShaderCode(body).c_str());
192 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
193 EXPECT_THAT(getDiagnosticString(),
194 HasSubstr("Expected Result Type to be a scalar type"));
195 }
196
TEST_F(ValidateComposites,VectorExtractDynamicNotVector)197 TEST_F(ValidateComposites, VectorExtractDynamicNotVector) {
198 const std::string body = R"(
199 %val1 = OpVectorExtractDynamic %f32 %f32mat22_1212 %u32_0
200 )";
201
202 CompileSuccessfully(GenerateShaderCode(body).c_str());
203 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
204 EXPECT_THAT(getDiagnosticString(),
205 HasSubstr("Expected Vector type to be OpTypeVector"));
206 }
207
TEST_F(ValidateComposites,VectorExtractDynamicWrongVectorComponent)208 TEST_F(ValidateComposites, VectorExtractDynamicWrongVectorComponent) {
209 const std::string body = R"(
210 %val1 = OpVectorExtractDynamic %f32 %u32vec4_0123 %u32_0
211 )";
212
213 CompileSuccessfully(GenerateShaderCode(body).c_str());
214 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
215 EXPECT_THAT(
216 getDiagnosticString(),
217 HasSubstr("Expected Vector component type to be equal to Result Type"));
218 }
219
TEST_F(ValidateComposites,VectorExtractDynamicWrongIndexType)220 TEST_F(ValidateComposites, VectorExtractDynamicWrongIndexType) {
221 const std::string body = R"(
222 %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %f32_0
223 )";
224
225 CompileSuccessfully(GenerateShaderCode(body).c_str());
226 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
227 EXPECT_THAT(getDiagnosticString(),
228 HasSubstr("Expected Index to be int scalar"));
229 }
230
TEST_F(ValidateComposites,VectorInsertDynamicSuccess)231 TEST_F(ValidateComposites, VectorInsertDynamicSuccess) {
232 const std::string body = R"(
233 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %u32_0
234 )";
235
236 CompileSuccessfully(GenerateShaderCode(body).c_str());
237 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
238 }
239
TEST_F(ValidateComposites,VectorInsertDynamicWrongResultType)240 TEST_F(ValidateComposites, VectorInsertDynamicWrongResultType) {
241 const std::string body = R"(
242 %val1 = OpVectorInsertDynamic %f32 %f32vec4_0123 %f32_1 %u32_0
243 )";
244
245 CompileSuccessfully(GenerateShaderCode(body).c_str());
246 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
247 EXPECT_THAT(getDiagnosticString(),
248 HasSubstr("Expected Result Type to be OpTypeVector"));
249 }
250
TEST_F(ValidateComposites,VectorInsertDynamicNotVector)251 TEST_F(ValidateComposites, VectorInsertDynamicNotVector) {
252 const std::string body = R"(
253 %val1 = OpVectorInsertDynamic %f32vec4 %f32mat22_1212 %f32_1 %u32_0
254 )";
255
256 CompileSuccessfully(GenerateShaderCode(body).c_str());
257 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
258 EXPECT_THAT(getDiagnosticString(),
259 HasSubstr("Expected Vector type to be equal to Result Type"));
260 }
261
TEST_F(ValidateComposites,VectorInsertDynamicWrongComponentType)262 TEST_F(ValidateComposites, VectorInsertDynamicWrongComponentType) {
263 const std::string body = R"(
264 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %u32_1 %u32_0
265 )";
266
267 CompileSuccessfully(GenerateShaderCode(body).c_str());
268 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
269 EXPECT_THAT(getDiagnosticString(),
270 HasSubstr("Expected Component type to be equal to Result Type "
271 "component type"));
272 }
273
TEST_F(ValidateComposites,VectorInsertDynamicWrongIndexType)274 TEST_F(ValidateComposites, VectorInsertDynamicWrongIndexType) {
275 const std::string body = R"(
276 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %f32_0
277 )";
278
279 CompileSuccessfully(GenerateShaderCode(body).c_str());
280 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
281 EXPECT_THAT(getDiagnosticString(),
282 HasSubstr("Expected Index to be int scalar"));
283 }
284
TEST_F(ValidateComposites,CompositeConstructNotComposite)285 TEST_F(ValidateComposites, CompositeConstructNotComposite) {
286 const std::string body = R"(
287 %val1 = OpCompositeConstruct %f32 %f32_1
288 )";
289
290 CompileSuccessfully(GenerateShaderCode(body).c_str());
291 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
292 EXPECT_THAT(getDiagnosticString(),
293 HasSubstr("Expected Result Type to be a composite type"));
294 }
295
TEST_F(ValidateComposites,CompositeConstructVectorSuccess)296 TEST_F(ValidateComposites, CompositeConstructVectorSuccess) {
297 const std::string body = R"(
298 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12
299 %val2 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0 %f32_0
300 %val3 = OpCompositeConstruct %f32vec4 %f32_0 %f32_0 %f32vec2_12
301 %val4 = OpCompositeConstruct %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
302 )";
303
304 CompileSuccessfully(GenerateShaderCode(body).c_str());
305 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
306 }
307
TEST_F(ValidateComposites,CompositeConstructVectorOnlyOneConstituent)308 TEST_F(ValidateComposites, CompositeConstructVectorOnlyOneConstituent) {
309 const std::string body = R"(
310 %val1 = OpCompositeConstruct %f32vec4 %f32vec4_0123
311 )";
312
313 CompileSuccessfully(GenerateShaderCode(body).c_str());
314 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
315 EXPECT_THAT(getDiagnosticString(),
316 HasSubstr("Expected number of constituents to be at least 2"));
317 }
318
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituent1)319 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent1) {
320 const std::string body = R"(
321 %val1 = OpCompositeConstruct %f32vec4 %f32 %f32vec2_12
322 )";
323
324 CompileSuccessfully(GenerateShaderCode(body).c_str());
325 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
326 EXPECT_THAT(getDiagnosticString(), 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 100
648 %val16 = OpCompositeExtract %f32 %struct 4 1000 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 100
872 %val16 = OpCompositeInsert %big_struct %f32_3 %struct 4 1000 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 3 members. "
1386 "Largest valid index is 2."));
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 3 members. Largest valid index "
1407 "is 2."));
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 =
1490 R"(
1491 OpCapability Shader
1492 OpCapability Float16
1493 OpCapability CooperativeMatrixNV
1494 OpExtension "SPV_NV_cooperative_matrix"
1495 OpMemoryModel Logical GLSL450
1496 OpEntryPoint GLCompute %main "main"
1497 %void = OpTypeVoid
1498 %func = OpTypeFunction %void
1499 %bool = OpTypeBool
1500 %f16 = OpTypeFloat 16
1501 %f32 = OpTypeFloat 32
1502 %u32 = OpTypeInt 32 0
1503
1504 %u32_8 = OpConstant %u32 8
1505 %subgroup = OpConstant %u32 3
1506
1507 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1508
1509 %f32_1 = OpConstant %f32 1
1510
1511 %f16mat_1 = OpConstantComposite %f16mat %f32_1
1512
1513 %main = OpFunction %void None %func
1514 %main_entry = OpLabel
1515
1516 OpReturn
1517 OpFunctionEnd)";
1518
1519 CompileSuccessfully(body.c_str());
1520 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1521 EXPECT_THAT(
1522 getDiagnosticString(),
1523 HasSubstr("OpConstantComposite Constituent <id> '11[%float_1]' type does "
1524 "not match the Result Type <id> '10[%10]'s component type."));
1525 }
1526
TEST_F(ValidateComposites,CoopMatCompositeConstructMismatchFail)1527 TEST_F(ValidateComposites, CoopMatCompositeConstructMismatchFail) {
1528 const std::string body =
1529 R"(
1530 OpCapability Shader
1531 OpCapability Float16
1532 OpCapability CooperativeMatrixNV
1533 OpExtension "SPV_NV_cooperative_matrix"
1534 OpMemoryModel Logical GLSL450
1535 OpEntryPoint GLCompute %main "main"
1536 %void = OpTypeVoid
1537 %func = OpTypeFunction %void
1538 %bool = OpTypeBool
1539 %f16 = OpTypeFloat 16
1540 %f32 = OpTypeFloat 32
1541 %u32 = OpTypeInt 32 0
1542
1543 %u32_8 = OpConstant %u32 8
1544 %subgroup = OpConstant %u32 3
1545
1546 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1547
1548 %f32_1 = OpConstant %f32 1
1549
1550 %main = OpFunction %void None %func
1551 %main_entry = OpLabel
1552
1553 %f16mat_1 = OpCompositeConstruct %f16mat %f32_1
1554
1555 OpReturn
1556 OpFunctionEnd)";
1557
1558 CompileSuccessfully(body.c_str());
1559 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1560 EXPECT_THAT(
1561 getDiagnosticString(),
1562 HasSubstr("Expected Constituent type to be equal to the component type"));
1563 }
1564
TEST_F(ValidateComposites,ExtractDynamicLabelIndex)1565 TEST_F(ValidateComposites, ExtractDynamicLabelIndex) {
1566 const std::string spirv = R"(
1567 OpCapability Shader
1568 OpCapability Linkage
1569 OpMemoryModel Logical GLSL450
1570 %void = OpTypeVoid
1571 %float = OpTypeFloat 32
1572 %v4float = OpTypeVector %float 4
1573 %void_fn = OpTypeFunction %void
1574 %float_0 = OpConstant %float 0
1575 %v4float_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1576 %func = OpFunction %void None %void_fn
1577 %1 = OpLabel
1578 %ex = OpVectorExtractDynamic %float %v4float_0 %v4float_0
1579 OpReturn
1580 OpFunctionEnd
1581 )";
1582
1583 CompileSuccessfully(spirv);
1584 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1585 EXPECT_THAT(getDiagnosticString(),
1586 HasSubstr("Expected Index to be int scalar"));
1587 }
1588
TEST_F(ValidateComposites,CopyLogicalSameType)1589 TEST_F(ValidateComposites, CopyLogicalSameType) {
1590 const std::string spirv = R"(
1591 OpCapability Shader
1592 OpCapability Linkage
1593 OpMemoryModel Logical GLSL450
1594 %void = OpTypeVoid
1595 %struct = OpTypeStruct
1596 %const_struct = OpConstantComposite %struct
1597 %void_fn = OpTypeFunction %void
1598 %func = OpFunction %void None %void_fn
1599 %1 = OpLabel
1600 %copy = OpCopyLogical %struct %const_struct
1601 OpReturn
1602 OpFunctionEnd
1603 )";
1604
1605 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1606 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1607 EXPECT_THAT(getDiagnosticString(),
1608 HasSubstr("Result Type must not equal the Operand type"));
1609 }
1610
TEST_F(ValidateComposites,CopyLogicalSameStructDifferentId)1611 TEST_F(ValidateComposites, CopyLogicalSameStructDifferentId) {
1612 const std::string spirv = R"(
1613 OpCapability Shader
1614 OpCapability Linkage
1615 OpMemoryModel Logical GLSL450
1616 %void = OpTypeVoid
1617 %struct1 = OpTypeStruct
1618 %struct2 = OpTypeStruct
1619 %const_struct = OpConstantComposite %struct1
1620 %void_fn = OpTypeFunction %void
1621 %func = OpFunction %void None %void_fn
1622 %1 = OpLabel
1623 %copy = OpCopyLogical %struct2 %const_struct
1624 OpReturn
1625 OpFunctionEnd
1626 )";
1627
1628 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1629 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1630 }
1631
TEST_F(ValidateComposites,CopyLogicalArrayDifferentLength)1632 TEST_F(ValidateComposites, CopyLogicalArrayDifferentLength) {
1633 const std::string spirv = R"(
1634 OpCapability Shader
1635 OpCapability Linkage
1636 OpMemoryModel Logical GLSL450
1637 %void = OpTypeVoid
1638 %int = OpTypeInt 32 0
1639 %int_4 = OpConstant %int 4
1640 %int_5 = OpConstant %int 5
1641 %array1 = OpTypeArray %int %int_4
1642 %array2 = OpTypeArray %int %int_5
1643 %const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4
1644 %void_fn = OpTypeFunction %void
1645 %func = OpFunction %void None %void_fn
1646 %1 = OpLabel
1647 %copy = OpCopyLogical %array2 %const_array
1648 OpReturn
1649 OpFunctionEnd
1650 )";
1651
1652 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1653 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1654 EXPECT_THAT(
1655 getDiagnosticString(),
1656 HasSubstr("Result Type does not logically match the Operand type"));
1657 }
1658
TEST_F(ValidateComposites,CopyLogicalArrayDifferentElement)1659 TEST_F(ValidateComposites, CopyLogicalArrayDifferentElement) {
1660 const std::string spirv = R"(
1661 OpCapability Shader
1662 OpCapability Linkage
1663 OpMemoryModel Logical GLSL450
1664 %void = OpTypeVoid
1665 %float = OpTypeFloat 32
1666 %int = OpTypeInt 32 0
1667 %int_4 = OpConstant %int 4
1668 %array1 = OpTypeArray %int %int_4
1669 %array2 = OpTypeArray %float %int_4
1670 %const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4
1671 %void_fn = OpTypeFunction %void
1672 %func = OpFunction %void None %void_fn
1673 %1 = OpLabel
1674 %copy = OpCopyLogical %array2 %const_array
1675 OpReturn
1676 OpFunctionEnd
1677 )";
1678
1679 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1680 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1681 EXPECT_THAT(
1682 getDiagnosticString(),
1683 HasSubstr("Result Type does not logically match the Operand type"));
1684 }
1685
TEST_F(ValidateComposites,CopyLogicalArrayLogicallyMatchedElement)1686 TEST_F(ValidateComposites, CopyLogicalArrayLogicallyMatchedElement) {
1687 const std::string spirv = R"(
1688 OpCapability Shader
1689 OpCapability Linkage
1690 OpMemoryModel Logical GLSL450
1691 %void = OpTypeVoid
1692 %float = OpTypeFloat 32
1693 %int = OpTypeInt 32 0
1694 %int_1 = OpConstant %int 1
1695 %inner1 = OpTypeArray %int %int_1
1696 %inner2 = OpTypeArray %int %int_1
1697 %array1 = OpTypeArray %inner1 %int_1
1698 %array2 = OpTypeArray %inner2 %int_1
1699 %const_inner = OpConstantComposite %inner1 %int_1
1700 %const_array = OpConstantComposite %array1 %const_inner
1701 %void_fn = OpTypeFunction %void
1702 %func = OpFunction %void None %void_fn
1703 %1 = OpLabel
1704 %copy = OpCopyLogical %array2 %const_array
1705 OpReturn
1706 OpFunctionEnd
1707 )";
1708
1709 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1710 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1711 }
1712
TEST_F(ValidateComposites,CopyLogicalStructDifferentNumberElements)1713 TEST_F(ValidateComposites, CopyLogicalStructDifferentNumberElements) {
1714 const std::string spirv = R"(
1715 OpCapability Shader
1716 OpCapability Linkage
1717 OpMemoryModel Logical GLSL450
1718 %void = OpTypeVoid
1719 %int = OpTypeInt 32 0
1720 %struct1 = OpTypeStruct
1721 %struct2 = OpTypeStruct %int
1722 %const_struct = OpConstantComposite %struct1
1723 %void_fn = OpTypeFunction %void
1724 %func = OpFunction %void None %void_fn
1725 %1 = OpLabel
1726 %copy = OpCopyLogical %struct2 %const_struct
1727 OpReturn
1728 OpFunctionEnd
1729 )";
1730
1731 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1732 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1733 EXPECT_THAT(
1734 getDiagnosticString(),
1735 HasSubstr("Result Type does not logically match the Operand type"));
1736 }
1737
TEST_F(ValidateComposites,CopyLogicalStructDifferentElement)1738 TEST_F(ValidateComposites, CopyLogicalStructDifferentElement) {
1739 const std::string spirv = R"(
1740 OpCapability Shader
1741 OpCapability Linkage
1742 OpMemoryModel Logical GLSL450
1743 %void = OpTypeVoid
1744 %uint = OpTypeInt 32 0
1745 %int = OpTypeInt 32 1
1746 %int_0 = OpConstant %int 0
1747 %uint_0 = OpConstant %uint 0
1748 %struct1 = OpTypeStruct %int %uint
1749 %struct2 = OpTypeStruct %int %int
1750 %const_struct = OpConstantComposite %struct1 %int_0 %uint_0
1751 %void_fn = OpTypeFunction %void
1752 %func = OpFunction %void None %void_fn
1753 %1 = OpLabel
1754 %copy = OpCopyLogical %struct2 %const_struct
1755 OpReturn
1756 OpFunctionEnd
1757 )";
1758
1759 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1760 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1761 EXPECT_THAT(
1762 getDiagnosticString(),
1763 HasSubstr("Result Type does not logically match the Operand type"));
1764 }
1765
TEST_F(ValidateComposites,CopyLogicalStructLogicallyMatch)1766 TEST_F(ValidateComposites, CopyLogicalStructLogicallyMatch) {
1767 const std::string spirv = R"(
1768 OpCapability Shader
1769 OpCapability Linkage
1770 OpMemoryModel Logical GLSL450
1771 %void = OpTypeVoid
1772 %int = OpTypeInt 32 0
1773 %int_1 = OpConstant %int 1
1774 %array1 = OpTypeArray %int %int_1
1775 %array2 = OpTypeArray %int %int_1
1776 %struct1 = OpTypeStruct %int %array1
1777 %struct2 = OpTypeStruct %int %array2
1778 %const_array = OpConstantComposite %array1 %int_1
1779 %const_struct = OpConstantComposite %struct1 %int_1 %const_array
1780 %void_fn = OpTypeFunction %void
1781 %func = OpFunction %void None %void_fn
1782 %1 = OpLabel
1783 %copy = OpCopyLogical %struct2 %const_struct
1784 OpReturn
1785 OpFunctionEnd
1786 )";
1787
1788 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1789 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1790 }
1791
1792 using ValidateSmallComposites = spvtest::ValidateBase<std::string>;
1793
GetSmallCompositesCodeGenerator()1794 CodeGenerator GetSmallCompositesCodeGenerator() {
1795 CodeGenerator generator;
1796 generator.capabilities_ = R"(
1797 OpCapability Shader
1798 OpCapability Linkage
1799 OpCapability UniformAndStorageBuffer16BitAccess
1800 OpCapability UniformAndStorageBuffer8BitAccess
1801 )";
1802 generator.extensions_ = R"(
1803 OpExtension "SPV_KHR_16bit_storage"
1804 OpExtension "SPV_KHR_8bit_storage"
1805 )";
1806 generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
1807 generator.before_types_ = R"(
1808 OpDecorate %char_block Block
1809 OpMemberDecorate %char_block 0 Offset 0
1810 OpDecorate %short_block Block
1811 OpMemberDecorate %short_block 0 Offset 0
1812 OpDecorate %half_block Block
1813 OpMemberDecorate %half_block 0 Offset 0
1814 )";
1815 generator.types_ = R"(
1816 %void = OpTypeVoid
1817 %int = OpTypeInt 32 0
1818 %int_0 = OpConstant %int 0
1819 %int_1 = OpConstant %int 1
1820 %char = OpTypeInt 8 0
1821 %char2 = OpTypeVector %char 2
1822 %short = OpTypeInt 16 0
1823 %short2 = OpTypeVector %short 2
1824 %half = OpTypeFloat 16
1825 %half2 = OpTypeVector %half 2
1826 %char_block = OpTypeStruct %char2
1827 %short_block = OpTypeStruct %short2
1828 %half_block = OpTypeStruct %half2
1829 %ptr_ssbo_char_block = OpTypePointer StorageBuffer %char_block
1830 %ptr_ssbo_char2 = OpTypePointer StorageBuffer %char2
1831 %ptr_ssbo_char = OpTypePointer StorageBuffer %char
1832 %ptr_ssbo_short_block = OpTypePointer StorageBuffer %short_block
1833 %ptr_ssbo_short2 = OpTypePointer StorageBuffer %short2
1834 %ptr_ssbo_short = OpTypePointer StorageBuffer %short
1835 %ptr_ssbo_half_block = OpTypePointer StorageBuffer %half_block
1836 %ptr_ssbo_half2 = OpTypePointer StorageBuffer %half2
1837 %ptr_ssbo_half = OpTypePointer StorageBuffer %half
1838 %void_fn = OpTypeFunction %void
1839 %char_var = OpVariable %ptr_ssbo_char_block StorageBuffer
1840 %short_var = OpVariable %ptr_ssbo_short_block StorageBuffer
1841 %half_var = OpVariable %ptr_ssbo_half_block StorageBuffer
1842 )";
1843 generator.after_types_ = R"(
1844 %func = OpFunction %void None %void_fn
1845 %entry = OpLabel
1846 %char2_gep = OpAccessChain %ptr_ssbo_char2 %char_var %int_0
1847 %ld_char2 = OpLoad %char2 %char2_gep
1848 %char_gep = OpAccessChain %ptr_ssbo_char %char_var %int_0 %int_0
1849 %ld_char = OpLoad %char %char_gep
1850 %short2_gep = OpAccessChain %ptr_ssbo_short2 %short_var %int_0
1851 %ld_short2 = OpLoad %short2 %short2_gep
1852 %short_gep = OpAccessChain %ptr_ssbo_short %short_var %int_0 %int_0
1853 %ld_short = OpLoad %short %short_gep
1854 %half2_gep = OpAccessChain %ptr_ssbo_half2 %half_var %int_0
1855 %ld_half2 = OpLoad %half2 %half2_gep
1856 %half_gep = OpAccessChain %ptr_ssbo_half %half_var %int_0 %int_0
1857 %ld_half = OpLoad %half %half_gep
1858 )";
1859 generator.add_at_the_end_ = R"(
1860 OpReturn
1861 OpFunctionEnd
1862 )";
1863 return generator;
1864 }
1865
TEST_P(ValidateSmallComposites,VectorExtractDynamic)1866 TEST_P(ValidateSmallComposites, VectorExtractDynamic) {
1867 std::string type = GetParam();
1868 CodeGenerator generator = GetSmallCompositesCodeGenerator();
1869 std::string inst =
1870 "%inst = OpVectorExtractDynamic %" + type + " %ld_" + type + "2 %int_0\n";
1871 generator.after_types_ += inst;
1872 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1873 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1874 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1875 EXPECT_THAT(getDiagnosticString(),
1876 HasSubstr("Cannot extract from a vector of 8- or 16-bit types"));
1877 }
1878
TEST_P(ValidateSmallComposites,VectorInsertDynamic)1879 TEST_P(ValidateSmallComposites, VectorInsertDynamic) {
1880 std::string type = GetParam();
1881 CodeGenerator generator = GetSmallCompositesCodeGenerator();
1882 std::string inst = "%inst = OpVectorInsertDynamic %" + type + "2 %ld_" +
1883 type + "2 %ld_" + type + " %int_0\n";
1884 generator.after_types_ += inst;
1885 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1886 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1887 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1888 EXPECT_THAT(getDiagnosticString(),
1889 HasSubstr("Cannot insert into a vector of 8- or 16-bit types"));
1890 }
1891
TEST_P(ValidateSmallComposites,VectorShuffle)1892 TEST_P(ValidateSmallComposites, VectorShuffle) {
1893 std::string type = GetParam();
1894 CodeGenerator generator = GetSmallCompositesCodeGenerator();
1895 std::string inst = "%inst = OpVectorShuffle %" + type + "2 %ld_" + type +
1896 "2 %ld_" + type + "2 0 0\n";
1897 generator.after_types_ += inst;
1898 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1899 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1900 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1901 EXPECT_THAT(getDiagnosticString(),
1902 HasSubstr("Cannot shuffle a vector of 8- or 16-bit types"));
1903 }
1904
TEST_P(ValidateSmallComposites,CompositeConstruct)1905 TEST_P(ValidateSmallComposites, CompositeConstruct) {
1906 std::string type = GetParam();
1907 CodeGenerator generator = GetSmallCompositesCodeGenerator();
1908 std::string inst = "%inst = OpCompositeConstruct %" + type + "2 %ld_" + type +
1909 " %ld_" + type + "\n";
1910 generator.after_types_ += inst;
1911 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1912 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1913 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1914 EXPECT_THAT(
1915 getDiagnosticString(),
1916 HasSubstr("Cannot create a composite containing 8- or 16-bit types"));
1917 }
1918
TEST_P(ValidateSmallComposites,CompositeExtract)1919 TEST_P(ValidateSmallComposites, CompositeExtract) {
1920 std::string type = GetParam();
1921 CodeGenerator generator = GetSmallCompositesCodeGenerator();
1922 std::string inst =
1923 "%inst = OpCompositeExtract %" + type + " %ld_" + type + "2 0\n";
1924 generator.after_types_ += inst;
1925 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1926 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1927 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1928 EXPECT_THAT(
1929 getDiagnosticString(),
1930 HasSubstr("Cannot extract from a composite of 8- or 16-bit types"));
1931 }
1932
TEST_P(ValidateSmallComposites,CompositeInsert)1933 TEST_P(ValidateSmallComposites, CompositeInsert) {
1934 std::string type = GetParam();
1935 CodeGenerator generator = GetSmallCompositesCodeGenerator();
1936 std::string inst = "%inst = OpCompositeInsert %" + type + "2 %ld_" + type +
1937 " %ld_" + type + "2 0\n";
1938 generator.after_types_ += inst;
1939 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1940 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1941 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1942 EXPECT_THAT(
1943 getDiagnosticString(),
1944 HasSubstr("Cannot insert into a composite of 8- or 16-bit types"));
1945 }
1946
TEST_P(ValidateSmallComposites,CopyObject)1947 TEST_P(ValidateSmallComposites, CopyObject) {
1948 std::string type = GetParam();
1949 CodeGenerator generator = GetSmallCompositesCodeGenerator();
1950 std::string inst = "%inst = OpCopyObject %" + type + "2 %ld_" + type + "2\n";
1951 generator.after_types_ += inst;
1952 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1953 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1954 }
1955
1956 INSTANTIATE_TEST_SUITE_P(SmallCompositeInstructions, ValidateSmallComposites,
1957 Values("char", "short", "half"));
1958
TEST_F(ValidateComposites,HalfMatrixCannotTranspose)1959 TEST_F(ValidateComposites, HalfMatrixCannotTranspose) {
1960 const std::string spirv = R"(
1961 OpCapability Shader
1962 OpCapability Linkage
1963 OpCapability UniformAndStorageBuffer16BitAccess
1964 OpExtension "SPV_KHR_16bit_storage"
1965 OpMemoryModel Logical GLSL450
1966 OpDecorate %block Block
1967 OpMemberDecorate %block 0 Offset 0
1968 OpMemberDecorate %block 0 RowMajor
1969 OpMemberDecorate %block 0 MatrixStride 8
1970 %void = OpTypeVoid
1971 %int = OpTypeInt 32 0
1972 %int_0 = OpConstant %int 0
1973 %float = OpTypeFloat 16
1974 %float2 = OpTypeVector %float 2
1975 %mat2x2 = OpTypeMatrix %float2 2
1976 %block = OpTypeStruct %mat2x2
1977 %ptr_ssbo_block = OpTypePointer StorageBuffer %block
1978 %ptr_ssbo_mat2x2 = OpTypePointer StorageBuffer %mat2x2
1979 %var = OpVariable %ptr_ssbo_block StorageBuffer
1980 %void_fn = OpTypeFunction %void
1981 %func = OpFunction %void None %void_fn
1982 %entry = OpLabel
1983 %gep = OpAccessChain %ptr_ssbo_mat2x2 %var %int_0
1984 %ld = OpLoad %mat2x2 %gep
1985 %inst = OpTranspose %mat2x2 %ld
1986 OpReturn
1987 OpFunctionEnd
1988 )";
1989
1990 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1991 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1992 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1993 EXPECT_THAT(getDiagnosticString(),
1994 HasSubstr("Cannot transpose matrices of 16-bit floats"));
1995 }
1996
1997 } // namespace
1998 } // namespace val
1999 } // namespace spvtools
2000