[d3d11] Flush immediate context on command list execution

This optimization may help keep the GPU busy in case there's
a large number of draw calls pending at the time a command
list from a deferred context is submitted for execution.
This commit is contained in:
Philip Rebohle 2018-04-03 19:52:14 +02:00
parent 0b2e88b087
commit 7de27d4fd8
6 changed files with 34 additions and 7 deletions

View File

@ -41,8 +41,11 @@ namespace dxvk {
}
void D3D11CommandList::AddChunk(Rc<DxvkCsChunk>&& Chunk) {
void D3D11CommandList::AddChunk(
Rc<DxvkCsChunk>&& Chunk,
UINT DrawCount) {
m_chunks.push_back(std::move(Chunk));
m_drawCount += DrawCount;
}
@ -51,6 +54,8 @@ namespace dxvk {
for (auto chunk : m_chunks)
cmdList->m_chunks.push_back(chunk);
cmdList->m_drawCount += m_drawCount;
}

View File

@ -23,7 +23,9 @@ namespace dxvk {
UINT STDMETHODCALLTYPE GetContextFlags() final;
void AddChunk(Rc<DxvkCsChunk>&& Chunk);
void AddChunk(
Rc<DxvkCsChunk>&& Chunk,
UINT DrawCount);
void EmitToCommandList(
ID3D11CommandList* pCommandList);
@ -31,10 +33,15 @@ namespace dxvk {
void EmitToCsThread(
DxvkCsThread* CsThread);
UINT GetDrawCount() const {
return m_drawCount;
}
private:
D3D11Device* const m_device;
UINT const m_contextFlags;
UINT m_drawCount = 0;
std::vector<Rc<DxvkCsChunk>> m_chunks;

View File

@ -648,7 +648,7 @@ namespace dxvk {
Com<D3D11RasterizerState> m_defaultRasterizerState;
D3D11ContextState m_state;
uint64_t m_drawCount = 0;
UINT m_drawCount = 0;
void ApplyInputLayout();

View File

@ -256,7 +256,8 @@ namespace dxvk {
void D3D11DeferredContext::EmitCsChunk(Rc<DxvkCsChunk>&& chunk) {
m_commandList->AddChunk(std::move(chunk));
m_commandList->AddChunk(std::move(chunk), m_drawCount);
m_drawCount = 0;
}
}

View File

@ -72,16 +72,30 @@ namespace dxvk {
void STDMETHODCALLTYPE D3D11ImmediateContext::ExecuteCommandList(
ID3D11CommandList* pCommandList,
BOOL RestoreContextState) {
auto commandList = static_cast<D3D11CommandList*>(pCommandList);
// Flush any outstanding commands so that
// we don't mess up the execution order
FlushCsChunk();
static_cast<D3D11CommandList*>(pCommandList)->EmitToCsThread(&m_csThread);
// As an optimization, flush everything if the
// number of pending draw calls is high enough.
if (m_drawCount >= MaxPendingDraws)
Flush();
// Dispatch command list to the CS thread and
// restore the immediate context's state
commandList->EmitToCsThread(&m_csThread);
if (RestoreContextState)
RestoreState();
else
ClearState();
// Mark CS thread as busy so that subsequent
// flush operations get executed correctly.
m_csIsBusy = true;
m_drawCount += commandList->GetDrawCount();
}
@ -190,7 +204,7 @@ namespace dxvk {
// prior to the previous context flush is above a certain threshold,
// submit the current command buffer in order to keep the GPU busy.
// This also helps keep the command buffers at a reasonable size.
if (m_drawCount >= 500)
if (m_drawCount >= MaxPendingDraws)
Flush();
D3D11DeviceContext::OMSetRenderTargets(

View File

@ -8,7 +8,7 @@ namespace dxvk {
class D3D11CommonTexture;
class D3D11ImmediateContext : public D3D11DeviceContext {
constexpr static UINT MaxPendingDraws = 500;
public:
D3D11ImmediateContext(