diff --git a/src/graphics/host_gpu/renderer/cache/textureCache.cpp b/src/graphics/host_gpu/renderer/cache/textureCache.cpp index 7eb12a12..c8cd7c7e 100644 --- a/src/graphics/host_gpu/renderer/cache/textureCache.cpp +++ b/src/graphics/host_gpu/renderer/cache/textureCache.cpp @@ -1221,9 +1221,6 @@ void TextureCache::RefreshImage(ImageId id) { m_slot_images[image.depth_id].info.samples != 1)) { return; } - if (image.info.HasStencil()) { - RefreshImage(AssociateStencil(id, image.info.stencil)); - } TrackImage(id); if (image.IsMaybeCpuDirty()) { const auto hash = image.HashGuestEdges(); @@ -1418,6 +1415,19 @@ vk::ImageView TextureCache::FindTexture(ImageId id, const ImageDesc& desc) { } if (!image.info.data.Empty()) { RefreshImage(id); + if (image.info.HasStencil() && + desc.info.data.address >= image.info.stencil.address && + desc.info.data.End() <= image.info.stencil.End()) { + for (const auto stencil_id: + FindImagesInRegion(image.info.stencil.address, image.info.stencil.size, false)) { + const auto* stencil = m_slot_images.try_get(stencil_id); + if (stencil != nullptr && stencil->depth_id == id && + stencil->info.data == image.info.stencil) { + RefreshImage(stencil_id); + break; + } + } + } } switch (desc.type) { case BindingType::Texture: break; @@ -1475,6 +1485,9 @@ vk::ImageView TextureCache::FindDepthTarget(ImageId id, const ImageDesc& desc) { } RefreshImage(id); CommitGpuWrite(image); + if (desc.info.HasStencil()) { + RefreshImage(AssociateStencil(id, desc.info.stencil)); + } const auto view = image.FindView(desc.view_info); NameImageBinding(m_graphics, image, view, desc.type, desc.view_info); return view; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 4b2d34d9..a82190f1 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -12374,7 +12374,25 @@ public: plane_depth.info.tile_mode = Prospero::TileMode::kDepth; plane_depth.info.mip_layout[0] = {0, plane_size, plane_depth.info.pitch, 2}; const auto plane_depth_id = texture_cache.FindImage(plane_depth); + auto sampled_plane = plane_depth; + sampled_plane.type = BindingType::Texture; + sampled_plane.info.data = plane_depth.info.stencil; + sampled_plane.info.stencil = {}; + sampled_plane.info.metadata = {}; + sampled_plane.info.pixel_format = vk::Format::eR8Uint; + sampled_plane.info.guest_format = Prospero::BufferFormat::k8UInt; + sampled_plane.info.bytes_per_block = 1; + sampled_plane.info.pitch = TileGetDepthPitch(3, 1); + sampled_plane.info.mip_layout[0] = {0, plane_size, sampled_plane.info.pitch, 2}; + sampled_plane.view_info.format = vk::Format::eR8Uint; + sampled_plane.view_info.aspect = vk::ImageAspectFlagBits::eColor; + sampled_plane.view_info.usage = vk::ImageUsageFlagBits::eSampled; + const auto sampled_plane_id = texture_cache.FindImage(sampled_plane); + (void)texture_cache.FindTexture(sampled_plane_id, sampled_plane); (void)texture_cache.FindDepthTarget(plane_depth_id, plane_depth); + Require(name, "sampled stencil association", + texture_cache.GetImage(sampled_plane_id).depth_id == plane_depth_id, + "depth acquisition did not associate the sampled stencil plane"); TextureCacheTestAccess::ClearImage(texture_cache, scheduler.Current(), plane_depth_id, {vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil, 0, 1, 0, 1}, stencil_initial); @@ -12480,6 +12498,25 @@ public: } std::memcpy(reinterpret_cast(plane_address), plane_words.data(), plane_size); check_plane("CPU stencil write after native clear", false); + for (uint32_t i = 0; i < texels; ++i) { + plane_bytes[plane_offsets[i]] += 0x10; + } + std::memcpy(reinterpret_cast(plane_address), plane_words.data(), plane_size); + Require(name, "sampled stencil view", + texture_cache.FindTexture(plane_depth_id, sampled_plane) != nullptr, + "an associated stencil plane could not be sampled"); + texture_cache.GetImage(plane_depth_id).Download( + plane_copies, plane_readback.buffer, 0, plane_readback.size); + scheduler.Current().Handle().pipelineBarrier2(stencil_dependency); + scheduler.Finish(); + const auto sampled_values = ReadBuffer(name, plane_readback, texels + 2); + const auto *sampled_bytes = + reinterpret_cast(sampled_values.data() + texels); + for (uint32_t i = 0; i < texels; ++i) { + Require(name, "sampled stencil plane refresh", + sampled_bytes[i] == plane_bytes[plane_offsets[i]], + "sampling without another depth acquisition used stale stencil bytes"); + } DestroyBuffer(&plane_readback); DestroyBuffer(&plane_upload); LibKernel::Memory::InstallGpuResources(nullptr);