[dxvk] Implemented proper swap chain synchronization

This commit is contained in:
Philip Rebohle 2017-12-16 21:30:48 +01:00
parent 1fe5b74762
commit ebabc0e578
4 changed files with 47 additions and 18 deletions

View File

@ -29,10 +29,6 @@ namespace dxvk {
m_swapchain = m_device->createSwapchain(
m_surface, swapchainProperties);
// Synchronization semaphores for swap chain operations
m_acquireSync = m_device->createSemaphore();
m_presentSync = m_device->createSemaphore();
// Sampler for presentation
DxvkSamplerCreateInfo samplerInfo;
samplerInfo.magFilter = VK_FILTER_NEAREST;
@ -172,7 +168,9 @@ namespace dxvk {
m_backBuffer, resolveSubresources);
}
auto framebuffer = m_swapchain->getFramebuffer(m_acquireSync);
const DxvkSwapSemaphores sem = m_swapchain->getSemaphorePair();
auto framebuffer = m_swapchain->getFramebuffer(sem.acquireSync);
auto framebufferSize = framebuffer->size();
m_context->bindFramebuffer(framebuffer);
@ -203,13 +201,9 @@ namespace dxvk {
m_device->submitCommandList(
m_context->endRecording(),
m_acquireSync, m_presentSync);
sem.acquireSync, sem.presentSync);
m_swapchain->present(m_presentSync);
// FIXME Make sure that the semaphores and the command
// list can be safely used without stalling the device.
m_device->waitForIdle();
m_swapchain->present(sem.presentSync);
}

View File

@ -78,9 +78,6 @@ namespace dxvk {
Rc<DxvkSurface> m_surface;
Rc<DxvkSwapchain> m_swapchain;
Rc<DxvkSemaphore> m_acquireSync;
Rc<DxvkSemaphore> m_presentSync;
Rc<DxvkSampler> m_sampler;
Rc<DxvkImage> m_backBuffer;

View File

@ -26,6 +26,14 @@ namespace dxvk {
}
DxvkSwapSemaphores DxvkSwapchain::getSemaphorePair() {
// It doesn't really matter that we increment the
// counter *before* returning the semaphore pair
m_frameIndex = (m_frameIndex + 1) % m_semaphoreSet.size();
return m_semaphoreSet.at(m_frameIndex);
}
Rc<DxvkFramebuffer> DxvkSwapchain::getFramebuffer(
const Rc<DxvkSemaphore>& wakeSync) {
VkResult status = this->acquireNextImage(wakeSync);
@ -131,7 +139,9 @@ namespace dxvk {
// Retrieve swap images
auto swapImages = this->retrieveSwapImages();
m_framebuffers.resize(swapImages.size());
m_semaphoreSet.resize(swapImages.size());
DxvkImageCreateInfo imageInfo;
imageInfo.type = VK_IMAGE_TYPE_2D;
@ -169,6 +179,9 @@ namespace dxvk {
m_framebuffers.at(i) = new DxvkFramebuffer(
m_vkd, m_renderPass, renderTargets);
m_semaphoreSet.at(i).acquireSync = m_device->createSemaphore();
m_semaphoreSet.at(i).presentSync = m_device->createSemaphore();
}
}

View File

@ -10,7 +10,19 @@ namespace dxvk {
class DxvkSurface;
/**
* \brief
* \brief Swap chain semaphore pair
*
* Holds the two semaphores requires for
* synchronizing swap chain operations.
*/
struct DxvkSwapSemaphores {
Rc<DxvkSemaphore> acquireSync; ///< Post-acquire semaphore
Rc<DxvkSemaphore> presentSync; ///< Pre-present semaphore
};
/**
* \brief Swap chain properties
*/
struct DxvkSwapchainProperties {
VkSurfaceFormatKHR preferredSurfaceFormat;
@ -22,7 +34,9 @@ namespace dxvk {
/**
* \brief DXVK swapchain
*
* Manages a Vulkan swapchain object.
* Manages a Vulkan swap chain object. Implements
* acquire and present methods and recreates the
* underlying swap chain object as necessary.
*/
class DxvkSwapchain : public RcObject {
@ -34,6 +48,16 @@ namespace dxvk {
const DxvkSwapchainProperties& properties);
~DxvkSwapchain();
/**
* \brief Acquires a pair of semaphores
*
* Retrieves a set of semaphores for the acquire
* and present operations. This must be called
* \e before \c getFramebuffer.
* \returns Semaphore pair
*/
DxvkSwapSemaphores getSemaphorePair();
/**
* \brief Retrieves the framebuffer for the current frame
*
@ -78,8 +102,9 @@ namespace dxvk {
uint32_t m_imageIndex = 0;
uint32_t m_frameIndex = 0;
Rc<DxvkRenderPass> m_renderPass;
std::vector<Rc<DxvkFramebuffer>> m_framebuffers;
Rc<DxvkRenderPass> m_renderPass;
std::vector<Rc<DxvkFramebuffer>> m_framebuffers;
std::vector<DxvkSwapSemaphores> m_semaphoreSet;
VkResult acquireNextImage(
const Rc<DxvkSemaphore>& wakeSync);