[Vulkan] Create per-swapchain-image present semaphores
Fixes vulkan validation issues.
This commit is contained in:
@@ -75,9 +75,6 @@ VulkanPresenter::PaintContext::Submission::~Submission() {
|
||||
dfn.vkDestroyCommandPool(device, draw_command_pool_, nullptr);
|
||||
}
|
||||
|
||||
if (present_semaphore_ != VK_NULL_HANDLE) {
|
||||
dfn.vkDestroySemaphore(device, present_semaphore_, nullptr);
|
||||
}
|
||||
if (acquire_semaphore_ != VK_NULL_HANDLE) {
|
||||
dfn.vkDestroySemaphore(device, acquire_semaphore_, nullptr);
|
||||
}
|
||||
@@ -98,13 +95,6 @@ bool VulkanPresenter::PaintContext::Submission::Initialize() {
|
||||
"semaphore");
|
||||
return false;
|
||||
}
|
||||
if (dfn.vkCreateSemaphore(device, &semaphore_create_info, nullptr,
|
||||
&present_semaphore_) != VK_SUCCESS) {
|
||||
XELOGE(
|
||||
"VulkanPresenter: Failed to create a swapchain image presentation "
|
||||
"semaphore");
|
||||
return false;
|
||||
}
|
||||
|
||||
VkCommandPoolCreateInfo command_pool_create_info;
|
||||
command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
@@ -816,6 +806,29 @@ VulkanPresenter::ConnectOrReconnectPaintingToSurfaceFromUIThread(
|
||||
paint_context_.swapchain_framebuffers.emplace_back(image_view, framebuffer);
|
||||
}
|
||||
|
||||
// Create per-swapchain-image present semaphores to avoid
|
||||
// VUID-vkQueueSubmit-pSignalSemaphores-00067 (semaphore reuse before the
|
||||
// previous present completes).
|
||||
paint_context_.swapchain_image_present_semaphores.reserve(
|
||||
paint_context_.swapchain_images.size());
|
||||
VkSemaphoreCreateInfo present_semaphore_create_info;
|
||||
present_semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
present_semaphore_create_info.pNext = nullptr;
|
||||
present_semaphore_create_info.flags = 0;
|
||||
for (size_t i = 0; i < paint_context_.swapchain_images.size(); ++i) {
|
||||
VkSemaphore present_semaphore;
|
||||
if (dfn.vkCreateSemaphore(device, &present_semaphore_create_info, nullptr,
|
||||
&present_semaphore) != VK_SUCCESS) {
|
||||
XELOGE(
|
||||
"VulkanPresenter: Failed to create a per-swapchain-image present "
|
||||
"semaphore");
|
||||
paint_context_.DestroySwapchainAndVulkanSurface();
|
||||
return SurfacePaintConnectResult::kFailure;
|
||||
}
|
||||
paint_context_.swapchain_image_present_semaphores.push_back(
|
||||
present_semaphore);
|
||||
}
|
||||
|
||||
is_vsync_implicit_out = paint_context_.swapchain_is_fifo;
|
||||
return SurfacePaintConnectResult::kSuccess;
|
||||
}
|
||||
@@ -1242,6 +1255,13 @@ VkSwapchainKHR VulkanPresenter::PaintContext::CreateSwapchainForVulkanSurface(
|
||||
VkSwapchainKHR VulkanPresenter::PaintContext::PrepareForSwapchainRetirement() {
|
||||
if (swapchain != VK_NULL_HANDLE) {
|
||||
completion_timeline.AwaitAllSubmissions();
|
||||
// Also wait for the presentation queue since vkQueuePresentKHR doesn't
|
||||
// signal a fence, and the present semaphores may still be in use.
|
||||
if (present_queue_family != UINT32_MAX) {
|
||||
const VulkanDevice::Queue::Acquisition queue_acquisition =
|
||||
vulkan_device->AcquireQueue(present_queue_family, 0);
|
||||
vulkan_device->functions().vkQueueWaitIdle(queue_acquisition.queue());
|
||||
}
|
||||
}
|
||||
const VulkanDevice::Functions& dfn = vulkan_device->functions();
|
||||
const VkDevice device = vulkan_device->device();
|
||||
@@ -1250,6 +1270,10 @@ VkSwapchainKHR VulkanPresenter::PaintContext::PrepareForSwapchainRetirement() {
|
||||
dfn.vkDestroyImageView(device, framebuffer.image_view, nullptr);
|
||||
}
|
||||
swapchain_framebuffers.clear();
|
||||
for (VkSemaphore present_semaphore : swapchain_image_present_semaphores) {
|
||||
dfn.vkDestroySemaphore(device, present_semaphore, nullptr);
|
||||
}
|
||||
swapchain_image_present_semaphores.clear();
|
||||
swapchain_images.clear();
|
||||
swapchain_extent.width = 0;
|
||||
swapchain_extent.height = 0;
|
||||
@@ -1386,6 +1410,8 @@ Presenter::PaintResult VulkanPresenter::PaintAndPresentImpl(
|
||||
// safe to return early from this function in case of an error.
|
||||
|
||||
VkSemaphore acquire_semaphore = paint_submission.acquire_semaphore();
|
||||
|
||||
|
||||
uint32_t swapchain_image_index;
|
||||
VkResult acquire_result = dfn.vkAcquireNextImageKHR(
|
||||
device, paint_context_.swapchain, UINT64_MAX, acquire_semaphore,
|
||||
@@ -1997,7 +2023,8 @@ Presenter::PaintResult VulkanPresenter::PaintAndPresentImpl(
|
||||
paint_context_.ui_setup_command_buffer_current_index = SIZE_MAX;
|
||||
}
|
||||
command_buffers[command_buffer_count++] = draw_command_buffer;
|
||||
VkSemaphore present_semaphore = paint_submission.present_semaphore();
|
||||
VkSemaphore present_semaphore =
|
||||
paint_context_.swapchain_image_present_semaphores[swapchain_image_index];
|
||||
VkSubmitInfo submit_info;
|
||||
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submit_info.pNext = nullptr;
|
||||
|
||||
@@ -297,7 +297,6 @@ class VulkanPresenter final : public Presenter {
|
||||
~Submission();
|
||||
|
||||
VkSemaphore acquire_semaphore() const { return acquire_semaphore_; }
|
||||
VkSemaphore present_semaphore() const { return present_semaphore_; }
|
||||
VkCommandPool draw_command_pool() const { return draw_command_pool_; }
|
||||
VkCommandBuffer draw_command_buffer() const {
|
||||
return draw_command_buffer_;
|
||||
@@ -310,7 +309,6 @@ class VulkanPresenter final : public Presenter {
|
||||
|
||||
const VulkanDevice* vulkan_device_;
|
||||
VkSemaphore acquire_semaphore_ = VK_NULL_HANDLE;
|
||||
VkSemaphore present_semaphore_ = VK_NULL_HANDLE;
|
||||
VkCommandPool draw_command_pool_ = VK_NULL_HANDLE;
|
||||
VkCommandBuffer draw_command_buffer_ = VK_NULL_HANDLE;
|
||||
};
|
||||
@@ -442,6 +440,7 @@ class VulkanPresenter final : public Presenter {
|
||||
bool swapchain_is_fifo = false;
|
||||
std::vector<VkImage> swapchain_images;
|
||||
std::vector<SwapchainFramebuffer> swapchain_framebuffers;
|
||||
std::vector<VkSemaphore> swapchain_image_present_semaphores;
|
||||
};
|
||||
|
||||
explicit VulkanPresenter(HostGpuLossCallback host_gpu_loss_callback,
|
||||
|
||||
Reference in New Issue
Block a user