Batch together initial state application into fewer command buffers

* Some drivers struggle with one command buffer per resource and that's
  certainly inefficient, so batching work together (without going too far) keeps
  things working better.
This commit is contained in:
baldurk
2021-06-25 16:46:24 +01:00
parent b8d7cd17ec
commit 9547de7405
3 changed files with 87 additions and 41 deletions
+65 -2
View File
@@ -202,6 +202,49 @@ WrappedVulkan::~WrappedVulkan()
delete m_Replay;
}
VkCommandBuffer WrappedVulkan::GetInitStateCmd()
{
if(initStateCurBatch >= initialStateMaxBatch)
{
CloseInitStateCmd();
}
if(initStateCurCmd == VK_NULL_HANDLE)
{
initStateCurCmd = GetNextCmd();
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT};
VkResult vkr = ObjDisp(initStateCurCmd)->BeginCommandBuffer(Unwrap(initStateCurCmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
if(IsReplayMode(m_State))
{
VkMarkerRegion::Begin("!!!!RenderDoc Internal: ApplyInitialContents batched list",
initStateCurCmd);
}
}
initStateCurBatch++;
return initStateCurCmd;
}
void WrappedVulkan::CloseInitStateCmd()
{
if(initStateCurCmd == VK_NULL_HANDLE)
return;
VkMarkerRegion::End(initStateCurCmd);
VkResult vkr = ObjDisp(initStateCurCmd)->EndCommandBuffer(Unwrap(initStateCurCmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
initStateCurCmd = VK_NULL_HANDLE;
initStateCurBatch = 0;
}
VkCommandBuffer WrappedVulkan::GetNextCmd()
{
VkCommandBuffer ret;
@@ -224,13 +267,12 @@ VkCommandBuffer WrappedVulkan::GetNextCmd()
};
VkResult vkr = ObjDisp(m_Device)->AllocateCommandBuffers(Unwrap(m_Device), &cmdInfo, &ret);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
if(m_SetDeviceLoaderData)
m_SetDeviceLoaderData(m_Device, ret);
else
SetDispatchTableOverMagicNumber(m_Device, ret);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(m_Device), ret);
}
@@ -2768,6 +2810,9 @@ void WrappedVulkan::ApplyInitialContents()
RENDERDOC_PROFILEFUNCTION();
VkMarkerRegion region("ApplyInitialContents");
initStateCurBatch = 0;
initStateCurCmd = VK_NULL_HANDLE;
// check that we have all external queues necessary
for(size_t i = 0; i < m_ExternalQueues.size(); i++)
{
@@ -2816,6 +2861,15 @@ void WrappedVulkan::ApplyInitialContents()
// actually apply the initial contents here
GetResourceManager()->ApplyInitialContents();
// close the final command buffer
if(initStateCurCmd != VK_NULL_HANDLE)
{
CloseInitStateCmd();
}
initStateCurBatch = 0;
initStateCurCmd = VK_NULL_HANDLE;
for(auto it = m_ImageStates.begin(); it != m_ImageStates.end(); ++it)
{
if(GetResourceManager()->HasCurrentResource(it->first))
@@ -3359,6 +3413,15 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
{
GetResourceManager()->CreateInitialContents(ser);
if(initStateCurCmd != VK_NULL_HANDLE)
{
CloseInitStateCmd();
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();
SubmitAndFlushImageStateBarriers(m_cleanupImageBarriers);
}
SERIALISE_CHECK_READ_ERRORS();
}
else if(system == SystemChunk::InitialContents)
+6
View File
@@ -534,6 +534,10 @@ private:
// -> FlushQ() ----back to freesems-------^
} m_InternalCmds;
static const int initialStateMaxBatch = 100;
int initStateCurBatch = 0;
VkCommandBuffer initStateCurCmd = VK_NULL_HANDLE;
// Internal lumped/pooled memory allocations
// Each memory scope gets a separate vector of allocation objects. The vector contains the list of
@@ -1087,6 +1091,8 @@ public:
return m_PhysicalDevice;
}
VkCommandBuffer GetNextCmd();
VkCommandBuffer GetInitStateCmd();
void CloseInitStateCmd();
void RemovePendingCommandBuffer(VkCommandBuffer cmd);
void AddPendingCommandBuffer(VkCommandBuffer cmd);
void AddFreeCommandBuffer(VkCommandBuffer cmd);
+16 -39
View File
@@ -1794,21 +1794,6 @@ void WrappedVulkan::Create_InitialState(ResourceId id, WrappedVkRes *live, bool)
}
}
std::map<uint32_t, rdcarray<VkImageMemoryBarrier>> GetExtQBarriers(
const rdcarray<VkImageMemoryBarrier> &barriers)
{
std::map<uint32_t, rdcarray<VkImageMemoryBarrier>> extQBarriers;
for(auto barrierIt = barriers.begin(); barrierIt != barriers.end(); ++barrierIt)
{
if(barrierIt->srcQueueFamilyIndex != barrierIt->dstQueueFamilyIndex)
{
extQBarriers[barrierIt->srcQueueFamilyIndex].push_back(*barrierIt);
}
}
return extQBarriers;
}
void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialContents &initial)
{
VkResourceType type = initial.type;
@@ -1971,10 +1956,10 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
if(IsBlockFormat(format) || IsYUVFormat(format))
return;
VkCommandBuffer cmd = GetNextCmd();
VkCommandBuffer cmd = GetInitStateCmd();
vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkMarkerRegion::Begin(StringFormat::Fmt("Clear colour state for %s", ToStr(orig).c_str()),
cmd);
ImageBarrierSequence setupBarriers;
state->DiscardContents();
@@ -1990,9 +1975,10 @@ 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);
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkMarkerRegion::End(cmd);
#if ENABLED(SINGLE_FLUSH_VALIDATE)
CloseInitStateCmd();
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();
@@ -2001,10 +1987,10 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
}
else if(initial.tag == VkInitialContents::ClearDepthStencilImage)
{
VkCommandBuffer cmd = GetNextCmd();
VkCommandBuffer cmd = GetInitStateCmd();
vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkMarkerRegion::Begin(StringFormat::Fmt("Clear depth state for %s", ToStr(orig).c_str()),
cmd);
ImageBarrierSequence setupBarriers; // , cleanupBarriers;
state->DiscardContents();
@@ -2020,9 +2006,10 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearval, 1,
&range);
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkMarkerRegion::End(cmd);
#if ENABLED(SINGLE_FLUSH_VALIDATE)
CloseInitStateCmd();
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();
@@ -2039,6 +2026,8 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
if(m_CreationInfo.m_Image[id].samples != VK_SAMPLE_COUNT_1_BIT)
{
CloseInitStateCmd();
VkCommandBuffer cmd = GetNextCmd();
vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
@@ -2064,13 +2053,6 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
GetDebugManager()->CopyArrayToTex2DMS(ToUnwrappedHandle<VkImage>(live), Unwrap(arrayIm),
c.extent, c.arrayLayers, (uint32_t)c.samples, fmt);
cmd = GetNextCmd();
vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
#if ENABLED(SINGLE_FLUSH_VALIDATE)
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
@@ -2265,10 +2247,7 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
if(copyRegions.size() + clearRegions.size() > 0)
{
VkCommandBuffer cmd = GetNextCmd();
vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
VkCommandBuffer cmd = GetInitStateCmd();
VkMarkerRegion::Begin(StringFormat::Fmt("Initial state for %s", ToStr(orig).c_str()), cmd);
@@ -2303,12 +2282,10 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
}
VkMarkerRegion::End(cmd);
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
}
#if ENABLED(SINGLE_FLUSH_VALIDATE)
CloseInitStateCmd();
SubmitAndFlushImageStateBarriers(m_setupImageBarriers);
SubmitCmds();
FlushQ();