From d77e62c94e32e364568d14dbb1b14fc2a3f66131 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 12 Jun 2018 19:22:02 +0300 Subject: [PATCH] rsx: Improve GPU resource read prediction --- rpcs3/Emu/RSX/Common/texture_cache.h | 87 +++++++++++++++++++++++----- rpcs3/Emu/RSX/GL/GLRenderTargets.cpp | 4 +- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 4 +- 3 files changed, 75 insertions(+), 20 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 61eedbd96c..08ad31d1b7 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -72,8 +72,9 @@ namespace rsx bool synchronized = false; bool flushed = false; - u32 num_writes = 0; - u32 required_writes = 1; + + u32 num_writes = 0; + std::deque read_history; u64 cache_tag = 0; @@ -120,7 +121,12 @@ namespace rsx void reset_write_statistics() { - required_writes = num_writes; + if (read_history.size() == 16) + { + read_history.pop_back(); + } + + read_history.push_front(num_writes); num_writes = 0; } @@ -196,8 +202,51 @@ namespace rsx bool writes_likely_completed() const { + // TODO: Move this to the miss statistics block if (context == rsx::texture_upload_context::blit_engine_dst) - return num_writes >= required_writes; + { + const auto num_records = read_history.size(); + + if (num_records == 0) + { + return false; + } + else if (num_records == 1) + { + return num_writes >= read_history.front(); + } + else + { + const u32 last = read_history.front(); + const u32 prev_last = read_history[1]; + + if (last == prev_last && num_records <= 3) + { + return num_writes >= last; + } + + u32 compare = UINT32_MAX; + for (u32 n = 1; n < num_records; n++) + { + if (read_history[n] == last) + { + // Uncertain, but possible + compare = read_history[n - 1]; + + if (num_records > (n + 1)) + { + if (read_history[n + 1] == prev_last) + { + // Confirmed with 2 values + break; + } + } + } + } + + return num_writes >= compare; + } + } return true; } @@ -1045,7 +1094,7 @@ namespace rsx } template - bool flush_memory_to_cache(u32 memory_address, u32 memory_size, bool skip_synchronized, Args&&... extra) + bool flush_memory_to_cache(u32 memory_address, u32 memory_size, bool skip_synchronized, u32 allowed_types_mask, Args&&... extra) { writer_lock lock(m_cache_mutex); section_storage_type* region = find_flushable_section(memory_address, memory_size); @@ -1057,6 +1106,9 @@ namespace rsx if (skip_synchronized && region->is_synchronized()) return false; + if ((allowed_types_mask & region->get_context()) == 0) + return true; + if (!region->writes_likely_completed()) return true; @@ -1243,23 +1295,26 @@ namespace rsx //Reset since the data has changed //TODO: Keep track of all this information together m_cache_miss_statistics_table[memory_address] = { 0, memory_size, fmt }; - return false; } - //Properly synchronized - no miss - if (!value.misses) return false; + // By default, blit targets are always to be tested for readback + u32 flush_mask = rsx::texture_upload_context::blit_engine_dst; - //Auto flush if this address keeps missing (not properly synchronized) - if (value.misses > 16) + // Auto flush if this address keeps missing (not properly synchronized) + if (value.misses >= 4) { - //TODO: Determine better way of setting threshold - if (!flush_memory_to_cache(memory_address, memory_size, true, std::forward(extras)...)) - value.misses--; - - return true; + // TODO: Determine better way of setting threshold + // Allow all types + flush_mask = 0xFF; } - return false; + if (!flush_memory_to_cache(memory_address, memory_size, true, flush_mask, std::forward(extras)...) && + value.misses > 0) + { + value.misses--; + } + + return true; } void purge_dirty() diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index 6ba91eb980..44d3c360de 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -706,7 +706,7 @@ void GLGSRender::write_buffers() */ const u32 range = m_surface_info[i].pitch * m_surface_info[i].height; - __glcheck m_gl_texture_cache.flush_memory_to_cache(m_surface_info[i].address, range, true); + __glcheck m_gl_texture_cache.flush_memory_to_cache(m_surface_info[i].address, range, true, 0xFF); } }; @@ -721,6 +721,6 @@ void GLGSRender::write_buffers() u32 range = m_depth_surface_info.width * m_depth_surface_info.height * 2; if (m_depth_surface_info.depth_format != rsx::surface_depth_format::z16) range *= 2; - m_gl_texture_cache.flush_memory_to_cache(m_depth_surface_info.address, range, true); + m_gl_texture_cache.flush_memory_to_cache(m_depth_surface_info.address, range, true, 0xFF); } } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index cea34a6894..9a0369658f 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1812,7 +1812,7 @@ void VKGSRender::copy_render_targets_to_dma_location() if (!m_surface_info[index].pitch) continue; - m_texture_cache.flush_memory_to_cache(m_surface_info[index].address, m_surface_info[index].pitch * m_surface_info[index].height, true, + m_texture_cache.flush_memory_to_cache(m_surface_info[index].address, m_surface_info[index].pitch * m_surface_info[index].height, true, 0xFF, *m_current_command_buffer, m_swapchain->get_graphics_queue()); } } @@ -1821,7 +1821,7 @@ void VKGSRender::copy_render_targets_to_dma_location() { if (m_depth_surface_info.pitch) { - m_texture_cache.flush_memory_to_cache(m_depth_surface_info.address, m_depth_surface_info.pitch * m_depth_surface_info.height, true, + m_texture_cache.flush_memory_to_cache(m_depth_surface_info.address, m_depth_surface_info.pitch * m_depth_surface_info.height, true, 0xFF, *m_current_command_buffer, m_swapchain->get_graphics_queue()); } }