mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2025-01-11 09:00:06 +00:00
spirv-val: Add Vulkan Memory Scope VUs (#4106)
* Fix test using Fragment execution
This commit is contained in:
parent
8383bd5d6f
commit
e25db023c4
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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"));
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user