spirv-val: Add Vulkan FP Mode VUID (#4088)
This commit is contained in:
Родитель
6d05ed8410
Коммит
94d1a80159
|
@ -1260,7 +1260,8 @@ spv_result_t CheckVulkanMemoryModelDeprecatedDecorations(
|
|||
// decorations. Otherwise emits a diagnostic and returns something other than
|
||||
// SPV_SUCCESS.
|
||||
spv_result_t CheckFPRoundingModeForShaders(ValidationState_t& vstate,
|
||||
const Instruction& inst) {
|
||||
const Instruction& inst,
|
||||
const Decoration& decoration) {
|
||||
// Validates width-only conversion instruction for floating-point object
|
||||
// i.e., OpFConvert
|
||||
if (inst.opcode() != SpvOpFConvert) {
|
||||
|
@ -1270,6 +1271,15 @@ spv_result_t CheckFPRoundingModeForShaders(ValidationState_t& vstate,
|
|||
"object.";
|
||||
}
|
||||
|
||||
if (spvIsVulkanEnv(vstate.context()->target_env)) {
|
||||
const auto mode = decoration.params()[0];
|
||||
if ((mode != SpvFPRoundingModeRTE) && (mode != SpvFPRoundingModeRTZ)) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
|
||||
<< vstate.VkErrorID(4675)
|
||||
<< "In Vulkan, the FPRoundingMode mode must only by RTE or RTZ.";
|
||||
}
|
||||
}
|
||||
|
||||
// Validates Object operand of an OpStore
|
||||
for (const auto& use : inst.uses()) {
|
||||
const auto store = use.first;
|
||||
|
@ -1588,7 +1598,8 @@ spv_result_t CheckDecorationsFromDecoration(ValidationState_t& vstate) {
|
|||
break;
|
||||
case SpvDecorationFPRoundingMode:
|
||||
if (is_shader)
|
||||
PASS_OR_BAIL(CheckFPRoundingModeForShaders(vstate, *inst));
|
||||
PASS_OR_BAIL(
|
||||
CheckFPRoundingModeForShaders(vstate, *inst, decoration));
|
||||
break;
|
||||
case SpvDecorationNonWritable:
|
||||
PASS_OR_BAIL(CheckNonWritableDecoration(vstate, *inst, decoration));
|
||||
|
|
|
@ -1671,6 +1671,8 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
|
|||
return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04656);
|
||||
case 4658:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-OpImageTexelPointer-04658);
|
||||
case 4675:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
|
||||
case 4685:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685);
|
||||
case 4711:
|
||||
|
|
|
@ -4679,6 +4679,95 @@ OpFunctionEnd
|
|||
"Object operand of an OpStore."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, VulkanFPRoundingModeGood) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpCapability StorageBuffer16BitAccess
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %main "main" %_
|
||||
OpExecutionMode %main LocalSize 1 1 1
|
||||
OpMemberDecorate %ssbo 0 Offset 0
|
||||
OpDecorate %ssbo Block
|
||||
OpDecorate %_ DescriptorSet 0
|
||||
OpDecorate %_ Binding 0
|
||||
OpDecorate %17 FPRoundingMode RTE
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%float_1 = OpConstant %float 1
|
||||
%half = OpTypeFloat 16
|
||||
%ssbo = OpTypeStruct %half
|
||||
%_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo
|
||||
%_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%_ptr_StorageBuffer_half = OpTypePointer StorageBuffer %half
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%b = OpVariable %_ptr_Function_float Function
|
||||
OpStore %b %float_1
|
||||
%16 = OpLoad %float %b
|
||||
%17 = OpFConvert %half %16
|
||||
%19 = OpAccessChain %_ptr_StorageBuffer_half %_ %int_0
|
||||
OpStore %19 %17
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_EQ(SPV_SUCCESS,
|
||||
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, VulkanFPRoundingModeBadMode) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpCapability StorageBuffer16BitAccess
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %main "main" %_
|
||||
OpExecutionMode %main LocalSize 1 1 1
|
||||
OpMemberDecorate %ssbo 0 Offset 0
|
||||
OpDecorate %ssbo Block
|
||||
OpDecorate %_ DescriptorSet 0
|
||||
OpDecorate %_ Binding 0
|
||||
OpDecorate %17 FPRoundingMode RTP
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%float_1 = OpConstant %float 1
|
||||
%half = OpTypeFloat 16
|
||||
%ssbo = OpTypeStruct %half
|
||||
%_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo
|
||||
%_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%_ptr_StorageBuffer_half = OpTypePointer StorageBuffer %half
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%b = OpVariable %_ptr_Function_float Function
|
||||
OpStore %b %float_1
|
||||
%16 = OpLoad %float %b
|
||||
%17 = OpFConvert %half %16
|
||||
%19 = OpAccessChain %_ptr_StorageBuffer_half %_ %int_0
|
||||
OpStore %19 %17
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID,
|
||||
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
AnyVUID("VUID-StandaloneSpirv-FPRoundingMode-04675"));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("In Vulkan, the FPRoundingMode mode must only by RTE or RTZ."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
|
|
Загрузка…
Ссылка в новой задаче