mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-10-12 02:09:17 +00:00
gl: Extend copy image API to allow explicit 3D offsets
This commit is contained in:
@@ -755,6 +755,33 @@ struct coord3_base
|
||||
{
|
||||
return{ static_cast<NT>(x), static_cast<NT>(y), static_cast<NT>(z), static_cast<NT>(width), static_cast<NT>(height), static_cast<NT>(depth) };
|
||||
}
|
||||
|
||||
void flip_horizontal()
|
||||
requires std::is_signed_v<T>
|
||||
{
|
||||
auto x2 = x + width;
|
||||
x = x2;
|
||||
width = -width;
|
||||
}
|
||||
|
||||
void flip_vertical()
|
||||
requires std::is_signed_v<T>
|
||||
{
|
||||
auto y2 = y + height;
|
||||
y = y2;
|
||||
height = -height;
|
||||
}
|
||||
|
||||
bool is_flipped() const
|
||||
requires std::is_signed_v<T>
|
||||
{
|
||||
return width < 0 || height < 0 || depth < 0;
|
||||
}
|
||||
|
||||
area_base<T> to_area() const
|
||||
{
|
||||
return { x, y, x + width, y + height };
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -113,8 +113,11 @@ namespace gl
|
||||
}
|
||||
}
|
||||
|
||||
void blitter::scale_image(gl::command_context& cmd, const texture* src, texture* dst, areai src_rect, areai dst_rect,
|
||||
bool linear_interpolation, const rsx::typeless_xfer& xfer_info, const rsx::image_copy_subresource_layers& mip_layers)
|
||||
void blitter::scale_image(gl::command_context& cmd,
|
||||
const texture* src, texture* dst,
|
||||
const coord3i& src_rect, const coord3i& dst_rect,
|
||||
bool linear_interpolation, const rsx::typeless_xfer& xfer_info,
|
||||
const rsx::image_copy_subresource_layers& mip_layers)
|
||||
{
|
||||
std::unique_ptr<texture> typeless_src;
|
||||
std::unique_ptr<texture> typeless_dst;
|
||||
@@ -129,10 +132,12 @@ namespace gl
|
||||
ensure(!targets_subresource || (!xfer_info.src_is_typeless && !xfer_info.dst_is_typeless));
|
||||
|
||||
// Optimization pass; check for pass-through data transfer
|
||||
if (!xfer_info.flip_horizontal && !xfer_info.flip_vertical && src_rect.height() == dst_rect.height())
|
||||
if (!xfer_info.flip_horizontal && !xfer_info.flip_vertical &&
|
||||
!src_rect.is_flipped() && !dst_rect.is_flipped() &&
|
||||
src_rect.height == dst_rect.height && src_rect.depth == dst_rect.depth)
|
||||
{
|
||||
auto src_w = src_rect.width();
|
||||
auto dst_w = dst_rect.width();
|
||||
auto src_w = src_rect.width;
|
||||
auto dst_w = dst_rect.width;
|
||||
|
||||
if (xfer_info.src_is_typeless) src_w = static_cast<int>(src_w * xfer_info.src_scaling_hint);
|
||||
if (xfer_info.dst_is_typeless) dst_w = static_cast<int>(dst_w * xfer_info.dst_scaling_hint);
|
||||
@@ -142,19 +147,20 @@ namespace gl
|
||||
// Final dimensions are a match
|
||||
if (xfer_info.src_is_typeless || xfer_info.dst_is_typeless)
|
||||
{
|
||||
const coord3i src_region = { { src_rect.x1, src_rect.y1, 0 }, { src_rect.width(), src_rect.height(), 1 } };
|
||||
const coord3i dst_region = { { dst_rect.x1, dst_rect.y1, 0 }, { dst_rect.width(), dst_rect.height(), 1 } };
|
||||
gl::copy_typeless(cmd, dst, src, static_cast<coord3u>(dst_region), static_cast<coord3u>(src_region), mip_layers);
|
||||
gl::copy_typeless(cmd, dst, src, static_cast<coord3u>(dst_rect), static_cast<coord3u>(src_rect), mip_layers);
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_image(cmd, src, dst, position3i{ src_rect.x1, src_rect.y1, 0u }, position3i{ dst_rect.x1, dst_rect.y1, 0 }, size3i{ src_rect.width(), src_rect.height(), 1 }, mip_layers);
|
||||
copy_image(cmd, src, dst, src_rect.position, dst_rect.position, src_rect.size, mip_layers);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto src_rect_ = src_rect;
|
||||
auto dst_rect_ = dst_rect;
|
||||
|
||||
if (xfer_info.src_is_typeless)
|
||||
{
|
||||
const auto internal_fmt = xfer_info.src_native_format_override ?
|
||||
@@ -168,8 +174,8 @@ namespace gl
|
||||
copy_typeless(cmd, typeless_src.get(), src);
|
||||
|
||||
real_src = typeless_src.get();
|
||||
src_rect.x1 = static_cast<u16>(src_rect.x1 * xfer_info.src_scaling_hint);
|
||||
src_rect.x2 = static_cast<u16>(src_rect.x2 * xfer_info.src_scaling_hint);
|
||||
src_rect_.x = static_cast<int>(src_rect.x * xfer_info.src_scaling_hint);
|
||||
src_rect_.width = static_cast<int>(src_rect.width * xfer_info.src_scaling_hint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,8 +192,8 @@ namespace gl
|
||||
copy_typeless(cmd, typeless_dst.get(), dst);
|
||||
|
||||
real_dst = typeless_dst.get();
|
||||
dst_rect.x1 = static_cast<u16>(dst_rect.x1 * xfer_info.dst_scaling_hint);
|
||||
dst_rect.x2 = static_cast<u16>(dst_rect.x2 * xfer_info.dst_scaling_hint);
|
||||
dst_rect_.x = static_cast<int>(dst_rect_.x * xfer_info.dst_scaling_hint);
|
||||
dst_rect_.width = static_cast<int>(dst_rect_.width * xfer_info.dst_scaling_hint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,19 +201,20 @@ namespace gl
|
||||
|
||||
if (xfer_info.flip_horizontal)
|
||||
{
|
||||
src_rect.flip_horizontal();
|
||||
src_rect_.flip_horizontal();
|
||||
}
|
||||
|
||||
if (xfer_info.flip_vertical)
|
||||
{
|
||||
src_rect.flip_vertical();
|
||||
src_rect_.flip_vertical();
|
||||
}
|
||||
|
||||
if (src_rect.width() == dst_rect.width() &&
|
||||
src_rect.height() == dst_rect.height() &&
|
||||
!src_rect.is_flipped() && !dst_rect.is_flipped())
|
||||
if (src_rect_.width == dst_rect_.width &&
|
||||
src_rect_.height == dst_rect_.height &&
|
||||
src_rect_.depth == dst_rect_.depth &&
|
||||
!src_rect_.is_flipped() && !dst_rect_.is_flipped())
|
||||
{
|
||||
copy_image(cmd, real_src, real_dst, position3i{ src_rect.x1, src_rect.y1, 0 }, position3i{ dst_rect.x1, dst_rect.y1, 0 }, size3i{ src_rect.width(), src_rect.height(), 1 }, mip_layers);
|
||||
copy_image(cmd, real_src, real_dst, src_rect_.position, dst_rect_.position, src_rect_.size, mip_layers);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -245,7 +252,7 @@ namespace gl
|
||||
gl::fbo::attachment src_att{ blit_src, static_cast<fbo::attachment::type>(attachment) };
|
||||
gl::fbo::attachment dst_att{ blit_dst, static_cast<fbo::attachment::type>(attachment) };
|
||||
|
||||
auto attach_slice = [](fbo::attachment& att, const texture* tex, int level, u8 layer)
|
||||
auto attach_slice = [](fbo::attachment& att, const texture* tex, int level, int layer)
|
||||
{
|
||||
if (is_layered_target(tex)) [[ unlikely ]]
|
||||
{
|
||||
@@ -257,15 +264,22 @@ namespace gl
|
||||
att.bind(*tex, level);
|
||||
};
|
||||
|
||||
areai src_area = src_rect;
|
||||
areai dst_area = dst_rect;
|
||||
// Pick volume or layered transfer, not both.
|
||||
ensure(!mip_layers.src_layer || !src_rect_.z);
|
||||
ensure(!mip_layers.dst_layer || !dst_rect_.z);
|
||||
const int src_layer = mip_layers.src_layer + src_rect_.z;
|
||||
const int dst_layer = mip_layers.dst_layer + dst_rect_.z;
|
||||
|
||||
areai src_area = src_rect_.to_area();
|
||||
areai dst_area = dst_rect_.to_area();
|
||||
|
||||
int src_level = mip_layers.src_mip_level;
|
||||
int dst_level = mip_layers.dst_mip_level;
|
||||
|
||||
for (u32 remaining_levels = mip_layers.mipmap_count; remaining_levels > 0; --remaining_levels)
|
||||
{
|
||||
attach_slice(src_att, real_src, src_level, mip_layers.src_layer);
|
||||
attach_slice(dst_att, real_dst, dst_level, mip_layers.dst_layer);
|
||||
attach_slice(src_att, real_src, src_level, src_layer);
|
||||
attach_slice(dst_att, real_dst, dst_level, dst_layer);
|
||||
|
||||
blit_src.check();
|
||||
blit_dst.check();
|
||||
|
||||
@@ -34,6 +34,16 @@ namespace gl
|
||||
|
||||
void destroy();
|
||||
|
||||
void scale_image(
|
||||
gl::command_context& cmd,
|
||||
const texture* src,
|
||||
texture* dst,
|
||||
const coord3i& src_rect, //<- Note, negative w/h/d is allowed for flipping
|
||||
const coord3i& dst_rect, //<- Note, negative w/h/d is allowed for flipping
|
||||
bool linear_interpolation,
|
||||
const rsx::typeless_xfer& xfer_info,
|
||||
const rsx::image_copy_subresource_layers& mip_layers = {});
|
||||
|
||||
void scale_image(
|
||||
gl::command_context& cmd,
|
||||
const texture* src,
|
||||
@@ -42,7 +52,12 @@ namespace gl
|
||||
areai dst_rect,
|
||||
bool linear_interpolation,
|
||||
const rsx::typeless_xfer& xfer_info,
|
||||
const rsx::image_copy_subresource_layers& mip_layers = {});
|
||||
const rsx::image_copy_subresource_layers& mip_layers = {})
|
||||
{
|
||||
const auto src_region = coord3i{ src_rect.x1, src_rect.y1, 0, src_rect.x2 - src_rect.x1, src_rect.y2 - src_rect.y1, 1 };
|
||||
const auto dst_region = coord3i{ dst_rect.x1, dst_rect.y1, 0, dst_rect.x2 - dst_rect.x1, dst_rect.y2 - dst_rect.y1, 1 };
|
||||
scale_image(cmd, src, dst, src_region, dst_region, linear_interpolation, xfer_info, mip_layers);
|
||||
}
|
||||
|
||||
void copy_image(
|
||||
gl::command_context& cmd,
|
||||
|
||||
Reference in New Issue
Block a user