1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 20:52:10 +01:00

[d3d11] Recycle command lists from deferred contexts

Can save a few memory allocations and deallocations at runtime.
This commit is contained in:
Philip Rebohle 2019-10-25 22:08:21 +02:00
parent 7f66373a69
commit 4e3da45fde
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
5 changed files with 132 additions and 12 deletions

View File

@ -4,10 +4,11 @@
namespace dxvk {
D3D11CommandList::D3D11CommandList(
D3D11Device* pDevice,
UINT ContextFlags)
: m_device (pDevice),
m_contextFlags(ContextFlags) { }
D3D11Device* pDevice,
D3D11CommandListAllocator* pAllocator)
: m_device(pDevice), m_allocator(pAllocator) {
}
D3D11CommandList::~D3D11CommandList() {
@ -25,8 +26,14 @@ namespace dxvk {
ULONG STDMETHODCALLTYPE D3D11CommandList::Release() {
ULONG refCount = --m_refCount;
if (!refCount)
if (!refCount) {
Reset();
m_allocator->RecycleCommandList(this);
m_device->Release();
}
return refCount;
}
@ -81,6 +88,15 @@ namespace dxvk {
MarkSubmitted();
}
void D3D11CommandList::Reset() {
m_chunks.clear();
m_contextFlags = 0;
m_submitted = false;
m_warned = false;
}
void D3D11CommandList::MarkSubmitted() {
@ -92,4 +108,42 @@ namespace dxvk {
}
}
D3D11CommandListAllocator::D3D11CommandListAllocator(D3D11Device* pDevice)
: m_device(pDevice) {
}
D3D11CommandListAllocator::~D3D11CommandListAllocator() {
for (uint32_t i = 0; i < m_listCount; i++)
delete m_lists[i];
}
D3D11CommandList* D3D11CommandListAllocator::AllocCommandList(
UINT ContextFlags) {
std::lock_guard<std::mutex> lock(m_mutex);
D3D11CommandList* result = nullptr;
if (m_listCount)
result = m_lists[--m_listCount];
else
result = new D3D11CommandList(m_device, this);
result->SetContextFlags(ContextFlags);
return result;
}
void D3D11CommandListAllocator::RecycleCommandList(
D3D11CommandList* pCommandList) {
std::lock_guard<std::mutex> lock(m_mutex);
if (m_listCount < m_lists.size())
m_lists[m_listCount++] = pCommandList;
else
delete pCommandList;
}
}

View File

@ -1,16 +1,21 @@
#pragma once
#include <mutex>
#include <vector>
#include "d3d11_context.h"
namespace dxvk {
class D3D11CommandListAllocator;
class D3D11CommandList : public D3D11DeviceChild<ID3D11CommandList, NoWrapper> {
public:
D3D11CommandList(
D3D11Device* pDevice,
UINT ContextFlags);
D3D11Device* pDevice,
D3D11CommandListAllocator* pAllocator);
~D3D11CommandList();
@ -26,6 +31,10 @@ namespace dxvk {
ID3D11Device **ppDevice) final;
UINT STDMETHODCALLTYPE GetContextFlags() final;
void SetContextFlags(UINT ContextFlags) {
m_contextFlags = ContextFlags;
}
void AddChunk(
DxvkCsChunkRef&& Chunk);
@ -38,9 +47,11 @@ namespace dxvk {
private:
D3D11Device* const m_device;
UINT const m_contextFlags;
D3D11Device* m_device;
D3D11CommandListAllocator* m_allocator;
uint32_t m_contextFlags = 0;
std::vector<DxvkCsChunkRef> m_chunks;
std::atomic<bool> m_submitted = { false };
@ -48,8 +59,56 @@ namespace dxvk {
std::atomic<uint32_t> m_refCount = { 0u };
void Reset();
void MarkSubmitted();
};
/**
* \brief Command list allocator
*
* Creates and recycles command list instances
* in order to reduce deferred context overhead.
*/
class D3D11CommandListAllocator {
public:
D3D11CommandListAllocator(
D3D11Device* pDevice);
~D3D11CommandListAllocator();
/**
* \brief Allocates a command list
*
* \param [in] ContextFlags Flags of the parent context
* \returns The command list
*/
D3D11CommandList* AllocCommandList(
UINT ContextFlags);
/**
* \brief Recycles a command list
*
* Automatically called when the command list
* in question reaches a ref count of zero.
* \param [in] pCommandList The command list
*/
void RecycleCommandList(
D3D11CommandList* pCommandList);
private:
D3D11Device* m_device;
std::mutex m_mutex;
std::array<D3D11CommandList*, 64> m_lists;
uint32_t m_listCount = 0;
};
}

View File

@ -309,7 +309,7 @@ namespace dxvk {
Com<D3D11CommandList> D3D11DeferredContext::CreateCommandList() {
return new D3D11CommandList(m_parent, m_contextFlags);
return m_parent->AllocCommandList(m_contextFlags);
}

View File

@ -39,7 +39,8 @@ namespace dxvk {
m_dxvkAdapter (m_dxvkDevice->adapter()),
m_d3d11Formats (m_dxvkAdapter),
m_d3d11Options (m_dxvkAdapter->instance()->config()),
m_dxbcOptions (m_dxvkDevice, m_d3d11Options) {
m_dxbcOptions (m_dxvkDevice, m_d3d11Options),
m_commandListAllocator(this) {
m_initializer = new D3D11Initializer(this);
m_context = new D3D11ImmediateContext(this, m_dxvkDevice);
m_d3d10Device = new D3D10Device(this, m_context);

View File

@ -14,6 +14,7 @@
#include "../util/com/com_private_data.h"
#include "d3d11_cmdlist.h"
#include "d3d11_counter_buffer.h"
#include "d3d11_initializer.h"
#include "d3d11_interfaces.h"
@ -411,6 +412,10 @@ namespace dxvk {
DxvkCsChunk* chunk = m_csChunkPool.allocChunk(flags);
return DxvkCsChunkRef(chunk, &m_csChunkPool);
}
D3D11CommandList* AllocCommandList(UINT ContextFlags) {
return m_commandListAllocator.AllocCommandList(ContextFlags);
}
const D3D11Options* GetOptions() const {
return &m_d3d11Options;
@ -465,6 +470,7 @@ namespace dxvk {
D3D11StateObjectSet<D3D11RasterizerState> m_rsStateObjects;
D3D11StateObjectSet<D3D11SamplerState> m_samplerObjects;
D3D11ShaderModuleSet m_shaderModules;
D3D11CommandListAllocator m_commandListAllocator;
Rc<D3D11CounterBuffer> CreateUAVCounterBuffer();
Rc<D3D11CounterBuffer> CreateXFBCounterBuffer();