From: Iago Toral Quiroga Date: Thu, 12 Mar 2020 10:59:04 +0000 (+0100) Subject: v3dv: handle the case where we fail to allocate a new job gracefully X-Git-Tag: upstream/21.0.0~4077 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5cfc3b5cc965a64c07e69833f85d44e60d6f3a6e;p=platform%2Fupstream%2Fmesa.git v3dv: handle the case where we fail to allocate a new job gracefully There are a handful of tests that simulate 'out of memory' situations during swapchain image creation, and these can lead to failed job allocations when the driver is running on the prime blit path, as that involves creating a command buffer. The tests expect us to handle this scenario gracefully and return an appropriate OOM error as a result. This make sure we don't try to dereference a job if we failed to allocate it so we don't crash and can return the OOM error gracefully in the process. Fixes: dEQP-VK.wsi.xlib.swapchain.simulate_oom.* Part-of: --- diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index 8c0d68a..5ac8ab2 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -505,7 +505,14 @@ v3dv_cmd_buffer_start_job(struct v3dv_cmd_buffer *cmd_buffer, struct v3dv_job *job = vk_zalloc(&cmd_buffer->device->alloc, sizeof(struct v3dv_job), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - assert(job); + + cmd_buffer->state.job = job; + + if (!job) { + fprintf(stderr, "Error: failed to allocate CPU memory for job\n"); + cmd_buffer->state.oom = true; + return NULL; + } job->cmd_buffer = cmd_buffer; @@ -532,8 +539,6 @@ v3dv_cmd_buffer_start_job(struct v3dv_cmd_buffer *cmd_buffer, if (cmd_buffer->state.pass) job->first_subpass = subpass_idx; - cmd_buffer->state.job = job; - return job; } @@ -1486,6 +1491,8 @@ subpass_start(struct v3dv_cmd_buffer *cmd_buffer, uint32_t subpass_idx) * the new job. */ struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, subpass_idx); + if (!job) + return; state->subpass_idx = subpass_idx; @@ -1551,6 +1558,9 @@ v3dv_EndCommandBuffer(VkCommandBuffer commandBuffer) { V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer); + if (cmd_buffer->state.oom) + return VK_ERROR_OUT_OF_HOST_MEMORY; + cmd_buffer->status = V3DV_CMD_BUFFER_STATUS_EXECUTABLE; struct v3dv_job *job = cmd_buffer->state.job; diff --git a/src/broadcom/vulkan/v3dv_meta_copy.c b/src/broadcom/vulkan/v3dv_meta_copy.c index 37988d1..fdc6400 100644 --- a/src/broadcom/vulkan/v3dv_meta_copy.c +++ b/src/broadcom/vulkan/v3dv_meta_copy.c @@ -644,6 +644,8 @@ copy_image_to_buffer_tlb(struct v3dv_cmd_buffer *cmd_buffer, assert(num_layers > 0); struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); + if (!job) + return; v3dv_cmd_buffer_start_frame(cmd_buffer, region->imageExtent.width, @@ -785,6 +787,8 @@ copy_image_tlb(struct v3dv_cmd_buffer *cmd_buffer, assert(num_layers > 0); struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); + if (!job) + return; v3dv_cmd_buffer_start_frame(cmd_buffer, region->extent.width, @@ -928,6 +932,8 @@ clear_image_tlb(struct v3dv_cmd_buffer *cmd_buffer, uint32_t height = u_minify(image->extent.height, level); struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); + if (!job) + return; v3dv_cmd_buffer_start_frame(cmd_buffer, width, height, 1, 1, internal_bpp); @@ -1131,6 +1137,8 @@ copy_buffer(struct v3dv_cmd_buffer *cmd_buffer, uint32_t dst_offset = region->dstOffset; while (num_items > 0) { job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); + if (!job) + return NULL; uint32_t width, height; framebuffer_size_for_pixel_count(num_items, &width, &height); @@ -1209,6 +1217,8 @@ v3dv_CmdUpdateBuffer(VkCommandBuffer commandBuffer, }; struct v3dv_job *copy_job = copy_buffer(cmd_buffer, dst_buffer->mem->bo, src_bo, ®ion); + if (!copy_job) + return; /* Make sure we add the BO to the list of extra BOs so it is not leaked. * If the copy job was split into multiple jobs, we just bind it to the last @@ -1299,6 +1309,8 @@ fill_buffer(struct v3dv_cmd_buffer *cmd_buffer, while (num_items > 0) { struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); + if (!job) + return; uint32_t width, height; framebuffer_size_for_pixel_count(num_items, &width, &height); @@ -1487,6 +1499,9 @@ copy_buffer_to_image_tlb(struct v3dv_cmd_buffer *cmd_buffer, assert(num_layers > 0); struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); + if (!job) + return; + v3dv_cmd_buffer_start_frame(cmd_buffer, region->imageExtent.width, region->imageExtent.height, diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index 46413a7..ec786d7 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -612,6 +612,9 @@ struct v3dv_cmd_buffer_state { struct v3dv_vertex_binding vertex_bindings[MAX_VBS]; uint8_t index_size; + + /* Used to flag OOM conditions during command buffer recording */ + bool oom; }; struct v3dv_descriptor {