diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 08c599255b..757f72c92b 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -273,13 +273,14 @@ namespace rsx if (trampled_set.size() > 0) { // Rebuild the cache by only destroying ranges that need to be destroyed to unlock this page - const auto to_reprotect = std::remove_if(trampled_set.begin(), trampled_set.end(), + const auto to_reprotect = !rebuild_cache? trampled_set.end() : + std::remove_if(trampled_set.begin(), trampled_set.end(), [&](const std::pair& obj) { if (!is_writing && obj.first->get_protection() != utils::protection::no) return true; - if (!rebuild_cache && !obj.first->is_flushable()) + if (!obj.first->is_flushable()) return false; const std::pair null_check = std::make_pair(UINT32_MAX, 0); @@ -309,6 +310,20 @@ namespace rsx obj.second->remove_one(); } + if (allow_flush) + { + // Flush here before 'reprotecting' since flushing will write the whole span + for (const auto &tex : sections_to_flush) + { + if (!tex->flush(std::forward(extras)...)) + { + //Missed address, note this + //TODO: Lower severity when successful to keep the cache from overworking + record_cache_miss(*tex); + } + } + } + for (auto It = to_reprotect; It != trampled_set.end(); It++) { auto obj = *It; @@ -319,26 +334,9 @@ namespace rsx obj.first->set_dirty(false); } - if (discard_only) + if (discard_only || allow_flush) return{ true, {} }; - //trampled_set.erase(to_reprotect, trampled_set.end()); - - if (allow_flush) - { - for (const auto &tex : sections_to_flush) - { - if (!tex->flush(std::forward(extras)...)) - { - //Missed address, note this - //TODO: Lower severity when successful to keep the cache from overworking - record_cache_miss(*tex); - } - } - - return{ true, {} }; - } - return std::make_pair(true, sections_to_flush); } @@ -348,7 +346,7 @@ namespace rsx template std::pair> invalidate_range_impl(u32 address, u32 range, bool is_writing, bool discard, bool allow_flush, Args&&... extras) { - return invalidate_range_impl_base(address, range, is_writing, discard, false, allow_flush, std::forward(extras)...); + return invalidate_range_impl_base(address, range, is_writing, discard, true, allow_flush, std::forward(extras)...); } bool is_hw_blit_engine_compatible(const u32 format) const @@ -930,7 +928,8 @@ namespace rsx auto subresources_layout = get_subresources_layout(tex); auto remap_vector = tex.decoded_remap(); - invalidate_range_impl(texaddr, tex_size, false, false, true, std::forward(extras)...); + //Invalidate with writing=false, discard=false, rebuild=false, native_flush=true + invalidate_range_impl_base(texaddr, tex_size, false, false, false, true, std::forward(extras)...); m_texture_memory_in_use += (tex_pitch * tex_height); return upload_image_from_cpu(cmd, texaddr, tex_width, tex_height, depth, tex.get_exact_mipmap_count(), tex_pitch, format, diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index d7145921ff..30d1a0f73f 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -386,6 +386,8 @@ namespace gl bool flush() { + if (flushed) return true; //Already written, ignore + if (!copied) { LOG_WARNING(RSX, "Cache miss at address 0x%X. This is gonna hurt...", cpu_address_base); @@ -399,7 +401,6 @@ namespace gl } } - protect(utils::protection::rw); m_fence.wait_for_signal(); flushed = true; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index cf60adc94a..9ce490064f 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -567,6 +567,7 @@ VKGSRender::VKGSRender() : GSRender() //Create secondary command_buffer for parallel operations m_secondary_command_buffer_pool.create((*m_device)); m_secondary_command_buffer.create(m_secondary_command_buffer_pool); + m_secondary_command_buffer.access_hint = vk::command_buffer::access_type_hint::all; //Precalculated stuff m_render_passes = get_precomputed_render_passes(*m_device, m_optimal_tiling_supported_formats); diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index 0e14088f8f..ecf1c3d95e 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -1013,6 +1013,14 @@ namespace vk vk::command_pool *pool = nullptr; VkCommandBuffer commands = nullptr; + public: + enum access_type_hint + { + flush_only, //Only to be submitted/opened/closed via command flush + all //Auxilliary, can be sumitted/opened/closed at any time + } + access_hint = flush_only; + public: command_buffer() {} ~command_buffer() {} diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 6ed7ee8039..e79b1bb01c 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -20,6 +20,7 @@ namespace vk //DMA relevant data VkFence dma_fence = VK_NULL_HANDLE; bool synchronized = false; + bool flushed = false; u64 sync_timestamp = 0; u64 last_use_timestamp = 0; vk::render_device* m_device = nullptr; @@ -62,6 +63,7 @@ namespace vk //Even if we are managing the same vram section, we cannot guarantee contents are static //The create method is only invoked when a new mangaged session is required synchronized = false; + flushed = false; sync_timestamp = 0ull; last_use_timestamp = get_system_time(); } @@ -179,6 +181,9 @@ namespace vk CHECK_RESULT(vkWaitForFences(*m_device, 1, &dma_fence, VK_TRUE, UINT64_MAX)); CHECK_RESULT(vkResetCommandBuffer(cmd, 0)); CHECK_RESULT(vkResetFences(*m_device, 1, &dma_fence)); + + if (cmd.access_hint != vk::command_buffer::access_type_hint::all) + cmd.begin(); } synchronized = true; @@ -204,6 +209,8 @@ namespace vk bool flush(vk::render_device& dev, vk::command_buffer& cmd, vk::memory_type_mapping& memory_types, VkQueue submit_queue) { + if (flushed) return true; + if (m_device == nullptr) m_device = &dev; @@ -217,7 +224,7 @@ namespace vk result = false; } - protect(utils::protection::rw); + flushed = true; void* pixels_src = dma_buffer->map(0, cpu_address_range); void* pixels_dst = vm::base(cpu_address_base);