spirv-val: Add Vulkan Memory Scope VUs (#4106)

* Fix test using Fragment execution
This commit is contained in:
sfricke-samsung 2021-01-19 05:37:42 -08:00 committed by GitHub
parent 8383bd5d6f
commit e25db023c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 110 additions and 13 deletions

View File

@ -190,7 +190,7 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst,
if (spvIsVulkanEnv(_.context()->target_env)) {
if (value == SpvScopeCrossDevice) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< spvOpcodeString(opcode)
<< _.VkErrorID(4638) << spvOpcodeString(opcode)
<< ": in Vulkan environment, Memory Scope cannot be CrossDevice";
}
// Vulkan 1.0 specifc rules
@ -198,7 +198,7 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst,
value != SpvScopeDevice && value != SpvScopeWorkgroup &&
value != SpvScopeInvocation) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< spvOpcodeString(opcode)
<< _.VkErrorID(4638) << spvOpcodeString(opcode)
<< ": in Vulkan 1.0 environment Memory Scope is limited to "
<< "Device, Workgroup and Invocation";
}
@ -209,15 +209,16 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst,
value != SpvScopeSubgroup && value != SpvScopeInvocation &&
value != SpvScopeShaderCallKHR) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< spvOpcodeString(opcode)
<< _.VkErrorID(4638) << spvOpcodeString(opcode)
<< ": in Vulkan 1.1 and 1.2 environment Memory Scope is limited "
<< "to Device, Workgroup, Invocation, and ShaderCall";
}
if (value == SpvScopeShaderCallKHR) {
std::string errorVUID = _.VkErrorID(4640);
_.function(inst->function()->id())
->RegisterExecutionModelLimitation(
[](SpvExecutionModel model, std::string* message) {
[errorVUID](SpvExecutionModel model, std::string* message) {
if (model != SpvExecutionModelRayGenerationKHR &&
model != SpvExecutionModelIntersectionKHR &&
model != SpvExecutionModelAnyHitKHR &&
@ -226,6 +227,7 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst,
model != SpvExecutionModelCallableKHR) {
if (message) {
*message =
errorVUID +
"ShaderCallKHR Memory Scope requires a ray tracing "
"execution model";
}
@ -234,6 +236,25 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst,
return true;
});
}
if (value == SpvScopeWorkgroup) {
std::string errorVUID = _.VkErrorID(4639);
_.function(inst->function()->id())
->RegisterExecutionModelLimitation(
[errorVUID](SpvExecutionModel model, std::string* message) {
if (model != SpvExecutionModelGLCompute &&
model != SpvExecutionModelTaskNV &&
model != SpvExecutionModelMeshNV) {
if (message) {
*message = errorVUID +
"Workgroup Memory Scope is limited to MeshNV, "
"TaskNV, and GLCompute execution model";
}
return false;
}
return true;
});
}
}
// TODO(atgoo@github.com) Add checks for OpenCL and OpenGL environments.

View File

@ -1652,6 +1652,12 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
return VUID_WRAP(VUID-StandaloneSpirv-None-04633);
case 4635:
return VUID_WRAP(VUID-StandaloneSpirv-None-04635);
case 4638:
return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
case 4639:
return VUID_WRAP(VUID-StandaloneSpirv-None-04639);
case 4640:
return VUID_WRAP(VUID-StandaloneSpirv-None-04640);
case 4642:
return VUID_WRAP(VUID-StandaloneSpirv-None-04642);
case 4649:

View File

@ -30,16 +30,16 @@ using ValidateAtomics = spvtest::ValidateBase<bool>;
std::string GenerateShaderCodeImpl(
const std::string& body, const std::string& capabilities_and_extensions,
const std::string& definitions, const std::string& memory_model) {
const std::string& definitions, const std::string& memory_model,
const std::string& execution) {
std::ostringstream ss;
ss << R"(
OpCapability Shader
)";
ss << capabilities_and_extensions;
ss << "OpMemoryModel Logical " << memory_model << "\n";
ss << execution;
ss << R"(
OpEntryPoint Fragment %main "main"
OpExecutionMode %main OriginUpperLeft
%void = OpTypeVoid
%func = OpTypeFunction %void
%bool = OpTypeBool
@ -96,6 +96,10 @@ std::string GenerateShaderCode(
const std::string& body,
const std::string& capabilities_and_extensions = "",
const std::string& memory_model = "GLSL450") {
const std::string execution = R"(
OpEntryPoint Fragment %main "main"
OpExecutionMode %main OriginUpperLeft
)";
const std::string defintions = R"(
%u64 = OpTypeInt 64 0
%s64 = OpTypeInt 64 1
@ -110,7 +114,32 @@ std::string GenerateShaderCode(
)";
return GenerateShaderCodeImpl(
body, "OpCapability Int64\n" + capabilities_and_extensions, defintions,
memory_model);
memory_model, execution);
}
std::string GenerateShaderComputeCode(
const std::string& body,
const std::string& capabilities_and_extensions = "",
const std::string& memory_model = "GLSL450") {
const std::string execution = R"(
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 32 1 1
)";
const std::string defintions = R"(
%u64 = OpTypeInt 64 0
%s64 = OpTypeInt 64 1
%u64_1 = OpConstant %u64 1
%s64_1 = OpConstant %s64 1
%u64_ptr = OpTypePointer Workgroup %u64
%s64_ptr = OpTypePointer Workgroup %s64
%u64_var = OpVariable %u64_ptr Workgroup
%s64_var = OpVariable %s64_ptr Workgroup
)";
return GenerateShaderCodeImpl(
body, "OpCapability Int64\n" + capabilities_and_extensions, defintions,
memory_model, execution);
}
std::string GenerateKernelCode(
@ -217,7 +246,7 @@ TEST_F(ValidateAtomics, AtomicLoadInt32VulkanSuccess) {
%val2 = OpAtomicLoad %u32 %u32_var %workgroup %acquire
)";
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
}
@ -341,7 +370,7 @@ TEST_F(ValidateAtomics, AtomicLoadFloatVulkan) {
%val2 = OpAtomicLoad %f32 %f32_var %workgroup %acquire
)";
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
}
@ -369,8 +398,9 @@ TEST_F(ValidateAtomics, AtomicLoadInt64WithCapabilityVulkanSuccess) {
%val2 = OpAtomicLoad %u64 %u64_var %workgroup %acquire
)";
CompileSuccessfully(GenerateShaderCode(body, "OpCapability Int64Atomics\n"),
SPV_ENV_VULKAN_1_0);
CompileSuccessfully(
GenerateShaderComputeCode(body, "OpCapability Int64Atomics\n"),
SPV_ENV_VULKAN_1_0);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
}
@ -380,7 +410,7 @@ TEST_F(ValidateAtomics, AtomicLoadInt64WithoutCapabilityVulkan) {
%val2 = OpAtomicLoad %u64 %u64_var %workgroup %acquire
)";
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("64-bit atomics require the Int64Atomics capability"));

View File

@ -121,6 +121,15 @@ OpCapability Int64
execution_model, memory_model);
}
std::string GenerateVulkanVertexShaderCode(
const std::string& body,
const std::string& capabilities_and_extensions = "",
const std::string& execution_model = "Vertex") {
const std::string memory_model = "OpMemoryModel Logical GLSL450";
return GenerateShaderCodeImpl(body, capabilities_and_extensions, "",
execution_model, memory_model);
}
std::string GenerateKernelCode(
const std::string& body,
const std::string& capabilities_and_extensions = "") {
@ -348,6 +357,8 @@ OpControlBarrier %subgroup %subgroup %none
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_THAT(getDiagnosticString(),
AnyVUID("VUID-StandaloneSpirv-None-04638"));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("ControlBarrier: in Vulkan 1.0 environment Memory Scope is "
@ -370,11 +381,36 @@ OpControlBarrier %subgroup %cross_device %none
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
AnyVUID("VUID-StandaloneSpirv-None-04638"));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("ControlBarrier: in Vulkan environment, Memory Scope "
"cannot be CrossDevice"));
}
TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeFailure) {
const std::string body = R"(
OpControlBarrier %workgroup %workgroup %acquire
)";
CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
AnyVUID("VUID-StandaloneSpirv-None-04639"));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Workgroup Memory Scope is limited to MeshNV, TaskNV, "
"and GLCompute execution model"));
}
TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeSuccess) {
const std::string body = R"(
OpControlBarrier %workgroup %workgroup %acquire
)";
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
}
TEST_F(ValidateBarriers, OpControlBarrierAcquireAndRelease) {
const std::string body = R"(
OpControlBarrier %device %device %acquire_and_release_uniform
@ -647,6 +683,8 @@ OpMemoryBarrier %subgroup %acquire_release_uniform_workgroup
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_THAT(getDiagnosticString(),
AnyVUID("VUID-StandaloneSpirv-None-04638"));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("MemoryBarrier: in Vulkan 1.0 environment Memory Scope is "
@ -1397,6 +1435,8 @@ TEST_F(ValidateBarriers, OpMemoryBarrierShaderCallComputeFailure) {
SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
AnyVUID("VUID-StandaloneSpirv-None-04640"));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(