2017-12-20 22:17:14 +01:00
|
|
|
#include "dxvk_cs.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
DxvkCsChunk::DxvkCsChunk() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DxvkCsChunk::~DxvkCsChunk() {
|
2018-08-27 16:07:38 +02:00
|
|
|
this->reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-20 10:35:23 +01:00
|
|
|
void DxvkCsChunk::init(DxvkCsChunkFlags flags) {
|
|
|
|
m_flags = flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-27 16:07:38 +02:00
|
|
|
void DxvkCsChunk::executeAll(DxvkContext* ctx) {
|
2018-03-02 10:31:08 +01:00
|
|
|
auto cmd = m_head;
|
|
|
|
|
2018-11-20 10:35:23 +01:00
|
|
|
if (m_flags.test(DxvkCsChunkFlag::SingleUse)) {
|
|
|
|
m_commandCount = 0;
|
|
|
|
m_commandOffset = 0;
|
|
|
|
|
|
|
|
while (cmd != nullptr) {
|
|
|
|
auto next = cmd->next();
|
|
|
|
cmd->exec(ctx);
|
|
|
|
cmd->~DxvkCsCmd();
|
|
|
|
cmd = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_head = nullptr;
|
|
|
|
m_tail = nullptr;
|
|
|
|
} else {
|
|
|
|
while (cmd != nullptr) {
|
|
|
|
cmd->exec(ctx);
|
|
|
|
cmd = cmd->next();
|
|
|
|
}
|
2018-03-02 10:31:08 +01:00
|
|
|
}
|
2017-12-20 22:17:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-27 16:07:38 +02:00
|
|
|
void DxvkCsChunk::reset() {
|
2018-03-02 10:31:08 +01:00
|
|
|
auto cmd = m_head;
|
|
|
|
|
2018-11-20 10:35:23 +01:00
|
|
|
m_commandCount = 0;
|
|
|
|
m_commandOffset = 0;
|
|
|
|
|
2018-03-02 10:31:08 +01:00
|
|
|
while (cmd != nullptr) {
|
|
|
|
auto next = cmd->next();
|
|
|
|
cmd->~DxvkCsCmd();
|
|
|
|
cmd = next;
|
2017-12-20 22:17:14 +01:00
|
|
|
}
|
|
|
|
|
2018-03-02 10:31:08 +01:00
|
|
|
m_head = nullptr;
|
|
|
|
m_tail = nullptr;
|
2017-12-20 22:17:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-27 16:07:38 +02:00
|
|
|
DxvkCsChunkPool::DxvkCsChunkPool() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DxvkCsChunkPool::~DxvkCsChunkPool() {
|
|
|
|
for (DxvkCsChunk* chunk : m_chunks)
|
|
|
|
delete chunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-20 10:35:23 +01:00
|
|
|
DxvkCsChunk* DxvkCsChunkPool::allocChunk(DxvkCsChunkFlags flags) {
|
|
|
|
DxvkCsChunk* chunk = nullptr;
|
|
|
|
|
2018-08-27 16:07:38 +02:00
|
|
|
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
|
|
|
|
|
|
|
if (m_chunks.size() != 0) {
|
2018-11-20 10:35:23 +01:00
|
|
|
chunk = m_chunks.back();
|
2018-08-27 16:07:38 +02:00
|
|
|
m_chunks.pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-20 10:35:23 +01:00
|
|
|
if (!chunk)
|
|
|
|
chunk = new DxvkCsChunk();
|
|
|
|
|
|
|
|
chunk->init(flags);
|
|
|
|
return chunk;
|
2018-08-27 16:07:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkCsChunkPool::freeChunk(DxvkCsChunk* chunk) {
|
|
|
|
chunk->reset();
|
|
|
|
|
|
|
|
std::lock_guard<sync::Spinlock> lock(m_mutex);
|
|
|
|
m_chunks.push_back(chunk);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-20 22:17:14 +01:00
|
|
|
DxvkCsThread::DxvkCsThread(const Rc<DxvkContext>& context)
|
2018-01-20 14:59:50 +01:00
|
|
|
: m_context(context), m_thread([this] { threadFunc(); }) {
|
2017-12-20 22:17:14 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DxvkCsThread::~DxvkCsThread() {
|
2017-12-25 16:05:11 +01:00
|
|
|
{ std::unique_lock<std::mutex> lock(m_mutex);
|
|
|
|
m_stopped.store(true);
|
|
|
|
}
|
|
|
|
|
2017-12-20 22:17:14 +01:00
|
|
|
m_condOnAdd.notify_one();
|
|
|
|
m_thread.join();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-27 16:07:38 +02:00
|
|
|
void DxvkCsThread::dispatchChunk(DxvkCsChunkRef&& chunk) {
|
2018-04-03 20:06:25 +02:00
|
|
|
{ std::unique_lock<std::mutex> lock(m_mutex);
|
|
|
|
m_chunksQueued.push(std::move(chunk));
|
|
|
|
m_chunksPending += 1;
|
2017-12-20 22:17:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
m_condOnAdd.notify_one();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkCsThread::synchronize() {
|
|
|
|
std::unique_lock<std::mutex> lock(m_mutex);
|
|
|
|
|
|
|
|
m_condOnSync.wait(lock, [this] {
|
2018-01-20 23:12:03 +01:00
|
|
|
return m_chunksPending == 0;
|
2017-12-20 22:17:14 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkCsThread::threadFunc() {
|
2019-01-11 13:43:15 +01:00
|
|
|
env::setThreadName("dxvk-cs");
|
2018-06-21 15:12:04 +02:00
|
|
|
|
2018-08-27 16:07:38 +02:00
|
|
|
DxvkCsChunkRef chunk;
|
2018-01-21 12:59:43 +01:00
|
|
|
|
2017-12-20 22:17:14 +01:00
|
|
|
while (!m_stopped.load()) {
|
|
|
|
{ std::unique_lock<std::mutex> lock(m_mutex);
|
2018-08-27 16:07:38 +02:00
|
|
|
if (chunk) {
|
2018-04-03 20:06:25 +02:00
|
|
|
if (--m_chunksPending == 0)
|
|
|
|
m_condOnSync.notify_one();
|
|
|
|
|
2018-08-27 16:07:38 +02:00
|
|
|
chunk = DxvkCsChunkRef();
|
2018-01-21 12:59:43 +01:00
|
|
|
}
|
2017-12-20 22:17:14 +01:00
|
|
|
|
2018-01-29 00:00:19 +01:00
|
|
|
if (m_chunksQueued.size() == 0) {
|
|
|
|
m_condOnAdd.wait(lock, [this] {
|
|
|
|
return (m_chunksQueued.size() != 0)
|
|
|
|
|| (m_stopped.load());
|
|
|
|
});
|
|
|
|
}
|
2017-12-20 22:17:14 +01:00
|
|
|
|
2018-01-21 12:59:43 +01:00
|
|
|
if (m_chunksQueued.size() != 0) {
|
|
|
|
chunk = std::move(m_chunksQueued.front());
|
|
|
|
m_chunksQueued.pop();
|
2017-12-20 22:17:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-27 16:07:38 +02:00
|
|
|
if (chunk)
|
2017-12-20 22:17:14 +01:00
|
|
|
chunk->executeAll(m_context.ptr());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|