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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev