diff --git a/src/graphics/host_gpu/renderer/cache/textureCache.cpp b/src/graphics/host_gpu/renderer/cache/textureCache.cpp index c87c68559..8ee4283ca 100644 --- a/src/graphics/host_gpu/renderer/cache/textureCache.cpp +++ b/src/graphics/host_gpu/renderer/cache/textureCache.cpp @@ -629,17 +629,6 @@ ImageId TextureCache::ResolveDepthOverlap(const ImageInfo& requested, BindingTyp } const bool stencil_match = requested.HasStencil() == cached.info.HasStencil(); const bool bpp_match = requested.bytes_per_block == cached.info.bytes_per_block; - // PPSA04264 - const bool raw_d16_texture = - binding == BindingType::Texture && cached.info.IsDepth() && - cached.info.guest_format == Prospero::BufferFormat::k16UNorm && - requested.guest_format == Prospero::BufferFormat::k16UInt && - requested.pixel_format == vk::Format::eR16Uint && cached.backing.samples == 1 && - requested.samples == 1 && requested.data == cached.info.data && - requested.extent == cached.info.extent && requested.resources == cached.info.resources && - requested.type == cached.info.type && requested.pitch == cached.info.pitch && - !requested.HasStencil() && !cached.info.HasStencil() && !requested.HasMetadata() && - !cached.info.HasMetadata(); // PPSA04264, PPSA04288 // A partial view retains the entire matching array layout. HTile belongs to // the depth source, independently of the data slices copied into color storage. @@ -663,12 +652,20 @@ ImageId TextureCache::ResolveDepthOverlap(const ImageInfo& requested, BindingTyp !requested.HasStencil() && !cached.info.HasStencil() && !requested.HasMetadata() && (cached.info.metadata.kind == ImageMetadataKind::None || cached.info.metadata.kind == ImageMetadataKind::Htile); + // Depth bytes sampled through a color format no depth view provides (16_UINT, 8_8_UNORM) + // need a color copy of the whole single-sample depth layout. + const bool raw_depth_texture = + cached.info.IsDepth() && !requested.IsDepth() && !cached.info.HasStencil() && + !requested.HasMetadata() && cached.backing.samples == 1 && requested.samples == 1 && + requested.pitch == cached.info.pitch && + (requested.resources == cached.info.resources || retain_cached_layout) && + !IsSupportedSampledDepthFormat(cached.info.pixel_format, requested.pixel_format); bool recreate = cached.info.resources < requested.resources || requested.IsVolume() != cached.info.IsVolume(); switch (binding) { case BindingType::Texture: recreate |= requested.IsDepth() && !cached.info.IsDepth(); - recreate |= raw_d16_texture; + recreate |= raw_depth_texture; break; case BindingType::Storage: recreate |= cached.info.IsDepth(); break; case BindingType::RenderTarget: recreate |= cached.info.IsDepth(); break; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 6fa5317bc..ab2017ed8 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -7025,6 +7025,65 @@ public: nullptr, "D16 uint sampling did not create an integer sampled view"); + auto raw_d16_rg8_depth = raw_d16; + raw_d16_rg8_depth.info.data.address += 0x800; + const auto raw_d16_rg8_depth_image = + texture_cache.FindImage(raw_d16_rg8_depth); + (void)texture_cache.FindDepthTarget(raw_d16_rg8_depth_image, + raw_d16_rg8_depth); + auto &raw_d16_rg8_depth_native = + texture_cache.GetImage(raw_d16_rg8_depth_image); + raw_d16_rg8_depth_native.Transit(vk::ImageLayout::eTransferDstOptimal, + vk::AccessFlagBits2::eTransferWrite, {}, + scheduler.Current().Handle()); + const vk::ClearDepthStencilValue raw_d16_rg8_clear{16384.0f / 65535.0f, + 0}; + const vk::ImageSubresourceRange raw_d16_rg8_clear_range{ + vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}; + scheduler.Current().Handle().clearDepthStencilImage( + raw_d16_rg8_depth_native.backing.image, + vk::ImageLayout::eTransferDstOptimal, &raw_d16_rg8_clear, 1, + &raw_d16_rg8_clear_range); + texture_cache.MarkGpuWritten(raw_d16_rg8_depth_image); + auto raw_d16_rg8 = raw_d16_uint; + raw_d16_rg8.info.data = raw_d16_rg8_depth.info.data; + raw_d16_rg8.info.pixel_format = vk::Format::eR8G8Unorm; + raw_d16_rg8.info.guest_format = Prospero::BufferFormat::k8_8UNorm; + raw_d16_rg8.view_info.format = vk::Format::eR8G8Unorm; + const auto raw_d16_rg8_image = texture_cache.FindImage(raw_d16_rg8); + Require( + name, "raw D16 8_8 texture backing", + raw_d16_rg8_image && raw_d16_rg8_image != raw_d16_rg8_depth_image && + !TextureCacheTestAccess::Contains(texture_cache, + raw_d16_rg8_depth_image) && + texture_cache.GetImage(raw_d16_rg8_image).backing.format == + vk::Format::eR8G8Unorm && + texture_cache.FindTexture(raw_d16_rg8_image, raw_d16_rg8) != + nullptr, + "D16 sampled as 8_8 UNORM did not recreate a color backing"); + auto raw_d16_rg8_readback = + CreateHostBuffer(name, sizeof(raw_d16_values), + vk::BufferUsageFlagBits::eTransferDst, {0u}); + auto &raw_d16_rg8_native = texture_cache.GetImage(raw_d16_rg8_image); + raw_d16_rg8_native.Transit(vk::ImageLayout::eTransferSrcOptimal, + vk::AccessFlagBits2::eTransferRead, {}, + scheduler.Current().Handle()); + vk::BufferImageCopy raw_d16_rg8_copy{}; + raw_d16_rg8_copy.imageSubresource = {vk::ImageAspectFlagBits::eColor, 0, + 0, 1}; + raw_d16_rg8_copy.imageExtent = {2, 1, 1}; + scheduler.Current().Handle().copyImageToBuffer( + raw_d16_rg8_native.backing.image, + vk::ImageLayout::eTransferSrcOptimal, raw_d16_rg8_readback.buffer, 1, + &raw_d16_rg8_copy); + HostReadBarrier(raw_d16_rg8_readback.buffer, raw_d16_rg8_readback.size, + vk::PipelineStageFlagBits::eTransfer, + vk::AccessFlagBits::eTransferWrite); + scheduler.Finish(); + Require(name, "raw D16 8_8 texture bytes", + ReadBuffer(name, raw_d16_rg8_readback, 1)[0] == 0x40004000u, + "D16 sampled as 8_8 UNORM lost the depth bytes"); + constexpr uint64_t layered_raw_d16_offset = raw_d16_offset + 0x1000; constexpr std::array layered_raw_d16_values{ 0x0102u, 0x0304u, 0x1112u, 0x1314u, 0x2122u, 0x2324u,