rsx: Do not reuse/destroy sections that have references held

- Avoids a situation where blit-dst and blit-src have overlapping ranges. Uploading blit-dst destroys blit-src and vice-versa.
  This is not the end of the world, but blit-src should be kept around until the operation is completed to avoid stale references!
This commit is contained in:
kd-11 2021-10-26 23:43:27 +03:00 committed by kd-11
parent c733e794de
commit 78bcb0fd53
2 changed files with 15 additions and 4 deletions

View file

@ -1106,7 +1106,7 @@ namespace rsx
} }
else if (best_fit == nullptr && tex.can_be_reused()) else if (best_fit == nullptr && tex.can_be_reused())
{ {
//By grabbing a ref to a matching entry, duplicates are avoided // By grabbing a ref to a matching entry, duplicates are avoided
best_fit = &tex; best_fit = &tex;
} }
} }
@ -2502,6 +2502,7 @@ namespace rsx
} }
section_storage_type* cached_dest = nullptr; section_storage_type* cached_dest = nullptr;
section_storage_type* cached_src = nullptr;
bool dst_is_depth_surface = false; bool dst_is_depth_surface = false;
u16 max_dst_width = dst.width; u16 max_dst_width = dst.width;
u16 max_dst_height = dst.height; u16 max_dst_height = dst.height;
@ -2688,9 +2689,7 @@ namespace rsx
// NOTE: Src address already takes into account the flipped nature of the overlap! // NOTE: Src address already takes into account the flipped nature of the overlap!
const u32 lookup_mask = rsx::texture_upload_context::blit_engine_src | rsx::texture_upload_context::blit_engine_dst | rsx::texture_upload_context::shader_read; const u32 lookup_mask = rsx::texture_upload_context::blit_engine_src | rsx::texture_upload_context::blit_engine_dst | rsx::texture_upload_context::shader_read;
auto overlapping_surfaces = find_texture_from_range<false>(address_range::start_length(src_address, src_payload_length), src.pitch, lookup_mask); auto overlapping_surfaces = find_texture_from_range<false>(address_range::start_length(src_address, src_payload_length), src.pitch, lookup_mask);
auto old_src_area = src_area; auto old_src_area = src_area;
section_storage_type *cached_src = nullptr;
for (const auto &surface : overlapping_surfaces) for (const auto &surface : overlapping_surfaces)
{ {
@ -2816,6 +2815,7 @@ namespace rsx
typeless_info.src_gcm_format = cached_src->get_gcm_format(); typeless_info.src_gcm_format = cached_src->get_gcm_format();
} }
cached_src->add_ref();
vram_texture = cached_src->get_raw_texture(); vram_texture = cached_src->get_raw_texture();
typeless_info.src_context = cached_src->get_context(); typeless_info.src_context = cached_src->get_context();
} }
@ -2879,6 +2879,7 @@ namespace rsx
lock.upgrade(); lock.upgrade();
// NOTE: Write flag set to remove all other overlapping regions (e.g shader_read or blit_src) // NOTE: Write flag set to remove all other overlapping regions (e.g shader_read or blit_src)
// NOTE: This step can potentially invalidate the newly created src image as well.
invalidate_range_impl_base(cmd, rsx_range, invalidation_cause::write, std::forward<Args>(extras)...); invalidate_range_impl_base(cmd, rsx_range, invalidation_cause::write, std::forward<Args>(extras)...);
if (use_null_region) [[likely]] if (use_null_region) [[likely]]
@ -3059,6 +3060,11 @@ namespace rsx
cached_dest->dma_transfer(cmd, vram_texture, src_area, dst_range, dst.pitch); cached_dest->dma_transfer(cmd, vram_texture, src_area, dst_range, dst.pitch);
} }
if (cached_src)
{
cached_src->release();
}
blit_op_result result = true; blit_op_result result = true;
if (cached_dest) if (cached_dest)

View file

@ -1042,7 +1042,7 @@ namespace rsx
* Cached Texture Section * Cached Texture Section
*/ */
template <typename derived_type, typename traits> template <typename derived_type, typename traits>
class cached_texture_section : public rsx::buffered_section class cached_texture_section : public rsx::buffered_section, public rsx::ref_counted
{ {
public: public:
using ranged_storage_type = ranged_storage<traits>; using ranged_storage_type = ranged_storage<traits>;
@ -1312,6 +1312,11 @@ namespace rsx
bool can_be_reused() const bool can_be_reused() const
{ {
if (has_refs()) [[unlikely]]
{
return false;
}
return !exists() || (is_dirty() && !is_locked()); return !exists() || (is_dirty() && !is_locked());
} }