1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00

[dxvk] Recycle CS chunks

This commit is contained in:
Philip Rebohle 2018-01-21 12:59:43 +01:00
parent 70b639784b
commit 7c3a9beb22
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 48 additions and 27 deletions

View File

@ -266,10 +266,8 @@ namespace dxvk {
void D3D11ImmediateContext::EmitCsChunk() { void D3D11ImmediateContext::EmitCsChunk() {
if (m_csChunk->commandCount() > 0) { if (m_csChunk->commandCount() > 0)
m_csThread.dispatchChunk(std::move(m_csChunk)); m_csChunk = m_csThread.dispatchChunk(std::move(m_csChunk));
m_csChunk = new DxvkCsChunk();
}
} }
} }

View File

@ -40,17 +40,37 @@ namespace dxvk {
} }
void DxvkCsThread::dispatchChunk(Rc<DxvkCsChunk>&& chunk) { Rc<DxvkCsChunk> DxvkCsThread::dispatchChunk(Rc<DxvkCsChunk>&& chunk) {
Rc<DxvkCsChunk> nextChunk = nullptr;
{ std::unique_lock<std::mutex> lock(m_mutex); { std::unique_lock<std::mutex> lock(m_mutex);
m_chunks.push(std::move(chunk)); m_chunksQueued.push(std::move(chunk));
m_chunksPending += 1; m_chunksPending += 1;
m_condOnSync.wait(lock, [this] { // If a large number of chunks are queued up, wait for
return m_stopped.load() || (m_chunksPending < MaxChunksInFlight); // some of them to be processed in order to avoid memory
}); // leaks, stuttering, input lag and similar issues.
if (m_chunksPending >= MaxChunksInFlight) {
m_condOnSync.wait(lock, [this] {
return (m_chunksPending < MaxChunksInFlight / 2)
|| (m_stopped.load());
});
}
if (m_chunksUnused.size() != 0) {
nextChunk = std::move(m_chunksUnused.front());
m_chunksUnused.pop();
}
} }
// Wake CS thread
m_condOnAdd.notify_one(); m_condOnAdd.notify_one();
// Allocate new chunk if needed
if (nextChunk == nullptr)
nextChunk = new DxvkCsChunk();
return nextChunk;
} }
@ -64,30 +84,31 @@ namespace dxvk {
void DxvkCsThread::threadFunc() { void DxvkCsThread::threadFunc() {
Rc<DxvkCsChunk> chunk;
while (!m_stopped.load()) { while (!m_stopped.load()) {
Rc<DxvkCsChunk> chunk;
{ std::unique_lock<std::mutex> lock(m_mutex); { std::unique_lock<std::mutex> lock(m_mutex);
if (chunk != nullptr) {
m_chunksPending -= 1;
m_chunksUnused.push(std::move(chunk));
m_condOnSync.notify_one();
}
m_condOnAdd.wait(lock, [this] { m_condOnAdd.wait(lock, [this] {
return m_stopped.load() || (m_chunks.size() != 0); return m_stopped.load() || (m_chunksQueued.size() != 0);
}); });
if (m_chunks.size() != 0) { if (m_chunksQueued.size() != 0) {
chunk = std::move(m_chunks.front()); chunk = std::move(m_chunksQueued.front());
m_chunks.pop(); m_chunksQueued.pop();
} else {
chunk = nullptr;
} }
} }
if (chunk != nullptr) { if (chunk != nullptr)
chunk->executeAll(m_context.ptr()); chunk->executeAll(m_context.ptr());
{ std::unique_lock<std::mutex> lock(m_mutex);
m_chunksPending -= 1;
}
m_condOnSync.notify_one();
}
} }
} }

View File

@ -65,7 +65,7 @@ namespace dxvk {
* Stores a list of commands. * Stores a list of commands.
*/ */
class DxvkCsChunk : public RcObject { class DxvkCsChunk : public RcObject {
constexpr static size_t MaxCommands = 64; constexpr static size_t MaxCommands = 1024;
constexpr static size_t MaxBlockSize = 64 * MaxCommands; constexpr static size_t MaxBlockSize = 64 * MaxCommands;
public: public:
@ -140,7 +140,7 @@ namespace dxvk {
class DxvkCsThread { class DxvkCsThread {
// Limit the number of chunks in the queue // Limit the number of chunks in the queue
// to prevent memory leaks, stuttering etc. // to prevent memory leaks, stuttering etc.
constexpr static uint32_t MaxChunksInFlight = 128; constexpr static uint32_t MaxChunksInFlight = 16;
public: public:
DxvkCsThread(const Rc<DxvkContext>& context); DxvkCsThread(const Rc<DxvkContext>& context);
@ -152,8 +152,9 @@ namespace dxvk {
* Can be used to efficiently play back large * Can be used to efficiently play back large
* command lists recorded on another thread. * command lists recorded on another thread.
* \param [in] chunk The chunk to dispatch * \param [in] chunk The chunk to dispatch
* \returns New chunk for the next submissions
*/ */
void dispatchChunk(Rc<DxvkCsChunk>&& chunk); Rc<DxvkCsChunk> dispatchChunk(Rc<DxvkCsChunk>&& chunk);
/** /**
* \brief Synchronizes with the thread * \brief Synchronizes with the thread
@ -173,7 +174,8 @@ namespace dxvk {
std::mutex m_mutex; std::mutex m_mutex;
std::condition_variable m_condOnAdd; std::condition_variable m_condOnAdd;
std::condition_variable m_condOnSync; std::condition_variable m_condOnSync;
std::queue<Rc<DxvkCsChunk>> m_chunks; std::queue<Rc<DxvkCsChunk>> m_chunksQueued;
std::queue<Rc<DxvkCsChunk>> m_chunksUnused;
std::thread m_thread; std::thread m_thread;
uint32_t m_chunksPending = 0; uint32_t m_chunksPending = 0;