1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00
OpenDX/src/dxvk/dxvk_queue.cpp
Joshua Ashton c39c3e8dcc [dxvk] Hook up platform-specific clock
See 89dfa2bc22577c758cb8badd34e4f177192a6eff
2019-11-26 01:52:58 +01:00

188 lines
4.8 KiB
C++

#include "dxvk_device.h"
#include "dxvk_queue.h"
namespace dxvk {
DxvkSubmissionQueue::DxvkSubmissionQueue(DxvkDevice* device)
: m_device(device),
m_submitThread([this] () { submitCmdLists(); }),
m_finishThread([this] () { finishCmdLists(); }) {
}
DxvkSubmissionQueue::~DxvkSubmissionQueue() {
{ std::unique_lock<std::mutex> lock(m_mutex);
m_stopped.store(true);
}
m_appendCond.notify_all();
m_submitCond.notify_all();
m_submitThread.join();
m_finishThread.join();
}
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;
});
DxvkSubmitEntry entry = { };
entry.submit = std::move(submitInfo);
m_pending += 1;
m_submitQueue.push(std::move(entry));
m_appendCond.notify_all();
}
void DxvkSubmissionQueue::present(DxvkPresentInfo presentInfo, DxvkSubmitStatus* status) {
std::unique_lock<std::mutex> lock(m_mutex);
DxvkSubmitEntry entry = { };
entry.status = status;
entry.present = std::move(presentInfo);
m_submitQueue.push(std::move(entry));
m_appendCond.notify_all();
}
void DxvkSubmissionQueue::synchronizeSubmission(
DxvkSubmitStatus* status) {
std::unique_lock<std::mutex> lock(m_mutex);
m_submitCond.wait(lock, [status] {
return status->result.load() != VK_NOT_READY;
});
}
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();
});
if (m_stopped.load())
return;
DxvkSubmitEntry entry = std::move(m_submitQueue.front());
lock.unlock();
// Submit command buffer to device
VkResult status = VK_NOT_READY;
if (m_lastError != VK_ERROR_DEVICE_LOST) {
std::lock_guard<std::mutex> lock(m_mutexQueue);
if (entry.submit.cmdList != nullptr) {
status = entry.submit.cmdList->submit(
entry.submit.waitSync,
entry.submit.wakeSync);
} else if (entry.present.presenter != nullptr) {
status = entry.present.presenter->presentImage(
entry.present.waitSync);
}
} else {
// Don't submit anything after device loss
// so that drivers get a chance to recover
status = VK_ERROR_DEVICE_LOST;
}
if (entry.status)
entry.status->result = status;
// On success, pass it on to the queue thread
lock = std::unique_lock<std::mutex>(m_mutex);
if (status == VK_SUCCESS) {
if (entry.submit.cmdList != nullptr)
m_finishQueue.push(std::move(entry));
} else if (status == VK_ERROR_DEVICE_LOST || entry.submit.cmdList != nullptr) {
Logger::err(str::format("DxvkSubmissionQueue: Command submission failed: ", status));
m_lastError = status;
m_device->waitForIdle();
}
m_submitQueue.pop();
m_submitCond.notify_all();
}
}
void DxvkSubmissionQueue::finishCmdLists() {
env::setThreadName("dxvk-queue");
std::unique_lock<std::mutex> lock(m_mutex);
while (!m_stopped.load()) {
if (m_finishQueue.empty()) {
auto t0 = dxvk::high_resolution_clock::now();
m_submitCond.wait(lock, [this] {
return m_stopped.load() || !m_finishQueue.empty();
});
auto t1 = dxvk::high_resolution_clock::now();
m_gpuIdle += std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count();
}
if (m_stopped.load())
return;
DxvkSubmitEntry entry = std::move(m_finishQueue.front());
lock.unlock();
VkResult status = m_lastError.load();
if (status != VK_ERROR_DEVICE_LOST)
status = entry.submit.cmdList->synchronize();
if (status != VK_SUCCESS) {
Logger::err(str::format("DxvkSubmissionQueue: Failed to sync fence: ", status));
m_lastError = status;
m_device->waitForIdle();
}
entry.submit.cmdList->notifySignals();
entry.submit.cmdList->reset();
m_device->recycleCommandList(entry.submit.cmdList);
lock = std::unique_lock<std::mutex>(m_mutex);
m_pending -= 1;
m_finishQueue.pop();
m_finishCond.notify_all();
}
}
}