gpu: bound overlapping image copies by both native backings

This commit is contained in:
Pixeluted
2026-10-19 04:12:25 +02:00
committed by nmzik
parent 05d25ef28c
commit 440245f616
2 changed files with 51 additions and 2 deletions
@@ -353,8 +353,12 @@ void Image::CopyImage(Image& source) {
std::vector<vk::ImageCopy> copies; std::vector<vk::ImageCopy> copies;
copies.reserve(levels); copies.reserve(levels);
for (uint32_t level = 0; level < levels; level++) { for (uint32_t level = 0; level < levels; level++) {
const auto width = std::max(source.backing.extent.width >> level, 1u); // Overlapping cache images can differ in size; copying the source extent into a smaller
const auto height = std::max(source.backing.extent.height >> level, 1u); // destination writes out of bounds and loses the device.
const auto width = std::min(std::max(source.backing.extent.width >> level, 1u),
std::max(backing.extent.width >> level, 1u));
const auto height = std::min(std::max(source.backing.extent.height >> level, 1u),
std::max(backing.extent.height >> level, 1u));
const auto depth = std::max(base_depth >> level, 1u); const auto depth = std::max(base_depth >> level, 1u);
const auto [source_layers, destination_layers] = SanitizeCopyLayers(source, *this, depth); const auto [source_layers, destination_layers] = SanitizeCopyLayers(source, *this, depth);
vk::ImageCopy copy {}; vk::ImageCopy copy {};
+45
View File
@@ -6709,6 +6709,51 @@ public:
"Image::CopyImage did not retain pinned " "Image::CopyImage did not retain pinned "
"source/destination states"); "source/destination states");
auto wide_volume_info = native_volume_info;
wide_volume_info.extent = {85, 5, 5};
wide_volume_info.pitch = 85;
auto narrow_volume_info = wide_volume_info;
narrow_volume_info.extent.width = 20;
narrow_volume_info.pitch = 20;
Libs::Graphics::Image wide_volume(m_runtime_context, scheduler,
wide_volume_info);
Libs::Graphics::Image narrow_volume(m_runtime_context, scheduler,
narrow_volume_info);
std::vector<uint32_t> volume_source_words(85 * 5 * 5);
for (uint32_t i = 0; i < volume_source_words.size(); ++i)
volume_source_words[i] = i + 1;
auto volume_upload = CreateHostBuffer(
name, volume_source_words.size() * sizeof(uint32_t),
vk::BufferUsageFlagBits::eTransferSrc, volume_source_words);
auto shrinking_readback =
CreateHostBuffer(name, 20 * 5 * 5 * sizeof(uint32_t),
vk::BufferUsageFlagBits::eTransferDst, {});
vk::BufferImageCopy volume_region{};
volume_region.imageSubresource = {vk::ImageAspectFlagBits::eColor, 0, 0,
1};
volume_region.imageExtent = wide_volume_info.extent;
wide_volume.Upload(std::span{&volume_region, 1}, volume_upload.buffer, 0,
volume_upload.size);
narrow_volume.CopyImage(wide_volume);
volume_region.imageExtent = narrow_volume_info.extent;
narrow_volume.Download(std::span{&volume_region, 1},
shrinking_readback.buffer, 0,
shrinking_readback.size);
HostReadBarrier(shrinking_readback.buffer, shrinking_readback.size,
vk::PipelineStageFlagBits::eTransfer,
vk::AccessFlagBits::eTransferWrite);
scheduler.Finish();
const auto volume_copied_words =
ReadBuffer(name, shrinking_readback, 20 * 5 * 5);
for (uint32_t row = 0; row < 5 * 5; ++row)
Require(name, "shrinking volume copy contents",
std::equal(volume_copied_words.begin() + row * 20,
volume_copied_words.begin() + (row + 1) * 20,
volume_source_words.begin() + row * 85),
"85x5x5 to 20x5x5 copy lost a row or depth slice");
DestroyBuffer(&shrinking_readback);
DestroyBuffer(&volume_upload);
ImageInfo resolve_source_info{}; ImageInfo resolve_source_info{};
resolve_source_info.pixel_format = vk::Format::eR8G8B8A8Unorm; resolve_source_info.pixel_format = vk::Format::eR8G8B8A8Unorm;
resolve_source_info.guest_format = Prospero::BufferFormat::k8_8_8_8UNorm; resolve_source_info.guest_format = Prospero::BufferFormat::k8_8_8_8UNorm;