mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-15 22:21:25 +00:00
rsx: Add duplicate section detection when there are too many sections in the surface cache
- Check for useless sections. Helps in games that create a bunch of sections randomly for one-time use
This commit is contained in:
parent
b8311caa6b
commit
eba7d3b172
@ -956,6 +956,49 @@ namespace rsx
|
||||
return result;
|
||||
}
|
||||
|
||||
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 (it->base_address < range.start)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void on_write(const bool* color, bool z)
|
||||
{
|
||||
if (write_tag == cache_tag && m_skip_write_updates)
|
||||
|
@ -1783,6 +1783,26 @@ namespace rsx
|
||||
|
||||
if (result_is_valid)
|
||||
{
|
||||
// Check for possible duplicates
|
||||
usz max_safe_sections = UINT32_MAX;
|
||||
switch (result.external_subresource_desc.op)
|
||||
{
|
||||
case deferred_request_command::atlas_gather:
|
||||
max_safe_sections = 8 + attr.mipmaps; break;
|
||||
case deferred_request_command::cubemap_gather:
|
||||
max_safe_sections = 8 * attr.mipmaps; break;
|
||||
case deferred_request_command::_3d_gather:
|
||||
max_safe_sections = (attr.depth * attr.mipmaps * 110) / 100; break; // 10% factor of safety
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (overlapping_fbos.size() > max_safe_sections)
|
||||
{
|
||||
rsx_log.error("[Performance warning] Texture gather routine encountered too many objects!");
|
||||
m_rtts.check_for_duplicates(overlapping_fbos, memory_range);
|
||||
}
|
||||
|
||||
// Optionally disallow caching if resource is being written to as it is being read from
|
||||
for (const auto& section : overlapping_fbos)
|
||||
{
|
||||
@ -1855,6 +1875,7 @@ namespace rsx
|
||||
attributes.bpp = get_format_block_size_in_bytes(attributes.gcm_format);
|
||||
attributes.width = tex.width();
|
||||
attributes.height = tex.height();
|
||||
attributes.mipmaps = tex.get_exact_mipmap_count();
|
||||
attributes.swizzled = !(tex.format() & CELL_GCM_TEXTURE_LN);
|
||||
|
||||
const bool is_unnormalized = !!(tex.format() & CELL_GCM_TEXTURE_UN);
|
||||
|
Loading…
x
Reference in New Issue
Block a user