[Mesa-dev] [PATCH vulkan] anv/pipeline: Try to create all pipelines

Neil Roberts bpeeluk at yahoo.co.uk
Fri Feb 26 20:37:34 UTC 2016


According to the Vulkan 1.0 spec section 9.4:

“When an application attempts to create many pipelines in a single
 command, it is possible that some subset may fail creation. In that
 case, the corresponding entries in the pPipelines output array will
 be filled with VK_NULL_HANDLE values. If any pipeline fails creation
 (for example, due to out of memory errors), the vkCreate*Pipelines
 commands will return an error code. The implementation will attempt
 to create all pipelines, and only return VK_NULL_HANDLE values for
 those that actually failed.”

Previously anv_Create{Graphics,Compute}Pipelines would destroy any
previous pipelines that it created. The problem with this is that if
the application is expecting the driver to behave like the spec then
it may try to free any pipelines that were successfully created by
iterating through the results array. If any of them succeeded then the
pointer will be a stale pointer and the application would probably
crash.
---
 src/intel/vulkan/anv_pipeline.c | 52 +++++++++++++++++++++++------------------
 1 file changed, 29 insertions(+), 23 deletions(-)

diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c
index 1173b4f..d3a01df 100644
--- a/src/intel/vulkan/anv_pipeline.c
+++ b/src/intel/vulkan/anv_pipeline.c
@@ -1231,24 +1231,28 @@ VkResult anv_CreateGraphicsPipelines(
     const VkAllocationCallbacks*                pAllocator,
     VkPipeline*                                 pPipelines)
 {
-   VkResult result = VK_SUCCESS;
+   VkResult this_result;
+   VkResult overall_result = VK_SUCCESS;
 
    unsigned i = 0;
    for (; i < count; i++) {
-      result = anv_graphics_pipeline_create(_device,
-                                            pipelineCache,
-                                            &pCreateInfos[i],
-                                            NULL, pAllocator, &pPipelines[i]);
-      if (result != VK_SUCCESS) {
-         for (unsigned j = 0; j < i; j++) {
-            anv_DestroyPipeline(_device, pPipelines[j], pAllocator);
-         }
-
-         return result;
+      this_result = anv_graphics_pipeline_create(_device,
+                                                 pipelineCache,
+                                                 &pCreateInfos[i],
+                                                 NULL,
+                                                 pAllocator,
+                                                 &pPipelines[i]);
+      if (this_result != VK_SUCCESS) {
+         /* According to the spec this should try to create all pipelines and
+          * if any fail then it will set the corresponding pipeline handle to
+          * NULL.
+          */
+         pPipelines[i] = VK_NULL_HANDLE;
+         overall_result = this_result;
       }
    }
 
-   return VK_SUCCESS;
+   return overall_result;
 }
 
 static VkResult anv_compute_pipeline_create(
@@ -1287,21 +1291,23 @@ VkResult anv_CreateComputePipelines(
     const VkAllocationCallbacks*                pAllocator,
     VkPipeline*                                 pPipelines)
 {
-   VkResult result = VK_SUCCESS;
+   VkResult this_result;
+   VkResult overall_result = VK_SUCCESS;
 
    unsigned i = 0;
    for (; i < count; i++) {
-      result = anv_compute_pipeline_create(_device, pipelineCache,
-                                           &pCreateInfos[i],
-                                           pAllocator, &pPipelines[i]);
-      if (result != VK_SUCCESS) {
-         for (unsigned j = 0; j < i; j++) {
-            anv_DestroyPipeline(_device, pPipelines[j], pAllocator);
-         }
-
-         return result;
+      this_result = anv_compute_pipeline_create(_device, pipelineCache,
+                                                &pCreateInfos[i],
+                                                pAllocator, &pPipelines[i]);
+      if (this_result != VK_SUCCESS) {
+         /* According to the spec this should try to create all pipelines and
+          * if any fail then it will set the corresponding pipeline handle to
+          * NULL.
+          */
+         pPipelines[i] = VK_NULL_HANDLE;
+         overall_result = this_result;
       }
    }
 
-   return VK_SUCCESS;
+   return overall_result;
 }
-- 
2.5.0



More information about the mesa-dev mailing list