mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-26 21:30:07 +00:00
spirv-val: Add Vulkan Execution Scope checks (#4183)
* spirv-val: Add Vulkan Execution Scope checks
This commit is contained in:
parent
8866fd7ae2
commit
c040bd3ae5
@ -105,21 +105,53 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If OpControlBarrier is used in fragment, vertex, tessellation evaluation,
|
// OpControlBarrier must only use Subgroup execution scope for a subset of
|
||||||
// or geometry stages, the execution Scope must be Subgroup.
|
// execution models.
|
||||||
if (opcode == SpvOpControlBarrier && value != SpvScopeSubgroup) {
|
if (opcode == SpvOpControlBarrier && value != SpvScopeSubgroup) {
|
||||||
|
std::string errorVUID = _.VkErrorID(4682);
|
||||||
_.function(inst->function()->id())
|
_.function(inst->function()->id())
|
||||||
->RegisterExecutionModelLimitation([](SpvExecutionModel model,
|
->RegisterExecutionModelLimitation([errorVUID](
|
||||||
|
SpvExecutionModel model,
|
||||||
std::string* message) {
|
std::string* message) {
|
||||||
if (model == SpvExecutionModelFragment ||
|
if (model == SpvExecutionModelFragment ||
|
||||||
model == SpvExecutionModelVertex ||
|
model == SpvExecutionModelVertex ||
|
||||||
model == SpvExecutionModelGeometry ||
|
model == SpvExecutionModelGeometry ||
|
||||||
model == SpvExecutionModelTessellationEvaluation) {
|
model == SpvExecutionModelTessellationEvaluation ||
|
||||||
|
model == SpvExecutionModelRayGenerationKHR ||
|
||||||
|
model == SpvExecutionModelIntersectionKHR ||
|
||||||
|
model == SpvExecutionModelAnyHitKHR ||
|
||||||
|
model == SpvExecutionModelClosestHitKHR ||
|
||||||
|
model == SpvExecutionModelMissKHR) {
|
||||||
if (message) {
|
if (message) {
|
||||||
*message =
|
*message =
|
||||||
"in Vulkan evironment, OpControlBarrier execution scope "
|
errorVUID +
|
||||||
"must be Subgroup for Fragment, Vertex, Geometry and "
|
"in Vulkan environment, OpControlBarrier execution scope "
|
||||||
"TessellationEvaluation execution models";
|
"must be Subgroup for Fragment, Vertex, Geometry, "
|
||||||
|
"TessellationEvaluation, RayGeneration, Intersection, "
|
||||||
|
"AnyHit, ClosestHit, and Miss execution models";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 false;
|
||||||
}
|
}
|
||||||
@ -131,7 +163,7 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _,
|
|||||||
// Scope for execution must be limited to Workgroup or Subgroup
|
// Scope for execution must be limited to Workgroup or Subgroup
|
||||||
if (value != SpvScopeWorkgroup && value != SpvScopeSubgroup) {
|
if (value != SpvScopeWorkgroup && value != SpvScopeSubgroup) {
|
||||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||||
<< spvOpcodeString(opcode)
|
<< _.VkErrorID(4636) << spvOpcodeString(opcode)
|
||||||
<< ": in Vulkan environment Execution Scope is limited to "
|
<< ": in Vulkan environment Execution Scope is limited to "
|
||||||
<< "Workgroup and Subgroup";
|
<< "Workgroup and Subgroup";
|
||||||
}
|
}
|
||||||
|
@ -1680,6 +1680,10 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
|
|||||||
return VUID_WRAP(VUID-StandaloneSpirv-None-04634);
|
return VUID_WRAP(VUID-StandaloneSpirv-None-04634);
|
||||||
case 4635:
|
case 4635:
|
||||||
return VUID_WRAP(VUID-StandaloneSpirv-None-04635);
|
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:
|
case 4638:
|
||||||
return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
|
return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
|
||||||
case 4639:
|
case 4639:
|
||||||
@ -1720,6 +1724,8 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
|
|||||||
return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
|
return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
|
||||||
case 4677:
|
case 4677:
|
||||||
return VUID_WRAP(VUID-StandaloneSpirv-Invariant-04677);
|
return VUID_WRAP(VUID-StandaloneSpirv-Invariant-04677);
|
||||||
|
case 4682:
|
||||||
|
return VUID_WRAP(VUID-StandaloneSpirv-OpControlBarrier-04682);
|
||||||
case 4683:
|
case 4683:
|
||||||
return VUID_WRAP(VUID-StandaloneSpirv-LocalSize-04683);
|
return VUID_WRAP(VUID-StandaloneSpirv-LocalSize-04683);
|
||||||
case 4685:
|
case 4685:
|
||||||
|
@ -345,6 +345,8 @@ OpControlBarrier %device %workgroup %none
|
|||||||
|
|
||||||
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
|
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(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(),
|
EXPECT_THAT(getDiagnosticString(),
|
||||||
HasSubstr("ControlBarrier: in Vulkan environment Execution Scope "
|
HasSubstr("ControlBarrier: in Vulkan environment Execution Scope "
|
||||||
"is limited to Workgroup and Subgroup"));
|
"is limited to Workgroup and Subgroup"));
|
||||||
@ -388,9 +390,10 @@ OpControlBarrier %subgroup %cross_device %none
|
|||||||
"cannot be CrossDevice"));
|
"cannot be CrossDevice"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeFailure) {
|
TEST_F(ValidateBarriers,
|
||||||
|
OpControlBarrierVulkan1p1WorkgroupNonComputeMemoryFailure) {
|
||||||
const std::string body = R"(
|
const std::string body = R"(
|
||||||
OpControlBarrier %workgroup %workgroup %acquire
|
OpControlBarrier %subgroup %workgroup %acquire
|
||||||
)";
|
)";
|
||||||
|
|
||||||
CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
|
CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
|
||||||
@ -402,7 +405,23 @@ OpControlBarrier %workgroup %workgroup %acquire
|
|||||||
"and GLCompute execution model"));
|
"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"(
|
const std::string body = R"(
|
||||||
OpControlBarrier %workgroup %workgroup %acquire
|
OpControlBarrier %workgroup %workgroup %acquire
|
||||||
)";
|
)";
|
||||||
@ -411,6 +430,15 @@ OpControlBarrier %workgroup %workgroup %acquire
|
|||||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
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) {
|
TEST_F(ValidateBarriers, OpControlBarrierVulkanInvocationSuccess) {
|
||||||
const std::string body = R"(
|
const std::string body = R"(
|
||||||
OpControlBarrier %workgroup %invocation %none
|
OpControlBarrier %workgroup %invocation %none
|
||||||
@ -483,9 +511,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
|
|||||||
SPV_ENV_VULKAN_1_1);
|
SPV_ENV_VULKAN_1_1);
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
||||||
EXPECT_THAT(getDiagnosticString(),
|
EXPECT_THAT(getDiagnosticString(),
|
||||||
HasSubstr("OpControlBarrier execution scope must be Subgroup for "
|
AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
|
||||||
"Fragment, Vertex, Geometry and TessellationEvaluation "
|
EXPECT_THAT(
|
||||||
"execution models"));
|
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) {
|
TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p0) {
|
||||||
@ -521,9 +553,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
|
|||||||
SPV_ENV_VULKAN_1_1);
|
SPV_ENV_VULKAN_1_1);
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
||||||
EXPECT_THAT(getDiagnosticString(),
|
EXPECT_THAT(getDiagnosticString(),
|
||||||
HasSubstr("OpControlBarrier execution scope must be Subgroup for "
|
AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
|
||||||
"Fragment, Vertex, Geometry and TessellationEvaluation "
|
EXPECT_THAT(
|
||||||
"execution models"));
|
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) {
|
TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p0) {
|
||||||
@ -561,9 +597,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
|
|||||||
SPV_ENV_VULKAN_1_1);
|
SPV_ENV_VULKAN_1_1);
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
||||||
EXPECT_THAT(getDiagnosticString(),
|
EXPECT_THAT(getDiagnosticString(),
|
||||||
HasSubstr("OpControlBarrier execution scope must be Subgroup for "
|
AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
|
||||||
"Fragment, Vertex, Geometry and TessellationEvaluation "
|
EXPECT_THAT(
|
||||||
"execution models"));
|
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) {
|
TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p0) {
|
||||||
@ -604,9 +644,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
|
|||||||
SPV_ENV_VULKAN_1_1);
|
SPV_ENV_VULKAN_1_1);
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
|
||||||
EXPECT_THAT(getDiagnosticString(),
|
EXPECT_THAT(getDiagnosticString(),
|
||||||
HasSubstr("OpControlBarrier execution scope must be Subgroup for "
|
AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
|
||||||
"Fragment, Vertex, Geometry and TessellationEvaluation "
|
EXPECT_THAT(
|
||||||
"execution models"));
|
getDiagnosticString(),
|
||||||
|
HasSubstr(
|
||||||
|
"OpControlBarrier execution scope must be Subgroup for Fragment, "
|
||||||
|
"Vertex, Geometry, TessellationEvaluation, RayGeneration, "
|
||||||
|
"Intersection, AnyHit, ClosestHit, and Miss execution models"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ValidateBarriers,
|
TEST_F(ValidateBarriers,
|
||||||
@ -1487,6 +1531,8 @@ TEST_F(ValidateBarriers, OpControlBarrierShaderCallRayGenFailure) {
|
|||||||
SPV_ENV_VULKAN_1_1);
|
SPV_ENV_VULKAN_1_1);
|
||||||
|
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(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(),
|
EXPECT_THAT(getDiagnosticString(),
|
||||||
HasSubstr("in Vulkan environment Execution Scope is limited to "
|
HasSubstr("in Vulkan environment Execution Scope is limited to "
|
||||||
"Workgroup and Subgroup"));
|
"Workgroup and Subgroup"));
|
||||||
|
@ -4991,6 +4991,8 @@ TEST_F(ValidateDecorations, UniformDecorationWithScopeIdV14VulkanEnv) {
|
|||||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1_SPIRV_1_4);
|
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1_SPIRV_1_4);
|
||||||
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
||||||
ValidateInstructions(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
|
ValidateInstructions(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
|
||||||
|
EXPECT_THAT(getDiagnosticString(),
|
||||||
|
AnyVUID("VUID-StandaloneSpirv-None-04636"));
|
||||||
EXPECT_THAT(getDiagnosticString(),
|
EXPECT_THAT(getDiagnosticString(),
|
||||||
HasSubstr(": in Vulkan environment Execution Scope is limited to "
|
HasSubstr(": in Vulkan environment Execution Scope is limited to "
|
||||||
"Workgroup and Subgroup"));
|
"Workgroup and Subgroup"));
|
||||||
|
Loading…
Reference in New Issue
Block a user