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:
parent
70b639784b
commit
7c3a9beb22
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user