Ensure draw index is correct when replaying draws

This commit is contained in:
baldurk
2020-10-06 16:59:12 +01:00
parent 90437b3a65
commit 99811dd604
8 changed files with 234 additions and 109 deletions
@@ -884,17 +884,7 @@ void VulkanReplay::FetchShaderFeedback(uint32_t eventId)
{
modifiedstate.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics);
if(drawcall->flags & DrawFlags::Indexed)
{
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->indexOffset, drawcall->baseVertex,
drawcall->instanceOffset);
}
else
{
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
}
m_pDriver->ReplayDraw(cmd, *drawcall);
modifiedstate.EndRenderPass(cmd);
}
+101 -1
View File
@@ -2434,7 +2434,7 @@ ReplayStatus WrappedVulkan::ReadLogInitialisation(RDCFile *rdc, bool storeStruct
// create indirect draw buffer
m_IndirectBufferSize = AlignUp(m_IndirectBufferSize + 63, (size_t)64);
m_IndirectBuffer.Create(this, GetDev(), m_IndirectBufferSize, 1,
m_IndirectBuffer.Create(this, GetDev(), m_IndirectBufferSize * 2, 1,
GPUBuffer::eGPUBufferGPULocal | GPUBuffer::eGPUBufferIndirectBuffer);
m_IndirectCommandBuffer = GetNextCmd();
@@ -4442,6 +4442,106 @@ void WrappedVulkan::UpdateImageStates(const rdcflatmap<ResourceId, ImageState> &
}
}
void WrappedVulkan::ReplayDraw(VkCommandBuffer cmd, const DrawcallDescription &drawcall)
{
// if this isn't a multidraw (or it's the first draw in a multidraw, it's fairly easy
if(drawcall.drawIndex == 0)
{
if(drawcall.flags & DrawFlags::Indexed)
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), drawcall.numIndices, drawcall.numInstances,
drawcall.indexOffset, drawcall.baseVertex,
drawcall.instanceOffset);
else
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), drawcall.numIndices, drawcall.numInstances,
drawcall.vertexOffset, drawcall.instanceOffset);
}
else
{
// otherwise it's a bit more complex, we need to set up a multidraw with the first N draws nop'd
// out and the parameters added into the last one
VkMarkerRegion::Begin(StringFormat::Fmt("ReplayDraw(drawIndex=%u)", drawcall.drawIndex), cmd);
bytebuf params;
if(drawcall.flags & DrawFlags::Indexed)
{
VkDrawIndexedIndirectCommand drawParams;
drawParams.indexCount = drawcall.numIndices;
drawParams.instanceCount = drawcall.numInstances;
drawParams.firstIndex = drawcall.indexOffset;
drawParams.vertexOffset = drawcall.baseVertex;
drawParams.firstInstance = drawcall.instanceOffset;
params.resize(sizeof(drawParams));
memcpy(params.data(), &drawParams, sizeof(drawParams));
}
else
{
VkDrawIndirectCommand drawParams;
drawParams.vertexCount = drawcall.numIndices;
drawParams.instanceCount = drawcall.numInstances;
drawParams.firstVertex = drawcall.vertexOffset;
drawParams.firstInstance = drawcall.instanceOffset;
params.resize(sizeof(drawParams));
memcpy(params.data(), &drawParams, sizeof(drawParams));
}
// ensure the custom buffer is large enough
VkDeviceSize bufLength = params.size() * (drawcall.drawIndex + 1);
RDCASSERT(bufLength <= m_IndirectBufferSize, bufLength, m_IndirectBufferSize);
VkBufferMemoryBarrier bufBarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
NULL,
VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
Unwrap(m_IndirectBuffer.buf),
m_IndirectBufferSize,
m_IndirectBufferSize,
};
// wait for any previous indirect draws to complete before filling/transferring
DoPipelineBarrier(cmd, 1, &bufBarrier);
// initialise to 0 so all other draws don't draw anything
ObjDisp(cmd)->CmdFillBuffer(Unwrap(cmd), Unwrap(m_IndirectBuffer.buf), m_IndirectBufferSize,
m_IndirectBufferSize, 0);
// wait for fill to complete before update
bufBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
bufBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
DoPipelineBarrier(cmd, 1, &bufBarrier);
// upload the parameters for the draw we want
ObjDisp(cmd)->CmdUpdateBuffer(Unwrap(cmd), Unwrap(m_IndirectBuffer.buf),
m_IndirectBufferSize + params.size() * drawcall.drawIndex,
params.size(), params.data());
// finally wait for copy to complete before drawing from it
bufBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
bufBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
DoPipelineBarrier(cmd, 1, &bufBarrier);
if(drawcall.flags & DrawFlags::Indexed)
ObjDisp(cmd)->CmdDrawIndexedIndirect(Unwrap(cmd), Unwrap(m_IndirectBuffer.buf),
m_IndirectBufferSize, drawcall.drawIndex + 1,
(uint32_t)params.size());
else
ObjDisp(cmd)->CmdDrawIndirect(Unwrap(cmd), Unwrap(m_IndirectBuffer.buf), m_IndirectBufferSize,
drawcall.drawIndex + 1, (uint32_t)params.size());
VkMarkerRegion::End(cmd);
}
}
#if ENABLED(ENABLE_UNIT_TESTS)
#undef None
+1
View File
@@ -1030,6 +1030,7 @@ public:
}
void Shutdown();
void ReplayLog(uint32_t startEventID, uint32_t endEventID, ReplayLogType replayType);
void ReplayDraw(VkCommandBuffer cmd, const DrawcallDescription &drawcall);
ReplayStatus ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers);
SDFile &GetStructuredFile() { return *m_StructuredFile; }
+5 -2
View File
@@ -1036,8 +1036,11 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
// do single draw
m_pDriver->m_RenderState.BeginRenderPassAndApplyState(m_pDriver, cmd,
VulkanRenderState::BindGraphics);
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), patchedIndexCount, mainDraw->numInstances, 0, 0,
mainDraw->instanceOffset);
DrawcallDescription draw = *mainDraw;
draw.numIndices = patchedIndexCount;
draw.baseVertex = 0;
draw.indexOffset = 0;
m_pDriver->ReplayDraw(cmd, draw);
m_pDriver->m_RenderState.EndRenderPass(cmd);
vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
+13 -48
View File
@@ -1177,13 +1177,7 @@ private:
uint32_t occlIndex = (uint32_t)m_OcclusionQueries.size();
ObjDisp(cmd)->CmdBeginQuery(Unwrap(cmd), m_OcclusionPool, occlIndex, m_QueryFlags);
if(drawcall->flags & DrawFlags::Indexed)
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->indexOffset, drawcall->baseVertex,
drawcall->instanceOffset);
else
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
m_pDriver->ReplayDraw(cmd, *drawcall);
ObjDisp(cmd)->CmdEndQuery(Unwrap(cmd), m_OcclusionPool, occlIndex);
m_OcclusionQueries.insert(std::make_pair(eventId, occlIndex));
@@ -1602,13 +1596,7 @@ private:
}
const DrawcallDescription *drawcall = m_pDriver->GetDrawcall(eventId);
if(drawcall->flags & DrawFlags::Indexed)
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->indexOffset, drawcall->baseVertex,
drawcall->instanceOffset);
else
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
m_pDriver->ReplayDraw(cmd, *drawcall);
m_pDriver->GetCmdRenderState().EndRenderPass(cmd);
}
@@ -2141,13 +2129,7 @@ private:
ObjDisp(cmd)->CmdBeginQuery(Unwrap(cmd), m_OcclusionPool, index, m_QueryFlags);
const DrawcallDescription *drawcall = m_pDriver->GetDrawcall(eventId);
if(drawcall->flags & DrawFlags::Indexed)
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->indexOffset, drawcall->baseVertex,
drawcall->instanceOffset);
else
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
m_pDriver->ReplayDraw(cmd, *drawcall);
ObjDisp(cmd)->CmdEndQuery(Unwrap(cmd), m_OcclusionPool, index);
}
@@ -2368,13 +2350,7 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, 0xff);
ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, f);
const DrawcallDescription *drawcall = m_pDriver->GetDrawcall(eid);
if(drawcall->flags & DrawFlags::Indexed)
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->indexOffset, drawcall->baseVertex,
drawcall->instanceOffset);
else
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
m_pDriver->ReplayDraw(cmd, *drawcall);
state.EndRenderPass(cmd);
if(i == 1)
@@ -2465,13 +2441,7 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, 0xff);
ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, f);
const DrawcallDescription *drawcall = m_pDriver->GetDrawcall(eid);
if(drawcall->flags & DrawFlags::Indexed)
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->indexOffset, drawcall->baseVertex,
drawcall->instanceOffset);
else
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
m_pDriver->ReplayDraw(cmd, *drawcall);
state.EndRenderPass(cmd);
CopyImagePixel(cmd, colourCopyParams, (fragsProcessed + f) * sizeof(PerFragmentInfo) +
@@ -2736,20 +2706,15 @@ struct VulkanPixelHistoryDiscardedFragmentsCallback : VulkanPixelHistoryCallback
ObjDisp(cmd)->CmdBeginQuery(Unwrap(cmd), m_OcclusionPool, queryId, m_QueryFlags);
const DrawcallDescription *drawcall = m_pDriver->GetDrawcall(eid);
uint32_t primId = primIds[i];
DrawcallDescription draw = *drawcall;
draw.numIndices = RENDERDOC_NumVerticesPerPrimitive(drawcall->topology);
draw.indexOffset += RENDERDOC_VertexOffset(drawcall->topology, primId);
draw.vertexOffset += RENDERDOC_VertexOffset(drawcall->topology, primId);
// TODO once pixel history distinguishes between instances, draw only the instance for
// this fragment
if(drawcall->flags & DrawFlags::Indexed)
ObjDisp(cmd)->CmdDrawIndexed(
Unwrap(cmd), RENDERDOC_NumVerticesPerPrimitive(drawcall->topology),
RDCMAX(1U, drawcall->numInstances),
drawcall->indexOffset + RENDERDOC_VertexOffset(drawcall->topology, primId),
drawcall->baseVertex, drawcall->instanceOffset);
else
ObjDisp(cmd)->CmdDraw(
Unwrap(cmd), RENDERDOC_NumVerticesPerPrimitive(drawcall->topology),
RDCMAX(1U, drawcall->numInstances),
drawcall->vertexOffset + RENDERDOC_VertexOffset(drawcall->topology, primId),
drawcall->instanceOffset);
// this fragment.
// TODO replay with a dummy index buffer so that all primitives other than the target one are
// degenerate - that way the vertex index etc is still the same as it should be.
m_pDriver->ReplayDraw(cmd, draw);
ObjDisp(cmd)->CmdEndQuery(Unwrap(cmd), m_OcclusionPool, queryId);
m_OcclusionIndices[make_rdcpair<uint32_t, uint32_t>(eid, primId)] = queryId;
+5 -21
View File
@@ -2676,17 +2676,7 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state)
ObjDisp(cmd)->CmdBeginTransformFeedbackEXT(Unwrap(cmd), 0, 1, NULL, NULL);
if(drawcall->flags & DrawFlags::Indexed)
{
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->indexOffset, drawcall->baseVertex,
drawcall->instanceOffset);
}
else
{
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
}
m_pDriver->ReplayDraw(cmd, *drawcall);
ObjDisp(cmd)->CmdEndTransformFeedbackEXT(Unwrap(cmd), 0, 1, NULL, NULL);
@@ -2731,6 +2721,8 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state)
state.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics);
DrawcallDescription draw = *drawcall;
// do incremental draws to get the output size. We have to do this O(N^2) style because
// there's no way to replay only a single instance. We have to replay 1, 2, 3, ... N
// instances and count the total number of verts each time, then we can see from the
@@ -2745,16 +2737,8 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state)
ObjDisp(cmd)->CmdBeginTransformFeedbackEXT(Unwrap(cmd), 0, 1, NULL, NULL);
if(drawcall->flags & DrawFlags::Indexed)
{
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), drawcall->numIndices, inst, drawcall->indexOffset,
drawcall->baseVertex, drawcall->instanceOffset);
}
else
{
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), drawcall->numIndices, inst, drawcall->vertexOffset,
drawcall->instanceOffset);
}
draw.numInstances = inst;
m_pDriver->ReplayDraw(cmd, draw);
ObjDisp(cmd)->CmdEndTransformFeedbackEXT(Unwrap(cmd), 0, 1, NULL, NULL);
+1 -10
View File
@@ -4084,16 +4084,7 @@ ShaderDebugTrace *VulkanReplay::DebugPixel(uint32_t eventId, uint32_t x, uint32_
modifiedstate.BeginRenderPassAndApplyState(m_pDriver, cmd, VulkanRenderState::BindGraphics);
if(draw->flags & DrawFlags::Indexed)
{
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), draw->numIndices, draw->numInstances,
draw->indexOffset, draw->baseVertex, draw->instanceOffset);
}
else
{
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), draw->numIndices, draw->numInstances, draw->vertexOffset,
draw->instanceOffset);
}
m_pDriver->ReplayDraw(cmd, *draw);
modifiedstate.EndRenderPass(cmd);
@@ -73,7 +73,7 @@ VkIndirectPatchData WrappedVulkan::FetchIndirectData(VkIndirectPatchType type,
VkBufferMemoryBarrier buf = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
NULL,
VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_ALL_WRITE_BITS,
VK_ACCESS_TRANSFER_READ_BIT,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
@@ -461,22 +461,68 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirect(SerialiserType &ser, VkCommandBu
// when we have a callback, submit every drawcall individually to the callback
if(m_DrawcallCallback && IsDrawInRenderPass())
{
VkMarkerRegion::Begin(
StringFormat::Fmt("Drawcall callback replay (drawCount=%u)", count), commandBuffer);
// first copy off the buffer segment to our indirect draw buffer
VkBufferMemoryBarrier bufBarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
NULL,
VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
Unwrap(buffer),
offset,
(count > 0 ? stride * (count - 1) : 0) + sizeof(VkDrawIndirectCommand),
};
DoPipelineBarrier(commandBuffer, 1, &bufBarrier);
VkBufferCopy region = {offset, 0, bufBarrier.size};
ObjDisp(commandBuffer)
->CmdCopyBuffer(Unwrap(commandBuffer), Unwrap(buffer),
Unwrap(m_IndirectBuffer.buf), 1, &region);
// wait for the copy to finish
bufBarrier.buffer = Unwrap(m_IndirectBuffer.buf);
bufBarrier.offset = 0;
DoPipelineBarrier(commandBuffer, 1, &bufBarrier);
bufBarrier.size = sizeof(VkDrawIndirectCommand);
for(uint32_t i = 0; i < count; i++)
{
uint32_t eventId = HandlePreCallback(commandBuffer, DrawFlags::Drawcall, i + 1);
// draw up to and including i. The previous draws will be nop'd out
ObjDisp(commandBuffer)
->CmdDrawIndirect(Unwrap(commandBuffer), Unwrap(buffer), offset, 1, stride);
->CmdDrawIndirect(Unwrap(commandBuffer), Unwrap(m_IndirectBuffer.buf), 0, i + 1,
stride);
if(eventId && m_DrawcallCallback->PostDraw(eventId, commandBuffer))
{
ObjDisp(commandBuffer)
->CmdDrawIndirect(Unwrap(commandBuffer), Unwrap(buffer), offset, 1, stride);
->CmdDrawIndirect(Unwrap(commandBuffer), Unwrap(m_IndirectBuffer.buf), 0,
i + 1, stride);
m_DrawcallCallback->PostRedraw(eventId, commandBuffer);
}
offset += stride;
// now that we're done, nop out this draw so that the next time around we only draw
// the next draw.
bufBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
bufBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
DoPipelineBarrier(commandBuffer, 1, &bufBarrier);
ObjDisp(commandBuffer)
->CmdFillBuffer(Unwrap(commandBuffer), bufBarrier.buffer, bufBarrier.offset,
bufBarrier.size, 0);
bufBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
bufBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
DoPipelineBarrier(commandBuffer, 1, &bufBarrier);
bufBarrier.offset += stride;
}
VkMarkerRegion::End(commandBuffer);
}
// To add the multidraw, we made an event N that is the 'parent' marker, then
// N+1, N+2, N+3, ... for each of the sub-draws. If the first sub-draw is selected
@@ -521,7 +567,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirect(SerialiserType &ser, VkCommandBu
VK_QUEUE_FAMILY_IGNORED,
Unwrap(m_IndirectBuffer.buf),
0,
VK_WHOLE_SIZE,
m_IndirectBufferSize,
};
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
@@ -601,8 +647,8 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirect(SerialiserType &ser, VkCommandBu
// add on the size we'll need for an indirect buffer in the worst case.
// Note that we'll only ever be partially replaying one draw at a time, so we only need the
// worst case.
m_IndirectBufferSize = RDCMAX(m_IndirectBufferSize, sizeof(VkDrawIndirectCommand) +
(count > 0 ? count - 1 : 0) * stride);
m_IndirectBufferSize =
RDCMAX(m_IndirectBufferSize, sizeof(VkDrawIndirectCommand) + count * stride);
rdcstr name = "vkCmdDrawIndirect";
@@ -902,7 +948,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirect(SerialiserType &ser,
VK_QUEUE_FAMILY_IGNORED,
Unwrap(m_IndirectBuffer.buf),
0,
VK_WHOLE_SIZE,
m_IndirectBufferSize,
};
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
@@ -984,8 +1030,8 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirect(SerialiserType &ser,
// add on the size we'll need for an indirect buffer in the worst case.
// Note that we'll only ever be partially replaying one draw at a time, so we only need the
// worst case.
m_IndirectBufferSize = RDCMAX(m_IndirectBufferSize, sizeof(VkDrawIndexedIndirectCommand) +
(count > 0 ? count - 1 : 0) * stride);
m_IndirectBufferSize =
RDCMAX(m_IndirectBufferSize, sizeof(VkDrawIndexedIndirectCommand) + count * stride);
rdcstr name = "vkCmdDrawIndexedIndirect";
@@ -2775,7 +2821,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirectCount(SerialiserType &ser,
VK_QUEUE_FAMILY_IGNORED,
Unwrap(m_IndirectBuffer.buf),
0,
VK_WHOLE_SIZE,
m_IndirectBufferSize,
};
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
@@ -3029,23 +3075,68 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirectCount(
// when we have a callback, submit every drawcall individually to the callback
if(m_DrawcallCallback && IsDrawInRenderPass())
{
VkMarkerRegion::Begin(
StringFormat::Fmt("Drawcall callback replay (drawCount=%u)", count), commandBuffer);
// first copy off the buffer segment to our indirect draw buffer
VkBufferMemoryBarrier bufBarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
NULL,
VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
Unwrap(buffer),
offset,
(count > 0 ? stride * (count - 1) : 0) + sizeof(VkDrawIndirectCommand),
};
DoPipelineBarrier(commandBuffer, 1, &bufBarrier);
VkBufferCopy region = {offset, 0, bufBarrier.size};
ObjDisp(commandBuffer)
->CmdCopyBuffer(Unwrap(commandBuffer), Unwrap(buffer), Unwrap(m_IndirectBuffer.buf),
1, &region);
// wait for the copy to finish
bufBarrier.buffer = Unwrap(m_IndirectBuffer.buf);
bufBarrier.offset = 0;
DoPipelineBarrier(commandBuffer, 1, &bufBarrier);
bufBarrier.size = sizeof(VkDrawIndexedIndirectCommand);
for(uint32_t i = 0; i < count; i++)
{
uint32_t eventId = HandlePreCallback(commandBuffer, DrawFlags::Drawcall, i + 1);
// draw up to and including i. The previous draws will be nop'd out
ObjDisp(commandBuffer)
->CmdDrawIndexedIndirect(Unwrap(commandBuffer), Unwrap(buffer), offset, 1, stride);
->CmdDrawIndexedIndirect(Unwrap(commandBuffer), Unwrap(m_IndirectBuffer.buf), 0,
i + 1, stride);
if(eventId && m_DrawcallCallback->PostDraw(eventId, commandBuffer))
{
ObjDisp(commandBuffer)
->CmdDrawIndexedIndirect(Unwrap(commandBuffer), Unwrap(buffer), offset, 1,
stride);
->CmdDrawIndexedIndirect(Unwrap(commandBuffer), Unwrap(m_IndirectBuffer.buf), 0,
i + 1, stride);
m_DrawcallCallback->PostRedraw(eventId, commandBuffer);
}
offset += stride;
// now that we're done, nop out this draw so that the next time around we only draw
// the next draw.
bufBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
bufBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
DoPipelineBarrier(commandBuffer, 1, &bufBarrier);
ObjDisp(commandBuffer)
->CmdFillBuffer(Unwrap(commandBuffer), bufBarrier.buffer, bufBarrier.offset,
bufBarrier.size, 0);
bufBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
bufBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
DoPipelineBarrier(commandBuffer, 1, &bufBarrier);
bufBarrier.offset += stride;
}
VkMarkerRegion::End(commandBuffer);
}
// To add the multidraw, we made an event N that is the 'parent' marker, then
// N+1, N+2, N+3, ... for each of the sub-draws. If the first sub-draw is selected
@@ -3090,7 +3181,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirectCount(
VK_QUEUE_FAMILY_IGNORED,
Unwrap(m_IndirectBuffer.buf),
0,
VK_WHOLE_SIZE,
m_IndirectBufferSize,
};
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,