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

rsx: Fix texture lookups and avoid out-of-bounds copies/transfers

This commit is contained in:
kd-11 2019-03-16 14:31:39 +03:00 committed by kd-11
parent bb65e45614
commit 3ef16bee47
2 changed files with 35 additions and 5 deletions

View File

@ -100,6 +100,11 @@ u8 get_format_block_size_in_bytes(int format);
u8 get_format_block_size_in_texel(int format); u8 get_format_block_size_in_texel(int format);
u8 get_format_block_size_in_bytes(rsx::surface_color_format format); u8 get_format_block_size_in_bytes(rsx::surface_color_format format);
/**
* Returns number of texel rows encoded in one pitch-length line of bytes
*/
u8 get_format_texel_rows_per_line(u32 format);
/** /**
* Get number of bytes occupied by texture in RSX mem * Get number of bytes occupied by texture in RSX mem
*/ */

View File

@ -1734,6 +1734,19 @@ namespace rsx
const auto clipped = rsx::intersect_region(address, slice_w, slice_h, bpp, const auto clipped = rsx::intersect_region(address, slice_w, slice_h, bpp,
section->get_section_base(), section->get_width(), section->get_height(), section_bpp, pitch); section->get_section_base(), section->get_width(), section->get_height(), section_bpp, pitch);
const auto slice_begin = (slice * src_slice_h);
const auto slice_end = (slice_begin + slice_h);
const auto dst_y = std::get<1>(clipped).y;
const auto dst_h = std::get<2>(clipped).height;
const auto section_end = dst_y + dst_h;
if (dst_y >= slice_end || section_end <= slice_begin)
{
// Belongs to a different slice
return;
}
if (scaling) if (scaling)
{ {
// Since output is upscaled, also upscale on dst // Since output is upscaled, also upscale on dst
@ -2064,13 +2077,25 @@ namespace rsx
} }
} }
// Check shader_read storage. In a given scene, reads from local memory far outnumber reads from the surface cache
const u32 lookup_mask = (is_compressed_format) ? rsx::texture_upload_context::shader_read :
rsx::texture_upload_context::shader_read | rsx::texture_upload_context::blit_engine_dst | rsx::texture_upload_context::blit_engine_src;
auto lookup_range = tex_range;
if (LIKELY(extended_dimension <= rsx::texture_dimension_extended::texture_dimension_2d))
{
// Optimize the range a bit by only searching for mip0, layer0 to avoid false positives
const auto texel_rows_per_line = get_format_texel_rows_per_line(format);
const auto num_rows = (tex_height + texel_rows_per_line - 1) / texel_rows_per_line;
if (const auto length = num_rows * tex_pitch; length < tex_range.length())
{
lookup_range = utils::address_range::start_length(texaddr, length);
}
}
reader_lock lock(m_cache_mutex); reader_lock lock(m_cache_mutex);
// Check shader_read storage. In a given scene, reads from local memory far outnumber reads from the surface cache const auto overlapping_locals = find_texture_from_range<true>(lookup_range, tex_height > 1? tex_pitch : 0, lookup_mask);
const u32 lookup_mask = (is_compressed_format)? rsx::texture_upload_context::shader_read :
rsx::texture_upload_context::shader_read | rsx::texture_upload_context::blit_engine_dst | rsx::texture_upload_context::blit_engine_src;
const auto overlapping_locals = find_texture_from_range<true>(tex_range, tex_height > 1? tex_pitch : 0, lookup_mask);
for (auto& cached_texture : overlapping_locals) for (auto& cached_texture : overlapping_locals)
{ {
if (cached_texture->matches(texaddr, tex_width, tex_height, depth, 0)) if (cached_texture->matches(texaddr, tex_width, tex_height, depth, 0))