Validate VK_KHR_zero_initialize_workgroup_memory (#4124)

* Allow OpConstantNull for Workgroup variable initializer in Vulkan
environment
* tests
This commit is contained in:
alan-baker 2021-01-27 19:38:09 -05:00 committed by GitHub
parent d71ac38b8e
commit cc81f53d3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 11 deletions

View File

@ -584,16 +584,26 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
storage_class != SpvStorageClassPrivate && storage_class != SpvStorageClassPrivate &&
storage_class != SpvStorageClassFunction) { storage_class != SpvStorageClassFunction) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
return _.diag(SPV_ERROR_INVALID_ID, inst) if (storage_class == SpvStorageClassWorkgroup) {
<< _.VkErrorID(4651) << "OpVariable, <id> '" auto init_id = inst->GetOperandAs<uint32_t>(3);
<< _.getIdName(inst->id()) auto init = _.FindDef(init_id);
<< "', has a disallowed initializer & storage class " if (init->opcode() != SpvOpConstantNull) {
<< "combination.\n" return _.diag(SPV_ERROR_INVALID_ID, inst)
<< "From " << spvLogStringForEnv(_.context()->target_env) << "Variable initializers in Workgroup storage class are "
<< " spec:\n" "limited to OpConstantNull";
<< "Variable declarations that include initializers must have " }
<< "one of the following storage classes: Output, Private, or " } else {
<< "Function"; return _.diag(SPV_ERROR_INVALID_ID, inst)
<< _.VkErrorID(4651) << "OpVariable, <id> '"
<< _.getIdName(inst->id())
<< "', has a disallowed initializer & storage class "
<< "combination.\n"
<< "From " << spvLogStringForEnv(_.context()->target_env)
<< " spec:\n"
<< "Variable declarations that include initializers must have "
<< "one of the following storage classes: Output, Private, "
<< "Function or Workgroup";
}
} }
} }

View File

@ -451,7 +451,8 @@ OpFunctionEnd
HasSubstr("OpVariable, <id> '5[%5]', has a disallowed initializer & " HasSubstr("OpVariable, <id> '5[%5]', has a disallowed initializer & "
"storage class combination.\nFrom Vulkan spec:\nVariable " "storage class combination.\nFrom Vulkan spec:\nVariable "
"declarations that include initializers must have one of the " "declarations that include initializers must have one of the "
"following storage classes: Output, Private, or Function\n %5 " "following storage classes: Output, Private, Function or "
"Workgroup\n %5 "
"= OpVariable %_ptr_Input_float Input %float_1\n")); "= OpVariable %_ptr_Input_float Input %float_1\n"));
} }
@ -4080,6 +4081,55 @@ OpFunctionEnd
"Cannot use a pointer in the PhysicalStorageBuffer storage class")); "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(),
HasSubstr("Variable initializers in Workgroup storage class are "
"limited to OpConstantNull"));
}
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));
}
} // namespace } // namespace
} // namespace val } // namespace val
} // namespace spvtools } // namespace spvtools