2017-12-16 18:10:55 +01:00
|
|
|
#include "dxvk_device.h"
|
|
|
|
#include "dxvk_queue.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
DxvkSubmissionQueue::DxvkSubmissionQueue(DxvkDevice* device)
|
2018-09-20 19:58:00 +02:00
|
|
|
: m_device(device),
|
2019-05-05 14:08:07 +02:00
|
|
|
m_submitThread([this] () { submitCmdLists(); }),
|
|
|
|
m_finishThread([this] () { finishCmdLists(); }) {
|
2017-12-16 18:10:55 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DxvkSubmissionQueue::~DxvkSubmissionQueue() {
|
2018-09-20 19:58:00 +02:00
|
|
|
{ std::unique_lock<std::mutex> lock(m_mutex);
|
2017-12-25 16:05:11 +01:00
|
|
|
m_stopped.store(true);
|
|
|
|
}
|
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
m_appendCond.notify_all();
|
|
|
|
m_submitCond.notify_all();
|
|
|
|
|
|
|
|
m_submitThread.join();
|
|
|
|
m_finishThread.join();
|
2017-12-16 18:10:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
void DxvkSubmissionQueue::submit(DxvkSubmitInfo submitInfo) {
|
|
|
|
std::unique_lock<std::mutex> lock(m_mutex);
|
|
|
|
|
|
|
|
m_finishCond.wait(lock, [this] {
|
|
|
|
return m_submitQueue.size() + m_finishQueue.size() <= MaxNumQueuedCommandBuffers;
|
|
|
|
});
|
|
|
|
|
|
|
|
m_pending += 1;
|
|
|
|
m_submitQueue.push(std::move(submitInfo));
|
|
|
|
m_appendCond.notify_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkResult DxvkSubmissionQueue::present(DxvkPresentInfo presentInfo) {
|
|
|
|
this->synchronize();
|
|
|
|
|
|
|
|
std::unique_lock<std::mutex> lock(m_mutexQueue);
|
|
|
|
return presentInfo.presenter->presentImage(presentInfo.waitSync);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkSubmissionQueue::synchronize() {
|
|
|
|
std::unique_lock<std::mutex> lock(m_mutex);
|
|
|
|
|
|
|
|
m_submitCond.wait(lock, [this] {
|
|
|
|
return m_submitQueue.empty();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkSubmissionQueue::lockDeviceQueue() {
|
|
|
|
m_mutexQueue.lock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkSubmissionQueue::unlockDeviceQueue() {
|
|
|
|
m_mutexQueue.unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkSubmissionQueue::submitCmdLists() {
|
|
|
|
env::setThreadName("dxvk-submit");
|
|
|
|
|
|
|
|
std::unique_lock<std::mutex> lock(m_mutex);
|
|
|
|
|
|
|
|
while (!m_stopped.load()) {
|
|
|
|
m_appendCond.wait(lock, [this] {
|
|
|
|
return m_stopped.load() || !m_submitQueue.empty();
|
2018-09-20 19:58:00 +02:00
|
|
|
});
|
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
if (m_stopped.load())
|
|
|
|
return;
|
|
|
|
|
|
|
|
DxvkSubmitInfo submitInfo = std::move(m_submitQueue.front());
|
|
|
|
lock.unlock();
|
|
|
|
|
|
|
|
// Submit command buffer to device
|
|
|
|
VkResult status;
|
|
|
|
|
|
|
|
{ std::lock_guard<std::mutex> lock(m_mutexQueue);
|
|
|
|
|
|
|
|
status = submitInfo.cmdList->submit(
|
|
|
|
submitInfo.waitSync,
|
|
|
|
submitInfo.wakeSync);
|
|
|
|
}
|
|
|
|
|
|
|
|
// On success, pass it on to the queue thread
|
|
|
|
lock = std::unique_lock<std::mutex>(m_mutex);
|
|
|
|
|
|
|
|
if (status == VK_SUCCESS) {
|
|
|
|
m_finishQueue.push(std::move(submitInfo));
|
|
|
|
m_submitQueue.pop();
|
|
|
|
m_submitCond.notify_all();
|
|
|
|
} else {
|
|
|
|
Logger::err(str::format(
|
|
|
|
"DxvkSubmissionQueue: Command submission failed with ",
|
|
|
|
status));
|
|
|
|
m_pending -= 1;
|
|
|
|
}
|
2018-09-20 19:58:00 +02:00
|
|
|
}
|
2017-12-16 18:10:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
void DxvkSubmissionQueue::finishCmdLists() {
|
2019-01-11 13:43:15 +01:00
|
|
|
env::setThreadName("dxvk-queue");
|
2018-06-21 15:12:04 +02:00
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
std::unique_lock<std::mutex> lock(m_mutex);
|
|
|
|
|
2017-12-16 18:10:55 +01:00
|
|
|
while (!m_stopped.load()) {
|
2019-05-05 14:08:07 +02:00
|
|
|
m_submitCond.wait(lock, [this] {
|
|
|
|
return m_stopped.load() || !m_finishQueue.empty();
|
|
|
|
});
|
|
|
|
|
|
|
|
if (m_stopped.load())
|
|
|
|
return;
|
2017-12-16 18:10:55 +01:00
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
DxvkSubmitInfo submitInfo = std::move(m_finishQueue.front());
|
|
|
|
lock.unlock();
|
2017-12-16 18:10:55 +01:00
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
VkResult status = submitInfo.cmdList->synchronize();
|
|
|
|
|
|
|
|
if (status == VK_SUCCESS) {
|
|
|
|
submitInfo.cmdList->signalEvents();
|
|
|
|
submitInfo.cmdList->reset();
|
2018-06-04 23:24:42 +02:00
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
m_device->recycleCommandList(submitInfo.cmdList);
|
|
|
|
} else {
|
|
|
|
Logger::err(str::format(
|
|
|
|
"DxvkSubmissionQueue: Failed to sync fence: ",
|
|
|
|
status));
|
2017-12-16 18:10:55 +01:00
|
|
|
}
|
2019-05-05 14:08:07 +02:00
|
|
|
|
|
|
|
lock = std::unique_lock<std::mutex>(m_mutex);
|
|
|
|
m_pending -= 1;
|
|
|
|
|
|
|
|
m_finishQueue.pop();
|
|
|
|
m_finishCond.notify_all();
|
2017-12-16 18:10:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|