1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-02 04:29:14 +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; 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 * \brief Queries supported shader stages
* \returns Supported shader pipeline stages * \returns Supported shader pipeline stages

View File

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

View File

@ -92,6 +92,17 @@ namespace dxvk {
uint64_t gpuIdleTicks() const { uint64_t gpuIdleTicks() const {
return m_gpuIdle.load(); 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 * \brief Submits a command list asynchronously
@ -157,6 +168,8 @@ namespace dxvk {
DxvkDevice* m_device; DxvkDevice* m_device;
bool m_asyncPresent; bool m_asyncPresent;
std::atomic<VkResult> m_lastError = { VK_SUCCESS };
std::atomic<bool> m_stopped = { false }; std::atomic<bool> m_stopped = { false };
std::atomic<uint32_t> m_pending = { 0u }; std::atomic<uint32_t> m_pending = { 0u };