Skip to content

Commit 2e215d9

Browse files
committed
Add support for DX12 and Vulkan drawIndexedIndirectCount
1 parent 06d4fdc commit 2e215d9

9 files changed

Lines changed: 96 additions & 2 deletions

File tree

include/nvrhi/nvrhi.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2665,6 +2665,9 @@ namespace nvrhi
26652665

26662666
IBuffer* indirectParams = nullptr;
26672667

2668+
IBuffer* indirectCountBuffer = nullptr;
2669+
uint32_t indirectCountOffset = 0;
2670+
26682671
GraphicsState& setPipeline(IGraphicsPipeline* value) { pipeline = value; return *this; }
26692672
GraphicsState& setFramebuffer(IFramebuffer* value) { framebuffer = value; return *this; }
26702673
GraphicsState& setViewport(const ViewportState& value) { viewport = value; return *this; }
@@ -2675,6 +2678,7 @@ namespace nvrhi
26752678
GraphicsState& addVertexBuffer(const VertexBufferBinding& value) { vertexBuffers.push_back(value); return *this; }
26762679
GraphicsState& setIndexBuffer(const IndexBufferBinding& value) { indexBuffer = value; return *this; }
26772680
GraphicsState& setIndirectParams(IBuffer* value) { indirectParams = value; return *this; }
2681+
GraphicsState& setIndirectCountBuffer(IBuffer* buf, uint32_t offset = 0) { indirectCountBuffer = buf; indirectCountOffset = offset; return *this; }
26782682
};
26792683

26802684
struct DrawArguments
@@ -3286,7 +3290,14 @@ namespace nvrhi
32863290
// - DX12: Maps to ExecuteIndirect with a predefined signature.
32873291
// - Vulkan: Maps to vkCmdDrawIndexedIndirect.
32883292
virtual void drawIndexedIndirect(uint32_t offsetBytes, uint32_t drawCount = 1) = 0;
3289-
3293+
3294+
// Draws primitives with indexed vertices using the parameters provided in the indirect arguments buffer.
3295+
// The draw count is read from the indirectCountBuffer specified in setGraphicsState(...).
3296+
// - DX11: Not supported (falls back to maxDrawCount draws).
3297+
// - DX12: Maps to ExecuteIndirect with pCountBuffer parameter.
3298+
// - Vulkan: Maps to vkCmdDrawIndexedIndirectCount.
3299+
virtual void drawIndexedIndirectCount(uint32_t offsetBytes, uint32_t maxDrawCount) = 0;
3300+
32903301
// Sets the specified compute state on the command list.
32913302
// The state includes the pipeline (or individual shaders on DX11) and all resources bound to it.
32923303
// See the members of ComputeState for more information.

src/d3d11/d3d11-backend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ namespace nvrhi::d3d11
323323
void drawIndexed(const DrawArguments& args) override;
324324
void drawIndirect(uint32_t offsetBytes, uint32_t drawCount) override;
325325
void drawIndexedIndirect(uint32_t offsetBytes, uint32_t drawCount) override;
326+
void drawIndexedIndirectCount(uint32_t offsetBytes, uint32_t maxDrawCount) override;
326327

327328
void setComputeState(const ComputeState& state) override;
328329
void dispatch(uint32_t groupsX, uint32_t groupsY = 1, uint32_t groupsZ = 1) override;

src/d3d11/d3d11-graphics.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,12 @@ namespace nvrhi::d3d11
414414
}
415415
}
416416

417+
void CommandList::drawIndexedIndirectCount(uint32_t offsetBytes, uint32_t maxDrawCount)
418+
{
419+
// D3D11 doesn't support count buffers - fall back to default drawIndexedIndirect behavior
420+
drawIndexedIndirect(offsetBytes, maxDrawCount);
421+
}
422+
417423
ID3D11BlendState* Device::getBlendState(const BlendState& blendState)
418424
{
419425
size_t hash = 0;

src/d3d12/d3d12-backend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,7 @@ namespace nvrhi::d3d12
979979
void drawIndexed(const DrawArguments& args) override;
980980
void drawIndirect(uint32_t offsetBytes, uint32_t drawCount) override;
981981
void drawIndexedIndirect(uint32_t offsetBytes, uint32_t drawCount) override;
982+
void drawIndexedIndirectCount(uint32_t offsetBytes, uint32_t maxDrawCount) override;
982983

983984
void setComputeState(const ComputeState& state) override;
984985
void dispatch(uint32_t groupsX, uint32_t groupsY = 1, uint32_t groupsZ = 1) override;

src/d3d12/d3d12-graphics.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,26 @@ namespace nvrhi::d3d12
580580

581581
m_ActiveCommandList->commandList->ExecuteIndirect(m_Context.drawIndexedIndirectSignature, drawCount, indirectParams->resource, offsetBytes, nullptr, 0);
582582
}
583-
583+
584+
void CommandList::drawIndexedIndirectCount(uint32_t offsetBytes, uint32_t maxDrawCount)
585+
{
586+
Buffer* indirectParams = checked_cast<Buffer*>(m_CurrentGraphicsState.indirectParams);
587+
Buffer* countBuf = checked_cast<Buffer*>(m_CurrentGraphicsState.indirectCountBuffer);
588+
assert(indirectParams);
589+
assert(countBuf);
590+
591+
updateGraphicsVolatileBuffers();
592+
593+
m_ActiveCommandList->commandList->ExecuteIndirect(
594+
m_Context.drawIndexedIndirectSignature,
595+
maxDrawCount,
596+
indirectParams->resource,
597+
offsetBytes,
598+
countBuf->resource,
599+
m_CurrentGraphicsState.indirectCountOffset
600+
);
601+
}
602+
584603
DX12_ViewportState convertViewportState(const RasterState& rasterState, const FramebufferInfoEx& framebufferInfo, const ViewportState& vpState)
585604
{
586605
DX12_ViewportState ret;

src/validation/validation-backend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ namespace nvrhi::validation
223223
void drawIndexed(const DrawArguments& args) override;
224224
void drawIndirect(uint32_t offsetBytes, uint32_t drawCount) override;
225225
void drawIndexedIndirect(uint32_t offsetBytes, uint32_t drawCount) override;
226+
void drawIndexedIndirectCount(uint32_t offsetBytes, uint32_t maxDrawCount) override;
226227

227228
void setComputeState(const ComputeState& state) override;
228229
void dispatch(uint32_t groupsX, uint32_t groupsY = 1, uint32_t groupsZ = 1) override;

src/validation/validation-commandlist.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,39 @@ namespace nvrhi::validation
762762
m_CommandList->drawIndexedIndirect(offsetBytes, drawCount);
763763
}
764764

765+
void CommandListWrapper::drawIndexedIndirectCount(uint32_t offsetBytes, uint32_t maxDrawCount)
766+
{
767+
if (!requireOpenState())
768+
return;
769+
770+
if (!requireType(CommandQueue::Graphics, "drawIndexedIndirectCount"))
771+
return;
772+
773+
if (!m_GraphicsStateSet)
774+
{
775+
error("Graphics state is not set before a drawIndexedIndirectCount call.\n"
776+
"Note that setting compute state invalidates the graphics state.");
777+
return;
778+
}
779+
780+
if (!m_CurrentGraphicsState.indirectParams)
781+
{
782+
error("Indirect params buffer is not set before a drawIndexedIndirectCount call.");
783+
return;
784+
}
785+
786+
if (!m_CurrentGraphicsState.indirectCountBuffer)
787+
{
788+
error("Indirect count buffer is not set before a drawIndexedIndirectCount call.");
789+
return;
790+
}
791+
792+
if (!validatePushConstants("graphics", "setGraphicsState"))
793+
return;
794+
795+
m_CommandList->drawIndexedIndirectCount(offsetBytes, maxDrawCount);
796+
}
797+
765798
void CommandListWrapper::setComputeState(const ComputeState& state)
766799
{
767800
if (!requireOpenState())

src/vulkan/vulkan-backend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,6 +1239,7 @@ namespace nvrhi::vulkan
12391239
void drawIndexed(const DrawArguments& args) override;
12401240
void drawIndirect(uint32_t offsetBytes, uint32_t drawCount) override;
12411241
void drawIndexedIndirect(uint32_t offsetBytes, uint32_t drawCount) override;
1242+
void drawIndexedIndirectCount(uint32_t offsetBytes, uint32_t maxDrawCount) override;
12421243

12431244
void setComputeState(const ComputeState& state) override;
12441245
void dispatch(uint32_t groupsX, uint32_t groupsY = 1, uint32_t groupsZ = 1) override;

src/vulkan/vulkan-graphics.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,4 +713,25 @@ namespace nvrhi::vulkan
713713
m_CurrentCmdBuf->cmdBuf.drawIndexedIndirect(indirectParams->buffer, offsetBytes, drawCount, sizeof(DrawIndexedIndirectArguments));
714714
}
715715

716+
void CommandList::drawIndexedIndirectCount(uint32_t offsetBytes, uint32_t maxDrawCount)
717+
{
718+
assert(m_CurrentCmdBuf);
719+
720+
updateGraphicsVolatileBuffers();
721+
722+
Buffer* indirectParams = checked_cast<Buffer*>(m_CurrentGraphicsState.indirectParams);
723+
Buffer* countBuf = checked_cast<Buffer*>(m_CurrentGraphicsState.indirectCountBuffer);
724+
assert(indirectParams);
725+
assert(countBuf);
726+
727+
m_CurrentCmdBuf->cmdBuf.drawIndexedIndirectCount(
728+
indirectParams->buffer,
729+
offsetBytes,
730+
countBuf->buffer,
731+
m_CurrentGraphicsState.indirectCountOffset,
732+
maxDrawCount,
733+
sizeof(DrawIndexedIndirectArguments)
734+
);
735+
}
736+
716737
} // namespace nvrhi::vulkan

0 commit comments

Comments
 (0)