rsx: Refactor surface inheritance logic

This commit is contained in:
kd-11 2021-04-18 21:42:34 +03:00 committed by Ivan
parent 24e4a43ec4
commit 78972cd611
2 changed files with 52 additions and 42 deletions

View File

@ -279,6 +279,7 @@ namespace rsx
} }
result.push_back({ e.first, surface }); result.push_back({ e.first, surface });
ensure(e.first == surface->base_addr);
} }
return result; return result;
@ -327,10 +328,6 @@ namespace rsx
} }
// TODO: Modify deferred_clip_region::direct_copy() to take a few more things into account! // TODO: Modify deferred_clip_region::direct_copy() to take a few more things into account!
const areau child_region = new_surface->get_normalized_memory_area();
const auto child_w = child_region.width();
const auto child_h = child_region.height();
const auto pitch = new_surface->get_rsx_pitch(); const auto pitch = new_surface->get_rsx_pitch();
for (const auto &e: surface_info) for (const auto &e: surface_info)
{ {
@ -367,41 +364,8 @@ namespace rsx
ensure(this_address); ensure(this_address);
} }
const auto parent_region = surface->get_normalized_memory_area(); if (new_surface->inherit_surface_contents(surface) == surface_inheritance_result::full &&
const auto parent_w = parent_region.width(); surface->memory_usage_flags == surface_usage_flags::storage &&
const auto parent_h = parent_region.height();
const auto rect = rsx::intersect_region(this_address, parent_w, parent_h, 1, address, child_w, child_h, 1, pitch);
const auto src_offset = std::get<0>(rect);
const auto dst_offset = std::get<1>(rect);
const auto size = std::get<2>(rect);
if (src_offset.x >= parent_w || src_offset.y >= parent_h)
{
continue;
}
if (dst_offset.x >= child_w || dst_offset.y >= child_h)
{
continue;
}
// TODO: Eventually need to stack all the overlapping regions, but for now just do the latest rect in the space
deferred_clipped_region<surface_type> region;
region.src_x = src_offset.x;
region.src_y = src_offset.y;
region.dst_x = dst_offset.x;
region.dst_y = dst_offset.y;
region.width = size.width;
region.height = size.height;
region.source = surface;
region.target = new_surface;
new_surface->set_old_contents_region(region, true);
if (surface->memory_usage_flags == surface_usage_flags::storage &&
region.width == parent_w &&
region.height == parent_h &&
surface != prev_surface && surface != prev_surface &&
surface == e.second) surface == e.second)
{ {
@ -409,8 +373,6 @@ namespace rsx
auto &storage = surface->is_depth_surface() ? m_depth_stencil_storage : m_render_targets_storage; auto &storage = surface->is_depth_surface() ? m_depth_stencil_storage : m_render_targets_storage;
auto &object = storage[e.first]; auto &object = storage[e.first];
ensure(!src_offset.x);
ensure(!src_offset.y);
ensure(object); ensure(object);
if (!surface->old_contents.empty()) [[unlikely]] if (!surface->old_contents.empty()) [[unlikely]]
{ {

View File

@ -19,12 +19,19 @@ namespace rsx
require_unresolve = 4 require_unresolve = 4
}; };
enum surface_sample_layout : u32 enum class surface_sample_layout : u32
{ {
null = 0, null = 0,
ps3 = 1 ps3 = 1
}; };
enum class surface_inheritance_result : u32
{
none = 0,
partial,
full
};
template <typename surface_type> template <typename surface_type>
struct surface_overlap_info_t struct surface_overlap_info_t
{ {
@ -504,6 +511,47 @@ namespace rsx
} }
} }
template <typename T>
surface_inheritance_result inherit_surface_contents(T* surface)
{
const auto child_w = get_surface_width(rsx::surface_metrics::bytes);
const auto child_h = get_surface_height(rsx::surface_metrics::bytes);
const auto parent_w = surface->get_surface_width(rsx::surface_metrics::bytes);
const auto parent_h = surface->get_surface_height(rsx::surface_metrics::bytes);
const auto rect = rsx::intersect_region(surface->base_addr, parent_w, parent_h, 1, base_addr, child_w, child_h, 1, get_rsx_pitch());
const auto src_offset = std::get<0>(rect);
const auto dst_offset = std::get<1>(rect);
const auto size = std::get<2>(rect);
if (src_offset.x >= parent_w || src_offset.y >= parent_h)
{
return surface_inheritance_result::none;
}
if (dst_offset.x >= child_w || dst_offset.y >= child_h)
{
return surface_inheritance_result::none;
}
// TODO: Eventually need to stack all the overlapping regions, but for now just do the latest rect in the space
deferred_clipped_region<T*> region;
region.src_x = src_offset.x;
region.src_y = src_offset.y;
region.dst_x = dst_offset.x;
region.dst_y = dst_offset.y;
region.width = size.width;
region.height = size.height;
region.source = surface;
region.target = static_cast<T*>(this);
set_old_contents_region(region, true);
return (region.width == parent_w && region.height == parent_h) ?
surface_inheritance_result::full :
surface_inheritance_result::partial;
}
void on_write(u64 write_tag = 0, void on_write(u64 write_tag = 0,
rsx::surface_state_flags resolve_flags = surface_state_flags::require_resolve, rsx::surface_state_flags resolve_flags = surface_state_flags::require_resolve,
surface_raster_type type = rsx::surface_raster_type::undefined) surface_raster_type type = rsx::surface_raster_type::undefined)