mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-15 16:29:16 +01:00
[dxvk] Perform acquire and present synchronization in the backend
And add method to explicitly destroy relevant Vulkan objects.
This commit is contained in:
parent
b03ff775ce
commit
42adc4ac11
@ -70,14 +70,25 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
VkResult Presenter::acquireNextImage(PresenterSync& sync, Rc<DxvkImage>& image) {
|
VkResult Presenter::acquireNextImage(PresenterSync& sync, Rc<DxvkImage>& image) {
|
||||||
std::lock_guard lock(m_surfaceMutex);
|
std::unique_lock lock(m_surfaceMutex);
|
||||||
|
|
||||||
|
// Don't acquire more than one image at a time
|
||||||
|
VkResult status = VK_SUCCESS;
|
||||||
|
|
||||||
|
m_surfaceCond.wait(lock, [this, &status] {
|
||||||
|
status = m_device->getDeviceStatus();
|
||||||
|
return !m_presentPending || status < 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
|
||||||
// Ensure that the swap chain gets recreated if it is dirty
|
// Ensure that the swap chain gets recreated if it is dirty
|
||||||
bool hasSwapchain = m_swapchain != VK_NULL_HANDLE;
|
bool hasSwapchain = m_swapchain != VK_NULL_HANDLE;
|
||||||
|
|
||||||
updateSwapChain();
|
updateSwapChain();
|
||||||
|
|
||||||
// Don't acquire more than one image at a time
|
// Don't acquire if we already did so after present
|
||||||
if (m_acquireStatus == VK_NOT_READY && m_swapchain) {
|
if (m_acquireStatus == VK_NOT_READY && m_swapchain) {
|
||||||
PresenterSync sync = m_semaphores.at(m_frameIndex);
|
PresenterSync sync = m_semaphores.at(m_frameIndex);
|
||||||
|
|
||||||
@ -136,6 +147,7 @@ namespace dxvk {
|
|||||||
sync = m_semaphores.at(m_frameIndex);
|
sync = m_semaphores.at(m_frameIndex);
|
||||||
image = m_images.at(m_imageIndex);
|
image = m_images.at(m_imageIndex);
|
||||||
|
|
||||||
|
m_presentPending = true;
|
||||||
return m_acquireStatus;
|
return m_acquireStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,25 +197,29 @@ namespace dxvk {
|
|||||||
m_frameIndex %= m_semaphores.size();
|
m_frameIndex %= m_semaphores.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recreate the swapchain on the next acquire, even if we get suboptimal.
|
|
||||||
// There is no guarantee that suboptimal state is returned by both functions.
|
|
||||||
if (status != VK_SUCCESS) {
|
|
||||||
Logger::info(str::format("Presenter: Got ", status, ", recreating swapchain"));
|
|
||||||
|
|
||||||
std::lock_guard lock(m_surfaceMutex);
|
|
||||||
m_dirtySwapchain = true;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// On a successful present, try to acquire next image already, in
|
// On a successful present, try to acquire next image already, in
|
||||||
// order to hide potential delays from the application thread.
|
// order to hide potential delays from the application thread.
|
||||||
|
if (status == VK_SUCCESS) {
|
||||||
PresenterSync& nextSync = m_semaphores.at(m_frameIndex);
|
PresenterSync& nextSync = m_semaphores.at(m_frameIndex);
|
||||||
waitForSwapchainFence(nextSync);
|
waitForSwapchainFence(nextSync);
|
||||||
|
|
||||||
m_acquireStatus = m_vkd->vkAcquireNextImageKHR(m_vkd->device(),
|
m_acquireStatus = m_vkd->vkAcquireNextImageKHR(m_vkd->device(),
|
||||||
m_swapchain, std::numeric_limits<uint64_t>::max(),
|
m_swapchain, std::numeric_limits<uint64_t>::max(),
|
||||||
nextSync.acquire, VK_NULL_HANDLE, &m_imageIndex);
|
nextSync.acquire, VK_NULL_HANDLE, &m_imageIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recreate the swapchain on the next acquire, even if we get suboptimal.
|
||||||
|
// There is no guarantee that suboptimal state is returned by both functions.
|
||||||
|
std::lock_guard lock(m_surfaceMutex);
|
||||||
|
|
||||||
|
if (status != VK_SUCCESS) {
|
||||||
|
Logger::info(str::format("Presenter: Got ", status, ", recreating swapchain"));
|
||||||
|
|
||||||
|
m_dirtySwapchain = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_presentPending = false;
|
||||||
|
m_surfaceCond.notify_one();
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,6 +281,19 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Presenter::destroyResources() {
|
||||||
|
std::unique_lock lock(m_surfaceMutex);
|
||||||
|
|
||||||
|
m_surfaceCond.wait(lock, [this] {
|
||||||
|
VkResult status = m_device->getDeviceStatus();
|
||||||
|
return !m_presentPending || status < 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
destroySwapchain();
|
||||||
|
destroySurface();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Presenter::setSyncInterval(uint32_t syncInterval) {
|
void Presenter::setSyncInterval(uint32_t syncInterval) {
|
||||||
std::lock_guard lock(m_surfaceMutex);
|
std::lock_guard lock(m_surfaceMutex);
|
||||||
|
|
||||||
@ -965,6 +994,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_swapchain = VK_NULL_HANDLE;
|
m_swapchain = VK_NULL_HANDLE;
|
||||||
m_acquireStatus = VK_NOT_READY;
|
m_acquireStatus = VK_NOT_READY;
|
||||||
|
|
||||||
|
m_presentPending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,6 +200,17 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
void invalidateSurface();
|
void invalidateSurface();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Destroys resources immediately
|
||||||
|
*
|
||||||
|
* Blocks calling thread until pending swapchain operations
|
||||||
|
* have completed, and guarantees that the Vulkan swapchain
|
||||||
|
* and surface get destroyed before the function returns.
|
||||||
|
* This is useful to ensure that the application window can
|
||||||
|
* be reused, even if the presenter object is kept alive.
|
||||||
|
*/
|
||||||
|
void destroyResources();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Rc<DxvkDevice> m_device;
|
Rc<DxvkDevice> m_device;
|
||||||
@ -208,9 +219,11 @@ namespace dxvk {
|
|||||||
Rc<vk::InstanceFn> m_vki;
|
Rc<vk::InstanceFn> m_vki;
|
||||||
Rc<vk::DeviceFn> m_vkd;
|
Rc<vk::DeviceFn> m_vkd;
|
||||||
|
|
||||||
dxvk::mutex m_surfaceMutex;
|
|
||||||
PresenterSurfaceProc m_surfaceProc;
|
PresenterSurfaceProc m_surfaceProc;
|
||||||
|
|
||||||
|
dxvk::mutex m_surfaceMutex;
|
||||||
|
dxvk::condition_variable m_surfaceCond;
|
||||||
|
|
||||||
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
||||||
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
|
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
|
||||||
|
|
||||||
@ -234,6 +247,7 @@ namespace dxvk {
|
|||||||
uint32_t m_frameIndex = 0;
|
uint32_t m_frameIndex = 0;
|
||||||
|
|
||||||
VkResult m_acquireStatus = VK_NOT_READY;
|
VkResult m_acquireStatus = VK_NOT_READY;
|
||||||
|
bool m_presentPending = false;
|
||||||
|
|
||||||
std::optional<VkHdrMetadataEXT> m_hdrMetadata;
|
std::optional<VkHdrMetadataEXT> m_hdrMetadata;
|
||||||
bool m_hdrMetadataDirty = false;
|
bool m_hdrMetadataDirty = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user