From 9641b519259a5efa76a7f26e18d089723b5562a6 Mon Sep 17 00:00:00 2001 From: nmzik Date: Sat, 5 Sep 2026 11:44:11 +0400 Subject: [PATCH] render: fix tiled depth comparison textures Co-authored-by: Ettore Sartori <85788613+Ekt0re@users.noreply.github.com> Co-authored-by: Mac --- .../host_gpu/renderer/cache/textureCache.cpp | 81 ++++---- .../host_gpu/renderer/cache/textureCache.h | 8 +- .../renderer/pipeline/descriptors.cpp | 19 +- .../host_gpu/renderer/pipeline/descriptors.h | 4 +- tests/ShaderRecompilerComputeTests.cpp | 188 +++++++++++++++++- 5 files changed, 241 insertions(+), 59 deletions(-) diff --git a/src/graphics/host_gpu/renderer/cache/textureCache.cpp b/src/graphics/host_gpu/renderer/cache/textureCache.cpp index 45a37dd3f..1c1327cb5 100644 --- a/src/graphics/host_gpu/renderer/cache/textureCache.cpp +++ b/src/graphics/host_gpu/renderer/cache/textureCache.cpp @@ -130,7 +130,10 @@ bool TextureCache::SameBacking(const ImageInfo& cached, const ImageInfo& request TextureCache::BindingType TextureCache::UploadBinding(const Image& image) { if (image.info.IsDepth()) { - return BindingType::DepthTarget; + return image.info.tile_mode == Prospero::TileMode::kDepth || + image.info.tile_mode == Prospero::TileMode::kLinear + ? BindingType::DepthTarget + : BindingType::Texture; } if (image.usage.render_target) { return BindingType::RenderTarget; @@ -815,7 +818,7 @@ ImageId TextureCache::ExpandImage(const ImageInfo& info, ImageId source_id) { return expanded_id; } -struct TextureCache::ColorTransferPlan { +struct TextureCache::TextureTransferPlan { TextureUploadLayout layout; std::vector regions; std::vector tiles; @@ -834,14 +837,14 @@ static uint64_t GetLinearSize(std::span tiles) { } struct TextureCache::DownloadPlan { - ColorTransferPlan color; - bool depth = false; - bool valid = false; + TextureTransferPlan texture; + bool depth_target = false; + bool valid = false; }; -TextureCache::ColorTransferPlan -TextureCache::BuildColorTransfer(const Image& image, BindingType binding, - TransferDirection direction) const { +TextureCache::TextureTransferPlan +TextureCache::BuildTextureTransfer(const Image& image, BindingType binding, + TransferDirection direction) const { const auto& info = image.info; auto format = info.guest_format; uint32_t layers = info.TransferLayers(); @@ -850,7 +853,7 @@ TextureCache::BuildColorTransfer(const Image& image, BindingType binding, const char* owner = direction == TransferDirection::Upload ? "TextureCache" : "TextureCache readback"; - ColorTransferPlan plan; + TextureTransferPlan plan; if (direction == TransferDirection::Upload) { switch (binding) { case BindingType::Texture: break; @@ -895,6 +898,11 @@ TextureCache::BuildColorTransfer(const Image& image, BindingType binding, info.resources.levels, layers, info.tile_mode, info.data.size, allow_depth_tile, volume, owner); plan.regions = TextureBuildImageCopies(plan.layout); + if (info.IsDepth()) { + for (auto& region: plan.regions) { + region.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eDepth; + } + } plan.tiled = plan.layout.surface.description.tile_mode != Prospero::TileMode::kLinear; if (plan.tiled) { if (!TextureBuildGpuTileInfos(info.data.size, plan.regions, plan.layout, @@ -908,12 +916,13 @@ TextureCache::BuildColorTransfer(const Image& image, BindingType binding, } TextureCache::DownloadPlan TextureCache::BuildDownload(const Image& image) const { - const auto& info = image.info; - DownloadPlan plan {.depth = info.IsDepth()}; + const auto& info = image.info; + const auto binding = UploadBinding(image); + DownloadPlan plan {.depth_target = binding == BindingType::DepthTarget}; if (info.samples != 1 || image.backing.samples != 1) { return plan; } - if (plan.depth) { + if (plan.depth_target) { plan.valid = IsSupportedDepthPlaneReadback(info) && info.resources.layers != 0 && info.data.size % info.resources.layers == 0 && Prospero::NumBytesPerElement(info.guest_format) == info.bytes_per_block; @@ -922,8 +931,8 @@ TextureCache::DownloadPlan TextureCache::BuildDownload(const Image& image) const if (info.metadata.compression != VideoOutCompression::Uncompressed) { return plan; } - plan.color = BuildColorTransfer(image, UploadBinding(image), TransferDirection::Download); - plan.valid = plan.color.valid; + plan.texture = BuildTextureTransfer(image, binding, TransferDirection::Download); + plan.valid = plan.texture.valid; return plan; } @@ -938,9 +947,9 @@ void TextureCache::UploadImage(Image& image, Buffer& source, uint64_t source_off }; if (binding != BindingType::DepthTarget) { - auto plan = BuildColorTransfer(image, binding, TransferDirection::Upload); + auto plan = BuildTextureTransfer(image, binding, TransferDirection::Upload); if (!plan.valid) { - EXIT("TextureCache: invalid color upload: binding=%u addr=0x%016" PRIx64 + EXIT("TextureCache: invalid texture upload: binding=%u addr=0x%016" PRIx64 " size=0x%016" PRIx64 " format=%u tile=%u family=%u extent=%ux%ux%u " "pitch=%u levels=%u layers=%u samples=%u\n", static_cast(binding), info.data.address, info.data.size, @@ -1536,7 +1545,7 @@ void TextureCache::DownloadImageData(Image& image, Buffer& destination, uint64_t if (!plan.valid) { EXIT("TextureCache: invalid image download plan\n"); } - if (plan.depth) { + if (plan.depth_target) { if (destination_size != image.info.data.size) { EXIT("TextureCache: partial depth image download is unsupported\n"); } @@ -1544,26 +1553,26 @@ void TextureCache::DownloadImageData(Image& image, Buffer& destination, uint64_t return; } - auto& color = plan.color; - const auto transform = color.swap_bgra16 ? TileManager::ColorTransform::SwapBgra16 - : TileManager::ColorTransform::None; - if (!color.tiled) { + auto& texture = plan.texture; + const auto transform = texture.swap_bgra16 ? TileManager::ColorTransform::SwapBgra16 + : TileManager::ColorTransform::None; + if (!texture.tiled) { if (transform == TileManager::ColorTransform::SwapBgra16) { auto linear = m_tiler.GetScratchBuffer(destination_size); - image.Download(color.regions, linear.buffer, 0, linear.size); + image.Download(texture.regions, linear.buffer, 0, linear.size); m_tiler.SwapBgra16(linear, {destination.Handle(), destination_offset, destination_size}); return; } - for (auto& copy: color.regions) { + for (auto& copy: texture.regions) { copy.bufferOffset += destination_offset; } - image.Download(color.regions, destination.Handle(), destination_offset, destination_size); + image.Download(texture.regions, destination.Handle(), destination_offset, destination_size); return; } - m_tiler.TileImage(image, color.regions, destination.Handle(), destination_offset, - destination_size, color.linear_size, color.tiles, transform); + m_tiler.TileImage(image, texture.regions, destination.Handle(), destination_offset, + destination_size, texture.linear_size, texture.tiles, transform); } bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, uint64_t vaddr, uint64_t size) { @@ -1634,24 +1643,24 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, uint64_t vaddr, uin if (!plan.valid) { return false; } - if (plan.depth && copy_size != image.info.data.size) { + if (plan.depth_target && copy_size != image.info.data.size) { return false; } - if (!plan.depth && levels < image.info.resources.levels) { - auto& color = plan.color; - std::erase_if(color.regions, [levels](const vk::BufferImageCopy& region) { + if (!plan.depth_target && levels < image.info.resources.levels) { + auto& texture = plan.texture; + std::erase_if(texture.regions, [levels](const vk::BufferImageCopy& region) { return region.imageSubresource.mipLevel >= levels; }); - if (color.regions.empty()) { + if (texture.regions.empty()) { return false; } - if (color.tiled) { - color.tiles.clear(); - if (!TextureBuildGpuTileInfos(copy_size, color.regions, color.layout, levels, - color.tiles)) { + if (texture.tiled) { + texture.tiles.clear(); + if (!TextureBuildGpuTileInfos(copy_size, texture.regions, texture.layout, levels, + texture.tiles)) { return false; } - color.linear_size = GetLinearSize(color.tiles); + texture.linear_size = GetLinearSize(texture.tiles); } } m_texture_cache.DownloadImageData(image, buffer, buf_offset, copy_size, std::move(plan)); diff --git a/src/graphics/host_gpu/renderer/cache/textureCache.h b/src/graphics/host_gpu/renderer/cache/textureCache.h index 11a3db4e8..72651d288 100644 --- a/src/graphics/host_gpu/renderer/cache/textureCache.h +++ b/src/graphics/host_gpu/renderer/cache/textureCache.h @@ -83,7 +83,7 @@ public: private: enum class TransferDirection { Upload, Download }; - struct ColorTransferPlan; + struct TextureTransferPlan; struct DownloadPlan; struct MetaDataInfo { @@ -139,9 +139,9 @@ private: [[nodiscard]] ImageId ExpandImage(const ImageInfo& info, ImageId source); void RefreshImage(ImageId id); void InitializeImage(ImageId id); - [[nodiscard]] ColorTransferPlan BuildColorTransfer(const Image& image, BindingType binding, - TransferDirection direction) const; - [[nodiscard]] DownloadPlan BuildDownload(const Image& image) const; + [[nodiscard]] TextureTransferPlan + BuildTextureTransfer(const Image& image, BindingType binding, TransferDirection direction) const; + [[nodiscard]] DownloadPlan BuildDownload(const Image& image) const; void UploadImage(Image& image, Buffer& source, uint64_t source_offset); void DownloadImageData(Image& image, Buffer& destination, uint64_t destination_offset, uint64_t destination_size, DownloadPlan plan); diff --git a/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp b/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp index dba27f3bc..4ced2bb11 100644 --- a/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp @@ -252,7 +252,7 @@ bool IsSupportedSampledVideoOutView(const ShaderRecompiler::IR::ImageResource& r descriptor.BaseArray5() == 0; } -bool IsSupportedDepthTargetDescriptor(const ShaderTextureResource& descriptor, const Image& image, +bool IsSupportedSampledDepthDescriptor(const ShaderTextureResource& descriptor, const Image& image, bool r128) { const auto width = static_cast(descriptor.Width5()) + 1u; const auto height = static_cast(descriptor.Height5()) + 1u; @@ -291,7 +291,9 @@ bool IsSupportedDepthTargetDescriptor(const ShaderTextureResource& descriptor, c (supported_2d || supported_array || supported_cube || supported_msaa_2d || supported_msaa_array) && levels_ok && descriptor.MinLod() == 0 && - descriptor.TileMode() == Prospero::TileMode::kDepth && descriptor.BCSwizzle() == 0 && + descriptor.TileMode() == image.info.tile_mode && + (!multisampled || descriptor.TileMode() == Prospero::TileMode::kDepth) && + descriptor.BCSwizzle() == 0 && (!descriptor.MsaaDepth() || multisampled) && pitch >= width && pitch == image.info.pitch; } @@ -332,12 +334,12 @@ bool IsSupportedDepthTextureEncoding(const ShaderTextureResource& descriptor, co image.info.metadata.range.Valid() && image.info.metadata.range.address == metadata_addr; } -static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource& resource, +static void ValidateSampledDepthBinding(const ShaderRecompiler::IR::ImageResource& resource, const ShaderTextureResource& descriptor, const Image* image, vk::Format view_format, uint64_t size) { const bool resource_ok = IsSupportedSampledDepthResource(resource); const bool descriptor_ok = - image != nullptr && IsSupportedDepthTargetDescriptor(descriptor, *image, resource.r128); + image != nullptr && IsSupportedSampledDepthDescriptor(descriptor, *image, resource.r128); const bool encoding_ok = image != nullptr && IsSupportedDepthTextureEncoding(descriptor, *image, resource.r128); const bool format_ok = @@ -348,7 +350,7 @@ static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource const auto descriptor_pitch = TileGetTexturePitch(descriptor.Format(), static_cast(descriptor.Width5()) + 1u, descriptor.TileMode()); - EXIT("unsupported sampled depth target: resource=%d descriptor=%d encoding=%d format=%d " + EXIT("unsupported sampled depth image: resource=%d descriptor=%d encoding=%d format=%d " "class=%u numeric=%u dimension=%u mip_mode=%u read=%d written=%d atomic=%d compare=%d " "guest_format=%u swizzle=0x%03x image_format=%d view_format=%d image_layers=%u " "descriptor_type=%u base_array=%u depth=%u descriptor_pitch=%u target_pitch=%u " @@ -745,7 +747,10 @@ TextureBinding RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageR ValidateStorageTexture(resource, descriptor, size.size); } - const auto pixel_format = surface_format.vk_format; + const auto* depth_format = resource.depth_compare ? FindGuestDepthFormatPolicy(format) : nullptr; + EXIT_NOT_IMPLEMENTED(resource.depth_compare && depth_format == nullptr); + const auto pixel_format = + depth_format != nullptr ? depth_format->depth_attachment_format : surface_format.vk_format; const auto storage_view_format = storage && format == Prospero::BufferFormat::k32SInt ? vk::Format::eR32Uint : SrgbStorageViewFormat(pixel_format); @@ -784,7 +789,7 @@ TextureBinding RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageR if (storage) { EXIT("depth target cannot be bound as a storage image\n"); } - ValidateDepthTargetBinding(resource, descriptor, image, pixel_format, size.size); + ValidateSampledDepthBinding(resource, descriptor, image, pixel_format, size.size); (void)SelectSampledDepthView(image->info.pixel_format, pixel_format, descriptor.DstSelXYZW()); } else if (storage) { diff --git a/src/graphics/host_gpu/renderer/pipeline/descriptors.h b/src/graphics/host_gpu/renderer/pipeline/descriptors.h index f53acf99d..e5b8af02d 100644 --- a/src/graphics/host_gpu/renderer/pipeline/descriptors.h +++ b/src/graphics/host_gpu/renderer/pipeline/descriptors.h @@ -78,8 +78,8 @@ struct 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 Image& image, bool r128 = false); +[[nodiscard]] bool IsSupportedSampledDepthDescriptor(const ShaderTextureResource& descriptor, + const Image& image, bool r128 = false); [[nodiscard]] bool IsSupportedDepthTextureEncoding(const ShaderTextureResource& descriptor, const Image& image, bool r128 = false); [[nodiscard]] bool diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 33ccf87bc..ccb854e58 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -7744,6 +7744,170 @@ public: std::printf("[gpu] %-32s ok\n", name); } + void CheckComparisonDepthTexture() { + constexpr const char *name = "ComparisonDepthTexture"; + constexpr uintptr_t base = 0x0000000204200000ull; + constexpr uint64_t allocation_size = 0x10000; + constexpr uint64_t ordinary_address = base + 0x1000; + constexpr std::array depths{0, 13107, 26214, 39321, 52428, 65535}; + constexpr std::array references{0.1f, 0.3f, 0.5f, 0.7f, 0.9f}; + EnsureRuntimeContext(); + int64_t direct_offset = -1; + Require(name, "direct allocation", + Libs::LibKernel::Memory::KernelAllocateDirectMemory( + 0, Libs::LibKernel::Memory::KernelGetDirectMemorySize(), + allocation_size, allocation_size, 0, &direct_offset) == 0, + "comparison texture allocation failed"); + void *mapped = reinterpret_cast(base); + Require(name, "direct mapping", + Libs::LibKernel::Memory::KernelMapDirectMemory( + &mapped, allocation_size, 0x3, 0x10, direct_offset, + allocation_size) == 0 && mapped == reinterpret_cast(base), + "comparison texture mapping failed"); + std::memset(mapped, 0, allocation_size); + for (uint32_t face = 0; face < depths.size(); face++) { + for (const auto address : {base, ordinary_address}) { + std::memcpy(reinterpret_cast(address + face * 0x100), + &depths[face], sizeof(uint16_t)); + } + } + + { + RenderContext context(m_runtime_context); + auto &scheduler = context.GetCommandScheduler(); + HW::Context registers{}; + HW::UserConfig user_config{}; + HW::Shader shaders{}; + scheduler.Begin(registers, user_config, shaders); + auto &resources = context.GetGpuResources(); + auto &cache = resources.GetTextureCache(); + auto &executor = context.GetRenderExecutor(); + resources.MapMemory(base, allocation_size); + ShaderTextureResource descriptor{{static_cast(base >> 8u), + 0x00700000u, 0, 0xb0100204u, 5, 0x00700000u, 0, 0}}; + ShaderSamplerResource sampler_descriptor{{1u << 12u, 0, 1u << 24u, 0}}; + TestCase test; + test.name = name; + test.has_user_data = true; + test.image_descriptor_swizzle = descriptor.DstSelXYZW(); + std::copy_n(descriptor.fields, 8, test.user_data.begin()); + std::copy_n(sampler_descriptor.fields, 4, test.user_data.begin() + 8); + test.user_data[50] = depths.size() * references.size() * sizeof(uint32_t); + test.opcodes = {ShaderOpcode::V_MOV_B32, ShaderOpcode::IMAGE_SAMPLE, + ShaderOpcode::BUFFER_STORE_DWORD, ShaderOpcode::S_ENDPGM}; + test.required_spirv = {"OpImageSampleDrefExplicitLod"}; + std::vector promoted_expected; + for (uint32_t face = 0; face < depths.size(); face++) { + for (const auto reference : references) { + AppendVMovLiteral(&test.code, 20, std::bit_cast(reference)); + AppendVMovLiteral(&test.code, 21, std::bit_cast(1.5f)); + AppendVMovLiteral(&test.code, 22, std::bit_cast(1.5f)); + AppendVMovLiteral(&test.code, 23, std::bit_cast(static_cast(face))); + test.code.push_back(EncodeMimg0(0x2f, 1, 0, false, 3)); + test.code.push_back(EncodeMimg1(0, 20, 0, 2)); + AppendStoreVgpr(&test.code, 0, static_cast(test.expected.size())); + test.expected.push_back(reference < static_cast(depths[face]) / 65535.f + ? 0x3f800000u : 0u); + promoted_expected.push_back(reference < static_cast(depths[5 - face]) / 65535.f + ? 0x3f800000u : 0u); + } + } + AppendEnd(&test.code); + const auto compiled = CompileCase(test, SubgroupSize()); + Require(name, "comparison resource", compiled.program.info.images.size() == 1 && + compiled.program.info.images[0].depth_compare && + compiled.program.info.images[0].cube, + "native cube comparison did not retain its resource semantics"); + ShaderRecompiler::IR::DescriptorValue value{}; + value.dword_count = 8; + std::copy_n(descriptor.fields, 8, value.dwords.begin()); + auto binding = RenderExecutorTestAccess::ResolveTexture( + executor, compiled.program.info.images[0], value); + const auto view = cache.FindTexture(binding.image_id, binding.desc); + auto &image = cache.GetImage(binding.image_id); + Require(name, "fresh depth backing", view != nullptr && + image.info.pixel_format == vk::Format::eD16Unorm && + image.info.guest_format == Prospero::BufferFormat::k16UNorm && + image.info.tile_mode == Prospero::TileMode::kStandard256B && + image.info.data.size == 0x600 && image.info.resources.layers == 6, + "comparison texture lost its guest layout or depth representation"); + auto ordinary_resource = compiled.program.info.images[0]; + ordinary_resource.depth_compare = false; + value.dwords[0] = static_cast(ordinary_address >> 8u); + auto ordinary = RenderExecutorTestAccess::ResolveTexture(executor, ordinary_resource, value); + (void)cache.FindTexture(ordinary.image_id, ordinary.desc); + auto &color = cache.GetImage(ordinary.image_id); + Require(name, "ordinary R16", color.info.pixel_format == vk::Format::eR16Unorm, + "ordinary R16 sampling unexpectedly acquired a depth format"); + scheduler.Finish(); + + auto output = CreateStorageBuffer(name, {}, test.expected.size()); + const auto sampler = context.GetSamplerCache().GetSampler(sampler_descriptor); + Image sampled; + sampled.view = view; + sampled.layout = image.backing.state.layout; + Dispatch(test, compiled, output, nullptr, &sampled, nullptr, nullptr, sampler); + Require(name, "six face comparisons", + ReadBuffer(name, output, test.expected.size()) == test.expected, + "comparison samples lost a depth value or Standard256B face stride"); + + image.Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite, + {}, scheduler.Current().Handle()); + color.Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite, + {}, scheduler.Current().Handle()); + for (uint32_t face = 0; face < depths.size(); face++) { + const vk::ImageSubresourceRange depth_range{vk::ImageAspectFlagBits::eDepth, 0, 1, face, 1}; + const vk::ClearDepthStencilValue clear_depth{ + static_cast(depths[5 - face]) / 65535.f, 0}; + scheduler.Current().Handle().clearDepthStencilImage(image.backing.image, + vk::ImageLayout::eTransferDstOptimal, &clear_depth, 1, &depth_range); + const vk::ImageSubresourceRange color_range{vk::ImageAspectFlagBits::eColor, 0, 1, face, 1}; + const vk::ClearColorValue clear_color{std::array{ + static_cast(depths[5 - face]) / 65535.f, 0.f, 0.f, 0.f}}; + scheduler.Current().Handle().clearColorImage(color.backing.image, + vk::ImageLayout::eTransferDstOptimal, &clear_color, 1, &color_range); + } + cache.MarkGpuWritten(binding.image_id); + cache.MarkGpuWritten(ordinary.image_id); + Require(name, "depth readback", TextureCacheTestAccess::TryDownload(cache, binding.image_id), + "ordinary tiled depth readback did not use the shared transfer path"); + scheduler.Finish(); + scheduler.DrainPriorityOperations(); + for (uint32_t face = 0; face < depths.size(); face++) { + uint16_t actual = 0; + std::memcpy(&actual, reinterpret_cast(base + face * 0x100), sizeof(actual)); + Require(name, "depth guest roundtrip", actual == depths[5 - face], + "GPU depth clear was not written to the correct guest face"); + } + + auto promoted = RenderExecutorTestAccess::ResolveTexture( + executor, compiled.program.info.images[0], value); + sampled.view = cache.FindTexture(promoted.image_id, promoted.desc); + auto &promoted_image = cache.GetImage(promoted.image_id); + Require(name, "GPU color owner promotion", promoted.image_id != ordinary.image_id && + promoted_image.info.pixel_format == vk::Format::eD16Unorm && + promoted_image.IsGpuModified(), + "comparison binding did not preserve the GPU-current color owner"); + sampled.layout = promoted_image.backing.state.layout; + scheduler.Finish(); + Dispatch(test, compiled, output, nullptr, &sampled, nullptr, nullptr, sampler); + Require(name, "promoted comparisons", + ReadBuffer(name, output, promoted_expected.size()) == promoted_expected, + "color-to-depth ownership conversion changed comparison results"); + DestroyBuffer(&output); + RenderExecutorTestAccess::ResetBindings(executor); + resources.UnmapMemory(base, allocation_size); + scheduler.Finish(); + } + Require(name, "unmap", Libs::LibKernel::Memory::KernelMunmap(base, allocation_size) == 0, + "comparison texture unmap failed"); + Require(name, "release", Libs::LibKernel::Memory::KernelReleaseDirectMemory( + direct_offset, allocation_size) == 0, + "comparison texture release failed"); + std::printf("[gpu] %-32s ok\n", name); + } + + void CheckRenderExecutorColorStandardTileDiscovery() { constexpr const char *name = "RenderExecutorColorStandardTile"; constexpr uintptr_t base = 0x0000000203b00000ull; @@ -9943,7 +10107,9 @@ public: image.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim1D || image.dimension == - ShaderRecompiler::Decoder::ImageDimension::Dim1DArray; + ShaderRecompiler::Decoder::ImageDimension::Dim1DArray || + image.dimension == + ShaderRecompiler::Decoder::ImageDimension::Dim2DArray; } Require(test.name, "dispatch", supported, "unsupported image dimension needs a matching Vulkan test view"); @@ -23648,7 +23814,7 @@ void CheckSampledDepthDescriptor(RenderContext &renderer) { Require("SampledDepthDescriptor", "normalized padded pitch", descriptor.Width5() + 1u == image.info.extent.width && descriptor.Height5() + 1u == image.info.extent.height && - IsSupportedDepthTargetDescriptor(descriptor, image), + IsSupportedSampledDepthDescriptor(descriptor, image), "normalized depth image rejected a valid padded descriptor"); const ShaderTextureResource disabled_sampler_tweaks{{ @@ -23682,7 +23848,7 @@ void CheckSampledDepthDescriptor(RenderContext &renderer) { Image msaa_image(context, scheduler, msaa_info); msaa_image.usage.depth_target = true; Require("SampledDepthDescriptor", "uncompressed 2x MSAA depth", - IsSupportedDepthTargetDescriptor(uncompressed_msaa, msaa_image) && + IsSupportedSampledDepthDescriptor(uncompressed_msaa, msaa_image) && IsSupportedDepthTextureEncoding(uncompressed_msaa, msaa_image), "valid uncompressed MSAA depth descriptor required an HTILE " "compatibility flag"); @@ -23690,7 +23856,7 @@ void CheckSampledDepthDescriptor(RenderContext &renderer) { auto r128_msaa = uncompressed_msaa; std::fill(r128_msaa.fields + 4, r128_msaa.fields + 8, 0u); Require("SampledDepthDescriptor", "R128 uncompressed 2x MSAA depth", - IsSupportedDepthTargetDescriptor(r128_msaa, msaa_image, true) && + IsSupportedSampledDepthDescriptor(r128_msaa, msaa_image, true) && IsSupportedDepthTextureEncoding(r128_msaa, msaa_image, true), "valid R128 MSAA depth descriptor required omitted dwords"); @@ -23698,7 +23864,7 @@ void CheckSampledDepthDescriptor(RenderContext &renderer) { (descriptor.fields[3] & ~(0xfu << 28u)) | (static_cast(Prospero::ImageType::kColor2DArray) << 28u); Require("SampledDepthDescriptor", "singleton array descriptor", - IsSupportedDepthTargetDescriptor(descriptor, image), + IsSupportedSampledDepthDescriptor(descriptor, image), "normalized singleton-array depth view was rejected"); descriptor.fields[3] = (descriptor.fields[3] & ~(0xfu << 28u)) | @@ -23723,7 +23889,7 @@ void CheckSampledDepthDescriptor(RenderContext &renderer) { ResolveTargetTextureView(cube_resource, Prospero::ImageType::kCube, 0, cube_image.info.resources.layers); Require("SampledDepthDescriptor", "normalized depth cube", - IsSupportedDepthTargetDescriptor(cube_descriptor, cube_image) && + IsSupportedSampledDepthDescriptor(cube_descriptor, cube_image) && IsSupportedDepthTextureEncoding(cube_descriptor, cube_image) && cube_view.type == vk::ImageViewType::e2DArray && cube_view.layer_count == 6, @@ -23787,14 +23953,14 @@ void CheckSampledDepthDescriptor(RenderContext &renderer) { (non_square_cube.fields[2] & ~(0x3fffu << 14u)) | (511u << 14u); image.info.pitch = 1344; const bool rejects_pitch = - !IsSupportedDepthTargetDescriptor(descriptor, image); + !IsSupportedSampledDepthDescriptor(descriptor, image); image.info.pitch = 1408; Require("SampledDepthDescriptor", "normalized hard guards", rejects_pitch && - !IsSupportedDepthTargetDescriptor(partial_cube, cube_image) && - !IsSupportedDepthTargetDescriptor(based_cube, cube_image) && + !IsSupportedSampledDepthDescriptor(partial_cube, cube_image) && + !IsSupportedSampledDepthDescriptor(based_cube, cube_image) && !IsSupportedDepthTextureEncoding(reserved_cube, cube_image) && - !IsSupportedDepthTargetDescriptor(non_square_cube, cube_image), + !IsSupportedSampledDepthDescriptor(non_square_cube, cube_image), "normalized depth descriptor accepted an incompatible image view"); std::printf("[host] %-32s ok\n", "SampledDepthDescriptor"); } @@ -26863,6 +27029,7 @@ int main(int argc, char **argv) { VulkanHarness vulkan; CheckSampledDepthResource(); CheckSampledDepthDescriptor(vulkan.RuntimeRenderer()); + vulkan.CheckComparisonDepthTexture(); return 0; } if (argc == 2 && std::strcmp(argv[1], "--storage-bgra-only") == 0) { @@ -26913,6 +27080,7 @@ int main(int argc, char **argv) { CheckImageTransitionState(vulkan.RuntimeRenderer()); CheckSampledDepthResource(); CheckSampledDepthDescriptor(vulkan.RuntimeRenderer()); + vulkan.CheckComparisonDepthTexture(); CheckBasicStorageTextureDescriptor(); CheckStorageTextureLinearUploadLayout(); CheckStorageTextureDepthTileUploadLayout();