aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralan-baker <alanbaker@google.com>2021-01-27 19:38:09 -0500
committerGitHub <noreply@github.com>2021-01-27 19:38:09 -0500
commitcc81f53d3d6146638b302694d319a580e4d88f70 (patch)
tree8dc6b65a1d7a72bcffb97db8a9c4b66e4ba432d2
parentd71ac38b8ee14f9acad22a3bcb0c294d489bedf4 (diff)
downloadspirv-tools-cc81f53d3d6146638b302694d319a580e4d88f70.tar.gz
Validate VK_KHR_zero_initialize_workgroup_memory (#4124)
* Allow OpConstantNull for Workgroup variable initializer in Vulkan environment * tests
-rw-r--r--source/val/validate_memory.cpp30
-rw-r--r--test/val/val_memory_test.cpp52
2 files changed, 71 insertions, 11 deletions
diff --git a/source/val/validate_memory.cpp b/source/val/validate_memory.cpp
index 45a232da..baa35031 100644
--- a/source/val/validate_memory.cpp
+++ b/source/val/validate_memory.cpp
@@ -584,16 +584,26 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
storage_class != SpvStorageClassPrivate &&
storage_class != SpvStorageClassFunction) {
if (spvIsVulkanEnv(_.context()->target_env)) {
- 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, or "
- << "Function";
+ if (storage_class == SpvStorageClassWorkgroup) {
+ auto init_id = inst->GetOperandAs<uint32_t>(3);
+ auto init = _.FindDef(init_id);
+ if (init->opcode() != SpvOpConstantNull) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "Variable initializers in Workgroup storage class are "
+ "limited to OpConstantNull";
+ }
+ } else {
+ 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";
+ }
}
}
diff --git a/test/val/val_memory_test.cpp b/test/val/val_memory_test.cpp
index 8142f859..0d97c66b 100644
--- a/test/val/val_memory_test.cpp
+++ b/test/val/val_memory_test.cpp
@@ -451,7 +451,8 @@ OpFunctionEnd
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, or Function\n %5 "
+ "following storage classes: Output, Private, Function or "
+ "Workgroup\n %5 "
"= OpVariable %_ptr_Input_float Input %float_1\n"));
}
@@ -4080,6 +4081,55 @@ OpFunctionEnd
"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 val
} // namespace spvtools