From c61200d35f8562ff525544033d48b58fadd31c6f Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 20 Nov 2018 10:35:23 +0100 Subject: [PATCH] [dxvk] Introduce single-use mode for CS chunks This allows us to reset the CS chunk immediately while executing it, which can reduce the overhead of the reset operation and may lead to resources being released earlier. --- src/d3d11/d3d11_context.cpp | 2 +- src/d3d11/d3d11_device.h | 4 ++-- src/dxvk/dxvk_cs.cpp | 45 ++++++++++++++++++++++++++++--------- src/dxvk/dxvk_cs.h | 29 ++++++++++++++++++++---- 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 1fa53d8d..6ac4c4a5 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -3350,7 +3350,7 @@ namespace dxvk { DxvkCsChunkRef D3D11DeviceContext::AllocCsChunk() { - return m_parent->AllocCsChunk(); + return m_parent->AllocCsChunk(0); } } diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index c8fccffc..0fe46678 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -333,8 +333,8 @@ namespace dxvk { DXGI_FORMAT Format, DXGI_VK_FORMAT_MODE Mode) const; - DxvkCsChunkRef AllocCsChunk() { - DxvkCsChunk* chunk = m_csChunkPool.allocChunk(); + DxvkCsChunkRef AllocCsChunk(DxvkCsChunkFlags flags) { + DxvkCsChunk* chunk = m_csChunkPool.allocChunk(flags); return DxvkCsChunkRef(chunk, &m_csChunkPool); } diff --git a/src/dxvk/dxvk_cs.cpp b/src/dxvk/dxvk_cs.cpp index ff19f9b5..bdc4f0da 100644 --- a/src/dxvk/dxvk_cs.cpp +++ b/src/dxvk/dxvk_cs.cpp @@ -12,12 +12,32 @@ namespace dxvk { } + void DxvkCsChunk::init(DxvkCsChunkFlags flags) { + m_flags = flags; + } + + void DxvkCsChunk::executeAll(DxvkContext* ctx) { auto cmd = m_head; - while (cmd != nullptr) { - cmd->exec(ctx); - cmd = cmd->next(); + if (m_flags.test(DxvkCsChunkFlag::SingleUse)) { + m_commandCount = 0; + m_commandOffset = 0; + + while (cmd != nullptr) { + auto next = cmd->next(); + cmd->exec(ctx); + cmd->~DxvkCsCmd(); + cmd = next; + } + + m_head = nullptr; + m_tail = nullptr; + } else { + while (cmd != nullptr) { + cmd->exec(ctx); + cmd = cmd->next(); + } } } @@ -25,15 +45,15 @@ namespace dxvk { void DxvkCsChunk::reset() { auto cmd = m_head; + m_commandCount = 0; + m_commandOffset = 0; + while (cmd != nullptr) { auto next = cmd->next(); cmd->~DxvkCsCmd(); cmd = next; } - m_commandCount = 0; - m_commandOffset = 0; - m_head = nullptr; m_tail = nullptr; } @@ -50,17 +70,22 @@ namespace dxvk { } - DxvkCsChunk* DxvkCsChunkPool::allocChunk() { + DxvkCsChunk* DxvkCsChunkPool::allocChunk(DxvkCsChunkFlags flags) { + DxvkCsChunk* chunk = nullptr; + { std::lock_guard lock(m_mutex); if (m_chunks.size() != 0) { - DxvkCsChunk* chunk = m_chunks.back(); + chunk = m_chunks.back(); m_chunks.pop_back(); - return chunk; } } - return new DxvkCsChunk(); + if (!chunk) + chunk = new DxvkCsChunk(); + + chunk->init(flags); + return chunk; } diff --git a/src/dxvk/dxvk_cs.h b/src/dxvk/dxvk_cs.h index 82113af8..bbc54e17 100644 --- a/src/dxvk/dxvk_cs.h +++ b/src/dxvk/dxvk_cs.h @@ -82,6 +82,18 @@ namespace dxvk { }; + /** + * \brief Submission flags + */ + enum class DxvkCsChunkFlag : uint32_t { + /// Indicates that the submitted chunk will + /// no longer be needed after one submission. + SingleUse, + }; + + using DxvkCsChunkFlags = Flags; + + /** * \brief Command chunk * @@ -103,7 +115,7 @@ namespace dxvk { size_t commandCount() const { return m_commandCount; } - + /** * \brief Tries to add a command to the chunk * @@ -136,6 +148,12 @@ namespace dxvk { return true; } + /** + * \brief Initializes chunk for recording + * \param [in] flags Chunk flags + */ + void init(DxvkCsChunkFlags flags); + /** * \brief Executes all commands * @@ -161,6 +179,8 @@ namespace dxvk { DxvkCsCmd* m_head = nullptr; DxvkCsCmd* m_tail = nullptr; + + DxvkCsChunkFlags m_flags; alignas(64) char m_data[MaxBlockSize]; @@ -190,9 +210,10 @@ namespace dxvk { * * Takes an existing chunk from the pool, * or creates a new one if necessary. + * \param [in] flags Chunk flags * \returns Allocated chunk object */ - DxvkCsChunk* allocChunk(); + DxvkCsChunk* allocChunk(DxvkCsChunkFlags flags); /** * \brief Releases a chunk @@ -288,8 +309,8 @@ namespace dxvk { } }; - - + + /** * \brief Command stream thread *