1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-02 10:24:12 +01:00

Revert "[dxvk] Move command submission to separate thread"

This reverts commit f61ff5d345.

Apparently, this causes extremely poor frame times on some
configurations. Reason is currently unknown.
This commit is contained in:
Philip Rebohle 2018-09-20 19:58:00 +02:00
parent 2eda95f61a
commit 0f52ec2796
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 75 additions and 167 deletions

View File

@ -221,16 +221,13 @@ namespace dxvk {
VkResult DxvkDevice::presentSwapImage(
const VkPresentInfoKHR& presentInfo) {
{ std::lock_guard<sync::Spinlock> statLock(m_statLock);
m_statCounters.addCtr(DxvkStatCounter::QueuePresentCount, 1);
}
{ // Queue submissions are not thread safe
std::lock_guard<std::mutex> queueLock(m_submissionLock);
std::lock_guard<sync::Spinlock> statLock(m_statLock);
this->lockSubmission();
VkResult status = m_vkd->vkQueuePresentKHR(
m_presentQueue.queueHandle, &presentInfo);
this->unlockSubmission();
return status;
m_statCounters.addCtr(DxvkStatCounter::QueuePresentCount, 1);
return m_vkd->vkQueuePresentKHR(m_presentQueue.queueHandle, &presentInfo);
}
}
@ -238,17 +235,41 @@ namespace dxvk {
const Rc<DxvkCommandList>& commandList,
const Rc<DxvkSemaphore>& waitSync,
const Rc<DxvkSemaphore>& wakeSync) {
{ std::lock_guard<sync::Spinlock> statLock(m_statLock);
VkSemaphore waitSemaphore = VK_NULL_HANDLE;
VkSemaphore wakeSemaphore = VK_NULL_HANDLE;
if (waitSync != nullptr) {
waitSemaphore = waitSync->handle();
commandList->trackResource(waitSync);
}
if (wakeSync != nullptr) {
wakeSemaphore = wakeSync->handle();
commandList->trackResource(wakeSync);
}
VkResult status;
{ // Queue submissions are not thread safe
std::lock_guard<std::mutex> queueLock(m_submissionLock);
std::lock_guard<sync::Spinlock> statLock(m_statLock);
m_statCounters.merge(commandList->statCounters());
m_statCounters.addCtr(DxvkStatCounter::QueueSubmitCount, 1);
status = commandList->submit(
m_graphicsQueue.queueHandle,
waitSemaphore, wakeSemaphore);
}
if (status == VK_SUCCESS) {
// Add this to the set of running submissions
m_submissionQueue.submit(commandList);
} else {
Logger::err(str::format(
"DxvkDevice: Command buffer submission failed: ",
status));
}
DxvkSubmission submission;
submission.cmdList = commandList;
submission.semWait = waitSync;
submission.semWake = wakeSync;
m_submissionQueue.submit(std::move(submission));
}

View File

@ -327,6 +327,7 @@ namespace dxvk {
* \param [in] commandList The command list to submit
* \param [in] waitSync (Optional) Semaphore to wait on
* \param [in] wakeSync (Optional) Semaphore to notify
* \returns Synchronization fence
*/
void submitCommandList(
const Rc<DxvkCommandList>& commandList,
@ -341,8 +342,7 @@ namespace dxvk {
* to lock the queue before submitting command buffers.
*/
void lockSubmission() {
m_submissionQueue.synchronize();
m_submissionQueue.lock();
m_submissionLock.lock();
}
/**
@ -352,7 +352,7 @@ namespace dxvk {
* itself can use them for submissions again.
*/
void unlockSubmission() {
m_submissionQueue.unlock();
m_submissionLock.unlock();
}
/**
@ -399,6 +399,7 @@ namespace dxvk {
sync::Spinlock m_statLock;
DxvkStatCounters m_statCounters;
std::mutex m_submissionLock;
DxvkDeviceQueue m_graphicsQueue;
DxvkDeviceQueue m_presentQueue;

View File

@ -4,130 +4,54 @@
namespace dxvk {
DxvkSubmissionQueue::DxvkSubmissionQueue(DxvkDevice* device)
: m_device (device),
m_queueThread ([this] () { threadQueue(); }),
m_submitThread([this] () { threadSubmit(); }) {
: m_device(device),
m_thread([this] () { threadFunc(); }) {
}
DxvkSubmissionQueue::~DxvkSubmissionQueue() {
{ std::unique_lock<std::mutex> lockQueue (m_queueLock);
std::unique_lock<std::mutex> lockSubmit(m_submitLock);
{ std::unique_lock<std::mutex> lock(m_mutex);
m_stopped.store(true);
}
m_submitCondOnAdd.notify_one();
m_submitThread.join();
m_queueCond.notify_one();
m_queueThread.join();
m_condOnAdd.notify_one();
m_thread.join();
}
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();
}
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::submit(const Rc<DxvkCommandList>& cmdList) {
{ std::unique_lock<std::mutex> lock(m_mutex);
m_condOnTake.wait(lock, [this] {
return m_entries.size() < MaxNumQueuedCommandBuffers;
});
m_submits += 1;
m_entries.push(cmdList);
m_condOnAdd.notify_one();
}
}
void DxvkSubmissionQueue::threadQueue() {
void DxvkSubmissionQueue::threadFunc() {
env::setThreadName(L"dxvk-queue");
while (!m_stopped.load()) {
Rc<DxvkCommandList> cmdList;
{ std::unique_lock<std::mutex> lock(m_queueLock);
{ std::unique_lock<std::mutex> lock(m_mutex);
m_queueCond.wait(lock, [this] {
return m_stopped.load() || (m_queueEntries.size() != 0);
m_condOnAdd.wait(lock, [this] {
return m_stopped.load() || (m_entries.size() != 0);
});
if (m_queueEntries.size() != 0) {
cmdList = std::move(m_queueEntries.front());
m_queueEntries.pop();
if (m_entries.size() != 0) {
cmdList = std::move(m_entries.front());
m_entries.pop();
}
m_condOnTake.notify_one();
}
if (cmdList != nullptr) {

View File

@ -11,12 +11,6 @@
namespace dxvk {
class DxvkDevice;
struct DxvkSubmission {
Rc<DxvkCommandList> cmdList;
Rc<DxvkSemaphore> semWait;
Rc<DxvkSemaphore> semWake;
};
/**
* \brief Submission queue
@ -47,33 +41,9 @@ namespace dxvk {
* to finish executing on the GPU and signal
* any queries and events that are used by
* the command list in question.
* \param [in] submission Command submission
* \param [in] cmdList The command list
*/
void submit(DxvkSubmission submission);
/**
* \brief Synchronizes with submission thread
*
* Waits until all submissions queued prior
* to this call are submitted to the GPU.
*/
void synchronize();
/**
* \brief Locks external queue lock
* Protects the Vulkan queue.
*/
void lock() {
m_externalLock.lock();
}
/**
* \brief Locks external queue lock
* Releases the Vulkan queue.
*/
void unlock() {
m_externalLock.unlock();
}
void submit(const Rc<DxvkCommandList>& cmdList);
private:
@ -81,22 +51,14 @@ namespace dxvk {
std::atomic<bool> m_stopped = { false };
std::atomic<uint32_t> m_submits = { 0u };
std::mutex m_externalLock;
std::mutex m_queueLock;
std::condition_variable m_queueCond;
std::queue<Rc<DxvkCommandList>> m_queueEntries;
dxvk::thread m_queueThread;
std::mutex m_mutex;
std::condition_variable m_condOnAdd;
std::condition_variable m_condOnTake;
std::queue<Rc<DxvkCommandList>> m_entries;
dxvk::thread m_thread;
std::mutex m_submitLock;
std::condition_variable m_submitCondOnAdd;
std::condition_variable m_submitCondOnTake;
std::queue<DxvkSubmission> m_submitQueue;
dxvk::thread m_submitThread;
void threadSubmit();
void threadQueue();
void threadFunc();
};