mirror of
https://gitee.com/openharmony/third_party_spirv-tools
synced 2024-11-28 01:50:54 +00:00
Validate variable types for UniformConstant storage in Vulkan (#2008) From the Vulkan 1.1 spec 14.5.2: 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, or an array of one of these types. Fixes #2008
This commit is contained in:
parent
dc9d155d62
commit
a362e60d5a
@ -19,6 +19,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "source/opcode.h"
|
||||
#include "source/spirv_target_env.h"
|
||||
#include "source/val/instruction.h"
|
||||
#include "source/val/validation_state.h"
|
||||
|
||||
@ -323,6 +324,35 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
|
||||
<< "Classes: Workgroup, CrossWorkgroup, Private, and Function";
|
||||
}
|
||||
}
|
||||
|
||||
// Check that UniformConstant variables are the correct type, see Vulkan spec
|
||||
// section 14.5.2 for details.
|
||||
if (spvIsVulkanEnv(_.context()->target_env) &&
|
||||
storage_class == SpvStorageClassUniformConstant) {
|
||||
auto variable_type = _.FindDef(result_type->GetOperandAs<uint32_t>(2));
|
||||
auto variable_type_opcode = variable_type->opcode();
|
||||
|
||||
// If the variable is actually an array extract the element type.
|
||||
if (variable_type_opcode == SpvOpTypeArray) {
|
||||
variable_type = _.FindDef(variable_type->GetOperandAs<uint32_t>(1));
|
||||
variable_type_opcode = variable_type->opcode();
|
||||
}
|
||||
|
||||
switch (variable_type_opcode) {
|
||||
case SpvOpTypeImage:
|
||||
case SpvOpTypeSampler:
|
||||
case SpvOpTypeSampledImage:
|
||||
break;
|
||||
default:
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "From Vulkan spec, section 14.5.2:\n"
|
||||
<< "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, or an array of one of these types.";
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,7 @@ add_spvtools_unittest(TARGET val_ijklmnop
|
||||
val_layout_test.cpp
|
||||
val_literals_test.cpp
|
||||
val_logicals_test.cpp
|
||||
val_memory_test.cpp
|
||||
val_modes_test.cpp
|
||||
val_non_uniform_test.cpp
|
||||
val_primitives_test.cpp
|
||||
|
@ -1203,7 +1203,7 @@ INSTANTIATE_TEST_CASE_P(
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SampleMaskWrongStorageClass,
|
||||
ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
|
||||
Combine(Values("SampleMask"), Values("Fragment"), Values("UniformConstant"),
|
||||
Combine(Values("SampleMask"), Values("Fragment"), Values("Uniform"),
|
||||
Values("%u32arr2"),
|
||||
Values(TestResult(
|
||||
SPV_ERROR_INVALID_DATA,
|
||||
|
@ -621,12 +621,12 @@ TEST_F(ValidateDecorations, RuntimeArrayOfDescriptorSetsIsAllowed) {
|
||||
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%11 = OpTypeSampledImage %10
|
||||
%_runtimearr_11 = OpTypeRuntimeArray %11
|
||||
%_ptr_UniformConstant__runtimearr_11 = OpTypePointer UniformConstant %_runtimearr_11
|
||||
%s2d = OpVariable %_ptr_UniformConstant__runtimearr_11 UniformConstant
|
||||
%_ptr_Uniform__runtimearr_11 = OpTypePointer Uniform %_runtimearr_11
|
||||
%s2d = OpVariable %_ptr_Uniform__runtimearr_11 Uniform
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Input_int = OpTypePointer Input %int
|
||||
%i = OpVariable %_ptr_Input_int Input
|
||||
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
|
||||
%_ptr_Uniform_11 = OpTypePointer Uniform %11
|
||||
%v2float = OpTypeVector %float 2
|
||||
%float_0_300000012 = OpConstant %float 0.300000012
|
||||
%24 = OpConstantComposite %v2float %float_0_300000012 %float_0_300000012
|
||||
@ -635,7 +635,7 @@ TEST_F(ValidateDecorations, RuntimeArrayOfDescriptorSetsIsAllowed) {
|
||||
%5 = OpLabel
|
||||
%v = OpVariable %_ptr_Function_v4float Function
|
||||
%18 = OpLoad %int %i
|
||||
%20 = OpAccessChain %_ptr_UniformConstant_11 %s2d %18
|
||||
%20 = OpAccessChain %_ptr_Uniform_11 %s2d %18
|
||||
%21 = OpLoad %11 %20
|
||||
%26 = OpImageSampleExplicitLod %v4float %21 %24 Lod %float_0
|
||||
OpStore %v %26
|
||||
@ -689,12 +689,12 @@ TEST_F(ValidateDecorations, RuntimeArrayOfArraysOfDescriptorSetsIsDisallowed) {
|
||||
%uint_2 = OpConstant %uint 2
|
||||
%_arr_11_uint_2 = OpTypeArray %11 %uint_2
|
||||
%_runtimearr__arr_11_uint_2 = OpTypeRuntimeArray %_arr_11_uint_2
|
||||
%_ptr_UniformConstant__runtimearr__arr_11_uint_2 = OpTypePointer UniformConstant %_runtimearr__arr_11_uint_2
|
||||
%s2d = OpVariable %_ptr_UniformConstant__runtimearr__arr_11_uint_2 UniformConstant
|
||||
%_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_UniformConstant_11 = OpTypePointer UniformConstant %11
|
||||
%_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
|
||||
@ -704,7 +704,7 @@ TEST_F(ValidateDecorations, RuntimeArrayOfArraysOfDescriptorSetsIsDisallowed) {
|
||||
%v = OpVariable %_ptr_Function_v4float Function
|
||||
%21 = OpLoad %int %i
|
||||
%22 = OpLoad %int %i
|
||||
%24 = OpAccessChain %_ptr_UniformConstant_11 %s2d %21 %22
|
||||
%24 = OpAccessChain %_ptr_Uniform_11 %s2d %21 %22
|
||||
%25 = OpLoad %11 %24
|
||||
%30 = OpImageSampleExplicitLod %v4float %25 %28 Lod %float_0
|
||||
OpStore %v %30
|
||||
@ -744,8 +744,8 @@ TEST_F(ValidateDecorations, ArrayOfArraysOfDescriptorSetsIsDisallowed) {
|
||||
%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_UniformConstant__arr__arr_8_uint_2_uint_2 = OpTypePointer UniformConstant %_arr__arr_8_uint_2_uint_2
|
||||
%variableName = OpVariable %_ptr_UniformConstant__arr__arr_8_uint_2_uint_2 UniformConstant
|
||||
%_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
|
||||
|
135
test/val/val_memory_test.cpp
Normal file
135
test/val/val_memory_test.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
// 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_fixtures.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace val {
|
||||
namespace {
|
||||
|
||||
using ::testing::Eq;
|
||||
using ::testing::HasSubstr;
|
||||
|
||||
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(),
|
||||
HasSubstr("From Vulkan spec, section 14.5.2:\n"
|
||||
"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, 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
|
||||
%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(),
|
||||
HasSubstr("From Vulkan spec, section 14.5.2:\n"
|
||||
"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, 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
|
||||
%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));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
Loading…
Reference in New Issue
Block a user