mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-07 13:39:55 +00:00
fix(agc): copy a depth surface's plane through the texture's padded linear slices
The plane copy laid its staging buffer out as tight slices while the detiler writes the guest's linear layout, which pads rows and slices: a 32x32 D16 cube in a 64 KiB swizzle has 16384-byte slices, not 2048, and a 128x128 one has 512-byte rows and 64 KiB slices. Each region in record now takes the layer's LinearLayerOffset plus the mip's linear offset and its pitch as the row length, for both the slices copied from a live depth surface and the ones detiled from guest memory. The staging buffer grows to the padded size, keeping the buffer it replaces alive for copies already recorded, and a mismatch says which geometry it saw.
This commit is contained in:
1 parent
e154f56585
commit
6b480cc2be
1 file changed
+18
-3
@@ -316,7 +316,8 @@ public:
|
||||
allocation.memoryTypeIndex = context.MemoryType(requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
Check(context.Function<PFN_vkAllocateMemory>("vkAllocateMemory")(context.device, &allocation, nullptr, &memory), "vkAllocateMemory depth plane copy");
|
||||
Check(context.Function<PFN_vkBindImageMemory>("vkBindImageMemory")(context.device, image, memory, 0), "vkBindImageMemory depth plane copy");
|
||||
staging = std::make_unique<DeviceBuffer>(context, static_cast<std::size_t>(sliceBytes()) * layers, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
stagingSize = static_cast<std::size_t>(sliceBytes()) * layers;
|
||||
staging = std::make_unique<DeviceBuffer>(context, stagingSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
} catch (...) {
|
||||
release();
|
||||
throw;
|
||||
@@ -329,7 +330,17 @@ public:
|
||||
std::shared_ptr<Texture> Refresh(std::span<const DepthPlaneSlice> slices, const GuestTextureResource& resource, VkComponentMapping components, VkImageViewType viewType, std::uint32_t baseLayer) {
|
||||
Require(slices.size() == layers, "depth plane copy slices do not match its layers");
|
||||
const auto geometry = DescribeSurface(resource);
|
||||
Require(geometry.layers == layers && geometry.sliceLinearBytes == sliceBytes() && !geometry.mips.empty(), "depth plane copy geometry does not match its layers");
|
||||
if (geometry.layers != layers || geometry.sliceLinearBytes < sliceBytes() || geometry.mips.empty()) {
|
||||
char text[320];
|
||||
std::snprintf(text, sizeof(text), "AGC graphics: depth plane copy geometry does not match its layers (copy %ux%u, %u layers, %llu bytes a slice; texture %ux%u guest format %u, dimension %d, tile mode %u, %u layers, %llu bytes a slice, %zu mips)", extent.width, extent.height, layers, static_cast<unsigned long long>(sliceBytes()), resource.width, resource.height, resource.format, static_cast<int>(resource.dimension), resource.tileMode, geometry.layers, static_cast<unsigned long long>(geometry.sliceLinearBytes), geometry.mips.size());
|
||||
throw std::runtime_error(text);
|
||||
}
|
||||
const auto stagingBytes = static_cast<std::size_t>(geometry.sliceLinearBytes) * layers;
|
||||
if (stagingBytes > stagingSize) {
|
||||
retiredStaging.push_back(std::move(staging));
|
||||
staging = std::make_unique<DeviceBuffer>(context, stagingBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
stagingSize = stagingBytes;
|
||||
}
|
||||
std::vector<std::shared_ptr<Buffer>> uploads;
|
||||
std::vector<std::uint32_t> uploadLayers;
|
||||
std::vector<std::uint32_t> copiedLayers;
|
||||
@@ -382,6 +393,8 @@ private:
|
||||
VkImage image = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
std::unique_ptr<DeviceBuffer> staging;
|
||||
std::size_t stagingSize = 0;
|
||||
std::vector<std::unique_ptr<DeviceBuffer>> retiredStaging;
|
||||
std::map<std::array<std::uint32_t, 6>, std::shared_ptr<Texture>> textures;
|
||||
std::vector<GuestLayer> guestLayers;
|
||||
std::vector<DepthPlaneSlice> surfaceLayers;
|
||||
@@ -399,9 +412,11 @@ private:
|
||||
const auto barrier = context.Resolved(&DeviceFunctions::cmdPipelineBarrier, "vkCmdPipelineBarrier");
|
||||
RecordMemoryBarrier(context, commands, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||
std::vector<VkBufferImageCopy> regions;
|
||||
const auto& mip = geometry.mips.front();
|
||||
const auto region = [&](std::uint32_t layer, VkImageAspectFlags aspectMask, std::uint32_t imageLayer) {
|
||||
VkBufferImageCopy copy{};
|
||||
copy.bufferOffset = sliceBytes() * layer;
|
||||
copy.bufferOffset = geometry.LinearLayerOffset(layer) + mip.linearOffset;
|
||||
copy.bufferRowLength = mip.pitchBytes / (format == VK_FORMAT_D32_SFLOAT ? 4u : 2u);
|
||||
copy.imageSubresource = {aspectMask, 0, imageLayer, 1};
|
||||
copy.imageExtent = {extent.width, extent.height, 1};
|
||||
return copy;
|
||||
|
||||
Reference in new issue
Block a user