mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-25 13:00:04 +00:00
7810 lines
247 KiB
C++
7810 lines
247 KiB
C++
// Copyright (c) 2018 Google Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Validation tests for memory/storage
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "gmock/gmock.h"
|
|
#include "test/unit_spirv.h"
|
|
#include "test/val/val_code_generator.h"
|
|
#include "test/val/val_fixtures.h"
|
|
|
|
// For pretty-printing tuples with spv_target_env.
|
|
std::ostream& operator<<(std::ostream& stream, spv_target_env target) {
|
|
switch (target) {
|
|
case SPV_ENV_UNIVERSAL_1_3:
|
|
return stream << "SPV_ENV_UNIVERSAL_1_3";
|
|
case SPV_ENV_UNIVERSAL_1_4:
|
|
return stream << "SPV_ENV_UNIVERSAL_1_4";
|
|
default:
|
|
return stream << (unsigned)target;
|
|
}
|
|
}
|
|
|
|
namespace spvtools {
|
|
namespace val {
|
|
namespace {
|
|
|
|
using ::testing::Combine;
|
|
using ::testing::Eq;
|
|
using ::testing::HasSubstr;
|
|
using ::testing::Values;
|
|
|
|
using ValidateMemory = spvtest::ValidateBase<bool>;
|
|
|
|
TEST_F(ValidateMemory, VulkanUniformConstantOnNonOpaqueResourceBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%float = OpTypeFloat 32
|
|
%float_ptr = OpTypePointer UniformConstant %float
|
|
%2 = OpVariable %float_ptr UniformConstant
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-UniformConstant-04655"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Variables identified with the UniformConstant storage class "
|
|
"are used only as handles to refer to opaque resources. Such "
|
|
"variables must be typed as OpTypeImage, OpTypeSampler, "
|
|
"OpTypeSampledImage, OpTypeAccelerationStructureKHR, "
|
|
"or an array of one of these types."));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceGood) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %2 DescriptorSet 0
|
|
OpDecorate %2 Binding 0
|
|
%sampler = OpTypeSampler
|
|
%sampler_ptr = OpTypePointer UniformConstant %sampler
|
|
%2 = OpVariable %sampler_ptr UniformConstant
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanUniformConstantOnNonOpaqueResourceArrayBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%float = OpTypeFloat 32
|
|
%uint = OpTypeInt 32 0
|
|
%array_size = OpConstant %uint 5
|
|
%array = OpTypeArray %float %array_size
|
|
%array_ptr = OpTypePointer UniformConstant %array
|
|
%2 = OpVariable %array_ptr UniformConstant
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-UniformConstant-04655"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Variables identified with the UniformConstant storage class "
|
|
"are used only as handles to refer to opaque resources. Such "
|
|
"variables must be typed as OpTypeImage, OpTypeSampler, "
|
|
"OpTypeSampledImage, OpTypeAccelerationStructureKHR, "
|
|
"or an array of one of these types."));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceArrayGood) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %2 DescriptorSet 0
|
|
OpDecorate %2 Binding 0
|
|
%sampler = OpTypeSampler
|
|
%uint = OpTypeInt 32 0
|
|
%array_size = OpConstant %uint 5
|
|
%array = OpTypeArray %sampler %array_size
|
|
%array_ptr = OpTypePointer UniformConstant %array
|
|
%2 = OpVariable %array_ptr UniformConstant
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceRuntimeArrayGood) {
|
|
std::string spirv = R"(
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %2 DescriptorSet 0
|
|
OpDecorate %2 Binding 0
|
|
%sampler = OpTypeSampler
|
|
%uint = OpTypeInt 32 0
|
|
%array = OpTypeRuntimeArray %sampler
|
|
%array_ptr = OpTypePointer UniformConstant %array
|
|
%2 = OpVariable %array_ptr UniformConstant
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanUniformOnIntBad) {
|
|
char src[] = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %kernel "main"
|
|
OpExecutionMode %kernel LocalSize 1 1 1
|
|
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
|
|
%voidty = OpTypeVoid
|
|
%kernelty = OpTypeFunction %voidty
|
|
%intty = OpTypeInt 32 0
|
|
%varty = OpTypePointer Uniform %intty
|
|
%value = OpConstant %intty 42
|
|
|
|
%var = OpVariable %varty Uniform
|
|
|
|
%kernel = OpFunction %voidty None %kernelty
|
|
%label = OpLabel
|
|
OpStore %var %value
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(src, SPV_ENV_VULKAN_1_1);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("From Vulkan spec:\n"
|
|
"Variables identified with the Uniform storage class are used "
|
|
"to access transparent buffer backed resources. Such variables "
|
|
"must be typed as OpTypeStruct, or an array of this type"));
|
|
}
|
|
|
|
// #version 440
|
|
// #extension GL_EXT_nonuniform_qualifier : enable
|
|
// layout(binding = 1) uniform sampler2D s2d[][2];
|
|
// layout(location = 0) in nonuniformEXT int i;
|
|
// void main()
|
|
// {
|
|
// vec4 v = texture(s2d[i][i], vec2(0.3));
|
|
// }
|
|
TEST_F(ValidateMemory, VulkanUniformOnRuntimeArrayOfArrayBad) {
|
|
char src[] = R"(
|
|
OpCapability Shader
|
|
OpCapability ShaderNonUniformEXT
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpCapability SampledImageArrayNonUniformIndexingEXT
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main" %i
|
|
OpSource GLSL 440
|
|
OpSourceExtension "GL_EXT_nonuniform_qualifier"
|
|
OpName %main "main"
|
|
OpName %v "v"
|
|
OpName %s2d "s2d"
|
|
OpName %i "i"
|
|
OpDecorate %s2d DescriptorSet 0
|
|
OpDecorate %s2d Binding 1
|
|
OpDecorate %i Location 0
|
|
OpDecorate %i NonUniformEXT
|
|
OpDecorate %21 NonUniformEXT
|
|
OpDecorate %22 NonUniformEXT
|
|
OpDecorate %25 NonUniformEXT
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%v4float = OpTypeVector %float 4
|
|
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
|
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
|
%11 = OpTypeSampledImage %10
|
|
%uint = OpTypeInt 32 0
|
|
%uint_2 = OpConstant %uint 2
|
|
%_arr_11_uint_2 = OpTypeArray %11 %uint_2
|
|
%_runtimearr__arr_11_uint_2 = OpTypeRuntimeArray %_arr_11_uint_2
|
|
%_ptr_Uniform__runtimearr__arr_11_uint_2 = OpTypePointer Uniform %_runtimearr__arr_11_uint_2
|
|
%s2d = OpVariable %_ptr_Uniform__runtimearr__arr_11_uint_2 Uniform
|
|
%int = OpTypeInt 32 1
|
|
%_ptr_Input_int = OpTypePointer Input %int
|
|
%i = OpVariable %_ptr_Input_int Input
|
|
%_ptr_Uniform_11 = OpTypePointer Uniform %11
|
|
%v2float = OpTypeVector %float 2
|
|
%float_0_300000012 = OpConstant %float 0.300000012
|
|
%28 = OpConstantComposite %v2float %float_0_300000012 %float_0_300000012
|
|
%float_0 = OpConstant %float 0
|
|
%main = OpFunction %void None %3
|
|
%5 = OpLabel
|
|
%v = OpVariable %_ptr_Function_v4float Function
|
|
%21 = OpLoad %int %i
|
|
%22 = OpLoad %int %i
|
|
%24 = OpAccessChain %_ptr_Uniform_11 %s2d %21 %22
|
|
%25 = OpLoad %11 %24
|
|
%30 = OpImageSampleExplicitLod %v4float %25 %28 Lod %float_0
|
|
OpStore %v %30
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(src, SPV_ENV_VULKAN_1_1);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("From Vulkan spec:\n"
|
|
"Variables identified with the Uniform storage class are used "
|
|
"to access transparent buffer backed resources. Such variables "
|
|
"must be typed as OpTypeStruct, or an array of this type"));
|
|
}
|
|
|
|
// #version 440
|
|
// layout (set=1, binding=1) uniform sampler2D variableName[2][2];
|
|
// void main() {
|
|
// }
|
|
TEST_F(ValidateMemory, VulkanUniformOnArrayOfArrayBad) {
|
|
char src[] = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main"
|
|
OpSource GLSL 440
|
|
OpName %main "main"
|
|
OpName %variableName "variableName"
|
|
OpDecorate %variableName DescriptorSet 1
|
|
OpDecorate %variableName Binding 1
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%7 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
|
%8 = OpTypeSampledImage %7
|
|
%uint = OpTypeInt 32 0
|
|
%uint_2 = OpConstant %uint 2
|
|
%_arr_8_uint_2 = OpTypeArray %8 %uint_2
|
|
%_arr__arr_8_uint_2_uint_2 = OpTypeArray %_arr_8_uint_2 %uint_2
|
|
%_ptr_Uniform__arr__arr_8_uint_2_uint_2 = OpTypePointer Uniform %_arr__arr_8_uint_2_uint_2
|
|
%variableName = OpVariable %_ptr_Uniform__arr__arr_8_uint_2_uint_2 Uniform
|
|
%main = OpFunction %void None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(src, SPV_ENV_VULKAN_1_1);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("From Vulkan spec:\n"
|
|
"Variables identified with the Uniform storage class are used "
|
|
"to access transparent buffer backed resources. Such variables "
|
|
"must be typed as OpTypeStruct, or an array of this type"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, MismatchingStorageClassesBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%float = OpTypeFloat 32
|
|
%float_ptr = OpTypePointer Uniform %float
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%1 = OpLabel
|
|
%2 = OpVariable %float_ptr Function
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Storage class must match result type storage class"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, MatchingStorageClassesGood) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%float = OpTypeFloat 32
|
|
%float_ptr = OpTypePointer Function %float
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%1 = OpLabel
|
|
%2 = OpVariable %float_ptr Function
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanInitializerWithOutputStorageClassesGood) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%float = OpTypeFloat 32
|
|
%float_ptr = OpTypePointer Output %float
|
|
%init_val = OpConstant %float 1.0
|
|
%1 = OpVariable %float_ptr Output %init_val
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%2 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanInitializerWithFunctionStorageClassesGood) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%float = OpTypeFloat 32
|
|
%float_ptr = OpTypePointer Function %float
|
|
%init_val = OpConstant %float 1.0
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%1 = OpLabel
|
|
%2 = OpVariable %float_ptr Function %init_val
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanInitializerWithPrivateStorageClassesGood) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%float = OpTypeFloat 32
|
|
%float_ptr = OpTypePointer Private %float
|
|
%init_val = OpConstant %float 1.0
|
|
%1 = OpVariable %float_ptr Private %init_val
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%2 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanInitializerWithDisallowedStorageClassesBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%float = OpTypeFloat 32
|
|
%float_ptr = OpTypePointer Input %float
|
|
%init_val = OpConstant %float 1.0
|
|
%1 = OpVariable %float_ptr Input %init_val
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%2 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpVariable-04651"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("OpVariable, <id> '5[%5]', has a disallowed initializer & "
|
|
"storage class combination.\nFrom Vulkan spec:\nVariable "
|
|
"declarations that include initializers must have one of the "
|
|
"following storage classes: Output, Private, Function or "
|
|
"Workgroup\n %5 "
|
|
"= OpVariable %_ptr_Input_float Input %float_1\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UniversalInitializerWithDisallowedStorageClassesBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%float = OpTypeFloat 32
|
|
%float_ptr = OpTypePointer Input %float
|
|
%init_val = OpConstant %float 1.0
|
|
%1 = OpVariable %float_ptr Input %init_val
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%2 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"OpVariable, <id> '5[%5]', initializer are not allowed for Input"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, InitializerWithTaskPayloadWorkgroupEXT) {
|
|
std::string spirv = R"(
|
|
OpCapability MeshShadingEXT
|
|
OpExtension "SPV_EXT_mesh_shader"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint TaskEXT %main "main" %payload
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%uint = OpTypeInt 32 0
|
|
%_ptr_TaskPayloadWorkgroupEXT = OpTypePointer TaskPayloadWorkgroupEXT %uint
|
|
%uint_1 = OpConstant %uint 1
|
|
%payload = OpVariable %_ptr_TaskPayloadWorkgroupEXT TaskPayloadWorkgroupEXT %uint_1
|
|
%main = OpFunction %void None %func
|
|
%label = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_UNIVERSAL_1_5);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("OpVariable, <id> '2[%2]', initializer are not allowed "
|
|
"for TaskPayloadWorkgroupEXT"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLenCorrectResultType) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%uint = OpTypeInt 32 0
|
|
%_runtimearr_float = OpTypeRuntimeArray %float
|
|
%_struct_7 = OpTypeStruct %_runtimearr_float
|
|
%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
|
|
%1 = OpFunction %void None %3
|
|
%9 = OpLabel
|
|
%10 = OpVariable %_ptr_Function__struct_7 Function
|
|
%11 = OpArrayLength %uint %10 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLenIndexCorrectWith2Members) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%uint = OpTypeInt 32 0
|
|
%_runtimearr_float = OpTypeRuntimeArray %float
|
|
%_struct_7 = OpTypeStruct %float %_runtimearr_float
|
|
%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
|
|
%1 = OpFunction %void None %3
|
|
%9 = OpLabel
|
|
%10 = OpVariable %_ptr_Function__struct_7 Function
|
|
%11 = OpArrayLength %uint %10 1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLenResultNotIntType) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%_runtimearr_float = OpTypeRuntimeArray %float
|
|
%_struct_6 = OpTypeStruct %_runtimearr_float
|
|
%_ptr_Function__struct_6 = OpTypePointer Function %_struct_6
|
|
%1 = OpFunction %void None %3
|
|
%8 = OpLabel
|
|
%9 = OpVariable %_ptr_Function__struct_6 Function
|
|
%10 = OpArrayLength %float %9 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"The Result Type of OpArrayLength <id> '10[%10]' must be OpTypeInt "
|
|
"with width 32 and signedness 0.\n %10 = OpArrayLength %float %9 "
|
|
"0\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLenResultNot32bits) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Int16
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%ushort = OpTypeInt 16 0
|
|
%_runtimearr_float = OpTypeRuntimeArray %float
|
|
%_struct_7 = OpTypeStruct %_runtimearr_float
|
|
%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
|
|
%1 = OpFunction %void None %3
|
|
%9 = OpLabel
|
|
%10 = OpVariable %_ptr_Function__struct_7 Function
|
|
%11 = OpArrayLength %ushort %10 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"The Result Type of OpArrayLength <id> '11[%11]' must be OpTypeInt "
|
|
"with width 32 and signedness 0.\n %11 = OpArrayLength %ushort %10 "
|
|
"0\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLenResultSigned) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%int = OpTypeInt 32 1
|
|
%_runtimearr_float = OpTypeRuntimeArray %float
|
|
%_struct_7 = OpTypeStruct %_runtimearr_float
|
|
%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
|
|
%1 = OpFunction %void None %3
|
|
%9 = OpLabel
|
|
%10 = OpVariable %_ptr_Function__struct_7 Function
|
|
%11 = OpArrayLength %int %10 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"The Result Type of OpArrayLength <id> '11[%11]' must be OpTypeInt "
|
|
"with width 32 and signedness 0.\n %11 = OpArrayLength %int %10 "
|
|
"0\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLenInputNotStruct) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%uint = OpTypeInt 32 0
|
|
%_runtimearr_float = OpTypeRuntimeArray %float
|
|
%_struct_7 = OpTypeStruct %_runtimearr_float
|
|
%_ptr_Function_float = OpTypePointer Function %float
|
|
%1 = OpFunction %void None %3
|
|
%9 = OpLabel
|
|
%10 = OpVariable %_ptr_Function_float Function
|
|
%11 = OpArrayLength %uint %10 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("The Structure's type in OpArrayLength <id> '11[%11]' "
|
|
"must be a pointer to an OpTypeStruct."));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLenInputLastMemberNoRTA) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%uint = OpTypeInt 32 0
|
|
%_runtimearr_float = OpTypeRuntimeArray %float
|
|
%_struct_7 = OpTypeStruct %float
|
|
%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
|
|
%1 = OpFunction %void None %3
|
|
%9 = OpLabel
|
|
%10 = OpVariable %_ptr_Function__struct_7 Function
|
|
%11 = OpArrayLength %uint %10 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("The Structure's last member in OpArrayLength <id> '11[%11]' "
|
|
"must be an OpTypeRuntimeArray.\n %11 = OpArrayLength %uint "
|
|
"%10 0\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLenInputLastMemberNoRTA2) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%uint = OpTypeInt 32 0
|
|
%_runtimearr_float = OpTypeRuntimeArray %float
|
|
%_struct_7 = OpTypeStruct %_runtimearr_float %float
|
|
%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
|
|
%1 = OpFunction %void None %3
|
|
%9 = OpLabel
|
|
%10 = OpVariable %_ptr_Function__struct_7 Function
|
|
%11 = OpArrayLength %uint %10 1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("The Structure's last member in OpArrayLength <id> '11[%11]' "
|
|
"must be an OpTypeRuntimeArray.\n %11 = OpArrayLength %uint "
|
|
"%10 1\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLenIndexNotLastMember) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%uint = OpTypeInt 32 0
|
|
%_runtimearr_float = OpTypeRuntimeArray %float
|
|
%_struct_7 = OpTypeStruct %float %_runtimearr_float
|
|
%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
|
|
%1 = OpFunction %void None %3
|
|
%9 = OpLabel
|
|
%10 = OpVariable %_ptr_Function__struct_7 Function
|
|
%11 = OpArrayLength %uint %10 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"The array member in OpArrayLength <id> '11[%11]' must be the "
|
|
"last member of the struct.\n %11 = OpArrayLength %uint %10 0\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLenIndexNotPointerToStruct) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%uint = OpTypeInt 32 0
|
|
%_runtimearr_float = OpTypeRuntimeArray %float
|
|
%_struct_7 = OpTypeStruct %float
|
|
%_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
|
|
%1 = OpFunction %void None %3
|
|
%9 = OpLabel
|
|
%10 = OpVariable %_ptr_Function__struct_7 Function
|
|
%11 = OpLoad %_struct_7 %10
|
|
%12 = OpArrayLength %uint %11 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"The Structure's type in OpArrayLength <id> '12[%12]' must be a "
|
|
"pointer to an OpTypeStruct.\n %12 = OpArrayLength %uint %11 0\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLenPointerIsAType) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%uint = OpTypeInt 32 0
|
|
%1 = OpFunction %void None %3
|
|
%9 = OpLabel
|
|
%12 = OpArrayLength %uint %float 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Operand '4[%float]' cannot be a "
|
|
"type"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PushConstantNotStructGood) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%ptr = OpTypePointer PushConstant %float
|
|
%pc = OpVariable %ptr PushConstant
|
|
|
|
%1 = OpFunction %void None %voidfn
|
|
%label = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanPushConstantNotStructBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%ptr = OpTypePointer PushConstant %float
|
|
%pc = OpVariable %ptr PushConstant
|
|
|
|
%1 = OpFunction %void None %voidfn
|
|
%label = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-PushConstant-06808"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("PushConstant OpVariable <id> '6[%6]' has illegal "
|
|
"type.\nFrom Vulkan spec, Push Constant Interface section:\n"
|
|
"Such variables must be typed as OpTypeStruct"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanPushConstantArrayOfStructBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%int = OpTypeInt 32 0
|
|
%int_1 = OpConstant %int 1
|
|
%struct = OpTypeStruct %float
|
|
%array = OpTypeArray %struct %int_1
|
|
%ptr = OpTypePointer PushConstant %array
|
|
%pc = OpVariable %ptr PushConstant
|
|
|
|
%1 = OpFunction %void None %voidfn
|
|
%label = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-PushConstant-06808"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("PushConstant OpVariable <id> '10[%10]' has illegal "
|
|
"type.\nFrom Vulkan spec, Push Constant Interface section:\n"
|
|
"Such variables must be typed as OpTypeStruct"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanPushConstant) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %1 "main"
|
|
OpExecutionMode %1 OriginUpperLeft
|
|
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%struct = OpTypeStruct %float
|
|
%ptr = OpTypePointer PushConstant %struct
|
|
%pc = OpVariable %ptr PushConstant
|
|
|
|
%1 = OpFunction %void None %voidfn
|
|
%label = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadBad1) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%load = OpLoad %int %var MakePointerVisibleKHR|NonPrivatePointerKHR %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Use of device scope with VulkanKHR memory model requires the "
|
|
"VulkanMemoryModelDeviceScopeKHR capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadBad2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%load = OpLoad %int %var Aligned|MakePointerVisibleKHR|NonPrivatePointerKHR 4 %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Use of device scope with VulkanKHR memory model requires the "
|
|
"VulkanMemoryModelDeviceScopeKHR capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadGood1) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%load = OpLoad %int %var MakePointerVisibleKHR|NonPrivatePointerKHR %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadGood2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%load = OpLoad %int %var Aligned|MakePointerVisibleKHR|NonPrivatePointerKHR 4 %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreBad1) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpStore %var %device MakePointerAvailableKHR|NonPrivatePointerKHR %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Use of device scope with VulkanKHR memory model requires the "
|
|
"VulkanMemoryModelDeviceScopeKHR capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreBad2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpStore %var %device Aligned|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Use of device scope with VulkanKHR memory model requires the "
|
|
"VulkanMemoryModelDeviceScopeKHR capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreGood1) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpStore %var %device MakePointerAvailableKHR|NonPrivatePointerKHR %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreGood2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpStore %var %device Aligned|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad1) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2 MakePointerAvailableKHR|NonPrivatePointerKHR %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Use of device scope with VulkanKHR memory model requires the "
|
|
"VulkanMemoryModelDeviceScopeKHR capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%workgroup = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Use of device scope with VulkanKHR memory model requires the "
|
|
"VulkanMemoryModelDeviceScopeKHR capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad3) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%workgroup = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Use of device scope with VulkanKHR memory model requires the "
|
|
"VulkanMemoryModelDeviceScopeKHR capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryGood2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%workgroup = OpConstant %int 2
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryGood3) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%workgroup = OpConstant %int 2
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessAvVisBadBinaryV13) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2
|
|
MakePointerAvailableKHR|NonPrivatePointerKHR %device
|
|
MakePointerVisibleKHR|NonPrivatePointerKHR %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"with two memory access operands requires SPIR-V 1.4 or later"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessAvVisGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2
|
|
MakePointerAvailableKHR|NonPrivatePointerKHR %device
|
|
MakePointerVisibleKHR|NonPrivatePointerKHR %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessFirstWithAvBad) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2
|
|
MakePointerAvailableKHR|NonPrivatePointerKHR %device
|
|
MakePointerAvailableKHR|NonPrivatePointerKHR %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"Source memory access must not include MakePointerAvailableKHR\n"
|
|
" OpCopyMemory %5 %6 MakePointerAvailable|NonPrivatePointer"
|
|
" %uint_1 MakePointerAvailable|NonPrivatePointer %uint_1"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessSecondWithVisBad) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2
|
|
MakePointerVisibleKHR|NonPrivatePointerKHR %device
|
|
MakePointerVisibleKHR|NonPrivatePointerKHR %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Target memory access must not include MakePointerVisibleKHR\n"
|
|
" OpCopyMemory %5 %6 MakePointerVisible|NonPrivatePointer"
|
|
" %uint_1 MakePointerVisible|NonPrivatePointer %uint_1"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad1) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability Linkage
|
|
OpCapability Addresses
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_4 = OpConstant %int 4
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var1 %var2 %int_4 MakePointerAvailableKHR|NonPrivatePointerKHR %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Use of device scope with VulkanKHR memory model requires the "
|
|
"VulkanMemoryModelDeviceScopeKHR capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability Linkage
|
|
OpCapability Addresses
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_4 = OpConstant %int 4
|
|
%device = OpConstant %int 1
|
|
%workgroup = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var1 %var2 %int_4 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Use of device scope with VulkanKHR memory model requires the "
|
|
"VulkanMemoryModelDeviceScopeKHR capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad3) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability Linkage
|
|
OpCapability Addresses
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_4 = OpConstant %int 4
|
|
%device = OpConstant %int 1
|
|
%workgroup = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var1 %var2 %int_4 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Use of device scope with VulkanKHR memory model requires the "
|
|
"VulkanMemoryModelDeviceScopeKHR capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood1) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpCapability Addresses
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_4 = OpConstant %int 4
|
|
%device = OpConstant %int 1
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var1 %var2 %int_4 MakePointerAvailableKHR|NonPrivatePointerKHR %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpCapability Addresses
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_4 = OpConstant %int 4
|
|
%device = OpConstant %int 1
|
|
%workgroup = OpConstant %int 2
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var1 %var2 %int_4 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood3) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability VulkanMemoryModelDeviceScopeKHR
|
|
OpCapability Linkage
|
|
OpCapability Addresses
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_4 = OpConstant %int 4
|
|
%device = OpConstant %int 1
|
|
%workgroup = OpConstant %int 2
|
|
%int_ptr_ssbo = OpTypePointer StorageBuffer %int
|
|
%var1 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%var2 = OpVariable %int_ptr_ssbo StorageBuffer
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var1 %var2 %int_4 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, ArrayLengthStructIsLabel) {
|
|
const std::string spirv = R"(
|
|
OpCapability Tessellation
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %20 "incorrect"
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%v4float = OpTypeVector %float 4
|
|
%uint = OpTypeInt 32 0
|
|
%4 = OpFunction %void None %3
|
|
%20 = OpLabel
|
|
%24 = OpArrayLength %uint %20 0
|
|
%25 = OpLoad %v4float %24
|
|
OpReturnValue %25
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Operand '1[%incorrect]' requires a type"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PSBLoadAlignedSuccess) {
|
|
const std::string body = R"(
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability Int64
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_physical_storage_buffer"
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint Fragment %main "main"
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpDecorate %val1 AliasedPointer
|
|
%uint64 = OpTypeInt 64 0
|
|
%ptr = OpTypePointer PhysicalStorageBuffer %uint64
|
|
%pptr_f = OpTypePointer Function %ptr
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%main = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%val1 = OpVariable %pptr_f Function
|
|
%val2 = OpLoad %ptr %val1
|
|
%val3 = OpLoad %uint64 %val2 Aligned 8
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PSBLoadAlignedMissing) {
|
|
const std::string body = R"(
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability Int64
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_physical_storage_buffer"
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint Fragment %main "main"
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpDecorate %val1 AliasedPointer
|
|
%uint64 = OpTypeInt 64 0
|
|
%ptr = OpTypePointer PhysicalStorageBuffer %uint64
|
|
%pptr_f = OpTypePointer Function %ptr
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%main = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%val1 = OpVariable %pptr_f Function
|
|
%val2 = OpLoad %ptr %val1
|
|
%val3 = OpLoad %uint64 %val2
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PSBLoadAlignedMissingWithOtherOperand) {
|
|
const std::string body = R"(
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability Int64
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_physical_storage_buffer"
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint Fragment %main "main"
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpDecorate %val1 AliasedPointer
|
|
%uint64 = OpTypeInt 64 0
|
|
%ptr = OpTypePointer PhysicalStorageBuffer %uint64
|
|
%pptr_f = OpTypePointer Function %ptr
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%main = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%val1 = OpVariable %pptr_f Function
|
|
%val2 = OpLoad %ptr %val1
|
|
%val3 = OpLoad %uint64 %val2 Volatile
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PSBStoreAlignedSuccess) {
|
|
const std::string body = R"(
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability Int64
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_physical_storage_buffer"
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint Fragment %main "main"
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpDecorate %val1 AliasedPointer
|
|
%uint64 = OpTypeInt 64 0
|
|
%u64_1 = OpConstant %uint64 1
|
|
%ptr = OpTypePointer PhysicalStorageBuffer %uint64
|
|
%pptr_f = OpTypePointer Function %ptr
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%main = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%val1 = OpVariable %pptr_f Function
|
|
%val2 = OpLoad %ptr %val1
|
|
OpStore %val2 %u64_1 Aligned 8
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PSBStoreAlignedMissing) {
|
|
const std::string body = R"(
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability Int64
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_physical_storage_buffer"
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint Fragment %main "main"
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpDecorate %val1 AliasedPointer
|
|
%uint64 = OpTypeInt 64 0
|
|
%u64_1 = OpConstant %uint64 1
|
|
%ptr = OpTypePointer PhysicalStorageBuffer %uint64
|
|
%pptr_f = OpTypePointer Function %ptr
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%main = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%val1 = OpVariable %pptr_f Function
|
|
%val2 = OpLoad %ptr %val1
|
|
OpStore %val2 %u64_1 None
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PSBCopyMemoryAlignedSuccess) {
|
|
const std::string body = R"(
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability Int64
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_physical_storage_buffer"
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint Fragment %main "main"
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpDecorate %val1 AliasedPointer
|
|
%int = OpTypeInt 32 0
|
|
%uint64 = OpTypeInt 64 0
|
|
%u64_1 = OpConstant %uint64 1
|
|
%ptr = OpTypePointer PhysicalStorageBuffer %uint64
|
|
%pptr_f = OpTypePointer Function %ptr
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%main = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%val1 = OpVariable %pptr_f Function
|
|
%val2 = OpLoad %ptr %val1
|
|
%val3 = OpLoad %ptr %val1
|
|
OpCopyMemory %val2 %val3 Aligned 4
|
|
OpCopyMemory %val3 %val2 Aligned 4 Aligned 4
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PSBCopyMemoryAlignedMissingTarget) {
|
|
const std::string body = R"(
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability Int64
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_physical_storage_buffer"
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint Fragment %main "main"
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpDecorate %val1 AliasedPointer
|
|
%int = OpTypeInt 32 0
|
|
%uint64 = OpTypeInt 64 0
|
|
%u64_1 = OpConstant %uint64 1
|
|
%ptr = OpTypePointer PhysicalStorageBuffer %uint64
|
|
%pptr_f = OpTypePointer Function %ptr
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%main = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%val1 = OpVariable %pptr_f Function
|
|
%val2 = OpLoad %ptr %val1
|
|
%val3 = OpLoad %ptr %val1
|
|
OpCopyMemory %val2 %val3 Volatile Aligned 4
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PSBCopyMemoryAlignedMissingSource) {
|
|
const std::string body = R"(
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability Int64
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_physical_storage_buffer"
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint Fragment %main "main"
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpDecorate %val1 AliasedPointer
|
|
%int = OpTypeInt 32 0
|
|
%uint64 = OpTypeInt 64 0
|
|
%u64_1 = OpConstant %uint64 1
|
|
%ptr = OpTypePointer PhysicalStorageBuffer %uint64
|
|
%pptr_f = OpTypePointer Function %ptr
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%main = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%val1 = OpVariable %pptr_f Function
|
|
%val2 = OpLoad %ptr %val1
|
|
%val3 = OpLoad %ptr %val1
|
|
OpCopyMemory %val2 %val3 Aligned 4 Volatile
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PSBCopyMemoryAlignedMissingBoth) {
|
|
const std::string body = R"(
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability Int64
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_physical_storage_buffer"
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint Fragment %main "main"
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpDecorate %val1 AliasedPointer
|
|
%int = OpTypeInt 32 0
|
|
%uint64 = OpTypeInt 64 0
|
|
%u64_1 = OpConstant %uint64 1
|
|
%ptr = OpTypePointer PhysicalStorageBuffer %uint64
|
|
%pptr_f = OpTypePointer Function %ptr
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%main = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%val1 = OpVariable %pptr_f Function
|
|
%val2 = OpLoad %ptr %val1
|
|
%val3 = OpLoad %ptr %val1
|
|
OpCopyMemory %val2 %val3 Volatile
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PSBVariable) {
|
|
const std::string body = R"(
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability Int64
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_physical_storage_buffer"
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint Fragment %main "main"
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpDecorate %val1 AliasedPointer
|
|
%uint64 = OpTypeInt 64 0
|
|
%ptr = OpTypePointer PhysicalStorageBuffer %uint64
|
|
%val1 = OpVariable %ptr PhysicalStorageBuffer
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
%main = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(body);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("PhysicalStorageBuffer must not be used with OpVariable"));
|
|
}
|
|
|
|
std::string GenCoopMatLoadStoreShader(const std::string& storeMemoryAccess,
|
|
const std::string& loadMemoryAccess) {
|
|
std::string s = R"(
|
|
OpCapability Shader
|
|
OpCapability GroupNonUniform
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability CooperativeMatrixNV
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpExtension "SPV_NV_cooperative_matrix"
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical VulkanKHR
|
|
OpEntryPoint GLCompute %4 "main" %11 %21
|
|
OpExecutionMode %4 LocalSize 1 1 1
|
|
OpDecorate %11 BuiltIn SubgroupId
|
|
OpDecorate %21 BuiltIn WorkgroupId
|
|
OpDecorate %74 ArrayStride 4
|
|
OpMemberDecorate %75 0 Offset 0
|
|
OpDecorate %75 Block
|
|
OpDecorate %77 DescriptorSet 0
|
|
OpDecorate %77 Binding 0
|
|
OpDecorate %92 ArrayStride 4
|
|
OpMemberDecorate %93 0 Offset 0
|
|
OpDecorate %93 Block
|
|
OpDecorate %95 DescriptorSet 0
|
|
OpDecorate %95 Binding 1
|
|
OpDecorate %102 ArrayStride 4
|
|
OpMemberDecorate %103 0 Offset 0
|
|
OpDecorate %103 Block
|
|
OpDecorate %105 DescriptorSet 0
|
|
OpDecorate %105 Binding 2
|
|
OpDecorate %117 ArrayStride 4
|
|
OpMemberDecorate %118 0 Offset 0
|
|
OpDecorate %118 Block
|
|
OpDecorate %120 DescriptorSet 0
|
|
OpDecorate %120 Binding 3
|
|
OpDecorate %123 SpecId 2
|
|
OpDecorate %124 SpecId 3
|
|
OpDecorate %125 SpecId 4
|
|
OpDecorate %126 SpecId 5
|
|
OpDecorate %127 SpecId 0
|
|
OpDecorate %128 SpecId 1
|
|
OpDecorate %129 BuiltIn WorkgroupSize
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeInt 32 0
|
|
%7 = OpTypeVector %6 2
|
|
%8 = OpTypePointer Function %7
|
|
%10 = OpTypePointer Input %6
|
|
%11 = OpVariable %10 Input
|
|
%13 = OpConstant %6 2
|
|
%19 = OpTypeVector %6 3
|
|
%20 = OpTypePointer Input %19
|
|
%21 = OpVariable %20 Input
|
|
%27 = OpConstantComposite %7 %13 %13
|
|
%31 = OpTypePointer Function %6
|
|
%33 = OpConstant %6 1024
|
|
%34 = OpConstant %6 1
|
|
%38 = OpConstant %6 8
|
|
%39 = OpConstant %6 0
|
|
%68 = OpTypeFloat 32
|
|
%69 = OpConstant %6 16
|
|
%70 = OpConstant %6 3
|
|
%71 = OpTypeCooperativeMatrixNV %68 %70 %69 %38
|
|
%72 = OpTypePointer Function %71
|
|
%74 = OpTypeRuntimeArray %68
|
|
%75 = OpTypeStruct %74
|
|
%76 = OpTypePointer StorageBuffer %75
|
|
%77 = OpVariable %76 StorageBuffer
|
|
%78 = OpTypeInt 32 1
|
|
%79 = OpConstant %78 0
|
|
%81 = OpConstant %6 5
|
|
%82 = OpTypePointer StorageBuffer %68
|
|
%84 = OpConstant %6 64
|
|
%85 = OpTypeBool
|
|
%86 = OpConstantFalse %85
|
|
%88 = OpTypePointer Private %71
|
|
%89 = OpVariable %88 Private
|
|
%92 = OpTypeRuntimeArray %68
|
|
%93 = OpTypeStruct %92
|
|
%94 = OpTypePointer StorageBuffer %93
|
|
%95 = OpVariable %94 StorageBuffer
|
|
%99 = OpVariable %88 Private
|
|
%102 = OpTypeRuntimeArray %68
|
|
%103 = OpTypeStruct %102
|
|
%104 = OpTypePointer StorageBuffer %103
|
|
%105 = OpVariable %104 StorageBuffer
|
|
%109 = OpVariable %88 Private
|
|
%111 = OpVariable %88 Private
|
|
%112 = OpSpecConstantOp %6 CooperativeMatrixLengthNV %71
|
|
%113 = OpSpecConstantOp %78 IAdd %112 %79
|
|
%117 = OpTypeRuntimeArray %68
|
|
%118 = OpTypeStruct %117
|
|
%119 = OpTypePointer StorageBuffer %118
|
|
%120 = OpVariable %119 StorageBuffer
|
|
%123 = OpSpecConstant %78 1
|
|
%124 = OpSpecConstant %78 1
|
|
%125 = OpSpecConstant %78 1
|
|
%126 = OpSpecConstant %78 1
|
|
%127 = OpSpecConstant %6 1
|
|
%128 = OpSpecConstant %6 1
|
|
%129 = OpSpecConstantComposite %19 %127 %128 %34
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%9 = OpVariable %8 Function
|
|
%18 = OpVariable %8 Function
|
|
%32 = OpVariable %31 Function
|
|
%44 = OpVariable %31 Function
|
|
%52 = OpVariable %31 Function
|
|
%60 = OpVariable %31 Function
|
|
%73 = OpVariable %72 Function
|
|
%91 = OpVariable %72 Function
|
|
%101 = OpVariable %72 Function
|
|
%12 = OpLoad %6 %11
|
|
%14 = OpUMod %6 %12 %13
|
|
%15 = OpLoad %6 %11
|
|
%16 = OpUDiv %6 %15 %13
|
|
%17 = OpCompositeConstruct %7 %14 %16
|
|
OpStore %9 %17
|
|
%22 = OpLoad %19 %21
|
|
%23 = OpVectorShuffle %7 %22 %22 0 1
|
|
%24 = OpCompositeExtract %6 %23 0
|
|
%25 = OpCompositeExtract %6 %23 1
|
|
%26 = OpCompositeConstruct %7 %24 %25
|
|
%28 = OpIMul %7 %26 %27
|
|
%29 = OpLoad %7 %9
|
|
%30 = OpIAdd %7 %28 %29
|
|
OpStore %18 %30
|
|
%35 = OpAccessChain %31 %18 %34
|
|
%36 = OpLoad %6 %35
|
|
%37 = OpIMul %6 %33 %36
|
|
%40 = OpAccessChain %31 %18 %39
|
|
%41 = OpLoad %6 %40
|
|
%42 = OpIMul %6 %38 %41
|
|
%43 = OpIAdd %6 %37 %42
|
|
OpStore %32 %43
|
|
%45 = OpAccessChain %31 %18 %34
|
|
%46 = OpLoad %6 %45
|
|
%47 = OpIMul %6 %33 %46
|
|
%48 = OpAccessChain %31 %18 %39
|
|
%49 = OpLoad %6 %48
|
|
%50 = OpIMul %6 %38 %49
|
|
%51 = OpIAdd %6 %47 %50
|
|
OpStore %44 %51
|
|
%53 = OpAccessChain %31 %18 %34
|
|
%54 = OpLoad %6 %53
|
|
%55 = OpIMul %6 %33 %54
|
|
%56 = OpAccessChain %31 %18 %39
|
|
%57 = OpLoad %6 %56
|
|
%58 = OpIMul %6 %38 %57
|
|
%59 = OpIAdd %6 %55 %58
|
|
OpStore %52 %59
|
|
%61 = OpAccessChain %31 %18 %34
|
|
%62 = OpLoad %6 %61
|
|
%63 = OpIMul %6 %33 %62
|
|
%64 = OpAccessChain %31 %18 %39
|
|
%65 = OpLoad %6 %64
|
|
%66 = OpIMul %6 %38 %65
|
|
%67 = OpIAdd %6 %63 %66
|
|
OpStore %60 %67
|
|
%80 = OpLoad %6 %32
|
|
%83 = OpAccessChain %82 %77 %79 %80
|
|
%87 = OpCooperativeMatrixLoadNV %71 %83 %84 %86 )" +
|
|
loadMemoryAccess + R"( %81
|
|
OpStore %73 %87
|
|
%90 = OpLoad %71 %73
|
|
OpStore %89 %90
|
|
%96 = OpLoad %6 %44
|
|
%97 = OpAccessChain %82 %95 %79 %96
|
|
%98 = OpCooperativeMatrixLoadNV %71 %97 %84 %86 MakePointerVisibleKHR|NonPrivatePointerKHR %81
|
|
OpStore %91 %98
|
|
%100 = OpLoad %71 %91
|
|
OpStore %99 %100
|
|
%106 = OpLoad %6 %52
|
|
%107 = OpAccessChain %82 %105 %79 %106
|
|
%108 = OpCooperativeMatrixLoadNV %71 %107 %84 %86 MakePointerVisibleKHR|NonPrivatePointerKHR %81
|
|
OpStore %101 %108
|
|
%110 = OpLoad %71 %101
|
|
OpStore %109 %110
|
|
%114 = OpConvertSToF %68 %113
|
|
%115 = OpCompositeConstruct %71 %114
|
|
OpStore %111 %115
|
|
%116 = OpLoad %71 %111
|
|
%121 = OpLoad %6 %60
|
|
%122 = OpAccessChain %82 %120 %79 %121
|
|
OpCooperativeMatrixStoreNV %122 %116 %84 %86 )" + storeMemoryAccess + R"( %81
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
return s;
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatLoadStoreSuccess) {
|
|
std::string spirv =
|
|
GenCoopMatLoadStoreShader("MakePointerAvailableKHR|NonPrivatePointerKHR",
|
|
"MakePointerVisibleKHR|NonPrivatePointerKHR");
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatStoreMemoryAccessFail) {
|
|
std::string spirv =
|
|
GenCoopMatLoadStoreShader("MakePointerVisibleKHR|NonPrivatePointerKHR",
|
|
"MakePointerVisibleKHR|NonPrivatePointerKHR");
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("MakePointerVisibleKHR cannot be used with OpStore"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatLoadMemoryAccessFail) {
|
|
std::string spirv =
|
|
GenCoopMatLoadStoreShader("MakePointerAvailableKHR|NonPrivatePointerKHR",
|
|
"MakePointerAvailableKHR|NonPrivatePointerKHR");
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("MakePointerAvailableKHR cannot be used with OpLoad"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatInvalidStorageClassFail) {
|
|
const std::string body =
|
|
R"(
|
|
OpCapability Shader
|
|
OpCapability Float16
|
|
OpCapability CooperativeMatrixNV
|
|
OpExtension "SPV_NV_cooperative_matrix"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%f16 = OpTypeFloat 16
|
|
%u32 = OpTypeInt 32 0
|
|
|
|
%u32_8 = OpConstant %u32 8
|
|
%subgroup = OpConstant %u32 3
|
|
|
|
%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
|
|
|
|
%str = OpTypeStruct %f16mat
|
|
%str_ptr = OpTypePointer Workgroup %str
|
|
%sh = OpVariable %str_ptr Workgroup
|
|
|
|
%main = OpFunction %void None %func
|
|
%main_entry = OpLabel
|
|
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
CompileSuccessfully(body.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"Cooperative matrix types (or types containing them) can only be "
|
|
"allocated in Function or Private storage classes or as function "
|
|
"parameters"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatMatrixLengthResultTypeBad) {
|
|
const std::string body =
|
|
R"(
|
|
OpCapability Shader
|
|
OpCapability Float16
|
|
OpCapability CooperativeMatrixNV
|
|
OpExtension "SPV_NV_cooperative_matrix"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%f16 = OpTypeFloat 16
|
|
%u32 = OpTypeInt 32 0
|
|
%i32 = OpTypeInt 32 1
|
|
|
|
%u32_8 = OpConstant %u32 8
|
|
%subgroup = OpConstant %u32 3
|
|
|
|
%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
|
|
|
|
%main = OpFunction %void None %func
|
|
%main_entry = OpLabel
|
|
|
|
%1 = OpCooperativeMatrixLengthNV %i32 %f16mat
|
|
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
CompileSuccessfully(body.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("The Result Type of OpCooperativeMatrixLengthNV <id> "
|
|
"'11[%11]' must be OpTypeInt with width 32 and signedness 0"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatMatrixLengthOperandTypeBad) {
|
|
const std::string body =
|
|
R"(
|
|
OpCapability Shader
|
|
OpCapability Float16
|
|
OpCapability CooperativeMatrixNV
|
|
OpExtension "SPV_NV_cooperative_matrix"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%f16 = OpTypeFloat 16
|
|
%u32 = OpTypeInt 32 0
|
|
%i32 = OpTypeInt 32 1
|
|
|
|
%u32_8 = OpConstant %u32 8
|
|
%subgroup = OpConstant %u32 3
|
|
|
|
%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
|
|
|
|
%main = OpFunction %void None %func
|
|
%main_entry = OpLabel
|
|
|
|
%1 = OpCooperativeMatrixLengthNV %u32 %u32
|
|
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
CompileSuccessfully(body.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("The type in OpCooperativeMatrixLengthNV <id> '5[%uint]' "
|
|
"must be OpTypeCooperativeMatrixNV"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatMatrixLengthGood) {
|
|
const std::string body =
|
|
R"(
|
|
OpCapability Shader
|
|
OpCapability Float16
|
|
OpCapability CooperativeMatrixNV
|
|
OpExtension "SPV_NV_cooperative_matrix"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%f16 = OpTypeFloat 16
|
|
%u32 = OpTypeInt 32 0
|
|
%i32 = OpTypeInt 32 1
|
|
|
|
%u32_8 = OpConstant %u32 8
|
|
%subgroup = OpConstant %u32 3
|
|
|
|
%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
|
|
|
|
%main = OpFunction %void None %func
|
|
%main_entry = OpLabel
|
|
|
|
%1 = OpCooperativeMatrixLengthNV %u32 %f16mat
|
|
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
CompileSuccessfully(body.c_str());
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
std::string GenCoopMatLoadStoreShaderKHR(const std::string& storeMemoryAccess,
|
|
const std::string& loadMemoryAccess,
|
|
unsigned layout = 0,
|
|
bool useSpecConstantLayout = false,
|
|
bool useStoreStride = true,
|
|
bool useLoadStride = true) {
|
|
std::string s = R"(
|
|
OpCapability Shader
|
|
OpCapability GroupNonUniform
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpCapability CooperativeMatrixKHR
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpExtension "SPV_KHR_cooperative_matrix"
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical VulkanKHR
|
|
OpEntryPoint GLCompute %4 "main" %11 %21
|
|
OpExecutionMode %4 LocalSize 1 1 1
|
|
OpDecorate %11 BuiltIn SubgroupId
|
|
OpDecorate %21 BuiltIn WorkgroupId
|
|
OpDecorate %74 ArrayStride 4
|
|
OpMemberDecorate %75 0 Offset 0
|
|
OpDecorate %75 Block
|
|
OpDecorate %77 DescriptorSet 0
|
|
OpDecorate %77 Binding 0
|
|
OpDecorate %92 ArrayStride 4
|
|
OpMemberDecorate %93 0 Offset 0
|
|
OpDecorate %93 Block
|
|
OpDecorate %95 DescriptorSet 0
|
|
OpDecorate %95 Binding 1
|
|
OpDecorate %102 ArrayStride 4
|
|
OpMemberDecorate %103 0 Offset 0
|
|
OpDecorate %103 Block
|
|
OpDecorate %105 DescriptorSet 0
|
|
OpDecorate %105 Binding 2
|
|
OpDecorate %117 ArrayStride 4
|
|
OpMemberDecorate %118 0 Offset 0
|
|
OpDecorate %118 Block
|
|
OpDecorate %120 DescriptorSet 0
|
|
OpDecorate %120 Binding 3
|
|
OpDecorate %123 SpecId 2
|
|
OpDecorate %124 SpecId 3
|
|
OpDecorate %125 SpecId 4
|
|
OpDecorate %126 SpecId 5
|
|
OpDecorate %127 SpecId 0
|
|
OpDecorate %128 SpecId 1
|
|
OpDecorate %129 BuiltIn WorkgroupSize
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeInt 32 0
|
|
%7 = OpTypeVector %6 2
|
|
%8 = OpTypePointer Function %7
|
|
%10 = OpTypePointer Input %6
|
|
%11 = OpVariable %10 Input
|
|
%13 = OpConstant %6 2
|
|
%19 = OpTypeVector %6 3
|
|
%20 = OpTypePointer Input %19
|
|
%21 = OpVariable %20 Input
|
|
%27 = OpConstantComposite %7 %13 %13
|
|
%31 = OpTypePointer Function %6
|
|
%33 = OpConstant %6 1024
|
|
%34 = OpConstant %6 1
|
|
%38 = OpConstant %6 8
|
|
%uint_0 = OpConstant %6 0
|
|
)";
|
|
if (useSpecConstantLayout) {
|
|
s += "%layout = OpSpecConstant %6 " + std::to_string(layout);
|
|
} else {
|
|
s += "%layout = OpConstant %6 " + std::to_string(layout);
|
|
}
|
|
s += R"(
|
|
%68 = OpTypeFloat 32
|
|
%69 = OpConstant %6 16
|
|
%70 = OpConstant %6 3
|
|
%71 = OpTypeCooperativeMatrixKHR %68 %70 %69 %38 %uint_0
|
|
%72 = OpTypePointer Function %71
|
|
%74 = OpTypeRuntimeArray %68
|
|
%75 = OpTypeStruct %74
|
|
%76 = OpTypePointer StorageBuffer %75
|
|
%77 = OpVariable %76 StorageBuffer
|
|
%78 = OpTypeInt 32 1
|
|
%79 = OpConstant %78 0
|
|
%81 = OpConstant %6 5
|
|
%82 = OpTypePointer StorageBuffer %68
|
|
%stride = OpConstant %6 64
|
|
%88 = OpTypePointer Private %71
|
|
%89 = OpVariable %88 Private
|
|
%92 = OpTypeRuntimeArray %68
|
|
%93 = OpTypeStruct %92
|
|
%94 = OpTypePointer StorageBuffer %93
|
|
%95 = OpVariable %94 StorageBuffer
|
|
%99 = OpVariable %88 Private
|
|
%102 = OpTypeRuntimeArray %68
|
|
%103 = OpTypeStruct %102
|
|
%104 = OpTypePointer StorageBuffer %103
|
|
%105 = OpVariable %104 StorageBuffer
|
|
%109 = OpVariable %88 Private
|
|
%111 = OpVariable %88 Private
|
|
%112 = OpSpecConstantOp %6 CooperativeMatrixLengthKHR %71
|
|
%113 = OpSpecConstantOp %78 IAdd %112 %79
|
|
%117 = OpTypeRuntimeArray %68
|
|
%118 = OpTypeStruct %117
|
|
%119 = OpTypePointer StorageBuffer %118
|
|
%120 = OpVariable %119 StorageBuffer
|
|
%123 = OpSpecConstant %78 1
|
|
%124 = OpSpecConstant %78 1
|
|
%125 = OpSpecConstant %78 1
|
|
%126 = OpSpecConstant %78 1
|
|
%127 = OpSpecConstant %6 1
|
|
%128 = OpSpecConstant %6 1
|
|
%129 = OpSpecConstantComposite %19 %127 %128 %34
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%9 = OpVariable %8 Function
|
|
%18 = OpVariable %8 Function
|
|
%32 = OpVariable %31 Function
|
|
%44 = OpVariable %31 Function
|
|
%52 = OpVariable %31 Function
|
|
%60 = OpVariable %31 Function
|
|
%73 = OpVariable %72 Function
|
|
%91 = OpVariable %72 Function
|
|
%101 = OpVariable %72 Function
|
|
%12 = OpLoad %6 %11
|
|
%14 = OpUMod %6 %12 %13
|
|
%15 = OpLoad %6 %11
|
|
%16 = OpUDiv %6 %15 %13
|
|
%17 = OpCompositeConstruct %7 %14 %16
|
|
OpStore %9 %17
|
|
%22 = OpLoad %19 %21
|
|
%23 = OpVectorShuffle %7 %22 %22 0 1
|
|
%24 = OpCompositeExtract %6 %23 0
|
|
%25 = OpCompositeExtract %6 %23 1
|
|
%26 = OpCompositeConstruct %7 %24 %25
|
|
%28 = OpIMul %7 %26 %27
|
|
%29 = OpLoad %7 %9
|
|
%30 = OpIAdd %7 %28 %29
|
|
OpStore %18 %30
|
|
%35 = OpAccessChain %31 %18 %34
|
|
%36 = OpLoad %6 %35
|
|
%37 = OpIMul %6 %33 %36
|
|
%40 = OpAccessChain %31 %18 %uint_0
|
|
%41 = OpLoad %6 %40
|
|
%42 = OpIMul %6 %38 %41
|
|
%43 = OpIAdd %6 %37 %42
|
|
OpStore %32 %43
|
|
%45 = OpAccessChain %31 %18 %34
|
|
%46 = OpLoad %6 %45
|
|
%47 = OpIMul %6 %33 %46
|
|
%48 = OpAccessChain %31 %18 %uint_0
|
|
%49 = OpLoad %6 %48
|
|
%50 = OpIMul %6 %38 %49
|
|
%51 = OpIAdd %6 %47 %50
|
|
OpStore %44 %51
|
|
%53 = OpAccessChain %31 %18 %34
|
|
%54 = OpLoad %6 %53
|
|
%55 = OpIMul %6 %33 %54
|
|
%56 = OpAccessChain %31 %18 %uint_0
|
|
%57 = OpLoad %6 %56
|
|
%58 = OpIMul %6 %38 %57
|
|
%59 = OpIAdd %6 %55 %58
|
|
OpStore %52 %59
|
|
%61 = OpAccessChain %31 %18 %34
|
|
%62 = OpLoad %6 %61
|
|
%63 = OpIMul %6 %33 %62
|
|
%64 = OpAccessChain %31 %18 %uint_0
|
|
%65 = OpLoad %6 %64
|
|
%66 = OpIMul %6 %38 %65
|
|
%67 = OpIAdd %6 %63 %66
|
|
OpStore %60 %67
|
|
%80 = OpLoad %6 %32
|
|
%83 = OpAccessChain %82 %77 %79 %80
|
|
)";
|
|
if (useLoadStride) {
|
|
s += "%87 = OpCooperativeMatrixLoadKHR %71 %83 %layout %stride " +
|
|
loadMemoryAccess + " %81";
|
|
} else {
|
|
s += "%87 = OpCooperativeMatrixLoadKHR %71 %83 %layout";
|
|
}
|
|
s += R"(
|
|
OpStore %73 %87
|
|
%90 = OpLoad %71 %73
|
|
OpStore %89 %90
|
|
%96 = OpLoad %6 %44
|
|
%97 = OpAccessChain %82 %95 %79 %96
|
|
%98 = OpCooperativeMatrixLoadKHR %71 %97 %layout %stride MakePointerVisibleKHR|NonPrivatePointerKHR %81
|
|
OpStore %91 %98
|
|
%100 = OpLoad %71 %91
|
|
OpStore %99 %100
|
|
%106 = OpLoad %6 %52
|
|
%107 = OpAccessChain %82 %105 %79 %106
|
|
%108 = OpCooperativeMatrixLoadKHR %71 %107 %layout %stride MakePointerVisibleKHR|NonPrivatePointerKHR %81
|
|
OpStore %101 %108
|
|
%110 = OpLoad %71 %101
|
|
OpStore %109 %110
|
|
%114 = OpConvertSToF %68 %113
|
|
%115 = OpCompositeConstruct %71 %114
|
|
OpStore %111 %115
|
|
%116 = OpLoad %71 %111
|
|
%121 = OpLoad %6 %60
|
|
%122 = OpAccessChain %82 %120 %79 %121
|
|
)";
|
|
if (useStoreStride) {
|
|
s += "OpCooperativeMatrixStoreKHR %122 %116 %layout %stride " +
|
|
storeMemoryAccess + " %81";
|
|
} else {
|
|
s += "OpCooperativeMatrixStoreKHR %122 %116 %layout";
|
|
}
|
|
s += R"(
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
return s;
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatKHRLoadStoreSuccess) {
|
|
std::string spirv = GenCoopMatLoadStoreShaderKHR(
|
|
"MakePointerAvailableKHR|NonPrivatePointerKHR",
|
|
"MakePointerVisibleKHR|NonPrivatePointerKHR");
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
struct StrideMissingCase {
|
|
unsigned layout;
|
|
bool useLoadStride;
|
|
bool useStoreStride;
|
|
};
|
|
|
|
using ValidateCoopMatrixStrideMissing =
|
|
spvtest::ValidateBase<StrideMissingCase>;
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
CoopMatrixStrideMissing, ValidateCoopMatrixStrideMissing,
|
|
Values(
|
|
StrideMissingCase{(unsigned)spv::CooperativeMatrixLayout::RowMajorKHR,
|
|
false, true},
|
|
StrideMissingCase{(unsigned)spv::CooperativeMatrixLayout::RowMajorKHR,
|
|
true, false},
|
|
StrideMissingCase{
|
|
(unsigned)spv::CooperativeMatrixLayout::ColumnMajorKHR, false,
|
|
true},
|
|
StrideMissingCase{
|
|
(unsigned)spv::CooperativeMatrixLayout::ColumnMajorKHR, true,
|
|
false}));
|
|
|
|
TEST_P(ValidateCoopMatrixStrideMissing, CoopMatKHRLoadStrideMissingFail) {
|
|
const StrideMissingCase& param = GetParam();
|
|
std::string spirv = GenCoopMatLoadStoreShaderKHR(
|
|
"MakePointerAvailableKHR|NonPrivatePointerKHR",
|
|
"MakePointerVisibleKHR|NonPrivatePointerKHR", param.layout,
|
|
false /*useSpecConstantLayout*/, param.useStoreStride,
|
|
param.useLoadStride);
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("MemoryLayout " + std::to_string(param.layout) +
|
|
" requires a Stride"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatKHRMemoryLayoutFromSpecConstantSuccess) {
|
|
std::string spirv = GenCoopMatLoadStoreShaderKHR(
|
|
"MakePointerAvailableKHR|NonPrivatePointerKHR",
|
|
"MakePointerVisibleKHR|NonPrivatePointerKHR",
|
|
(unsigned)spv::CooperativeMatrixLayout::RowMajorKHR,
|
|
true /*useSpecConstantLayout*/);
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatKHRStoreMemoryAccessFail) {
|
|
std::string spirv = GenCoopMatLoadStoreShaderKHR(
|
|
"MakePointerVisibleKHR|NonPrivatePointerKHR",
|
|
"MakePointerVisibleKHR|NonPrivatePointerKHR");
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("MakePointerVisibleKHR cannot be used with OpStore"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatKHRLoadMemoryAccessFail) {
|
|
std::string spirv = GenCoopMatLoadStoreShaderKHR(
|
|
"MakePointerAvailableKHR|NonPrivatePointerKHR",
|
|
"MakePointerAvailableKHR|NonPrivatePointerKHR");
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("MakePointerAvailableKHR cannot be used with OpLoad"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatKHRInvalidStorageClassFail) {
|
|
const std::string body = R"(
|
|
OpCapability Shader
|
|
OpCapability Float16
|
|
OpCapability CooperativeMatrixKHR
|
|
OpExtension "SPV_KHR_cooperative_matrix"
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%f16 = OpTypeFloat 16
|
|
%u32 = OpTypeInt 32 0
|
|
|
|
%u32_8 = OpConstant %u32 8
|
|
%use_A = OpConstant %u32 0
|
|
%subgroup = OpConstant %u32 3
|
|
|
|
%f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_8 %u32_8 %use_A
|
|
|
|
%str = OpTypeStruct %f16mat
|
|
%str_ptr = OpTypePointer Workgroup %str
|
|
%sh = OpVariable %str_ptr Workgroup
|
|
|
|
%main = OpFunction %void None %func
|
|
%main_entry = OpLabel
|
|
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
CompileSuccessfully(body.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"Cooperative matrix types (or types containing them) can only be "
|
|
"allocated in Function or Private storage classes or as function "
|
|
"parameters"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatMatrixKHRLengthResultTypeBad) {
|
|
const std::string body = R"(
|
|
OpCapability Shader
|
|
OpCapability Float16
|
|
OpCapability CooperativeMatrixKHR
|
|
OpExtension "SPV_KHR_cooperative_matrix"
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%f16 = OpTypeFloat 16
|
|
%u32 = OpTypeInt 32 0
|
|
%i32 = OpTypeInt 32 1
|
|
|
|
%u32_8 = OpConstant %u32 8
|
|
%use_A = OpConstant %u32 0
|
|
%subgroup = OpConstant %u32 3
|
|
|
|
%f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_8 %u32_8 %use_A
|
|
|
|
%main = OpFunction %void None %func
|
|
%main_entry = OpLabel
|
|
|
|
%1 = OpCooperativeMatrixLengthKHR %i32 %f16mat
|
|
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
CompileSuccessfully(body.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("The Result Type of OpCooperativeMatrixLengthKHR <id> "
|
|
"'12[%12]' must be OpTypeInt with width 32 and signedness 0"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatMatrixKHRLengthOperandTypeBad) {
|
|
const std::string body =
|
|
R"(
|
|
OpCapability Shader
|
|
OpCapability Float16
|
|
OpCapability CooperativeMatrixKHR
|
|
OpExtension "SPV_KHR_cooperative_matrix"
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%f16 = OpTypeFloat 16
|
|
%u32 = OpTypeInt 32 0
|
|
%i32 = OpTypeInt 32 1
|
|
|
|
%u32_8 = OpConstant %u32 8
|
|
%use_A = OpConstant %u32 0
|
|
%subgroup = OpConstant %u32 3
|
|
|
|
%f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_8 %u32_8 %use_A
|
|
|
|
%main = OpFunction %void None %func
|
|
%main_entry = OpLabel
|
|
|
|
%1 = OpCooperativeMatrixLengthKHR %u32 %u32
|
|
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
CompileSuccessfully(body.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("The type in OpCooperativeMatrixLengthKHR <id> '5[%uint]' "
|
|
"must be OpTypeCooperativeMatrixKHR"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMatMatrixKHRLengthGood) {
|
|
const std::string body =
|
|
R"(
|
|
OpCapability Shader
|
|
OpCapability Float16
|
|
OpCapability CooperativeMatrixKHR
|
|
OpExtension "SPV_KHR_cooperative_matrix"
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%f16 = OpTypeFloat 16
|
|
%u32 = OpTypeInt 32 0
|
|
%i32 = OpTypeInt 32 1
|
|
|
|
%u32_8 = OpConstant %u32 8
|
|
%use_A = OpConstant %u32 0
|
|
%subgroup = OpConstant %u32 3
|
|
|
|
%f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_8 %u32_8 %use_A
|
|
|
|
%main = OpFunction %void None %func
|
|
%main_entry = OpLabel
|
|
|
|
%1 = OpCooperativeMatrixLengthKHR %u32 %f16mat
|
|
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
CompileSuccessfully(body.c_str());
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAOutsideOfStructBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%sampler_t = OpTypeSampler
|
|
%array_t = OpTypeRuntimeArray %sampler_t
|
|
%array_ptr = OpTypePointer UniformConstant %array_t
|
|
%2 = OpVariable %array_ptr UniformConstant
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"OpVariable, <id> '5[%5]', is attempting to create memory for an "
|
|
"illegal type, OpTypeRuntimeArray.\nFor Vulkan OpTypeRuntimeArray "
|
|
"can only appear as the final member of an OpTypeStruct, thus cannot "
|
|
"be instantiated via OpVariable\n %5 = OpVariable "
|
|
"%_ptr_UniformConstant__runtimearr_2 UniformConstant\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAOutsideOfStructWithRuntimeDescriptorArrayGood) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%sampler_t = OpTypeSampler
|
|
%uint = OpTypeInt 32 0
|
|
%array_t = OpTypeRuntimeArray %sampler_t
|
|
%struct = OpTypeStruct %uint
|
|
%sb_array_t = OpTypeRuntimeArray %struct
|
|
%array_sb_ptr = OpTypePointer StorageBuffer %sb_array_t
|
|
%2 = OpVariable %array_sb_ptr StorageBuffer
|
|
%array_uc_ptr = OpTypePointer UniformConstant %array_t
|
|
%3 = OpVariable %array_uc_ptr UniformConstant
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(
|
|
ValidateMemory,
|
|
VulkanRTAOutsideOfStructWithRuntimeDescriptorArrayAndWrongStorageClassBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%uint_t = OpTypeInt 32 0
|
|
%array_t = OpTypeRuntimeArray %uint_t
|
|
%array_ptr = OpTypePointer Workgroup %array_t
|
|
%2 = OpVariable %array_ptr Workgroup
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("For Vulkan with RuntimeDescriptorArrayEXT, a variable "
|
|
"containing OpTypeRuntimeArray must have storage class of "
|
|
"StorageBuffer, Uniform, or UniformConstant.\n %5 = "
|
|
"OpVariable %_ptr_Workgroup__runtimearr_uint Workgroup\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAInsideStorageBufferStructGood) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %array_t ArrayStride 4
|
|
OpMemberDecorate %struct_t 0 Offset 0
|
|
OpDecorate %struct_t Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%array_t = OpTypeRuntimeArray %uint_t
|
|
%struct_t = OpTypeStruct %array_t
|
|
%struct_ptr = OpTypePointer StorageBuffer %struct_t
|
|
%2 = OpVariable %struct_ptr StorageBuffer
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAInsideWrongStorageClassStructBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %struct_t Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%array_t = OpTypeRuntimeArray %uint_t
|
|
%struct_t = OpTypeStruct %array_t
|
|
%struct_ptr = OpTypePointer Workgroup %struct_t
|
|
%2 = OpVariable %struct_ptr Workgroup
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"For Vulkan, OpTypeStruct variables containing OpTypeRuntimeArray "
|
|
"must have storage class of StorageBuffer, PhysicalStorageBuffer, or "
|
|
"Uniform.\n %6 = "
|
|
"OpVariable %_ptr_Workgroup__struct_2 Workgroup\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAInsideStorageBufferStructWithoutBlockBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %struct_t BufferBlock
|
|
%uint_t = OpTypeInt 32 0
|
|
%array_t = OpTypeRuntimeArray %uint_t
|
|
%struct_t = OpTypeStruct %array_t
|
|
%struct_ptr = OpTypePointer StorageBuffer %struct_t
|
|
%2 = OpVariable %struct_ptr StorageBuffer
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("For Vulkan, an OpTypeStruct variable containing an "
|
|
"OpTypeRuntimeArray must be decorated with Block if it "
|
|
"has storage class StorageBuffer or "
|
|
"PhysicalStorageBuffer.\n %6 = OpVariable "
|
|
"%_ptr_StorageBuffer__struct_2 StorageBuffer\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAInsideUniformStructGood) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %array_t ArrayStride 4
|
|
OpMemberDecorate %struct_t 0 Offset 0
|
|
OpDecorate %struct_t BufferBlock
|
|
%uint_t = OpTypeInt 32 0
|
|
%array_t = OpTypeRuntimeArray %uint_t
|
|
%struct_t = OpTypeStruct %array_t
|
|
%struct_ptr = OpTypePointer Uniform %struct_t
|
|
%2 = OpVariable %struct_ptr Uniform
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAInsideUniformStructWithoutBufferBlockBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %struct_t Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%array_t = OpTypeRuntimeArray %uint_t
|
|
%struct_t = OpTypeStruct %array_t
|
|
%struct_ptr = OpTypePointer Uniform %struct_t
|
|
%2 = OpVariable %struct_ptr Uniform
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("For Vulkan, an OpTypeStruct variable containing an "
|
|
"OpTypeRuntimeArray must be decorated with BufferBlock "
|
|
"if it has storage class Uniform.\n %6 = OpVariable "
|
|
"%_ptr_Uniform__struct_2 Uniform\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAInsideRTABad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%sampler_t = OpTypeSampler
|
|
%inner_array_t = OpTypeRuntimeArray %sampler_t
|
|
%array_t = OpTypeRuntimeArray %inner_array_t
|
|
%array_ptr = OpTypePointer UniformConstant %array_t
|
|
%2 = OpVariable %array_ptr UniformConstant
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"OpTypeRuntimeArray Element Type <id> '3[%_runtimearr_2]' is not "
|
|
"valid in Vulkan environments.\n %_runtimearr__runtimearr_2 = "
|
|
"OpTypeRuntimeArray %_runtimearr_2\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAInsideRTAWithRuntimeDescriptorArrayBad) {
|
|
std::string spirv = R"(
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %struct Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%inner_array_t = OpTypeRuntimeArray %uint_t
|
|
%array_t = OpTypeRuntimeArray %inner_array_t
|
|
%struct = OpTypeStruct %array_t
|
|
%array_ptr = OpTypePointer StorageBuffer %struct
|
|
%2 = OpVariable %array_ptr StorageBuffer
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"OpTypeRuntimeArray Element Type <id> '4[%_runtimearr_uint]' is not "
|
|
"valid in Vulkan environments.\n %_runtimearr__runtimearr_uint = "
|
|
"OpTypeRuntimeArray %_runtimearr_uint\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory,
|
|
VulkanUniformStructInsideRTAWithRuntimeDescriptorArrayGood) {
|
|
std::string spirv = R"(
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %array_t ArrayStride 4
|
|
OpMemberDecorate %struct_t 0 Offset 0
|
|
OpDecorate %struct_t Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%struct_t = OpTypeStruct %uint_t
|
|
%array_t = OpTypeRuntimeArray %struct_t
|
|
%array_ptr = OpTypePointer Uniform %array_t
|
|
%2 = OpVariable %array_ptr Uniform
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAInsideRTAInsideStructBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %array_t ArrayStride 4
|
|
OpMemberDecorate %struct_t 0 Offset 0
|
|
OpDecorate %struct_t Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%inner_array_t = OpTypeRuntimeArray %uint_t
|
|
%array_t = OpTypeRuntimeArray %inner_array_t
|
|
%struct_t = OpTypeStruct %array_t
|
|
%struct_ptr = OpTypePointer StorageBuffer %struct_t
|
|
%2 = OpVariable %struct_ptr StorageBuffer
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"OpTypeRuntimeArray Element Type <id> '5[%_runtimearr_uint]' is not "
|
|
"valid in Vulkan environments.\n %_runtimearr__runtimearr_uint = "
|
|
"OpTypeRuntimeArray %_runtimearr_uint\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory,
|
|
VulkanRTAInsideRTAInsideStructWithRuntimeDescriptorArrayBad) {
|
|
std::string spirv = R"(
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %array_t ArrayStride 4
|
|
OpMemberDecorate %struct_t 0 Offset 0
|
|
OpDecorate %struct_t Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%inner_array_t = OpTypeRuntimeArray %uint_t
|
|
%array_t = OpTypeRuntimeArray %inner_array_t
|
|
%struct_t = OpTypeStruct %array_t
|
|
%struct_ptr = OpTypePointer StorageBuffer %struct_t
|
|
%2 = OpVariable %struct_ptr StorageBuffer
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"OpTypeRuntimeArray Element Type <id> '5[%_runtimearr_uint]' is not "
|
|
"valid in Vulkan environments.\n %_runtimearr__runtimearr_uint = "
|
|
"OpTypeRuntimeArray %_runtimearr_uint\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAInsideArrayBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%uint_t = OpTypeInt 32 0
|
|
%dim = OpConstant %uint_t 1
|
|
%sampler_t = OpTypeSampler
|
|
%inner_array_t = OpTypeRuntimeArray %sampler_t
|
|
%array_t = OpTypeArray %inner_array_t %dim
|
|
%array_ptr = OpTypePointer UniformConstant %array_t
|
|
%2 = OpVariable %array_ptr UniformConstant
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("OpTypeArray Element Type <id> '5[%_runtimearr_4]' is not "
|
|
"valid in Vulkan environments.\n %_arr__runtimearr_4_uint_1 = "
|
|
"OpTypeArray %_runtimearr_4 %uint_1\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAInsideArrayWithRuntimeDescriptorArrayBad) {
|
|
std::string spirv = R"(
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %struct Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%dim = OpConstant %uint_t 1
|
|
%sampler_t = OpTypeSampler
|
|
%inner_array_t = OpTypeRuntimeArray %uint_t
|
|
%array_t = OpTypeRuntimeArray %inner_array_t
|
|
%struct = OpTypeStruct %array_t
|
|
%array_ptr = OpTypePointer StorageBuffer %struct
|
|
%2 = OpVariable %array_ptr StorageBuffer
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"OpTypeRuntimeArray Element Type <id> '6[%_runtimearr_uint]' is not "
|
|
"valid in Vulkan environments.\n %_runtimearr__runtimearr_uint = "
|
|
"OpTypeRuntimeArray %_runtimearr_uint\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAInsideArrayInsideStructBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %array_t ArrayStride 4
|
|
OpMemberDecorate %struct_t 0 Offset 0
|
|
OpDecorate %struct_t Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%dim = OpConstant %uint_t 1
|
|
%inner_array_t = OpTypeRuntimeArray %uint_t
|
|
%array_t = OpTypeArray %inner_array_t %dim
|
|
%struct_t = OpTypeStruct %array_t
|
|
%struct_ptr = OpTypePointer StorageBuffer %struct_t
|
|
%2 = OpVariable %struct_ptr StorageBuffer
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"OpTypeArray Element Type <id> '6[%_runtimearr_uint]' is not "
|
|
"valid in Vulkan environments.\n %_arr__runtimearr_uint_uint_1 "
|
|
"= OpTypeArray %_runtimearr_uint %uint_1\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory,
|
|
VulkanRTAInsideArrayInsideStructWithRuntimeDescriptorArrayBad) {
|
|
std::string spirv = R"(
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %array_t ArrayStride 4
|
|
OpMemberDecorate %struct_t 0 Offset 0
|
|
OpDecorate %struct_t Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%dim = OpConstant %uint_t 1
|
|
%inner_array_t = OpTypeRuntimeArray %uint_t
|
|
%array_t = OpTypeArray %inner_array_t %dim
|
|
%struct_t = OpTypeStruct %array_t
|
|
%struct_ptr = OpTypePointer StorageBuffer %struct_t
|
|
%2 = OpVariable %struct_ptr StorageBuffer
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"OpTypeArray Element Type <id> '6[%_runtimearr_uint]' is not "
|
|
"valid in Vulkan environments.\n %_arr__runtimearr_uint_uint_1 "
|
|
"= OpTypeArray %_runtimearr_uint %uint_1\n"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAStructInsideRTAWithRuntimeDescriptorArrayGood) {
|
|
std::string spirv = R"(
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %inner_array_t ArrayStride 4
|
|
OpDecorate %array_t ArrayStride 4
|
|
OpMemberDecorate %struct_t 0 Offset 0
|
|
OpDecorate %struct_t Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%inner_array_t = OpTypeRuntimeArray %uint_t
|
|
%struct_t = OpTypeStruct %inner_array_t
|
|
%array_t = OpTypeRuntimeArray %struct_t
|
|
%array_ptr = OpTypePointer StorageBuffer %array_t
|
|
%2 = OpVariable %array_ptr StorageBuffer
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanRTAStructInsideArrayGood) {
|
|
std::string spirv = R"(
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpCapability Shader
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
OpDecorate %inner_array_t ArrayStride 4
|
|
OpDecorate %array_t ArrayStride 4
|
|
OpMemberDecorate %struct_t 0 Offset 0
|
|
OpDecorate %struct_t Block
|
|
%uint_t = OpTypeInt 32 0
|
|
%inner_array_t = OpTypeRuntimeArray %uint_t
|
|
%struct_t = OpTypeStruct %inner_array_t
|
|
%array_size = OpConstant %uint_t 5
|
|
%array_t = OpTypeArray %struct_t %array_size
|
|
%array_ptr = OpTypePointer StorageBuffer %array_t
|
|
%2 = OpVariable %array_ptr StorageBuffer
|
|
%void = OpTypeVoid
|
|
%func_t = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_t
|
|
%1 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemoryNoAccessGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_ptr_priv = OpTypePointer Private %int
|
|
%var1 = OpVariable %int_ptr_priv Private
|
|
%var2 = OpVariable %int_ptr_priv Private
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySimpleMixedAccessGood) {
|
|
// Test one memory access operand using features that don't require the
|
|
// Vulkan memory model.
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_ptr_priv = OpTypePointer Private %int
|
|
%var1 = OpVariable %int_ptr_priv Private
|
|
%var2 = OpVariable %int_ptr_priv Private
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2 Volatile|Aligned|Nontemporal 4
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySimpleTwoMixedAccessV13Bad) {
|
|
// Two memory access operands is invalid up to SPIR-V 1.3
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_ptr_priv = OpTypePointer Private %int
|
|
%var1 = OpVariable %int_ptr_priv Private
|
|
%var2 = OpVariable %int_ptr_priv Private
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2 Volatile Volatile
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("CopyMemory with two memory access operands requires "
|
|
"SPIR-V 1.4 or later"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySimpleTwoMixedAccessV14Good) {
|
|
// Two memory access operands is valid in SPIR-V 1.4
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_ptr_priv = OpTypePointer Private %int
|
|
%var1 = OpVariable %int_ptr_priv Private
|
|
%var2 = OpVariable %int_ptr_priv Private
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2 Volatile Volatile
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySizedNoAccessGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability Addresses
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_16 = OpConstant %int 16
|
|
%int_ptr_priv = OpTypePointer Private %int
|
|
%var1 = OpVariable %int_ptr_priv Private
|
|
%var2 = OpVariable %int_ptr_priv Private
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var1 %var2 %int_16
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySizedSimpleMixedAccessGood) {
|
|
// Test one memory access operand using features that don't require the
|
|
// Vulkan memory model.
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability Addresses
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_16 = OpConstant %int 16
|
|
%int_ptr_priv = OpTypePointer Private %int
|
|
%var1 = OpVariable %int_ptr_priv Private
|
|
%var2 = OpVariable %int_ptr_priv Private
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var1 %var2 %int_16 Volatile|Aligned|Nontemporal 4
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySizedSimpleTwoMixedAccessV13Bad) {
|
|
// Two memory access operands is invalid up to SPIR-V 1.3
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability Addresses
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_16 = OpConstant %int 16
|
|
%int_ptr_priv = OpTypePointer Private %int
|
|
%var1 = OpVariable %int_ptr_priv Private
|
|
%var2 = OpVariable %int_ptr_priv Private
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var1 %var2 %int_16 Volatile Volatile
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("CopyMemorySized with two memory access operands requires "
|
|
"SPIR-V 1.4 or later"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySizedSimpleTwoMixedAccessV14Good) {
|
|
// Two memory access operands is valid in SPIR-V 1.4
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability Addresses
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_16 = OpConstant %int 16
|
|
%int_ptr_priv = OpTypePointer Private %int
|
|
%var1 = OpVariable %int_ptr_priv Private
|
|
%var2 = OpVariable %int_ptr_priv Private
|
|
%voidfn = OpTypeFunction %void
|
|
%func = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var1 %var2 %int_16 Volatile Volatile
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
|
}
|
|
|
|
using ValidatePointerComparisons = spvtest::ValidateBase<std::string>;
|
|
|
|
TEST_P(ValidatePointerComparisons, Good) {
|
|
const std::string operation = GetParam();
|
|
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability VariablePointersStorageBuffer
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%int = OpTypeInt 32 0
|
|
%ptr_int = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %ptr_int StorageBuffer
|
|
%func_ty = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_ty
|
|
%1 = OpLabel
|
|
%equal = )" + operation;
|
|
|
|
if (operation == "OpPtrDiff") {
|
|
spirv += " %int ";
|
|
} else {
|
|
spirv += " %bool ";
|
|
}
|
|
|
|
spirv += R"(%var %var
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
}
|
|
|
|
TEST_P(ValidatePointerComparisons, GoodWorkgroup) {
|
|
const std::string operation = GetParam();
|
|
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability VariablePointers
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%int = OpTypeInt 32 0
|
|
%ptr_int = OpTypePointer Workgroup %int
|
|
%var = OpVariable %ptr_int Workgroup
|
|
%func_ty = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_ty
|
|
%1 = OpLabel
|
|
%equal = )" + operation;
|
|
|
|
if (operation == "OpPtrDiff") {
|
|
spirv += " %int ";
|
|
} else {
|
|
spirv += " %bool ";
|
|
}
|
|
|
|
spirv += R"(%var %var
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
}
|
|
|
|
TEST_P(ValidatePointerComparisons, BadResultType) {
|
|
const std::string operation = GetParam();
|
|
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability VariablePointersStorageBuffer
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%int = OpTypeInt 32 0
|
|
%ptr_int = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %ptr_int StorageBuffer
|
|
%func_ty = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_ty
|
|
%1 = OpLabel
|
|
%equal = )" + operation;
|
|
|
|
if (operation == "OpPtrDiff") {
|
|
spirv += " %bool ";
|
|
} else {
|
|
spirv += " %int ";
|
|
}
|
|
|
|
spirv += R"(%var %var
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
if (operation == "OpPtrDiff") {
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Result Type must be an integer scalar"));
|
|
} else {
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Result Type must be OpTypeBool"));
|
|
}
|
|
}
|
|
|
|
TEST_P(ValidatePointerComparisons, BadCapabilities) {
|
|
const std::string operation = GetParam();
|
|
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%int = OpTypeInt 32 0
|
|
%ptr_int = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %ptr_int StorageBuffer
|
|
%func_ty = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_ty
|
|
%1 = OpLabel
|
|
%equal = )" + operation;
|
|
|
|
if (operation == "OpPtrDiff") {
|
|
spirv += " %int ";
|
|
} else {
|
|
spirv += " %bool ";
|
|
}
|
|
|
|
spirv += R"(%var %var
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
if (operation == "OpPtrDiff") {
|
|
// Gets caught by the grammar.
|
|
EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
} else {
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Instruction cannot for logical addressing model be "
|
|
"used without a variable pointers capability"));
|
|
}
|
|
}
|
|
|
|
TEST_P(ValidatePointerComparisons, BadOperandType) {
|
|
const std::string operation = GetParam();
|
|
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability VariablePointersStorageBuffer
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%int = OpTypeInt 32 0
|
|
%ptr_int = OpTypePointer StorageBuffer %int
|
|
%var = OpVariable %ptr_int StorageBuffer
|
|
%func_ty = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_ty
|
|
%1 = OpLabel
|
|
%ld = OpLoad %int %var
|
|
%equal = )" + operation;
|
|
|
|
if (operation == "OpPtrDiff") {
|
|
spirv += " %int ";
|
|
} else {
|
|
spirv += " %bool ";
|
|
}
|
|
|
|
spirv += R"(%ld %ld
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Operand type must be a pointer"));
|
|
}
|
|
|
|
TEST_P(ValidatePointerComparisons, BadStorageClassWorkgroup) {
|
|
const std::string operation = GetParam();
|
|
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability VariablePointersStorageBuffer
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%int = OpTypeInt 32 0
|
|
%ptr_int = OpTypePointer Workgroup %int
|
|
%var = OpVariable %ptr_int Workgroup
|
|
%func_ty = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_ty
|
|
%1 = OpLabel
|
|
%equal = )" + operation;
|
|
|
|
if (operation == "OpPtrDiff") {
|
|
spirv += " %int ";
|
|
} else {
|
|
spirv += " %bool ";
|
|
}
|
|
|
|
spirv += R"(%var %var
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Workgroup storage class pointer requires "
|
|
"VariablePointers capability to be specified"));
|
|
}
|
|
|
|
TEST_P(ValidatePointerComparisons, BadStorageClass) {
|
|
const std::string operation = GetParam();
|
|
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability VariablePointersStorageBuffer
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%int = OpTypeInt 32 0
|
|
%ptr_int = OpTypePointer Private %int
|
|
%var = OpVariable %ptr_int Private
|
|
%func_ty = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_ty
|
|
%1 = OpLabel
|
|
%equal = )" + operation;
|
|
|
|
if (operation == "OpPtrDiff") {
|
|
spirv += " %int ";
|
|
} else {
|
|
spirv += " %bool ";
|
|
}
|
|
|
|
spirv += R"(%var %var
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Invalid pointer storage class"));
|
|
}
|
|
|
|
TEST_P(ValidatePointerComparisons, BadDiffOperandTypes) {
|
|
const std::string operation = GetParam();
|
|
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability VariablePointersStorageBuffer
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%int = OpTypeInt 32 0
|
|
%ptr_int = OpTypePointer Private %int
|
|
%var = OpVariable %ptr_int Private
|
|
%func_ty = OpTypeFunction %void
|
|
%func = OpFunction %void None %func_ty
|
|
%1 = OpLabel
|
|
%ld = OpLoad %int %var
|
|
%equal = )" + operation;
|
|
|
|
if (operation == "OpPtrDiff") {
|
|
spirv += " %int ";
|
|
} else {
|
|
spirv += " %bool ";
|
|
}
|
|
|
|
spirv += R"(%var %ld
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("The types of Operand 1 and Operand 2 must match"));
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(PointerComparisons, ValidatePointerComparisons,
|
|
Values("OpPtrEqual", "OpPtrNotEqual", "OpPtrDiff"));
|
|
|
|
TEST_F(ValidateMemory, VariableInitializerWrongType) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability VariablePointersStorageBuffer
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%float = OpTypeFloat 32
|
|
%ptr_wg_int = OpTypePointer Workgroup %int
|
|
%ptr_wg_float = OpTypePointer Workgroup %int
|
|
%wg_var = OpVariable %ptr_wg_int Workgroup
|
|
%ptr_private_wg_float = OpTypePointer Private %ptr_wg_float
|
|
%priv_var = OpVariable %ptr_private_wg_float Private %wg_var
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Initializer type must match the data type"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, StoreToImage) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%img = OpTypeImage %int 2D 2 0 0 2 R32i
|
|
%ptr_img = OpTypePointer Function %img
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr_img Function
|
|
%value = OpLoad %img %var
|
|
OpStore %var %value
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeImage-06924"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Cannot store to OpTypeImage, OpTypeSampler, "
|
|
"OpTypeSampledImage, or OpTypeAccelerationStructureKHR"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, StoreToImageArray) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%img = OpTypeImage %int 2D 2 0 0 2 R32i
|
|
%arr_size = OpConstant %int 5
|
|
%i = OpConstant %int 2
|
|
%arr_img = OpTypeArray %img %arr_size
|
|
%ptr_img = OpTypePointer Function %img
|
|
%ptr_arr_img = OpTypePointer Function %arr_img
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr_arr_img Function
|
|
%value = OpLoad %arr_img %var
|
|
OpStore %var %value
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeImage-06924"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Cannot store to OpTypeImage, OpTypeSampler, "
|
|
"OpTypeSampledImage, or OpTypeAccelerationStructureKHR"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, StoreToSampler) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%void = OpTypeVoid
|
|
%smp = OpTypeSampler
|
|
%ptr_smp = OpTypePointer Function %smp
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr_smp Function
|
|
%value = OpLoad %smp %var
|
|
OpStore %var %value
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeImage-06924"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Cannot store to OpTypeImage, OpTypeSampler, "
|
|
"OpTypeSampledImage, or OpTypeAccelerationStructureKHR"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, StoreToSampledImage) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%img = OpTypeImage %int 2D 2 0 0 1 R32i
|
|
%samp_img = OpTypeSampledImage %img
|
|
%ptr_samp_img = OpTypePointer Function %samp_img
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr_samp_img Function
|
|
%value = OpLoad %samp_img %var
|
|
OpStore %var %value
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeImage-06924"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Cannot store to OpTypeImage, OpTypeSampler, "
|
|
"OpTypeSampledImage, or OpTypeAccelerationStructureKHR"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, StoreToAccelarationStructureKHR) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability RayQueryKHR
|
|
OpExtension "SPV_KHR_ray_query"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%void = OpTypeVoid
|
|
%as = OpTypeAccelerationStructureKHR
|
|
%ptr_as = OpTypePointer Function %as
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr_as Function
|
|
%value = OpLoad %as %var
|
|
OpStore %var %value
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-OpTypeImage-06924"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Cannot store to OpTypeImage, OpTypeSampler, "
|
|
"OpTypeSampledImage, or OpTypeAccelerationStructureKHR"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, StoreToUniformBlock) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%int4 = OpTypeVector %int 4
|
|
%struct = OpTypeStruct %int4
|
|
%ptr_uniform_struct = OpTypePointer Uniform %struct
|
|
%ptr_uniform_int4 = OpTypePointer Uniform %int4
|
|
%ptr_uniform_int = OpTypePointer Uniform %int
|
|
%var = OpVariable %ptr_uniform_struct Uniform
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
|
|
%gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
|
|
OpStore %gep2 %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, StoreToUniformBlockVulkan) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%int4 = OpTypeVector %int 4
|
|
%struct = OpTypeStruct %int4
|
|
%ptr_uniform_struct = OpTypePointer Uniform %struct
|
|
%ptr_uniform_int4 = OpTypePointer Uniform %int4
|
|
%ptr_uniform_int = OpTypePointer Uniform %int
|
|
%var = OpVariable %ptr_uniform_struct Uniform
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
|
|
%gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
|
|
OpStore %gep2 %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
|
|
}
|
|
|
|
// This test requires that the struct is not id 2.
|
|
TEST_F(ValidateMemory, StoreToUniformBlockVulkan2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %gid_var
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %3 Block
|
|
OpMemberDecorate %3 0 Offset 0
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %gid_var BuiltIn GlobalInvocationId
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%int3 = OpTypeVector %int 3
|
|
%int4 = OpTypeVector %int 4
|
|
%3 = OpTypeStruct %int4
|
|
%ptr_uniform_struct = OpTypePointer Uniform %3
|
|
%ptr_uniform_int4 = OpTypePointer Uniform %int4
|
|
%ptr_uniform_int = OpTypePointer Uniform %int
|
|
%var = OpVariable %ptr_uniform_struct Uniform
|
|
%ptr_input_int3 = OpTypePointer Input %int3
|
|
%gid_var = OpVariable %ptr_input_int3 Input
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
|
|
%gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
|
|
OpStore %gep2 %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, StoreToUniformBufferBlockVulkan) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %struct BufferBlock
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%int4 = OpTypeVector %int 4
|
|
%struct = OpTypeStruct %int4
|
|
%ptr_uniform_struct = OpTypePointer Uniform %struct
|
|
%ptr_uniform_int4 = OpTypePointer Uniform %int4
|
|
%ptr_uniform_int = OpTypePointer Uniform %int
|
|
%var = OpVariable %ptr_uniform_struct Uniform
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
|
|
%gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
|
|
OpStore %gep2 %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, StoreToUniformBlockVulkanArray) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%int_1 = OpConstant %int 1
|
|
%int4 = OpTypeVector %int 4
|
|
%struct = OpTypeStruct %int4
|
|
%array_struct = OpTypeArray %struct %int_1
|
|
%ptr_uniform_array = OpTypePointer Uniform %array_struct
|
|
%ptr_uniform_struct = OpTypePointer Uniform %struct
|
|
%ptr_uniform_int4 = OpTypePointer Uniform %int4
|
|
%ptr_uniform_int = OpTypePointer Uniform %int
|
|
%var = OpVariable %ptr_uniform_array Uniform
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep1 = OpAccessChain %ptr_uniform_int %var %int_0 %int_0 %int_0
|
|
%gep2 = OpCopyObject %ptr_uniform_int %gep1
|
|
OpStore %gep2 %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
|
|
}
|
|
|
|
// This test requires that the struct is not id 2.
|
|
TEST_F(ValidateMemory, StoreToUniformBlockVulkanArray2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %gid_var
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %gid_var BuiltIn GlobalInvocationId
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%int_1 = OpConstant %int 1
|
|
%int3 = OpTypeVector %int 3
|
|
%int4 = OpTypeVector %int 4
|
|
%struct = OpTypeStruct %int4
|
|
%array_struct = OpTypeArray %struct %int_1
|
|
%ptr_uniform_array = OpTypePointer Uniform %array_struct
|
|
%ptr_uniform_struct = OpTypePointer Uniform %struct
|
|
%ptr_uniform_int4 = OpTypePointer Uniform %int4
|
|
%ptr_uniform_int = OpTypePointer Uniform %int
|
|
%var = OpVariable %ptr_uniform_array Uniform
|
|
%ptr_input_int3 = OpTypePointer Input %int3
|
|
%gid_var = OpVariable %ptr_input_int3 Input
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep1 = OpAccessChain %ptr_uniform_int %var %int_0 %int_0 %int_0
|
|
%gep2 = OpCopyObject %ptr_uniform_int %gep1
|
|
OpStore %gep2 %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, StoreToUniformBlockVulkanRuntimeArray) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%int4 = OpTypeVector %int 4
|
|
%struct = OpTypeStruct %int4
|
|
%array_struct = OpTypeRuntimeArray %struct
|
|
%ptr_uniform_array = OpTypePointer Uniform %array_struct
|
|
%ptr_uniform_struct = OpTypePointer Uniform %struct
|
|
%ptr_uniform_int4 = OpTypePointer Uniform %int4
|
|
%ptr_uniform_int = OpTypePointer Uniform %int
|
|
%var = OpVariable %ptr_uniform_array Uniform
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0 %int_0
|
|
%gep2 = OpInBoundsAccessChain %ptr_uniform_int %gep1 %int_0
|
|
OpStore %gep2 %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
|
|
}
|
|
|
|
using ValidateSizedVariable = spvtest::ValidateBase<
|
|
std::tuple<std::string, std::string, std::string, spv_target_env>>;
|
|
|
|
CodeGenerator GetSizedVariableCodeGenerator(bool is_8bit, bool buffer_block) {
|
|
CodeGenerator generator;
|
|
generator.capabilities_ = "OpCapability Shader\nOpCapability Linkage\n";
|
|
generator.extensions_ =
|
|
"OpExtension \"SPV_KHR_16bit_storage\"\nOpExtension "
|
|
"\"SPV_KHR_8bit_storage\"\n";
|
|
generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
|
|
if (is_8bit) {
|
|
generator.before_types_ =
|
|
"OpMemberDecorate %char_buffer_block 0 Offset 0\n";
|
|
if (buffer_block)
|
|
generator.before_types_ += "OpDecorate %char_buffer_block BufferBlock\n";
|
|
|
|
generator.types_ = R"(%void = OpTypeVoid
|
|
%char = OpTypeInt 8 0
|
|
%char4 = OpTypeVector %char 4
|
|
%char_buffer_block = OpTypeStruct %char
|
|
)";
|
|
} else {
|
|
generator.before_types_ =
|
|
"OpMemberDecorate %half_buffer_block 0 Offset 0\n"
|
|
"OpMemberDecorate %short_buffer_block 0 Offset 0\n";
|
|
if (buffer_block) {
|
|
generator.before_types_ +=
|
|
"OpDecorate %half_buffer_block BufferBlock\n"
|
|
"OpDecorate %short_buffer_block BufferBlock\n";
|
|
}
|
|
|
|
generator.types_ = R"(%void = OpTypeVoid
|
|
%short = OpTypeInt 16 0
|
|
%half = OpTypeFloat 16
|
|
%short4 = OpTypeVector %short 4
|
|
%half4 = OpTypeVector %half 4
|
|
%mat4x4 = OpTypeMatrix %half4 4
|
|
%short_buffer_block = OpTypeStruct %short
|
|
%half_buffer_block = OpTypeStruct %half
|
|
)";
|
|
}
|
|
generator.after_types_ = R"(%void_fn = OpTypeFunction %void
|
|
%func = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
)";
|
|
generator.add_at_the_end_ = "OpReturn\nOpFunctionEnd\n";
|
|
return generator;
|
|
}
|
|
|
|
TEST_P(ValidateSizedVariable, Capability) {
|
|
const std::string storage_class = std::get<0>(GetParam());
|
|
const std::string capability = std::get<1>(GetParam());
|
|
const std::string var_type = std::get<2>(GetParam());
|
|
const spv_target_env target = std::get<3>(GetParam());
|
|
|
|
ASSERT_TRUE(target == SPV_ENV_UNIVERSAL_1_3 ||
|
|
target == SPV_ENV_UNIVERSAL_1_4);
|
|
|
|
bool type_8bit = false;
|
|
if (var_type == "%char" || var_type == "%char4" ||
|
|
var_type == "%char_buffer_block") {
|
|
type_8bit = true;
|
|
}
|
|
|
|
const bool buffer_block = var_type.find("buffer_block") != std::string::npos;
|
|
|
|
auto generator = GetSizedVariableCodeGenerator(type_8bit, buffer_block);
|
|
|
|
if (capability == "WorkgroupMemoryExplicitLayout8BitAccessKHR" ||
|
|
capability == "WorkgroupMemoryExplicitLayout16BitAccessKHR") {
|
|
generator.extensions_ +=
|
|
"OpExtension \"SPV_KHR_workgroup_memory_explicit_layout\"\n";
|
|
}
|
|
|
|
generator.types_ += "%ptr_type = OpTypePointer " + storage_class + " " +
|
|
var_type + "\n%var = OpVariable %ptr_type " +
|
|
storage_class + "\n";
|
|
generator.capabilities_ += "OpCapability " + capability + "\n";
|
|
|
|
bool capability_ok = false;
|
|
bool storage_class_ok = false;
|
|
if (storage_class == "Input" || storage_class == "Output") {
|
|
if (!type_8bit) {
|
|
capability_ok = capability == "StorageInputOutput16";
|
|
storage_class_ok = true;
|
|
}
|
|
} else if (storage_class == "StorageBuffer") {
|
|
if (type_8bit) {
|
|
capability_ok = capability == "StorageBuffer8BitAccess" ||
|
|
capability == "UniformAndStorageBuffer8BitAccess";
|
|
} else {
|
|
capability_ok = capability == "StorageBuffer16BitAccess" ||
|
|
capability == "UniformAndStorageBuffer16BitAccess";
|
|
}
|
|
storage_class_ok = true;
|
|
} else if (storage_class == "PushConstant") {
|
|
if (type_8bit) {
|
|
capability_ok = capability == "StoragePushConstant8";
|
|
} else {
|
|
capability_ok = capability == "StoragePushConstant16";
|
|
}
|
|
storage_class_ok = true;
|
|
} else if (storage_class == "Uniform") {
|
|
if (type_8bit) {
|
|
capability_ok = capability == "UniformAndStorageBuffer8BitAccess" ||
|
|
(capability == "StorageBuffer8BitAccess" && buffer_block);
|
|
} else {
|
|
capability_ok =
|
|
capability == "UniformAndStorageBuffer16BitAccess" ||
|
|
(capability == "StorageBuffer16BitAccess" && buffer_block);
|
|
}
|
|
storage_class_ok = true;
|
|
} else if (storage_class == "Workgroup") {
|
|
if (type_8bit) {
|
|
capability_ok =
|
|
capability == "WorkgroupMemoryExplicitLayout8BitAccessKHR";
|
|
} else {
|
|
capability_ok =
|
|
capability == "WorkgroupMemoryExplicitLayout16BitAccessKHR";
|
|
}
|
|
storage_class_ok = true;
|
|
}
|
|
|
|
CompileSuccessfully(generator.Build(), target);
|
|
spv_result_t result = ValidateInstructions(target);
|
|
if (target < SPV_ENV_UNIVERSAL_1_4 &&
|
|
(capability == "WorkgroupMemoryExplicitLayout8BitAccessKHR" ||
|
|
capability == "WorkgroupMemoryExplicitLayout16BitAccessKHR")) {
|
|
EXPECT_EQ(SPV_ERROR_WRONG_VERSION, result);
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("requires SPIR-V version 1.4 or later"));
|
|
} else if (buffer_block && target > SPV_ENV_UNIVERSAL_1_3) {
|
|
EXPECT_EQ(SPV_ERROR_WRONG_VERSION, result);
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("requires SPIR-V version 1.3 or earlier"));
|
|
} else if (capability_ok) {
|
|
EXPECT_EQ(SPV_SUCCESS, result);
|
|
} else {
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, result);
|
|
if (storage_class_ok) {
|
|
std::string message = std::string("Allocating a variable containing a ") +
|
|
(type_8bit ? "8" : "16") + "-bit element in " +
|
|
storage_class +
|
|
" storage class requires an additional capability";
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr(message));
|
|
} else {
|
|
std::string message =
|
|
std::string("Cannot allocate a variable containing a ") +
|
|
(type_8bit ? "8" : "16") + "-bit type in " + storage_class +
|
|
" storage class";
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr(message));
|
|
}
|
|
}
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
Storage8, ValidateSizedVariable,
|
|
Combine(Values("UniformConstant", "Input", "Output", "Workgroup",
|
|
"CrossWorkgroup", "Private", "StorageBuffer", "Uniform"),
|
|
Values("StorageBuffer8BitAccess",
|
|
"UniformAndStorageBuffer8BitAccess", "StoragePushConstant8",
|
|
"WorkgroupMemoryExplicitLayout8BitAccessKHR"),
|
|
Values("%char", "%char4", "%char_buffer_block"),
|
|
Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4)));
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
Storage16, ValidateSizedVariable,
|
|
Combine(Values("UniformConstant", "Input", "Output", "Workgroup",
|
|
"CrossWorkgroup", "Private", "StorageBuffer", "Uniform"),
|
|
Values("StorageBuffer16BitAccess",
|
|
"UniformAndStorageBuffer16BitAccess",
|
|
"StoragePushConstant16", "StorageInputOutput16",
|
|
"WorkgroupMemoryExplicitLayout16BitAccessKHR"),
|
|
Values("%short", "%half", "%short4", "%half4", "%mat4x4",
|
|
"%short_buffer_block", "%half_buffer_block"),
|
|
Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4)));
|
|
|
|
using ValidateSizedLoadStore =
|
|
spvtest::ValidateBase<std::tuple<std::string, uint32_t, std::string>>;
|
|
|
|
CodeGenerator GetSizedLoadStoreCodeGenerator(const std::string& base_type,
|
|
uint32_t width) {
|
|
CodeGenerator generator;
|
|
generator.capabilities_ = "OpCapability Shader\nOpCapability Linkage\n";
|
|
if (width == 8) {
|
|
generator.capabilities_ +=
|
|
"OpCapability UniformAndStorageBuffer8BitAccess\n";
|
|
generator.extensions_ = "OpExtension \"SPV_KHR_8bit_storage\"\n";
|
|
} else {
|
|
generator.capabilities_ +=
|
|
"OpCapability UniformAndStorageBuffer16BitAccess\n";
|
|
generator.extensions_ = "OpExtension \"SPV_KHR_16bit_storage\"\n";
|
|
}
|
|
generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
|
|
generator.before_types_ = R"(OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
)";
|
|
generator.types_ = R"(%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%int_1 = OpConstant %int 1
|
|
%int_2 = OpConstant %int 2
|
|
%int_3 = OpConstant %int 3
|
|
)";
|
|
|
|
if (width == 8) {
|
|
generator.types_ += R"(%scalar = OpTypeInt 8 0
|
|
%vector = OpTypeVector %scalar 4
|
|
%struct = OpTypeStruct %vector
|
|
)";
|
|
} else if (base_type == "int") {
|
|
generator.types_ += R"(%scalar = OpTypeInt 16 0
|
|
%vector = OpTypeVector %scalar 4
|
|
%struct = OpTypeStruct %vector
|
|
)";
|
|
} else {
|
|
generator.types_ += R"(%scalar = OpTypeFloat 16
|
|
%vector = OpTypeVector %scalar 4
|
|
%matrix = OpTypeMatrix %vector 4
|
|
%struct = OpTypeStruct %matrix
|
|
%ptr_ssbo_matrix = OpTypePointer StorageBuffer %matrix
|
|
)";
|
|
generator.before_types_ += R"(OpMemberDecorate %struct 0 RowMajor
|
|
OpMemberDecorate %struct 0 MatrixStride 16
|
|
)";
|
|
}
|
|
generator.types_ += R"(%block = OpTypeStruct %struct
|
|
%ptr_ssbo_block = OpTypePointer StorageBuffer %block
|
|
%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
|
|
%ptr_ssbo_vector = OpTypePointer StorageBuffer %vector
|
|
%ptr_ssbo_scalar = OpTypePointer StorageBuffer %scalar
|
|
%ld_var = OpVariable %ptr_ssbo_block StorageBuffer
|
|
%st_var = OpVariable %ptr_ssbo_block StorageBuffer
|
|
)";
|
|
|
|
generator.after_types_ = R"(%void_fn = OpTypeFunction %void
|
|
%func = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
)";
|
|
generator.add_at_the_end_ = "OpReturn\nOpFunctionEnd\n";
|
|
return generator;
|
|
}
|
|
|
|
TEST_P(ValidateSizedLoadStore, Load) {
|
|
std::string base_type = std::get<0>(GetParam());
|
|
uint32_t width = std::get<1>(GetParam());
|
|
std::string mem_type = std::get<2>(GetParam());
|
|
|
|
CodeGenerator generator = GetSizedLoadStoreCodeGenerator(base_type, width);
|
|
generator.after_types_ +=
|
|
"%ld_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %ld_var %int_0";
|
|
if (mem_type != "struct") {
|
|
generator.after_types_ += " %int_0";
|
|
if (mem_type != "matrix" && base_type == "float") {
|
|
generator.after_types_ += " %int_0";
|
|
}
|
|
if (mem_type == "scalar") {
|
|
generator.after_types_ += " %int_0";
|
|
}
|
|
}
|
|
generator.after_types_ += "\n";
|
|
generator.after_types_ += "%ld = OpLoad %" + mem_type + " %ld_gep\n";
|
|
|
|
CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
|
|
if (mem_type == "struct") {
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"8- or 16-bit loads must be a scalar, vector or matrix type"));
|
|
} else {
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
}
|
|
|
|
TEST_P(ValidateSizedLoadStore, Store) {
|
|
std::string base_type = std::get<0>(GetParam());
|
|
uint32_t width = std::get<1>(GetParam());
|
|
std::string mem_type = std::get<2>(GetParam());
|
|
|
|
CodeGenerator generator = GetSizedLoadStoreCodeGenerator(base_type, width);
|
|
generator.after_types_ +=
|
|
"%ld_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %ld_var %int_0";
|
|
if (mem_type != "struct") {
|
|
generator.after_types_ += " %int_0";
|
|
if (mem_type != "matrix" && base_type == "float") {
|
|
generator.after_types_ += " %int_0";
|
|
}
|
|
if (mem_type == "scalar") {
|
|
generator.after_types_ += " %int_0";
|
|
}
|
|
}
|
|
generator.after_types_ += "\n";
|
|
generator.after_types_ += "%ld = OpLoad %" + mem_type + " %ld_gep\n";
|
|
generator.after_types_ +=
|
|
"%st_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %st_var %int_0";
|
|
if (mem_type != "struct") {
|
|
generator.after_types_ += " %int_0";
|
|
if (mem_type != "matrix" && base_type == "float") {
|
|
generator.after_types_ += " %int_0";
|
|
}
|
|
if (mem_type == "scalar") {
|
|
generator.after_types_ += " %int_0";
|
|
}
|
|
}
|
|
generator.after_types_ += "\n";
|
|
generator.after_types_ += "OpStore %st_gep %ld\n";
|
|
|
|
CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
|
|
if (mem_type == "struct") {
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
// Can only catch the load.
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"8- or 16-bit loads must be a scalar, vector or matrix type"));
|
|
} else {
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(LoadStoreInt8, ValidateSizedLoadStore,
|
|
Combine(Values("int"), Values(8u),
|
|
Values("scalar", "vector", "struct")));
|
|
INSTANTIATE_TEST_SUITE_P(LoadStoreInt16, ValidateSizedLoadStore,
|
|
Combine(Values("int"), Values(16u),
|
|
Values("scalar", "vector", "struct")));
|
|
INSTANTIATE_TEST_SUITE_P(LoadStoreFloat16, ValidateSizedLoadStore,
|
|
Combine(Values("float"), Values(16u),
|
|
Values("scalar", "vector", "matrix",
|
|
"struct")));
|
|
|
|
TEST_F(ValidateMemory, SmallStorageCopyMemoryChar) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UniformAndStorageBuffer8BitAccess
|
|
OpExtension "SPV_KHR_8bit_storage"
|
|
OpMemoryModel Logical GLSL450
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%char = OpTypeInt 8 0
|
|
%block = OpTypeStruct %char
|
|
%ptr_ssbo_block = OpTypePointer StorageBuffer %block
|
|
%in = OpVariable %ptr_ssbo_block StorageBuffer
|
|
%out = OpVariable %ptr_ssbo_block StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%func = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpCopyMemory %out %in
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, SmallStorageCopyMemoryShort) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UniformAndStorageBuffer16BitAccess
|
|
OpExtension "SPV_KHR_16bit_storage"
|
|
OpMemoryModel Logical GLSL450
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%short = OpTypeInt 16 0
|
|
%block = OpTypeStruct %short
|
|
%ptr_ssbo_block = OpTypePointer StorageBuffer %block
|
|
%in = OpVariable %ptr_ssbo_block StorageBuffer
|
|
%out = OpVariable %ptr_ssbo_block StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%func = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpCopyMemory %out %in
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, SmallStorageCopyMemoryHalf) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UniformAndStorageBuffer16BitAccess
|
|
OpExtension "SPV_KHR_16bit_storage"
|
|
OpMemoryModel Logical GLSL450
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%half = OpTypeFloat 16
|
|
%block = OpTypeStruct %half
|
|
%ptr_ssbo_block = OpTypePointer StorageBuffer %block
|
|
%in = OpVariable %ptr_ssbo_block StorageBuffer
|
|
%out = OpVariable %ptr_ssbo_block StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%func = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpCopyMemory %out %in
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockShort) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability StorageBuffer16BitAccess
|
|
OpExtension "SPV_KHR_16bit_storage"
|
|
OpMemoryModel Logical GLSL450
|
|
OpDecorate %block BufferBlock
|
|
OpMemberDecorate %block 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%short = OpTypeInt 16 0
|
|
%int = OpTypeInt 32 0
|
|
%int_4 = OpConstant %int 4
|
|
%block = OpTypeStruct %short
|
|
%block_array = OpTypeArray %block %int_4
|
|
%ptr_block_array = OpTypePointer Uniform %block_array
|
|
%var = OpVariable %ptr_block_array Uniform
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockChar) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability StorageBuffer8BitAccess
|
|
OpExtension "SPV_KHR_8bit_storage"
|
|
OpMemoryModel Logical GLSL450
|
|
OpDecorate %block BufferBlock
|
|
OpMemberDecorate %block 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%char = OpTypeInt 8 0
|
|
%int = OpTypeInt 32 0
|
|
%int_4 = OpConstant %int 4
|
|
%block = OpTypeStruct %char
|
|
%block_array = OpTypeArray %block %int_4
|
|
%ptr_block_array = OpTypePointer Uniform %block_array
|
|
%var = OpVariable %ptr_block_array Uniform
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockHalf) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability StorageBuffer16BitAccess
|
|
OpExtension "SPV_KHR_16bit_storage"
|
|
OpMemoryModel Logical GLSL450
|
|
OpDecorate %block BufferBlock
|
|
OpMemberDecorate %block 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%half = OpTypeFloat 16
|
|
%int = OpTypeInt 32 0
|
|
%int_4 = OpConstant %int 4
|
|
%block = OpTypeStruct %half
|
|
%block_array = OpTypeArray %block %int_4
|
|
%ptr_block_array = OpTypePointer Uniform %block_array
|
|
%var = OpVariable %ptr_block_array Uniform
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanStorageBufferNotAStruct) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%void = OpTypeVoid
|
|
%uint = OpTypeInt 32 0
|
|
%ptr_ssbo = OpTypePointer StorageBuffer %uint
|
|
%var = OpVariable %ptr_ssbo StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("From Vulkan spec:\nVariables identified with "
|
|
"the StorageBuffer storage class are used to access "
|
|
"transparent buffer backed resources. Such variables must be "
|
|
"typed as OpTypeStruct, or an array of this type"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanStorageBufferRuntimeArrayNotAStruct) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability RuntimeDescriptorArrayEXT
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_EXT_descriptor_indexing"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%void = OpTypeVoid
|
|
%uint = OpTypeInt 32 0
|
|
%array = OpTypeRuntimeArray %uint
|
|
%ptr_ssbo = OpTypePointer StorageBuffer %array
|
|
%var = OpVariable %ptr_ssbo StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("From Vulkan spec:\nVariables identified with "
|
|
"the StorageBuffer storage class are used to access "
|
|
"transparent buffer backed resources. Such variables must be "
|
|
"typed as OpTypeStruct, or an array of this type"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanStorageBufferArrayNotAStruct) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%void = OpTypeVoid
|
|
%uint = OpTypeInt 32 0
|
|
%uint_4 = OpConstant %uint 4
|
|
%array = OpTypeArray %uint %uint_4
|
|
%ptr_ssbo = OpTypePointer StorageBuffer %array
|
|
%var = OpVariable %ptr_ssbo StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("From Vulkan spec:\nVariables identified with "
|
|
"the StorageBuffer storage class are used to access "
|
|
"transparent buffer backed resources. Such variables must be "
|
|
"typed as OpTypeStruct, or an array of this type"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanInvariantOutputSuccess) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main" %var
|
|
OpDecorate %var Location 0
|
|
OpDecorate %var Invariant
|
|
%void = OpTypeVoid
|
|
%f32 = OpTypeFloat 32
|
|
%ptr_output = OpTypePointer Output %f32
|
|
%var = OpVariable %ptr_output Output
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanInvariantInputStructSuccess) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %main "main" %var
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpDecorate %var Location 0
|
|
OpMemberDecorate %struct 1 Invariant
|
|
%void = OpTypeVoid
|
|
%f32 = OpTypeFloat 32
|
|
%struct = OpTypeStruct %f32 %f32
|
|
%ptr_input = OpTypePointer Input %struct
|
|
%var = OpVariable %ptr_input Input
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanInvariantWrongStorageClass) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main"
|
|
OpDecorate %var Invariant
|
|
%void = OpTypeVoid
|
|
%f32 = OpTypeFloat 32
|
|
%ptr_private = OpTypePointer Private %f32
|
|
%var = OpVariable %ptr_private Private
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Invariant-04677"));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"Variable decorated with Invariant must only be identified with the "
|
|
"Input or Output storage class in Vulkan environment."));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanInvariantMemberWrongStorageClass) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %main "main"
|
|
OpExecutionMode %main OriginUpperLeft
|
|
OpMemberDecorate %struct 1 Invariant
|
|
%void = OpTypeVoid
|
|
%f32 = OpTypeFloat 32
|
|
%struct = OpTypeStruct %f32 %f32
|
|
%ptr_private = OpTypePointer Private %struct
|
|
%var = OpVariable %ptr_private Private
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Invariant-04677"));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Variable struct member decorated with Invariant must "
|
|
"only be identified with the Input or Output storage "
|
|
"class in Vulkan environment."));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PhysicalStorageBufferPtrEqual) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Int64
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%long = OpTypeInt 64 0
|
|
%long_0 = OpConstant %long 0
|
|
%ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%conv = OpConvertUToPtr %ptr_pssbo_long %long_0
|
|
%eq = OpPtrEqual %bool %conv %conv
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"Cannot use a pointer in the PhysicalStorageBuffer storage class"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PhysicalStorageBufferPtrNotEqual) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Int64
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%long = OpTypeInt 64 0
|
|
%long_0 = OpConstant %long 0
|
|
%ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%conv = OpConvertUToPtr %ptr_pssbo_long %long_0
|
|
%neq = OpPtrNotEqual %bool %conv %conv
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"Cannot use a pointer in the PhysicalStorageBuffer storage class"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PhysicalStorageBufferPtrDiff) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Int64
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability VariablePointers
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%void = OpTypeVoid
|
|
%long = OpTypeInt 64 0
|
|
%long_0 = OpConstant %long 0
|
|
%ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%conv = OpConvertUToPtr %ptr_pssbo_long %long_0
|
|
%diff = OpPtrDiff %long %conv %conv
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr(
|
|
"Cannot use a pointer in the PhysicalStorageBuffer storage class"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanInitializerWithWorkgroupStorageClassBad) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%float = OpTypeFloat 32
|
|
%float_ptr = OpTypePointer Workgroup %float
|
|
%init_val = OpConstant %float 1.0
|
|
%1 = OpVariable %float_ptr Workgroup %init_val
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%2 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID(" VUID-StandaloneSpirv-OpVariable-04734"));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("OpVariable, <id> '5[%5]', initializers are limited to "
|
|
"OpConstantNull in Workgroup storage class"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanInitializerWithWorkgroupStorageClassGood) {
|
|
std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VulkanMemoryModelKHR
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
OpEntryPoint Fragment %func "func"
|
|
OpExecutionMode %func OriginUpperLeft
|
|
%float = OpTypeFloat 32
|
|
%float_ptr = OpTypePointer Workgroup %float
|
|
%init_val = OpConstantNull %float
|
|
%1 = OpVariable %float_ptr Workgroup %init_val
|
|
%void = OpTypeVoid
|
|
%functy = OpTypeFunction %void
|
|
%func = OpFunction %void None %functy
|
|
%2 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, LoadRuntimeArray) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%rta = OpTypeRuntimeArray %int
|
|
%block = OpTypeStruct %rta
|
|
%ptr_rta = OpTypePointer StorageBuffer %rta
|
|
%ptr_block = OpTypePointer StorageBuffer %block
|
|
%var = OpVariable %ptr_block StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = OpAccessChain %ptr_rta %var %int_0
|
|
%ld = OpLoad %rta %gep
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Cannot load a runtime-sized array"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, LoadRuntimeArrayInStruct) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%rta = OpTypeRuntimeArray %int
|
|
%block = OpTypeStruct %rta
|
|
%ptr_rta = OpTypePointer StorageBuffer %rta
|
|
%ptr_block = OpTypePointer StorageBuffer %block
|
|
%var = OpVariable %ptr_block StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%ld = OpLoad %block %var
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Cannot load a runtime-sized array"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, LoadRuntimeArrayInArray) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%int_4 = OpConstant %int 4
|
|
%rta = OpTypeRuntimeArray %int
|
|
%block = OpTypeStruct %rta
|
|
%array = OpTypeArray %block %int_4
|
|
%ptr_rta = OpTypePointer StorageBuffer %rta
|
|
%ptr_block = OpTypePointer StorageBuffer %block
|
|
%ptr_array = OpTypePointer StorageBuffer %array
|
|
%var = OpVariable %ptr_array StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%ld = OpLoad %array %var
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Cannot load a runtime-sized array"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, Pre1p4WorkgroupMemoryBadLayoutOk) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%struct = OpTypeStruct %bool
|
|
%ptr = OpTypePointer Workgroup %struct
|
|
%var = OpVariable %ptr Workgroup
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%ptr = OpTypeUntypedPointerKHR Private
|
|
%var = OpUntypedVariableKHR %ptr Private %int %int_0
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableNoDataType) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpMemoryModel Logical GLSL450
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%var = OpUntypedVariableKHR %ptr StorageBuffer
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableNoDataTypeFunction) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%ptr = OpTypeUntypedPointerKHR Function
|
|
%var = OpUntypedVariableKHR %ptr Function
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Data type must be specified for Function, "
|
|
"Private, and Workgroup storage classes"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableNoDataTypePrivate) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%ptr = OpTypeUntypedPointerKHR Private
|
|
%var = OpUntypedVariableKHR %ptr Private
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Data type must be specified for Function, "
|
|
"Private, and Workgroup storage classes"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableNoDataTypeWorkgroup) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%var = OpUntypedVariableKHR %ptr Workgroup
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Data type must be specified for Function, "
|
|
"Private, and Workgroup storage classes"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableNoDataTypeVulkan) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%var = OpUntypedVariableKHR %ptr StorageBuffer
|
|
%void = OpTypeVoid
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Vulkan requires that data type be specified"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PtrAccessChainArrayStrideBad) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VariablePointersStorageBuffer
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "foo" %var
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
%uint = OpTypeInt 32 0
|
|
%uint_0 = OpConstant %uint 0
|
|
%uint_1 = OpConstant %uint 1
|
|
%ptr = OpTypePointer StorageBuffer %uint
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%var = OpVariable %ptr StorageBuffer
|
|
%main = OpFunction %void None %func
|
|
%label = OpLabel
|
|
%access = OpAccessChain %ptr %var
|
|
%ptr_access = OpPtrAccessChain %ptr %access %uint_1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("OpPtrAccessChain must have a Base whose type is "
|
|
"decorated with ArrayStride"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PtrAccessChainArrayStrideSuccess) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VariablePointersStorageBuffer
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "foo" %var
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 00
|
|
OpDecorate %ptr ArrayStride 4
|
|
%uint = OpTypeInt 32 0
|
|
%uint_0 = OpConstant %uint 0
|
|
%uint_1 = OpConstant %uint 1
|
|
%ptr = OpTypePointer StorageBuffer %uint
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%var = OpVariable %ptr StorageBuffer
|
|
%main = OpFunction %void None %func
|
|
%label = OpLabel
|
|
%access = OpAccessChain %ptr %var
|
|
%ptr_access = OpPtrAccessChain %ptr %access %uint_1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanPtrAccessChainStorageBufferSuccess) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VariablePointersStorageBuffer
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "foo" %var
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %_runtimearr_uint ArrayStride 4
|
|
OpMemberDecorate %_struct_10 0 Offset 0
|
|
OpDecorate %_struct_10 Block
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %_ptr_StorageBuffer_uint ArrayStride 4
|
|
%uint = OpTypeInt 32 0
|
|
%uint_0 = OpConstant %uint 0
|
|
%uint_1 = OpConstant %uint 1
|
|
%_runtimearr_uint = OpTypeRuntimeArray %uint
|
|
%_struct_10 = OpTypeStruct %_runtimearr_uint
|
|
%_ptr_StorageBuffer__struct_10 = OpTypePointer StorageBuffer %_struct_10
|
|
%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
|
|
%void = OpTypeVoid
|
|
%func2 = OpTypeFunction %void %_ptr_StorageBuffer_uint
|
|
%func1 = OpTypeFunction %void
|
|
%var = OpVariable %_ptr_StorageBuffer__struct_10 StorageBuffer
|
|
%called = OpFunction %void None %func2
|
|
%param = OpFunctionParameter %_ptr_StorageBuffer_uint
|
|
%label2 = OpLabel
|
|
%ptr_access = OpPtrAccessChain %_ptr_StorageBuffer_uint %param %uint_1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%main = OpFunction %void None %func1
|
|
%label1 = OpLabel
|
|
%access = OpAccessChain %_ptr_StorageBuffer_uint %var %uint_0 %uint_0
|
|
%call = OpFunctionCall %void %called %access
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanPtrAccessChainStorageBufferCapability) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpMemoryModel PhysicalStorageBuffer64 GLSL450
|
|
OpEntryPoint GLCompute %main "foo" %var
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %_runtimearr_uint ArrayStride 4
|
|
OpMemberDecorate %_struct_10 0 Offset 0
|
|
OpDecorate %_struct_10 Block
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %_ptr_StorageBuffer_uint ArrayStride 4
|
|
%uint = OpTypeInt 32 0
|
|
%uint_0 = OpConstant %uint 0
|
|
%uint_1 = OpConstant %uint 1
|
|
%_runtimearr_uint = OpTypeRuntimeArray %uint
|
|
%_struct_10 = OpTypeStruct %_runtimearr_uint
|
|
%_ptr_StorageBuffer__struct_10 = OpTypePointer StorageBuffer %_struct_10
|
|
%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%var = OpVariable %_ptr_StorageBuffer__struct_10 StorageBuffer
|
|
%main = OpFunction %void None %func
|
|
%label = OpLabel
|
|
%access = OpAccessChain %_ptr_StorageBuffer_uint %var %uint_0 %uint_0
|
|
%ptr_access = OpPtrAccessChain %_ptr_StorageBuffer_uint %access %uint_1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Base-07652"));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("OpPtrAccessChain Base operand pointing to "
|
|
"StorageBuffer storage class must use VariablePointers "
|
|
"or VariablePointersStorageBuffer capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanPtrAccessChainWorkgroupCapability) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VariablePointersStorageBuffer
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "foo" %var
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %_ptr_Workgroup_uint ArrayStride 4
|
|
%uint = OpTypeInt 32 0
|
|
%uint_0 = OpConstant %uint 0
|
|
%uint_1 = OpConstant %uint 1
|
|
%_arr_uint = OpTypeArray %uint %uint_1
|
|
%_ptr_Workgroup__arr_uint = OpTypePointer Workgroup %_arr_uint
|
|
%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%var = OpVariable %_ptr_Workgroup__arr_uint Workgroup
|
|
%main = OpFunction %void None %func
|
|
%label = OpLabel
|
|
%access = OpAccessChain %_ptr_Workgroup_uint %var %uint_0
|
|
%ptr_access = OpPtrAccessChain %_ptr_Workgroup_uint %access %uint_1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
AnyVUID("VUID-StandaloneSpirv-Base-07651"));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("OpPtrAccessChain Base operand pointing to Workgroup "
|
|
"storage class must use VariablePointers capability"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, VulkanPtrAccessChainWorkgroupNoArrayStrideSuccess) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VariablePointers
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "foo" %var
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
%uint = OpTypeInt 32 0
|
|
%uint_0 = OpConstant %uint 0
|
|
%uint_1 = OpConstant %uint 1
|
|
%_arr_uint = OpTypeArray %uint %uint_1
|
|
%_ptr_Workgroup__arr_uint = OpTypePointer Workgroup %_arr_uint
|
|
%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
|
|
%void = OpTypeVoid
|
|
%func = OpTypeFunction %void
|
|
%var = OpVariable %_ptr_Workgroup__arr_uint Workgroup
|
|
%main = OpFunction %void None %func
|
|
%label = OpLabel
|
|
%access = OpAccessChain %_ptr_Workgroup_uint %var %uint_0
|
|
%ptr_access = OpPtrAccessChain %_ptr_Workgroup_uint %access %uint_1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, AccessChainNegativeStructIndex32) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%void_fn = OpTypeFunction %void
|
|
%int = OpTypeInt 32 1
|
|
%_struct_4 = OpTypeStruct %int %int %int
|
|
%_ptr_Function__struct_4 = OpTypePointer Function %_struct_4
|
|
%_ptr_Function_int = OpTypePointer Function %int
|
|
%int_n224 = OpConstant %int -224
|
|
%fn = OpFunction %void Inline %void_fn
|
|
%entry = OpLabel
|
|
%var = OpVariable %_ptr_Function__struct_4 Function
|
|
%gep = OpInBoundsAccessChain %_ptr_Function_int %var %int_n224
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("Index is out of bounds"));
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("cannot find index -224"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, AccessChainNegativeStructIndex64) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability Int64
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%void_fn = OpTypeFunction %void
|
|
%int = OpTypeInt 32 1
|
|
%long = OpTypeInt 64 1
|
|
%_struct_4 = OpTypeStruct %int %int %int
|
|
%_ptr_Function__struct_4 = OpTypePointer Function %_struct_4
|
|
%_ptr_Function_int = OpTypePointer Function %int
|
|
%long_n224 = OpConstant %long -224
|
|
%fn = OpFunction %void Inline %void_fn
|
|
%entry = OpLabel
|
|
%var = OpVariable %_ptr_Function__struct_4 Function
|
|
%gep = OpInBoundsAccessChain %_ptr_Function_int %var %long_n224
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("Index is out of bounds"));
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("cannot find index -224"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableFunctionOutsideFunction) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%ptr = OpTypeUntypedPointerKHR Function
|
|
%var = OpUntypedVariableKHR %ptr Function %int
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Variables can not have a function[7] storage class "
|
|
"outside of a function"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableBadResultType) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%var = OpUntypedVariableKHR %int Workgroup %int
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Result type must be an untyped pointer"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableBadDataType) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%var = OpUntypedVariableKHR %ptr Workgroup %int_0
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Data type must be a type instruction"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableBadStorageClass) {
|
|
const std::string spirv = R"(
|
|
OpCapability Kernel
|
|
OpCapability GenericPointer
|
|
OpCapability Linkage
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical OpenCL
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%ptr = OpTypeUntypedPointerKHR Generic
|
|
%var = OpUntypedVariableKHR %ptr Generic %int
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_2);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
|
|
ValidateInstructions(SPV_ENV_UNIVERSAL_1_2));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Variable storage class cannot be Generic"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableMismatchedStorageClass) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%var = OpUntypedVariableKHR %ptr Private %int
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Storage class must match result type storage class"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableBadInitializer) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
%int = OpTypeInt 32 0
|
|
%float = OpTypeFloat 32
|
|
%float_0 = OpConstant %float 0
|
|
%ptr = OpTypeUntypedPointerKHR Private
|
|
%var = OpUntypedVariableKHR %ptr Private %int %float_0
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Initializer type must match the data type"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, AccessChainBaseUntypedPointer) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpName %var "var"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%block = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypePointer StorageBuffer %block
|
|
%ptr_ssbo_int = OpTypePointer StorageBuffer %int
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%var = OpUntypedVariableKHR %ptr StorageBuffer %int
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = OpAccessChain %ptr_ssbo_int %var %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("The Base <id> '2[%var]' in OpAccessChain "
|
|
"instruction must be a pointer"));
|
|
}
|
|
|
|
using ValidateMemoryUntypedAccessChain = spvtest::ValidateBase<std::string>;
|
|
|
|
TEST_P(ValidateMemoryUntypedAccessChain, GoodTypedPointerBase) {
|
|
const std::string opcode = GetParam();
|
|
const bool ptr = opcode == "OpUntypedPtrAccessChainKHR" ||
|
|
opcode == "OpUntypedInBoundsPtrAccessChainKHR";
|
|
const std::string extra_param = ptr ? "%int_0" : "";
|
|
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability VariablePointers
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%block = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypePointer StorageBuffer %block
|
|
%var = OpVariable %ptr_ssbo StorageBuffer
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = )" + opcode + R"( %ptr %block %var )" +
|
|
extra_param + R"( %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_P(ValidateMemoryUntypedAccessChain, GoodUntypedPointerBase) {
|
|
const std::string opcode = GetParam();
|
|
const bool ptr = opcode == "OpUntypedPtrAccessChainKHR" ||
|
|
opcode == "OpUntypedInBoundsPtrAccessChainKHR";
|
|
const std::string extra_param = ptr ? "%int_0" : "";
|
|
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability VariablePointers
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%block = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypePointer StorageBuffer %block
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%var = OpUntypedVariableKHR %ptr StorageBuffer %int
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = )" + opcode + R"( %ptr %block %var )" +
|
|
extra_param + R"( %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_P(ValidateMemoryUntypedAccessChain, ResultTypedPointer) {
|
|
const std::string opcode = GetParam();
|
|
const bool ptr = opcode == "OpUntypedPtrAccessChainKHR" ||
|
|
opcode == "OpUntypedInBoundsPtrAccessChainKHR";
|
|
const std::string extra_param = ptr ? "%int_0" : "";
|
|
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability VariablePointers
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpName %gep "gep"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%block = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypePointer StorageBuffer %block
|
|
%var = OpVariable %ptr_ssbo StorageBuffer
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%ptr_int = OpTypePointer StorageBuffer %int
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = )" + opcode + R"( %ptr_int %block %var )" +
|
|
extra_param + R"( %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("The Result Type of " + opcode +
|
|
" <id> '2[%gep]' must be OpTypeUntypedPointer"));
|
|
}
|
|
|
|
TEST_P(ValidateMemoryUntypedAccessChain, BaseTypeNotAType) {
|
|
const std::string opcode = GetParam();
|
|
const bool ptr = opcode == "OpUntypedPtrAccessChainKHR" ||
|
|
opcode == "OpUntypedInBoundsPtrAccessChainKHR";
|
|
const std::string extra_param = ptr ? "%int_0" : "";
|
|
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability VariablePointers
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpName %gep "gep"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%block = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypePointer StorageBuffer %block
|
|
%var = OpVariable %ptr_ssbo StorageBuffer
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = )" + opcode + R"( %ptr %int_0 %var )" +
|
|
extra_param + R"( %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Base type must be a non-pointer type"));
|
|
}
|
|
|
|
TEST_P(ValidateMemoryUntypedAccessChain, BaseTypedPointer) {
|
|
const std::string opcode = GetParam();
|
|
const bool ptr = opcode == "OpUntypedPtrAccessChainKHR" ||
|
|
opcode == "OpUntypedInBoundsPtrAccessChainKHR";
|
|
const std::string extra_param = ptr ? "%int_0" : "";
|
|
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability VariablePointers
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpName %gep "gep"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%block = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypePointer StorageBuffer %block
|
|
%var = OpVariable %ptr_ssbo StorageBuffer
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = )" + opcode + R"( %ptr %ptr_ssbo %var )" +
|
|
extra_param + R"( %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Base type must be a non-pointer type"));
|
|
}
|
|
|
|
TEST_P(ValidateMemoryUntypedAccessChain, BaseUntypedPointer) {
|
|
const std::string opcode = GetParam();
|
|
const bool ptr = opcode == "OpUntypedPtrAccessChainKHR" ||
|
|
opcode == "OpUntypedInBoundsPtrAccessChainKHR";
|
|
const std::string extra_param = ptr ? "%int_0" : "";
|
|
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability VariablePointers
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpName %gep "gep"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%block = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypePointer StorageBuffer %block
|
|
%var = OpVariable %ptr_ssbo StorageBuffer
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = )" + opcode + R"( %ptr %ptr %var )" +
|
|
extra_param + R"( %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Base type must be a non-pointer type"));
|
|
}
|
|
|
|
TEST_P(ValidateMemoryUntypedAccessChain, BaseNotAPointer) {
|
|
const std::string opcode = GetParam();
|
|
const bool ptr = opcode == "OpUntypedPtrAccessChainKHR" ||
|
|
opcode == "OpUntypedInBoundsPtrAccessChainKHR";
|
|
const std::string extra_param = ptr ? "%int_0" : "";
|
|
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability VariablePointers
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpName %int_0 "int_0"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%block = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypePointer StorageBuffer %block
|
|
%var = OpVariable %ptr_ssbo StorageBuffer
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = )" + opcode + R"( %ptr %int %int_0 )" +
|
|
extra_param + R"( %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("The Base <id> '2[%int_0]' in " + opcode +
|
|
" instruction must be a pointer"));
|
|
}
|
|
|
|
TEST_P(ValidateMemoryUntypedAccessChain, StorageClassMismatch) {
|
|
const std::string opcode = GetParam();
|
|
const bool ptr = opcode == "OpUntypedPtrAccessChainKHR" ||
|
|
opcode == "OpUntypedInBoundsPtrAccessChainKHR";
|
|
const std::string extra_param = ptr ? "%int_0" : "";
|
|
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability VariablePointers
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpName %int_0 "int_0"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%block = OpTypeStruct %int
|
|
%ptr_wg = OpTypePointer Workgroup %block
|
|
%var = OpVariable %ptr_wg Workgroup
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = )" + opcode + R"( %ptr %block %var )" +
|
|
extra_param + R"( %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("The result pointer storage class and base pointer storage "
|
|
"class in " +
|
|
opcode + " do not match"));
|
|
}
|
|
|
|
TEST_P(ValidateMemoryUntypedAccessChain, NonCompositeBase) {
|
|
const std::string opcode = GetParam();
|
|
const bool ptr = opcode == "OpUntypedPtrAccessChainKHR" ||
|
|
opcode == "OpUntypedInBoundsPtrAccessChainKHR";
|
|
const std::string extra_param = ptr ? "%int_0" : "";
|
|
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability VariablePointers
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpName %int_0 "int_0"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%block = OpTypeStruct %int
|
|
%ptr_wg = OpTypePointer StorageBuffer %block
|
|
%var = OpVariable %ptr_wg StorageBuffer
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = )" + opcode + R"( %ptr %int %var )" +
|
|
extra_param + R"( %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr(opcode + " reached non-composite type while indexes "
|
|
"still remain to be traversed"));
|
|
}
|
|
|
|
TEST_P(ValidateMemoryUntypedAccessChain, TooManyIndices) {
|
|
const std::string opcode = GetParam();
|
|
const bool ptr = opcode == "OpUntypedPtrAccessChainKHR" ||
|
|
opcode == "OpUntypedInBoundsPtrAccessChainKHR";
|
|
const std::string extra_param = ptr ? "%int_0" : "";
|
|
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability VariablePointers
|
|
OpExtension "SPV_KHR_variable_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpName %int_0 "int_0"
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%block = OpTypeStruct %int
|
|
%ptr_wg = OpTypePointer StorageBuffer %block
|
|
%var = OpVariable %ptr_wg StorageBuffer
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = )" + opcode + R"( %ptr %block %var )" +
|
|
extra_param + R"( %int_0 %int_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr(opcode + " reached non-composite type while indexes "
|
|
"still remain to be traversed"));
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
ValidateUntypedAccessChains, ValidateMemoryUntypedAccessChain,
|
|
Values("OpUntypedAccessChainKHR", "OpUntypedInBoundsAccessChainKHR",
|
|
"OpUntypedPtrAccessChainKHR", "OpUntypedInBoundsPtrAccessChainKHR"));
|
|
|
|
TEST_F(ValidateMemory, LoadUntypedPointerGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %var
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%float = OpTypeFloat 32
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%var = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%load = OpLoad %float %var
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, StoreUntypedPointerGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %var
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%float = OpTypeFloat 32
|
|
%float_0 = OpConstant %float 0
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%var = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpStore %var %float_0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemoryUntypedPointerSourceGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %var1 %var2
|
|
OpName %var1 "var1"
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%var1 = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%ptr_wg = OpTypePointer Workgroup %int
|
|
%var2 = OpVariable %ptr_wg Workgroup
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var2 %var1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemoryUntypedPointerTargetGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %var1 %var2
|
|
OpName %var1 "var1"
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%var1 = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%ptr_wg = OpTypePointer Workgroup %int
|
|
%var2 = OpVariable %ptr_wg Workgroup
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemoryUntypedPointerTargetAndSourceBad) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %var1 %var2
|
|
OpName %var1 "var1"
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%var1 = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%var2 = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpCopyMemory %var1 %var2
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("One of Source or Target must be a typed pointer"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySizedUntypedPointersGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %v1 %v2
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%int_4 = OpConstant %int 4
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%v1 = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%v2 = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %v2 %v1 %int_4
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySizedUntypedPointersSizeBad1) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability StorageBuffer16BitAccess
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %var_wg %var_ssbo
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%short = OpTypeInt 16 0
|
|
%int_2 = OpConstant %int 2
|
|
%struct = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypeUntypedPointerKHR StorageBuffer
|
|
%ptr_wg = OpTypeUntypedPointerKHR Workgroup
|
|
%var_ssbo = OpUntypedVariableKHR %ptr_ssbo StorageBuffer %struct
|
|
%var_wg = OpUntypedVariableKHR %ptr_wg Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var_ssbo %var_wg %int_2
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("Size must be a multiple of 4"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySizedUntypedPointersSizeBad2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability StorageBuffer16BitAccess
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %var_ssbo %var_wg
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%short = OpTypeInt 16 0
|
|
%int_2 = OpConstant %int 2
|
|
%struct = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypeUntypedPointerKHR StorageBuffer
|
|
%ptr_wg = OpTypeUntypedPointerKHR Workgroup
|
|
%var_ssbo = OpUntypedVariableKHR %ptr_ssbo StorageBuffer %struct
|
|
%var_wg = OpUntypedVariableKHR %ptr_wg Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var_wg %var_ssbo %int_2
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("Size must be a multiple of 4"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySizedUntypedPointersSizeBad3) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Int16
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability StorageBuffer8BitAccess
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_8bit_storage"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %var_ssbo %var_wg
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%short = OpTypeInt 16 0
|
|
%int_1 = OpConstant %int 1
|
|
%struct = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypeUntypedPointerKHR StorageBuffer
|
|
%ptr_wg = OpTypeUntypedPointerKHR Workgroup
|
|
%var_ssbo = OpUntypedVariableKHR %ptr_ssbo StorageBuffer %struct
|
|
%var_wg = OpUntypedVariableKHR %ptr_wg Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var_ssbo %var_wg %int_1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("Size must be a multiple of 2"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CopyMemorySizedUntypedPointersSizeBad4) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Int16
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability StorageBuffer8BitAccess
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_8bit_storage"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %var_ssbo %var_wg
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%short = OpTypeInt 16 0
|
|
%int_1 = OpConstant %int 1
|
|
%struct = OpTypeStruct %int
|
|
%ptr_ssbo = OpTypeUntypedPointerKHR StorageBuffer
|
|
%ptr_wg = OpTypeUntypedPointerKHR Workgroup
|
|
%var_ssbo = OpUntypedVariableKHR %ptr_ssbo StorageBuffer %struct
|
|
%var_wg = OpUntypedVariableKHR %ptr_wg Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpCopyMemorySized %var_wg %var_ssbo %int_1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("Size must be a multiple of 2"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PtrEqualUntypedPointersGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VariablePointers
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %v1 %v2
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%int = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%v1 = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%v2 = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%res = OpPtrEqual %bool %v1 %v2
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PtrNotEqualUntypedPointersGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VariablePointers
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %v1 %v2
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%int = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%v1 = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%v2 = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%res = OpPtrNotEqual %bool %v1 %v2
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, PtrDiffUntypedPointersGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability VariablePointers
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %v1
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%v1 = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%res = OpPtrDiff %int %v1 %v1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableVulkanPushConstantGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR PushConstant
|
|
%var = OpUntypedVariableKHR %ptr PushConstant %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableVulkanStorageBufferGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%var = OpUntypedVariableKHR %ptr StorageBuffer %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableVulkanUniformGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR Uniform
|
|
%var = OpUntypedVariableKHR %ptr Uniform %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedVariableVulkanWorkgroupGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability WorkgroupMemoryExplicitLayoutKHR
|
|
OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %struct Block
|
|
OpMemberDecorate %struct 0 Offset 0
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR Workgroup
|
|
%var = OpUntypedVariableKHR %ptr Workgroup %struct
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1_SPIRV_1_4);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedPointerAsVariableType) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
OpCapability VariablePointers
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
%void = OpTypeVoid
|
|
%float = OpTypeFloat 32
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%priv_ptr = OpTypePointer Private %ptr
|
|
%var = OpVariable %priv_ptr Private
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedArrayLengthGood) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
OpDecorate %array ArrayStride 4
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%array = OpTypeRuntimeArray %int
|
|
%block = OpTypeStruct %array
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%var = OpUntypedVariableKHR %ptr StorageBuffer %block
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%length = OpUntypedArrayLengthKHR %int %block %var 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedArrayLengthBadResultType) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
OpDecorate %array ArrayStride 4
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%float = OpTypeFloat 32
|
|
%array = OpTypeRuntimeArray %int
|
|
%block = OpTypeStruct %array
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%var = OpUntypedVariableKHR %ptr StorageBuffer %block
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%length = OpUntypedArrayLengthKHR %float %block %var 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("must be OpTypeInt with width 32 and signedness 0"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedArrayLengthBadPointer) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
OpDecorate %array ArrayStride 4
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%array = OpTypeRuntimeArray %int
|
|
%block = OpTypeStruct %array
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%typed_ptr = OpTypePointer StorageBuffer %block
|
|
%var = OpVariable %typed_ptr StorageBuffer
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%length = OpUntypedArrayLengthKHR %int %block %var 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Pointer must be an untyped pointer"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedArrayLengtBadStruct) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
OpDecorate %array ArrayStride 4
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%array = OpTypeRuntimeArray %int
|
|
%block = OpTypeStruct %array
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%var = OpUntypedVariableKHR %ptr StorageBuffer %block
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%length = OpUntypedArrayLengthKHR %int %int %var 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("to an OpTypeStruct"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedArrayLengthLastMemberNotArray) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
OpDecorate %array ArrayStride 4
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%array = OpTypeRuntimeArray %int
|
|
%block = OpTypeStruct %int
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%var = OpUntypedVariableKHR %ptr StorageBuffer %block
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%length = OpUntypedArrayLengthKHR %int %block %var 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("must be an OpTypeRuntimeArray"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedArrayLengthBadIndex) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
OpDecorate %array ArrayStride 4
|
|
%void = OpTypeVoid
|
|
%int = OpTypeInt 32 0
|
|
%array = OpTypeRuntimeArray %int
|
|
%block = OpTypeStruct %array
|
|
%ptr = OpTypeUntypedPointerKHR StorageBuffer
|
|
%var = OpUntypedVariableKHR %ptr StorageBuffer %block
|
|
%void_fn = OpTypeFunction %void
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%length = OpUntypedArrayLengthKHR %int %block %var 1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("must be the last member of the struct"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedCooperativeMatrixLoad) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability CooperativeMatrixKHR
|
|
OpCapability VulkanMemoryModel
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpExtension "SPV_KHR_cooperative_matrix"
|
|
OpMemoryModel Logical Vulkan
|
|
OpEntryPoint GLCompute %main "main" %var
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
OpDecorate %array ArrayStride 4
|
|
%void = OpTypeVoid
|
|
%void_fn = OpTypeFunction %void
|
|
%untyped = OpTypeUntypedPointerKHR StorageBuffer
|
|
%float = OpTypeFloat 32
|
|
%array = OpTypeRuntimeArray %float
|
|
%block = OpTypeStruct %array
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%subgroup = OpConstant %int 3
|
|
%rows = OpSpecConstant %int 1
|
|
%cols = OpSpecConstant %int 1
|
|
%matrix_a = OpConstant %int 1
|
|
%stride = OpConstant %int 42
|
|
%matrix = OpTypeCooperativeMatrixKHR %float %subgroup %rows %cols %matrix_a
|
|
%var = OpUntypedVariableKHR %untyped StorageBuffer %block
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%ld = OpCooperativeMatrixLoadKHR %matrix %var %int_0 %stride
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedCooperativeMatrixLoad2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability CooperativeMatrixKHR
|
|
OpCapability VulkanMemoryModel
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpExtension "SPV_KHR_cooperative_matrix"
|
|
OpMemoryModel Logical Vulkan
|
|
OpEntryPoint GLCompute %main "main" %var
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var DescriptorSet 0
|
|
OpDecorate %var Binding 0
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
OpDecorate %array ArrayStride 4
|
|
%void = OpTypeVoid
|
|
%void_fn = OpTypeFunction %void
|
|
%untyped = OpTypeUntypedPointerKHR StorageBuffer
|
|
%float = OpTypeFloat 32
|
|
%array = OpTypeRuntimeArray %float
|
|
%block = OpTypeStruct %array
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%subgroup = OpConstant %int 3
|
|
%rows = OpSpecConstant %int 1
|
|
%cols = OpSpecConstant %int 1
|
|
%matrix_a = OpConstant %int 1
|
|
%stride = OpConstant %int 42
|
|
%matrix = OpTypeCooperativeMatrixKHR %float %subgroup %rows %cols %matrix_a
|
|
%var = OpUntypedVariableKHR %untyped StorageBuffer %block
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = OpUntypedAccessChainKHR %untyped %block %var %int_0 %int_0
|
|
%ld = OpCooperativeMatrixLoadKHR %matrix %gep %int_0 %stride
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedCooperativeMatrixStore) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability CooperativeMatrixKHR
|
|
OpCapability VulkanMemoryModel
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpExtension "SPV_KHR_cooperative_matrix"
|
|
OpMemoryModel Logical Vulkan
|
|
OpEntryPoint GLCompute %main "main" %var1 %var2
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var1 DescriptorSet 0
|
|
OpDecorate %var1 Binding 0
|
|
OpDecorate %var2 DescriptorSet 0
|
|
OpDecorate %var2 Binding 1
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
OpDecorate %array ArrayStride 4
|
|
%void = OpTypeVoid
|
|
%void_fn = OpTypeFunction %void
|
|
%untyped = OpTypeUntypedPointerKHR StorageBuffer
|
|
%float = OpTypeFloat 32
|
|
%array = OpTypeRuntimeArray %float
|
|
%block = OpTypeStruct %array
|
|
%ptr = OpTypePointer StorageBuffer %block
|
|
%ptr_float = OpTypePointer StorageBuffer %float
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%subgroup = OpConstant %int 3
|
|
%rows = OpSpecConstant %int 1
|
|
%cols = OpSpecConstant %int 1
|
|
%matrix_a = OpConstant %int 1
|
|
%stride = OpConstant %int 42
|
|
%matrix = OpTypeCooperativeMatrixKHR %float %subgroup %rows %cols %matrix_a
|
|
%var1 = OpVariable %ptr StorageBuffer
|
|
%var2 = OpUntypedVariableKHR %untyped StorageBuffer %block
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = OpAccessChain %ptr_float %var1 %int_0 %int_0
|
|
%ld = OpCooperativeMatrixLoadKHR %matrix %gep %int_0 %stride
|
|
OpCooperativeMatrixStoreKHR %var2 %ld %int_0 %stride
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, UntypedCooperativeMatrixStore2) {
|
|
const std::string spirv = R"(
|
|
OpCapability Shader
|
|
OpCapability UntypedPointersKHR
|
|
OpCapability CooperativeMatrixKHR
|
|
OpCapability VulkanMemoryModel
|
|
OpExtension "SPV_KHR_untyped_pointers"
|
|
OpExtension "SPV_KHR_cooperative_matrix"
|
|
OpMemoryModel Logical Vulkan
|
|
OpEntryPoint GLCompute %main "main" %var1 %var2
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpDecorate %var1 DescriptorSet 0
|
|
OpDecorate %var1 Binding 0
|
|
OpDecorate %var2 DescriptorSet 0
|
|
OpDecorate %var2 Binding 1
|
|
OpDecorate %block Block
|
|
OpMemberDecorate %block 0 Offset 0
|
|
OpDecorate %array ArrayStride 4
|
|
%void = OpTypeVoid
|
|
%void_fn = OpTypeFunction %void
|
|
%untyped = OpTypeUntypedPointerKHR StorageBuffer
|
|
%float = OpTypeFloat 32
|
|
%array = OpTypeRuntimeArray %float
|
|
%block = OpTypeStruct %array
|
|
%ptr = OpTypePointer StorageBuffer %block
|
|
%ptr_float = OpTypePointer StorageBuffer %float
|
|
%int = OpTypeInt 32 0
|
|
%int_0 = OpConstant %int 0
|
|
%subgroup = OpConstant %int 3
|
|
%rows = OpSpecConstant %int 1
|
|
%cols = OpSpecConstant %int 1
|
|
%matrix_a = OpConstant %int 1
|
|
%stride = OpConstant %int 42
|
|
%matrix = OpTypeCooperativeMatrixKHR %float %subgroup %rows %cols %matrix_a
|
|
%var1 = OpVariable %ptr StorageBuffer
|
|
%var2 = OpUntypedVariableKHR %untyped StorageBuffer %block
|
|
%main = OpFunction %void None %void_fn
|
|
%entry = OpLabel
|
|
%gep = OpAccessChain %ptr_float %var1 %int_0 %int_0
|
|
%ld = OpCooperativeMatrixLoadKHR %matrix %gep %int_0 %stride
|
|
%gep2 = OpUntypedAccessChainKHR %untyped %block %var2 %int_0 %int_0
|
|
OpCooperativeMatrixStoreKHR %gep2 %ld %int_0 %stride
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
|
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
|
|
}
|
|
|
|
std::string GenCoopMat2Shader(const std::string& extra_types,
|
|
const std::string& main_body,
|
|
const std::string& after_main = "",
|
|
const std::string& extra_decorations = "") {
|
|
const std::string prefix = R"(
|
|
OpCapability Shader
|
|
OpCapability Float16
|
|
OpCapability PhysicalStorageBufferAddresses
|
|
OpCapability VulkanMemoryModel
|
|
OpCapability CooperativeMatrixKHR
|
|
OpCapability TensorAddressingNV
|
|
OpCapability CooperativeMatrixTensorAddressingNV
|
|
OpCapability CooperativeMatrixBlockLoadsNV
|
|
OpExtension "SPV_KHR_physical_storage_buffer"
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpExtension "SPV_NV_tensor_addressing"
|
|
OpExtension "SPV_NV_cooperative_matrix2"
|
|
OpExtension "SPV_KHR_cooperative_matrix"
|
|
OpExtension "SPV_KHR_vulkan_memory_model"
|
|
OpMemoryModel Logical VulkanKHR
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
|
|
OpDecorate %f16_arr ArrayStride 2
|
|
OpDecorate %46 Block
|
|
OpMemberDecorate %46 0 Offset 0
|
|
OpDecorate %48 Binding 0
|
|
OpDecorate %48 DescriptorSet 0
|
|
OpDecorate %psb Restrict
|
|
)" + extra_decorations + R"(
|
|
%void = OpTypeVoid
|
|
%bool = OpTypeBool
|
|
%func = OpTypeFunction %void
|
|
%f16 = OpTypeFloat 16
|
|
%f32 = OpTypeFloat 32
|
|
%u32 = OpTypeInt 32 0
|
|
%s32 = OpTypeInt 32 1
|
|
|
|
%s32_0 = OpConstant %s32 0
|
|
%f16_0 = OpConstant %f16 0
|
|
%u32_2 = OpConstant %u32 2
|
|
%u32_8 = OpConstant %u32 8
|
|
%use_A = OpConstant %u32 0
|
|
%workgroup = OpConstant %u32 2
|
|
%subgroup = OpConstant %u32 3
|
|
|
|
%f16_arr = OpTypeRuntimeArray %f16
|
|
%46 = OpTypeStruct %f16_arr
|
|
%47 = OpTypePointer StorageBuffer %46
|
|
%48 = OpVariable %47 StorageBuffer
|
|
%51 = OpTypePointer StorageBuffer %f16_arr
|
|
%psbptr = OpTypePointer PhysicalStorageBuffer %f16_arr
|
|
|
|
%f16mat = OpTypeCooperativeMatrixKHR %f16 %workgroup %u32_8 %u32_8 %use_A
|
|
%f32mat = OpTypeCooperativeMatrixKHR %f32 %subgroup %u32_8 %u32_8 %use_A
|
|
|
|
%arr2 = OpTypeArray %u32 %u32_2
|
|
%functy = OpTypeFunction %f16 %psbptr %arr2 %arr2
|
|
)";
|
|
|
|
const std::string decode_func =
|
|
R"(
|
|
%decodefunc = OpFunction %f16 None %functy
|
|
%psb = OpFunctionParameter %psbptr
|
|
%c0 = OpFunctionParameter %arr2
|
|
%c1 = OpFunctionParameter %arr2
|
|
%entry2 = OpLabel
|
|
OpReturnValue %f16_0
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const std::string func_begin =
|
|
R"(
|
|
%main = OpFunction %void None %func
|
|
%main_entry = OpLabel
|
|
|
|
%array_ptr = OpAccessChain %51 %48 %s32_0
|
|
)";
|
|
|
|
const std::string suffix =
|
|
R"(
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
return prefix + extra_types + func_begin + main_body + suffix + decode_func +
|
|
after_main;
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutAndViewSuccess) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 2
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%hasdim = OpConstantFalse %bool
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1
|
|
)",
|
|
R"(
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutInvalidDimFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 6
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
)",
|
|
R"(
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("must be between 1 and 5"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutInvalidClampFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 6
|
|
%dim = OpConstant %u32 2
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
)",
|
|
R"(
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("must be a valid TensorClampMode"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorViewInvalidDimFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%dim = OpConstant %u32 6
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%hasdim = OpConstantFalse %bool
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1
|
|
)",
|
|
R"(
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("must be between 1 and 5"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorViewInvalidPermutationFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%dim = OpConstant %u32 3
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%hasdim = OpConstantFalse %bool
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1 %p1
|
|
)",
|
|
R"(
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Permutation values don't form a valid permutation"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorViewInvalidPermutation2Fail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%dim = OpConstant %u32 3
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%hasdim = OpConstantFalse %bool
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1
|
|
)",
|
|
R"(
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("Incorrect number of permutation values."));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutBlockSizePass) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 3
|
|
%b = OpConstant %u32 1
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
)",
|
|
R"(
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tl2 = OpTensorLayoutSetBlockSizeNV %layout %tl %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutBlockSizeFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 3
|
|
%b = OpConstant %u32 1
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
)",
|
|
R"(
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tl2 = OpTensorLayoutSetBlockSizeNV %layout %tl %b %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("unexpected number of operands"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutDimensionPass) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 3
|
|
%b = OpConstant %u32 1
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
)",
|
|
R"(
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tl2 = OpTensorLayoutSetDimensionNV %layout %tl %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutDimensionFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 3
|
|
%b = OpConstant %u32 1
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
)",
|
|
R"(
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tl2 = OpTensorLayoutSetDimensionNV %layout %tl %b %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("unexpected number of operands"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutStridePass) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 3
|
|
%b = OpConstant %u32 1
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
)",
|
|
R"(
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tl2 = OpTensorLayoutSetStrideNV %layout %tl %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutStrideFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 3
|
|
%b = OpConstant %u32 1
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
)",
|
|
R"(
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tl2 = OpTensorLayoutSetStrideNV %layout %tl %b %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("unexpected number of operands"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutSlicePass) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 3
|
|
%b = OpConstant %u32 1
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
)",
|
|
R"(
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tl2 = OpTensorLayoutSliceNV %layout %tl %b %b %b %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutSliceFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 3
|
|
%b = OpConstant %u32 1
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
)",
|
|
R"(
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tl2 = OpTensorLayoutSliceNV %layout %tl %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("unexpected number of operands"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorLayoutSetClampValuePass) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 3
|
|
%b = OpConstant %u32 1
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
)",
|
|
R"(
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tl2 = OpTensorLayoutSetClampValueNV %layout %tl %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorViewDimensionPass) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%dim = OpConstant %u32 3
|
|
%hasdim = OpConstantFalse %bool
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%p2 = OpConstant %u32 2
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1 %p2
|
|
%b = OpConstant %u32 1
|
|
)",
|
|
R"(
|
|
%tv = OpCreateTensorViewNV %view
|
|
%tv2 = OpTensorViewSetDimensionNV %view %tv %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorViewDimensionFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%dim = OpConstant %u32 3
|
|
%hasdim = OpConstantFalse %bool
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%p2 = OpConstant %u32 2
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1 %p2
|
|
%b = OpConstant %u32 1
|
|
)",
|
|
R"(
|
|
%tv = OpCreateTensorViewNV %view
|
|
%tv2 = OpTensorViewSetDimensionNV %view %tv %b %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("unexpected number of operands"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorViewStridePass) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%dim = OpConstant %u32 3
|
|
%hasdim = OpConstantFalse %bool
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%p2 = OpConstant %u32 2
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1 %p2
|
|
%b = OpConstant %u32 1
|
|
)",
|
|
R"(
|
|
%tv = OpCreateTensorViewNV %view
|
|
%tv2 = OpTensorViewSetStrideNV %view %tv %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorViewStrideFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%dim = OpConstant %u32 3
|
|
%hasdim = OpConstantFalse %bool
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%p2 = OpConstant %u32 2
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1 %p2
|
|
%b = OpConstant %u32 1
|
|
)",
|
|
R"(
|
|
%tv = OpCreateTensorViewNV %view
|
|
%tv2 = OpTensorViewSetStrideNV %view %tv %b %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("unexpected number of operands"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2TensorViewClipPass) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%dim = OpConstant %u32 3
|
|
%hasdim = OpConstantFalse %bool
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%p2 = OpConstant %u32 2
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1 %p2
|
|
%b = OpConstant %u32 1
|
|
)",
|
|
R"(
|
|
%tv = OpCreateTensorViewNV %view
|
|
%tv2 = OpTensorViewSetClipNV %view %tv %b %b %b %b
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2LoadStoreTensorPass) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 2
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%hasdim = OpConstantFalse %bool
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1
|
|
)",
|
|
R"(
|
|
%mat = OpUndef %f16mat
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tv = OpCreateTensorViewNV %view
|
|
%mat2 = OpCooperativeMatrixLoadTensorNV %f16mat %array_ptr %mat %tl None None
|
|
%mat3 = OpCooperativeMatrixLoadTensorNV %f16mat %array_ptr %mat %tl Aligned 4 None
|
|
%mat4 = OpCooperativeMatrixLoadTensorNV %f16mat %array_ptr %mat %tl None TensorView %tv
|
|
%mat5 = OpCooperativeMatrixLoadTensorNV %f16mat %array_ptr %mat %tl None DecodeFunc %decodefunc
|
|
%mat6 = OpCooperativeMatrixLoadTensorNV %f16mat %array_ptr %mat %tl None TensorView|DecodeFunc %tv %decodefunc
|
|
%mat7 = OpCooperativeMatrixLoadTensorNV %f16mat %array_ptr %mat %tl Aligned 4 TensorView|DecodeFunc %tv %decodefunc
|
|
OpCooperativeMatrixStoreTensorNV %array_ptr %mat %tl None None
|
|
OpCooperativeMatrixStoreTensorNV %array_ptr %mat %tl Aligned 4 None
|
|
OpCooperativeMatrixStoreTensorNV %array_ptr %mat %tl None TensorView %tv
|
|
OpCooperativeMatrixStoreTensorNV %array_ptr %mat %tl Aligned 4 TensorView %tv
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2LoadTensorWrongLayoutTypeFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 2
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%hasdim = OpConstantFalse %bool
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1
|
|
)",
|
|
R"(
|
|
%mat = OpUndef %f16mat
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tv = OpCreateTensorViewNV %view
|
|
%mat2 = OpCooperativeMatrixLoadTensorNV %f16mat %array_ptr %mat %tv None None
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("does not have a tensor layout type"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2LoadTensorWrongObjectTypeFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 2
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%hasdim = OpConstantFalse %bool
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1
|
|
)",
|
|
R"(
|
|
%mat = OpUndef %f32mat
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tv = OpCreateTensorViewNV %view
|
|
%mat2 = OpCooperativeMatrixLoadTensorNV %f16mat %array_ptr %mat %tl None None
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("type does not match Result Type"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2LoadTensorDecodeFuncTypeFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 2
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%hasdim = OpConstantFalse %bool
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1
|
|
)",
|
|
R"(
|
|
%mat = OpUndef %f32mat
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tv = OpCreateTensorViewNV %view
|
|
%mat2 = OpCooperativeMatrixLoadTensorNV %f32mat %array_ptr %mat %tl None DecodeFunc %decodefunc
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("return type must match matrix component type"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2LoadTensorDecodeFuncArrayTypeFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 2
|
|
%u32_3 = OpConstant %u32 3
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%hasdim = OpConstantFalse %bool
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1
|
|
%arr3 = OpTypeArray %u32 %u32_3
|
|
%functy2 = OpTypeFunction %f16 %psbptr %arr3 %arr3
|
|
)",
|
|
R"(
|
|
%mat = OpUndef %f16mat
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tv = OpCreateTensorViewNV %view
|
|
%mat2 = OpCooperativeMatrixLoadTensorNV %f16mat %array_ptr %mat %tl None DecodeFunc %decodefunc2
|
|
)",
|
|
R"(
|
|
%decodefunc2 = OpFunction %f16 None %functy2
|
|
%psb2 = OpFunctionParameter %psbptr
|
|
%c02 = OpFunctionParameter %arr3
|
|
%c12 = OpFunctionParameter %arr3
|
|
%entry3 = OpLabel
|
|
OpReturnValue %f16_0
|
|
OpFunctionEnd
|
|
)",
|
|
R"(
|
|
OpDecorate %psb2 Restrict
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(),
|
|
HasSubstr("dimension equal to the tensor dimension"));
|
|
}
|
|
|
|
TEST_F(ValidateMemory, CoopMat2LoadTensorDecodeFuncPointerTypeFail) {
|
|
std::string spirv = GenCoopMat2Shader(
|
|
R"(
|
|
%clamp = OpConstant %u32 0
|
|
%dim = OpConstant %u32 2
|
|
%p0 = OpConstant %u32 0
|
|
%p1 = OpConstant %u32 1
|
|
%hasdim = OpConstantFalse %bool
|
|
%layout = OpTypeTensorLayoutNV %dim %clamp
|
|
%view = OpTypeTensorViewNV %dim %hasdim %p0 %p1
|
|
%sbptr = OpTypePointer StorageBuffer %f16_arr
|
|
%functy2 = OpTypeFunction %f16 %sbptr %arr2 %arr2
|
|
)",
|
|
R"(
|
|
%mat = OpUndef %f16mat
|
|
%tl = OpCreateTensorLayoutNV %layout
|
|
%tv = OpCreateTensorViewNV %view
|
|
%mat2 = OpCooperativeMatrixLoadTensorNV %f16mat %array_ptr %mat %tl None DecodeFunc %decodefunc2
|
|
)",
|
|
R"(
|
|
%decodefunc2 = OpFunction %f16 None %functy2
|
|
%sb = OpFunctionParameter %sbptr
|
|
%c02 = OpFunctionParameter %arr2
|
|
%c12 = OpFunctionParameter %arr2
|
|
%entry3 = OpLabel
|
|
OpReturnValue %f16_0
|
|
OpFunctionEnd
|
|
)");
|
|
|
|
CompileSuccessfully(spirv.c_str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(
|
|
getDiagnosticString(),
|
|
HasSubstr("first parameter must be pointer to PhysicalStorageBuffer"));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace val
|
|
} // namespace spvtools
|