From df385a7aadd751b63b85fe3162ed3bc667f9d60d Mon Sep 17 00:00:00 2001 From: nmzik Date: Sat, 18 Jul 2026 03:52:30 +0200 Subject: [PATCH] broad depth guards --- .../host_gpu/renderer/descriptors.cpp | 30 ++++++++++++------- src/graphics/host_gpu/renderer/descriptors.h | 12 ++++++++ src/graphics/host_gpu/renderer/imageView.h | 3 +- tests/ShaderRecompilerComputeTests.cpp | 27 +++++++++++++++-- 4 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/graphics/host_gpu/renderer/descriptors.cpp b/src/graphics/host_gpu/renderer/descriptors.cpp index eea1e731d..f3d98f7b0 100644 --- a/src/graphics/host_gpu/renderer/descriptors.cpp +++ b/src/graphics/host_gpu/renderer/descriptors.cpp @@ -299,13 +299,7 @@ static bool IsSupportedSampledColorResource(const ShaderRecompiler::IR::ImageRes !resource.written && !resource.atomic && !resource.depth_compare; } -struct TargetTextureViewInfo { - VkImageViewType type = VK_IMAGE_VIEW_TYPE_MAX_ENUM; - uint32_t base_layer = 0; - uint32_t layer_count = 0; -}; - -static TargetTextureViewInfo +TargetTextureViewInfo ResolveTargetTextureView(const ShaderRecompiler::IR::ImageResource& resource, Prospero::ImageType type, uint32_t base_layer, uint32_t image_layers) { switch (type) { @@ -343,12 +337,15 @@ bool IsSupportedDepthTargetDescriptor(const ShaderTextureResource& descriptor, const auto width = static_cast(descriptor.Width5()) + 1u; const auto height = static_cast(descriptor.Height5()) + 1u; const auto pitch = TileGetTexturePitch(descriptor.Format(), width, 1, descriptor.TileMode()); + const auto type = static_cast(descriptor.Type()); + const bool supported_type = type == Prospero::ImageType::kColor2D || + type == Prospero::ImageType::kColor2DArray; return image.type == VulkanImageType::DepthStencil && image.layers == 1 && width == image.extent.width && height == image.extent.height && descriptor.Depth() == 0 && descriptor.BaseLevel() == 0 && descriptor.LastLevel() == 0 && descriptor.MaxMip() == 0 && descriptor.MinLod() == 0 && descriptor.BaseArray5() == 0 && descriptor.TileMode() == Prospero::GpuEnumValue(Prospero::TileMode::kDepth) && - descriptor.Type() == Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) && + supported_type && descriptor.BCSwizzle() == 0 && !descriptor.MsaaDepth() && pitch >= width && pitch == image.guest_pitch; } @@ -356,11 +353,13 @@ bool IsSupportedDepthTargetDescriptor(const ShaderTextureResource& descriptor, static bool IsSupportedDepthTextureEncoding(const ShaderTextureResource& descriptor) { constexpr uint32_t field1_reserved_mask = 0x200fff00u; constexpr uint32_t field2_reserved_mask = 0xf0003000u; - constexpr uint32_t field3_base = 0x91800000u; + constexpr uint32_t field3_common = 0x01800000u; constexpr uint32_t field5_expected = 0x00700000u; + const uint32_t field3_expected = + (descriptor.Type() << 28u) | field3_common | descriptor.DstSelXYZW(); return (descriptor.fields[1] & field1_reserved_mask) == 0 && (descriptor.fields[2] & field2_reserved_mask) == 0 && - descriptor.fields[3] == (field3_base | descriptor.DstSelXYZW()) && + descriptor.fields[3] == field3_expected && descriptor.fields[4] == 0 && descriptor.fields[5] == field5_expected && descriptor.fields[6] == 0 && descriptor.fields[7] == 0; } @@ -591,10 +590,19 @@ NativeTexture(uint64_t submit_id, CommandBuffer* command_buffer, if (uint_reinterpret || uint_storage_reinterpret) { image = nullptr; } else { + const auto depth_view = ResolveTargetTextureView( + resource, type, descriptor.BaseArray5(), image->layers); ValidateDepthTargetBinding(resource, descriptor, image, view_format, size.size); + if (depth_view.type == VK_IMAGE_VIEW_TYPE_MAX_ENUM) { + EXIT("unsupported sampled depth target view: dimension=%u descriptor_type=%u " + "base_array=%u image_layers=%u\n", + static_cast(resource.dimension), descriptor.Type(), + descriptor.BaseArray5(), image->layers); + } image_view = g_render_ctx->GetTextureCache()->GetDepthTargetSampledView( g_render_ctx->GetGraphicCtx(), static_cast(image), - view_format, swizzle, 0, 1, VK_IMAGE_VIEW_TYPE_2D, 0, 1); + view_format, swizzle, 0, 1, depth_view.type, depth_view.base_layer, + depth_view.layer_count); } } else { if (!(storage ? IsSupportedStorageImageResource(resource) diff --git a/src/graphics/host_gpu/renderer/descriptors.h b/src/graphics/host_gpu/renderer/descriptors.h index d7a0ab458..4c57fc7e3 100644 --- a/src/graphics/host_gpu/renderer/descriptors.h +++ b/src/graphics/host_gpu/renderer/descriptors.h @@ -5,11 +5,23 @@ #include "graphics/shader/shaderBindings.h" #include +#include namespace Libs::Graphics { struct VulkanImage; +struct TargetTextureViewInfo { + VkImageViewType type = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + uint32_t base_layer = 0; + uint32_t layer_count = 0; +}; + +[[nodiscard]] TargetTextureViewInfo +ResolveTargetTextureView(const ShaderRecompiler::IR::ImageResource& resource, + Prospero::ImageType type, uint32_t base_layer, + uint32_t image_layers); + [[nodiscard]] bool IsSupportedDepthTargetDescriptor(const ShaderTextureResource& descriptor, const VulkanImage& image); [[nodiscard]] bool diff --git a/src/graphics/host_gpu/renderer/imageView.h b/src/graphics/host_gpu/renderer/imageView.h index 42605e8b9..728d10b37 100644 --- a/src/graphics/host_gpu/renderer/imageView.h +++ b/src/graphics/host_gpu/renderer/imageView.h @@ -155,7 +155,8 @@ namespace Libs::Graphics { [[nodiscard]] inline bool IsSupportedSampledDepthResource(const ShaderRecompiler::IR::ImageResource& resource) noexcept { return resource.kind == ShaderRecompiler::IR::ResourceKind::Image && - resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D && + (resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D || + resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DArray) && resource.mip_mode == ShaderRecompiler::IR::ImageMipMode::None && resource.read && !resource.written && !resource.atomic; } diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index eaf81f190..8537b1e02 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -9367,9 +9367,20 @@ void CheckSampledDepthResource() { "dynamic-storage mip depth resource was accepted"); resource = basic; resource.dimension = ShaderRecompiler::Decoder::ImageDimension::Dim2DArray; - Require("SampledDepthResource", "array rejected", - !IsSupportedSampledDepthResource(resource), - "array depth resource was accepted"); + Require("SampledDepthResource", "singleton array accepted", + IsSupportedSampledDepthResource(resource), + "array depth resource was rejected"); + const auto singleton_array_view = ResolveTargetTextureView( + resource, Prospero::ImageType::kColor2DArray, 0, 1); + Require("SampledDepthResource", "singleton array view", + singleton_array_view.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY && + singleton_array_view.base_layer == 0 && + singleton_array_view.layer_count == 1, + "singleton depth array did not preserve the shader array view type"); + Require("SampledDepthResource", "array type mismatch rejected", + ResolveTargetTextureView(resource, Prospero::ImageType::kColor2D, 0, 1) + .type == VK_IMAGE_VIEW_TYPE_MAX_ENUM, + "array shader resource accepted a non-array descriptor view"); resource = basic; resource.kind = ShaderRecompiler::IR::ResourceKind::ImageUint; Require("SampledDepthResource", "integer rejected", @@ -9449,6 +9460,16 @@ void CheckSampledDepthDescriptor() { IsSupportedDepthTargetDescriptor(descriptor, image), "valid padded-pitch depth texture was rejected"); + descriptor.fields[3] = + (descriptor.fields[3] & ~(0xfu << 28u)) | + (Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray) << 28u); + Require("SampledDepthDescriptor", "singleton array descriptor", + IsSupportedDepthTargetDescriptor(descriptor, image), + "valid singleton-array depth texture was rejected"); + descriptor.fields[3] = + (descriptor.fields[3] & ~(0xfu << 28u)) | + (Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) << 28u); + image.guest_pitch = 1344; Require("SampledDepthDescriptor", "target pitch mismatch", !IsSupportedDepthTargetDescriptor(descriptor, image),