spirv-val: Add Vulkan Execution Scope checks (#4183)

* spirv-val: Add Vulkan Execution Scope checks
This commit is contained in:
sfricke-samsung 2021-03-17 07:00:11 -07:00 committed by GitHub
parent 8866fd7ae2
commit c040bd3ae5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 110 additions and 24 deletions

View File

@ -105,21 +105,30 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _,
}
}
// If OpControlBarrier is used in fragment, vertex, tessellation evaluation,
// or geometry stages, the execution Scope must be Subgroup.
// OpControlBarrier must only use Subgroup execution scope for a subset of
// execution models.
if (opcode == SpvOpControlBarrier && value != SpvScopeSubgroup) {
std::string errorVUID = _.VkErrorID(4682);
_.function(inst->function()->id())
->RegisterExecutionModelLimitation([](SpvExecutionModel model,
std::string* message) {
->RegisterExecutionModelLimitation([errorVUID](
SpvExecutionModel model,
std::string* message) {
if (model == SpvExecutionModelFragment ||
model == SpvExecutionModelVertex ||
model == SpvExecutionModelGeometry ||
model == SpvExecutionModelTessellationEvaluation) {
model == SpvExecutionModelTessellationEvaluation ||
model == SpvExecutionModelRayGenerationKHR ||
model == SpvExecutionModelIntersectionKHR ||
model == SpvExecutionModelAnyHitKHR ||
model == SpvExecutionModelClosestHitKHR ||
model == SpvExecutionModelMissKHR) {
if (message) {
*message =
"in Vulkan evironment, OpControlBarrier execution scope "
"must be Subgroup for Fragment, Vertex, Geometry and "
"TessellationEvaluation execution models";
errorVUID +
"in Vulkan environment, OpControlBarrier execution scope "
"must be Subgroup for Fragment, Vertex, Geometry, "
"TessellationEvaluation, RayGeneration, Intersection, "
"AnyHit, ClosestHit, and Miss execution models";
}
return false;
}
@ -127,11 +136,34 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _,
});
}
// Only subset of execution models support Workgroup.
if (value == SpvScopeWorkgroup) {
std::string errorVUID = _.VkErrorID(4637);
_.function(inst->function()->id())
->RegisterExecutionModelLimitation(
[errorVUID](SpvExecutionModel model, std::string* message) {
if (model != SpvExecutionModelTaskNV &&
model != SpvExecutionModelMeshNV &&
model != SpvExecutionModelTessellationControl &&
model != SpvExecutionModelGLCompute) {
if (message) {
*message =
errorVUID +
"in Vulkan environment, Workgroup execution scope is "
"only for TaskNV, MeshNV, TessellationControl, and "
"GLCompute execution models";
}
return false;
}
return true;
});
}
// Vulkan generic rules
// Scope for execution must be limited to Workgroup or Subgroup
if (value != SpvScopeWorkgroup && value != SpvScopeSubgroup) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< spvOpcodeString(opcode)
<< _.VkErrorID(4636) << spvOpcodeString(opcode)
<< ": in Vulkan environment Execution Scope is limited to "
<< "Workgroup and Subgroup";
}

View File

@ -1680,6 +1680,10 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
return VUID_WRAP(VUID-StandaloneSpirv-None-04634);
case 4635:
return VUID_WRAP(VUID-StandaloneSpirv-None-04635);
case 4636:
return VUID_WRAP(VUID-StandaloneSpirv-None-04636);
case 4637:
return VUID_WRAP(VUID-StandaloneSpirv-None-04637);
case 4638:
return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
case 4639:
@ -1720,6 +1724,8 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
case 4677:
return VUID_WRAP(VUID-StandaloneSpirv-Invariant-04677);
case 4682:
return VUID_WRAP(VUID-StandaloneSpirv-OpControlBarrier-04682);
case 4683:
return VUID_WRAP(VUID-StandaloneSpirv-LocalSize-04683);
case 4685:

View File

@ -345,6 +345,8 @@ OpControlBarrier %device %workgroup %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-04636"));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("ControlBarrier: in Vulkan environment Execution Scope "
"is limited to Workgroup and Subgroup"));
@ -388,9 +390,10 @@ OpControlBarrier %subgroup %cross_device %none
"cannot be CrossDevice"));
}
TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeFailure) {
TEST_F(ValidateBarriers,
OpControlBarrierVulkan1p1WorkgroupNonComputeMemoryFailure) {
const std::string body = R"(
OpControlBarrier %workgroup %workgroup %acquire
OpControlBarrier %subgroup %workgroup %acquire
)";
CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
@ -402,7 +405,23 @@ OpControlBarrier %workgroup %workgroup %acquire
"and GLCompute execution model"));
}
TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeSuccess) {
TEST_F(ValidateBarriers,
OpControlBarrierVulkan1p1WorkgroupNonComputeExecutionFailure) {
const std::string body = R"(
OpControlBarrier %workgroup %subgroup %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-04637"));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("in Vulkan environment, Workgroup execution scope is "
"only for TaskNV, MeshNV, TessellationControl, and "
"GLCompute execution models"));
}
TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupComputeSuccess) {
const std::string body = R"(
OpControlBarrier %workgroup %workgroup %acquire
)";
@ -411,6 +430,15 @@ OpControlBarrier %workgroup %workgroup %acquire
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
}
TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeSuccess) {
const std::string body = R"(
OpControlBarrier %subgroup %subgroup %acquire
)";
CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
}
TEST_F(ValidateBarriers, OpControlBarrierVulkanInvocationSuccess) {
const std::string body = R"(
OpControlBarrier %workgroup %invocation %none
@ -483,9 +511,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("OpControlBarrier execution scope must be Subgroup for "
"Fragment, Vertex, Geometry and TessellationEvaluation "
"execution models"));
AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"OpControlBarrier execution scope must be Subgroup for Fragment, "
"Vertex, Geometry, TessellationEvaluation, RayGeneration, "
"Intersection, AnyHit, ClosestHit, and Miss execution models"));
}
TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p0) {
@ -521,9 +553,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("OpControlBarrier execution scope must be Subgroup for "
"Fragment, Vertex, Geometry and TessellationEvaluation "
"execution models"));
AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"OpControlBarrier execution scope must be Subgroup for Fragment, "
"Vertex, Geometry, TessellationEvaluation, RayGeneration, "
"Intersection, AnyHit, ClosestHit, and Miss execution models"));
}
TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p0) {
@ -561,9 +597,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("OpControlBarrier execution scope must be Subgroup for "
"Fragment, Vertex, Geometry and TessellationEvaluation "
"execution models"));
AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"OpControlBarrier execution scope must be Subgroup for Fragment, "
"Vertex, Geometry, TessellationEvaluation, RayGeneration, "
"Intersection, AnyHit, ClosestHit, and Miss execution models"));
}
TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p0) {
@ -604,9 +644,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("OpControlBarrier execution scope must be Subgroup for "
"Fragment, Vertex, Geometry and TessellationEvaluation "
"execution models"));
AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"OpControlBarrier execution scope must be Subgroup for Fragment, "
"Vertex, Geometry, TessellationEvaluation, RayGeneration, "
"Intersection, AnyHit, ClosestHit, and Miss execution models"));
}
TEST_F(ValidateBarriers,
@ -1487,6 +1531,8 @@ TEST_F(ValidateBarriers, OpControlBarrierShaderCallRayGenFailure) {
SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
AnyVUID("VUID-StandaloneSpirv-None-04636"));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("in Vulkan environment Execution Scope is limited to "
"Workgroup and Subgroup"));

View File

@ -4991,6 +4991,8 @@ TEST_F(ValidateDecorations, UniformDecorationWithScopeIdV14VulkanEnv) {
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1_SPIRV_1_4);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
EXPECT_THAT(getDiagnosticString(),
AnyVUID("VUID-StandaloneSpirv-None-04636"));
EXPECT_THAT(getDiagnosticString(),
HasSubstr(": in Vulkan environment Execution Scope is limited to "
"Workgroup and Subgroup"));