Add changes for SPV_EXT_shader_atomic_float (#3562)

This commit is contained in:
vkushwaha-nv 2020-07-21 07:31:05 -07:00 committed by GitHub
parent 5dc96d5d27
commit e4aebf99fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 202 additions and 14 deletions

View File

@ -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:

View File

@ -214,6 +214,7 @@ bool CodeSinkingPass::HasUniformMemorySync() {
case SpvOpAtomicIIncrement:
case SpvOpAtomicIDecrement:
case SpvOpAtomicIAdd:
case SpvOpAtomicFAddEXT:
case SpvOpAtomicISub:
case SpvOpAtomicSMin:
case SpvOpAtomicUMin:

View File

@ -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 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)

View File

@ -177,6 +177,8 @@ INSTANTIATE_TEST_SUITE_P(
{SpvCapabilityStoragePushConstant16, "StoragePushConstant16"},
{SpvCapabilityStorageInputOutput16, "StorageInputOutput16"},
{SpvCapabilityDeviceGroup, "DeviceGroup"},
{SpvCapabilityAtomicFloat32AddEXT, "AtomicFloat32AddEXT"},
{SpvCapabilityAtomicFloat64AddEXT, "AtomicFloat64AddEXT"},
{SpvCapabilityMultiView, "MultiView"},
{SpvCapabilitySampleMaskOverrideCoverageNV,
"SampleMaskOverrideCoverageNV"},

View File

@ -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) {