Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/doitsujin/dxvk.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Rebohle <philip.rebohle@tu-dortmund.de>2022-09-04 19:05:33 +0300
committerPhilip Rebohle <philip.rebohle@tu-dortmund.de>2022-09-04 19:23:11 +0300
commit1b66b8c9f369d2d38d93c2dbe59b333f632a0dea (patch)
tree62c33a3fd512eb47526f815abc60f89e45874d95
parent439043ddb4db3b03a4f0b3448b1c9b682f978dbf (diff)
[dxvk] Go back to fence-based command list synchronizationvk-fence
Timeline semaphores are too unreliable on 32-bit Proton builds.
-rw-r--r--src/dxvk/dxvk_cmdlist.cpp29
-rw-r--r--src/dxvk/dxvk_cmdlist.h15
-rw-r--r--src/dxvk/dxvk_queue.cpp34
-rw-r--r--src/dxvk/dxvk_queue.h4
4 files changed, 45 insertions, 37 deletions
diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp
index 2026a916..86c3acbd 100644
--- a/src/dxvk/dxvk_cmdlist.cpp
+++ b/src/dxvk/dxvk_cmdlist.cpp
@@ -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");
}
diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h
index fc096b01..45f67c6d 100644
--- a/src/dxvk/dxvk_cmdlist.h
+++ b/src/dxvk/dxvk_cmdlist.h
@@ -73,6 +73,13 @@ namespace dxvk {
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;
@@ -360,6 +368,12 @@ namespace dxvk {
}
/**
+ * \brief Synchronizes with command list fence
+ * \returns Return value of vkWaitForFences call
+ */
+ VkResult synchronizeFence();
+
+ /**
* \brief Resets the command list
*
* Resets the internal command buffer of the command list and
@@ -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;
diff --git a/src/dxvk/dxvk_queue.cpp b/src/dxvk/dxvk_queue.cpp
index 2db3fdd3..520a901e 100644
--- a/src/dxvk/dxvk_queue.cpp
+++ b/src/dxvk/dxvk_queue.cpp
@@ -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;
diff --git a/src/dxvk/dxvk_queue.h b/src/dxvk/dxvk_queue.h
index 370c763b..8f589b55 100644
--- a/src/dxvk/dxvk_queue.h
+++ b/src/dxvk/dxvk_queue.h
@@ -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();