diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 28c01e26..d2582bcd 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -3195,7 +3195,7 @@ namespace dxvk { ? pBuffer->GetBufferSlice() : DxvkBufferSlice() ] (DxvkContext* ctx) { - ctx->bindDrawBuffer(cBufferSlice); + ctx->bindDrawBuffers(cBufferSlice, DxvkBufferSlice()); }); } diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 652d4c32..aaee55af 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -128,10 +128,13 @@ namespace dxvk { } - void DxvkContext::bindDrawBuffer( - const DxvkBufferSlice& buffer) { - if (!m_state.id.argBuffer.matches(buffer)) { - m_state.id.argBuffer = buffer; + void DxvkContext::bindDrawBuffers( + const DxvkBufferSlice& argBuffer, + const DxvkBufferSlice& cntBuffer) { + if (!m_state.id.argBuffer.matches(argBuffer) + || !m_state.id.argBuffer.matches(cntBuffer)) { + m_state.id.argBuffer = argBuffer; + m_state.id.cntBuffer = cntBuffer; m_flags.set(DxvkContextFlag::DirtyDrawBuffer); } @@ -1458,6 +1461,32 @@ namespace dxvk { } + void DxvkContext::drawIndirectCount( + VkDeviceSize offset, + VkDeviceSize countOffset, + uint32_t maxCount, + uint32_t stride) { + this->commitGraphicsState(false); + + if (this->validateGraphicsState()) { + auto argDescriptor = m_state.id.argBuffer.getDescriptor(); + auto cntDescriptor = m_state.id.cntBuffer.getDescriptor(); + + m_cmd->cmdDrawIndirectCount( + argDescriptor.buffer.buffer, + argDescriptor.buffer.offset + offset, + cntDescriptor.buffer.buffer, + cntDescriptor.buffer.offset + countOffset, + maxCount, stride); + + this->commitGraphicsPostBarriers(); + this->trackDrawBuffer(); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDrawCalls, 1); + } + + void DxvkContext::drawIndexed( uint32_t indexCount, uint32_t instanceCount, @@ -1501,6 +1530,32 @@ namespace dxvk { } + void DxvkContext::drawIndexedIndirectCount( + VkDeviceSize offset, + VkDeviceSize countOffset, + uint32_t maxCount, + uint32_t stride) { + this->commitGraphicsState(true); + + if (this->validateGraphicsState()) { + auto argDescriptor = m_state.id.argBuffer.getDescriptor(); + auto cntDescriptor = m_state.id.cntBuffer.getDescriptor(); + + m_cmd->cmdDrawIndexedIndirectCount( + argDescriptor.buffer.buffer, + argDescriptor.buffer.offset + offset, + cntDescriptor.buffer.buffer, + cntDescriptor.buffer.offset + countOffset, + maxCount, stride); + + this->commitGraphicsPostBarriers(); + this->trackDrawBuffer(); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDrawCalls, 1); + } + + void DxvkContext::drawIndirectXfb( const DxvkBufferSlice& counterBuffer, uint32_t counterDivisor, @@ -4004,6 +4059,9 @@ namespace dxvk { if (m_state.id.argBuffer.defined()) m_cmd->trackResource(m_state.id.argBuffer.buffer()); + + if (m_state.id.cntBuffer.defined()) + m_cmd->trackResource(m_state.id.cntBuffer.buffer()); } } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 91204d2b..c6a8b538 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -105,12 +105,14 @@ namespace dxvk { /** * \brief Binds indirect argument buffer * - * Sets the buffer that is going to be used + * Sets the buffers that are going to be used * for indirect draw and dispatch operations. - * \param [in] buffer New argument buffer + * \param [in] argBuffer New argument buffer + * \param [in] cntBuffer New count buffer */ - void bindDrawBuffer( - const DxvkBufferSlice& buffer); + void bindDrawBuffers( + const DxvkBufferSlice& argBuffer, + const DxvkBufferSlice& cntBuffer); /** * \brief Binds index buffer @@ -525,12 +527,12 @@ namespace dxvk { uint32_t firstInstance); /** - * \brief Indirect indexed draw call + * \brief Indirect draw call * * Takes arguments from a buffer. The structure stored * in the buffer must be of type \c VkDrawIndirectCommand. * \param [in] offset Draw buffer offset - * \param [in] count Number of dispatch calls + * \param [in] count Number of draws * \param [in] stride Stride between dispatch calls */ void drawIndirect( @@ -538,6 +540,22 @@ namespace dxvk { uint32_t count, uint32_t stride); + /** + * \brief Indirect draw call + * + * Takes arguments from a buffer. The structure stored + * in the buffer must be of type \c VkDrawIndirectCommand. + * \param [in] offset Draw buffer offset + * \param [in] countOffset Draw count offset + * \param [in] maxCount Maximum number of draws + * \param [in] stride Stride between dispatch calls + */ + void drawIndirectCount( + VkDeviceSize offset, + VkDeviceSize countOffset, + uint32_t maxCount, + uint32_t stride); + /** * \brief Draws primitives using an index buffer * @@ -560,7 +578,7 @@ namespace dxvk { * Takes arguments from a buffer. The structure type for * the draw buffer is \c VkDrawIndexedIndirectCommand. * \param [in] offset Draw buffer offset - * \param [in] count Number of dispatch calls + * \param [in] count Number of draws * \param [in] stride Stride between dispatch calls */ void drawIndexedIndirect( @@ -568,6 +586,22 @@ namespace dxvk { uint32_t count, uint32_t stride); + /** + * \brief Indirect indexed draw call + * + * Takes arguments from a buffer. The structure type for + * the draw buffer is \c VkDrawIndexedIndirectCommand. + * \param [in] offset Draw buffer offset + * \param [in] countOffset Draw count offset + * \param [in] maxCount Maximum number of draws + * \param [in] stride Stride between dispatch calls + */ + void drawIndexedIndirectCount( + VkDeviceSize offset, + VkDeviceSize countOffset, + uint32_t maxCount, + uint32_t stride); + /** * \brief Transform feddback draw call diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index 69ec26bb..5cae2d69 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -71,6 +71,7 @@ namespace dxvk { struct DxvkIndirectDrawState { DxvkBufferSlice argBuffer; + DxvkBufferSlice cntBuffer; };