gl: Extend copy image API to allow explicit 3D offsets

This commit is contained in:
kd-11
2026-08-18 13:47:28 +03:00
committed by kd-11
parent e7c3d6ab26
commit 91cd82a0c2
3 changed files with 81 additions and 25 deletions
+27
View File
@@ -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 };
}
};
+38 -24
View File
@@ -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();
+16 -1
View File
@@ -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,