Add new image tracking to replay side

Change-Id: I67ef6b1f6fd9b84621ec6700a8260c24afb35a05
This commit is contained in:
Benson Joeris
2020-01-27 20:44:54 +00:00
committed by Baldur Karlsson
parent 1d44386724
commit cb66100840
17 changed files with 513 additions and 753 deletions
+23 -83
View File
@@ -360,89 +360,6 @@ void WrappedVulkan::FlushQ()
}
}
void WrappedVulkan::TempTransition(VkImage image, VkImageLayout layout, VkAccessFlags access,
rdcarray<VkImageMemoryBarrier> &setupBarriers,
rdcarray<VkImageMemoryBarrier> &cleanupBarriers,
bool &extQCleanup) const
{
ResourceId id = GetResID(image);
auto it = m_ImageLayouts.find(id);
if(it == m_ImageLayouts.end())
{
RDCERR("Can't find image layouts for image %s in TempTransition", ToStr(id).c_str());
return;
}
setupBarriers.clear();
cleanupBarriers.clear();
const ImageLayouts &layouts = it->second;
VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
barrier.image = Unwrap(image);
barrier.newLayout = layout;
barrier.srcQueueFamilyIndex = layouts.queueFamilyIndex;
barrier.dstQueueFamilyIndex = GetQueueFamilyIndex();
extQCleanup = true;
// if we're on the same queue, don't need to bother with queue acquire/release
if(barrier.srcQueueFamilyIndex == barrier.dstQueueFamilyIndex)
{
barrier.srcQueueFamilyIndex = barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
extQCleanup = false;
}
barrier.dstAccessMask = access;
for(const ImageRegionState &region : layouts.subresourceStates)
{
barrier.subresourceRange = region.subresourceRange;
barrier.oldLayout = region.newLayout;
barrier.srcAccessMask = VK_ACCESS_ALL_WRITE_BITS | MakeAccessMask(barrier.oldLayout);
SanitiseOldImageLayout(barrier.oldLayout);
setupBarriers.push_back(barrier);
}
if(SeparateDepthStencil())
CombineDepthStencilLayouts(setupBarriers);
cleanupBarriers = setupBarriers;
for(VkImageMemoryBarrier &b : cleanupBarriers)
{
std::swap(b.srcQueueFamilyIndex, b.dstQueueFamilyIndex);
std::swap(b.oldLayout, b.newLayout);
SanitiseNewImageLayout(b.newLayout);
b.srcAccessMask = access;
b.dstAccessMask = VK_ACCESS_ALL_READ_BITS | MakeAccessMask(b.newLayout);
}
// if we have some queue transfer to do, submit the release on the ext queue now (which is what we
// defined above). The user will have to check the bool themselves and submit cleanupBarriers as
// external after they're done and submitted on the main queue
if(extQCleanup)
{
VkCommandBuffer extQCmd = GetExtQueueCmd(barrier.srcQueueFamilyIndex);
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT};
VkResult vkr = ObjDisp(extQCmd)->BeginCommandBuffer(Unwrap(extQCmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
DoPipelineBarrier(extQCmd, setupBarriers.size(), setupBarriers.data());
vkr = ObjDisp(extQCmd)->EndCommandBuffer(Unwrap(extQCmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
SubmitAndFlushExtQueue(layouts.queueFamilyIndex);
}
}
VkCommandBuffer WrappedVulkan::GetExtQueueCmd(uint32_t queueFamilyIdx) const
{
if(queueFamilyIdx >= m_ExternalQueues.size())
@@ -2443,8 +2360,10 @@ ReplayStatus WrappedVulkan::ContextReplayLog(CaptureState readType, uint32_t sta
ApplyInitialContents();
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();
SubmitAndFlushImageStateBarriers(m_cleanupImageBarriers);
SetDebugMessageSink(sink);
}
@@ -2661,6 +2580,19 @@ void WrappedVulkan::ApplyInitialContents()
// actually apply the initial contents here
GetResourceManager()->ApplyInitialContents();
for(auto it = m_ImageStates.begin(); it != m_ImageStates.end(); ++it)
{
if(GetResourceManager()->HasCurrentResource(it->first))
{
it->second.LockWrite()->ResetToOldState(m_cleanupImageBarriers, GetImageTransitionInfo());
}
else
{
it = m_ImageStates.erase(it);
--it;
}
}
// likewise again to make sure the initial states are all applied
cmd = GetNextCmd();
@@ -2673,7 +2605,10 @@ void WrappedVulkan::ApplyInitialContents()
RDCASSERTEQUAL(vkr, VK_SUCCESS);
#if ENABLED(SINGLE_FLUSH_VALIDATE)
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();
SubmitAndFlushImageStateBarriers(m_cleanupImageBarriers);
#endif
}
@@ -3168,8 +3103,10 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay
ApplyInitialContents();
VkMarkerRegion::End();
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();
SubmitAndFlushImageStateBarriers(m_cleanupImageBarriers);
}
m_State = CaptureState::ActiveReplaying;
@@ -3287,7 +3224,10 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay
}
#if ENABLED(SINGLE_FLUSH_VALIDATE)
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();
SubmitAndFlushImageStateBarriers(m_cleanupImageBarriers);
#endif
}
-12
View File
@@ -577,7 +577,6 @@ private:
} state;
std::map<ResourceId, ImageState> imageStates;
rdcarray<rdcpair<ResourceId, ImageRegionState>> imgbarriers;
ResourceId pushDescriptorID[2][64];
@@ -763,9 +762,6 @@ private:
std::map<ResourceId, LockingImageState> m_ImageStates;
Threading::CriticalSection m_ImageStatesLock;
std::map<ResourceId, ImageLayouts> m_ImageLayouts;
Threading::CriticalSection m_ImageLayoutsLock;
// find swapchain for an image
std::map<RENDERDOC_WindowHandle, VkSwapchainKHR> m_SwapLookup;
Threading::CriticalSection m_SwapLookupLock;
@@ -931,10 +927,6 @@ private:
int32_t messageCode, const char *pLayerPrefix,
const char *pMessage, void *pUserData);
void AddFrameTerminator(uint64_t queueMarkerTag);
void ImageInitializationBarriers(ResourceId id, WrappedVkRes *live, InitPolicy policy,
bool initialized, const ImgRefs *imgRefs,
rdcarray<VkImageMemoryBarrier> &setupBarriers,
rdcarray<VkImageMemoryBarrier> &cleanupBarriers) const;
void SubmitExtQBarriers(const std::map<uint32_t, rdcarray<VkImageMemoryBarrier>> &extQBarriers);
void SubmitExtQBarriers(uint32_t queueFamilyIndex,
const rdcarray<VkImageMemoryBarrier> &queueFamilyBarriers);
@@ -1028,10 +1020,6 @@ public:
void SubmitSemaphores();
void FlushQ();
void TempTransition(VkImage image, VkImageLayout layout, VkAccessFlags access,
rdcarray<VkImageMemoryBarrier> &setupBarriers,
rdcarray<VkImageMemoryBarrier> &cleanupBarriers, bool &extQCleanup) const;
bool SeparateDepthStencil() const { return m_SeparateDepthStencil; }
VulkanRenderState &GetRenderState() { return m_RenderState; }
void SetDrawcallCB(VulkanDrawcallCallback *cb) { m_DrawcallCallback = cb; }
+4 -17
View File
@@ -881,22 +881,6 @@ void VulkanDebugManager::CreateCustomShaderTex(uint32_t width, uint32_t height,
// need to update image layout into valid state
VkImageMemoryBarrier barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
NULL,
0,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
Unwrap(m_Custom.TexImg),
{VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0, 1},
};
m_pDriver->m_ImageLayouts[GetResID(m_Custom.TexImg)].subresourceStates[0].newLayout =
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
@@ -904,7 +888,10 @@ void VulkanDebugManager::CreateCustomShaderTex(uint32_t width, uint32_t height,
ObjDisp(dev)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
DoPipelineBarrier(cmd, 1, &barrier);
m_pDriver->FindImageState(GetResID(m_Custom.TexImg))
->InlineTransition(cmd, m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
m_pDriver->GetImageTransitionInfo());
vkr = ObjDisp(dev)->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
+2 -1
View File
@@ -86,7 +86,8 @@ public:
void PixelHistoryCopyPixel(VkCommandBuffer cmd, CopyPixelParams &p, size_t offset);
VkImageLayout GetImageLayout(ResourceId image, VkImageAspectFlags aspect, uint32_t mip);
VkImageLayout GetImageLayout(ResourceId image, VkImageAspectFlagBits aspect, uint32_t mip,
uint32_t slice);
const VulkanCreationInfo::Image &GetImageInfo(ResourceId img);
+75 -221
View File
@@ -1208,22 +1208,21 @@ void WrappedVulkan::Create_InitialState(ResourceId id, WrappedVkRes *live, bool
{
ResourceId liveid = GetResourceManager()->GetLiveID(id);
if(m_ImageLayouts.find(liveid) == m_ImageLayouts.end())
VkInitialContents::Tag tag = VkInitialContents::ClearColorImage;
LockedImageStateRef state = FindImageState(liveid);
if(!state)
{
RDCERR("Couldn't find image info for %llu", id);
RDCERR("Couldn't find image info for %s", ToStr(id).c_str());
GetResourceManager()->SetInitialContents(
id, VkInitialContents(type, VkInitialContents::ClearColorImage));
return;
}
else if(IsDepthOrStencilFormat(state->GetImageInfo().format))
{
tag = VkInitialContents::ClearDepthStencilImage;
}
ImageLayouts &layouts = m_ImageLayouts[liveid];
if(!IsDepthOrStencilFormat(layouts.imageInfo.format))
GetResourceManager()->SetInitialContents(
id, VkInitialContents(type, VkInitialContents::ClearColorImage));
else
GetResourceManager()->SetInitialContents(
id, VkInitialContents(type, VkInitialContents::ClearDepthStencilImage));
GetResourceManager()->SetInitialContents(id, VkInitialContents(type, tag));
}
else if(type == eResDeviceMemory)
{
@@ -1235,121 +1234,6 @@ void WrappedVulkan::Create_InitialState(ResourceId id, WrappedVkRes *live, bool
}
}
void WrappedVulkan::ImageInitializationBarriers(ResourceId id, WrappedVkRes *live, InitPolicy policy,
bool initialized, const ImgRefs *imgRefs,
rdcarray<VkImageMemoryBarrier> &setupBarriers,
rdcarray<VkImageMemoryBarrier> &cleanupBarriers) const
{
// For each subresource that will be initialized (either copy or fill), create barriers that will
// transition the subresource from UNDEFINED to TRANSFER_DST_OPTIMAL before the write (in
// `setupBarriers`), and barriers to transition the subresource from TRANSFER_DST_OPTIMAL back to
// the current layout (`cleanupBarriers`). `cleanupBarriers` will also transfer ownership back to
// the correct queues, if necessary.
const ImageLayouts &imageLayouts = m_ImageLayouts.at(id);
for(size_t si = 0; si < imageLayouts.subresourceStates.size(); si++)
{
VkImageMemoryBarrier barrier = {
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,
ToUnwrappedHandle<VkImage>(live),
imageLayouts.subresourceStates[si].subresourceRange,
};
if(IsDepthAndStencilFormat(imageLayouts.imageInfo.format) && !SeparateDepthStencil())
{
if(barrier.subresourceRange.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
{
// There will be a different subresourceState with DEPTH aspect, which is when we will
// handle both the depth and stencil aspects.
continue;
}
else
{
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
}
}
VkImageMemoryBarrier revBarrier = barrier;
revBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
revBarrier.newLayout = imageLayouts.subresourceStates[si].newLayout;
SanitiseNewImageLayout(revBarrier.newLayout);
revBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
revBarrier.dstAccessMask = VK_ACCESS_ALL_READ_BITS | MakeAccessMask(revBarrier.newLayout);
if(imageLayouts.queueFamilyIndex != m_QueueFamilyIdx)
{
revBarrier.srcQueueFamilyIndex = m_QueueFamilyIdx;
revBarrier.dstQueueFamilyIndex = imageLayouts.queueFamilyIndex;
}
if(!initialized)
{
setupBarriers.push_back(barrier);
cleanupBarriers.push_back(revBarrier);
}
else
{
if(IsDepthAndStencilFormat(imageLayouts.imageInfo.format) && SeparateDepthStencil())
{
// process as if we're looking at both aspects in a depth/stencil format whenever we see
// either. If both are already separate, we need to transition them separately
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
}
auto initReqs =
imgRefs->SubresourceRangeInitReqs(barrier.subresourceRange, policy, initialized);
for(auto initIt = initReqs.begin(); initIt != initReqs.end(); ++initIt)
{
barrier.subresourceRange = revBarrier.subresourceRange = initIt->first;
InitReqType initReq = initIt->second;
if(IsDepthAndStencilFormat(imageLayouts.imageInfo.format))
{
if(SeparateDepthStencil())
{
// conservatively set init requirements for both aspects whenever we see either aspect.
barrier.subresourceRange.aspectMask = revBarrier.subresourceRange.aspectMask =
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
initReq =
imgRefs->SubresourceRangeMaxInitReq(barrier.subresourceRange, policy, initialized);
// but transition the original aspect. These barriers will be combined if identical
barrier.subresourceRange.aspectMask = revBarrier.subresourceRange.aspectMask =
imageLayouts.subresourceStates[si].subresourceRange.aspectMask;
}
else
{
if(barrier.subresourceRange.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
{
// There will be a different subresourceState with DEPTH aspect, which is when we will
// handle both the depth and stencil aspects.
continue;
}
else if(barrier.subresourceRange.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT)
{
barrier.subresourceRange.aspectMask = revBarrier.subresourceRange.aspectMask =
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
initReq =
imgRefs->SubresourceRangeMaxInitReq(barrier.subresourceRange, policy, initialized);
}
}
}
if(initReq != eInitReq_None)
{
setupBarriers.push_back(barrier);
cleanupBarriers.push_back(revBarrier);
}
}
}
}
}
std::map<uint32_t, rdcarray<VkImageMemoryBarrier> > GetExtQBarriers(
const rdcarray<VkImageMemoryBarrier> &barriers)
{
@@ -1466,22 +1350,25 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT};
ResourceId orig = GetResourceManager()->GetOriginalID(id);
ImgRefs *imgRefs = GetResourceManager()->FindImgRefs(orig);
bool initialized = false;
InitPolicy policy = GetResourceManager()->GetInitPolicy();
if(imgRefs)
LockedImageStateRef state = FindImageState(id);
if(!state)
{
initialized = imgRefs->initializedLiveRes == live;
imgRefs->initializedLiveRes = live;
RDCWARN("No image state found for image %s", ToStr(id).c_str());
return;
}
ResourceId boundMemory = state->boundMemory;
VkDeviceSize boundMemoryOffset = state->boundMemoryOffset;
VkDeviceSize boundMemorySize = state->boundMemorySize;
const ImageInfo &imageInfo = state->GetImageInfo();
initialized = IsActiveReplaying(m_State);
ImageLayouts &layout = m_ImageLayouts[id];
if(initialized && layout.boundMemory != ResourceId())
if(initialized && boundMemory != ResourceId())
{
ResourceId origMem = GetResourceManager()->GetOriginalID(layout.boundMemory);
ResourceId origMem = GetResourceManager()->GetOriginalID(boundMemory);
if(origMem != ResourceId())
{
MemRefs *memRefs = GetResourceManager()->FindMemRefs(origMem);
@@ -1497,9 +1384,8 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
}
else
{
for(auto it = memRefs->rangeRefs.find(layout.boundMemoryOffset);
it != memRefs->rangeRefs.end() &&
it->start() < layout.boundMemoryOffset + layout.boundMemorySize;
for(auto it = memRefs->rangeRefs.find(boundMemoryOffset);
it != memRefs->rangeRefs.end() && it->start() < boundMemoryOffset + boundMemorySize;
++it)
{
if(IncludesWrite(it->value()) ||
@@ -1526,7 +1412,7 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
{
if(initial.tag == VkInitialContents::ClearColorImage)
{
VkFormat format = layout.imageInfo.format;
VkFormat format = imageInfo.format;
// can't clear these, so leave them alone.
if(IsBlockFormat(format) || IsYUVFormat(format))
@@ -1537,11 +1423,12 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
rdcarray<VkImageMemoryBarrier> setupBarriers, cleanupBarriers;
bool extQCleanup = false;
TempTransition(ToWrappedHandle<VkImage>(live), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_ACCESS_TRANSFER_WRITE_BIT, setupBarriers, cleanupBarriers, extQCleanup);
DoPipelineBarrier(cmd, setupBarriers.size(), setupBarriers.data());
ImageBarrierSequence setupBarriers;
state->DiscardContents();
state->Transition(m_QueueFamilyIdx, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0,
VK_ACCESS_TRANSFER_WRITE_BIT, setupBarriers, GetImageTransitionInfo());
InlineSetupImageBarriers(cmd, setupBarriers);
m_setupImageBarriers.Merge(setupBarriers);
VkClearColorValue clearval = {};
VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0,
@@ -1550,63 +1437,43 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
ObjDisp(cmd)->CmdClearColorImage(Unwrap(cmd), ToUnwrappedHandle<VkImage>(live),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearval, 1, &range);
DoPipelineBarrier(cmd, cleanupBarriers.size(), cleanupBarriers.data());
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
if(extQCleanup)
{
// ensure work is completed before we pass ownership back to original queue
SubmitCmds();
FlushQ();
SubmitExtQBarriers(~0U, cleanupBarriers);
}
#if ENABLED(SINGLE_FLUSH_VALIDATE)
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();
SubmitAndFlushImageStateBarriers(m_cleanupImageBarriers);
#endif
}
else if(initial.tag == VkInitialContents::ClearDepthStencilImage)
{
VkFormat format = layout.imageInfo.format;
VkCommandBuffer cmd = GetNextCmd();
vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
rdcarray<VkImageMemoryBarrier> setupBarriers, cleanupBarriers;
bool extQCleanup = false;
TempTransition(ToWrappedHandle<VkImage>(live), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_ACCESS_TRANSFER_WRITE_BIT, setupBarriers, cleanupBarriers, extQCleanup);
DoPipelineBarrier(cmd, setupBarriers.size(), setupBarriers.data());
ImageBarrierSequence setupBarriers; // , cleanupBarriers;
state->DiscardContents();
state->Transition(m_QueueFamilyIdx, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0,
VK_ACCESS_TRANSFER_WRITE_BIT, setupBarriers, GetImageTransitionInfo());
InlineSetupImageBarriers(cmd, setupBarriers);
m_setupImageBarriers.Merge(setupBarriers);
VkClearDepthStencilValue clearval = {1.0f, 0};
VkImageSubresourceRange range = {FormatImageAspects(format), 0, VK_REMAINING_MIP_LEVELS, 0,
VK_REMAINING_ARRAY_LAYERS};
VkImageSubresourceRange range = imageInfo.FullRange();
ObjDisp(cmd)->CmdClearDepthStencilImage(Unwrap(cmd), ToUnwrappedHandle<VkImage>(live),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearval, 1,
&range);
DoPipelineBarrier(cmd, cleanupBarriers.size(), cleanupBarriers.data());
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
if(extQCleanup)
{
// ensure work is completed before we pass ownership back to original queue
SubmitCmds();
FlushQ();
SubmitExtQBarriers(~0U, cleanupBarriers);
}
#if ENABLED(SINGLE_FLUSH_VALIDATE)
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();
SubmitAndFlushImageStateBarriers(m_cleanupImageBarriers);
#endif
}
else
@@ -1628,12 +1495,13 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
VkFormat fmt = c.format;
rdcarray<VkImageMemoryBarrier> setupBarriers, cleanupBarriers;
bool extQCleanup = false;
TempTransition(ToWrappedHandle<VkImage>(live), VK_IMAGE_LAYOUT_GENERAL,
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
setupBarriers, cleanupBarriers, extQCleanup);
DoPipelineBarrier(cmd, setupBarriers.size(), setupBarriers.data());
ImageBarrierSequence setupBarriers; // , cleanupBarriers;
state->DiscardContents();
state->Transition(m_QueueFamilyIdx, VK_IMAGE_LAYOUT_GENERAL, 0,
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
setupBarriers, GetImageTransitionInfo());
InlineSetupImageBarriers(cmd, setupBarriers);
m_setupImageBarriers.Merge(setupBarriers);
VkImage arrayIm = initial.img;
@@ -1649,22 +1517,13 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
DoPipelineBarrier(cmd, cleanupBarriers.size(), cleanupBarriers.data());
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
if(extQCleanup)
{
// ensure work is completed before we pass ownership back to original queue
SubmitCmds();
FlushQ();
SubmitExtQBarriers(~0U, cleanupBarriers);
}
#if ENABLED(SINGLE_FLUSH_VALIDATE)
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();
SubmitAndFlushImageStateBarriers(m_cleanupImageBarriers);
#endif
return;
}
@@ -1719,17 +1578,11 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
}
}
rdcarray<VkImageMemoryBarrier> setupBarriers, cleanupBarriers;
ImageInitializationBarriers(id, live, policy, initialized, imgRefs, setupBarriers,
cleanupBarriers);
if(SeparateDepthStencil())
{
CombineDepthStencilLayouts(setupBarriers);
CombineDepthStencilLayouts(cleanupBarriers);
}
DoPipelineBarrier(cmd, setupBarriers.size(), setupBarriers.data());
SubmitExtQBarriers(GetExtQBarriers(setupBarriers));
ImageBarrierSequence setupBarriers;
state->Transition(m_QueueFamilyIdx, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0,
VK_ACCESS_TRANSFER_WRITE_BIT, setupBarriers, GetImageTransitionInfo());
InlineSetupImageBarriers(cmd, setupBarriers);
m_setupImageBarriers.Merge(setupBarriers);
VkDeviceSize bufOffset = 0;
@@ -1781,9 +1634,13 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
bufOffset += GetPlaneByteSize(extent.width, extent.height, extent.depth, fmt, 0, i);
if(!initialized)
{
initReq = eInitReq_Copy;
}
else
initReq = imgRefs->SubresourceRangeMaxInitReq(range, policy, initialized);
{
initReq = state->MaxInitReq(range, policy, initialized);
}
if(initReq == eInitReq_Copy)
copyRegions.push_back(region);
else if(initReq == eInitReq_Clear)
@@ -1797,9 +1654,13 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
if(!initialized)
{
initReq = eInitReq_Copy;
}
else
initReq = imgRefs->SubresourceRangeMaxInitReq(range, policy, initialized);
{
initReq = state->MaxInitReq(range, policy, initialized);
}
if(initReq == eInitReq_None)
continue;
@@ -1838,9 +1699,13 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
bufOffset += GetByteSize(extent.width, extent.height, extent.depth, fmt, 0);
if(!initialized)
{
initReq = eInitReq_Copy;
}
else
initReq = imgRefs->SubresourceRangeMaxInitReq(range, policy, initialized);
{
initReq = state->MaxInitReq(range, policy, initialized);
}
if(initReq == eInitReq_Copy)
copyRegions.push_back(region);
else if(initReq == eInitReq_Clear)
@@ -1878,24 +1743,13 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
}
}
DoPipelineBarrier(cmd, cleanupBarriers.size(), cleanupBarriers.data());
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
std::map<uint32_t, rdcarray<VkImageMemoryBarrier> > extQBarriers =
GetExtQBarriers(cleanupBarriers);
if(extQBarriers.size() > 0)
{
// ensure work is completed before we pass ownership back to original queue
SubmitCmds();
FlushQ();
SubmitExtQBarriers(extQBarriers);
}
#if ENABLED(SINGLE_FLUSH_VALIDATE)
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();
SubmitAndFlushImageStateBarriers(m_cleanupImageBarriers);
#endif
}
else if(type == eResDeviceMemory)
+7 -13
View File
@@ -285,6 +285,8 @@ void VulkanResourceManager::SerialiseImageStates(SerialiserType &ser,
}
else
{
bool hasLiveRes = HasLiveResource(Image);
ImageState imageState;
if(ser.VersionLess(0x11))
@@ -294,7 +296,7 @@ void VulkanResourceManager::SerialiseImageStates(SerialiserType &ser,
ImageLayouts &ImageState = imageLayouts;
SERIALISE_ELEMENT(ImageState);
}
if(IsReplayingAndReading())
if(IsReplayingAndReading() && hasLiveRes)
{
if(imageLayouts.imageInfo.extent.depth > 1)
imageLayouts.imageInfo.imageType = VK_IMAGE_TYPE_3D;
@@ -317,7 +319,8 @@ void VulkanResourceManager::SerialiseImageStates(SerialiserType &ser,
subresourceStates.push_back(p);
}
imageState.subresourceStates.FromArray(subresourceStates);
if(!subresourceStates.empty())
imageState.subresourceStates.FromArray(subresourceStates);
imageState.maxRefType = eFrameRef_Unknown;
}
}
@@ -327,7 +330,7 @@ void VulkanResourceManager::SerialiseImageStates(SerialiserType &ser,
::ImageState &ImageState = imageState;
SERIALISE_ELEMENT(ImageState);
}
if(IsReplayingAndReading())
if(IsReplayingAndReading() && hasLiveRes)
{
imageState.newQueueFamilyTransfers.clear();
for(auto it = imageState.subresourceStates.begin();
@@ -342,7 +345,7 @@ void VulkanResourceManager::SerialiseImageStates(SerialiserType &ser,
}
}
}
if(HasLiveResource(Image))
if(hasLiveRes)
{
ResourceId liveid = GetLiveID(Image);
@@ -878,15 +881,6 @@ MemRefs *VulkanResourceManager::FindMemRefs(ResourceId mem)
return NULL;
}
ImgRefs *VulkanResourceManager::FindImgRefs(ResourceId img)
{
auto it = m_ImgFrameRefs.find(img);
if(it != m_ImgFrameRefs.end())
return &it->second;
else
return NULL;
}
bool VulkanResourceManager::Prepare_InitialState(WrappedVkRes *res)
{
return m_Core->Prepare_InitialState(res);
-1
View File
@@ -460,6 +460,5 @@ private:
WrappedVulkan *m_Core;
std::map<ResourceId, MemRefs> m_MemFrameRefs;
std::map<ResourceId, ImgRefs> m_ImgFrameRefs;
InitPolicy m_InitPolicy = eInitPolicy_CopyAll;
};
+20 -44
View File
@@ -518,23 +518,10 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, CompType typeCast, Floa
// need to update image layout into valid state
VkImageMemoryBarrier barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
NULL,
0,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
Unwrap(m_Overlay.Image),
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
};
m_pDriver->m_ImageLayouts[GetResID(m_Overlay.Image)].subresourceStates[0].newLayout =
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
DoPipelineBarrier(cmd, 1, &barrier);
m_pDriver->FindImageState(GetResID(m_Overlay.Image))
->InlineTransition(
cmd, m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, m_pDriver->GetImageTransitionInfo());
VkAttachmentDescription colDesc = {
0,
@@ -1290,21 +1277,16 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, CompType typeCast, Floa
attDescs[1].format = depthImageInfo.format;
attDescs[0].samples = attDescs[1].samples = iminfo.samples;
rdcarray<ImageRegionState> &depthStates = m_pDriver->m_ImageLayouts[depthIm].subresourceStates;
for(ImageRegionState &ds : depthStates)
{
// find the state that overlaps the view's subresource range start. We assume all
// subresources are correctly in the same state (as they should be) so we just need to find
// the first match.
if(ds.subresourceRange.baseArrayLayer <= depthViewInfo.range.baseArrayLayer &&
ds.subresourceRange.baseArrayLayer + 1 > depthViewInfo.range.baseArrayLayer &&
ds.subresourceRange.baseMipLevel <= depthViewInfo.range.baseMipLevel &&
ds.subresourceRange.baseMipLevel + ds.subresourceRange.levelCount + 1 >
depthViewInfo.range.baseMipLevel)
LockedConstImageStateRef imState = m_pDriver->FindConstImageState(depthIm);
if(imState)
{
attDescs[1].initialLayout = attDescs[1].finalLayout = ds.newLayout;
break;
// find the state that overlaps the view's subresource range start. We assume all
// subresources are correctly in the same state (as they should be) so we just need to
// find the first match.
auto it = imState->subresourceStates.RangeBegin(depthViewInfo.range);
if(it != imState->subresourceStates.end())
attDescs[1].initialLayout = attDescs[1].finalLayout = it->state().newLayout;
}
}
@@ -2073,22 +2055,16 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, CompType typeCast, Floa
attDescs[1].format = depthImageInfo.format;
attDescs[0].samples = attDescs[1].samples = iminfo.samples;
rdcarray<ImageRegionState> &depthStates =
m_pDriver->m_ImageLayouts[depthIm].subresourceStates;
for(ImageRegionState &ds : depthStates)
{
// find the state that overlaps the view's subresource range start. We assume all
// subresources are correctly in the same state (as they should be) so we just need to
// find the first match.
if(ds.subresourceRange.baseArrayLayer <= depthViewInfo.range.baseArrayLayer &&
ds.subresourceRange.baseArrayLayer + 1 > depthViewInfo.range.baseArrayLayer &&
ds.subresourceRange.baseMipLevel <= depthViewInfo.range.baseMipLevel &&
ds.subresourceRange.baseMipLevel + ds.subresourceRange.levelCount + 1 >
depthViewInfo.range.baseMipLevel)
LockedConstImageStateRef imState = m_pDriver->FindConstImageState(depthIm);
if(imState)
{
attDescs[1].initialLayout = attDescs[1].finalLayout = ds.newLayout;
break;
// find the state that overlaps the view's subresource range start. We assume all
// subresources are correctly in the same state (as they should be) so we just need to
// find the first match.
auto it = imState->subresourceStates.RangeBegin(depthViewInfo.range);
if(it != imState->subresourceStates.end())
attDescs[1].initialLayout = attDescs[1].finalLayout = it->state().newLayout;
}
}
+27 -42
View File
@@ -1345,6 +1345,10 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou
vkr = m_pDriver->vkCreateImage(dev, &imgInfo, NULL, &colorImage);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkImage wrappedColorImage = colorImage;
m_pDriver->GetResourceManager()->WrapResource(Unwrap(dev), wrappedColorImage);
ImageState colorImageState = ImageState(wrappedColorImage, ImageInfo(imgInfo), eFrameRef_None);
VkMemoryRequirements colorImageMrq = {0};
m_pDriver->vkGetImageMemoryRequirements(dev, colorImage, &colorImageMrq);
@@ -1355,6 +1359,10 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou
vkr = m_pDriver->vkCreateImage(dev, &imgInfo, NULL, &stencilImage);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkImage wrappedStencilImage = stencilImage;
m_pDriver->GetResourceManager()->WrapResource(Unwrap(dev), wrappedStencilImage);
ImageState stencilImageState = ImageState(wrappedStencilImage, ImageInfo(imgInfo), eFrameRef_None);
VkMemoryRequirements stencilImageMrq = {0};
m_pDriver->vkGetImageMemoryRequirements(dev, stencilImage, &stencilImageMrq);
VkDeviceSize offset = AlignUp(colorImageMrq.size, stencilImageMrq.alignment);
@@ -1413,34 +1421,13 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou
vkr = ObjDisp(dev)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkImageMemoryBarrier barriers[2] = {};
barriers[0] = {};
barriers[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barriers[0].srcAccessMask = 0;
barriers[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
barriers[0].subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barriers[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
barriers[0].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
barriers[0].image = Unwrap(colorImage);
colorImageState.InlineTransition(
cmd, m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, m_pDriver->GetImageTransitionInfo());
stencilImageState.InlineTransition(
cmd, m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 0,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, m_pDriver->GetImageTransitionInfo());
barriers[1] = barriers[0];
barriers[1].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
barriers[1].newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
barriers[1].subresourceRange = {VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0,
1};
barriers[1].image = Unwrap(stencilImage);
DoPipelineBarrier(cmd, 2, barriers);
{
SCOPED_LOCK(m_pDriver->m_ImageLayoutsLock);
m_pDriver->m_ImageLayouts[GetResID(colorImage)].subresourceStates[0].newLayout =
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
m_pDriver->m_ImageLayouts[GetResID(stencilImage)].subresourceStates[0].newLayout =
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
}
vkr = ObjDisp(dev)->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
m_pDriver->SubmitCmds();
@@ -1569,23 +1556,19 @@ void CreateOcclusionPool(WrappedVulkan *vk, uint32_t poolSize, VkQueryPool *pQue
vk->FlushQ();
}
VkImageLayout VulkanDebugManager::GetImageLayout(ResourceId image, VkImageAspectFlags aspect,
uint32_t mip)
VkImageLayout VulkanDebugManager::GetImageLayout(ResourceId image, VkImageAspectFlagBits aspect,
uint32_t mip, uint32_t slice)
{
VkImageLayout imgLayout = VK_IMAGE_LAYOUT_UNDEFINED;
const ImageLayouts &imgLayouts = m_pDriver->m_ImageLayouts[image];
for(const ImageRegionState &resState : imgLayouts.subresourceStates)
auto state = m_pDriver->FindConstImageState(image);
if(!state)
{
VkImageSubresourceRange range = resState.subresourceRange;
if((range.aspectMask & aspect) &&
(mip >= range.baseMipLevel && mip < range.baseMipLevel + range.levelCount))
{
// Consider using the layer count
imgLayout = resState.newLayout;
}
RDCERR("Could not find image state for %s", ToStr(image).c_str());
return VK_IMAGE_LAYOUT_UNDEFINED;
}
return imgLayout;
if(state->GetImageInfo().extent.depth > 1)
return state->GetImageLayout(aspect, mip, 0);
else
return state->GetImageLayout(aspect, mip, slice);
}
void UpdateTestsFailed(const TestsFailedCallback *tfCb, uint32_t eventId, uint32_t eventFlags,
@@ -1686,10 +1669,12 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
return history;
uint32_t mip = sub.mip;
uint32_t slice = sub.slice;
uint32_t sampleIdx = sub.sample;
// TODO: figure out correct aspect.
VkImageLayout imgLayout = GetDebugManager()->GetImageLayout(target, VK_IMAGE_ASPECT_COLOR_BIT, mip);
VkImageLayout imgLayout =
GetDebugManager()->GetImageLayout(target, VK_IMAGE_ASPECT_COLOR_BIT, mip, slice);
RDCASSERTNOTEQUAL(imgLayout, VK_IMAGE_LAYOUT_UNDEFINED);
// TODO: use the given type hint for typeless textures
+28 -22
View File
@@ -145,10 +145,21 @@ bool VulkanReplay::RenderTexture(TextureDisplay cfg)
NULL,
};
return RenderTextureInternal(cfg, rpbegin, eTexDisplay_MipShift | eTexDisplay_BlendAlpha);
LockedConstImageStateRef imageState = m_pDriver->FindConstImageState(cfg.resourceId);
if(!imageState)
{
RDCWARN("Could not find image info for image %s", ToStr(cfg.resourceId).c_str());
return false;
}
if(!imageState->isMemoryBound)
return false;
return RenderTextureInternal(cfg, *imageState, rpbegin,
eTexDisplay_MipShift | eTexDisplay_BlendAlpha);
}
bool VulkanReplay::RenderTextureInternal(TextureDisplay cfg, VkRenderPassBeginInfo rpbegin, int flags)
bool VulkanReplay::RenderTextureInternal(TextureDisplay cfg, const ImageState &imageState,
VkRenderPassBeginInfo rpbegin, int flags)
{
const bool blendAlpha = (flags & eTexDisplay_BlendAlpha) != 0;
const bool mipShift = (flags & eTexDisplay_MipShift) != 0;
@@ -159,14 +170,11 @@ bool VulkanReplay::RenderTextureInternal(TextureDisplay cfg, VkRenderPassBeginIn
VkDevice dev = m_pDriver->GetDev();
const VkDevDispatchTable *vt = ObjDisp(dev);
ImageLayouts &layouts = m_pDriver->m_ImageLayouts[cfg.resourceId];
const ImageInfo &imageInfo = imageState.GetImageInfo();
VulkanCreationInfo::Image &iminfo = m_pDriver->m_CreationInfo.m_Image[cfg.resourceId];
TextureDisplayViews &texviews = m_TexRender.TextureViews[cfg.resourceId];
VkImage liveIm = m_pDriver->GetResourceManager()->GetCurrentHandle<VkImage>(cfg.resourceId);
const ImageInfo &imageInfo = layouts.imageInfo;
if(!layouts.isMemoryBound)
return false;
CreateTexImageView(liveIm, iminfo, cfg.typeCast, texviews);
@@ -481,12 +489,12 @@ bool VulkanReplay::RenderTextureInternal(TextureDisplay cfg, VkRenderPassBeginIn
vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
rdcarray<VkImageMemoryBarrier> setupBarriers, cleanupBarriers;
bool extQCleanup = false;
m_pDriver->TempTransition(liveIm, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_ACCESS_SHADER_READ_BIT, setupBarriers, cleanupBarriers, extQCleanup);
DoPipelineBarrier(cmd, setupBarriers.size(), setupBarriers.data());
ImageBarrierSequence setupBarriers, cleanupBarriers;
imageState.TempTransition(m_pDriver->GetQueueFamilyIndex(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_SHADER_READ_BIT,
setupBarriers, cleanupBarriers, m_pDriver->GetImageTransitionInfo());
m_pDriver->InlineSetupImageBarriers(cmd, setupBarriers);
m_pDriver->SubmitAndFlushImageStateBarriers(setupBarriers);
{
vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);
@@ -556,21 +564,19 @@ bool VulkanReplay::RenderTextureInternal(TextureDisplay cfg, VkRenderPassBeginIn
vt->CmdEndRenderPass(Unwrap(cmd));
}
DoPipelineBarrier(cmd, cleanupBarriers.size(), cleanupBarriers.data());
m_pDriver->InlineCleanupImageBarriers(cmd, cleanupBarriers);
vt->EndCommandBuffer(Unwrap(cmd));
if(extQCleanup)
if(!cleanupBarriers.empty())
{
// ensure work is completed before we pass ownership back to original queue
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
m_pDriver->SubmitExtQBarriers(~0U, cleanupBarriers);
m_pDriver->SubmitAndFlushImageStateBarriers(cleanupBarriers);
}
#if ENABLED(SINGLE_FLUSH_VALIDATE)
m_pDriver->SubmitCmds();
else
{
m_pDriver->SubmitCmds();
}
#endif
return true;
+171 -163
View File
@@ -296,7 +296,7 @@ rdcarray<ResourceId> VulkanReplay::GetTextures()
{
rdcarray<ResourceId> texs;
for(auto it = m_pDriver->m_ImageLayouts.begin(); it != m_pDriver->m_ImageLayouts.end(); ++it)
for(auto it = m_pDriver->m_ImageStates.begin(); it != m_pDriver->m_ImageStates.end(); ++it)
{
// skip textures that aren't from the capture
if(m_pDriver->GetResourceManager()->GetOriginalID(it->first) == it->first)
@@ -1849,9 +1849,9 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
// image layouts
{
m_VulkanPipelineState.images.resize(m_pDriver->m_ImageLayouts.size());
size_t i = 0;
for(auto it = m_pDriver->m_ImageLayouts.begin(); it != m_pDriver->m_ImageLayouts.end(); ++it)
m_VulkanPipelineState.images.resize(m_pDriver->m_ImageStates.size());
for(auto it = m_pDriver->m_ImageStates.begin(); it != m_pDriver->m_ImageStates.end(); ++it)
{
VKPipe::ImageData &img = m_VulkanPipelineState.images[i];
@@ -1860,14 +1860,16 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
img.resourceId = rm->GetOriginalID(it->first);
img.layouts.resize(it->second.subresourceStates.size());
for(size_t l = 0; l < it->second.subresourceStates.size(); l++)
LockedConstImageStateRef imState = it->second.LockRead();
img.layouts.resize(imState->subresourceStates.size());
auto subIt = imState->subresourceStates.begin();
for(size_t l = 0; l < img.layouts.size(); ++l, ++subIt)
{
img.layouts[l].name = ToStr(it->second.subresourceStates[l].newLayout);
img.layouts[l].baseMip = it->second.subresourceStates[l].subresourceRange.baseMipLevel;
img.layouts[l].baseLayer = it->second.subresourceStates[l].subresourceRange.baseArrayLayer;
img.layouts[l].numLayer = it->second.subresourceStates[l].subresourceRange.layerCount;
img.layouts[l].numMip = it->second.subresourceStates[l].subresourceRange.levelCount;
img.layouts[l].name = ToStr(subIt->state().newLayout);
img.layouts[l].baseMip = subIt->range().baseMipLevel;
img.layouts[l].numMip = subIt->range().levelCount;
img.layouts[l].baseLayer = subIt->range().baseArrayLayer;
img.layouts[l].numLayer = subIt->range().layerCount;
}
if(img.layouts.empty())
@@ -1965,6 +1967,14 @@ void VulkanReplay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, const S
m_DebugWidth = m_DebugHeight = 1;
VulkanCreationInfo::Image &iminfo = m_pDriver->m_CreationInfo.m_Image[texture];
LockedConstImageStateRef imageState = m_pDriver->FindConstImageState(texture);
if(!imageState)
{
RDCWARN("Could not find image info for image %s", ToStr(texture).c_str());
return;
}
if(!imageState->isMemoryBound)
return;
bool isStencil = IsStencilFormat(iminfo.format);
@@ -2012,7 +2022,8 @@ void VulkanReplay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, const S
&clearval,
};
RenderTextureInternal(texDisplay, rpbegin, eTexDisplay_32Render | eTexDisplay_MipShift);
RenderTextureInternal(texDisplay, *imageState, rpbegin,
eTexDisplay_32Render | eTexDisplay_MipShift);
}
VkDevice dev = m_pDriver->GetDev();
@@ -2114,9 +2125,15 @@ void VulkanReplay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, const S
bool VulkanReplay::GetMinMax(ResourceId texid, const Subresource &sub, CompType typeCast,
float *minval, float *maxval)
{
ImageLayouts &layouts = m_pDriver->m_ImageLayouts[texid];
const ImageInfo *imageInfo = NULL;
{
LockedConstImageStateRef state = m_pDriver->FindConstImageState(texid);
if(!state)
return false;
imageInfo = &state->GetImageInfo();
}
if(IsDepthAndStencilFormat(layouts.imageInfo.format))
if(IsDepthAndStencilFormat(imageInfo->format))
{
// for depth/stencil we need to run the code twice - once to fetch depth and once to fetch
// stencil - since we can't process float depth and int stencil at the same time
@@ -2154,12 +2171,15 @@ bool VulkanReplay::GetMinMax(ResourceId texid, const Subresource &sub, CompType
VkDevice dev = m_pDriver->GetDev();
const VkDevDispatchTable *vt = ObjDisp(dev);
ImageLayouts &layouts = m_pDriver->m_ImageLayouts[texid];
LockedConstImageStateRef state = m_pDriver->FindConstImageState(texid);
if(!state)
return false;
bool isMemoryBound = state->isMemoryBound;
VulkanCreationInfo::Image &iminfo = m_pDriver->m_CreationInfo.m_Image[texid];
TextureDisplayViews &texviews = m_TexRender.TextureViews[texid];
VkImage liveIm = m_pDriver->GetResourceManager()->GetCurrentHandle<VkImage>(texid);
if(!layouts.isMemoryBound)
if(!isMemoryBound)
return false;
if(!IsStencilFormat(iminfo.format))
@@ -2339,11 +2359,6 @@ bool VulkanReplay::GetMinMax(ResourceId texid, const Subresource &sub, CompType
m_Histogram.m_HistogramUBO.Unmap();
rdcarray<VkImageMemoryBarrier> setupBarriers, cleanupBarriers;
bool extQCleanup = false;
m_pDriver->TempTransition(liveIm, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_ACCESS_SHADER_READ_BIT, setupBarriers, cleanupBarriers, extQCleanup);
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT};
@@ -2351,7 +2366,12 @@ bool VulkanReplay::GetMinMax(ResourceId texid, const Subresource &sub, CompType
vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
DoPipelineBarrier(cmd, setupBarriers.size(), setupBarriers.data());
ImageBarrierSequence setupBarriers, cleanupBarriers;
state->TempTransition(m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_ACCESS_SHADER_READ_BIT, setupBarriers, cleanupBarriers,
m_pDriver->GetImageTransitionInfo());
m_pDriver->InlineSetupImageBarriers(cmd, setupBarriers);
m_pDriver->SubmitAndFlushImageStateBarriers(setupBarriers);
int blocksX = (int)ceil(iminfo.extent.width / float(HGRAM_PIXELS_PER_TILE * HGRAM_TILES_PER_BLOCK));
int blocksY =
@@ -2365,7 +2385,16 @@ bool VulkanReplay::GetMinMax(ResourceId texid, const Subresource &sub, CompType
vt->CmdDispatch(Unwrap(cmd), blocksX, blocksY, 1);
DoPipelineBarrier(cmd, cleanupBarriers.size(), cleanupBarriers.data());
m_pDriver->InlineCleanupImageBarriers(cmd, cleanupBarriers);
if(!cleanupBarriers.empty())
{
vt->EndCommandBuffer(Unwrap(cmd));
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
m_pDriver->SubmitAndFlushImageStateBarriers(cleanupBarriers);
cmd = m_pDriver->GetNextCmd();
vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
}
VkBufferMemoryBarrier tilebarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
@@ -2419,9 +2448,6 @@ bool VulkanReplay::GetMinMax(ResourceId texid, const Subresource &sub, CompType
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
if(extQCleanup)
m_pDriver->SubmitExtQBarriers(~0U, cleanupBarriers);
Vec4f *minmax = (Vec4f *)m_Histogram.m_MinMaxReadback.Map(NULL);
minval[0] = minmax[0].x;
@@ -2449,14 +2475,13 @@ bool VulkanReplay::GetHistogram(ResourceId texid, const Subresource &sub, CompTy
VkDevice dev = m_pDriver->GetDev();
const VkDevDispatchTable *vt = ObjDisp(dev);
ImageLayouts &layouts = m_pDriver->m_ImageLayouts[texid];
LockedConstImageStateRef state = m_pDriver->FindConstImageState(texid);
if(!state->isMemoryBound)
return false;
VulkanCreationInfo::Image &iminfo = m_pDriver->m_CreationInfo.m_Image[texid];
TextureDisplayViews &texviews = m_TexRender.TextureViews[texid];
VkImage liveIm = m_pDriver->GetResourceManager()->GetCurrentHandle<VkImage>(texid);
if(!layouts.isMemoryBound)
return false;
bool stencil = false;
// detect if stencil is selected
if(IsStencilFormat(iminfo.format) && !channels[0] && channels[1] && !channels[2] && !channels[3])
@@ -2655,11 +2680,12 @@ bool VulkanReplay::GetHistogram(ResourceId texid, const Subresource &sub, CompTy
vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
rdcarray<VkImageMemoryBarrier> setupBarriers, cleanupBarriers;
bool extQCleanup = false;
m_pDriver->TempTransition(liveIm, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_READ_BIT,
setupBarriers, cleanupBarriers, extQCleanup);
DoPipelineBarrier(cmd, setupBarriers.size(), setupBarriers.data());
ImageBarrierSequence setupBarriers, cleanupBarriers;
state->TempTransition(m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_GENERAL,
VK_ACCESS_SHADER_READ_BIT, setupBarriers, cleanupBarriers,
m_pDriver->GetImageTransitionInfo());
m_pDriver->InlineSetupImageBarriers(cmd, setupBarriers);
m_pDriver->SubmitAndFlushImageStateBarriers(setupBarriers);
int blocksX = (int)ceil(iminfo.extent.width / float(HGRAM_PIXELS_PER_TILE * HGRAM_TILES_PER_BLOCK));
int blocksY =
@@ -2676,7 +2702,16 @@ bool VulkanReplay::GetHistogram(ResourceId texid, const Subresource &sub, CompTy
vt->CmdDispatch(Unwrap(cmd), blocksX, blocksY, 1);
DoPipelineBarrier(cmd, cleanupBarriers.size(), cleanupBarriers.data());
m_pDriver->InlineCleanupImageBarriers(cmd, cleanupBarriers);
if(!cleanupBarriers.empty())
{
vt->EndCommandBuffer(Unwrap(cmd));
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
m_pDriver->SubmitAndFlushImageStateBarriers(cleanupBarriers);
cmd = m_pDriver->GetNextCmd();
vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
}
VkBufferMemoryBarrier tilebarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
@@ -2714,9 +2749,6 @@ bool VulkanReplay::GetHistogram(ResourceId texid, const Subresource &sub, CompTy
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
if(extQCleanup)
m_pDriver->SubmitExtQBarriers(~0U, cleanupBarriers);
uint32_t *buckets = (uint32_t *)m_Histogram.m_HistogramReadback.Map(NULL);
histogram.assign(buckets, HGRAM_NUM_BUCKETS);
@@ -2745,10 +2777,11 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
const VulkanCreationInfo::Image &imInfo = m_pDriver->m_CreationInfo.m_Image[tex];
ImageLayouts &layouts = m_pDriver->m_ImageLayouts[tex];
if(!layouts.isMemoryBound)
LockedConstImageStateRef lockedImage = m_pDriver->FindConstImageState(tex);
if(!lockedImage || !lockedImage->isMemoryBound)
return;
const ImageState *srcImageState = &*lockedImage;
ImageState tmpImageState;
VkMarkerRegion region(StringFormat::Fmt("GetTextureData(%u, %u, %u, remap=%d)", sub.mip,
sub.slice, sub.sample, params.remap));
@@ -2781,10 +2814,9 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
VkImage srcImage = Unwrap(liveWrappedImage);
VkImage tmpImage = VK_NULL_HANDLE;
VkImage wrappedTmpImage = VK_NULL_HANDLE;
VkDeviceMemory tmpMemory = VK_NULL_HANDLE;
uint32_t srcQueueIndex = layouts.queueFamilyIndex;
VkFramebuffer *tmpFB = NULL;
VkImageView *tmpView = NULL;
uint32_t numFBs = 0;
@@ -2812,9 +2844,6 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
if(wasms && (isDepth || isStencil))
resolve = false;
rdcarray<VkImageMemoryBarrier> setupBarriers, cleanupBarriers;
bool extQCleanup = false;
if(params.remap != RemapTexture::NoRemap)
{
int renderFlags = 0;
@@ -2875,6 +2904,9 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
// create render texture similar to readback texture
vt->CreateImage(Unwrap(dev), &imCreateInfo, NULL, &tmpImage);
wrappedTmpImage = tmpImage;
GetResourceManager()->WrapResource(Unwrap(dev), wrappedTmpImage);
tmpImageState = ImageState(wrappedTmpImage, ImageInfo(imCreateInfo), eFrameRef_None);
VkMemoryRequirements mrq = {0};
vt->GetImageMemoryRequirements(Unwrap(dev), tmpImage, &mrq);
@@ -2890,21 +2922,9 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
vkr = vt->BindImageMemory(Unwrap(dev), tmpImage, tmpMemory, 0);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkImageMemoryBarrier dstimBarrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
NULL,
0,
0,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
tmpImage,
{VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS},
};
// move tmp image into transfer destination layout
DoPipelineBarrier(cmd, 1, &dstimBarrier);
tmpImageState.InlineTransition(
cmd, m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, m_pDriver->GetImageTransitionInfo());
// end this command buffer, the rendertexture below will use its own and we want to ensure
// ordering
@@ -3046,7 +3066,7 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
&clearval,
};
RenderTextureInternal(texDisplay, rpbegin, renderFlags);
RenderTextureInternal(texDisplay, *srcImageState, rpbegin, renderFlags);
renderCount++;
// for textures with stencil, do another draw to copy the stencil
@@ -3062,8 +3082,9 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
rpbegin.framebuffer = tmpFB[i + numFBs];
texDisplay.red = texDisplay.blue = texDisplay.alpha = false;
RenderTextureInternal(texDisplay, rpbegin, (renderFlags & ~eTexDisplay_RemapFloat) |
eTexDisplay_RemapUInt | eTexDisplay_GreenOnly);
RenderTextureInternal(texDisplay, *srcImageState, rpbegin,
(renderFlags & ~eTexDisplay_RemapFloat) | eTexDisplay_RemapUInt |
eTexDisplay_GreenOnly);
renderCount++;
}
}
@@ -3072,7 +3093,7 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
m_DebugHeight = oldH;
srcImage = tmpImage;
srcQueueIndex = m_pDriver->GetQueueFamilyIndex();
srcImageState = &tmpImageState;
// fetch a new command buffer for copy & readback
cmd = m_pDriver->GetNextCmd();
@@ -3080,13 +3101,10 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
// ensure all writes happen before copy & readback
dstimBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
dstimBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
dstimBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dstimBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
DoPipelineBarrier(cmd, 1, &dstimBarrier);
tmpImageState.InlineTransition(cmd, m_pDriver->m_QueueFamilyIdx,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT, m_pDriver->GetImageTransitionInfo());
// these have already been selected, don't need to fetch that subresource
// when copying back to readback buffer
@@ -3108,6 +3126,9 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
// create resolve texture
vt->CreateImage(Unwrap(dev), &imCreateInfo, NULL, &tmpImage);
wrappedTmpImage = tmpImage;
GetResourceManager()->WrapResource(Unwrap(dev), wrappedTmpImage);
tmpImageState = ImageState(wrappedTmpImage, ImageInfo(imCreateInfo), eFrameRef_None);
VkMemoryRequirements mrq = {0};
vt->GetImageMemoryRequirements(Unwrap(dev), tmpImage, &mrq);
@@ -3133,43 +3154,27 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
imCreateInfo.extent,
};
m_pDriver->TempTransition(liveWrappedImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_ACCESS_TRANSFER_READ_BIT, setupBarriers, cleanupBarriers,
extQCleanup);
VkImageMemoryBarrier dstimBarrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
NULL,
0,
0,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
tmpImage,
{imageAspects, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS},
};
// move tmp image into transfer destination layout as well
setupBarriers.push_back(dstimBarrier);
DoPipelineBarrier(cmd, setupBarriers.size(), setupBarriers.data());
tmpImageState.InlineTransition(
cmd, m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0,
VK_ACCESS_TRANSFER_WRITE_BIT, m_pDriver->GetImageTransitionInfo());
ImageBarrierSequence setupBarriers, cleanupBarriers;
srcImageState->TempTransition(m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_ACCESS_TRANSFER_READ_BIT, setupBarriers, cleanupBarriers,
m_pDriver->GetImageTransitionInfo());
m_pDriver->InlineSetupImageBarriers(cmd, setupBarriers);
m_pDriver->SubmitAndFlushImageStateBarriers(setupBarriers);
// resolve from live texture to resolve texture
vt->CmdResolveImage(Unwrap(cmd), srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, tmpImage,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolveRegion);
dstimBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
dstimBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dstimBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
dstimBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
tmpImageState.InlineTransition(cmd, m_pDriver->m_QueueFamilyIdx,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT, m_pDriver->GetImageTransitionInfo());
// wait for resolve to finish before copy to buffer
cleanupBarriers.push_back(dstimBarrier);
m_pDriver->InlineCleanupImageBarriers(cmd, cleanupBarriers);
DoPipelineBarrier(cmd, cleanupBarriers.size(), cleanupBarriers.data());
if(extQCleanup)
if(!cleanupBarriers.empty())
{
// ensure this resolve happens before handing back the source image to the original queue
vkr = vt->EndCommandBuffer(Unwrap(cmd));
@@ -3178,10 +3183,7 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
// don't do our dest image barrier on the external queue
cleanupBarriers.pop_back();
m_pDriver->SubmitExtQBarriers(~0U, cleanupBarriers);
m_pDriver->SubmitAndFlushImageStateBarriers(cleanupBarriers);
// fetch a new command buffer for remaining work
cmd = m_pDriver->GetNextCmd();
@@ -3189,9 +3191,9 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
}
srcImageState = &tmpImageState;
srcImage = tmpImage;
srcQueueIndex = m_pDriver->GetQueueFamilyIndex();
// these have already been selected, don't need to fetch that subresource
// when copying back to readback buffer
@@ -3215,6 +3217,9 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
// create resolve texture
vt->CreateImage(Unwrap(dev), &imCreateInfo, NULL, &tmpImage);
wrappedTmpImage = tmpImage;
GetResourceManager()->WrapResource(Unwrap(dev), wrappedTmpImage);
tmpImageState = ImageState(wrappedTmpImage, ImageInfo(imCreateInfo), eFrameRef_None);
VkMemoryRequirements mrq = {0};
vt->GetImageMemoryRequirements(Unwrap(dev), tmpImage, &mrq);
@@ -3230,26 +3235,15 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
vkr = vt->BindImageMemory(Unwrap(dev), tmpImage, tmpMemory, 0);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
m_pDriver->TempTransition(liveWrappedImage, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_READ_BIT,
setupBarriers, cleanupBarriers, extQCleanup);
VkImageMemoryBarrier dstimBarrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
NULL,
0,
0,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
tmpImage,
{imageAspects, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS},
};
// move tmp image into transfer destination layout
setupBarriers.push_back(dstimBarrier);
DoPipelineBarrier(cmd, setupBarriers.size(), setupBarriers.data());
tmpImageState.InlineTransition(cmd, m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_GENERAL, 0,
VK_ACCESS_SHADER_WRITE_BIT, m_pDriver->GetImageTransitionInfo());
ImageBarrierSequence setupBarriers, cleanupBarriers;
srcImageState->TempTransition(m_pDriver->m_QueueFamilyIdx,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_ACCESS_SHADER_READ_BIT, setupBarriers, cleanupBarriers,
m_pDriver->GetImageTransitionInfo());
m_pDriver->InlineSetupImageBarriers(cmd, setupBarriers);
m_pDriver->SubmitAndFlushImageStateBarriers(setupBarriers);
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
@@ -3265,18 +3259,13 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
// wait for copy to finish before copy to buffer
dstimBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
dstimBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dstimBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
dstimBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
tmpImageState.InlineTransition(cmd, m_pDriver->m_QueueFamilyIdx,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT, m_pDriver->GetImageTransitionInfo());
// wait for work to finish before copy to buffer
cleanupBarriers.push_back(dstimBarrier);
m_pDriver->InlineCleanupImageBarriers(cmd, cleanupBarriers);
DoPipelineBarrier(cmd, cleanupBarriers.size(), cleanupBarriers.data());
if(extQCleanup)
if(!cleanupBarriers.empty())
{
// ensure this resolve happens before handing back the source image to the original queue
vkr = vt->EndCommandBuffer(Unwrap(cmd));
@@ -3285,10 +3274,7 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
// don't do our dest image barrier on the external queue
cleanupBarriers.pop_back();
m_pDriver->SubmitExtQBarriers(~0U, cleanupBarriers);
m_pDriver->SubmitAndFlushImageStateBarriers(cleanupBarriers);
// fetch a new command buffer for remaining work
cmd = m_pDriver->GetNextCmd();
@@ -3298,27 +3284,22 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
}
srcImage = tmpImage;
srcQueueIndex = m_pDriver->GetQueueFamilyIndex();
srcImageState = &tmpImageState;
s.slice = s.slice * numSamples + s.sample;
s.sample = 0;
}
ImageBarrierSequence cleanupBarriers;
// if we have no tmpImage, we're copying directly from the real image
if(tmpImage == VK_NULL_HANDLE)
{
m_pDriver->TempTransition(liveWrappedImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_ACCESS_TRANSFER_READ_BIT, setupBarriers, cleanupBarriers,
extQCleanup);
DoPipelineBarrier(cmd, setupBarriers.size(), setupBarriers.data());
}
else
{
// no more setup/cleanup to do, we read from the real image above
extQCleanup = false;
setupBarriers.clear();
cleanupBarriers.clear();
ImageBarrierSequence setupBarriers;
srcImageState->TempTransition(m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_ACCESS_TRANSFER_READ_BIT, setupBarriers, cleanupBarriers,
m_pDriver->GetImageTransitionInfo());
m_pDriver->InlineSetupImageBarriers(cmd, setupBarriers);
m_pDriver->SubmitAndFlushImageStateBarriers(setupBarriers);
}
VkImageAspectFlags copyAspects = VK_IMAGE_ASPECT_COLOR_BIT;
@@ -3435,6 +3416,30 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
readbackBuf, 1, copyregion);
}
// if we have no tmpImage, we're copying directly from the real image
if(tmpImage == VK_NULL_HANDLE)
{
m_pDriver->InlineCleanupImageBarriers(cmd, cleanupBarriers);
if(!cleanupBarriers.empty())
{
// ensure this resolve happens before handing back the source image to the original queue
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
m_pDriver->SubmitAndFlushImageStateBarriers(cleanupBarriers);
// fetch a new command buffer for remaining work
cmd = m_pDriver->GetNextCmd();
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
}
}
VkBufferMemoryBarrier bufBarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
NULL,
@@ -3447,10 +3452,6 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
dataSize,
};
// do any cleanup needed
if(!cleanupBarriers.empty())
DoPipelineBarrier(cmd, cleanupBarriers.size(), cleanupBarriers.data());
// wait for copy to finish before reading back to host
DoPipelineBarrier(cmd, 1, &bufBarrier);
@@ -3459,9 +3460,6 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
if(extQCleanup)
m_pDriver->SubmitExtQBarriers(~0U, cleanupBarriers);
// map the buffer and copy to return buffer
byte *pData = NULL;
vkr = vt->MapMemory(Unwrap(dev), readbackMem, 0, VK_WHOLE_SIZE, 0, (void **)&pData);
@@ -3577,6 +3575,7 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
if(tmpImage != VK_NULL_HANDLE)
{
GetResourceManager()->ReleaseWrappedResource(wrappedTmpImage, true);
vt->DestroyImage(Unwrap(dev), tmpImage, NULL);
vt->FreeMemory(Unwrap(dev), tmpMemory, NULL);
}
@@ -3658,7 +3657,16 @@ ResourceId VulkanReplay::ApplyCustomShader(ResourceId shader, ResourceId texid,
&clearval,
};
RenderTextureInternal(disp, rpbegin, eTexDisplay_MipShift);
LockedConstImageStateRef imageState = m_pDriver->FindConstImageState(texid);
if(!imageState)
{
RDCWARN("Could not find image info for image %s", ToStr(texid).c_str());
return ResourceId();
}
if(!imageState->isMemoryBound)
return ResourceId();
RenderTextureInternal(disp, *imageState, rpbegin, eTexDisplay_MipShift);
m_DebugWidth = oldW;
m_DebugHeight = oldH;
+2 -1
View File
@@ -426,7 +426,8 @@ private:
void RefreshDerivedReplacements();
bool RenderTextureInternal(TextureDisplay cfg, VkRenderPassBeginInfo rpbegin, int flags);
bool RenderTextureInternal(TextureDisplay cfg, const ImageState &imageState,
VkRenderPassBeginInfo rpbegin, int flags);
bool GetMinMax(ResourceId texid, const Subresource &sub, CompType typeCast, bool stencil,
float *minval, float *maxval);
@@ -453,7 +453,7 @@ bool WrappedVulkan::Serialise_vkCreateCommandPool(SerialiserType &ser, VkDevice
// remap the queue family index
CreateInfo.queueFamilyIndex = m_QueueRemapping[CreateInfo.queueFamilyIndex][0].family;
m_commandQueueFamilies[CmdPool] = CreateInfo.queueFamilyIndex;
InsertCommandQueueFamily(CmdPool, CreateInfo.queueFamilyIndex);
VkResult ret = ObjDisp(device)->CreateCommandPool(Unwrap(device), &CreateInfo, NULL, &pool);
@@ -466,7 +466,7 @@ bool WrappedVulkan::Serialise_vkCreateCommandPool(SerialiserType &ser, VkDevice
{
ResourceId live = GetResourceManager()->WrapResource(Unwrap(device), pool);
GetResourceManager()->AddLiveResource(CmdPool, pool);
m_commandQueueFamilies[live] = CreateInfo.queueFamilyIndex;
InsertCommandQueueFamily(live, CreateInfo.queueFamilyIndex);
}
AddResource(CmdPool, ResourceType::Pool, "Command Pool");
@@ -561,13 +561,18 @@ bool WrappedVulkan::Serialise_vkAllocateCommandBuffers(SerialiserType &ser, VkDe
{
ResourceId live = GetResourceManager()->WrapResource(Unwrap(device), cmd);
GetResourceManager()->AddLiveResource(CommandBuffer, cmd);
m_commandQueueFamilies[live] = m_commandQueueFamilies[GetResID(AllocateInfo.commandPool)];
auto cmdQueueFamilyIt = m_commandQueueFamilies.find(GetResID(AllocateInfo.commandPool));
if(cmdQueueFamilyIt == m_commandQueueFamilies.end())
{
RDCERR("Missing queue family for %s", ToStr(GetResID(AllocateInfo.commandPool)).c_str());
}
else
{
InsertCommandQueueFamily(CommandBuffer, cmdQueueFamilyIt->second);
InsertCommandQueueFamily(live, cmdQueueFamilyIt->second);
}
}
m_commandQueueFamilies[CommandBuffer] =
m_commandQueueFamilies[GetResID(AllocateInfo.commandPool)];
AddResource(CommandBuffer, ResourceType::CommandBuffer, "Command Buffer");
DerivedResource(device, CommandBuffer);
DerivedResource(AllocateInfo.commandPool, CommandBuffer);
@@ -695,6 +700,16 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(SerialiserType &ser, VkComman
if(IsReplayingAndReading())
{
auto cmdQueueFamilyIt = m_commandQueueFamilies.find(CommandBuffer);
if(cmdQueueFamilyIt == m_commandQueueFamilies.end())
{
RDCERR("Unknown queue family for %s", ToStr(CommandBuffer).c_str());
}
else
{
InsertCommandQueueFamily(BakedCommandBuffer, cmdQueueFamilyIt->second);
}
m_LastCmdBufferID = CommandBuffer;
// when loading, allocate a new resource ID for each push descriptor slot in this command buffer
@@ -827,6 +842,7 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(SerialiserType &ser, VkComman
// there's no issue with clashes here.
m_RerecordCmds[BakedCommandBuffer] = cmd;
m_RerecordCmds[m_LastCmdBufferID] = cmd;
InsertCommandQueueFamily(GetResID(cmd), FindCommandQueueFamily(m_LastCmdBufferID));
m_RerecordCmdList.push_back({AllocateInfo.commandPool, cmd});
@@ -921,6 +937,8 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(SerialiserType &ser, VkComman
}
ObjDisp(device)->BeginCommandBuffer(Unwrap(cmd), &unwrappedBeginInfo);
InsertCommandQueueFamily(GetResourceManager()->GetLiveID(BakedCommandBuffer),
FindCommandQueueFamily(BakedCommandBuffer));
}
}
@@ -1050,7 +1068,7 @@ bool WrappedVulkan::Serialise_vkEndCommandBuffer(SerialiserType &ser, VkCommandB
// subpass
uint32_t &sub = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass;
rdcarray<rdcpair<ResourceId, ImageRegionState> > imgbarriers;
std::map<ResourceId, ImageState> renderPassEndStates;
for(sub = m_RenderState.subpass + 1; sub < numSubpasses; sub++)
{
@@ -1059,51 +1077,43 @@ bool WrappedVulkan::Serialise_vkEndCommandBuffer(SerialiserType &ser, VkCommandB
rdcarray<VkImageMemoryBarrier> subpassBarriers = GetImplicitRenderPassBarriers();
GetResourceManager()->RecordBarriers(
imgbarriers, m_ImageLayouts, (uint32_t)subpassBarriers.size(), &subpassBarriers[0]);
renderPassEndStates, FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)subpassBarriers.size(), subpassBarriers.data());
}
rdcarray<VkImageMemoryBarrier> finalBarriers = GetImplicitRenderPassBarriers(~0U);
GetResourceManager()->RecordBarriers(imgbarriers, m_ImageLayouts,
(uint32_t)finalBarriers.size(), &finalBarriers[0]);
GetResourceManager()->RecordBarriers(renderPassEndStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)finalBarriers.size(), finalBarriers.data());
ObjDisp(commandBuffer)->CmdEndRenderPass(Unwrap(commandBuffer));
// undo any implicit transitions we just went through, so that we can pretend that the
// image stayed in the same layout as it was when we stopped partially replaying.
rdcarray<VkImageMemoryBarrier> revertBarriers;
for(auto it = imgbarriers.begin(); it != imgbarriers.end(); ++it)
for(auto it = renderPassEndStates.begin(); it != renderPassEndStates.end(); ++it)
{
VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
barrier.srcAccessMask = VK_ACCESS_ALL_READ_BITS | VK_ACCESS_ALL_WRITE_BITS;
barrier.dstAccessMask = VK_ACCESS_ALL_READ_BITS | VK_ACCESS_ALL_WRITE_BITS;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = Unwrap(GetResourceManager()->GetCurrentHandle<VkImage>(it->first));
// go from the layout we ended up in, to the layout we started in
barrier.oldLayout = it->second.newLayout;
barrier.newLayout = it->second.oldLayout;
barrier.subresourceRange = it->second.subresourceRange;
if(barrier.oldLayout != barrier.newLayout &&
barrier.newLayout != VK_IMAGE_LAYOUT_UNDEFINED)
ResourceId id = it->first;
ImageState &endState = it->second;
LockedConstImageStateRef current = FindConstImageState(id);
if(!current)
{
SanitiseOldImageLayout(barrier.oldLayout);
SanitiseNewImageLayout(barrier.newLayout);
revertBarriers.push_back(barrier);
RDCERR("Unknown image %s", ToStr(id).c_str());
}
else
{
ImageBarrierSequence barriers;
endState.Transition(*current, VK_ACCESS_ALL_WRITE_BITS, VK_ACCESS_ALL_READ_BITS,
barriers, GetImageTransitionInfo());
InlineCleanupImageBarriers(commandBuffer, barriers);
if(!barriers.empty())
{
// This should not happen, because the cleanup barriers are just image layout
// transitions, no queue family transitions
RDCERR("Partial RenderPass replay cleanup barriers could not all be inlined");
}
}
}
if(!revertBarriers.empty())
{
if(SeparateDepthStencil())
CombineDepthStencilLayouts(revertBarriers);
DoPipelineBarrier(commandBuffer, revertBarriers.size(), revertBarriers.data());
}
}
@@ -1327,12 +1337,12 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass(SerialiserType &ser, VkComman
}
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
if(m_FirstEventID == m_LastEventID)
GetResourceManager()->ApplyBarriers(
m_QueueFamilyIdx, m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts);
UpdateImageStates(m_BakedCmdBufferInfo[cmd].imageStates);
}
}
else
@@ -1389,7 +1399,8 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass(SerialiserType &ser, VkComman
rdcarray<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers();
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
AddEvent();
@@ -1529,7 +1540,8 @@ bool WrappedVulkan::Serialise_vkCmdNextSubpass(SerialiserType &ser, VkCommandBuf
rdcarray<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers();
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
}
}
@@ -1545,7 +1557,8 @@ bool WrappedVulkan::Serialise_vkCmdNextSubpass(SerialiserType &ser, VkCommandBuf
rdcarray<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers();
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
AddEvent();
@@ -1623,7 +1636,8 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass(SerialiserType &ser, VkCommandB
}
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
}
}
@@ -1641,7 +1655,8 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass(SerialiserType &ser, VkCommandB
rdcarray<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers(~0U);
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
AddImplicitResolveResourceUsage(~0U);
@@ -1801,12 +1816,12 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass2(SerialiserType &ser,
}
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
if(m_FirstEventID == m_LastEventID)
GetResourceManager()->ApplyBarriers(
m_QueueFamilyIdx, m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts);
UpdateImageStates(m_BakedCmdBufferInfo[cmd].imageStates);
}
}
else
@@ -1864,7 +1879,8 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass2(SerialiserType &ser,
rdcarray<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers();
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
AddEvent();
@@ -2021,7 +2037,8 @@ bool WrappedVulkan::Serialise_vkCmdNextSubpass2(SerialiserType &ser, VkCommandBu
rdcarray<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers();
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
}
}
@@ -2038,7 +2055,8 @@ bool WrappedVulkan::Serialise_vkCmdNextSubpass2(SerialiserType &ser, VkCommandBu
rdcarray<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers();
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
AddEvent();
@@ -2135,7 +2153,8 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass2(SerialiserType &ser, VkCommand
}
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
}
}
@@ -2146,7 +2165,8 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass2(SerialiserType &ser, VkCommand
rdcarray<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers(~0U);
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
AddEvent();
@@ -2962,14 +2982,25 @@ bool WrappedVulkan::Serialise_vkCmdPipelineBarrier(
if(commandBuffer != VK_NULL_HANDLE)
{
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
FindCommandQueueFamily(m_LastCmdBufferID),
(uint32_t)imgBarriers.size(), imgBarriers.data());
// now sanitise layouts before passing to vulkan
for(VkImageMemoryBarrier &barrier : imgBarriers)
{
SanitiseOldImageLayout(barrier.oldLayout);
SanitiseNewImageLayout(barrier.newLayout);
if(!IsLoading(m_State) && barrier.oldLayout == VK_IMAGE_LAYOUT_PREINITIALIZED)
{
// This is a transition from PRENITIALIZED, but we've already done this barrier once (when
// loading); Since we couldn't transition back to PREINITIALIZED, we instead left the
// image in GENERAL.
barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
}
else
{
SanitiseReplayImageLayout(barrier.oldLayout);
}
SanitiseReplayImageLayout(barrier.newLayout);
}
ObjDisp(commandBuffer)
@@ -3372,9 +3403,9 @@ bool WrappedVulkan::Serialise_vkCmdExecuteCommands(SerialiserType &ser, VkComman
// merge barriers into parent command buffer
for(uint32_t i = 0; i < commandBufferCount; i++)
{
GetResourceManager()->MergeBarriers(
m_BakedCmdBufferInfo[GetResID(commandBuffer)].imgbarriers,
m_BakedCmdBufferInfo[GetResID(pCommandBuffers[i])].imgbarriers);
ImageState::Merge(m_BakedCmdBufferInfo[GetResID(commandBuffer)].imageStates,
m_BakedCmdBufferInfo[GetResID(pCommandBuffers[i])].imageStates,
GetImageTransitionInfo());
}
// append deferred indirect copies
@@ -3588,9 +3619,8 @@ bool WrappedVulkan::Serialise_vkCmdExecuteCommands(SerialiserType &ser, VkComman
#endif
rerecordedCmds.push_back(Unwrap(cmd));
GetResourceManager()->MergeBarriers(
m_BakedCmdBufferInfo[GetResID(commandBuffer)].imgbarriers,
m_BakedCmdBufferInfo[rerecord].imgbarriers);
ImageState::Merge(m_BakedCmdBufferInfo[GetResID(commandBuffer)].imageStates,
m_BakedCmdBufferInfo[rerecord].imageStates, GetImageTransitionInfo());
}
else
{
@@ -268,9 +268,7 @@ bool WrappedVulkan::Serialise_vkQueueSubmit(SerialiserType &ser, VkQueue queue,
BakedCmdBufferInfo &cmdBufInfo = m_BakedCmdBufferInfo[cmd];
GetResourceManager()->ApplyBarriers(m_CreationInfo.m_Queue[GetResID(queue)],
m_BakedCmdBufferInfo[liveCmd].imgbarriers,
m_ImageLayouts);
UpdateImageStates(m_BakedCmdBufferInfo[liveCmd].imageStates);
rdcstr name = StringFormat::Fmt("=> %s[%u]: vkBeginCommandBuffer(%s)", basename.c_str(),
c, ToStr(cmd).c_str());
@@ -400,9 +398,7 @@ bool WrappedVulkan::Serialise_vkQueueSubmit(SerialiserType &ser, VkQueue queue,
#endif
rerecordedCmds.push_back(Unwrap(cmd));
GetResourceManager()->ApplyBarriers(m_CreationInfo.m_Queue[GetResID(queue)],
m_BakedCmdBufferInfo[rerecord].imgbarriers,
m_ImageLayouts);
UpdateImageStates(m_BakedCmdBufferInfo[rerecord].imageStates);
}
else
{
@@ -1011,11 +1011,20 @@ bool WrappedVulkan::Serialise_vkBindImageMemory(SerialiserType &ser, VkDevice de
ObjDisp(device)->BindImageMemory(Unwrap(device), Unwrap(image), Unwrap(memory), memoryOffset);
ImageLayouts &layout = m_ImageLayouts[GetResID(image)];
layout.isMemoryBound = true;
layout.boundMemory = GetResID(memory);
layout.boundMemoryOffset = memoryOffset;
layout.boundMemorySize = mrq.size;
{
LockedImageStateRef state = FindImageState(GetResID(image));
if(!state)
{
RDCERR("Binding memory for unknown image %s", ToStr(GetResID(image)).c_str());
}
else
{
state->isMemoryBound = true;
state->boundMemory = GetResID(memory);
state->boundMemoryOffset = memoryOffset;
state->boundMemorySize = mrq.size;
}
}
GetResourceDesc(memOrigId).derivedResources.push_back(resOrigId);
GetResourceDesc(resOrigId).parentResources.push_back(memOrigId);
@@ -1071,7 +1080,13 @@ VkResult WrappedVulkan::vkBindImageMemory(VkDevice device, VkImage image, VkDevi
}
else
{
m_ImageLayouts[GetResID(image)].isMemoryBound = true;
{
LockedImageStateRef state = FindImageState(GetResID(image));
if(!state)
RDCERR("Binding memory to unknown image %s", ToStr(GetResID(image)).c_str());
else
state->isMemoryBound = true;
}
}
return ret;
@@ -1551,39 +1566,13 @@ bool WrappedVulkan::Serialise_vkCreateImage(SerialiserType &ser, VkDevice device
m_CreationInfo.m_Image[live].Init(GetResourceManager(), m_CreationInfo, &CreateInfo);
VkImageSubresourceRange range;
range.baseMipLevel = range.baseArrayLayer = 0;
range.levelCount = CreateInfo.mipLevels;
range.layerCount = CreateInfo.arrayLayers;
ImageLayouts &layouts = m_ImageLayouts[live];
layouts.imageInfo = ImageInfo(CreateInfo);
layouts.subresourceStates.clear();
layouts.initialLayout = CreateInfo.initialLayout;
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
if(IsDepthOnlyFormat(CreateInfo.format))
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
else if(IsStencilOnlyFormat(CreateInfo.format))
range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
else if(IsDepthOrStencilFormat(CreateInfo.format))
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
// if we don't support separate depth/stencil, track both aspects together
if(!SeparateDepthStencil() && IsDepthAndStencilFormat(CreateInfo.format))
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
layouts.subresourceStates.push_back(ImageRegionState(
VK_QUEUE_FAMILY_IGNORED, range, UNKNOWN_PREV_IMG_LAYOUT, CreateInfo.initialLayout));
// if we do support separate depth stencil, add a separate stencil aspect tracker
if(SeparateDepthStencil() && IsDepthAndStencilFormat(CreateInfo.format))
bool inserted = false;
auto state = InsertImageState(img, live, CreateInfo, eFrameRef_Unknown, &inserted);
if(!inserted)
{
range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
layouts.subresourceStates.push_back(ImageRegionState(
VK_QUEUE_FAMILY_IGNORED, range, UNKNOWN_PREV_IMG_LAYOUT, CreateInfo.initialLayout));
// Image state already existed.
state->wrappedHandle = img;
*state = state->InitialState();
}
}
@@ -2121,11 +2110,21 @@ bool WrappedVulkan::Serialise_vkBindImageMemory2(SerialiserType &ser, VkDevice d
if(!ok)
return false;
ImageLayouts &imageLayouts = m_ImageLayouts[GetResID(bindInfo.image)];
imageLayouts.isMemoryBound = true;
imageLayouts.boundMemory = GetResID(bindInfo.memory);
imageLayouts.boundMemoryOffset = bindInfo.memoryOffset;
imageLayouts.boundMemorySize = mrq.size;
{
ResourceId id = GetResID(bindInfo.image);
LockedImageStateRef state = FindImageState(id);
if(!state)
{
RDCERR("Binding memory for unknown image %s", ToStr(id).c_str());
}
else
{
state->isMemoryBound = true;
state->boundMemory = GetResID(bindInfo.memory);
state->boundMemoryOffset = bindInfo.memoryOffset;
state->boundMemorySize = mrq.size;
}
}
GetResourceDesc(memOrigId).derivedResources.push_back(resOrigId);
GetResourceDesc(resOrigId).parentResources.push_back(memOrigId);
@@ -2193,7 +2192,13 @@ VkResult WrappedVulkan::vkBindImageMemory2(VkDevice device, uint32_t bindInfoCou
else
{
for(uint32_t i = 0; i < bindInfoCount; i++)
m_ImageLayouts[GetResID(pBindInfos[i].image)].isMemoryBound = true;
{
LockedImageStateRef state = FindImageState(GetResID(pBindInfos[i].image));
if(!state)
state->isMemoryBound = true;
else
RDCERR("Binding memory to unknown image %s", ToStr(GetResID(pBindInfos[i].image)).c_str());
}
}
return ret;
@@ -841,8 +841,9 @@ bool WrappedVulkan::Serialise_vkCmdWaitEvents(
}
ResourceId cmd = GetResID(commandBuffer);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, m_ImageLayouts,
(uint32_t)imgBarriers.size(), &imgBarriers[0]);
GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[cmd].imageStates,
m_commandQueueFamilies[cmd], (uint32_t)imgBarriers.size(),
&imgBarriers[0]);
if(commandBuffer != VK_NULL_HANDLE)
{
@@ -441,22 +441,11 @@ bool WrappedVulkan::Serialise_vkCreateSwapchainKHR(SerialiserType &ser, VkDevice
m_CreationInfo.m_Names[liveId] = StringFormat::Fmt("Presentable Image %u", i);
VkImageSubresourceRange range;
range.baseMipLevel = range.baseArrayLayer = 0;
range.levelCount = 1;
range.layerCount = CreateInfo.imageArrayLayers;
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
ImageLayouts &layouts = m_ImageLayouts[liveId];
layouts.imageInfo = swapinfo.imageInfo;
layouts.isMemoryBound = true;
layouts.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
layouts.subresourceStates.clear();
layouts.subresourceStates.push_back(ImageRegionState(
VK_QUEUE_FAMILY_IGNORED, range, UNKNOWN_PREV_IMG_LAYOUT, VK_IMAGE_LAYOUT_UNDEFINED));
{
LockedImageStateRef state =
InsertImageState(im, liveId, ImageInfo(swapinfo.imageInfo), eFrameRef_Unknown);
state->isMemoryBound = true;
}
}
}