Skip to content

Commit

Permalink
rsx: Explicity describe transfer regions for both source and destinat…
Browse files Browse the repository at this point in the history
…ion blocks
  • Loading branch information
kd-11 committed Oct 4, 2019
1 parent 08e674a commit 4a19a2d
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 83 deletions.
8 changes: 7 additions & 1 deletion Utilities/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,13 @@ struct coord_base
{
}

constexpr coord_base(T x, T y, T width, T height) : x{ x }, y{ y }, width{ width }, height{ height }
constexpr coord_base(const coord_base<T>& other)
: position{ other.position }, size{ other.size }
{
}

constexpr coord_base(T x, T y, T width, T height)
: x{ x }, y{ y }, width{ width }, height{ height }
{
}

Expand Down
51 changes: 29 additions & 22 deletions rpcs3/Emu/RSX/Common/surface_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ namespace rsx

auto process_list_function = [&](std::unordered_map<u32, surface_storage_type>& data, bool is_depth)
{
for (auto &tex_info : data)
for (auto& tex_info : data)
{
const auto range = tex_info.second->get_memory_range();
if (!range.overlaps(test_range))
Expand All @@ -782,48 +782,49 @@ namespace rsx
continue;

surface_overlap_info info;
u32 width, height;
info.surface = surface;
info.base_address = range.start;
info.is_depth = is_depth;

const auto normalized_surface_width = surface->get_surface_width(rsx::surface_metrics::bytes) / required_bpp;
const auto normalized_surface_height = surface->get_surface_height(rsx::surface_metrics::samples);
const u32 normalized_surface_width = surface->get_surface_width(rsx::surface_metrics::bytes) / required_bpp;
const u32 normalized_surface_height = surface->get_surface_height(rsx::surface_metrics::samples);

if (LIKELY(range.start >= texaddr))
{
const auto offset = range.start - texaddr;
info.dst_y = (offset / required_pitch);
info.dst_x = (offset % required_pitch) / required_bpp;
info.dst_area.y = (offset / required_pitch);
info.dst_area.x = (offset % required_pitch) / required_bpp;

if (UNLIKELY(info.dst_x >= required_width || info.dst_y >= required_height))
if (UNLIKELY(info.dst_area.x >= required_width || info.dst_area.y >= required_height))
{
// Out of bounds
continue;
}

info.src_x = 0;
info.src_y = 0;
info.width = std::min<u32>(normalized_surface_width, required_width - info.dst_x);
info.height = std::min<u32>(normalized_surface_height, required_height - info.dst_y);
info.src_area.x = 0;
info.src_area.y = 0;
width = std::min<u32>(normalized_surface_width, required_width - info.dst_area.x);
height = std::min<u32>(normalized_surface_height, required_height - info.dst_area.y);
}
else
{
const auto pitch = surface->get_rsx_pitch();
const auto offset = texaddr - range.start;
info.src_y = (offset / pitch);
info.src_x = (offset % pitch) / required_bpp;
info.src_area.y = (offset / pitch);
info.src_area.x = (offset % pitch) / required_bpp;

if (UNLIKELY(info.src_x >= normalized_surface_width || info.src_y >= normalized_surface_height))
if (UNLIKELY(info.src_area.x >= normalized_surface_width || info.src_area.y >= normalized_surface_height))
{
// Region lies outside the actual texture area, but inside the 'tile'
// In this case, a small region lies to the top-left corner, partially occupying the target
continue;
}

info.dst_x = 0;
info.dst_y = 0;
info.width = std::min<u32>(required_width, normalized_surface_width - info.src_x);
info.height = std::min<u32>(required_height, normalized_surface_height - info.src_y);
info.dst_area.x = 0;
info.dst_area.y = 0;
width = std::min<u32>(required_width, normalized_surface_width - info.src_area.x);
height = std::min<u32>(required_height, normalized_surface_height - info.src_area.y);
}

// Delay this as much as possible to avoid side-effects of spamming barrier
Expand All @@ -833,13 +834,19 @@ namespace rsx
continue;
}

info.is_clipped = (info.width < required_width || info.height < required_height);
info.is_clipped = (width < required_width || height < required_height);
info.src_area.height = info.dst_area.height = height;
info.dst_area.width = width;

if (auto surface_bpp = surface->get_bpp(); UNLIKELY(surface_bpp != required_bpp))
{
// Width is calculated in the coordinate-space of the requester; normalize
info.src_x = (info.src_x * required_bpp) / surface_bpp;
info.width = align(info.width * required_bpp, surface_bpp) / surface_bpp;
info.src_area.x = (info.src_area.x * required_bpp) / surface_bpp;
info.src_area.width = align(width * required_bpp, surface_bpp) / surface_bpp;
}
else
{
info.src_area.width = width;
}

result.push_back(info);
Expand Down Expand Up @@ -872,8 +879,8 @@ namespace rsx
{
if (a.surface->last_use_tag == b.surface->last_use_tag)
{
const auto area_a = a.width * a.height;
const auto area_b = b.width * b.height;
const auto area_a = a.dst_area.width * a.dst_area.height;
const auto area_b = b.dst_area.width * b.dst_area.height;

return area_a < area_b;
}
Expand Down
18 changes: 2 additions & 16 deletions rpcs3/Emu/RSX/Common/surface_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,8 @@ namespace rsx
bool is_depth = false;
bool is_clipped = false;

u16 src_x = 0;
u16 src_y = 0;
u16 dst_x = 0;
u16 dst_y = 0;
u16 width = 0;
u16 height = 0;

areai get_src_area() const
{
return coordi{ {src_x, src_y}, {width, height} };
}

areai get_dst_area() const
{
return coordi{ {dst_x, dst_y}, {width, height} };
}
coordu src_area;
coordu dst_area;
};

template <typename surface_type>
Expand Down
69 changes: 35 additions & 34 deletions rpcs3/Emu/RSX/Common/texture_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,14 @@ namespace rsx
enum surface_transform : u32
{
identity = 0,
argb_to_bgra = 1
argb_to_bgra = 1,
coordinate_transform = 2
};

struct copy_region_descriptor
{
image_resource_type src;
surface_transform xform;
flags32_t xform;
u16 src_x;
u16 src_y;
u16 dst_x;
Expand Down Expand Up @@ -1476,7 +1477,7 @@ namespace rsx
sections[n] =
{
desc.external_handle,
surface_transform::identity,
surface_transform::coordinate_transform,
0, (u16)(desc.slice_h * n),
0, 0, n,
desc.width, desc.height,
Expand All @@ -1501,7 +1502,7 @@ namespace rsx
sections[n] =
{
desc.external_handle,
surface_transform::identity,
surface_transform::coordinate_transform,
0, (u16)(desc.slice_h * n),
0, 0, n,
desc.width, desc.height,
Expand Down Expand Up @@ -1602,22 +1603,22 @@ namespace rsx
return;
}

const auto slice_begin = (slice * src_slice_h);
const auto slice_end = (slice_begin + slice_h);
const u32 slice_begin = (slice * src_slice_h);
const u32 slice_end = (slice_begin + slice_h);

const auto section_end = section.dst_y + section.height;
if (section.dst_y >= slice_end || section_end <= slice_begin)
const u32 section_end = section.dst_area.y + section.dst_area.height;
if (section.dst_area.y >= slice_end || section_end <= slice_begin)
{
// Belongs to a different slice
return;
}

// How much of this slice to read?
int rebased = int(section.dst_y) - slice_begin;
const auto src_x = section.src_x;
const auto dst_x = section.dst_x;
auto src_y = section.src_y;
auto dst_y = section.dst_y;
int rebased = int(section.dst_area.y) - slice_begin;
const auto src_x = section.src_area.x;
const auto dst_x = section.dst_area.x;
auto src_y = section.src_area.y;
auto dst_y = section.dst_area.y;

if (rebased < 0)
{
Expand All @@ -1629,10 +1630,10 @@ namespace rsx
verify(HERE), dst_y >= slice_begin;
dst_y = (dst_y - slice_begin);

const auto h = std::min(section_end, slice_end) - section.dst_y;
const auto src_width = rsx::apply_resolution_scale(section.width, true);
const auto h = std::min(section_end, slice_end) - section.dst_area.y;
const auto src_width = rsx::apply_resolution_scale(section.src_area.width, true);
const auto src_height = rsx::apply_resolution_scale(h, true);
const auto dst_width = src_width;
const auto dst_width = rsx::apply_resolution_scale(section.dst_area.width, true);
const auto dst_height = src_height;

surfaces.push_back
Expand Down Expand Up @@ -1687,7 +1688,10 @@ namespace rsx
return;
}

const u16 internal_clip_width = u16(std::get<2>(clipped).width * bpp) / section_bpp;
const u16 dst_w = (u16)std::get<2>(clipped).width;
const u16 src_w = u16(dst_w * bpp) / section_bpp;
const u16 height = (u16)std::get<2>(clipped).height;

if (scaling)
{
// Since output is upscaled, also upscale on dst
Expand All @@ -1700,16 +1704,14 @@ namespace rsx
rsx::apply_resolution_scale((u16)std::get<1>(clipped).x, true),
rsx::apply_resolution_scale((u16)std::get<1>(clipped).y, true),
slice,
internal_clip_width,
(u16)std::get<2>(clipped).height,
rsx::apply_resolution_scale(internal_clip_width, true),
rsx::apply_resolution_scale((u16)std::get<2>(clipped).height, true),
src_w,
height,
rsx::apply_resolution_scale(dst_w, true),
rsx::apply_resolution_scale(height, true),
});
}
else
{
const auto src_width = internal_clip_width, dst_width = src_width;
const auto src_height = (u16)std::get<2>(clipped).height, dst_height = src_height;
surfaces.push_back
({
section->get_raw_texture(),
Expand All @@ -1719,10 +1721,10 @@ namespace rsx
(u16)std::get<1>(clipped).x,
(u16)std::get<1>(clipped).y,
0,
src_width,
src_height,
dst_width,
dst_height,
src_w,
height,
dst_w,
height,
});
}
};
Expand Down Expand Up @@ -2136,10 +2138,9 @@ namespace rsx
{
// Surface cache data is newer, check if this thing fits our search parameters
const auto& last = overlapping_fbos.back();
if (last.src_x == 0 && last.src_y == 0)
if (last.src_area.x == 0 && last.src_area.y == 0)
{
u16 normalized_width = u16(last.width * last.surface->get_bpp()) / bpp;
if (normalized_width >= tex_width && last.height >= required_surface_height)
if (last.dst_area.width >= tex_width && last.dst_area.height >= required_surface_height)
{
return process_framebuffer_resource_fast(cmd, last.surface, texaddr, format, tex_width, tex_height, depth, slice_h,
scale_x, scale_y, extended_dimension, tex.remap(), tex.decoded_remap(), false);
Expand Down Expand Up @@ -2405,8 +2406,8 @@ namespace rsx
return *It;
}

auto _w = u32(It->width * It->surface->get_bpp()) / bpp;
auto _h = u32(It->height);
const auto _w = It->dst_area.width;
const auto _h = It->dst_area.height;

if (_w < width)
{
Expand Down Expand Up @@ -2629,7 +2630,7 @@ namespace rsx
else
{
// Destination dimensions are relaxed (true)
dst_area = dst_subres.get_src_area();
dst_area = dst_subres.src_area;

dest_texture = dst_subres.surface->get_surface(rsx::surface_access::transfer);
typeless_info.dst_context = texture_upload_context::framebuffer_storage;
Expand Down Expand Up @@ -2812,7 +2813,7 @@ namespace rsx
}
else
{
src_area = src_subres.get_src_area();
src_area = src_subres.src_area;
vram_texture = src_subres.surface->get_surface(rsx::surface_access::read);
typeless_info.src_context = texture_upload_context::framebuffer_storage;
}
Expand Down
15 changes: 13 additions & 2 deletions rpcs3/Emu/RSX/GL/GLTextureCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ namespace gl
std::vector<copy_region_descriptor> region =
{{
src,
surface_transform::identity,
surface_transform::coordinate_transform,
x, y, 0, 0, 0,
width, height, width, height
}};
Expand Down Expand Up @@ -612,6 +612,14 @@ namespace gl
auto src_w = slice.src_w;
auto src_h = slice.src_h;

if (slice.xform == surface_transform::coordinate_transform)
{
// Dimensions were given in 'dst' space. Work out the real source coordinates
const auto src_bpp = slice.src->pitch() / slice.src->width();
src_x = (src_x * dst_bpp) / src_bpp;
src_w = (src_w * dst_bpp) / src_bpp;
}

if (auto surface = dynamic_cast<gl::render_target*>(slice.src))
{
surface->transform_samples_to_pixels(src_x, src_w, src_y, src_h);
Expand All @@ -624,8 +632,11 @@ namespace gl
tmp = std::make_unique<texture>(GL_TEXTURE_2D, convert_w, slice.src->height(), 1, 1, (GLenum)dst_image->get_internal_format());

src_image = tmp.get();
src_x = u16(src_x * src_bpp) / dst_bpp;
gl::copy_typeless(src_image, slice.src);

// Compute src region in dst format layout
src_x = u16(src_x * src_bpp) / dst_bpp;
src_w = u16(src_w * src_bpp) / dst_bpp;
}

if (src_w == slice.dst_w && src_h == slice.dst_h)
Expand Down

0 comments on commit 4a19a2d

Please sign in to comment.