mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-23 04:00:05 +00:00
Add changes for SPV_EXT_shader_atomic_float (#3562)
This commit is contained in:
parent
5dc96d5d27
commit
e4aebf99fa
@ -413,6 +413,7 @@ bool spvOpcodeIsAtomicWithLoad(const SpvOp opcode) {
|
||||
case SpvOpAtomicIIncrement:
|
||||
case SpvOpAtomicIDecrement:
|
||||
case SpvOpAtomicIAdd:
|
||||
case SpvOpAtomicFAddEXT:
|
||||
case SpvOpAtomicISub:
|
||||
case SpvOpAtomicSMin:
|
||||
case SpvOpAtomicUMin:
|
||||
@ -700,6 +701,7 @@ std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode) {
|
||||
case SpvOpAtomicIIncrement:
|
||||
case SpvOpAtomicIDecrement:
|
||||
case SpvOpAtomicIAdd:
|
||||
case SpvOpAtomicFAddEXT:
|
||||
case SpvOpAtomicISub:
|
||||
case SpvOpAtomicSMin:
|
||||
case SpvOpAtomicUMin:
|
||||
|
@ -214,6 +214,7 @@ bool CodeSinkingPass::HasUniformMemorySync() {
|
||||
case SpvOpAtomicIIncrement:
|
||||
case SpvOpAtomicIDecrement:
|
||||
case SpvOpAtomicIAdd:
|
||||
case SpvOpAtomicFAddEXT:
|
||||
case SpvOpAtomicISub:
|
||||
case SpvOpAtomicSMin:
|
||||
case SpvOpAtomicUMin:
|
||||
|
@ -54,11 +54,16 @@ namespace val {
|
||||
spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
|
||||
const SpvOp opcode = inst->opcode();
|
||||
const uint32_t result_type = inst->type_id();
|
||||
|
||||
bool is_atomic_float_opcode = false;
|
||||
if (opcode == SpvOpAtomicLoad || opcode == SpvOpAtomicStore ||
|
||||
opcode == SpvOpAtomicFAddEXT || opcode == SpvOpAtomicExchange) {
|
||||
is_atomic_float_opcode = true;
|
||||
}
|
||||
switch (opcode) {
|
||||
case SpvOpAtomicLoad:
|
||||
case SpvOpAtomicStore:
|
||||
case SpvOpAtomicExchange:
|
||||
case SpvOpAtomicFAddEXT:
|
||||
case SpvOpAtomicCompareExchange:
|
||||
case SpvOpAtomicCompareExchangeWeak:
|
||||
case SpvOpAtomicIIncrement:
|
||||
@ -92,11 +97,59 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
|
||||
} else if (opcode == SpvOpAtomicFlagClear || opcode == SpvOpAtomicStore) {
|
||||
assert(result_type == 0);
|
||||
} else {
|
||||
if (!_.IsIntScalarType(result_type)) {
|
||||
if (_.IsFloatScalarType(result_type)) {
|
||||
if (is_atomic_float_opcode) {
|
||||
if (opcode == SpvOpAtomicFAddEXT) {
|
||||
if ((_.GetBitWidth(result_type) == 32) &&
|
||||
(!_.HasCapability(SpvCapabilityAtomicFloat32AddEXT))) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": float add atomics require the AtomicFloat32AddEXT "
|
||||
"capability";
|
||||
}
|
||||
if ((_.GetBitWidth(result_type) == 64) &&
|
||||
(!_.HasCapability(SpvCapabilityAtomicFloat64AddEXT))) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": float add atomics require the AtomicFloat64AddEXT "
|
||||
"capability";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": expected Result Type to be int scalar type";
|
||||
}
|
||||
} else if (_.IsIntScalarType(result_type) &&
|
||||
opcode == SpvOpAtomicFAddEXT) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": expected Result Type to be int scalar type";
|
||||
<< ": expected Result Type to be float scalar type";
|
||||
} else if (!_.IsFloatScalarType(result_type) &&
|
||||
!_.IsIntScalarType(result_type)) {
|
||||
switch (opcode) {
|
||||
case SpvOpAtomicFAddEXT:
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": expected Result Type to be float scalar type";
|
||||
case SpvOpAtomicIIncrement:
|
||||
case SpvOpAtomicIDecrement:
|
||||
case SpvOpAtomicIAdd:
|
||||
case SpvOpAtomicISub:
|
||||
case SpvOpAtomicSMin:
|
||||
case SpvOpAtomicSMax:
|
||||
case SpvOpAtomicUMin:
|
||||
case SpvOpAtomicUMax:
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": expected Result Type to be integer scalar type";
|
||||
default:
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": expected Result Type to be int or float scalar type";
|
||||
}
|
||||
}
|
||||
|
||||
if (spvIsVulkanEnv(_.context()->target_env) &&
|
||||
_.GetBitWidth(result_type) != 32) {
|
||||
switch (opcode) {
|
||||
@ -108,11 +161,17 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
|
||||
case SpvOpAtomicOr:
|
||||
case SpvOpAtomicXor:
|
||||
case SpvOpAtomicIAdd:
|
||||
case SpvOpAtomicISub:
|
||||
case SpvOpAtomicFAddEXT:
|
||||
case SpvOpAtomicLoad:
|
||||
case SpvOpAtomicStore:
|
||||
case SpvOpAtomicExchange:
|
||||
case SpvOpAtomicIIncrement:
|
||||
case SpvOpAtomicIDecrement:
|
||||
case SpvOpAtomicCompareExchangeWeak:
|
||||
case SpvOpAtomicCompareExchange: {
|
||||
if (_.GetBitWidth(result_type) == 64 &&
|
||||
_.IsIntScalarType(result_type) &&
|
||||
!_.HasCapability(SpvCapabilityInt64Atomics))
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
|
@ -177,6 +177,8 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
{SpvCapabilityStoragePushConstant16, "StoragePushConstant16"},
|
||||
{SpvCapabilityStorageInputOutput16, "StorageInputOutput16"},
|
||||
{SpvCapabilityDeviceGroup, "DeviceGroup"},
|
||||
{SpvCapabilityAtomicFloat32AddEXT, "AtomicFloat32AddEXT"},
|
||||
{SpvCapabilityAtomicFloat64AddEXT, "AtomicFloat64AddEXT"},
|
||||
{SpvCapabilityMultiView, "MultiView"},
|
||||
{SpvCapabilitySampleMaskOverrideCoverageNV,
|
||||
"SampleMaskOverrideCoverageNV"},
|
||||
|
@ -238,6 +238,120 @@ TEST_F(ValidateAtomics, AtomicLoadInt32VulkanSuccess) {
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicAddIntVulkanWrongType1) {
|
||||
const std::string body = R"(
|
||||
%val1 = OpAtomicIAdd %f32 %f32_var %device %relaxed %f32_1
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("AtomicIAdd: "
|
||||
"expected Result Type to be int scalar type"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicAddIntVulkanWrongType2) {
|
||||
const std::string body = R"(
|
||||
%val1 = OpAtomicIAdd %f32vec4 %f32vec4_var %device %relaxed %f32_1
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("AtomicIAdd: "
|
||||
"expected Result Type to be integer scalar type"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicAddFloatVulkan) {
|
||||
const std::string body = R"(
|
||||
%val1 = OpAtomicFAddEXT %f32 %f32_var %device %relaxed %f32_1
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Opcode AtomicFAddEXT requires one of these capabilities: "
|
||||
"AtomicFloat32AddEXT AtomicFloat64AddEXT"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongType1) {
|
||||
const std::string body = R"(
|
||||
%val1 = OpAtomicFAddEXT %f32vec4 %f32vec4_var %device %relaxed %f32_1
|
||||
)";
|
||||
const std::string extra = R"(
|
||||
OpCapability AtomicFloat32AddEXT
|
||||
OpExtension "SPV_EXT_shader_atomic_float_add"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("AtomicFAddEXT: "
|
||||
"expected Result Type to be float scalar type"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongType2) {
|
||||
const std::string body = R"(
|
||||
%val1 = OpAtomicFAddEXT %u32 %u32_var %device %relaxed %u32_1
|
||||
)";
|
||||
const std::string extra = R"(
|
||||
OpCapability AtomicFloat32AddEXT
|
||||
OpExtension "SPV_EXT_shader_atomic_float_add"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("AtomicFAddEXT: "
|
||||
"expected Result Type to be float scalar type"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongType3) {
|
||||
const std::string body = R"(
|
||||
%val1 = OpAtomicFAddEXT %u64 %u64_var %device %relaxed %u64_1
|
||||
)";
|
||||
const std::string extra = R"(
|
||||
OpCapability AtomicFloat32AddEXT
|
||||
OpExtension "SPV_EXT_shader_atomic_float_add"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("AtomicFAddEXT: "
|
||||
"expected Result Type to be float scalar type"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongCapability) {
|
||||
const std::string body = R"(
|
||||
%val1 = OpAtomicFAddEXT %f32 %f32_var %device %relaxed %f32_1
|
||||
)";
|
||||
const std::string extra = R"(
|
||||
OpCapability AtomicFloat64AddEXT
|
||||
OpExtension "SPV_EXT_shader_atomic_float_add"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("AtomicFAddEXT: float add atomics "
|
||||
"require the AtomicFloat32AddEXT capability"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicAddFloatVulkanSuccess) {
|
||||
const std::string body = R"(
|
||||
%val1 = OpAtomicFAddEXT %f32 %f32_var %device %relaxed %f32_1
|
||||
)";
|
||||
const std::string extra = R"(
|
||||
OpCapability AtomicFloat32AddEXT
|
||||
OpExtension "SPV_EXT_shader_atomic_float_add"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicLoadFloatVulkan) {
|
||||
const std::string body = R"(
|
||||
%val1 = OpAtomicLoad %f32 %f32_var %device %relaxed
|
||||
@ -245,9 +359,25 @@ TEST_F(ValidateAtomics, AtomicLoadFloatVulkan) {
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("expected Result Type to be int scalar type"));
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicStoreFloatVulkan) {
|
||||
const std::string body = R"(
|
||||
OpAtomicStore %f32_var %device %relaxed %f32_1
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicExchangeFloatVulkan) {
|
||||
const std::string body = R"(
|
||||
%val2 = OpAtomicExchange %f32 %f32_var %device %relaxed %f32_0
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicLoadInt64WithCapabilityVulkanSuccess) {
|
||||
@ -355,10 +485,7 @@ TEST_F(ValidateAtomics, AtomicLoadShaderFloat) {
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("AtomicLoad: "
|
||||
"expected Result Type to be int scalar type"));
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicLoadVulkanInt64) {
|
||||
@ -733,10 +860,7 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("AtomicExchange: "
|
||||
"expected Result Type to be int scalar type"));
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicExchangeWrongResultType) {
|
||||
|
Loading…
Reference in New Issue
Block a user