From 41a147904a95ba699358e8209e91d535f853ba61 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Thu, 10 Mar 2016 18:35:00 -0800 Subject: [PATCH] anv/wsi: Throttle rendering to no more than 2 frames ahead Right now, Vulkan apps can pretty easily DOS the GPU by simply submitting a lot of batches. This commit makes us wait until the rendering for earlier frames is comlete before continuing. By waiting 2 frames out, we can still keep the pipe reasonably full but without taking the entire system down. This is similar to what the GL driver does today. --- src/intel/vulkan/anv_wsi.c | 38 ++++++++++++++++++++++++++++++++++++++ src/intel/vulkan/anv_wsi.h | 4 ++++ 2 files changed, 42 insertions(+) diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c index c5911a3635b..c2938f3836f 100644 --- a/src/intel/vulkan/anv_wsi.c +++ b/src/intel/vulkan/anv_wsi.c @@ -132,6 +132,14 @@ VkResult anv_CreateSwapchainKHR( if (result != VK_SUCCESS) return result; + if (pAllocator) + swapchain->alloc = *pAllocator; + else + swapchain->alloc = device->alloc; + + for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++) + swapchain->fences[i] = VK_NULL_HANDLE; + *pSwapchain = anv_swapchain_to_handle(swapchain); return VK_SUCCESS; @@ -144,6 +152,11 @@ void anv_DestroySwapchainKHR( { ANV_FROM_HANDLE(anv_swapchain, swapchain, _swapchain); + for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++) { + if (swapchain->fences[i] != VK_NULL_HANDLE) + anv_DestroyFence(device, swapchain->fences[i], pAllocator); + } + swapchain->destroy(swapchain, pAllocator); } @@ -185,11 +198,36 @@ VkResult anv_QueuePresentKHR( assert(swapchain->device == queue->device); + if (swapchain->fences[0] == VK_NULL_HANDLE) { + result = anv_CreateFence(anv_device_to_handle(queue->device), + &(VkFenceCreateInfo) { + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + .flags = 0, + }, &swapchain->alloc, &swapchain->fences[0]); + if (result != VK_SUCCESS) + return result; + } else { + anv_ResetFences(anv_device_to_handle(queue->device), + 1, &swapchain->fences[0]); + } + + anv_QueueSubmit(_queue, 0, NULL, swapchain->fences[0]); + result = swapchain->queue_present(swapchain, queue, pPresentInfo->pImageIndices[i]); /* TODO: What if one of them returns OUT_OF_DATE? */ if (result != VK_SUCCESS) return result; + + VkFence last = swapchain->fences[2]; + swapchain->fences[2] = swapchain->fences[1]; + swapchain->fences[1] = swapchain->fences[0]; + swapchain->fences[0] = last; + + if (last != VK_NULL_HANDLE) { + anv_WaitForFences(anv_device_to_handle(queue->device), + 1, &last, true, 1); + } } return VK_SUCCESS; diff --git a/src/intel/vulkan/anv_wsi.h b/src/intel/vulkan/anv_wsi.h index 6e9ff9b8447..bf17f033173 100644 --- a/src/intel/vulkan/anv_wsi.h +++ b/src/intel/vulkan/anv_wsi.h @@ -53,6 +53,10 @@ struct anv_wsi_interface { struct anv_swapchain { struct anv_device *device; + VkAllocationCallbacks alloc; + + VkFence fences[3]; + VkResult (*destroy)(struct anv_swapchain *swapchain, const VkAllocationCallbacks *pAllocator); VkResult (*get_images)(struct anv_swapchain *swapchain, -- 2.30.2