mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-03 14:14:59 -06:00
Image copy Enhancement (#4041)
Some checks failed
Build and Release / reuse (push) Has been cancelled
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-sdl-gcc (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled
Some checks failed
Build and Release / reuse (push) Has been cancelled
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-sdl-gcc (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled
* copy image handle 2d->3d copies and opossite now * make gcc happy * fixed colouring issue
This commit is contained in:
parent
3a99051df9
commit
a99c814739
@ -462,50 +462,132 @@ static std::pair<u32, u32> SanitizeCopyLayers(const ImageInfo& src_info, const I
|
|||||||
void Image::CopyImage(Image& src_image) {
|
void Image::CopyImage(Image& src_image) {
|
||||||
const auto& src_info = src_image.info;
|
const auto& src_info = src_image.info;
|
||||||
const u32 num_mips = std::min(src_info.resources.levels, info.resources.levels);
|
const u32 num_mips = std::min(src_info.resources.levels, info.resources.levels);
|
||||||
ASSERT(src_info.resources.layers == info.resources.layers || num_mips == 1);
|
|
||||||
|
// Check format compatibility
|
||||||
|
if (src_info.pixel_format != info.pixel_format) {
|
||||||
|
LOG_WARNING(Render_Vulkan,
|
||||||
|
"Copy between different formats: src={}, dst={}. Color may be incorrect.",
|
||||||
|
vk::to_string(src_info.pixel_format), vk::to_string(info.pixel_format));
|
||||||
|
}
|
||||||
|
|
||||||
const u32 width = src_info.size.width;
|
const u32 width = src_info.size.width;
|
||||||
const u32 height = src_info.size.height;
|
const u32 height = src_info.size.height;
|
||||||
const u32 depth =
|
const u32 base_depth =
|
||||||
info.type == AmdGpu::ImageType::Color3D ? info.size.depth : src_info.size.depth;
|
info.type == AmdGpu::ImageType::Color3D ? info.size.depth : src_info.size.depth;
|
||||||
|
|
||||||
|
auto [test_src_layers, test_dst_layers] = SanitizeCopyLayers(src_info, info, base_depth);
|
||||||
|
|
||||||
|
ASSERT(test_src_layers == test_dst_layers || num_mips == 1 ||
|
||||||
|
(ConvertImageType(src_info.type) != ConvertImageType(info.type) &&
|
||||||
|
(test_src_layers == 1 || test_dst_layers == 1)));
|
||||||
|
|
||||||
SetBackingSamples(info.num_samples, false);
|
SetBackingSamples(info.num_samples, false);
|
||||||
src_image.SetBackingSamples(src_info.num_samples);
|
src_image.SetBackingSamples(src_info.num_samples);
|
||||||
|
|
||||||
boost::container::small_vector<vk::ImageCopy, 8> image_copies;
|
boost::container::small_vector<vk::ImageCopy, 8> image_copies;
|
||||||
|
|
||||||
|
const bool src_is_2d = ConvertImageType(src_info.type) == vk::ImageType::e2D;
|
||||||
|
const bool src_is_3d = ConvertImageType(src_info.type) == vk::ImageType::e3D;
|
||||||
|
const bool dst_is_2d = ConvertImageType(info.type) == vk::ImageType::e2D;
|
||||||
|
const bool dst_is_3d = ConvertImageType(info.type) == vk::ImageType::e3D;
|
||||||
|
|
||||||
|
const bool is_2d_to_3d = src_is_2d && dst_is_3d;
|
||||||
|
const bool is_3d_to_2d = src_is_3d && dst_is_2d;
|
||||||
|
const bool is_same_type = !is_2d_to_3d && !is_3d_to_2d;
|
||||||
|
|
||||||
|
// Use full aspect mask for color images
|
||||||
|
vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor;
|
||||||
|
|
||||||
|
// If images have depth/stencil, we might need to handle separately
|
||||||
|
if (src_image.aspect_mask & vk::ImageAspectFlagBits::eDepth) {
|
||||||
|
aspect = vk::ImageAspectFlagBits::eDepth;
|
||||||
|
} else if (src_image.aspect_mask & vk::ImageAspectFlagBits::eStencil) {
|
||||||
|
aspect = vk::ImageAspectFlagBits::eStencil;
|
||||||
|
}
|
||||||
|
|
||||||
for (u32 mip = 0; mip < num_mips; ++mip) {
|
for (u32 mip = 0; mip < num_mips; ++mip) {
|
||||||
const auto mip_w = std::max(width >> mip, 1u);
|
const auto mip_w = std::max(width >> mip, 1u);
|
||||||
const auto mip_h = std::max(height >> mip, 1u);
|
const auto mip_h = std::max(height >> mip, 1u);
|
||||||
const auto mip_d = std::max(depth >> mip, 1u);
|
const auto mip_d = std::max(base_depth >> mip, 1u);
|
||||||
const auto [src_layers, dst_layers] = SanitizeCopyLayers(src_info, info, mip_d);
|
|
||||||
|
|
||||||
image_copies.emplace_back(vk::ImageCopy{
|
auto [src_layers, dst_layers] = SanitizeCopyLayers(src_info, info, mip_d);
|
||||||
.srcSubresource{
|
|
||||||
.aspectMask = src_image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil,
|
if (is_same_type) {
|
||||||
.mipLevel = mip,
|
u32 copy_layers = std::min(src_layers, dst_layers);
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = src_layers,
|
if (src_is_3d)
|
||||||
},
|
src_layers = 1;
|
||||||
.dstSubresource{
|
if (dst_is_3d)
|
||||||
.aspectMask = aspect_mask & ~vk::ImageAspectFlagBits::eStencil,
|
dst_layers = 1;
|
||||||
.mipLevel = mip,
|
|
||||||
.baseArrayLayer = 0,
|
vk::ImageCopy copy_region = {
|
||||||
.layerCount = dst_layers,
|
.srcSubresource{
|
||||||
},
|
.aspectMask = aspect,
|
||||||
.extent = {mip_w, mip_h, mip_d},
|
.mipLevel = mip,
|
||||||
});
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = copy_layers,
|
||||||
|
},
|
||||||
|
.dstSubresource{
|
||||||
|
.aspectMask = aspect,
|
||||||
|
.mipLevel = mip,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = copy_layers,
|
||||||
|
},
|
||||||
|
.extent = vk::Extent3D(mip_w, mip_h, mip_d),
|
||||||
|
};
|
||||||
|
image_copies.push_back(copy_region);
|
||||||
|
} else if (is_2d_to_3d) {
|
||||||
|
vk::ImageCopy copy_region = {
|
||||||
|
.srcSubresource{
|
||||||
|
.aspectMask = aspect,
|
||||||
|
.mipLevel = mip,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = src_layers,
|
||||||
|
},
|
||||||
|
.dstSubresource{
|
||||||
|
.aspectMask = aspect,
|
||||||
|
.mipLevel = mip,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
.extent = vk::Extent3D(mip_w, mip_h, src_layers),
|
||||||
|
};
|
||||||
|
image_copies.push_back(copy_region);
|
||||||
|
} else if (is_3d_to_2d) {
|
||||||
|
vk::ImageCopy copy_region = {
|
||||||
|
.srcSubresource{
|
||||||
|
.aspectMask = aspect,
|
||||||
|
.mipLevel = mip,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
.dstSubresource{
|
||||||
|
.aspectMask = aspect,
|
||||||
|
.mipLevel = mip,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = dst_layers,
|
||||||
|
},
|
||||||
|
.extent = vk::Extent3D(mip_w, mip_h, dst_layers),
|
||||||
|
};
|
||||||
|
image_copies.push_back(copy_region);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduler->EndRendering();
|
scheduler->EndRendering();
|
||||||
|
|
||||||
src_image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {});
|
src_image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {});
|
||||||
Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite, {});
|
Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite, {});
|
||||||
|
|
||||||
auto cmdbuf = scheduler->CommandBuffer();
|
auto cmdbuf = scheduler->CommandBuffer();
|
||||||
cmdbuf.copyImage(src_image.GetImage(), src_image.backing->state.layout, GetImage(),
|
|
||||||
backing->state.layout, image_copies);
|
|
||||||
|
|
||||||
Transit(vk::ImageLayout::eGeneral,
|
if (!image_copies.empty()) {
|
||||||
vk::AccessFlagBits2::eShaderRead | vk::AccessFlagBits2::eTransferRead, {});
|
cmdbuf.copyImage(src_image.GetImage(), src_image.backing->state.layout, GetImage(),
|
||||||
|
backing->state.layout, image_copies);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simplified final layout - always use ShaderReadOnlyOptimal
|
||||||
|
// This is safe for most cases and avoids the usage check
|
||||||
|
Transit(vk::ImageLayout::eShaderReadOnlyOptimal, vk::AccessFlagBits2::eShaderRead, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::CopyImageWithBuffer(Image& src_image, vk::Buffer buffer, u64 offset) {
|
void Image::CopyImageWithBuffer(Image& src_image, vk::Buffer buffer, u64 offset) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user