summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2016-03-10 18:35:00 -0800
committerJason Ekstrand <[email protected]>2016-03-11 11:31:13 -0800
commit41a147904a95ba699358e8209e91d535f853ba61 (patch)
tree7ebccaa3233a0ae2c615d74e4cc85c7b5ac5d9f6
parent132f079a8cbaeab442a7ea8b0f02b9f07dfdd310 (diff)
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.
-rw-r--r--src/intel/vulkan/anv_wsi.c38
-rw-r--r--src/intel/vulkan/anv_wsi.h4
2 files changed, 42 insertions, 0 deletions
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,