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:
parent
08e674aa28
commit
4a19a2dd24
@ -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 }
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}};
|
||||
|
Loading…
Reference in New Issue
Block a user