diff --git a/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp b/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp index b8063ccd5..929697611 100644 --- a/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp @@ -309,7 +309,8 @@ void ValidateStorageTexture(const ShaderRecompiler::IR::ImageResource& resource, const bool encoding_ok = IsSupportedStorageTextureEncoding(resource, descriptor); const bool uint_resource = resource.numeric_class == Prospero::TextureNumericClass::Uint; const bool raw_sint_storage = format == Prospero::BufferFormat::k32SInt && uint_resource && - resource.written && !resource.read && !resource.atomic; + resource.written && + (resource.atomic ? !resource.atomic64 : !resource.read); const auto numeric_class = Prospero::SampledTextureNumericClass(format); const bool raw_float_atomic = format == Prospero::BufferFormat::k32Float && uint_resource && resource.atomic && !resource.atomic64; diff --git a/src/graphics/shader/recompiler/ir/passes/ResourceMaterialization.cpp b/src/graphics/shader/recompiler/ir/passes/ResourceMaterialization.cpp index bd9fabb0d..c05d9cf41 100644 --- a/src/graphics/shader/recompiler/ir/passes/ResourceMaterialization.cpp +++ b/src/graphics/shader/recompiler/ir/passes/ResourceMaterialization.cpp @@ -630,6 +630,7 @@ static bool BuildResourceSpecialization(const ResourcePlan& program, ResourceSna if (base.atomic && (base.atomic64 ? format != Prospero::BufferFormat::k32_32UInt : format != Prospero::BufferFormat::k32UInt && + format != Prospero::BufferFormat::k32SInt && format != Prospero::BufferFormat::k32Float)) { return SpecializationFail( fmt::format("atomic image descriptor {} uses unsupported format {}", i, @@ -650,7 +651,7 @@ static bool BuildResourceSpecialization(const ResourcePlan& program, ResourceSna image.shader_swizzle = DescriptorImageSwizzle(descriptor); } const bool raw_sint_storage = storage && format == Prospero::BufferFormat::k32SInt && - base.written && !base.read && !base.atomic; + base.written && (base.atomic ? !base.atomic64 : !base.read); image.numeric_class = Prospero::SampledTextureNumericClass(format); if (storage) { if ((!raw_sint_storage && image.numeric_class == Prospero::TextureNumericClass::Sint) || diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index f0464bccc..25206b803 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -37202,7 +37202,7 @@ TestCase ImageStoreAndAtomicUseSeparateBindings() { return test; } -TestCase ImageAtomicVariants() { +template TestCase ImageAtomicVariants() { using O = ShaderOpcode; const u32 initial[] = {10, 10, 0xf0f0u, 0xf000u, 0xf00fu}; @@ -37222,7 +37222,10 @@ TestCase ImageAtomicVariants() { AppendEnd(&code); TestCase test; - test.name = "ImageAtomicVariants"; + test.name = signed_format ? "ImageAtomicSintVariants" : "ImageAtomicVariants"; + test.user_data = MakeStorageTextureData(signed_format ? Prospero::BufferFormat::k32SInt + : Prospero::BufferFormat::k32UInt); + test.has_user_data = true; test.code = code; test.expected = {10, 10, 0xf0f0u, 0xf000u, 0xf00fu}; test.opcodes = {O::V_MOV_B32, O::IMAGE_ATOMIC_ADD, @@ -37370,7 +37373,7 @@ TestCase ImageAtomicIntegerGlcAndExec(const ImageAtomicIntegerCase &atomic, bool return test; } -template TestCase ImageAtomicSignedMinMax() { +template TestCase ImageAtomicSignedMinMax() { using O = ShaderOpcode; // Input, old value, signed minimum, signed maximum. constexpr u32 values[][4] = { @@ -37383,8 +37386,11 @@ template TestCase ImageAtomicSignedMinMax() { {2, 8, 2, 8}, {8, 2, 2, 8}, }; TestCase test; - test.name = max_value ? "ImageAtomicSMaxGlcAndExec" : "ImageAtomicSMinGlcAndExec"; - test.user_data = MakeStorageTextureData(Prospero::BufferFormat::k32UInt); + test.name = signed_format + ? (max_value ? "ImageAtomicSMaxSintGlcAndExec" : "ImageAtomicSMinSintGlcAndExec") + : (max_value ? "ImageAtomicSMaxGlcAndExec" : "ImageAtomicSMinGlcAndExec"); + test.user_data = MakeStorageTextureData(signed_format ? Prospero::BufferFormat::k32SInt + : Prospero::BufferFormat::k32UInt); test.has_user_data = true; test.storage_image_r32ui.assign(16, 0); test.expected_storage_image_r32ui = test.storage_image_r32ui; @@ -38479,6 +38485,8 @@ std::vector MakeCases() { AddCase(BufferAtomicAndX2GlcAndExec); AddCase(ImageAtomicSignedMinMax); AddCase(ImageAtomicSignedMinMax); + AddCase(ImageAtomicSignedMinMax); + AddCase(ImageAtomicSignedMinMax); for (bool decrement : {false, true}) { for (bool gds : {false, true}) { cases.push_back(DsBoundedAtomicBoundaries(decrement, gds)); @@ -38569,7 +38577,8 @@ std::vector MakeCases() { AddCase(ImageAtomicCompareSwapGlcAndExec); AddCase(ImageAtomicSwapReturnsPreviousTexel); AddCase(ImageStoreAndAtomicUseSeparateBindings); - AddCase(ImageAtomicVariants); + AddCase(ImageAtomicVariants<>); + AddCase(ImageAtomicVariants); for (const auto &atomic : ImageAtomicIntegerCases) { cases.push_back(ImageAtomicIntegerGlcAndExec(atomic, false)); cases.push_back(ImageAtomicIntegerGlcAndExec(atomic, true)); @@ -44385,6 +44394,9 @@ int main(int argc, char **argv) { RunCase(&vulkan, ImageAtomicCompareSwapGlcAndExec()); RunCase(&vulkan, ImageAtomicSwapReturnsPreviousTexel()); RunCase(&vulkan, ImageAtomicVariants()); + RunCase(&vulkan, ImageAtomicVariants()); + RunCase(&vulkan, ImageAtomicSignedMinMax()); + RunCase(&vulkan, ImageAtomicSignedMinMax()); return 0; } if (argc == 2 && std::strcmp(argv[1], "--image-atomic64-only") == 0) {