From 49e59e572efb08d3c918cddacbe4e098d0f98c02 Mon Sep 17 00:00:00 2001 From: nmzik Date: Mon, 7 Sep 2026 04:06:14 +0400 Subject: [PATCH] shader: separate depth comparison and regular image descriptors Co-authored-by: Lordix Co-authored-by: fxpw Co-authored-by: Mac --- .../backend/spirv/spirvEmitterAnalysis.cpp | 3 ++- src/graphics/shader/recompiler/ir/ShaderIR.h | 24 ++++++++++------- tests/ResourceTrackingTests.cpp | 27 ++++++++++++------- tests/ShaderRecompilerComputeTests.cpp | 9 ++++++- 4 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAnalysis.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAnalysis.cpp index 60ada8d76..fbbda2baa 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAnalysis.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAnalysis.cpp @@ -158,7 +158,8 @@ uint32_t ImageType(EmitterState& state, const IR::ImageResource& image) { } const auto& info = ImageDimensionInfoFor(image.dimension); return state.builder.Type(OpTypeImage, - {ImageScalarType(state, image.numeric_class), info.spirv_dimension, 0, + {ImageScalarType(state, image.numeric_class), info.spirv_dimension, + image.depth_compare ? 1u : 0u, info.arrayed, info.multisampled, sampled, format}); } diff --git a/src/graphics/shader/recompiler/ir/ShaderIR.h b/src/graphics/shader/recompiler/ir/ShaderIR.h index 933f1a976..05a08dbec 100644 --- a/src/graphics/shader/recompiler/ir/ShaderIR.h +++ b/src/graphics/shader/recompiler/ir/ShaderIR.h @@ -255,9 +255,10 @@ struct StageOutput { bool operator==(const StageOutput& other) const = default; }; -inline constexpr uint32_t FirstImageBinding = 1u; -inline constexpr uint32_t FirstStorageImageBinding = 22u; -inline constexpr uint32_t ImageBindingCount = 36u; +inline constexpr uint32_t FirstImageBinding = 1u; +inline constexpr uint32_t FirstComparisonImageBinding = 22u; +inline constexpr uint32_t FirstStorageImageBinding = 29u; +inline constexpr uint32_t ImageBindingCount = 43u; enum class DescriptorBindingKind : uint32_t { Buffers = 0u, @@ -270,8 +271,8 @@ enum class DescriptorBindingKind : uint32_t { Count, }; -static_assert(static_cast(DescriptorBindingKind::Samplers) == 37u); -static_assert(static_cast(DescriptorBindingKind::Count) == 43u); +static_assert(static_cast(DescriptorBindingKind::Samplers) == 44u); +static_assert(static_cast(DescriptorBindingKind::Count) == 50u); struct PushData { static constexpr uint32_t DwordCount = 32; @@ -316,9 +317,9 @@ DescriptorBindingForImage(const ImageResource& image) { constexpr uint32_t SampledFloatBinding = 1u; constexpr uint32_t SampledUintBinding = 8u; constexpr uint32_t SampledSintBinding = 15u; - constexpr uint32_t StorageFloatBinding = 22u; - constexpr uint32_t StorageUintBinding = 27u; - constexpr uint32_t AtomicUintBinding = 32u; + constexpr uint32_t StorageFloatBinding = FirstStorageImageBinding; + constexpr uint32_t StorageUintBinding = StorageFloatBinding + 5u; + constexpr uint32_t AtomicUintBinding = StorageUintBinding + 5u; uint32_t base = 0; bool sampled = false; @@ -328,12 +329,17 @@ DescriptorBindingForImage(const ImageResource& image) { } sampled = true; switch (image.numeric_class) { - case Prospero::TextureNumericClass::Float: base = SampledFloatBinding; break; + case Prospero::TextureNumericClass::Float: + base = image.depth_compare ? FirstComparisonImageBinding : SampledFloatBinding; + break; case Prospero::TextureNumericClass::Uint: base = SampledUintBinding; break; case Prospero::TextureNumericClass::Sint: base = SampledSintBinding; break; case Prospero::TextureNumericClass::Unsupported: return std::nullopt; default: return std::nullopt; } + if (image.depth_compare && image.numeric_class != Prospero::TextureNumericClass::Float) { + return std::nullopt; + } } else if (image.resource_class == ImageResourceClass::Storage) { if (image.atomic) { if (image.numeric_class != Prospero::TextureNumericClass::Uint) { diff --git a/tests/ResourceTrackingTests.cpp b/tests/ResourceTrackingTests.cpp index 971e2d457..8d35cc480 100644 --- a/tests/ResourceTrackingTests.cpp +++ b/tests/ResourceTrackingTests.cpp @@ -1617,15 +1617,15 @@ void TestShaderInfoAndBindingLayout() { void TestImageBindingAbi() { using NumericClass = Libs::Graphics::Prospero::TextureNumericClass; - Check(ImageBindingCount == 36u && + Check(ImageBindingCount == 43u && static_cast(DescriptorBindingKind::Buffers) == 0u && - static_cast(DescriptorBindingKind::Samplers) == 37u && - static_cast(DescriptorBindingKind::Gds) == 38u && - static_cast(DescriptorBindingKind::BdaPagetable) == 39u && - static_cast(DescriptorBindingKind::FaultBuffer) == 40u && - static_cast(DescriptorBindingKind::FlattenedSrt) == 41u && - static_cast(DescriptorBindingKind::ShaderData) == 42u && - static_cast(DescriptorBindingKind::Count) == 43u, + static_cast(DescriptorBindingKind::Samplers) == 44u && + static_cast(DescriptorBindingKind::Gds) == 45u && + static_cast(DescriptorBindingKind::BdaPagetable) == 46u && + static_cast(DescriptorBindingKind::FaultBuffer) == 47u && + static_cast(DescriptorBindingKind::FlattenedSrt) == 48u && + static_cast(DescriptorBindingKind::ShaderData) == 49u && + static_cast(DescriptorBindingKind::Count) == 50u, "native descriptor binding anchors changed"); const std::array sampled_dimensions{ @@ -1648,12 +1648,13 @@ void TestImageBindingAbi() { uint32_t index = 0; const auto CheckBinding = [&](ImageResourceClass resource_class, NumericClass numeric_class, - Decoder::ImageDimension dimension, bool atomic) { + Decoder::ImageDimension dimension, bool atomic, bool comparison = false) { ImageResource image; image.resource_class = resource_class; image.numeric_class = numeric_class; image.dimension = dimension; image.atomic = atomic; + image.depth_compare = comparison; const auto kind = DescriptorBindingForImage(image); Check(kind.has_value() && static_cast(*kind) == FirstImageBinding + index && @@ -1673,6 +1674,10 @@ void TestImageBindingAbi() { false); } } + for (const auto dimension : sampled_dimensions) { + CheckBinding(ImageResourceClass::Sampled, NumericClass::Float, dimension, + false, true); + } for (const auto numeric_class : storage_classes) { for (const auto dimension : storage_dimensions) { CheckBinding(ImageResourceClass::Storage, numeric_class, dimension, @@ -1699,6 +1704,10 @@ void TestImageBindingAbi() { image.numeric_class = NumericClass::Unsupported; Check(Invalid(image), "unsupported sampled class received a descriptor binding"); + image.numeric_class = NumericClass::Uint; + image.depth_compare = true; + Check(Invalid(image), "integer comparison image received a descriptor binding"); + image.depth_compare = false; image.numeric_class = static_cast(UINT32_MAX); Check(Invalid(image), "invalid sampled class received a descriptor binding"); image.numeric_class = NumericClass::Float; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 7bf2573bf..763d2e988 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -22307,6 +22307,10 @@ TestCase ImageSampleA16CompareBiasRdna2AddressOrder() { code.push_back(EncodeMimg0(0x2d, 0x1)); code.push_back(EncodeMimg1(0, 20, 0, 0, true)); AppendStoreVgpr(&code, 0, 0); + // Ordinary and comparison reads of one sharp require distinct SPIR-V image types. + code.push_back(EncodeMimg0(0x27, 0x1)); + code.push_back(EncodeMimg1(1, 22, 0, 0, true)); + AppendStoreVgpr(&code, 1, 1); AppendEnd(&code); TestCase test; @@ -22314,7 +22318,9 @@ TestCase ImageSampleA16CompareBiasRdna2AddressOrder() { test.code = code; test.opcodes = {O::V_MOV_B32, O::IMAGE_SAMPLE, O::BUFFER_STORE_DWORD, O::S_ENDPGM}; - test.required_spirv = {"OpImageSampleDrefExplicitLod", "UnpackHalf2x16"}; + test.required_spirv = {"OpTypeImage %float 2D 0", "OpTypeImage %float 2D 1", + "OpImageSampleDrefExplicitLod", "OpImageSampleExplicitLod", + "UnpackHalf2x16"}; test.compile_only = true; return test; } @@ -28097,6 +28103,7 @@ int main(int argc, char **argv) { CheckSampledDepthResource(); CheckDepthTextureEncoding(vulkan.RuntimeRenderer()); vulkan.CheckComparisonDepthTexture(); + RunCase(nullptr, ImageSampleA16CompareBiasRdna2AddressOrder()); return 0; } #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS