diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 08ad31d1b7..b6da62b6cb 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -70,6 +70,7 @@ namespace rsx u32 gcm_format = 0; bool pack_unpack_swap_bytes = false; + u64 sync_timestamp = 0; bool synchronized = false; bool flushed = false; @@ -250,6 +251,31 @@ namespace rsx return true; } + + void reprotect(utils::protection prot, const std::pair& range) + { + //Reset properties and protect again + flushed = false; + synchronized = false; + sync_timestamp = 0ull; + + protect(prot, range); + } + + void reprotect(utils::protection prot) + { + //Reset properties and protect again + flushed = false; + synchronized = false; + sync_timestamp = 0ull; + + protect(prot); + } + + u64 get_sync_timestamp() const + { + return sync_timestamp; + } }; template @@ -701,6 +727,18 @@ namespace rsx } else { + if (obj.first->get_memory_read_flags() == rsx::memory_read_flags::flush_always) + { + // This region is set to always read from itself (unavoi + const auto ROP_timestamp = rsx::get_current_renderer()->ROP_sync_timestamp; + if (obj.first->is_synchronized() && ROP_timestamp > obj.first->get_sync_timestamp()) + { + m_num_cache_mispredictions++; + m_num_cache_misses++; + obj.first->copy_texture(true, std::forward(extras)...); + } + } + if (!obj.first->flush(std::forward(extras)...)) { //Missed address, note this @@ -1216,6 +1254,18 @@ namespace rsx { if (tex->is_locked()) { + if (tex->get_memory_read_flags() == rsx::memory_read_flags::flush_always) + { + // This region is set to always read from itself (unavoi + const auto ROP_timestamp = rsx::get_current_renderer()->ROP_sync_timestamp; + if (tex->is_synchronized() && ROP_timestamp > tex->get_sync_timestamp()) + { + m_num_cache_mispredictions++; + m_num_cache_misses++; + tex->copy_texture(true, std::forward(extras)...); + } + } + if (!tex->flush(std::forward(extras)...)) { record_cache_miss(*tex); @@ -1303,9 +1353,13 @@ namespace rsx // Auto flush if this address keeps missing (not properly synchronized) if (value.misses >= 4) { - // TODO: Determine better way of setting threshold - // Allow all types - flush_mask = 0xFF; + // Disable prediction if memory is flagged as flush_always + if (m_flush_always_cache.find(memory_address) == m_flush_always_cache.end()) + { + // TODO: Determine better way of setting threshold + // Allow all types + flush_mask = 0xFF; + } } if (!flush_memory_to_cache(memory_address, memory_size, true, flush_mask, std::forward(extras)...) && diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 297580e766..5ce98fdd17 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -404,7 +404,7 @@ void D3D12GSRender::end() ); } - m_graphics_state = 0; + m_graphics_state &= ~rsx::pipeline_state::memory_barrier_bits; std::chrono::time_point constants_duration_end = steady_clock::now(); m_timers.constants_duration += std::chrono::duration_cast(constants_duration_end - constants_duration_start).count(); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 5dac3300b5..f1851774cc 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1183,7 +1183,7 @@ void GLGSRender::load_program(const gl::vertex_upload_info& upload_info) } // Fragment state - fill_fragment_state_buffer(buf+fragment_constants_size, current_fragment_program); + fill_fragment_state_buffer(buf + fragment_constants_size, current_fragment_program); m_vertex_state_buffer->bind_range(0, vertex_state_offset, 512); m_fragment_constants_buffer->bind_range(2, fragment_constants_offset, fragment_buffer_size); @@ -1198,7 +1198,7 @@ void GLGSRender::load_program(const gl::vertex_upload_info& upload_info) if (update_transform_constants) m_transform_constants_buffer->unmap(); } - m_graphics_state = 0; + m_graphics_state &= ~rsx::pipeline_state::memory_barrier_bits; } void GLGSRender::update_draw_state() @@ -1600,9 +1600,13 @@ void GLGSRender::do_local_task(rsx::FIFO_state state) } else if (!in_begin_end && state != rsx::FIFO_state::lock_wait) { - //This will re-engage locks and break the texture cache if another thread is waiting in access violation handler! - //Only call when there are no waiters - m_gl_texture_cache.do_update(); + if (m_graphics_state & rsx::pipeline_state::framebuffer_reads_dirty) + { + //This will re-engage locks and break the texture cache if another thread is waiting in access violation handler! + //Only call when there are no waiters + m_gl_texture_cache.do_update(); + m_graphics_state &= ~rsx::pipeline_state::framebuffer_reads_dirty; + } } rsx::thread::do_local_task(state); diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index a89c66eb6d..e734352518 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -260,6 +260,7 @@ namespace gl flushed = false; synchronized = false; + sync_timestamp = 0ull; is_depth = false; vram_texture = nullptr; @@ -291,6 +292,7 @@ namespace gl flushed = false; synchronized = false; + sync_timestamp = 0ull; is_depth = false; this->width = w; @@ -454,6 +456,7 @@ namespace gl m_fence.reset(); synchronized = true; + sync_timestamp = get_system_time(); } void fill_texture(gl::texture* tex) @@ -603,20 +606,6 @@ namespace gl return result; } - void reprotect(utils::protection prot, const std::pair& range) - { - flushed = false; - synchronized = false; - protect(prot, range); - } - - void reprotect(utils::protection prot) - { - flushed = false; - synchronized = false; - protect(prot); - } - void destroy() { if (!locked && pbo_id == 0 && vram_texture == 0 && m_fence.is_empty()) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index ee12f56001..0588938153 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -330,6 +330,9 @@ namespace rsx in_begin_end = false; + m_graphics_state |= rsx::pipeline_state::framebuffer_reads_dirty; + ROP_sync_timestamp = get_system_time(); + for (u8 index = 0; index < rsx::limits::vertex_count; ++index) { //Disabled, see https://github.com/RPCS3/rpcs3/issues/1932 diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 3725706669..c543081a68 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -76,8 +76,10 @@ namespace rsx fragment_state_dirty = 4, vertex_state_dirty = 8, transform_constants_dirty = 16, + framebuffer_reads_dirty = 32, invalidate_pipeline_bits = fragment_program_dirty | vertex_program_dirty, + memory_barrier_bits = framebuffer_reads_dirty, all_dirty = 255 }; @@ -358,6 +360,7 @@ namespace rsx bool m_vertex_textures_dirty[4]; bool m_framebuffer_state_contested = false; u32 m_graphics_state = 0; + u64 ROP_sync_timestamp = 0; protected: std::array get_color_surface_addresses() const; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 93c9cd9f23..44b56d4d4b 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -2065,9 +2065,13 @@ void VKGSRender::do_local_task(rsx::FIFO_state state) } else if (!in_begin_end && state != rsx::FIFO_state::lock_wait) { - //This will re-engage locks and break the texture cache if another thread is waiting in access violation handler! - //Only call when there are no waiters - m_texture_cache.do_update(); + if (m_graphics_state & rsx::pipeline_state::framebuffer_reads_dirty) + { + //This will re-engage locks and break the texture cache if another thread is waiting in access violation handler! + //Only call when there are no waiters + m_texture_cache.do_update(); + m_graphics_state &= ~rsx::pipeline_state::framebuffer_reads_dirty; + } } rsx::thread::do_local_task(state); @@ -2417,7 +2421,7 @@ void VKGSRender::load_program(const vk::vertex_upload_info& vertex_info) } //Clear flags - m_graphics_state = 0; + m_graphics_state &= ~rsx::pipeline_state::memory_barrier_bits; } static const u32 mr_color_offset[rsx::limits::color_buffers_count] = diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 4fc746cf51..ef7ec7b571 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -20,8 +20,6 @@ namespace vk //DMA relevant data VkFence dma_fence = VK_NULL_HANDLE; - u64 sync_timestamp = 0; - u64 last_use_timestamp = 0; vk::render_device* m_device = nullptr; vk::image *vram_texture = nullptr; std::unique_ptr dma_buffer; @@ -72,7 +70,6 @@ namespace vk synchronized = false; flushed = false; sync_timestamp = 0ull; - last_use_timestamp = get_system_time(); } void release_dma_resources() @@ -351,41 +348,11 @@ namespace vk pack_unpack_swap_bytes = swap_bytes; } - void reprotect(utils::protection prot, const std::pair& range) - { - //Reset properties and protect again - flushed = false; - synchronized = false; - sync_timestamp = 0ull; - - protect(prot, range); - } - - void reprotect(utils::protection prot) - { - //Reset properties and protect again - flushed = false; - synchronized = false; - sync_timestamp = 0ull; - - protect(prot); - } - - void invalidate_cached() - { - synchronized = false; - } - bool is_synchronized() const { return synchronized; } - bool sync_valid() const - { - return (sync_timestamp > last_use_timestamp); - } - bool has_compatible_format(vk::image* tex) const { return vram_texture->info.format == tex->info.format; @@ -403,11 +370,6 @@ namespace vk return false; } } - - u64 get_sync_timestamp() const - { - return sync_timestamp; - } }; struct discarded_storage