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

[dxvk] Handle device lost errors on command submission

This commit is contained in:
Philip Rebohle 2019-09-22 18:51:11 +02:00
parent 92d1cf8ae0
commit 2e9a836adb
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 46 additions and 12 deletions

View File

@ -173,6 +173,17 @@ namespace dxvk {
return m_properties;
}
/**
* \brief Get device status
*
* This may report device loss in
* case a submission failed.
* \returns Device status
*/
VkResult getDeviceStatus() const {
return m_submissionQueue.getLastError();
}
/**
* \brief Queries supported shader stages
* \returns Supported shader pipeline stages

View File

@ -114,7 +114,8 @@ namespace dxvk {
// Submit command buffer to device
VkResult status = VK_NOT_READY;
{ std::lock_guard<std::mutex> lock(m_mutexQueue);
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(
@ -124,6 +125,10 @@ namespace dxvk {
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)
@ -135,8 +140,10 @@ namespace dxvk {
if (status == VK_SUCCESS) {
if (entry.submit.cmdList != nullptr)
m_finishQueue.push(std::move(entry));
} else if (entry.submit.cmdList != nullptr) {
} 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();
@ -168,19 +175,22 @@ namespace dxvk {
DxvkSubmitEntry entry = std::move(m_finishQueue.front());
lock.unlock();
VkResult status = entry.submit.cmdList->synchronize();
VkResult status = m_lastError.load();
if (status == VK_SUCCESS) {
entry.submit.cmdList->notifySignals();
entry.submit.cmdList->reset();
m_device->recycleCommandList(entry.submit.cmdList);
} else {
Logger::err(str::format(
"DxvkSubmissionQueue: Failed to sync fence: ",
status));
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;

View File

@ -92,6 +92,17 @@ namespace dxvk {
uint64_t gpuIdleTicks() const {
return m_gpuIdle.load();
}
/**
* \brief Retrieves last submission error
*
* In case an error occured during asynchronous command
* submission, it will be returned by this function.
* \returns Last error from command submission
*/
VkResult getLastError() const {
return m_lastError.load();
}
/**
* \brief Submits a command list asynchronously
@ -157,6 +168,8 @@ namespace dxvk {
DxvkDevice* m_device;
bool m_asyncPresent;
std::atomic<VkResult> m_lastError = { VK_SUCCESS };
std::atomic<bool> m_stopped = { false };
std::atomic<uint32_t> m_pending = { 0u };