diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index a9929f4c32..122f03f0e0 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -323,6 +323,12 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6 //a5 low bits = ret.format = base | ((base + ((size - 1) / 0x10000)) << 13) | (comp << 26) | (1 << 30); auto& tile = render->tiles[a3]; + + // When tile is going to be unbinded, we can use it as a hint that the address will no longer be used as a surface and can be removed/invalidated + // Todo: There may be more checks such as format/size/width can could be done + if (tile.binded && a5 == 0) + render->notify_tile_unbound(a3); + tile.location = ((a4 >> 32) & 0xF) - 1; tile.offset = ((((a4 >> 32) & 0xFFFFFFFF) >> 16) * 0x10000); tile.size = ((((a4 & 0x7FFFFFFF) >> 16) + 1) * 0x10000) - tile.offset; diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index 77d6626b65..e3971ccce2 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -517,6 +517,31 @@ namespace rsx } } + /** + * Invalidates surface that exists at an address + */ + void invalidate_surface_address(u32 addr, bool depth) + { + if (!depth) + { + auto It = m_render_targets_storage.find(addr); + if (It != m_render_targets_storage.end()) + { + invalidated_resources.push_back(std::move(It->second)); + m_render_targets_storage.erase(It); + } + } + else + { + auto It = m_depth_stencil_storage.find(addr); + if (It != m_depth_stencil_storage.end()) + { + invalidated_resources.push_back(std::move(It->second)); + m_depth_stencil_storage.erase(It); + } + } + } + /** * Clipping and fitting lookup funcrions * surface_overlaps - returns true if surface overlaps a given surface address and returns the relative x and y position of the surface address within the surface diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index 066eabd467..18a94718e3 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -183,4 +183,5 @@ protected: virtual std::array, 4> copy_render_targets_to_memory() override; virtual std::array, 2> copy_depth_stencil_buffer_to_memory() override; virtual std::pair get_programs() const override; + virtual void notify_tile_unbound(u32 tile) override; }; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp index c96e9ce0dc..c3f04f0347 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp @@ -316,4 +316,10 @@ std::pair D3D12GSRender::get_programs() const { return std::make_pair(m_pso_cache.get_transform_program(current_vertex_program).content, m_pso_cache.get_shader_program(current_fragment_program).content); } + +void D3D12GSRender::notify_tile_unbound(u32 tile) +{ + u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location); + m_rtts.invalidate_surface_address(addr, false); +} #endif diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index d82b508135..87a1ac3b18 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1286,6 +1286,12 @@ bool GLGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst return m_gl_texture_cache.blit(src, dst, interpolate, m_rtts); } +void GLGSRender::notify_tile_unbound(u32 tile) +{ + u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location); + m_rtts.invalidate_surface_address(addr, false); +} + void GLGSRender::check_zcull_status(bool framebuffer_swap, bool force_read) { if (g_cfg.video.disable_zcull_queries) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index a23291c363..3f97d22cfa 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -453,6 +453,7 @@ protected: bool on_access_violation(u32 address, bool is_writing) override; void on_notify_memory_unmapped(u32 address_base, u32 size) override; + void notify_tile_unbound(u32 tile) override; virtual std::array, 4> copy_render_targets_to_memory() override; virtual std::array, 2> copy_depth_stencil_buffer_to_memory() override; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 075d50ee7f..c0f8f82cac 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -706,7 +706,6 @@ namespace rsx if (invalid_command_interrupt_raised) { //Skip the rest of this command - internal_get = put; break; } } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 085e393140..85cda50916 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -258,6 +258,7 @@ namespace rsx virtual u64 timestamp() const; virtual bool on_access_violation(u32 /*address*/, bool /*is_writing*/) { return false; } virtual void on_notify_memory_unmapped(u32 /*address_base*/, u32 /*size*/) {} + virtual void notify_tile_unbound(u32 tile) {} //zcull virtual void notify_zcull_info_changed() {} diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 3f7db8fa3a..3fa8878c9c 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -2685,3 +2685,9 @@ bool VKGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst return result; } + +void VKGSRender::notify_tile_unbound(u32 tile) +{ + u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location); + m_rtts.invalidate_surface_address(addr, false); +} \ No newline at end of file diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index db3f94ac26..6480f727ec 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -316,6 +316,7 @@ protected: void do_local_task() override; bool scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate) override; + void notify_tile_unbound(u32 tile) override; bool on_access_violation(u32 address, bool is_writing) override; void on_notify_memory_unmapped(u32 address_base, u32 size) override;