mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-29 17:52:18 +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(
|
||||
VkCommandBuffer commandBuffer) {
|
||||
VkCommandBufferSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO };
|
||||
@ -73,7 +79,7 @@ namespace dxvk {
|
||||
VkResult vr = VK_SUCCESS;
|
||||
|
||||
if (!this->isEmpty())
|
||||
vr = vk->vkQueueSubmit2(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
vr = vk->vkQueueSubmit2(queue, 1, &submitInfo, m_fence);
|
||||
|
||||
this->reset();
|
||||
return vr;
|
||||
@ -81,6 +87,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
void DxvkCommandSubmission::reset() {
|
||||
m_fence = VK_NULL_HANDLE;
|
||||
m_semaphoreWaits.clear();
|
||||
m_semaphoreSignals.clear();
|
||||
m_commandBuffers.clear();
|
||||
@ -88,7 +95,8 @@ namespace dxvk {
|
||||
|
||||
|
||||
bool DxvkCommandSubmission::isEmpty() const {
|
||||
return m_semaphoreWaits.empty()
|
||||
return m_fence == VK_NULL_HANDLE
|
||||
&& m_semaphoreWaits.empty()
|
||||
&& m_semaphoreSignals.empty()
|
||||
&& m_commandBuffers.empty();
|
||||
}
|
||||
@ -171,6 +179,11 @@ namespace dxvk {
|
||||
if (m_vkd->vkCreateSemaphore(m_vkd->device(), &semaphoreInfo, nullptr, &m_sdmaSemaphore))
|
||||
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);
|
||||
|
||||
if (transferQueue.queueFamily != graphicsQueue.queueFamily)
|
||||
@ -286,6 +299,9 @@ namespace dxvk {
|
||||
m_commandSubmission.signalSemaphore(m_wsiSemaphores.present,
|
||||
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
|
||||
@ -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() {
|
||||
// Free resources and other objects
|
||||
// that are no longer in use
|
||||
@ -389,6 +410,10 @@ namespace dxvk {
|
||||
// Reset actual command buffers and pools
|
||||
m_graphicsPool->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,
|
||||
VkPipelineStageFlags2 stageMask);
|
||||
|
||||
/**
|
||||
* \brief Adds a fence to signal
|
||||
* \param [in] fence The fence
|
||||
*/
|
||||
void signalFence(
|
||||
VkFence fence);
|
||||
|
||||
/**
|
||||
* \brief Adds a command buffer to execute
|
||||
* \param [in] commandBuffer The command buffer
|
||||
@ -105,6 +112,7 @@ namespace dxvk {
|
||||
|
||||
private:
|
||||
|
||||
VkFence m_fence = VK_NULL_HANDLE;
|
||||
std::vector<VkSemaphoreSubmitInfo> m_semaphoreWaits;
|
||||
std::vector<VkSemaphoreSubmitInfo> m_semaphoreSignals;
|
||||
std::vector<VkCommandBufferSubmitInfo> m_commandBuffers;
|
||||
@ -359,6 +367,12 @@ namespace dxvk {
|
||||
m_wsiSemaphores = wsiSemaphores;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Synchronizes with command list fence
|
||||
* \returns Return value of vkWaitForFences call
|
||||
*/
|
||||
VkResult synchronizeFence();
|
||||
|
||||
/**
|
||||
* \brief Resets the command list
|
||||
*
|
||||
@ -996,6 +1010,7 @@ namespace dxvk {
|
||||
Rc<DxvkCommandPool> m_transferPool;
|
||||
|
||||
VkSemaphore m_sdmaSemaphore = VK_NULL_HANDLE;
|
||||
VkFence m_fence = VK_NULL_HANDLE;
|
||||
|
||||
DxvkCommandSubmissionInfo m_cmd;
|
||||
|
||||
|
@ -32,8 +32,6 @@ namespace dxvk {
|
||||
m_submitThread.join();
|
||||
m_finishThread.join();
|
||||
|
||||
synchronizeSemaphore(m_semaphoreValue);
|
||||
|
||||
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() {
|
||||
env::setThreadName("dxvk-submit");
|
||||
|
||||
@ -141,12 +115,10 @@ namespace dxvk {
|
||||
if (m_lastError != VK_ERROR_DEVICE_LOST) {
|
||||
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);
|
||||
entry.submit.semaphoreValue = m_semaphoreValue;
|
||||
} else if (entry.present.presenter != nullptr) {
|
||||
else if (entry.present.presenter != nullptr)
|
||||
status = entry.present.presenter->presentImage();
|
||||
}
|
||||
} else {
|
||||
// Don't submit anything after device loss
|
||||
// so that drivers get a chance to recover
|
||||
@ -200,7 +172,7 @@ namespace dxvk {
|
||||
VkResult status = m_lastError.load();
|
||||
|
||||
if (status != VK_ERROR_DEVICE_LOST)
|
||||
status = synchronizeSemaphore(entry.submit.semaphoreValue);
|
||||
status = entry.submit.cmdList->synchronizeFence();
|
||||
|
||||
if (status != VK_SUCCESS) {
|
||||
m_lastError = status;
|
||||
|
@ -33,7 +33,6 @@ namespace dxvk {
|
||||
*/
|
||||
struct DxvkSubmitInfo {
|
||||
Rc<DxvkCommandList> cmdList;
|
||||
uint64_t semaphoreValue;
|
||||
};
|
||||
|
||||
|
||||
@ -200,9 +199,6 @@ namespace dxvk {
|
||||
dxvk::thread m_submitThread;
|
||||
dxvk::thread m_finishThread;
|
||||
|
||||
VkResult synchronizeSemaphore(
|
||||
uint64_t semaphoreValue);
|
||||
|
||||
void submitCmdLists();
|
||||
|
||||
void finishCmdLists();
|
||||
|
Loading…
x
Reference in New Issue
Block a user