diff --git a/src/graphics/host_gpu/renderer/image/imageInfo.h b/src/graphics/host_gpu/renderer/image/imageInfo.h index 20716b807..7b7fb100c 100644 --- a/src/graphics/host_gpu/renderer/image/imageInfo.h +++ b/src/graphics/host_gpu/renderer/image/imageInfo.h @@ -212,7 +212,6 @@ struct DepthFormatPolicy { Prospero::DepthFormat depth_format; Prospero::BufferFormat guest_format; uint32_t bytes_per_element; - vk::Format sampled_view_format; vk::Format depth_attachment_format; std::array stencil_attachment_formats; }; @@ -221,13 +220,11 @@ inline constexpr std::array DEPTH_FORMAT_POLICIES {{ {Prospero::DepthFormat::kZ16, Prospero::BufferFormat::k16UNorm, 2, - vk::Format::eR16Unorm, vk::Format::eD16Unorm, {vk::Format::eD16UnormS8Uint, vk::Format::eD24UnormS8Uint, vk::Format::eD32SfloatS8Uint}}, {Prospero::DepthFormat::kZ32F, Prospero::BufferFormat::k32Float, 4, - vk::Format::eR32Sfloat, vk::Format::eD32Sfloat, {vk::Format::eD32SfloatS8Uint, vk::Format::eUndefined, vk::Format::eUndefined}}, }}; @@ -317,25 +314,6 @@ inline bool ImageInfo::IsDepth() const noexcept { return std::bit_cast(static_cast(value) / 65535.0f); } -[[nodiscard]] inline constexpr bool -IsSupportedSampledDepthFormat(vk::Format image_format, Prospero::BufferFormat guest_format, - vk::Format view_format) noexcept { - const auto* policy = FindGuestDepthFormatPolicy(guest_format); - return policy != nullptr && view_format == policy->sampled_view_format && - (image_format == policy->depth_attachment_format || - IsStencilAttachmentFormat(*policy, image_format)); -} - -[[nodiscard]] inline constexpr bool IsSupportedSampledDepthFormat(vk::Format image_format, - vk::Format view_format) noexcept { - for (const auto& policy: DEPTH_FORMAT_POLICIES) { - if (IsSupportedSampledDepthFormat(image_format, policy.guest_format, view_format)) { - return true; - } - } - return false; -} - [[nodiscard]] inline constexpr bool IsSupportedDepthTargetFormat(const ImageInfo& info) { const auto* policy = FindGuestDepthFormatPolicy(info.guest_format); return policy != nullptr && info.bytes_per_block == policy->bytes_per_element && diff --git a/src/graphics/host_gpu/renderer/image/imageView.cpp b/src/graphics/host_gpu/renderer/image/imageView.cpp index 2449f1a40..72b97e828 100644 --- a/src/graphics/host_gpu/renderer/image/imageView.cpp +++ b/src/graphics/host_gpu/renderer/image/imageView.cpp @@ -36,17 +36,6 @@ namespace { } } -[[nodiscard]] bool IsDepthViewFormat(vk::Format format) { - switch (format) { - case vk::Format::eD16Unorm: - case vk::Format::eR16Unorm: - case vk::Format::eD32Sfloat: - case vk::Format::eR32Sfloat: - case vk::Format::eR32Uint: return true; - default: return false; - } -} - [[nodiscard]] bool IsValidViewType(const VulkanImage& image, const ImageViewInfo& info) { switch (image.image_type) { case vk::ImageType::e1D: @@ -328,7 +317,8 @@ vk::ImageView Image::FindView(const ImageViewInfo& view_info) { auto normalized = view_info; const bool is_storage = static_cast(normalized.usage & vk::ImageUsageFlagBits::eStorage); const auto image_aspect = FullAspectMask(image.format); - if (image_aspect & vk::ImageAspectFlagBits::eDepth && IsDepthViewFormat(normalized.format)) { + if (image_aspect & vk::ImageAspectFlagBits::eDepth && + ImageViewOps::IsFormatDepthCompatible(normalized.format)) { normalized.format = image.format; normalized.aspect = vk::ImageAspectFlagBits::eDepth; } diff --git a/src/graphics/host_gpu/renderer/image/imageView.h b/src/graphics/host_gpu/renderer/image/imageView.h index bc2ba51d2..32ab5bd81 100644 --- a/src/graphics/host_gpu/renderer/image/imageView.h +++ b/src/graphics/host_gpu/renderer/image/imageView.h @@ -12,8 +12,25 @@ namespace ImageViewOps { [[nodiscard]] vk::ImageAspectFlags DepthAspectMask(vk::Format format); [[nodiscard]] bool FormatsCompatible(vk::Format base, vk::Format view) noexcept; + +[[nodiscard]] inline bool IsFormatDepthCompatible(vk::Format format) noexcept { + switch (format) { + case vk::Format::eD32Sfloat: + case vk::Format::eR32Sfloat: + case vk::Format::eR32Uint: + case vk::Format::eD16Unorm: + case vk::Format::eR16Unorm: return true; + default: return false; + } +} } // namespace ImageViewOps +[[nodiscard]] inline bool IsSupportedSampledDepthFormat(vk::Format image_format, + vk::Format view_format) noexcept { + return DepthAspectTransferFormat(image_format) != vk::Format::eUndefined && + ImageViewOps::IsFormatDepthCompatible(view_format); +} + [[nodiscard]] inline bool IsValidImageSwizzle(uint32_t swizzle) noexcept { if ((swizzle & ~0xfffu) != 0) { return false; @@ -86,8 +103,14 @@ SelectSampledDepthView(vk::Format image_format, vk::Format view_format, uint32_t [[nodiscard]] inline bool IsSupportedSampledDepthResource(const ShaderRecompiler::IR::ImageResource& resource) noexcept { - return resource.kind == ShaderRecompiler::IR::ResourceKind::Image && - (resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D || + if (resource.kind != ShaderRecompiler::IR::ResourceKind::Image && + resource.kind != ShaderRecompiler::IR::ResourceKind::ImageUint) { + return false; + } + if (resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint && resource.depth_compare) { + return false; + } + return (resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D || resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DArray || resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaa || resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaaArray) && @@ -95,14 +118,6 @@ IsSupportedSampledDepthResource(const ShaderRecompiler::IR::ImageResource& resou !resource.written && !resource.atomic; } -[[nodiscard]] inline bool -IsSupportedSampledDepthUintResource(const ShaderRecompiler::IR::ImageResource& resource) noexcept { - return resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint && - resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D && - resource.mip_mode == ShaderRecompiler::IR::ImageMipMode::None && resource.read && - !resource.written && !resource.atomic && !resource.depth_compare; -} - inline void ValidateStorageColorView(vk::Format image_format, vk::Format view_format, uint32_t swizzle) noexcept { if (!ImageViewOps::FormatsCompatible(image_format, view_format) || diff --git a/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp b/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp index 80a1f1403..d8c2f2650 100644 --- a/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp @@ -316,8 +316,7 @@ static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource const bool encoding_ok = image != nullptr && IsSupportedDepthTextureEncoding(descriptor, *image); const bool format_ok = - image != nullptr && - IsSupportedSampledDepthFormat(image->info.pixel_format, descriptor.Format(), view_format); + image != nullptr && IsSupportedSampledDepthFormat(image->info.pixel_format, view_format); if (resource_ok && descriptor_ok && encoding_ok && format_ok && size != 0) { return; } diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 057dd5f72..4ab356110 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -7344,6 +7344,71 @@ public: "attachment"); RenderExecutorTestAccess::ResetBindings(executor); + const auto sampled_width = depth_only.desc.info.extent.width - 1u; + const auto sampled_height = depth_only.desc.info.extent.height - 1u; + const auto sampled_address = depth_only_address >> 8u; + ShaderTextureResource sampled_depth_descriptor{}; + sampled_depth_descriptor.fields[0] = + static_cast(sampled_address); + sampled_depth_descriptor.fields[1] = + static_cast(sampled_address >> 32u) | + (static_cast(Prospero::BufferFormat::k32UInt) << 20u) | + ((sampled_width & 3u) << 30u); + sampled_depth_descriptor.fields[2] = + (sampled_width >> 2u) | (sampled_height << 14u); + sampled_depth_descriptor.fields[3] = + DstSel(4, 4, 4, 4) | + (static_cast(Prospero::TileMode::kDepth) << 20u) | + (static_cast(Prospero::ImageType::kColor2D) << 28u); + sampled_depth_descriptor.fields[5] = 0x00700000u; + ShaderRecompiler::IR::DescriptorValue sampled_depth_value{}; + std::copy(std::begin(sampled_depth_descriptor.fields), + std::end(sampled_depth_descriptor.fields), + sampled_depth_value.dwords.begin()); + sampled_depth_value.dword_count = 8; + ShaderRecompiler::IR::ImageResource sampled_depth_resource{}; + sampled_depth_resource.kind = + ShaderRecompiler::IR::ResourceKind::ImageUint; + sampled_depth_resource.dimension = + ShaderRecompiler::Decoder::ImageDimension::Dim2D; + sampled_depth_resource.read = true; + const auto sampled_depth_backing = + texture_cache.GetImage(depth_only.image_id).backing.image; + auto sampled_depth_binding = RenderExecutorTestAccess::ResolveTexture( + executor, sampled_depth_resource, sampled_depth_value); + const auto sampled_depth_view = texture_cache.FindTexture( + sampled_depth_binding.image_id, sampled_depth_binding.desc); + const auto &sampled_depth_image = + texture_cache.GetImage(sampled_depth_binding.image_id); + const bool normalized_depth_view = std::ranges::any_of( + sampled_depth_image.views.views, [&](const auto &cached) { + return cached.view == sampled_depth_view && + cached.info.format == vk::Format::eD32Sfloat && + cached.info.aspect == vk::ImageAspectFlagBits::eDepth && + cached.info.usage == vk::ImageUsageFlags{}; + }); + Require( + name, "R32 uint depth-backed view", + sampled_depth_binding.image_id == depth_only.image_id && + sampled_depth_binding.desc.info.guest_format == + Prospero::BufferFormat::k32UInt && + sampled_depth_binding.desc.info.pixel_format == + vk::Format::eR32Uint && + sampled_depth_binding.desc.view_info.format == + vk::Format::eR32Uint && + sampled_depth_binding.desc.view_info.aspect == + vk::ImageAspectFlagBits::eColor && + sampled_depth_binding.desc.view_info.usage == + vk::ImageUsageFlagBits::eSampled && + sampled_depth_image.info.pixel_format == + vk::Format::eD32Sfloat && + sampled_depth_image.backing.format == vk::Format::eD32Sfloat && + sampled_depth_image.backing.image == sampled_depth_backing && + sampled_depth_view != nullptr && normalized_depth_view, + "uint T# did not retain its requested format while the concrete " + "view followed the D32 backing"); + RenderExecutorTestAccess::ResetBindings(executor); + auto video_subresource = make_target_desc(base + 0x20000, target_mip_size, {1, 1, 1}); video_subresource.type = BindingType::VideoOut; @@ -16650,7 +16715,8 @@ TestCase ImageLoadR32UintUsesIntegerSampledImage() { test.sampled_image_dwords_per_pixel = 1; test.user_data = MakeSampledTextureData(Prospero::BufferFormat::k32UInt); test.has_user_data = true; - test.required_spirv = {"sampled_uint_2d"}; + test.required_spirv = {"sampled_uint_2d", "OpTypeImage %uint", + "OpImageFetch %v4uint"}; return test; } @@ -18398,7 +18464,7 @@ void CheckRenderTargetFormatContract() { DstSel(7, 6, 5, 3)); } else if (std::strcmp(kind, "sampled-depth-format") == 0) { (void)SelectSampledDepthView(vk::Format::eD24UnormS8Uint, - vk::Format::eR32Sfloat, DstSel(4, 4, 4, 4)); + vk::Format::eR8Unorm, DstSel(4, 4, 4, 4)); } else if (std::strcmp(kind, "sampled-depth-swizzle") == 0) { (void)SelectSampledDepthView(vk::Format::eD32SfloatS8Uint, vk::Format::eR32Sfloat, DstSel(4, 5, 6, 7)); @@ -18767,12 +18833,19 @@ void CheckSampledDepthResource() { "array shader resource accepted a non-array descriptor view"); resource = basic; resource.kind = ShaderRecompiler::IR::ResourceKind::ImageUint; - Require("SampledDepthResource", "integer rejected", + Require("SampledDepthResource", "integer read", + IsSupportedSampledDepthResource(resource), + "read-only uint depth resource was rejected"); + resource.depth_compare = true; + Require("SampledDepthResource", "integer comparison rejected", !IsSupportedSampledDepthResource(resource), - "integer depth resource was accepted"); - Require("SampledDepthResource", "integer reinterpret resource", - IsSupportedSampledDepthUintResource(resource), - "read-only uint depth reinterpretation resource was rejected"); + "uint depth resource accepted comparison sampling"); + Require("SampledDepthResource", "R32 uint depth view", + IsSupportedSampledDepthFormat(vk::Format::eD32Sfloat, + vk::Format::eR32Uint) && + !IsSupportedSampledDepthFormat(vk::Format::eR32Uint, + vk::Format::eR32Uint), + "R32 uint depth-view compatibility diverged from its backing role"); std::printf("[host] %-32s ok\n", "SampledDepthResource"); }