1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

rsx: Add optimized version of section removal code

This commit is contained in:
kd-11 2022-01-05 01:27:49 +03:00 committed by kd-11
parent 9766d87126
commit 6889b48973

View File

@ -592,6 +592,115 @@ namespace rsx
invalidated_resources.push_back(std::move(storage));
}
int remove_duplicates_fast_impl(std::vector<surface_overlap_info>& sections, const rsx::address_range& range)
{
// Range tests to check for gaps
std::list<utils::address_range> m_ranges;
bool invalidate_sections = false;
int removed_count = 0;
for (auto it = sections.crbegin(); it != sections.crend(); ++it)
{
auto this_range = it->surface->get_memory_range();
if (invalidate_sections)
{
if (this_range.inside(range))
{
invalidate_surface_address(it->base_address, it->is_depth);
removed_count++;
}
continue;
}
if (it->surface->get_rsx_pitch() != it->surface->get_native_pitch() &&
it->surface->get_surface_height() != 1)
{
// Memory gap in descriptor
continue;
}
// Insert the range, respecting sort order
bool inserted = false;
for (auto iter = m_ranges.begin(); iter != m_ranges.end(); ++iter)
{
if (this_range.start < iter->start)
{
// This range slots in here. Test ranges after this one to find the end position
auto pos = iter;
for (auto _p = ++iter; _p != m_ranges.end();)
{
if (_p->start > (this_range.end + 1))
{
// Gap
break;
}
// Consume
this_range.end = std::max(this_range.end, _p->end);
_p = m_ranges.erase(_p);
}
m_ranges.insert(pos, this_range);
break;
}
}
if (!inserted)
{
m_ranges.push_back(this_range);
}
else if (m_ranges.size() == 1 && range.inside(m_ranges.front()))
{
invalidate_sections = true;
}
}
return removed_count;
}
void remove_duplicates_fallback_impl(std::vector<surface_overlap_info>& sections, const rsx::address_range& range)
{
// Generic painter's algorithm to detect obsolete sections
ensure(range.length() < 64 * 0x100000);
std::vector<u8> marker(range.length());
std::memset(marker.data(), 0, range.length());
for (auto it = sections.crbegin(); it != sections.crend(); ++it)
{
if (!it->surface->get_memory_range().inside(range))
{
continue;
}
const auto true_pitch_in_bytes = it->surface->get_surface_width(rsx::surface_metrics::bytes);
const auto true_height_in_rows = it->surface->get_surface_height(rsx::surface_metrics::samples);
bool valid = false;
auto addr = it->base_address - range.start;
auto data = marker.data();
for (usz row = 0; row < true_height_in_rows; ++row)
{
for (usz col = 0; col < true_pitch_in_bytes; ++col)
{
if (const auto loc = col + addr; !data[loc])
{
valid = true;
data[loc] = 1;
}
}
addr += true_pitch_in_bytes;
}
if (!valid)
{
rsx_log.error("Stale surface at address 0x%x will be deleted", it->base_address);
invalidate_surface_address(it->base_address, it->is_depth);
}
}
}
protected:
/**
* If render target already exists at address, issue state change operation on cmdList.
@ -923,44 +1032,9 @@ namespace rsx
void check_for_duplicates(std::vector<surface_overlap_info>& sections, const rsx::address_range& range)
{
// Generic painter's algorithm to detect obsolete sections
ensure(range.length() < 64 * 0x100000);
std::vector<u8> marker(range.length());
std::memset(marker.data(), 0, range.length());
for (auto it = sections.crbegin(); it != sections.crend(); ++it)
if (!remove_duplicates_fast_impl(sections, range))
{
if (!it->surface->get_memory_range().inside(range))
{
continue;
}
const auto true_pitch_in_bytes = it->surface->get_surface_width(rsx::surface_metrics::bytes);
const auto true_height_in_rows = it->surface->get_surface_height(rsx::surface_metrics::samples);
bool valid = false;
auto addr = it->base_address - range.start;
auto data = marker.data();
for (usz row = 0; row < true_height_in_rows; ++row)
{
for (usz col = 0; col < true_pitch_in_bytes; ++col)
{
if (const auto loc = col + addr; !data[loc])
{
valid = true;
data[loc] = 1;
}
}
addr += true_pitch_in_bytes;
}
if (!valid)
{
rsx_log.error("Stale surface at address 0x%x will be deleted", it->base_address);
invalidate_surface_address(it->base_address, it->is_depth);
}
remove_duplicates_fallback_impl(sections, range);
}
}