1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-03 13:24:20 +01:00

[d3d11] Implemented CS chunk submission for deferred contexts

Changes were necessary due to the fact that chunks in deferred
contexts are not directly submitted to the CS thread.
This commit is contained in:
Philip Rebohle 2018-01-23 12:03:26 +01:00
parent eff07dcf3f
commit 3148155c35
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
9 changed files with 63 additions and 34 deletions

View File

@ -34,4 +34,23 @@ namespace dxvk {
return m_contextFlags;
}
void D3D11CommandList::AddChunk(Rc<DxvkCsChunk>&& Chunk) {
m_chunks.push_back(std::move(Chunk));
}
void D3D11CommandList::EmitToCommandList(ID3D11CommandList* pCommandList) {
auto cmdList = static_cast<D3D11CommandList*>(pCommandList);
for (auto chunk : m_chunks)
cmdList->m_chunks.push_back(chunk);
}
void D3D11CommandList::EmitToCsThread(const Rc<DxvkCsThread>& CsThread) {
for (auto chunk : m_chunks)
CsThread->dispatchChunk(Rc<DxvkCsChunk>(chunk));
}
}

View File

@ -1,11 +1,9 @@
#pragma once
#include "d3d11_device_child.h"
#include "d3d11_context.h"
namespace dxvk {
class D3D11Device;
class D3D11CommandList : public D3D11DeviceChild<ID3D11CommandList> {
public:
@ -25,11 +23,21 @@ namespace dxvk {
UINT GetContextFlags();
void AddChunk(Rc<DxvkCsChunk>&& Chunk);
void EmitToCommandList(
ID3D11CommandList* pCommandList);
void EmitToCsThread(
const Rc<DxvkCsThread>& CsThread);
private:
D3D11Device* const m_device;
UINT const m_contextFlags;
std::vector<Rc<DxvkCsChunk>> m_chunks;
};
}

View File

@ -568,12 +568,21 @@ namespace dxvk {
template<typename Cmd>
void EmitCs(Cmd&& command) {
if (!m_csChunk->push(command)) {
EmitCsChunk();
EmitCsChunk(std::move(m_csChunk));
m_csChunk = new DxvkCsChunk();
m_csChunk->push(command);
}
}
virtual void EmitCsChunk() = 0;
void FlushCsChunk() {
if (m_csChunk->commandCount() != 0) {
EmitCsChunk(std::move(m_csChunk));
m_csChunk = new DxvkCsChunk();
}
}
virtual void EmitCsChunk(Rc<DxvkCsChunk>&& chunk) = 0;
};

View File

@ -7,7 +7,8 @@ namespace dxvk {
Rc<DxvkDevice> Device,
UINT ContextFlags)
: D3D11DeviceContext(pParent, Device),
m_contextFlags(ContextFlags) {
m_contextFlags(ContextFlags),
m_commandList (CreateCommandList()) {
}
@ -60,8 +61,13 @@ namespace dxvk {
}
void D3D11DeferredContext::EmitCsChunk() {
Com<D3D11CommandList> D3D11DeferredContext::CreateCommandList() {
return new D3D11CommandList(m_parent, m_contextFlags);
}
void D3D11DeferredContext::EmitCsChunk(Rc<DxvkCsChunk>&& chunk) {
m_commandList->AddChunk(std::move(chunk));
}
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "d3d11_cmdlist.h"
#include "d3d11_context.h"
namespace dxvk {
@ -42,7 +43,11 @@ namespace dxvk {
const UINT m_contextFlags;
void EmitCsChunk() final;
Com<D3D11CommandList> m_commandList;
Com<D3D11CommandList> CreateCommandList();
void EmitCsChunk(Rc<DxvkCsChunk>&& chunk) final;
};

View File

@ -55,7 +55,7 @@ namespace dxvk {
dev->createCommandList());
});
EmitCsChunk();
FlushCsChunk();
}
@ -251,7 +251,7 @@ namespace dxvk {
void D3D11ImmediateContext::SynchronizeCsThread() {
// Dispatch current chunk so that all commands
// recorded prior to this function will be run
EmitCsChunk();
FlushCsChunk();
m_csThread.synchronize();
}
@ -266,9 +266,8 @@ namespace dxvk {
}
void D3D11ImmediateContext::EmitCsChunk() {
if (m_csChunk->commandCount() > 0)
m_csChunk = m_csThread.dispatchChunk(std::move(m_csChunk));
void D3D11ImmediateContext::EmitCsChunk(Rc<DxvkCsChunk>&& chunk) {
m_csThread.dispatchChunk(std::move(chunk));
}
}

View File

@ -50,7 +50,7 @@ namespace dxvk {
void SynchronizeDevice();
void EmitCsChunk() final;
void EmitCsChunk(Rc<DxvkCsChunk>&& chunk) final;
};

View File

@ -40,9 +40,7 @@ namespace dxvk {
}
Rc<DxvkCsChunk> DxvkCsThread::dispatchChunk(Rc<DxvkCsChunk>&& chunk) {
Rc<DxvkCsChunk> nextChunk = nullptr;
void DxvkCsThread::dispatchChunk(Rc<DxvkCsChunk>&& chunk) {
{ std::unique_lock<std::mutex> lock(m_mutex);
m_chunksQueued.push(std::move(chunk));
m_chunksPending += 1;
@ -56,21 +54,10 @@ namespace dxvk {
|| (m_stopped.load());
});
}
if (m_chunksUnused.size() != 0) {
nextChunk = std::move(m_chunksUnused.front());
m_chunksUnused.pop();
}
}
// Wake CS thread
m_condOnAdd.notify_one();
// Allocate new chunk if needed
if (nextChunk == nullptr)
nextChunk = new DxvkCsChunk();
return nextChunk;
}
@ -90,8 +77,6 @@ namespace dxvk {
{ std::unique_lock<std::mutex> lock(m_mutex);
if (chunk != nullptr) {
m_chunksPending -= 1;
m_chunksUnused.push(std::move(chunk));
m_condOnSync.notify_one();
}

View File

@ -152,9 +152,8 @@ namespace dxvk {
* Can be used to efficiently play back large
* command lists recorded on another thread.
* \param [in] chunk The chunk to dispatch
* \returns New chunk for the next submissions
*/
Rc<DxvkCsChunk> dispatchChunk(Rc<DxvkCsChunk>&& chunk);
void dispatchChunk(Rc<DxvkCsChunk>&& chunk);
/**
* \brief Synchronizes with the thread
@ -175,7 +174,6 @@ namespace dxvk {
std::condition_variable m_condOnAdd;
std::condition_variable m_condOnSync;
std::queue<Rc<DxvkCsChunk>> m_chunksQueued;
std::queue<Rc<DxvkCsChunk>> m_chunksUnused;
std::thread m_thread;
uint32_t m_chunksPending = 0;