mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-12 12:33:24 +09:00
[MG_Backend] (Disaggregated): preserve the untouched aspect of depth stencil resolves
This commit is contained in:
@@ -537,6 +537,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
// Transfer/resolve scratch storage belongs to the submission that
|
// Transfer/resolve scratch storage belongs to the submission that
|
||||||
// consumes it, just like the views and framebuffer above.
|
// consumes it, just like the views and framebuffer above.
|
||||||
Vector<UniquePtr<VkTextureManager::TextureResource>> textures;
|
Vector<UniquePtr<VkTextureManager::TextureResource>> textures;
|
||||||
|
Vector<UniquePtr<VkBufferObject>> buffers;
|
||||||
};
|
};
|
||||||
void RetireWireObjects(WireRetiredObjects objects);
|
void RetireWireObjects(WireRetiredObjects objects);
|
||||||
void CollectWireObjects(Uint64 completedSubmit, Bool all = false);
|
void CollectWireObjects(Uint64 completedSubmit, Bool all = false);
|
||||||
|
|||||||
@@ -376,17 +376,52 @@
|
|||||||
auto& frame = m_frameContext.GetCurrent();
|
auto& frame = m_frameContext.GetCurrent();
|
||||||
vkCmdBeginRenderPass(frame.commandBuffer, &begin, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(frame.commandBuffer, &begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
vkCmdEndRenderPass(frame.commandBuffer);
|
vkCmdEndRenderPass(frame.commandBuffer);
|
||||||
TransitionWireImage(resolved, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
// Depth/stencil resolve writes execute in COLOR_ATTACHMENT_OUTPUT,
|
||||||
|
// unlike ordinary depth attachment writes. Include both when exposing
|
||||||
|
// the resolved image to a transfer; layout-based inference only covers
|
||||||
|
// EARLY/LATE_FRAGMENT_TESTS and misses the resolve's store operation.
|
||||||
|
if (!VkTextureManager::TransitionImageLayout(frame.commandBuffer, resolved.image, scratch->layout,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||||
|
VK_ACCESS_TRANSFER_READ_BIT, formatAspects))
|
||||||
|
MagmaWireFatal("multisample-depth-resolve-transition");
|
||||||
|
resolved.layout = scratch->layout;
|
||||||
TransitionWireImage(destination, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
TransitionWireImage(destination, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
UniquePtr<VkBufferObject> aspectBuffer;
|
||||||
if (source.format == destination.format) {
|
if (source.format == destination.format) {
|
||||||
VkImageCopy copy{};
|
// Copy one aspect through its buffer representation. Some packed
|
||||||
copy.srcSubresource = {source.aspect, 0, 0, 1};
|
// depth/stencil image-copy paths copy the complete native word even
|
||||||
copy.srcOffset = {sx0, sy0, 0};
|
// for a single-aspect region. A stencil byte or depth-only word in
|
||||||
copy.dstSubresource = {source.aspect, destination.level, destination.layer, 1};
|
// this GPU buffer cannot replace the destination's other aspect.
|
||||||
copy.dstOffset = {dx0, dy0, 0};
|
const VkDeviceSize texelSize = source.aspect == VK_IMAGE_ASPECT_STENCIL_BIT ? 1 :
|
||||||
copy.extent = {static_cast<Uint32>(width), static_cast<Uint32>(height), 1};
|
(source.format == VK_FORMAT_D16_UNORM || source.format == VK_FORMAT_D16_UNORM_S8_UINT ? 2 : 4);
|
||||||
vkCmdCopyImage(frame.commandBuffer, resolved.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
const VkDeviceSize bytes = static_cast<VkDeviceSize>(width) * height * texelSize;
|
||||||
destination.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©);
|
aspectBuffer = MakeUnique<VkBufferObject>();
|
||||||
|
if (!aspectBuffer->Create({.allocator = m_allocator, .size = bytes,
|
||||||
|
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
|
.memoryUsage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE}))
|
||||||
|
MagmaWireFatal("multisample-depth-resolve-buffer");
|
||||||
|
VkBufferImageCopy copy{};
|
||||||
|
copy.imageSubresource = {source.aspect, 0, 0, 1};
|
||||||
|
copy.imageOffset = {sx0, sy0, 0};
|
||||||
|
copy.imageExtent = {static_cast<Uint32>(width), static_cast<Uint32>(height), 1};
|
||||||
|
vkCmdCopyImageToBuffer(frame.commandBuffer, resolved.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
aspectBuffer->GetHandle(), 1, ©);
|
||||||
|
VkBufferMemoryBarrier barrier{VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER};
|
||||||
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
|
barrier.srcQueueFamilyIndex = barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
barrier.buffer = aspectBuffer->GetHandle();
|
||||||
|
barrier.size = bytes;
|
||||||
|
vkCmdPipelineBarrier(frame.commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
0, 0, nullptr, 1, &barrier, 0, nullptr);
|
||||||
|
copy.imageSubresource = {source.aspect, destination.level, destination.layer, 1};
|
||||||
|
copy.imageOffset = {dx0, dy0, 0};
|
||||||
|
vkCmdCopyBufferToImage(frame.commandBuffer, aspectBuffer->GetHandle(), destination.image,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©);
|
||||||
} else {
|
} else {
|
||||||
// A logical GL depth format may use different native renderbuffer
|
// A logical GL depth format may use different native renderbuffer
|
||||||
// and texture formats. Re-encode only after producing real resolved
|
// and texture formats. Re-encode only after producing real resolved
|
||||||
@@ -403,6 +438,7 @@
|
|||||||
retired.renderPasses.push_back(pass);
|
retired.renderPasses.push_back(pass);
|
||||||
retired.imageViews = {views[0], views[1]};
|
retired.imageViews = {views[0], views[1]};
|
||||||
retired.textures.push_back(Move(scratch));
|
retired.textures.push_back(Move(scratch));
|
||||||
|
if (aspectBuffer) retired.buffers.push_back(Move(aspectBuffer));
|
||||||
RetireWireObjects(Move(retired));
|
RetireWireObjects(Move(retired));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user