diff options
author | Damien Leone <dleone@nvidia.com> | 2017-04-14 16:10:14 -0700 |
---|---|---|
committer | Tony-LunarG <tony@lunarg.com> | 2017-05-02 08:56:10 -0600 |
commit | f06ab9cba631acdd64e8009b2290e3656073a499 (patch) | |
tree | 88aa1a10a4255e4c140757e9ca7bb3c786d4d1f6 | |
parent | ca472cf81919f5b020ccba721d2b7b56c39301aa (diff) |
cube: Throttle rendering rather than presentation
It is currently impossible to reliably throttle presentation per the
Vulkan spec.
The previous code was relying on fences returned by
vkAcquireNextImageKHR() to throttle. The only information this fence
holds is whether it is possible to render to that image since the *last
time* it was presented, which could have happened several frames ago.
Instead, we can throttle the rendering by passing a fence to
vkQueueSubmit().
The previous code (only the cube.c version) was using a fence there to
synchronize a vkMapMemory() in demo_update_data_buffer(), which doesn't
seem necessary.
Before this commit, we were effectively throttling to the number of
frames in the swapchain rather than on FRAME_LAG.
In the FIFO present mode, this could schedule too much work in the
presentation channel (since we have to account for VBLANK events)
and thus causing undesired side effects, such as stutters when trying
to move the cube window on a desktop, which is I assume why the
throttle code was added in the first place.
-rw-r--r-- | demos/cube.c | 23 | ||||
-rw-r--r-- | demos/cube.cpp | 8 |
2 files changed, 7 insertions, 24 deletions
diff --git a/demos/cube.c b/demos/cube.c index 10ec60d4..e2e40c3d 100644 --- a/demos/cube.c +++ b/demos/cube.c @@ -309,7 +309,6 @@ typedef struct { VkDeviceMemory uniform_memory; VkFramebuffer framebuffer; VkDescriptorSet descriptor_set; - VkFence fence; } SwapchainImageResources; struct demo { @@ -809,9 +808,6 @@ void demo_update_data_buffer(struct demo *demo) { (float)degreesToRadians(demo->spin_angle)); mat4x4_mul(MVP, VP, demo->model_matrix); - vkWaitForFences(demo->device, 1, &demo->swapchain_image_resources[demo->current_buffer].fence, - VK_TRUE, UINT64_MAX); - err = vkMapMemory(demo->device, demo->swapchain_image_resources[demo->current_buffer].uniform_memory, 0, VK_WHOLE_SIZE, 0, (void **)&pData); @@ -957,15 +953,14 @@ void DemoUpdateTargetIPD(struct demo *demo) { static void demo_draw(struct demo *demo) { VkResult U_ASSERT_ONLY err; - // Ensure no more than FRAME_LAG presentations are outstanding + // Ensure no more than FRAME_LAG renderings are outstanding vkWaitForFences(demo->device, 1, &demo->fences[demo->frame_index], VK_TRUE, UINT64_MAX); vkResetFences(demo->device, 1, &demo->fences[demo->frame_index]); // Get the index of the next available swapchain image: err = demo->fpAcquireNextImageKHR(demo->device, demo->swapchain, UINT64_MAX, demo->image_acquired_semaphores[demo->frame_index], - demo->fences[demo->frame_index], - &demo->current_buffer); + VK_NULL_HANDLE, &demo->current_buffer); demo_update_data_buffer(demo); @@ -1012,9 +1007,8 @@ static void demo_draw(struct demo *demo) { submit_info.pCommandBuffers = &demo->swapchain_image_resources[demo->current_buffer].cmd; submit_info.signalSemaphoreCount = 1; submit_info.pSignalSemaphores = &demo->draw_complete_semaphores[demo->frame_index]; - vkResetFences(demo->device, 1, &demo->swapchain_image_resources[demo->current_buffer].fence); err = vkQueueSubmit(demo->graphics_queue, 1, &submit_info, - demo->swapchain_image_resources[demo->current_buffer].fence); + demo->fences[demo->frame_index]); assert(!err); if (demo->separate_present_queue) { @@ -1313,12 +1307,6 @@ static void demo_prepare_buffers(struct demo *demo) { demo->swapchainImageCount); assert(demo->swapchain_image_resources); - VkFenceCreateInfo fence_ci = { - .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - .pNext = NULL, - .flags = VK_FENCE_CREATE_SIGNALED_BIT - }; - for (i = 0; i < demo->swapchainImageCount; i++) { VkImageViewCreateInfo color_image_view = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, @@ -1347,9 +1335,6 @@ static void demo_prepare_buffers(struct demo *demo) { err = vkCreateImageView(demo->device, &color_image_view, NULL, &demo->swapchain_image_resources[i].view); assert(!err); - - err = vkCreateFence(demo->device, &fence_ci, NULL, &demo->swapchain_image_resources[i].fence); - assert(!err); } if (demo->VK_GOOGLE_display_timing_enabled) { @@ -2399,7 +2384,6 @@ static void demo_cleanup(struct demo *demo) { &demo->swapchain_image_resources[i].cmd); vkDestroyBuffer(demo->device, demo->swapchain_image_resources[i].uniform_buffer, NULL); vkFreeMemory(demo->device, demo->swapchain_image_resources[i].uniform_memory, NULL); - vkDestroyFence(demo->device, demo->swapchain_image_resources[i].fence, NULL); } free(demo->swapchain_image_resources); free(demo->queue_props); @@ -2476,7 +2460,6 @@ static void demo_resize(struct demo *demo) { &demo->swapchain_image_resources[i].cmd); vkDestroyBuffer(demo->device, demo->swapchain_image_resources[i].uniform_buffer, NULL); vkFreeMemory(demo->device, demo->swapchain_image_resources[i].uniform_memory, NULL); - vkDestroyFence(demo->device, demo->swapchain_image_resources[i].fence, NULL); } vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL); if (demo->separate_present_queue) { diff --git a/demos/cube.cpp b/demos/cube.cpp index 588d1cd9..4470e8f3 100644 --- a/demos/cube.cpp +++ b/demos/cube.cpp @@ -434,13 +434,13 @@ struct Demo { } void draw() { - // Ensure no more than FRAME_LAG presentations are outstanding + // Ensure no more than FRAME_LAG renderings are outstanding device.waitForFences(1, &fences[frame_index], VK_TRUE, UINT64_MAX); device.resetFences(1, &fences[frame_index]); // Get the index of the next available swapchain image: - auto result = device.acquireNextImageKHR(swapchain, UINT64_MAX, image_acquired_semaphores[frame_index], fences[frame_index], - ¤t_buffer); + auto result = device.acquireNextImageKHR(swapchain, UINT64_MAX, image_acquired_semaphores[frame_index], + vk::Fence(), ¤t_buffer); if (result == vk::Result::eErrorOutOfDateKHR) { // swapchain is out of date (e.g. the window was resized) and // must be recreated: @@ -471,7 +471,7 @@ struct Demo { .setSignalSemaphoreCount(1) .setPSignalSemaphores(&draw_complete_semaphores[frame_index]); - result = graphics_queue.submit(1, &submit_info, vk::Fence()); + result = graphics_queue.submit(1, &submit_info, fences[frame_index]); VERIFY(result == vk::Result::eSuccess); if (separate_present_queue) { |