mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-06 18:40:36 +00:00
rsx: Blit engine tuning
- Attempt to identify blit operations that will be flushed immediately after and just do them on CPU instead if the transformation is trivial. - If only a single blit section is contributing to an atlas merge op, the threshold should be 100%. The only acceptable result here is a truncation.
This commit is contained in:
parent
7a275eaa3a
commit
44f2cacf7b
@ -213,7 +213,8 @@ namespace rsx
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool atlas_covers_target_area() const
|
// Returns true if at least threshold% is covered in pixels
|
||||||
|
bool atlas_covers_target_area(u32 threshold) const
|
||||||
{
|
{
|
||||||
if (external_subresource_desc.op != deferred_request_command::atlas_gather)
|
if (external_subresource_desc.op != deferred_request_command::atlas_gather)
|
||||||
return true;
|
return true;
|
||||||
@ -222,7 +223,7 @@ namespace rsx
|
|||||||
max_x = 0, max_y = 0;
|
max_x = 0, max_y = 0;
|
||||||
|
|
||||||
// Require at least 90% coverage
|
// Require at least 90% coverage
|
||||||
const u32 target_area = ((min_x * min_y) * 90u) / 100u;
|
const u32 target_area = ((min_x * min_y) * threshold) / 100u;
|
||||||
|
|
||||||
for (const auto §ion : external_subresource_desc.sections_to_copy)
|
for (const auto §ion : external_subresource_desc.sections_to_copy)
|
||||||
{
|
{
|
||||||
@ -1654,8 +1655,8 @@ namespace rsx
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.external_subresource_desc.sections_to_copy.empty() &&
|
if (const auto section_count = result.external_subresource_desc.sections_to_copy.size();
|
||||||
(_pool == 0 || result.atlas_covers_target_area()))
|
section_count > 0 && result.atlas_covers_target_area(section_count == 1? 99 : 90))
|
||||||
{
|
{
|
||||||
// TODO: Overlapped section persistance is required for framebuffer resources to work with this!
|
// TODO: Overlapped section persistance is required for framebuffer resources to work with this!
|
||||||
// Yellow filter in SCV is because of a 384x384 surface being reused as 160x90 (and likely not getting written to)
|
// Yellow filter in SCV is because of a 384x384 surface being reused as 160x90 (and likely not getting written to)
|
||||||
@ -1921,6 +1922,7 @@ namespace rsx
|
|||||||
|
|
||||||
const bool is_copy_op = (fcmp(scale_x, 1.f) && fcmp(scale_y, 1.f));
|
const bool is_copy_op = (fcmp(scale_x, 1.f) && fcmp(scale_y, 1.f));
|
||||||
const bool is_format_convert = (dst_is_argb8 != src_is_argb8);
|
const bool is_format_convert = (dst_is_argb8 != src_is_argb8);
|
||||||
|
bool skip_if_collision_exists = false;
|
||||||
|
|
||||||
// Offset in x and y for src is 0 (it is already accounted for when getting pixels_src)
|
// Offset in x and y for src is 0 (it is already accounted for when getting pixels_src)
|
||||||
// Reproject final clip onto source...
|
// Reproject final clip onto source...
|
||||||
@ -2075,6 +2077,9 @@ namespace rsx
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a matching section exists with a different use-case, fall back to CPU memcpy
|
||||||
|
skip_if_collision_exists = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_cfg.video.use_gpu_texture_scaling)
|
if (!g_cfg.video.use_gpu_texture_scaling)
|
||||||
@ -2176,9 +2181,20 @@ namespace rsx
|
|||||||
if (!dst_is_render_target)
|
if (!dst_is_render_target)
|
||||||
{
|
{
|
||||||
// Check for any available region that will fit this one
|
// Check for any available region that will fit this one
|
||||||
const auto required_type = (use_null_region) ? texture_upload_context::dma : texture_upload_context::blit_engine_dst;
|
u32 required_type_mask;
|
||||||
|
if (use_null_region)
|
||||||
|
{
|
||||||
|
required_type_mask = texture_upload_context::dma;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
required_type_mask = texture_upload_context::blit_engine_dst;
|
||||||
|
if (skip_if_collision_exists) required_type_mask |= texture_upload_context::shader_read;
|
||||||
|
}
|
||||||
|
|
||||||
const auto dst_range = address_range::start_length(dst_address, dst_payload_length);
|
const auto dst_range = address_range::start_length(dst_address, dst_payload_length);
|
||||||
auto overlapping_surfaces = find_texture_from_range(dst_range, dst.pitch, required_type);
|
auto overlapping_surfaces = find_texture_from_range(dst_range, dst.pitch, required_type_mask);
|
||||||
|
|
||||||
for (const auto &surface : overlapping_surfaces)
|
for (const auto &surface : overlapping_surfaces)
|
||||||
{
|
{
|
||||||
if (!surface->is_locked())
|
if (!surface->is_locked())
|
||||||
@ -2194,23 +2210,30 @@ namespace rsx
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!dst_range.inside(surface->get_section_range()))
|
||||||
|
{
|
||||||
|
// Hit test failed
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (use_null_region)
|
if (use_null_region)
|
||||||
{
|
{
|
||||||
if (dst_range.inside(surface->get_section_range()))
|
|
||||||
{
|
|
||||||
// Attach to existing region
|
// Attach to existing region
|
||||||
cached_dest = surface;
|
cached_dest = surface;
|
||||||
}
|
|
||||||
|
|
||||||
// Technically it is totally possible to just extend a pre-existing section
|
// Technically it is totally possible to just extend a pre-existing section
|
||||||
// Will leave this as a TODO
|
// Will leave this as a TODO
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto this_address = surface->get_section_base();
|
if (UNLIKELY(skip_if_collision_exists))
|
||||||
if (this_address > dst_address)
|
|
||||||
{
|
{
|
||||||
continue;
|
if (surface->get_context() != texture_upload_context::blit_engine_dst)
|
||||||
|
{
|
||||||
|
// This section is likely to be 'flushed' to CPU for reupload soon anyway
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (surface->get_gcm_format())
|
switch (surface->get_gcm_format())
|
||||||
@ -2227,7 +2250,8 @@ namespace rsx
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const u32 address_offset = dst_address - this_address)
|
if (const auto this_address = surface->get_section_base();
|
||||||
|
const u32 address_offset = dst_address - this_address)
|
||||||
{
|
{
|
||||||
const u16 offset_y = address_offset / dst.pitch;
|
const u16 offset_y = address_offset / dst.pitch;
|
||||||
const u16 offset_x = address_offset % dst.pitch;
|
const u16 offset_x = address_offset % dst.pitch;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user