Use a buffer for reading back swapchain at frame capture end on vulkan

This commit is contained in:
baldurk
2018-09-06 10:52:00 +01:00
parent 3b8a7ebf59
commit 57cf95783d
+44 -61
View File
@@ -1265,44 +1265,30 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
const SwapchainInfo &swapInfo = *swaprecord->swapInfo;
// since this happens during capture, we don't want to start serialising extra image creates,
// since this happens during capture, we don't want to start serialising extra buffer creates,
// so we manually create & then just wrap.
VkImage readbackIm = VK_NULL_HANDLE;
VkBuffer readbackBuf = VK_NULL_HANDLE;
VkResult vkr = VK_SUCCESS;
// create identical image
VkImageCreateInfo imInfo = {
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
// create readback buffer
VkBufferCreateInfo bufInfo = {
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
NULL,
0,
VK_IMAGE_TYPE_2D,
swapInfo.format,
{swapInfo.extent.width, swapInfo.extent.height, 1},
1,
1,
VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_LINEAR,
VK_IMAGE_USAGE_TRANSFER_DST_BIT,
VK_SHARING_MODE_EXCLUSIVE,
0,
NULL,
VK_IMAGE_LAYOUT_UNDEFINED,
GetByteSize(swapInfo.extent.width, swapInfo.extent.height, 1, swapInfo.format, 0),
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
};
vt->CreateImage(Unwrap(device), &imInfo, NULL, &readbackIm);
vt->CreateBuffer(Unwrap(device), &bufInfo, NULL, &readbackBuf);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(device), readbackIm);
VkImageSubresource subr = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0};
VkSubresourceLayout layout = {0};
vt->GetImageSubresourceLayout(Unwrap(device), Unwrap(readbackIm), &subr, &layout);
GetResourceManager()->WrapResource(Unwrap(device), readbackBuf);
MemoryAllocation readbackMem =
AllocateMemoryForResource(readbackIm, MemoryScope::InitialContents, MemoryType::Readback);
AllocateMemoryForResource(readbackBuf, MemoryScope::InitialContents, MemoryType::Readback);
vkr = vt->BindImageMemory(Unwrap(device), Unwrap(readbackIm), Unwrap(readbackMem.mem),
readbackMem.offs);
vkr = vt->BindBufferMemory(Unwrap(device), Unwrap(readbackBuf), Unwrap(readbackMem.mem),
readbackMem.offs);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
@@ -1312,10 +1298,17 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkImageCopy cpy = {
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, {0, 0, 0},
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, {0, 0, 0},
{imInfo.extent.width, imInfo.extent.height, 1},
uint32_t rowPitch = GetByteSize(swapInfo.extent.width, 1, 1, swapInfo.format, 0);
VkBufferImageCopy cpy = {
0,
0,
0,
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
{
0, 0, 0,
},
{swapInfo.extent.width, swapInfo.extent.height, 1},
};
uint32_t swapQueueIndex = m_ImageLayouts[GetResID(backbuffer)].queueFamilyIndex;
@@ -1333,21 +1326,7 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
};
VkImageMemoryBarrier readBarrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
NULL,
0,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
Unwrap(readbackIm),
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
};
DoPipelineBarrier(cmd, 1, &bbBarrier);
DoPipelineBarrier(cmd, 1, &readBarrier);
if(swapQueueIndex != m_QueueFamilyIdx)
{
@@ -1363,21 +1342,28 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
SubmitAndFlushExtQueue(swapQueueIndex);
}
vt->CmdCopyImage(Unwrap(cmd), Unwrap(backbuffer), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
Unwrap(readbackIm), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cpy);
vt->CmdCopyImageToBuffer(Unwrap(cmd), Unwrap(backbuffer), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
Unwrap(readbackBuf), 1, &cpy);
// barrier to switch backbuffer back to present layout
std::swap(bbBarrier.oldLayout, bbBarrier.newLayout);
std::swap(bbBarrier.srcAccessMask, bbBarrier.dstAccessMask);
std::swap(bbBarrier.srcQueueFamilyIndex, bbBarrier.dstQueueFamilyIndex);
readBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
readBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
readBarrier.oldLayout = readBarrier.newLayout;
readBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
VkBufferMemoryBarrier bufBarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
NULL,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_HOST_READ_BIT,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
Unwrap(readbackBuf),
0,
bufInfo.size,
};
DoPipelineBarrier(cmd, 1, &bbBarrier);
DoPipelineBarrier(cmd, 1, &readBarrier);
DoPipelineBarrier(cmd, 1, &bufBarrier);
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
@@ -1420,18 +1406,16 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
// point sample info into raw buffer
{
ResourceFormat fmt = MakeResourceFormat(imInfo.format);
ResourceFormat fmt = MakeResourceFormat(swapInfo.format);
byte *data = (byte *)pData;
data += layout.offset;
float widthf = float(imInfo.extent.width);
float heightf = float(imInfo.extent.height);
float widthf = float(swapInfo.extent.width);
float heightf = float(swapInfo.extent.height);
float aspect = widthf / heightf;
thwidth = (uint16_t)RDCMIN(maxSize, imInfo.extent.width);
thwidth = (uint16_t)RDCMIN(maxSize, swapInfo.extent.width);
thwidth &= ~0x7; // align down to multiple of 8
thheight = uint16_t(float(thwidth) / aspect);
@@ -1469,8 +1453,7 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
float xf = float(x) / float(thwidth);
float yf = float(y) / float(thheight);
byte *src =
&data[stride * uint32_t(xf * widthf) + layout.rowPitch * uint32_t(yf * heightf)];
byte *src = &data[stride * uint32_t(xf * widthf) + rowPitch * uint32_t(yf * heightf)];
if(buf1010102)
{
@@ -1540,8 +1523,8 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
vt->UnmapMemory(Unwrap(device), Unwrap(readbackMem.mem));
// delete all
vt->DestroyImage(Unwrap(device), Unwrap(readbackIm), NULL);
GetResourceManager()->ReleaseWrappedResource(readbackIm);
vt->DestroyBuffer(Unwrap(device), Unwrap(readbackBuf), NULL);
GetResourceManager()->ReleaseWrappedResource(readbackBuf);
}
byte *jpgbuf = NULL;