1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 20:22:30 +01:00

rsx: Implement image copy between 2D -> 3C/CUBE with scaling support.

This commit is contained in:
kd-11 2023-08-07 23:30:12 +03:00 committed by kd-11
parent bd7715b180
commit 767979ea44
2 changed files with 52 additions and 45 deletions

View File

@ -258,14 +258,12 @@ namespace gl
}
else
{
ensure(dst_image->get_target() == gl::texture::target::texture2D);
auto _blitter = gl::g_hw_blitter;
const areai src_rect = { src_x, src_y, src_x + src_w, src_y + src_h };
const areai dst_rect = { slice.dst_x, slice.dst_y, slice.dst_x + slice.dst_w, slice.dst_y + slice.dst_h };
gl::texture* _dst;
if (src_image->get_internal_format() == dst_image->get_internal_format() && slice.level == 0)
if (src_image->get_internal_format() == dst_image->get_internal_format() && slice.level == 0 && slice.dst_z == 0)
{
_dst = dst_image;
}

View File

@ -276,7 +276,32 @@ namespace vk
for (const auto& section : sections_to_transfer)
{
if (!section.src)
{
continue;
}
// Generates a region to write data to the final destination
const auto get_output_region = [&](s32 in_x, s32 in_y, u32 w, u32 h, vk::image* data_src)
{
VkImageCopy copy_rgn = {
.srcSubresource = { data_src->aspect(), 0, 0, 1},
.srcOffset = { in_x, in_y, 0 },
.dstSubresource = { dst_aspect, section.level, 0, 1 },
.dstOffset = { section.dst_x, section.dst_y, 0 },
.extent = { w, h, 1 }
};
if (dst->info.imageType == VK_IMAGE_TYPE_3D)
{
copy_rgn.dstOffset.z = section.dst_z;
}
else
{
copy_rgn.dstSubresource.baseArrayLayer = section.dst_z;
}
return copy_rgn;
};
const bool typeless = section.src->aspect() != dst_aspect ||
!formats_are_bitcast_compatible(dst, section.src);
@ -333,11 +358,12 @@ namespace vk
src_image->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
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 }};
const areai dst_rect = coordi{{ 0, 0 }, { convert_w, src_h }};
vk::copy_image_typeless(cmd, section.src, src_image, src_rect, dst_rect, 1);
src_image->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
src_x = convert_x;
src_x = 0;
src_y = 0;
src_w = convert_w;
}
@ -345,51 +371,47 @@ namespace vk
// Final aspect mask of the 'final' transfer source
const auto new_src_aspect = src_image->aspect();
const bool require_scaling = src_w != section.dst_w || src_h != section.dst_h;
if (src_w == section.dst_w && src_h == section.dst_h && transform == rsx::surface_transform::identity) [[likely]]
if (!require_scaling && transform == rsx::surface_transform::identity) [[likely]]
{
VkImageCopy copy_rgn;
copy_rgn.srcOffset = { src_x, src_y, 0 };
copy_rgn.dstOffset = { section.dst_x, section.dst_y, 0 };
copy_rgn.dstSubresource = { dst_aspect, 0, 0, 1 };
copy_rgn.srcSubresource = { new_src_aspect, 0, 0, 1 };
copy_rgn.extent = { src_w, src_h, 1 };
if (dst->info.imageType == VK_IMAGE_TYPE_3D)
{
copy_rgn.dstOffset.z = section.dst_z;
}
else
{
copy_rgn.dstSubresource.baseArrayLayer = section.dst_z;
copy_rgn.dstSubresource.mipLevel = section.level;
}
const auto copy_rgn = get_output_region(src_x, src_y, src_w, src_h, src_image);
vkCmdCopyImage(cmd, src_image->value, src_image->current_layout, dst->value, dst->current_layout, 1, &copy_rgn);
}
else
{
ensure(section.dst_z == 0);
u16 dst_x = section.dst_x, dst_y = section.dst_y;
vk::image* _dst;
if (src_image->info.format == dst->info.format && section.level == 0) [[likely]]
// Check for best-case scenario - we write directly to the output in this case
if (src_image->info.format == dst->info.format &&
section.level == 0 &&
section.dst_z == 0) [[likely]]
{
_dst = dst;
}
else
{
// Either a bitcast is required or a scale+copy to mipmap level
_dst = vk::get_typeless_helper(src_image->format(), src_image->format_class(), dst->width(), dst->height() * 2);
const u32 requested_width = dst->width();
const u32 requested_height = src_y + src_h + section.dst_h;
_dst = vk::get_typeless_helper(src_image->format(), src_image->format_class(), requested_width, requested_height);
_dst->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
}
if (_dst == src_image)
{
// Write-to-self situation. Account for the initial typeless copy.
ensure(dst != _dst);
dst_x = 0;
dst_y = src_y + src_h;
}
if (transform == rsx::surface_transform::identity)
{
vk::copy_scaled_image(cmd, src_image, _dst,
coordi{ { src_x, src_y }, { src_w, src_h } },
coordi{ { section.dst_x, section.dst_y }, { section.dst_w, section.dst_h } },
coordi{ { dst_x, dst_y }, { section.dst_w, section.dst_h } },
1, src_image->format() == _dst->format(),
VK_FILTER_NEAREST);
}
@ -413,23 +435,16 @@ namespace vk
vk::insert_buffer_memory_barrier(cmd, scratch_buf->value, 0, mem_length, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
auto tmp = vk::get_typeless_helper(src_image->format(), src_image->format_class(), section.dst_x + section.dst_w, section.dst_y + section.dst_h);
auto tmp = vk::get_typeless_helper(src_image->format(), src_image->format_class(), section.dst_w, section.dst_h);
tmp->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
dst_x = dst_y = 0;
copy.imageOffset = { 0, 0, 0 };
vkCmdCopyBufferToImage(cmd, scratch_buf->value, tmp->value, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy);
dst_x = 0;
dst_y = 0;
if (src_w != section.dst_w || src_h != section.dst_h)
if (require_scaling)
{
// Optionally scale if needed
if (tmp == _dst) [[unlikely]]
{
dst_y = src_h;
}
vk::copy_scaled_image(cmd, tmp, _dst,
areai{ 0, 0, src_w, static_cast<s32>(src_h) },
coordi{ { dst_x, dst_y }, { section.dst_w, section.dst_h } },
@ -449,13 +464,7 @@ namespace vk
if (_dst != dst) [[unlikely]]
{
// Casting comes after the scaling!
VkImageCopy copy_rgn;
copy_rgn.srcOffset = { s32(dst_x), s32(dst_y), 0 };
copy_rgn.dstOffset = { section.dst_x, section.dst_y, 0 };
copy_rgn.dstSubresource = { dst_aspect, section.level, 0, 1 };
copy_rgn.srcSubresource = { _dst->aspect(), 0, 0, 1 };
copy_rgn.extent = { section.dst_w, section.dst_h, 1 };
const auto copy_rgn = get_output_region(dst_x, dst_y, section.dst_w, section.dst_h, _dst);
_dst->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
vkCmdCopyImage(cmd, _dst->value, _dst->current_layout, dst->value, dst->current_layout, 1, &copy_rgn);
}