From a21bdb9f45ced84d504f8d40a8ea7dc9bd0a95c6 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 18 Sep 2018 21:06:34 +0300 Subject: [PATCH] rsx; blit engine fixes - Forcefully downloads and reuploads data from the CPU in case of unexpected overlaps - Properly detect correct size of newly created blit targets - Remember to clear any existing views when changing the default component map! --- rpcs3/Emu/RSX/Common/texture_cache.h | 45 +++++++++++++++++----------- rpcs3/Emu/RSX/GL/GLHelpers.h | 15 +++++++++- rpcs3/Emu/RSX/GL/GLTextureCache.h | 5 +++- rpcs3/Emu/RSX/VK/VKHelpers.h | 35 +++++++++++----------- rpcs3/Emu/RSX/VK/VKTextureCache.h | 5 +++- rpcs3/Emu/RSX/rsx_cache.h | 3 ++ 6 files changed, 70 insertions(+), 38 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index b6e6f882b5..54c1b09beb 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -2218,7 +2218,6 @@ namespace rsx } section_storage_type* cached_dest = nullptr; - bool invalidate_dst_range = false; if (!dst_is_render_target) { @@ -2266,10 +2265,6 @@ namespace rsx max_dst_width = cached_dest->get_width(); max_dst_height = cached_dest->get_height(); } - else if (overlapping_surfaces.size() > 0) - { - invalidate_dst_range = true; - } } else { @@ -2421,11 +2416,6 @@ namespace rsx dest_texture = 0; cached_dest = nullptr; } - else if (invalidate_dst_range) - { - lock.upgrade(); - invalidate_range_impl_base(dst_address, dst.pitch * dst.height, true, false, true, std::forward(extras)...); - } u32 gcm_format; if (is_depth_blit) @@ -2461,18 +2451,39 @@ namespace rsx if (dest_texture == 0) { - lock.upgrade(); + verify(HERE), !dst_is_render_target; - //render target data is already in correct swizzle layout + // Need to calculate the minium required size that will fit the data, anchored on the rsx_address + // If the application starts off with an 'inseted' section, the guessed dimensions may not fit! + const u32 write_end = dst_address + (dst.pitch * dst.clip_height); + const u32 expected_end = dst.rsx_address + (dst.pitch * dst_dimensions.height); + + const u32 section_length = std::max(write_end, expected_end) - dst.rsx_address; + dst_dimensions.height = section_length / dst.pitch; + + lock.upgrade(); + invalidate_range_impl_base(dst.rsx_address, section_length, true, false, true, std::forward(extras)...); + + const u16 pitch_in_block = dst_is_argb8 ? dst.pitch >> 2 : dst.pitch >> 1; + std::vector subresource_layout; + rsx_subresource_layout subres = {}; + subres.width_in_block = dst_dimensions.width; + subres.height_in_block = dst_dimensions.height; + subres.pitch_in_block = pitch_in_block; + subres.depth = 1; + subres.data = { (const gsl::byte*)dst.pixels, dst.pitch * dst_dimensions.height }; + subresource_layout.push_back(subres); + + cached_dest = upload_image_from_cpu(cmd, dst.rsx_address, dst_dimensions.width, dst_dimensions.height, 1, 1, dst.pitch, + gcm_format, rsx::texture_upload_context::blit_engine_dst, subresource_layout, + rsx::texture_dimension_extended::texture_dimension_2d, false); + + // render target data is already in correct swizzle layout auto channel_order = src_is_render_target ? rsx::texture_create_flags::native_component_order : dst_is_argb8 ? rsx::texture_create_flags::default_component_order : rsx::texture_create_flags::swapped_native_component_order; - //NOTE: Should upload from cpu instead of creating a blank texture - cached_dest = create_new_texture(cmd, dst.rsx_address, dst.pitch * dst_dimensions.height, - dst_dimensions.width, dst_dimensions.height, 1, 1, - gcm_format, rsx::texture_upload_context::blit_engine_dst, rsx::texture_dimension_extended::texture_dimension_2d, - channel_order); + enforce_surface_creation_type(*cached_dest, gcm_format, channel_order); dest_texture = cached_dest->get_raw_texture(); typeless_info.dst_context = texture_upload_context::blit_engine_dst; diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h index f3c9c42558..ffe71c40fd 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.h +++ b/rpcs3/Emu/RSX/GL/GLHelpers.h @@ -1464,7 +1464,7 @@ namespace gl depth = GL_TEXTURE_DEPTH_TYPE }; - private: + protected: GLuint m_id = 0; GLuint m_width = 0; GLuint m_height = 0; @@ -1902,6 +1902,7 @@ namespace gl public: using texture::texture; + texture_view* get_view(u32 remap_encoding, const std::pair, std::array>& remap) { auto found = views.find(remap_encoding); @@ -1916,6 +1917,18 @@ public: views[remap_encoding] = std::move(view); return result; } + + void set_native_component_layout(const std::array& layout) + { + if (m_component_layout[0] != layout[0] || + m_component_layout[1] != layout[1] || + m_component_layout[2] != layout[2] || + m_component_layout[3] != layout[3]) + { + texture::set_native_component_layout(layout); + views.clear(); + } + } }; class rbo diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index e3d8d1115e..a34775466e 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -1030,7 +1030,10 @@ namespace gl return; const auto swizzle = get_component_mapping(gcm_format, flags); - section.get_raw_texture()->set_native_component_layout(swizzle); + auto image = static_cast(section.get_raw_texture()); + + verify(HERE), image != nullptr; + image->set_native_component_layout(swizzle); section.set_view_flags(flags); } diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index c08b981e1a..e1526de208 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "stdafx.h" #include @@ -809,26 +809,13 @@ namespace vk } }; - struct viewable_image : public image + class viewable_image : public image { + private: std::unordered_multimap> views; - viewable_image(vk::render_device &dev, - uint32_t memory_type_index, - uint32_t access_flags, - VkImageType image_type, - VkFormat format, - uint32_t width, uint32_t height, uint32_t depth, - uint32_t mipmaps, uint32_t layers, - VkSampleCountFlagBits samples, - VkImageLayout initial_layout, - VkImageTiling tiling, - VkImageUsageFlags usage, - VkImageCreateFlags image_flags) - - :image(dev, memory_type_index, access_flags, image_type, format, width, height, depth, - mipmaps, layers, samples, initial_layout, tiling, usage, image_flags) - {} + public: + using image::image; image_view* get_view(u32 remap_encoding, const std::pair, std::array>& remap, VkImageAspectFlags mask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT) @@ -855,6 +842,18 @@ namespace vk views.emplace(remap_encoding, std::move(view)); return result; } + + void set_native_component_layout(VkComponentMapping new_layout) + { + if (new_layout.r != native_component_map.r || + new_layout.g != native_component_map.g || + new_layout.b != native_component_map.b || + new_layout.a != native_component_map.a) + { + native_component_map = new_layout; + views.clear(); + } + } }; struct buffer diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 180292dcd5..27bc84fd5e 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -917,7 +917,10 @@ namespace vk return; const VkComponentMapping mapping = apply_component_mapping_flags(gcm_format, expected_flags, rsx::default_remap_vector); - section.get_raw_texture()->native_component_map = mapping; + auto image = static_cast(section.get_raw_texture()); + + verify(HERE), image != nullptr; + image->set_native_component_layout(mapping); section.set_view_flags(expected_flags); } diff --git a/rpcs3/Emu/RSX/rsx_cache.h b/rpcs3/Emu/RSX/rsx_cache.h index 3f8b609bd2..a977d6d1a7 100644 --- a/rpcs3/Emu/RSX/rsx_cache.h +++ b/rpcs3/Emu/RSX/rsx_cache.h @@ -171,6 +171,9 @@ namespace rsx protection = utils::protection::rw; dirty = true; locked = false; + + confirmed_range = { 0, 0 }; + locked_memory_ptr = {}; } /**