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 08:01:30 +02:00
|
|
|
: m_device (device),
|
|
|
|
m_queueThread ([this] () { threadQueue(); }),
|
|
|
|
m_submitThread([this] () { threadSubmit(); }) {
|
2017-12-16 18:10:55 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DxvkSubmissionQueue::~DxvkSubmissionQueue() {
|
2018-09-20 08:01:30 +02:00
|
|
|
{ std::unique_lock<std::mutex> lockQueue (m_queueLock);
|
|
|
|
std::unique_lock<std::mutex> lockSubmit(m_submitLock);
|
|
|
|
|
2017-12-25 16:05:11 +01:00
|
|
|
m_stopped.store(true);
|
|
|
|
}
|
|
|
|
|
2018-09-20 08:01:30 +02:00
|
|
|
m_submitCondOnAdd.notify_one();
|
|
|
|
m_submitThread.join();
|
|
|
|
|
|
|
|
m_queueCond.notify_one();
|
|
|
|
m_queueThread.join();
|
2017-12-16 18:10:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-20 08:01:30 +02:00
|
|
|
void DxvkSubmissionQueue::submit(DxvkSubmission submission) {
|
|
|
|
std::unique_lock<std::mutex> lock(m_submitLock);
|
|
|
|
|
|
|
|
m_submitCondOnTake.wait(lock, [this] {
|
|
|
|
return m_submitQueue.size() < MaxNumQueuedCommandBuffers;
|
|
|
|
});
|
|
|
|
|
|
|
|
m_submits += 1;
|
|
|
|
m_submitQueue.push(std::move(submission));
|
|
|
|
m_submitCondOnAdd.notify_one();
|
2017-12-16 18:10:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-20 08:01:30 +02:00
|
|
|
void DxvkSubmissionQueue::synchronize() {
|
|
|
|
std::unique_lock<std::mutex> lock(m_submitLock);
|
|
|
|
|
|
|
|
m_submitCondOnTake.wait(lock, [this] {
|
|
|
|
return m_submitQueue.size() == 0;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkSubmissionQueue::threadSubmit() {
|
|
|
|
env::setThreadName(L"dxvk-submit");
|
|
|
|
|
|
|
|
while (!m_stopped.load()) {
|
|
|
|
DxvkSubmission submission;
|
|
|
|
|
|
|
|
{ std::unique_lock<std::mutex> lock(m_submitLock);
|
|
|
|
|
|
|
|
m_submitCondOnAdd.wait(lock, [this] {
|
|
|
|
return m_stopped.load() || (m_submitQueue.size() != 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (m_submitQueue.size() != 0)
|
|
|
|
submission = std::move(m_submitQueue.front());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (submission.cmdList != nullptr) {
|
|
|
|
// Make sure that the semaphores do not get deleted or
|
|
|
|
// reused before the command submission has completed
|
|
|
|
VkSemaphore waitSemaphore = VK_NULL_HANDLE;
|
|
|
|
VkSemaphore wakeSemaphore = VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
if (submission.semWait != nullptr) {
|
|
|
|
waitSemaphore = submission.semWait->handle();
|
|
|
|
submission.cmdList->trackResource(submission.semWait);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (submission.semWake != nullptr) {
|
|
|
|
wakeSemaphore = submission.semWake->handle();
|
|
|
|
submission.cmdList->trackResource(submission.semWake);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Protect the Vulkan queue itself from concurrent access
|
|
|
|
{ std::unique_lock<std::mutex> lock(m_externalLock);
|
|
|
|
|
|
|
|
VkResult status = submission.cmdList->submit(
|
|
|
|
m_device->m_graphicsQueue.queueHandle,
|
|
|
|
waitSemaphore, wakeSemaphore);
|
|
|
|
|
|
|
|
if (status != VK_SUCCESS)
|
|
|
|
Logger::err(str::format("Dxvk: Submission failed: ", status));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Process this submission on the 'queue' thread
|
|
|
|
{ std::unique_lock<std::mutex> lock(m_queueLock);
|
|
|
|
|
|
|
|
m_queueEntries.push(std::move(submission.cmdList));
|
|
|
|
m_queueCond.notify_one();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove submission now. We cannot do this earlier as
|
|
|
|
// the synchronize method depends on this behaviour.
|
|
|
|
{ std::unique_lock<std::mutex> lock(m_submitLock);
|
|
|
|
|
|
|
|
if (m_submitQueue.size() != 0)
|
|
|
|
m_submitQueue.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_submitCondOnTake.notify_one();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkSubmissionQueue::threadQueue() {
|
2018-06-21 15:12:04 +02:00
|
|
|
env::setThreadName(L"dxvk-queue");
|
|
|
|
|
2017-12-16 18:10:55 +01:00
|
|
|
while (!m_stopped.load()) {
|
2018-03-22 18:57:33 +01:00
|
|
|
Rc<DxvkCommandList> cmdList;
|
2017-12-16 18:10:55 +01:00
|
|
|
|
2018-09-20 08:01:30 +02:00
|
|
|
{ std::unique_lock<std::mutex> lock(m_queueLock);
|
2017-12-16 18:10:55 +01:00
|
|
|
|
2018-09-20 08:01:30 +02:00
|
|
|
m_queueCond.wait(lock, [this] {
|
|
|
|
return m_stopped.load() || (m_queueEntries.size() != 0);
|
2017-12-16 18:10:55 +01:00
|
|
|
});
|
|
|
|
|
2018-09-20 08:01:30 +02:00
|
|
|
if (m_queueEntries.size() != 0) {
|
|
|
|
cmdList = std::move(m_queueEntries.front());
|
|
|
|
m_queueEntries.pop();
|
2017-12-16 18:10:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-22 18:57:33 +01:00
|
|
|
if (cmdList != nullptr) {
|
|
|
|
VkResult status = cmdList->synchronize();
|
2018-02-18 20:11:05 +01:00
|
|
|
|
2018-03-22 18:57:33 +01:00
|
|
|
if (status == VK_SUCCESS) {
|
|
|
|
cmdList->writeQueryData();
|
|
|
|
cmdList->signalEvents();
|
|
|
|
cmdList->reset();
|
|
|
|
|
|
|
|
m_device->recycleCommandList(cmdList);
|
|
|
|
} else {
|
|
|
|
Logger::err(str::format(
|
|
|
|
"DxvkSubmissionQueue: Failed to sync fence: ",
|
|
|
|
status));
|
|
|
|
}
|
2018-06-04 23:24:42 +02:00
|
|
|
|
|
|
|
m_submits -= 1;
|
2017-12-16 18:10:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|