1 // Copyright (c) 2019 Google LLC.
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 // Validation tests for misc instructions
16
17 #include <string>
18 #include <vector>
19
20 #include "gmock/gmock.h"
21 #include "test/unit_spirv.h"
22 #include "test/val/val_fixtures.h"
23
24 namespace spvtools {
25 namespace val {
26 namespace {
27
28 using ::testing::Eq;
29 using ::testing::HasSubstr;
30
31 using ValidateMisc = spvtest::ValidateBase<bool>;
32
TEST_F(ValidateMisc,UndefRestrictedShort)33 TEST_F(ValidateMisc, UndefRestrictedShort) {
34 const std::string spirv = R"(
35 OpCapability Shader
36 OpCapability Linkage
37 OpCapability StorageBuffer16BitAccess
38 OpExtension "SPV_KHR_16bit_storage"
39 OpMemoryModel Logical GLSL450
40 %short = OpTypeInt 16 0
41 %undef = OpUndef %short
42 )";
43
44 CompileSuccessfully(spirv);
45 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
46 EXPECT_THAT(
47 getDiagnosticString(),
48 HasSubstr("Cannot create undefined values with 8- or 16-bit types"));
49 }
50
TEST_F(ValidateMisc,UndefRestrictedChar)51 TEST_F(ValidateMisc, UndefRestrictedChar) {
52 const std::string spirv = R"(
53 OpCapability Shader
54 OpCapability Linkage
55 OpCapability StorageBuffer8BitAccess
56 OpExtension "SPV_KHR_8bit_storage"
57 OpMemoryModel Logical GLSL450
58 %char = OpTypeInt 8 0
59 %undef = OpUndef %char
60 )";
61
62 CompileSuccessfully(spirv);
63 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
64 EXPECT_THAT(
65 getDiagnosticString(),
66 HasSubstr("Cannot create undefined values with 8- or 16-bit types"));
67 }
68
TEST_F(ValidateMisc,UndefRestrictedHalf)69 TEST_F(ValidateMisc, UndefRestrictedHalf) {
70 const std::string spirv = R"(
71 OpCapability Shader
72 OpCapability Linkage
73 OpCapability StorageBuffer16BitAccess
74 OpExtension "SPV_KHR_16bit_storage"
75 OpMemoryModel Logical GLSL450
76 %half = OpTypeFloat 16
77 %undef = OpUndef %half
78 )";
79
80 CompileSuccessfully(spirv);
81 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
82 EXPECT_THAT(
83 getDiagnosticString(),
84 HasSubstr("Cannot create undefined values with 8- or 16-bit types"));
85 }
86
TEST_F(ValidateMisc,SizeOfValid)87 TEST_F(ValidateMisc, SizeOfValid) {
88 const std::string spirv = R"(
89 OpCapability Addresses
90 OpCapability Kernel
91 OpMemoryModel Physical64 OpenCL
92 OpEntryPoint Kernel %f "f"
93 %void = OpTypeVoid
94 %i32 = OpTypeInt 32 0
95 %ptr = OpTypePointer CrossWorkgroup %i32
96 %fnTy = OpTypeFunction %void
97 %f = OpFunction %void None %fnTy
98 %entry = OpLabel
99 %s = OpSizeOf %i32 %ptr
100 OpReturn
101 OpFunctionEnd
102 )";
103
104 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_1);
105 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
106 }
107
108 const std::string ShaderClockSpirv = R"(
109 OpCapability Shader
110 OpCapability Int64
111 OpCapability ShaderClockKHR
112 OpExtension "SPV_KHR_shader_clock"
113 %1 = OpExtInstImport "GLSL.std.450"
114 OpMemoryModel Logical GLSL450
115 OpEntryPoint Fragment %main "main"
116 OpExecutionMode %main OriginUpperLeft
117 OpSource GLSL 450
118 OpSourceExtension "GL_ARB_gpu_shader_int64"
119 OpSourceExtension "GL_ARB_shader_clock"
120 OpSourceExtension "GL_EXT_shader_realtime_clock"
121 OpName %main "main"
122 OpName %time1 "time1"
123 %void = OpTypeVoid
124 )";
125
TEST_F(ValidateMisc,ShaderClockInt64)126 TEST_F(ValidateMisc, ShaderClockInt64) {
127 const std::string spirv = ShaderClockSpirv + R"(
128 %3 = OpTypeFunction %void
129 %uint = OpTypeInt 32 0
130 %_ptr_Function_uint = OpTypePointer Function %uint
131 %uint_3 = OpConstant %uint 3
132 %uint_1 = OpConstant %uint 1
133 %main = OpFunction %void None %3
134 %5 = OpLabel
135 %time1 = OpVariable %_ptr_Function_uint Function
136 %11 = OpReadClockKHR %uint %uint_3
137 OpStore %time1 %11
138 OpReturn
139 OpFunctionEnd)";
140
141 CompileSuccessfully(spirv);
142 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
143 EXPECT_THAT(getDiagnosticString(), HasSubstr("or 64bit unsigned integer"));
144 }
145
TEST_F(ValidateMisc,ShaderClockVec2)146 TEST_F(ValidateMisc, ShaderClockVec2) {
147 const std::string spirv = ShaderClockSpirv + R"(
148 %3 = OpTypeFunction %void
149 %ulong = OpTypeInt 64 0
150 %_ptr_Function_ulong = OpTypePointer Function %ulong
151 %uint = OpTypeInt 32 0
152 %uint_3 = OpConstant %uint 3
153 %v2uint = OpTypeVector %ulong 2
154 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
155 %main = OpFunction %void None %3
156 %5 = OpLabel
157 %time1 = OpVariable %_ptr_Function_v2uint Function
158 %15 = OpReadClockKHR %v2uint %uint_3
159 OpStore %time1 %15
160 OpReturn
161 OpFunctionEnd)";
162
163 CompileSuccessfully(spirv);
164 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
165 EXPECT_THAT(getDiagnosticString(), HasSubstr("vector of two components"));
166 }
167
TEST_F(ValidateMisc,ShaderClockInvalidScopeValue)168 TEST_F(ValidateMisc, ShaderClockInvalidScopeValue) {
169 const std::string spirv = ShaderClockSpirv + R"(
170 %3 = OpTypeFunction %void
171 %ulong = OpTypeInt 64 0
172 %uint = OpTypeInt 32 0
173 %_ptr_Function_ulong = OpTypePointer Function %ulong
174 %uint_10 = OpConstant %uint 10
175 %uint_1 = OpConstant %uint 1
176 %main = OpFunction %void None %3
177 %5 = OpLabel
178 %time1 = OpVariable %_ptr_Function_ulong Function
179 %11 = OpReadClockKHR %ulong %uint_10
180 OpStore %time1 %11
181 OpReturn
182 OpFunctionEnd)";
183
184 CompileSuccessfully(spirv);
185 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
186 EXPECT_THAT(getDiagnosticString(), HasSubstr("Invalid scope value"));
187 }
188
TEST_F(ValidateMisc,ShaderClockSubgroupScope)189 TEST_F(ValidateMisc, ShaderClockSubgroupScope) {
190 const std::string spirv = ShaderClockSpirv + R"(
191 %3 = OpTypeFunction %void
192 %ulong = OpTypeInt 64 0
193 %uint = OpTypeInt 32 0
194 %_ptr_Function_ulong = OpTypePointer Function %ulong
195 %subgroup = OpConstant %uint 3
196 %uint_1 = OpConstant %uint 1
197 %main = OpFunction %void None %3
198 %5 = OpLabel
199 %time1 = OpVariable %_ptr_Function_ulong Function
200 %11 = OpReadClockKHR %ulong %subgroup
201 OpStore %time1 %11
202 OpReturn
203 OpFunctionEnd)";
204
205 CompileSuccessfully(spirv);
206 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
207 }
208
TEST_F(ValidateMisc,ShaderClockDeviceScope)209 TEST_F(ValidateMisc, ShaderClockDeviceScope) {
210 const std::string spirv = ShaderClockSpirv + R"(
211 %3 = OpTypeFunction %void
212 %ulong = OpTypeInt 64 0
213 %uint = OpTypeInt 32 0
214 %_ptr_Function_ulong = OpTypePointer Function %ulong
215 %device = OpConstant %uint 1
216 %uint_1 = OpConstant %uint 1
217 %main = OpFunction %void None %3
218 %5 = OpLabel
219 %time1 = OpVariable %_ptr_Function_ulong Function
220 %11 = OpReadClockKHR %ulong %device
221 OpStore %time1 %11
222 OpReturn
223 OpFunctionEnd)";
224
225 CompileSuccessfully(spirv);
226 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
227 }
228
TEST_F(ValidateMisc,ShaderClockWorkgroupScope)229 TEST_F(ValidateMisc, ShaderClockWorkgroupScope) {
230 const std::string spirv = ShaderClockSpirv + R"(
231 %3 = OpTypeFunction %void
232 %ulong = OpTypeInt 64 0
233 %uint = OpTypeInt 32 0
234 %_ptr_Function_ulong = OpTypePointer Function %ulong
235 %workgroup = OpConstant %uint 2
236 %uint_1 = OpConstant %uint 1
237 %main = OpFunction %void None %3
238 %5 = OpLabel
239 %time1 = OpVariable %_ptr_Function_ulong Function
240 %11 = OpReadClockKHR %ulong %workgroup
241 OpStore %time1 %11
242 OpReturn
243 OpFunctionEnd)";
244
245 CompileSuccessfully(spirv);
246 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
247 EXPECT_THAT(getDiagnosticString(),
248 HasSubstr("Scope must be Subgroup or Device"));
249 }
250
TEST_F(ValidateMisc,VulkanShaderClockWorkgroupScope)251 TEST_F(ValidateMisc, VulkanShaderClockWorkgroupScope) {
252 const std::string spirv = ShaderClockSpirv + R"(
253 %3 = OpTypeFunction %void
254 %ulong = OpTypeInt 64 0
255 %uint = OpTypeInt 32 0
256 %_ptr_Function_ulong = OpTypePointer Function %ulong
257 %workgroup = OpConstant %uint 2
258 %uint_1 = OpConstant %uint 1
259 %main = OpFunction %void None %3
260 %5 = OpLabel
261 %time1 = OpVariable %_ptr_Function_ulong Function
262 %11 = OpReadClockKHR %ulong %workgroup
263 OpStore %time1 %11
264 OpReturn
265 OpFunctionEnd)";
266
267 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
268 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
269 EXPECT_THAT(getDiagnosticString(),
270 AnyVUID("VUID-StandaloneSpirv-OpReadClockKHR-04652"));
271 EXPECT_THAT(getDiagnosticString(),
272 HasSubstr("Scope must be Subgroup or Device"));
273 }
274
GenKernelClockSpirv(const std::string & scope)275 std::string GenKernelClockSpirv(const std::string& scope) {
276 const std::string s = R"(
277 OpCapability Kernel
278 OpCapability Addresses
279 OpCapability Int64
280 OpCapability ShaderClockKHR
281 OpExtension "SPV_KHR_shader_clock"
282 OpMemoryModel Physical32 OpenCL
283 OpEntryPoint Kernel %main "main"
284 OpExecutionMode %main ContractionOff
285 OpSource OpenCL_C 200000
286 OpName %main "main"
287 OpName %time1 "time1"
288 %void = OpTypeVoid
289 %3 = OpTypeFunction %void
290 %ulong = OpTypeInt 64 0
291 %uint = OpTypeInt 32 0
292 %_ptr_Function_ulong = OpTypePointer Function %ulong
293 %scope = OpConstant %uint )" +
294 scope + R"(
295 %main = OpFunction %void None %3
296 %5 = OpLabel
297 %time1 = OpVariable %_ptr_Function_ulong Function
298 %11 = OpReadClockKHR %ulong %scope
299 OpStore %time1 %11
300 OpReturn
301 OpFunctionEnd
302 )";
303 return s;
304 }
305
TEST_F(ValidateMisc,KernelClockScopeDevice)306 TEST_F(ValidateMisc, KernelClockScopeDevice) {
307 CompileSuccessfully(GenKernelClockSpirv("1"), SPV_ENV_OPENCL_1_2);
308 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
309 }
310
TEST_F(ValidateMisc,KernelClockScopeWorkgroup)311 TEST_F(ValidateMisc, KernelClockScopeWorkgroup) {
312 CompileSuccessfully(GenKernelClockSpirv("2"), SPV_ENV_OPENCL_1_2);
313 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
314 }
315
TEST_F(ValidateMisc,KernelClockScopeSubgroup)316 TEST_F(ValidateMisc, KernelClockScopeSubgroup) {
317 CompileSuccessfully(GenKernelClockSpirv("3"), SPV_ENV_OPENCL_1_2);
318 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
319 }
320
TEST_F(ValidateMisc,KernelClockScopeInvalid)321 TEST_F(ValidateMisc, KernelClockScopeInvalid) {
322 CompileSuccessfully(GenKernelClockSpirv("0"), SPV_ENV_OPENCL_1_2);
323 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
324 EXPECT_THAT(getDiagnosticString(),
325 HasSubstr("Scope must be Subgroup, Workgroup, or Device"));
326 }
327
TEST_F(ValidateMisc,UndefVoid)328 TEST_F(ValidateMisc, UndefVoid) {
329 const std::string spirv = R"(
330 OpCapability Shader
331 %1 = OpExtInstImport "GLSL.std.450"
332 OpMemoryModel Logical GLSL450
333 OpEntryPoint Fragment %4 "main"
334 OpExecutionMode %4 OriginUpperLeft
335 OpSource ESSL 320
336 %2 = OpTypeVoid
337 %10 = OpUndef %2
338 %3 = OpTypeFunction %2
339 %4 = OpFunction %2 None %3
340 %5 = OpLabel
341 OpReturn
342 OpFunctionEnd
343 )";
344
345 CompileSuccessfully(spirv);
346 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
347 EXPECT_THAT(getDiagnosticString(),
348 HasSubstr("Cannot create undefined values with void type"));
349 }
350
TEST_F(ValidateMisc,VulkanInvalidStorageClass)351 TEST_F(ValidateMisc, VulkanInvalidStorageClass) {
352 const std::string spirv = R"(
353 OpCapability Shader
354 OpMemoryModel Logical GLSL450
355 OpEntryPoint Vertex %func "shader"
356 %int = OpTypeInt 32 0
357 %ptr = OpTypePointer CrossWorkgroup %int
358 %var = OpVariable %ptr CrossWorkgroup
359 %void = OpTypeVoid
360 %void_f = OpTypeFunction %void
361 %func = OpFunction %void None %void_f
362 %label = OpLabel
363 OpReturn
364 OpFunctionEnd
365 )";
366
367 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
368 ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_VULKAN_1_0));
369 EXPECT_THAT(getDiagnosticString(),
370 AnyVUID("VUID-StandaloneSpirv-None-04643"));
371 EXPECT_THAT(getDiagnosticString(),
372 HasSubstr("Invalid storage class for target environment"));
373 }
374
TEST_F(ValidateMisc,CoopMat2WorkgroupLocalSizeIdPass)375 TEST_F(ValidateMisc, CoopMat2WorkgroupLocalSizeIdPass) {
376 const std::string body = R"(
377 OpCapability Shader
378 OpCapability Float16
379 OpCapability Int16
380 OpCapability CooperativeMatrixKHR
381 OpExtension "SPV_KHR_cooperative_matrix"
382 OpExtension "SPV_KHR_vulkan_memory_model"
383 OpMemoryModel Logical GLSL450
384 OpEntryPoint GLCompute %main "main"
385 OpExecutionModeId %main LocalSizeId %u32_16 %u32_16 %u32_16
386 %void = OpTypeVoid
387 %func = OpTypeFunction %void
388 %bool = OpTypeBool
389 %f16 = OpTypeFloat 16
390 %u32 = OpTypeInt 32 0
391
392 %u32_16 = OpConstant %u32 16
393 %use_Acc = OpConstant %u32 2
394 %workgroup = OpConstant %u32 2
395
396 %f16mat = OpTypeCooperativeMatrixKHR %f16 %workgroup %u32_16 %u32_16 %use_Acc
397
398 %main = OpFunction %void None %func
399 %main_entry = OpLabel
400
401 OpReturn
402 OpFunctionEnd)";
403
404 CompileSuccessfully(body.c_str(), SPV_ENV_UNIVERSAL_1_3);
405 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
406 }
407
TEST_F(ValidateMisc,CoopMat2WorkgroupLocalSizeIdConstantNotDeclaredYetFail)408 TEST_F(ValidateMisc, CoopMat2WorkgroupLocalSizeIdConstantNotDeclaredYetFail) {
409 const std::string body = R"(
410 OpCapability Shader
411 OpCapability Float16
412 OpCapability Int16
413 OpCapability CooperativeMatrixKHR
414 OpExtension "SPV_KHR_cooperative_matrix"
415 OpExtension "SPV_KHR_vulkan_memory_model"
416 OpMemoryModel Logical GLSL450
417 OpEntryPoint GLCompute %main "main"
418 OpExecutionModeId %main LocalSizeId %u32_16 %u32_8 %u32_16
419 %void = OpTypeVoid
420 %func = OpTypeFunction %void
421 %bool = OpTypeBool
422 %f16 = OpTypeFloat 16
423 %u32 = OpTypeInt 32 0
424
425 %u32_16 = OpConstant %u32 16
426 %use_Acc = OpConstant %u32 2
427 %workgroup = OpConstant %u32 2
428
429 %f16mat = OpTypeCooperativeMatrixKHR %f16 %workgroup %u32_16 %u32_16 %use_Acc
430 %u32_8 = OpConstant %u32 8
431
432 %main = OpFunction %void None %func
433 %main_entry = OpLabel
434
435 OpReturn
436 OpFunctionEnd)";
437
438 CompileSuccessfully(body.c_str(), SPV_ENV_UNIVERSAL_1_3);
439 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
440 EXPECT_THAT(getDiagnosticString(),
441 HasSubstr("OpTypeCooperativeMatrixKHR with ScopeWorkgroup used "
442 "before LocalSizeId constant value"));
443 }
444
445 } // namespace
446 } // namespace val
447 } // namespace spvtools
448