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

rsx: Explicity describe transfer regions for both source and destination blocks

This commit is contained in:
kd-11 2019-10-02 19:27:48 +03:00 committed by kd-11
parent 08e674aa28
commit 4a19a2dd24
6 changed files with 110 additions and 83 deletions

View File

@ -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 }
{
}

View File

@ -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))
@ -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
@ -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);
@ -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;
}

View File

@ -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>

View File

@ -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;
@ -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,
@ -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,
@ -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)
{
@ -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
@ -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
@ -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(),
@ -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,
});
}
};
@ -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);
@ -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)
{
@ -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;
@ -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;
}

View File

@ -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
}};
@ -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);
@ -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)

View File

@ -579,6 +579,17 @@ namespace vk
auto src_w = section.src_w;
auto src_h = section.src_h;
rsx::flags32_t transform = section.xform;
if (section.xform == surface_transform::coordinate_transform)
{
// Dimensions were given in 'dst' space. Work out the real source coordinates
const auto src_bpp = vk::get_format_texel_width(section.src->format());
src_x = (src_x * dst_bpp) / src_bpp;
src_w = (src_w * dst_bpp) / src_bpp;
transform &= ~(surface_transform::coordinate_transform);
}
if (auto surface = dynamic_cast<vk::render_target*>(section.src))
{
surface->transform_samples_to_pixels(src_x, src_w, src_y, src_h);
@ -586,15 +597,20 @@ namespace vk
if (UNLIKELY(typeless))
{
src_image = vk::get_typeless_helper(dst->info.format, src_x + src_w, src_y + src_h);
const auto src_bpp = vk::get_format_texel_width(section.src->format());
const u16 convert_w = u16(src_w * src_bpp) / dst_bpp;
const u16 convert_x = u16(src_x * src_bpp) / dst_bpp;
src_image = vk::get_typeless_helper(dst->info.format, convert_x + convert_w, src_y + src_h);
src_image->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
const auto src_bpp = vk::get_format_texel_width(section.src->format());
const u16 convert_w = u16(src_w * dst_bpp) / src_bpp;
const areai src_rect = coordi{{ src_x, src_y }, { convert_w, src_h }};
const areai dst_rect = coordi{{ src_x, src_y }, { src_w, src_h }};
const areai src_rect = coordi{{ src_x, src_y }, { src_w, src_h }};
const areai dst_rect = coordi{{ convert_x, src_y }, { convert_w, src_h }};
vk::copy_image_typeless(cmd, section.src, src_image, src_rect, dst_rect, 1, section.src->aspect(), dst_aspect);
src_image->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
src_x = convert_x;
src_w = convert_w;
}
verify(HERE), src_image->current_layout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
@ -641,7 +657,7 @@ namespace vk
_dst->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
}
if (section.xform == surface_transform::identity)
if (transform == surface_transform::identity)
{
vk::copy_scaled_image(cmd, src_image->value, _dst->value, section.src->current_layout, _dst->current_layout,
coordi{ { src_x, src_y }, { src_w, src_h } },
@ -649,7 +665,7 @@ namespace vk
1, src_image->aspect(), src_image->info.format == _dst->info.format,
VK_FILTER_NEAREST, src_image->info.format, _dst->info.format);
}
else if (section.xform == surface_transform::argb_to_bgra)
else if (transform == surface_transform::argb_to_bgra)
{
VkBufferImageCopy copy{};
copy.imageExtent = { src_w, src_h, 1 };
@ -838,7 +854,7 @@ namespace vk
std::vector<copy_region_descriptor> region =
{{
source,
surface_transform::identity,
surface_transform::coordinate_transform,
x, y, 0, 0, 0,
w, h, w, h
}};