mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-06 13:54:14 +01:00
[dxvk] Go back to fence-based command list synchronization
Timeline semaphores are too unreliable on 32-bit Proton builds.
This commit is contained in:
parent
439043ddb4
commit
1b66b8c9f3
@ -39,6 +39,12 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkCommandSubmission::signalFence(
|
||||||
|
VkFence fence) {
|
||||||
|
m_fence = fence;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkCommandSubmission::executeCommandBuffer(
|
void DxvkCommandSubmission::executeCommandBuffer(
|
||||||
VkCommandBuffer commandBuffer) {
|
VkCommandBuffer commandBuffer) {
|
||||||
VkCommandBufferSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO };
|
VkCommandBufferSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO };
|
||||||
@ -73,7 +79,7 @@ namespace dxvk {
|
|||||||
VkResult vr = VK_SUCCESS;
|
VkResult vr = VK_SUCCESS;
|
||||||
|
|
||||||
if (!this->isEmpty())
|
if (!this->isEmpty())
|
||||||
vr = vk->vkQueueSubmit2(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
vr = vk->vkQueueSubmit2(queue, 1, &submitInfo, m_fence);
|
||||||
|
|
||||||
this->reset();
|
this->reset();
|
||||||
return vr;
|
return vr;
|
||||||
@ -81,6 +87,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxvkCommandSubmission::reset() {
|
void DxvkCommandSubmission::reset() {
|
||||||
|
m_fence = VK_NULL_HANDLE;
|
||||||
m_semaphoreWaits.clear();
|
m_semaphoreWaits.clear();
|
||||||
m_semaphoreSignals.clear();
|
m_semaphoreSignals.clear();
|
||||||
m_commandBuffers.clear();
|
m_commandBuffers.clear();
|
||||||
@ -88,7 +95,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
bool DxvkCommandSubmission::isEmpty() const {
|
bool DxvkCommandSubmission::isEmpty() const {
|
||||||
return m_semaphoreWaits.empty()
|
return m_fence == VK_NULL_HANDLE
|
||||||
|
&& m_semaphoreWaits.empty()
|
||||||
&& m_semaphoreSignals.empty()
|
&& m_semaphoreSignals.empty()
|
||||||
&& m_commandBuffers.empty();
|
&& m_commandBuffers.empty();
|
||||||
}
|
}
|
||||||
@ -171,6 +179,11 @@ namespace dxvk {
|
|||||||
if (m_vkd->vkCreateSemaphore(m_vkd->device(), &semaphoreInfo, nullptr, &m_sdmaSemaphore))
|
if (m_vkd->vkCreateSemaphore(m_vkd->device(), &semaphoreInfo, nullptr, &m_sdmaSemaphore))
|
||||||
throw DxvkError("DxvkCommandList: Failed to create semaphore");
|
throw DxvkError("DxvkCommandList: Failed to create semaphore");
|
||||||
|
|
||||||
|
VkFenceCreateInfo fenceInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
|
||||||
|
|
||||||
|
if (m_vkd->vkCreateFence(m_vkd->device(), &fenceInfo, nullptr, &m_fence))
|
||||||
|
throw DxvkError("DxvkCommandList: Failed to create fence");
|
||||||
|
|
||||||
m_graphicsPool = new DxvkCommandPool(device, graphicsQueue.queueFamily);
|
m_graphicsPool = new DxvkCommandPool(device, graphicsQueue.queueFamily);
|
||||||
|
|
||||||
if (transferQueue.queueFamily != graphicsQueue.queueFamily)
|
if (transferQueue.queueFamily != graphicsQueue.queueFamily)
|
||||||
@ -286,6 +299,9 @@ namespace dxvk {
|
|||||||
m_commandSubmission.signalSemaphore(m_wsiSemaphores.present,
|
m_commandSubmission.signalSemaphore(m_wsiSemaphores.present,
|
||||||
0, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT);
|
0, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Signal synchronization fence on final submission
|
||||||
|
m_commandSubmission.signalFence(m_fence);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, submit all graphics commands of the current submission
|
// Finally, submit all graphics commands of the current submission
|
||||||
@ -350,6 +366,11 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VkResult DxvkCommandList::synchronizeFence() {
|
||||||
|
return m_vkd->vkWaitForFences(m_vkd->device(), 1, &m_fence, VK_TRUE, ~0ull);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkCommandList::reset() {
|
void DxvkCommandList::reset() {
|
||||||
// Free resources and other objects
|
// Free resources and other objects
|
||||||
// that are no longer in use
|
// that are no longer in use
|
||||||
@ -389,6 +410,10 @@ namespace dxvk {
|
|||||||
// Reset actual command buffers and pools
|
// Reset actual command buffers and pools
|
||||||
m_graphicsPool->reset();
|
m_graphicsPool->reset();
|
||||||
m_transferPool->reset();
|
m_transferPool->reset();
|
||||||
|
|
||||||
|
// Reset fence
|
||||||
|
if (m_vkd->vkResetFences(m_vkd->device(), 1, &m_fence))
|
||||||
|
Logger::err("DxvkCommandList: Failed to reset fence");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,6 +72,13 @@ namespace dxvk {
|
|||||||
uint64_t value,
|
uint64_t value,
|
||||||
VkPipelineStageFlags2 stageMask);
|
VkPipelineStageFlags2 stageMask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Adds a fence to signal
|
||||||
|
* \param [in] fence The fence
|
||||||
|
*/
|
||||||
|
void signalFence(
|
||||||
|
VkFence fence);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Adds a command buffer to execute
|
* \brief Adds a command buffer to execute
|
||||||
* \param [in] commandBuffer The command buffer
|
* \param [in] commandBuffer The command buffer
|
||||||
@ -105,6 +112,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
VkFence m_fence = VK_NULL_HANDLE;
|
||||||
std::vector<VkSemaphoreSubmitInfo> m_semaphoreWaits;
|
std::vector<VkSemaphoreSubmitInfo> m_semaphoreWaits;
|
||||||
std::vector<VkSemaphoreSubmitInfo> m_semaphoreSignals;
|
std::vector<VkSemaphoreSubmitInfo> m_semaphoreSignals;
|
||||||
std::vector<VkCommandBufferSubmitInfo> m_commandBuffers;
|
std::vector<VkCommandBufferSubmitInfo> m_commandBuffers;
|
||||||
@ -359,6 +367,12 @@ namespace dxvk {
|
|||||||
m_wsiSemaphores = wsiSemaphores;
|
m_wsiSemaphores = wsiSemaphores;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Synchronizes with command list fence
|
||||||
|
* \returns Return value of vkWaitForFences call
|
||||||
|
*/
|
||||||
|
VkResult synchronizeFence();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Resets the command list
|
* \brief Resets the command list
|
||||||
*
|
*
|
||||||
@ -996,6 +1010,7 @@ namespace dxvk {
|
|||||||
Rc<DxvkCommandPool> m_transferPool;
|
Rc<DxvkCommandPool> m_transferPool;
|
||||||
|
|
||||||
VkSemaphore m_sdmaSemaphore = VK_NULL_HANDLE;
|
VkSemaphore m_sdmaSemaphore = VK_NULL_HANDLE;
|
||||||
|
VkFence m_fence = VK_NULL_HANDLE;
|
||||||
|
|
||||||
DxvkCommandSubmissionInfo m_cmd;
|
DxvkCommandSubmissionInfo m_cmd;
|
||||||
|
|
||||||
|
@ -32,8 +32,6 @@ namespace dxvk {
|
|||||||
m_submitThread.join();
|
m_submitThread.join();
|
||||||
m_finishThread.join();
|
m_finishThread.join();
|
||||||
|
|
||||||
synchronizeSemaphore(m_semaphoreValue);
|
|
||||||
|
|
||||||
vk->vkDestroySemaphore(vk->device(), m_semaphore, nullptr);
|
vk->vkDestroySemaphore(vk->device(), m_semaphore, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,30 +93,6 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkResult DxvkSubmissionQueue::synchronizeSemaphore(
|
|
||||||
uint64_t semaphoreValue) {
|
|
||||||
auto vk = m_device->vkd();
|
|
||||||
|
|
||||||
VkSemaphoreWaitInfo waitInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO };
|
|
||||||
waitInfo.semaphoreCount = 1;
|
|
||||||
waitInfo.pSemaphores = &m_semaphore;
|
|
||||||
waitInfo.pValues = &semaphoreValue;
|
|
||||||
|
|
||||||
// 32-bit winevulkan on Proton seems to be broken here
|
|
||||||
// and returns with VK_TIMEOUT, even though the timeout
|
|
||||||
// is infinite. Work around this by spinning.
|
|
||||||
VkResult vr = VK_TIMEOUT;
|
|
||||||
|
|
||||||
while (vr == VK_TIMEOUT)
|
|
||||||
vr = vk->vkWaitSemaphores(vk->device(), &waitInfo, ~0ull);
|
|
||||||
|
|
||||||
if (vr)
|
|
||||||
Logger::err(str::format("Failed to synchronize with global timeline semaphore: ", vr));
|
|
||||||
|
|
||||||
return vr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DxvkSubmissionQueue::submitCmdLists() {
|
void DxvkSubmissionQueue::submitCmdLists() {
|
||||||
env::setThreadName("dxvk-submit");
|
env::setThreadName("dxvk-submit");
|
||||||
|
|
||||||
@ -141,12 +115,10 @@ namespace dxvk {
|
|||||||
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);
|
||||||
|
|
||||||
if (entry.submit.cmdList != nullptr) {
|
if (entry.submit.cmdList != nullptr)
|
||||||
status = entry.submit.cmdList->submit(m_semaphore, m_semaphoreValue);
|
status = entry.submit.cmdList->submit(m_semaphore, m_semaphoreValue);
|
||||||
entry.submit.semaphoreValue = m_semaphoreValue;
|
else if (entry.present.presenter != nullptr)
|
||||||
} else if (entry.present.presenter != nullptr) {
|
|
||||||
status = entry.present.presenter->presentImage();
|
status = entry.present.presenter->presentImage();
|
||||||
}
|
|
||||||
} 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
|
||||||
@ -200,7 +172,7 @@ namespace dxvk {
|
|||||||
VkResult status = m_lastError.load();
|
VkResult status = m_lastError.load();
|
||||||
|
|
||||||
if (status != VK_ERROR_DEVICE_LOST)
|
if (status != VK_ERROR_DEVICE_LOST)
|
||||||
status = synchronizeSemaphore(entry.submit.semaphoreValue);
|
status = entry.submit.cmdList->synchronizeFence();
|
||||||
|
|
||||||
if (status != VK_SUCCESS) {
|
if (status != VK_SUCCESS) {
|
||||||
m_lastError = status;
|
m_lastError = status;
|
||||||
|
@ -33,7 +33,6 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
struct DxvkSubmitInfo {
|
struct DxvkSubmitInfo {
|
||||||
Rc<DxvkCommandList> cmdList;
|
Rc<DxvkCommandList> cmdList;
|
||||||
uint64_t semaphoreValue;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -200,9 +199,6 @@ namespace dxvk {
|
|||||||
dxvk::thread m_submitThread;
|
dxvk::thread m_submitThread;
|
||||||
dxvk::thread m_finishThread;
|
dxvk::thread m_finishThread;
|
||||||
|
|
||||||
VkResult synchronizeSemaphore(
|
|
||||||
uint64_t semaphoreValue);
|
|
||||||
|
|
||||||
void submitCmdLists();
|
void submitCmdLists();
|
||||||
|
|
||||||
void finishCmdLists();
|
void finishCmdLists();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user