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:
parent
2eda95f61a
commit
0f52ec2796
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user