mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-04 16:24:29 +01:00
[dxvk] Implement waiting for specific present requests
This commit is contained in:
parent
ca3492570c
commit
5d1196733b
@ -414,7 +414,7 @@ namespace dxvk {
|
|||||||
if (cHud != nullptr && !cFrameId)
|
if (cHud != nullptr && !cFrameId)
|
||||||
cHud->update();
|
cHud->update();
|
||||||
|
|
||||||
m_device->presentImage(m_presenter, cPresentMode, &m_presentStatus);
|
m_device->presentImage(m_presenter, cPresentMode, 0, &m_presentStatus);
|
||||||
});
|
});
|
||||||
|
|
||||||
pContext->FlushCsChunk();
|
pContext->FlushCsChunk();
|
||||||
|
@ -833,7 +833,7 @@ namespace dxvk {
|
|||||||
if (cHud != nullptr && !cFrameId)
|
if (cHud != nullptr && !cFrameId)
|
||||||
cHud->update();
|
cHud->update();
|
||||||
|
|
||||||
m_device->presentImage(m_presenter, cPresentMode, &m_presentStatus);
|
m_device->presentImage(m_presenter, cPresentMode, 0, &m_presentStatus);
|
||||||
});
|
});
|
||||||
|
|
||||||
m_parent->FlushCsChunk();
|
m_parent->FlushCsChunk();
|
||||||
|
@ -254,12 +254,14 @@ namespace dxvk {
|
|||||||
void DxvkDevice::presentImage(
|
void DxvkDevice::presentImage(
|
||||||
const Rc<Presenter>& presenter,
|
const Rc<Presenter>& presenter,
|
||||||
VkPresentModeKHR presentMode,
|
VkPresentModeKHR presentMode,
|
||||||
|
uint64_t frameId,
|
||||||
DxvkSubmitStatus* status) {
|
DxvkSubmitStatus* status) {
|
||||||
status->result = VK_NOT_READY;
|
status->result = VK_NOT_READY;
|
||||||
|
|
||||||
DxvkPresentInfo presentInfo = { };
|
DxvkPresentInfo presentInfo = { };
|
||||||
presentInfo.presenter = presenter;
|
presentInfo.presenter = presenter;
|
||||||
presentInfo.presentMode = presentMode;
|
presentInfo.presentMode = presentMode;
|
||||||
|
presentInfo.frameId = frameId;
|
||||||
m_submissionQueue.present(presentInfo, status);
|
m_submissionQueue.present(presentInfo, status);
|
||||||
|
|
||||||
std::lock_guard<sync::Spinlock> statLock(m_statLock);
|
std::lock_guard<sync::Spinlock> statLock(m_statLock);
|
||||||
@ -310,10 +312,13 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxvkDevice::waitForIdle() {
|
void DxvkDevice::waitForIdle() {
|
||||||
this->lockSubmission();
|
m_submissionQueue.waitForIdle();
|
||||||
|
m_submissionQueue.lockDeviceQueue();
|
||||||
|
|
||||||
if (m_vkd->vkDeviceWaitIdle(m_vkd->device()) != VK_SUCCESS)
|
if (m_vkd->vkDeviceWaitIdle(m_vkd->device()) != VK_SUCCESS)
|
||||||
Logger::err("DxvkDevice: waitForIdle: Operation failed");
|
Logger::err("DxvkDevice: waitForIdle: Operation failed");
|
||||||
this->unlockSubmission();
|
|
||||||
|
m_submissionQueue.unlockDeviceQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -455,11 +455,13 @@ namespace dxvk {
|
|||||||
* can be retrieved with \ref waitForSubmission.
|
* can be retrieved with \ref waitForSubmission.
|
||||||
* \param [in] presenter The presenter
|
* \param [in] presenter The presenter
|
||||||
* \param [in] presenteMode Present mode
|
* \param [in] presenteMode Present mode
|
||||||
|
* \param [in] frameId Optional frame ID
|
||||||
* \param [out] status Present status
|
* \param [out] status Present status
|
||||||
*/
|
*/
|
||||||
void presentImage(
|
void presentImage(
|
||||||
const Rc<Presenter>& presenter,
|
const Rc<Presenter>& presenter,
|
||||||
VkPresentModeKHR presentMode,
|
VkPresentModeKHR presentMode,
|
||||||
|
uint64_t frameId,
|
||||||
DxvkSubmitStatus* status);
|
DxvkSubmitStatus* status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -593,7 +593,7 @@ namespace dxvk {
|
|||||||
VkExtent2D desired) {
|
VkExtent2D desired) {
|
||||||
if (caps.currentExtent.width != std::numeric_limits<uint32_t>::max())
|
if (caps.currentExtent.width != std::numeric_limits<uint32_t>::max())
|
||||||
return caps.currentExtent;
|
return caps.currentExtent;
|
||||||
|
|
||||||
VkExtent2D actual;
|
VkExtent2D actual;
|
||||||
actual.width = clamp(desired.width, caps.minImageExtent.width, caps.maxImageExtent.width);
|
actual.width = clamp(desired.width, caps.minImageExtent.width, caps.maxImageExtent.width);
|
||||||
actual.height = clamp(desired.height, caps.minImageExtent.height, caps.maxImageExtent.height);
|
actual.height = clamp(desired.height, caps.minImageExtent.height, caps.maxImageExtent.height);
|
||||||
|
@ -74,6 +74,19 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkSubmissionQueue::waitForIdle() {
|
||||||
|
std::unique_lock<dxvk::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
m_submitCond.wait(lock, [this] {
|
||||||
|
return m_submitQueue.empty();
|
||||||
|
});
|
||||||
|
|
||||||
|
m_finishCond.wait(lock, [this] {
|
||||||
|
return m_finishQueue.empty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkSubmissionQueue::lockDeviceQueue() {
|
void DxvkSubmissionQueue::lockDeviceQueue() {
|
||||||
m_mutexQueue.lock();
|
m_mutexQueue.lock();
|
||||||
|
|
||||||
@ -107,8 +120,6 @@ namespace dxvk {
|
|||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
// Submit command buffer to device
|
// Submit command buffer to device
|
||||||
VkResult status = VK_NOT_READY;
|
|
||||||
|
|
||||||
if (m_lastError != VK_ERROR_DEVICE_LOST) {
|
if (m_lastError != VK_ERROR_DEVICE_LOST) {
|
||||||
std::lock_guard<dxvk::mutex> lock(m_mutexQueue);
|
std::lock_guard<dxvk::mutex> lock(m_mutexQueue);
|
||||||
|
|
||||||
@ -116,31 +127,35 @@ namespace dxvk {
|
|||||||
m_callback(true);
|
m_callback(true);
|
||||||
|
|
||||||
if (entry.submit.cmdList != nullptr)
|
if (entry.submit.cmdList != nullptr)
|
||||||
status = entry.submit.cmdList->submit();
|
entry.result = entry.submit.cmdList->submit();
|
||||||
else if (entry.present.presenter != nullptr)
|
else if (entry.present.presenter != nullptr)
|
||||||
status = entry.present.presenter->presentImage(entry.present.presentMode, 0);
|
entry.result = entry.present.presenter->presentImage(entry.present.presentMode, entry.present.frameId);
|
||||||
|
|
||||||
if (m_callback)
|
if (m_callback)
|
||||||
m_callback(false);
|
m_callback(false);
|
||||||
} else {
|
} else {
|
||||||
// Don't submit anything after device loss
|
// Don't submit anything after device loss
|
||||||
// so that drivers get a chance to recover
|
// so that drivers get a chance to recover
|
||||||
status = VK_ERROR_DEVICE_LOST;
|
entry.result = VK_ERROR_DEVICE_LOST;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.status)
|
if (entry.status)
|
||||||
entry.status->result = status;
|
entry.status->result = entry.result;
|
||||||
|
|
||||||
// On success, pass it on to the queue thread
|
// On success, pass it on to the queue thread
|
||||||
lock = std::unique_lock<dxvk::mutex>(m_mutex);
|
lock = std::unique_lock<dxvk::mutex>(m_mutex);
|
||||||
|
|
||||||
if (status == VK_SUCCESS) {
|
bool doForward = (entry.result == VK_SUCCESS) ||
|
||||||
if (entry.submit.cmdList != nullptr)
|
(entry.present.presenter != nullptr && entry.result != VK_ERROR_DEVICE_LOST);
|
||||||
m_finishQueue.push(std::move(entry));
|
|
||||||
} else if (status == VK_ERROR_DEVICE_LOST || entry.submit.cmdList != nullptr) {
|
if (doForward) {
|
||||||
Logger::err(str::format("DxvkSubmissionQueue: Command submission failed: ", status));
|
m_finishQueue.push(std::move(entry));
|
||||||
m_lastError = status;
|
} else {
|
||||||
m_device->waitForIdle();
|
Logger::err(str::format("DxvkSubmissionQueue: Command submission failed: ", entry.result));
|
||||||
|
m_lastError = entry.result;
|
||||||
|
|
||||||
|
if (m_lastError != VK_ERROR_DEVICE_LOST)
|
||||||
|
m_device->waitForIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_submitQueue.pop();
|
m_submitQueue.pop();
|
||||||
@ -172,20 +187,31 @@ namespace dxvk {
|
|||||||
DxvkSubmitEntry entry = std::move(m_finishQueue.front());
|
DxvkSubmitEntry entry = std::move(m_finishQueue.front());
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
VkResult status = m_lastError.load();
|
if (entry.submit.cmdList != nullptr) {
|
||||||
|
VkResult status = m_lastError.load();
|
||||||
if (status != VK_ERROR_DEVICE_LOST)
|
|
||||||
status = entry.submit.cmdList->synchronizeFence();
|
if (status != VK_ERROR_DEVICE_LOST)
|
||||||
|
status = entry.submit.cmdList->synchronizeFence();
|
||||||
if (status != VK_SUCCESS) {
|
|
||||||
m_lastError = status;
|
if (status != VK_SUCCESS) {
|
||||||
m_device->waitForIdle();
|
m_lastError = status;
|
||||||
|
|
||||||
|
if (status != VK_ERROR_DEVICE_LOST)
|
||||||
|
m_device->waitForIdle();
|
||||||
|
}
|
||||||
|
} else if (entry.present.presenter != nullptr) {
|
||||||
|
// Signal the frame and then immediately destroy the reference.
|
||||||
|
// This is necessary since the front-end may want to explicitly
|
||||||
|
// destroy the presenter object.
|
||||||
|
entry.present.presenter->signalFrame(entry.result, entry.present.frameId);
|
||||||
|
entry.present.presenter = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release resources and signal events, then immediately wake
|
// Release resources and signal events, then immediately wake
|
||||||
// up any thread that's currently waiting on a resource in
|
// up any thread that's currently waiting on a resource in
|
||||||
// order to reduce delays as much as possible.
|
// order to reduce delays as much as possible.
|
||||||
entry.submit.cmdList->notifyObjects();
|
if (entry.submit.cmdList != nullptr)
|
||||||
|
entry.submit.cmdList->notifyObjects();
|
||||||
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
m_pending -= 1;
|
m_pending -= 1;
|
||||||
@ -195,8 +221,10 @@ namespace dxvk {
|
|||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
// Free the command list and associated objects now
|
// Free the command list and associated objects now
|
||||||
entry.submit.cmdList->reset();
|
if (entry.submit.cmdList != nullptr) {
|
||||||
m_device->recycleCommandList(entry.submit.cmdList);
|
entry.submit.cmdList->reset();
|
||||||
|
m_device->recycleCommandList(entry.submit.cmdList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ namespace dxvk {
|
|||||||
struct DxvkPresentInfo {
|
struct DxvkPresentInfo {
|
||||||
Rc<Presenter> presenter;
|
Rc<Presenter> presenter;
|
||||||
VkPresentModeKHR presentMode;
|
VkPresentModeKHR presentMode;
|
||||||
|
uint64_t frameId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -51,6 +52,7 @@ namespace dxvk {
|
|||||||
* \brief Submission queue entry
|
* \brief Submission queue entry
|
||||||
*/
|
*/
|
||||||
struct DxvkSubmitEntry {
|
struct DxvkSubmitEntry {
|
||||||
|
VkResult result;
|
||||||
DxvkSubmitStatus* status;
|
DxvkSubmitStatus* status;
|
||||||
DxvkSubmitInfo submit;
|
DxvkSubmitInfo submit;
|
||||||
DxvkPresentInfo present;
|
DxvkPresentInfo present;
|
||||||
@ -160,6 +162,11 @@ namespace dxvk {
|
|||||||
m_finishCond.wait(lock, pred);
|
m_finishCond.wait(lock, pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Waits for all submissions to complete
|
||||||
|
*/
|
||||||
|
void waitForIdle();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Locks device queue
|
* \brief Locks device queue
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user