mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-06 22:05:39 +00:00
When descriptor buffers are used, intercept swapchain images
* This is the only way we can handle the potential for creating descriptors for swapchain images as there is no way otherwise to fetch and replay the opaque descriptor data on the image that would be needed. We add an extra interception step and let the application write to a 'real' image that we allocate, prevent it from going into the present layout, and on present do a copy & fixup.
This commit is contained in:
@@ -433,7 +433,7 @@ bool VkInitParams::IsSupportedVersion(uint64_t ver)
|
||||
if(ver == CurrentVersion)
|
||||
return true;
|
||||
|
||||
// 0x16 -> 0x17 - added indication of reserved descriptors
|
||||
// 0x16 -> 0x17 - added indication of reserved descriptors and descriptor buffer support for swapchains
|
||||
if(ver == 0x16)
|
||||
return true;
|
||||
|
||||
@@ -489,6 +489,13 @@ bool VkInitParams::IsSupportedVersion(uint64_t ver)
|
||||
return false;
|
||||
}
|
||||
|
||||
void SanitiseDescriptorBufferImageLayout(VkImageLayout &layout)
|
||||
{
|
||||
// for descriptor buffers we intercept swapchain images so we have to remap present layouts to general
|
||||
if(layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR || layout == VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR)
|
||||
layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
|
||||
void SanitiseReplayImageLayout(VkImageLayout &layout)
|
||||
{
|
||||
// we don't replay with present layouts since we don't create actual swapchains. So change any
|
||||
@@ -1060,6 +1067,24 @@ void OpaqueDataForSerialising::fill(VkDevice wrappedDevice, VkBuffer wrappedBuff
|
||||
RDCERR("Couldn't get opaque capture/replay data: %s", ToStr(opaqueQuery).c_str());
|
||||
}
|
||||
|
||||
void OpaqueDataForSerialising::fillUnwrapped(VkDevice wrappedDevice, VkImage unwrappedImage,
|
||||
VkPhysicalDeviceDescriptorBufferPropertiesEXT &props)
|
||||
{
|
||||
VkImageCaptureDescriptorDataInfoEXT getInfo = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT,
|
||||
NULL,
|
||||
unwrappedImage,
|
||||
};
|
||||
|
||||
sz = props.imageCaptureReplayDescriptorDataSize;
|
||||
|
||||
VkResult opaqueQuery =
|
||||
ObjDisp(wrappedDevice)
|
||||
->GetImageOpaqueCaptureDescriptorDataEXT(Unwrap(wrappedDevice), &getInfo, data);
|
||||
if(opaqueQuery != VK_SUCCESS)
|
||||
RDCERR("Couldn't get opaque capture/replay data: %s", ToStr(opaqueQuery).c_str());
|
||||
}
|
||||
|
||||
void OpaqueDataForSerialising::fill(VkDevice wrappedDevice, VkImage wrappedImage,
|
||||
VkPhysicalDeviceDescriptorBufferPropertiesEXT &props)
|
||||
{
|
||||
|
||||
@@ -123,6 +123,7 @@ rdcstr HumanDriverName(VkDriverId driverId);
|
||||
void SanitiseOldImageLayout(VkImageLayout &layout);
|
||||
void SanitiseNewImageLayout(VkImageLayout &layout);
|
||||
void SanitiseReplayImageLayout(VkImageLayout &layout);
|
||||
void SanitiseDescriptorBufferImageLayout(VkImageLayout &layout);
|
||||
|
||||
void CombineDepthStencilLayouts(rdcarray<VkImageMemoryBarrier> &barriers);
|
||||
|
||||
@@ -946,6 +947,9 @@ struct OpaqueDataForSerialising : VkOpaqueCaptureDescriptorDataCreateInfoEXT
|
||||
void fill(VkDevice wrappedDevice, VkAccelerationStructureKHR wrappedAS,
|
||||
VkPhysicalDeviceDescriptorBufferPropertiesEXT &props);
|
||||
|
||||
void fillUnwrapped(VkDevice wrappedDevice, VkImage unwrappedImage,
|
||||
VkPhysicalDeviceDescriptorBufferPropertiesEXT &props);
|
||||
|
||||
void addForSerialising(VkBaseInStructure *serialisedCreateInfo);
|
||||
|
||||
byte data[FixedOpaqueDescriptorCaptureSize] = {};
|
||||
|
||||
@@ -2672,7 +2672,7 @@ bool WrappedVulkan::EndFrameCapture(DeviceOwnedWindow devWnd)
|
||||
|
||||
const SwapchainInfo &swapInfo = *swaprecord->swapInfo;
|
||||
|
||||
backbuffer = swapInfo.images[swapInfo.lastPresent.imageIndex].im;
|
||||
backbuffer = swapInfo.images[swapInfo.lastPresent.imageIndex].userSwapImage;
|
||||
swapImageInfo = &swapInfo.imageInfo;
|
||||
swapQueueIndex = GetRecord(swapInfo.lastPresent.presentQueue)->queueFamilyIndex;
|
||||
swapLayout =
|
||||
@@ -2680,8 +2680,12 @@ bool WrappedVulkan::EndFrameCapture(DeviceOwnedWindow devWnd)
|
||||
|
||||
// mark all images referenced as well
|
||||
for(size_t i = 0; i < swapInfo.images.size(); i++)
|
||||
GetResourceManager()->MarkResourceFrameReferenced(GetResID(swapInfo.images[i].im),
|
||||
GetResourceManager()->MarkResourceFrameReferenced(GetResID(swapInfo.images[i].userSwapImage),
|
||||
eFrameRef_Read);
|
||||
|
||||
// we're using the fake image for descriptor buffers, which is in layout general not present
|
||||
if(DescriptorBuffers())
|
||||
swapLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2697,7 +2701,7 @@ bool WrappedVulkan::EndFrameCapture(DeviceOwnedWindow devWnd)
|
||||
|
||||
const SwapchainInfo &swapInfo = *swaprecord->swapInfo;
|
||||
|
||||
backbuffer = swapInfo.images[swapInfo.lastPresent.imageIndex].im;
|
||||
backbuffer = swapInfo.images[swapInfo.lastPresent.imageIndex].userSwapImage;
|
||||
swapImageInfo = &swapInfo.imageInfo;
|
||||
swapQueueIndex = GetRecord(swapInfo.lastPresent.presentQueue)->queueFamilyIndex;
|
||||
swapLayout =
|
||||
@@ -2705,8 +2709,11 @@ bool WrappedVulkan::EndFrameCapture(DeviceOwnedWindow devWnd)
|
||||
|
||||
// mark all images referenced as well
|
||||
for(size_t i = 0; i < swapInfo.images.size(); i++)
|
||||
GetResourceManager()->MarkResourceFrameReferenced(GetResID(swapInfo.images[i].im),
|
||||
eFrameRef_Read);
|
||||
GetResourceManager()->MarkResourceFrameReferenced(
|
||||
GetResID(swapInfo.images[i].userSwapImage), eFrameRef_Read);
|
||||
|
||||
if(DescriptorBuffers())
|
||||
swapLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
else if(VRBackbufferRecord)
|
||||
{
|
||||
|
||||
@@ -979,9 +979,9 @@ DECLARE_REFLECTION_STRUCT(ImageInfo);
|
||||
|
||||
struct PresentInfo
|
||||
{
|
||||
VkQueue presentQueue;
|
||||
VkQueue presentQueue = VK_NULL_HANDLE;
|
||||
rdcarray<VkSemaphore> waitSemaphores;
|
||||
uint32_t imageIndex;
|
||||
uint32_t imageIndex = 0;
|
||||
};
|
||||
|
||||
struct SwapchainInfo
|
||||
@@ -996,16 +996,25 @@ struct SwapchainInfo
|
||||
|
||||
struct SwapImage
|
||||
{
|
||||
VkImage im;
|
||||
// the handle returned to the user, whether real or fake
|
||||
VkImage userSwapImage = VK_NULL_HANDLE;
|
||||
// if we made a fake swap image then this is the real unwrapped swapchain image
|
||||
VkImage unwrappedRealSwapImage = VK_NULL_HANDLE;
|
||||
|
||||
VkImageView view;
|
||||
VkFramebuffer fb;
|
||||
uint64_t fakeImageMemoryOffset = 0;
|
||||
|
||||
VkFence fence;
|
||||
VkCommandBuffer cmd;
|
||||
VkSemaphore overlaydone;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
VkFramebuffer fb = VK_NULL_HANDLE;
|
||||
|
||||
VkFence fence = VK_NULL_HANDLE;
|
||||
VkCommandBuffer cmd = VK_NULL_HANDLE;
|
||||
VkSemaphore overlaydone = VK_NULL_HANDLE;
|
||||
};
|
||||
rdcarray<SwapImage> images;
|
||||
VkDeviceMemory imageMemory = VK_NULL_HANDLE;
|
||||
uint32_t imageMemoryIndex = ~0U;
|
||||
uint64_t imageMemorySize = 0;
|
||||
|
||||
PresentInfo lastPresent;
|
||||
};
|
||||
|
||||
|
||||
@@ -4182,6 +4182,9 @@ void WrappedVulkan::vkCmdPipelineBarrier(
|
||||
{
|
||||
im[i] = pImageMemoryBarriers[i];
|
||||
im[i].image = Unwrap(im[i].image);
|
||||
|
||||
SanitiseDescriptorBufferImageLayout(im[i].newLayout);
|
||||
SanitiseDescriptorBufferImageLayout(im[i].newLayout);
|
||||
}
|
||||
|
||||
SERIALISE_TIME_CALL(ObjDisp(commandBuffer)
|
||||
@@ -4416,6 +4419,13 @@ void WrappedVulkan::vkCmdPipelineBarrier2(VkCommandBuffer commandBuffer,
|
||||
byte *tempMem = GetTempMemory(GetNextPatchSize(pDependencyInfo));
|
||||
VkDependencyInfo *unwrappedInfo = UnwrapStructAndChain(m_State, tempMem, pDependencyInfo);
|
||||
|
||||
for(uint32_t im = 0; im < unwrappedInfo->imageMemoryBarrierCount; im++)
|
||||
{
|
||||
VkImageMemoryBarrier2 &b = (VkImageMemoryBarrier2 &)unwrappedInfo->pImageMemoryBarriers[im];
|
||||
SanitiseDescriptorBufferImageLayout(b.newLayout);
|
||||
SanitiseDescriptorBufferImageLayout(b.newLayout);
|
||||
}
|
||||
|
||||
SERIALISE_TIME_CALL(
|
||||
ObjDisp(commandBuffer)->CmdPipelineBarrier2(Unwrap(commandBuffer), unwrappedInfo));
|
||||
|
||||
|
||||
@@ -348,15 +348,18 @@ void WrappedVulkan::vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR obj,
|
||||
for(size_t i = 0; i < info.images.size(); i++)
|
||||
{
|
||||
VkFramebuffer unwrappedFB = Unwrap(info.images[i].fb);
|
||||
VkImage unwrappedImage = Unwrap(info.images[i].userSwapImage);
|
||||
VkImageView unwrappedView = Unwrap(info.images[i].view);
|
||||
VkSemaphore unwrappedSem = Unwrap(info.images[i].overlaydone);
|
||||
VkFence unwrappedFence = Unwrap(info.images[i].fence);
|
||||
GetResourceManager()->ReleaseWrappedResource(info.images[i].fb, true);
|
||||
// note, image doesn't have to be destroyed, just untracked
|
||||
GetResourceManager()->ReleaseWrappedResource(info.images[i].im, true);
|
||||
GetResourceManager()->ReleaseWrappedResource(info.images[i].userSwapImage, true);
|
||||
GetResourceManager()->ReleaseWrappedResource(info.images[i].view, true);
|
||||
GetResourceManager()->ReleaseWrappedResource(info.images[i].overlaydone);
|
||||
GetResourceManager()->ReleaseWrappedResource(info.images[i].fence);
|
||||
// if we had a separate real image, then the unwrappedImage is a fake one we created and must be destroyed
|
||||
if(info.images[i].unwrappedRealSwapImage != VK_NULL_HANDLE)
|
||||
ObjDisp(device)->DestroyImage(Unwrap(device), unwrappedImage, NULL);
|
||||
ObjDisp(device)->DestroyFramebuffer(Unwrap(device), unwrappedFB, NULL);
|
||||
ObjDisp(device)->DestroyImageView(Unwrap(device), unwrappedView, NULL);
|
||||
ObjDisp(device)->DestroySemaphore(Unwrap(device), unwrappedSem, NULL);
|
||||
@@ -365,6 +368,12 @@ void WrappedVulkan::vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR obj,
|
||||
// return the command buffers to the pool
|
||||
AddFreeCommandBuffer(info.images[i].cmd);
|
||||
}
|
||||
|
||||
if(info.imageMemory != VK_NULL_HANDLE)
|
||||
{
|
||||
ObjDisp(device)->FreeMemory(Unwrap(device), Unwrap(info.imageMemory), NULL);
|
||||
GetResourceManager()->ReleaseWrappedResource(info.imageMemory, true);
|
||||
}
|
||||
}
|
||||
|
||||
VkSwapchainKHR unwrappedObj = Unwrap(obj);
|
||||
@@ -1313,9 +1322,27 @@ bool WrappedVulkan::Serialise_vkCreateRenderPass(SerialiserType &ser, VkDevice d
|
||||
VkResult WrappedVulkan::vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *, VkRenderPass *pRenderPass)
|
||||
{
|
||||
VkRenderPassCreateInfo patchedCreateInfo = *pCreateInfo;
|
||||
|
||||
// descriptor buffers intercepts all swapchain images during capture so we change any
|
||||
// reference to PRESENT layout into GENERAL since that's what is valid for our image
|
||||
if(DescriptorBuffers())
|
||||
{
|
||||
byte *tempMem = GetTempMemory(GetNextPatchSize(patchedCreateInfo.pNext));
|
||||
CopyNextChainForPatching("VkRenderPassCreateInfo", tempMem,
|
||||
(VkBaseInStructure *)&patchedCreateInfo);
|
||||
|
||||
for(uint32_t a = 0; a < patchedCreateInfo.attachmentCount; a++)
|
||||
{
|
||||
VkAttachmentDescription &att = (VkAttachmentDescription &)patchedCreateInfo.pAttachments[a];
|
||||
SanitiseDescriptorBufferImageLayout(att.initialLayout);
|
||||
SanitiseDescriptorBufferImageLayout(att.finalLayout);
|
||||
}
|
||||
}
|
||||
|
||||
VkResult ret;
|
||||
SERIALISE_TIME_CALL(
|
||||
ret = ObjDisp(device)->CreateRenderPass(Unwrap(device), pCreateInfo, NULL, pRenderPass));
|
||||
SERIALISE_TIME_CALL(ret = ObjDisp(device)->CreateRenderPass(Unwrap(device), &patchedCreateInfo,
|
||||
NULL, pRenderPass));
|
||||
|
||||
if(ret == VK_SUCCESS)
|
||||
{
|
||||
@@ -1573,6 +1600,24 @@ VkResult WrappedVulkan::vkCreateRenderPass2(VkDevice device,
|
||||
const VkRenderPassCreateInfo2 *pCreateInfo,
|
||||
const VkAllocationCallbacks *, VkRenderPass *pRenderPass)
|
||||
{
|
||||
VkRenderPassCreateInfo2 patchedCreateInfo = *pCreateInfo;
|
||||
|
||||
// descriptor buffers intercepts all swapchain images during capture so we change any
|
||||
// reference to PRESENT layout into GENERAL since that's what is valid for our image
|
||||
if(DescriptorBuffers())
|
||||
{
|
||||
byte *tempMem = GetTempMemory(GetNextPatchSize(patchedCreateInfo.pNext));
|
||||
CopyNextChainForPatching("VkRenderPassCreateInfo2", tempMem,
|
||||
(VkBaseInStructure *)&patchedCreateInfo);
|
||||
|
||||
for(uint32_t a = 0; a < patchedCreateInfo.attachmentCount; a++)
|
||||
{
|
||||
VkAttachmentDescription2 &att = (VkAttachmentDescription2 &)patchedCreateInfo.pAttachments[a];
|
||||
SanitiseDescriptorBufferImageLayout(att.initialLayout);
|
||||
SanitiseDescriptorBufferImageLayout(att.finalLayout);
|
||||
}
|
||||
}
|
||||
|
||||
VkResult ret;
|
||||
SERIALISE_TIME_CALL(
|
||||
ret = ObjDisp(device)->CreateRenderPass2(Unwrap(device), pCreateInfo, NULL, pRenderPass));
|
||||
|
||||
@@ -923,6 +923,14 @@ void WrappedVulkan::vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t even
|
||||
{
|
||||
im[i] = pImageMemoryBarriers[i];
|
||||
im[i].image = Unwrap(im[i].image);
|
||||
|
||||
// descriptor buffers intercepts all swapchain images during capture so we change any
|
||||
// reference to PRESENT layout into GENERAL since that's what is valid for our image
|
||||
if(DescriptorBuffers())
|
||||
{
|
||||
SanitiseDescriptorBufferImageLayout(im[i].newLayout);
|
||||
SanitiseDescriptorBufferImageLayout(im[i].newLayout);
|
||||
}
|
||||
}
|
||||
|
||||
SERIALISE_TIME_CALL(ObjDisp(commandBuffer)
|
||||
@@ -1182,6 +1190,13 @@ void WrappedVulkan::vkCmdSetEvent2(VkCommandBuffer commandBuffer, VkEvent event,
|
||||
byte *tempMem = GetTempMemory(GetNextPatchSize(pDependencyInfo));
|
||||
VkDependencyInfo *unwrappedInfo = UnwrapStructAndChain(m_State, tempMem, pDependencyInfo);
|
||||
|
||||
for(uint32_t im = 0; im < unwrappedInfo->imageMemoryBarrierCount; im++)
|
||||
{
|
||||
VkImageMemoryBarrier2 &b = (VkImageMemoryBarrier2 &)unwrappedInfo->pImageMemoryBarriers[im];
|
||||
SanitiseDescriptorBufferImageLayout(b.newLayout);
|
||||
SanitiseDescriptorBufferImageLayout(b.newLayout);
|
||||
}
|
||||
|
||||
SERIALISE_TIME_CALL(
|
||||
ObjDisp(commandBuffer)->CmdSetEvent2(Unwrap(commandBuffer), Unwrap(event), unwrappedInfo));
|
||||
|
||||
@@ -1431,6 +1446,13 @@ void WrappedVulkan::vkCmdWaitEvents2(VkCommandBuffer commandBuffer, uint32_t eve
|
||||
{
|
||||
ev[i] = Unwrap(pEvents[i]);
|
||||
depInfo[i] = *UnwrapStructAndChain(m_State, tempMem, &pDependencyInfos[i]);
|
||||
|
||||
for(uint32_t im = 0; im < depInfo[i].imageMemoryBarrierCount; im++)
|
||||
{
|
||||
VkImageMemoryBarrier2 &b = (VkImageMemoryBarrier2 &)depInfo[i].pImageMemoryBarriers[im];
|
||||
SanitiseDescriptorBufferImageLayout(b.newLayout);
|
||||
SanitiseDescriptorBufferImageLayout(b.newLayout);
|
||||
}
|
||||
}
|
||||
|
||||
SERIALISE_TIME_CALL(
|
||||
|
||||
@@ -238,7 +238,8 @@ bool WrappedVulkan::Serialise_vkGetSwapchainImagesKHR(SerialiserType &ser, VkDev
|
||||
|
||||
RDCASSERT(SwapchainImageIndex < swapInfo.images.size(), SwapchainImageIndex,
|
||||
swapInfo.images.size());
|
||||
GetResourceManager()->AddLiveResource(SwapchainImage, swapInfo.images[SwapchainImageIndex].im);
|
||||
GetResourceManager()->AddLiveResource(SwapchainImage,
|
||||
swapInfo.images[SwapchainImageIndex].userSwapImage);
|
||||
|
||||
AddResource(SwapchainImage, ResourceType::SwapchainImage, "Swapchain Image");
|
||||
DerivedResource(device, SwapchainImage);
|
||||
@@ -248,7 +249,7 @@ bool WrappedVulkan::Serialise_vkGetSwapchainImagesKHR(SerialiserType &ser, VkDev
|
||||
GetResourceDesc(Swapchain).derivedResources.push_back(SwapchainImage);
|
||||
GetResourceDesc(SwapchainImage).parentResources.push_back(Swapchain);
|
||||
|
||||
m_CreationInfo.m_Image[GetResID(swapInfo.images[SwapchainImageIndex].im)] =
|
||||
m_CreationInfo.m_Image[GetResID(swapInfo.images[SwapchainImageIndex].userSwapImage)] =
|
||||
m_CreationInfo.m_Image[Swapchain];
|
||||
}
|
||||
|
||||
@@ -267,23 +268,45 @@ VkResult WrappedVulkan::vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR
|
||||
SERIALISE_TIME_CALL(ret = ObjDisp(device)->GetSwapchainImagesKHR(
|
||||
Unwrap(device), Unwrap(swapchain), pCount, pSwapchainImages));
|
||||
|
||||
// during swapchain create this function is called once to initialise and wrap the images,
|
||||
// thereafter we just return the already wrapped image handles. When descriptor buffers are
|
||||
// enabled we are wrapping fake images we created to be able to descriptor-ise as well as
|
||||
// initialising the real image handles
|
||||
if(pSwapchainImages && IsCaptureMode(m_State))
|
||||
{
|
||||
uint32_t numImages = *pCount;
|
||||
|
||||
VkResourceRecord *swapRecord = GetRecord(swapchain);
|
||||
|
||||
const bool fakeBackbuffers = AccelerationStructures() || DescriptorBuffers();
|
||||
|
||||
for(uint32_t i = 0; i < numImages; i++)
|
||||
{
|
||||
// these were all wrapped and serialised on swapchain create - we just have to
|
||||
// return the wrapped image in that case
|
||||
if(swapRecord->swapInfo->images[i].im != VK_NULL_HANDLE)
|
||||
// for descriptor buffers or AS, if we already have the unwrapped real image then we've fully
|
||||
// initialised so we can return the user swap image
|
||||
if(fakeBackbuffers && swapRecord->swapInfo->images[i].unwrappedRealSwapImage != VK_NULL_HANDLE)
|
||||
{
|
||||
pSwapchainImages[i] = swapRecord->swapInfo->images[i].im;
|
||||
pSwapchainImages[i] = swapRecord->swapInfo->images[i].userSwapImage;
|
||||
}
|
||||
// if we're not using fake backbuffers and we've fetched & wrapped the user swap image we
|
||||
// can also return that too.
|
||||
else if(!fakeBackbuffers && swapRecord->swapInfo->images[i].userSwapImage != VK_NULL_HANDLE)
|
||||
{
|
||||
pSwapchainImages[i] = swapRecord->swapInfo->images[i].userSwapImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResourceId id = GetResourceManager()->WrapResource(Unwrap(device), pSwapchainImages[i]);
|
||||
VkImage imageToWrap = pSwapchainImages[i];
|
||||
|
||||
// if using fake backbuffers, we store the real swapchain image and wrap our fake
|
||||
if(fakeBackbuffers)
|
||||
{
|
||||
swapRecord->swapInfo->images[i].unwrappedRealSwapImage = pSwapchainImages[i];
|
||||
imageToWrap = swapRecord->swapInfo->images[i].userSwapImage;
|
||||
RDCASSERT(imageToWrap != VK_NULL_HANDLE);
|
||||
}
|
||||
|
||||
ResourceId id = GetResourceManager()->WrapResource(Unwrap(device), imageToWrap);
|
||||
|
||||
Chunk *chunk = NULL;
|
||||
|
||||
@@ -291,12 +314,12 @@ VkResult WrappedVulkan::vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR
|
||||
CACHE_THREAD_SERIALISER();
|
||||
|
||||
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkGetSwapchainImagesKHR);
|
||||
Serialise_vkGetSwapchainImagesKHR(ser, device, swapchain, &i, &pSwapchainImages[i]);
|
||||
Serialise_vkGetSwapchainImagesKHR(ser, device, swapchain, &i, &imageToWrap);
|
||||
|
||||
chunk = scope.Get();
|
||||
}
|
||||
|
||||
VkResourceRecord *record = GetResourceManager()->AddResourceRecord(pSwapchainImages[i]);
|
||||
VkResourceRecord *record = GetResourceManager()->AddResourceRecord(imageToWrap);
|
||||
VkResourceRecord *swaprecord = GetRecord(swapchain);
|
||||
|
||||
record->InternalResource = true;
|
||||
@@ -312,6 +335,8 @@ VkResult WrappedVulkan::vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR
|
||||
// swapchain, if the image is referenced the swapchain (and thus all the getimages) will be
|
||||
// included.
|
||||
swaprecord->AddChunk(chunk);
|
||||
|
||||
pSwapchainImages[i] = imageToWrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -351,6 +376,51 @@ bool WrappedVulkan::Serialise_vkCreateSwapchainKHR(SerialiserType &ser, VkDevice
|
||||
|
||||
SERIALISE_ELEMENT(NumImages);
|
||||
|
||||
rdcarray<OpaqueDataForSerialising> opaqueDataFetch;
|
||||
|
||||
rdcarray<VkOpaqueCaptureDescriptorDataCreateInfoEXT> opaqueData;
|
||||
rdcarray<uint64_t> imageMemOffsets;
|
||||
uint64_t opaqueMemAddress = 0;
|
||||
|
||||
const bool fakeBackbuffers = AccelerationStructures() || DescriptorBuffers();
|
||||
|
||||
if(IsCaptureMode(m_State) && fakeBackbuffers)
|
||||
{
|
||||
if(DescriptorBuffers())
|
||||
{
|
||||
opaqueDataFetch.resize(NumImages);
|
||||
opaqueData.resize(NumImages);
|
||||
}
|
||||
imageMemOffsets.resize(NumImages);
|
||||
|
||||
for(uint32_t i = 0; i < NumImages; i++)
|
||||
{
|
||||
if(DescriptorBuffers())
|
||||
{
|
||||
opaqueDataFetch[i].fillUnwrapped(device,
|
||||
GetRecord(*pSwapChain)->swapInfo->images[i].userSwapImage,
|
||||
m_DescriptorBufferProperties);
|
||||
opaqueData[i] = opaqueDataFetch[i];
|
||||
}
|
||||
imageMemOffsets[i] = GetRecord(*pSwapChain)->swapInfo->images[i].fakeImageMemoryOffset;
|
||||
}
|
||||
|
||||
VkDeviceMemoryOpaqueCaptureAddressInfo getInfo = {
|
||||
VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO,
|
||||
NULL,
|
||||
Unwrap(GetRecord(*pSwapChain)->swapInfo->imageMemory),
|
||||
};
|
||||
|
||||
opaqueMemAddress = ObjDisp(device)->GetDeviceMemoryOpaqueCaptureAddress(Unwrap(device), &getInfo);
|
||||
}
|
||||
|
||||
if(ser.VersionAtLeast(0x17))
|
||||
{
|
||||
SERIALISE_ELEMENT(opaqueData).Hidden();
|
||||
SERIALISE_ELEMENT(imageMemOffsets).Hidden();
|
||||
SERIALISE_ELEMENT(opaqueMemAddress).Hidden();
|
||||
}
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
@@ -374,7 +444,7 @@ bool WrappedVulkan::Serialise_vkCreateSwapchainKHR(SerialiserType &ser, VkDevice
|
||||
if(CreateInfo.flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR)
|
||||
imageFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
||||
|
||||
const VkImageCreateInfo imInfo = {
|
||||
VkImageCreateInfo imInfo = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
NULL,
|
||||
imageFlags,
|
||||
@@ -400,12 +470,21 @@ bool WrappedVulkan::Serialise_vkCreateSwapchainKHR(SerialiserType &ser, VkDevice
|
||||
queueFamiles[q] = m_QueueRemapping[queueFamiles[q]][0].family;
|
||||
}
|
||||
|
||||
uint32_t memIndices = ~0U;
|
||||
uint64_t memSize = 0;
|
||||
|
||||
rdcarray<VkImage> ims;
|
||||
ims.resize(NumImages);
|
||||
|
||||
for(uint32_t i = 0; i < NumImages; i++)
|
||||
{
|
||||
VkDeviceMemory mem = VK_NULL_HANDLE;
|
||||
VkImage im = VK_NULL_HANDLE;
|
||||
if(DescriptorBuffers())
|
||||
{
|
||||
RDCASSERT(i < opaqueData.size(), i, opaqueData.size());
|
||||
imInfo.pNext = &opaqueData[i];
|
||||
}
|
||||
|
||||
VkResult vkr = ObjDisp(device)->CreateImage(Unwrap(device), &imInfo, NULL, &im);
|
||||
VkResult vkr = ObjDisp(device)->CreateImage(Unwrap(device), &imInfo, NULL, &ims[i]);
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
if(vkr != VK_SUCCESS)
|
||||
@@ -416,49 +495,80 @@ bool WrappedVulkan::Serialise_vkCreateSwapchainKHR(SerialiserType &ser, VkDevice
|
||||
return false;
|
||||
}
|
||||
|
||||
ResourceId liveId = GetResourceManager()->WrapResource(Unwrap(device), im);
|
||||
ResourceId liveId = GetResourceManager()->WrapResource(Unwrap(device), ims[i]);
|
||||
|
||||
VkMemoryRequirements mrq = {0};
|
||||
ObjDisp(device)->GetImageMemoryRequirements(Unwrap(device), Unwrap(ims[i]), &mrq);
|
||||
|
||||
ObjDisp(device)->GetImageMemoryRequirements(Unwrap(device), Unwrap(im), &mrq);
|
||||
memSize = AlignUp(memSize, mrq.alignment);
|
||||
|
||||
if(i < imageMemOffsets.size())
|
||||
{
|
||||
RDCASSERT(imageMemOffsets[i] == memSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCASSERT(imageMemOffsets.size() == i);
|
||||
imageMemOffsets.push_back(memSize);
|
||||
}
|
||||
|
||||
memSize += mrq.size;
|
||||
memIndices &= mrq.memoryTypeBits;
|
||||
}
|
||||
|
||||
VkDeviceMemory mem = VK_NULL_HANDLE;
|
||||
ResourceId memid;
|
||||
|
||||
for(uint32_t i = 0; i < NumImages; i++)
|
||||
{
|
||||
VkMemoryAllocateInfo allocInfo = {
|
||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
NULL,
|
||||
mrq.size,
|
||||
GetGPULocalMemoryIndex(mrq.memoryTypeBits),
|
||||
memSize,
|
||||
GetGPULocalMemoryIndex(memIndices),
|
||||
};
|
||||
|
||||
VkMemoryAllocateFlagsInfo memFlags = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO};
|
||||
if(DescriptorBuffers())
|
||||
VkMemoryOpaqueCaptureAddressAllocateInfo memoryDeviceAddress = {
|
||||
VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO,
|
||||
};
|
||||
if(fakeBackbuffers)
|
||||
{
|
||||
allocInfo.pNext = &memFlags;
|
||||
memFlags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT |
|
||||
VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT;
|
||||
|
||||
memFlags.pNext = &memoryDeviceAddress;
|
||||
memoryDeviceAddress.opaqueCaptureAddress = opaqueMemAddress;
|
||||
}
|
||||
|
||||
vkr = ObjDisp(device)->AllocateMemory(Unwrap(device), &allocInfo, NULL, &mem);
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
if(vkr != VK_SUCCESS)
|
||||
VkResult vkr;
|
||||
if(mem == VK_NULL_HANDLE)
|
||||
{
|
||||
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIReplayFailed,
|
||||
"Failed allocating fake backbuffer texture memory, VkResult: %s",
|
||||
ToStr(vkr).c_str());
|
||||
return false;
|
||||
vkr = ObjDisp(device)->AllocateMemory(Unwrap(device), &allocInfo, NULL, &mem);
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
if(vkr != VK_SUCCESS)
|
||||
{
|
||||
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIReplayFailed,
|
||||
"Failed allocating fake backbuffer texture memory, VkResult: %s",
|
||||
ToStr(vkr).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
memid = GetResourceManager()->WrapResource(Unwrap(device), mem);
|
||||
// register as a live-only resource, so it is cleaned up properly
|
||||
GetResourceManager()->AddLiveResource(memid, mem);
|
||||
}
|
||||
|
||||
ResourceId memid = GetResourceManager()->WrapResource(Unwrap(device), mem);
|
||||
// register as a live-only resource, so it is cleaned up properly
|
||||
GetResourceManager()->AddLiveResource(memid, mem);
|
||||
|
||||
vkr = ObjDisp(device)->BindImageMemory(Unwrap(device), Unwrap(im), Unwrap(mem), 0);
|
||||
vkr = ObjDisp(device)->BindImageMemory(Unwrap(device), Unwrap(ims[i]), Unwrap(mem),
|
||||
imageMemOffsets[i]);
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
// image live ID will be assigned separately in Serialise_vkGetSwapChainInfoWSI
|
||||
// memory doesn't have a live ID
|
||||
|
||||
swapinfo.images[i].im = im;
|
||||
swapinfo.images[i].userSwapImage = ims[i];
|
||||
|
||||
// fill out image info so we track resource state barriers
|
||||
// sneaky-cheeky use of the swapchain's ID here (it's not a live ID because
|
||||
@@ -478,11 +588,11 @@ bool WrappedVulkan::Serialise_vkCreateSwapchainKHR(SerialiserType &ser, VkDevice
|
||||
iminfo.cube = false;
|
||||
iminfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
m_CreationInfo.m_Names[liveId] = StringFormat::Fmt("Presentable Image %u", i);
|
||||
m_CreationInfo.m_Names[GetResID(ims[i])] = StringFormat::Fmt("Presentable Image %u", i);
|
||||
|
||||
{
|
||||
LockedImageStateRef state =
|
||||
InsertImageState(im, liveId, ImageInfo(swapinfo.imageInfo), eFrameRef_Unknown);
|
||||
LockedImageStateRef state = InsertImageState(
|
||||
ims[i], GetResID(ims[i]), ImageInfo(swapinfo.imageInfo), eFrameRef_Unknown);
|
||||
state->isMemoryBound = true;
|
||||
}
|
||||
}
|
||||
@@ -501,17 +611,7 @@ void WrappedVulkan::WrapAndProcessCreatedSwapchain(VkDevice device,
|
||||
{
|
||||
Chunk *chunk = NULL;
|
||||
|
||||
{
|
||||
CACHE_THREAD_SERIALISER();
|
||||
|
||||
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCreateSwapchainKHR);
|
||||
Serialise_vkCreateSwapchainKHR(ser, device, pCreateInfo, NULL, pSwapChain);
|
||||
|
||||
chunk = scope.Get();
|
||||
}
|
||||
|
||||
VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pSwapChain);
|
||||
record->AddChunk(chunk);
|
||||
|
||||
record->swapInfo = new SwapchainInfo();
|
||||
SwapchainInfo &swapInfo = *record->swapInfo;
|
||||
@@ -530,7 +630,123 @@ void WrappedVulkan::WrapAndProcessCreatedSwapchain(VkDevice device,
|
||||
swapInfo.shared = (pCreateInfo->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
|
||||
pCreateInfo->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
|
||||
|
||||
VkResult vkr = VK_SUCCESS;
|
||||
uint32_t numSwapImages = 0;
|
||||
VkResult vkr;
|
||||
|
||||
vkr = ObjDisp(device)->GetSwapchainImagesKHR(Unwrap(device), Unwrap(*pSwapChain),
|
||||
&numSwapImages, NULL);
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
swapInfo.images.resize(numSwapImages);
|
||||
|
||||
const bool fakeBackbuffers = AccelerationStructures() || DescriptorBuffers();
|
||||
|
||||
// create fake images and memory if we're using descriptor buffers so that the user's handles
|
||||
// that views and descriptors are created from are replayable
|
||||
if(fakeBackbuffers)
|
||||
{
|
||||
VkImageCreateFlags imageFlags = DefaultImageCreateFlags();
|
||||
|
||||
if(pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR)
|
||||
imageFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
||||
|
||||
VkImageCreateInfo imInfo = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
NULL,
|
||||
imageFlags,
|
||||
VK_IMAGE_TYPE_2D,
|
||||
pCreateInfo->imageFormat,
|
||||
{pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, 1},
|
||||
1,
|
||||
pCreateInfo->imageArrayLayers,
|
||||
VK_SAMPLE_COUNT_1_BIT,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
// we add SAMPLED_BIT to help hint that views created should be capture/replayable (as
|
||||
// this could be used for a descriptor)
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | pCreateInfo->imageUsage,
|
||||
pCreateInfo->imageSharingMode,
|
||||
pCreateInfo->queueFamilyIndexCount,
|
||||
pCreateInfo->pQueueFamilyIndices,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
};
|
||||
|
||||
if(pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT)
|
||||
{
|
||||
uint32_t *queueFamiles = (uint32_t *)pCreateInfo->pQueueFamilyIndices;
|
||||
for(uint32_t q = 0; q < pCreateInfo->queueFamilyIndexCount; q++)
|
||||
queueFamiles[q] = m_QueueRemapping[queueFamiles[q]][0].family;
|
||||
}
|
||||
|
||||
uint64_t memOffs = 0;
|
||||
uint32_t memIndices = ~0U;
|
||||
for(uint32_t i = 0; i < numSwapImages; i++)
|
||||
{
|
||||
vkr = ObjDisp(device)->CreateImage(Unwrap(device), &imInfo, NULL,
|
||||
&swapInfo.images[i].userSwapImage);
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
if(vkr != VK_SUCCESS)
|
||||
{
|
||||
RDCERR("Failed creating fake backbuffer textures, VkResult: %s", ToStr(vkr).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// we don't wrap the image, vkGetSwapchainImagesKHR below will do that
|
||||
|
||||
VkMemoryRequirements mrq = {0};
|
||||
ObjDisp(device)->GetImageMemoryRequirements(Unwrap(device),
|
||||
swapInfo.images[i].userSwapImage, &mrq);
|
||||
|
||||
memOffs = AlignUp(memOffs, mrq.alignment);
|
||||
swapInfo.images[i].fakeImageMemoryOffset = memOffs;
|
||||
|
||||
memOffs += mrq.size;
|
||||
memIndices &= mrq.memoryTypeBits;
|
||||
}
|
||||
|
||||
VkMemoryAllocateFlagsInfo memFlags = {
|
||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
|
||||
NULL,
|
||||
VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT | VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT,
|
||||
};
|
||||
VkMemoryAllocateInfo allocInfo = {
|
||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
&memFlags,
|
||||
memOffs,
|
||||
GetGPULocalMemoryIndex(memIndices),
|
||||
};
|
||||
|
||||
vkr = ObjDisp(device)->AllocateMemory(Unwrap(device), &allocInfo, NULL, &swapInfo.imageMemory);
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
if(vkr != VK_SUCCESS)
|
||||
{
|
||||
RDCERR("Failed allocating fake backbuffer texture memory, VkResult: %s", ToStr(vkr).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
GetResourceManager()->WrapResource(Unwrap(device), swapInfo.imageMemory);
|
||||
GetResourceManager()->SetInternalResource(GetResID(swapInfo.imageMemory));
|
||||
|
||||
for(uint32_t i = 0; i < numSwapImages; i++)
|
||||
{
|
||||
vkr = ObjDisp(device)->BindImageMemory(Unwrap(device), swapInfo.images[i].userSwapImage,
|
||||
Unwrap(swapInfo.imageMemory),
|
||||
swapInfo.images[i].fakeImageMemoryOffset);
|
||||
CHECK_VKR(this, vkr);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
CACHE_THREAD_SERIALISER();
|
||||
|
||||
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCreateSwapchainKHR);
|
||||
Serialise_vkCreateSwapchainKHR(ser, device, pCreateInfo, NULL, pSwapChain);
|
||||
|
||||
chunk = scope.Get();
|
||||
}
|
||||
record->AddChunk(chunk);
|
||||
|
||||
const VkDevDispatchTable *vt = ObjDisp(device);
|
||||
|
||||
@@ -579,26 +795,11 @@ void WrappedVulkan::WrapAndProcessCreatedSwapchain(VkDevice device,
|
||||
|
||||
// serialise out the swap chain images
|
||||
{
|
||||
uint32_t numSwapImages;
|
||||
vkr = vt->GetSwapchainImagesKHR(Unwrap(device), Unwrap(*pSwapChain), &numSwapImages, NULL);
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
swapInfo.lastPresent.imageIndex = 0;
|
||||
swapInfo.lastPresent.presentQueue = VK_NULL_HANDLE;
|
||||
swapInfo.lastPresent.waitSemaphores.clear();
|
||||
|
||||
swapInfo.images.resize(numSwapImages);
|
||||
for(uint32_t i = 0; i < numSwapImages; i++)
|
||||
{
|
||||
swapInfo.images[i].im = VK_NULL_HANDLE;
|
||||
swapInfo.images[i].view = VK_NULL_HANDLE;
|
||||
swapInfo.images[i].fb = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
VkImage *images = new VkImage[numSwapImages];
|
||||
rdcarray<VkImage> images;
|
||||
images.resize(numSwapImages);
|
||||
|
||||
// go through our own function so we assign these images IDs
|
||||
vkr = vkGetSwapchainImagesKHR(device, *pSwapChain, &numSwapImages, images);
|
||||
vkr = vkGetSwapchainImagesKHR(device, *pSwapChain, &numSwapImages, images.data());
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
for(uint32_t i = 0; i < numSwapImages; i++)
|
||||
@@ -606,7 +807,7 @@ void WrappedVulkan::WrapAndProcessCreatedSwapchain(VkDevice device,
|
||||
SwapchainInfo::SwapImage &swapImInfo = swapInfo.images[i];
|
||||
|
||||
// memory doesn't exist for genuine WSI created images
|
||||
swapImInfo.im = images[i];
|
||||
swapImInfo.userSwapImage = images[i];
|
||||
|
||||
ResourceId imid = GetResID(images[i]);
|
||||
|
||||
@@ -649,12 +850,16 @@ void WrappedVulkan::WrapAndProcessCreatedSwapchain(VkDevice device,
|
||||
GetResourceManager()->SetInternalResource(GetResID(swapImInfo.overlaydone));
|
||||
}
|
||||
|
||||
VkImage renderImage = Unwrap(images[i]);
|
||||
if(swapImInfo.unwrappedRealSwapImage != VK_NULL_HANDLE)
|
||||
renderImage = swapImInfo.unwrappedRealSwapImage;
|
||||
|
||||
{
|
||||
VkImageViewCreateInfo info = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
NULL,
|
||||
DefaultImageViewCreateFlags(),
|
||||
Unwrap(images[i]),
|
||||
renderImage,
|
||||
VK_IMAGE_VIEW_TYPE_2D,
|
||||
pCreateInfo->imageFormat,
|
||||
{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
@@ -687,8 +892,6 @@ void WrappedVulkan::WrapAndProcessCreatedSwapchain(VkDevice device,
|
||||
GetResourceManager()->SetInternalResource(GetResID(swapImInfo.fb));
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY(images);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -756,7 +959,7 @@ bool WrappedVulkan::Serialise_vkQueuePresentKHR(SerialiserType &ser, VkQueue que
|
||||
const bool activeWindow = RenderDoc::Inst().IsActiveWindow(devWnd);
|
||||
|
||||
if(activeWindow || PresentedImage == ResourceId())
|
||||
PresentedImage = GetResID(swapInfo.images[pPresentInfo->pImageIndices[i]].im);
|
||||
PresentedImage = GetResID(swapInfo.images[pPresentInfo->pImageIndices[i]].userSwapImage);
|
||||
|
||||
if(activeWindow)
|
||||
break;
|
||||
@@ -971,10 +1174,13 @@ void WrappedVulkan::HandlePresent(VkQueue queue, const VkPresentInfoKHR *pPresen
|
||||
{
|
||||
uint32_t overlay = RenderDoc::Inst().GetOverlayBits();
|
||||
|
||||
const bool fakeBackbuffers = AccelerationStructures() || DescriptorBuffers();
|
||||
|
||||
if(overlay & eRENDERDOC_Overlay_Enabled)
|
||||
{
|
||||
VkRenderPass rp = swapInfo.rp;
|
||||
VkImage im = swapInfo.images[imgIndex].im;
|
||||
VkImage unwrappedRealSwapImage = swapInfo.images[imgIndex].unwrappedRealSwapImage;
|
||||
VkImage userSwapImage = swapInfo.images[imgIndex].userSwapImage;
|
||||
VkFramebuffer fb = swapInfo.images[imgIndex].fb;
|
||||
VkCommandBuffer cmd = swapInfo.images[imgIndex].cmd;
|
||||
VkFence imfence = swapInfo.images[imgIndex].fence;
|
||||
@@ -1010,29 +1216,55 @@ void WrappedVulkan::HandlePresent(VkQueue queue, const VkPresentInfoKHR *pPresen
|
||||
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
VkImageLayout presentLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
|
||||
if(swapInfo.shared)
|
||||
presentLayout = VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR;
|
||||
|
||||
VkImageMemoryBarrier bbBarrier = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
presentLayout,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
swapQueueIndex,
|
||||
m_QueueFamilyIdx,
|
||||
Unwrap(im),
|
||||
Unwrap(userSwapImage),
|
||||
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
|
||||
};
|
||||
|
||||
if(swapInfo.shared)
|
||||
bbBarrier.oldLayout = VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR;
|
||||
|
||||
if(swapInfo.concurrent)
|
||||
bbBarrier.srcQueueFamilyIndex = bbBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
|
||||
bbBarrier.srcAccessMask = VK_ACCESS_ALL_READ_BITS;
|
||||
bbBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
bbBarrier.srcAccessMask = VK_ACCESS_ALL_READ_BITS | VK_ACCESS_ALL_WRITE_BITS;
|
||||
|
||||
DoPipelineBarrier(cmd, 1, &bbBarrier);
|
||||
// if using descriptor buffers, we barrier both images - real and fake backbuffer to be ready
|
||||
// to copy from fake to real
|
||||
if(fakeBackbuffers)
|
||||
{
|
||||
bbBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
// we fully overwrite with a copy, so we can transition from undefined
|
||||
bbBarrier.image = unwrappedRealSwapImage;
|
||||
bbBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
bbBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
|
||||
DoPipelineBarrier(cmd, 1, &bbBarrier);
|
||||
|
||||
bbBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
|
||||
bbBarrier.image = Unwrap(userSwapImage);
|
||||
bbBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
bbBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
DoPipelineBarrier(cmd, 1, &bbBarrier);
|
||||
}
|
||||
else
|
||||
{
|
||||
bbBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
DoPipelineBarrier(cmd, 1, &bbBarrier);
|
||||
}
|
||||
|
||||
rdcarray<VkPipelineStageFlags> waitStage;
|
||||
waitStage.fill(unwrappedWaitSems.size(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
||||
@@ -1067,7 +1299,28 @@ void WrappedVulkan::HandlePresent(VkQueue queue, const VkPresentInfoKHR *pPresen
|
||||
vkr = vt->BeginCommandBuffer(Unwrap(extQCmd), &beginInfo);
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
DoPipelineBarrier(extQCmd, 1, &bbBarrier);
|
||||
// if using fake backbuffers, we barrier both images - real and fake backbuffer
|
||||
if(fakeBackbuffers)
|
||||
{
|
||||
bbBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
bbBarrier.image = unwrappedRealSwapImage;
|
||||
bbBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
bbBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
|
||||
DoPipelineBarrier(extQCmd, 1, &bbBarrier);
|
||||
|
||||
bbBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
|
||||
bbBarrier.image = Unwrap(userSwapImage);
|
||||
bbBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
bbBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
DoPipelineBarrier(extQCmd, 1, &bbBarrier);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoPipelineBarrier(extQCmd, 1, &bbBarrier);
|
||||
}
|
||||
|
||||
ObjDisp(extQCmd)->EndCommandBuffer(Unwrap(extQCmd));
|
||||
|
||||
@@ -1107,6 +1360,30 @@ void WrappedVulkan::HandlePresent(VkQueue queue, const VkPresentInfoKHR *pPresen
|
||||
overlayText += StringFormat::Fmt("\nCapture failed: %s",
|
||||
ResultDetails(m_LastCaptureError).Message().c_str());
|
||||
|
||||
if(fakeBackbuffers)
|
||||
{
|
||||
VkImageCopy region = {};
|
||||
region.dstSubresource.aspectMask = region.srcSubresource.aspectMask =
|
||||
VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.dstSubresource.layerCount = region.srcSubresource.layerCount = 1;
|
||||
region.extent = swapInfo.imageInfo.extent;
|
||||
ObjDisp(cmd)->CmdCopyImage(Unwrap(cmd), Unwrap(userSwapImage),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, unwrappedRealSwapImage,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
VkImageMemoryBarrier tmpBarrier = bbBarrier;
|
||||
// remove any queue family transfer
|
||||
tmpBarrier.srcQueueFamilyIndex = tmpBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
|
||||
// now do what the barrier above would have done, put the real swapchain in color attachment ready to render to
|
||||
tmpBarrier.image = unwrappedRealSwapImage;
|
||||
tmpBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
tmpBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
tmpBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
tmpBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
DoPipelineBarrier(cmd, 1, &tmpBarrier);
|
||||
}
|
||||
|
||||
if(!overlayText.empty())
|
||||
{
|
||||
m_TextRenderer->BeginText(textstate);
|
||||
@@ -1118,10 +1395,31 @@ void WrappedVulkan::HandlePresent(VkQueue queue, const VkPresentInfoKHR *pPresen
|
||||
|
||||
std::swap(bbBarrier.srcQueueFamilyIndex, bbBarrier.dstQueueFamilyIndex);
|
||||
std::swap(bbBarrier.oldLayout, bbBarrier.newLayout);
|
||||
bbBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
bbBarrier.dstAccessMask = VK_ACCESS_ALL_READ_BITS;
|
||||
|
||||
DoPipelineBarrier(textstate.cmd, 1, &bbBarrier);
|
||||
if(fakeBackbuffers)
|
||||
{
|
||||
bbBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
bbBarrier.image = unwrappedRealSwapImage;
|
||||
bbBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
bbBarrier.newLayout = presentLayout;
|
||||
|
||||
DoPipelineBarrier(textstate.cmd, 1, &bbBarrier);
|
||||
|
||||
bbBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
|
||||
bbBarrier.image = Unwrap(userSwapImage);
|
||||
bbBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
bbBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
DoPipelineBarrier(textstate.cmd, 1, &bbBarrier);
|
||||
}
|
||||
else
|
||||
{
|
||||
bbBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
DoPipelineBarrier(textstate.cmd, 1, &bbBarrier);
|
||||
}
|
||||
|
||||
ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
|
||||
|
||||
@@ -1141,7 +1439,29 @@ void WrappedVulkan::HandlePresent(VkQueue queue, const VkPresentInfoKHR *pPresen
|
||||
vkr = vt->BeginCommandBuffer(Unwrap(extQCmd), &beginInfo);
|
||||
CHECK_VKR(this, vkr);
|
||||
|
||||
DoPipelineBarrier(extQCmd, 1, &bbBarrier);
|
||||
if(fakeBackbuffers)
|
||||
{
|
||||
bbBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
bbBarrier.image = unwrappedRealSwapImage;
|
||||
bbBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
bbBarrier.newLayout = presentLayout;
|
||||
|
||||
DoPipelineBarrier(extQCmd, 1, &bbBarrier);
|
||||
|
||||
bbBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
|
||||
bbBarrier.image = Unwrap(userSwapImage);
|
||||
bbBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
bbBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
DoPipelineBarrier(extQCmd, 1, &bbBarrier);
|
||||
}
|
||||
else
|
||||
{
|
||||
bbBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
DoPipelineBarrier(extQCmd, 1, &bbBarrier);
|
||||
}
|
||||
|
||||
ObjDisp(extQCmd)->EndCommandBuffer(Unwrap(extQCmd));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user