anv: fix multiple creation with internal failure
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Fri, 23 Dec 2016 17:47:40 +0000 (17:47 +0000)
committerLionel Landwerlin <lionel.g.landwerlin@intel.com>
Thu, 5 Jan 2017 21:09:09 +0000 (21:09 +0000)
The specification section 9.4 says :

   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.

Fixes :

   dEQP-VK.api.object_management.alloc_callback_fail_multiple.graphics_pipeline
   dEQP-VK.api.object_management.alloc_callback_fail_multiple.compute_pipeline

v2: C is hard let's go shopping (Lionel)

v3: Remove unnecessary condition in for loops (Lionel)

v4: Document why we return on first failure (Eduardo)
    Move i declaration inside for() (Eduardo)

v5: Move array cleanup out of loop (Jason)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
src/intel/vulkan/genX_pipeline.c

index 845d020..9ff84cd 100644 (file)
@@ -1469,22 +1469,23 @@ VkResult genX(CreateGraphicsPipelines)(
 
    VkResult result = VK_SUCCESS;
 
-   unsigned i = 0;
-   for (; i < count; i++) {
+   unsigned i;
+   for (i = 0; i < count; i++) {
       result = genX(graphics_pipeline_create)(_device,
                                               pipeline_cache,
                                               &pCreateInfos[i],
                                               pAllocator, &pPipelines[i]);
-      if (result != VK_SUCCESS) {
-         for (unsigned j = 0; j < i; j++) {
-            anv_DestroyPipeline(_device, pPipelines[j], pAllocator);
-         }
 
-         return result;
-      }
+      /* Bail out on the first error as it is not obvious what error should be
+       * report upon 2 different failures. */
+      if (result != VK_SUCCESS)
+         break;
    }
 
-   return VK_SUCCESS;
+   for (; i < count; i++)
+      pPipelines[i] = VK_NULL_HANDLE;
+
+   return result;
 }
 
 VkResult genX(CreateComputePipelines)(
@@ -1499,19 +1500,20 @@ VkResult genX(CreateComputePipelines)(
 
    VkResult result = VK_SUCCESS;
 
-   unsigned i = 0;
-   for (; i < count; i++) {
+   unsigned i;
+   for (i = 0; i < count; i++) {
       result = compute_pipeline_create(_device, pipeline_cache,
                                        &pCreateInfos[i],
                                        pAllocator, &pPipelines[i]);
-      if (result != VK_SUCCESS) {
-         for (unsigned j = 0; j < i; j++) {
-            anv_DestroyPipeline(_device, pPipelines[j], pAllocator);
-         }
 
-         return result;
-      }
+      /* Bail out on the first error as it is not obvious what error should be
+       * report upon 2 different failures. */
+      if (result != VK_SUCCESS)
+         break;
    }
 
-   return VK_SUCCESS;
+   for (; i < count; i++)
+      pPipelines[i] = VK_NULL_HANDLE;
+
+   return result;
 }