diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 373c66a121..68b0de10bc 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -192,6 +192,7 @@ namespace rsx std::vector> result; u64 cache_tag = get_system_time(); u32 last_dirty_block = UINT32_MAX; + std::pair trampled_range = std::make_pair(address, address + range); for (auto It = m_cache.begin(); It != m_cache.end(); It++) @@ -250,7 +251,7 @@ namespace rsx //2. A vector of all sections that should be flushed if the caller did not set the allow_flush method. That way the caller can make preparations on how to deal with sections that require flushing // Note that the sections will be unlocked regardless of the allow_flush flag template - std::pair> invalidate_range_impl_base(u32 address, u32 range, bool discard_only, bool rebuild_cache, bool allow_flush, Args&&... extras) + std::pair> invalidate_range_impl_base(u32 address, u32 range, bool is_writing, bool discard_only, bool rebuild_cache, bool allow_flush, Args&&... extras) { auto trampled_set = get_intersecting_set(address, range, allow_flush); @@ -260,6 +261,9 @@ namespace rsx const auto to_reprotect = 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()) return false; @@ -300,7 +304,10 @@ namespace rsx obj.first->set_dirty(false); } - trampled_set.erase(to_reprotect, trampled_set.end()); + if (discard_only) + return{ true, {} }; + + //trampled_set.erase(to_reprotect, trampled_set.end()); if (allow_flush) { @@ -324,9 +331,9 @@ namespace rsx } template - std::pair> invalidate_range_impl(u32 address, u32 range, bool discard, bool allow_flush, Args&&... extras) + 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, discard, false, allow_flush, std::forward(extras)...); + return invalidate_range_impl_base(address, range, is_writing, discard, false, allow_flush, std::forward(extras)...); } bool is_hw_blit_engine_compatible(const u32 format) const @@ -565,19 +572,13 @@ namespace rsx } template - std::pair> invalidate_address(u32 address, bool allow_flush, Args&&... extras) + std::pair> invalidate_address(u32 address, bool is_writing, bool allow_flush, Args&&... extras) { - return invalidate_range(address, 4096 - (address & 4095), false, allow_flush, std::forward(extras)...); + return invalidate_range(address, 4096 - (address & 4095), is_writing, false, allow_flush, std::forward(extras)...); } template - std::pair> flush_address(u32 address, Args&&... extras) - { - return invalidate_range(address, 4096 - (address & 4095), false, true, std::forward(extras)...); - } - - template - std::pair> invalidate_range(u32 address, u32 range, bool discard, bool allow_flush, Args&&... extras) + std::pair> invalidate_range(u32 address, u32 range, bool is_writing, bool discard, bool allow_flush, Args&&... extras) { std::pair trampled_range = std::make_pair(address, address + range); @@ -591,7 +592,7 @@ namespace rsx } writer_lock lock(m_cache_mutex); - return invalidate_range_impl(address, range, discard, allow_flush, std::forward(extras)...); + return invalidate_range_impl(address, range, is_writing, discard, allow_flush, std::forward(extras)...); } template @@ -908,7 +909,7 @@ namespace rsx auto subresources_layout = get_subresources_layout(tex); auto remap_vector = tex.decoded_remap(); - invalidate_range_impl(texaddr, tex_size, false, true, std::forward(extras)...); + invalidate_range_impl(texaddr, tex_size, 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, @@ -1001,8 +1002,8 @@ namespace rsx const u32 memcpy_bytes_length = dst.clip_width * bpp * dst.clip_height; lock.upgrade(); - invalidate_range_impl(src_address, memcpy_bytes_length, false, true, std::forward(extras)...); - invalidate_range_impl(dst_address, memcpy_bytes_length, false, true, std::forward(extras)...); + invalidate_range_impl(src_address, memcpy_bytes_length, false, false, true, std::forward(extras)...); + invalidate_range_impl(dst_address, memcpy_bytes_length, true, false, true, std::forward(extras)...); memcpy(dst.pixels, src.pixels, memcpy_bytes_length); return true; } @@ -1104,7 +1105,7 @@ namespace rsx { lock.upgrade(); - invalidate_range_impl(src_address, src.pitch * src.slice_h, false, true, std::forward(extras)...); + invalidate_range_impl(src_address, src.pitch * src.slice_h, false, false, true, std::forward(extras)...); const u16 pitch_in_block = src_is_argb8 ? src.pitch >> 2 : src.pitch >> 1; std::vector subresource_layout; @@ -1176,7 +1177,7 @@ namespace rsx if (format_mismatch) { lock.upgrade(); - invalidate_range_impl(cached_dest->get_section_base(), cached_dest->get_section_size(), false, true, std::forward(extras)...); + invalidate_range_impl(cached_dest->get_section_base(), cached_dest->get_section_size(), true, false, true, std::forward(extras)...); dest_texture = 0; cached_dest = nullptr; @@ -1184,7 +1185,7 @@ namespace rsx else if (invalidate_dst_range) { lock.upgrade(); - invalidate_range_impl(dst_address, dst.pitch * dst.height, false, true, std::forward(extras)...); + invalidate_range_impl(dst_address, dst.pitch * dst.height, true, false, true, std::forward(extras)...); } //Validate clipping region diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 04ccc6e8e5..197aae2939 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1210,7 +1210,7 @@ u64 GLGSRender::timestamp() const bool GLGSRender::on_access_violation(u32 address, bool is_writing) { bool can_flush = (std::this_thread::get_id() == m_thread_id); - auto result = m_gl_texture_cache.invalidate_address(address, can_flush); + auto result = m_gl_texture_cache.invalidate_address(address, is_writing, can_flush); if (!result.first) return false; @@ -1235,7 +1235,7 @@ bool GLGSRender::on_access_violation(u32 address, bool is_writing) void GLGSRender::on_notify_memory_unmapped(u32 address_base, u32 size) { //Discard all memory in that range without bothering with writeback (Force it for strict?) - if (std::get<0>(m_gl_texture_cache.invalidate_range(address_base, size, true, false))) + if (std::get<0>(m_gl_texture_cache.invalidate_range(address_base, size, true, true, false))) m_gl_texture_cache.purge_dirty(); } diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index 0d2bb334ac..4d539c4c20 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -403,7 +403,7 @@ void GLGSRender::read_buffers() } else { - m_gl_texture_cache.invalidate_range(texaddr, range, false, true); + m_gl_texture_cache.invalidate_range(texaddr, range, false, false, true); std::unique_ptr buffer(new u8[pitch * height]); color_buffer.read(buffer.get(), width, height, pitch); diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index cbaa5eb809..388e199178 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -473,6 +473,7 @@ namespace gl glBindTexture(target, id); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 9cdae71618..9b9c70d1f3 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -740,7 +740,7 @@ VKGSRender::~VKGSRender() bool VKGSRender::on_access_violation(u32 address, bool is_writing) { std::lock_guard lock(m_secondary_cb_guard); - auto result = m_texture_cache.invalidate_address(address, false, *m_device, m_secondary_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue()); + auto result = m_texture_cache.invalidate_address(address, is_writing, false, *m_device, m_secondary_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue()); if (!result.first) return false; @@ -831,7 +831,7 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing) void VKGSRender::on_notify_memory_unmapped(u32 address_base, u32 size) { std::lock_guard lock(m_secondary_cb_guard); - if (std::get<0>(m_texture_cache.invalidate_range(address_base, size, false, false, + if (std::get<0>(m_texture_cache.invalidate_range(address_base, size, true, true, false, *m_device, m_secondary_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue()))) { m_texture_cache.purge_dirty();