diff options
author | alan-baker <alanbaker@google.com> | 2021-01-27 19:38:09 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-27 19:38:09 -0500 |
commit | cc81f53d3d6146638b302694d319a580e4d88f70 (patch) | |
tree | 8dc6b65a1d7a72bcffb97db8a9c4b66e4ba432d2 | |
parent | d71ac38b8ee14f9acad22a3bcb0c294d489bedf4 (diff) | |
download | spirv-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.cpp | 30 | ||||
-rw-r--r-- | test/val/val_memory_test.cpp | 52 |
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 |