[Mesa-dev] [PATCH 08/16] anv/cmd_buffer: track error scenarios during command buffer recording

Iago Toral itoral at igalia.com
Wed Mar 8 08:36:56 UTC 2017


On Tue, 2017-03-07 at 09:32 -0800, Jason Ekstrand wrote:
> On Mon, Mar 6, 2017 at 11:15 PM, Iago Toral Quiroga <itoral at igalia.co
> m> wrote:
> > The vkCmd*() functions do not report errors, instead, any errors
> > should be
> > reported by the time we call vkEndCommandBuffer(). This means that
> > we
> > need to track things such as "out of host memory" and use that
> > information
> > to avoid executing code that could lead to crashes (due to the fact
> > that the
> > command buffer could not allocate the memory it needs) and report
> > the error
> > when the client calls vkEndCommandBuffer().
> > 
> > Notice this patch is not sufficient to track and report all
> > possible cases
> > of out of host memory situations that can be produced while
> > recording
> > command buffers. Later patches will fix some of the missing cases.
> > Also,
> > some allocations may occur deep into the driver code (for example
> > during
> > batch emissions) and are more difficult to track because at that
> > point we
> > don't even have access to the command buffer object. Dealing with
> > these
> > scenarios would require more changes but for now this is sufficient
> > to make
> > CTS happy.
> Thinking about things a bit more, I don't think that is actually all
> that hard...
>  
> > Fixes:
> > dEQP-VK.api.out_of_host_memory.cmd_begin_render_pass
> > ---
> >  src/intel/vulkan/anv_cmd_buffer.c  |  5 +++++
> >  src/intel/vulkan/anv_private.h     |  7 +++++++
> >  src/intel/vulkan/genX_cmd_buffer.c | 22 +++++++++++++++++++---
> >  3 files changed, 31 insertions(+), 3 deletions(-)
> > 
> > diff --git a/src/intel/vulkan/anv_cmd_buffer.c
> > b/src/intel/vulkan/anv_cmd_buffer.c
> > index cab1dd7..01447b0 100644
> > --- a/src/intel/vulkan/anv_cmd_buffer.c
> > +++ b/src/intel/vulkan/anv_cmd_buffer.c
> > @@ -117,6 +117,8 @@ anv_cmd_state_reset(struct anv_cmd_buffer
> > *cmd_buffer)
> >  {
> >     struct anv_cmd_state *state = &cmd_buffer->state;
> > 
> > +   cmd_buffer->error_status = VK_SUCCESS;
> > +
> >     memset(&state->descriptors, 0, sizeof(state->descriptors));
> >     memset(&state->push_constants, 0, sizeof(state-
> > >push_constants));
> >     memset(state->binding_tables, 0, sizeof(state-
> > >binding_tables));
> > @@ -185,6 +187,8 @@ static VkResult anv_create_cmd_buffer(
> >     if (cmd_buffer == NULL)
> >        return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
> > 
> > +   cmd_buffer->error_status = VK_SUCCESS;
> > +
> >     cmd_buffer->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
> >     cmd_buffer->device = device;
> >     cmd_buffer->pool = pool;
> > @@ -217,6 +221,7 @@ static VkResult anv_create_cmd_buffer(
> >     return VK_SUCCESS;
> > 
> >   fail:
> > +   cmd_buffer->error_status = result;
> >     vk_free(&cmd_buffer->pool->alloc, cmd_buffer);
> > 
> >     return result;
> > diff --git a/src/intel/vulkan/anv_private.h
> > b/src/intel/vulkan/anv_private.h
> > index d3e32bc..46b51a9 100644
> > --- a/src/intel/vulkan/anv_private.h
> > +++ b/src/intel/vulkan/anv_private.h
> > @@ -1377,6 +1377,13 @@ struct anv_cmd_buffer {
> >     VkCommandBufferLevel                         level;
> > 
> >     struct anv_cmd_state                         state;
> > +
> > +   /**
> > +    * Current error status of the command buffer. Used to track
> > inconsistent
> > +    * or incomplete command buffer states that are the consequence
> > of run-time
> > +    * errors such as out of memory scenarios.
> > +    */
> > +   VkResult                                     error_status;
> If we put this in anv_batch, we can easily set the status from "deep"
> parts of the driver. 

Yeah, that seems like a a better approach, I'll give it a try, thanks!

>  Also, I'm not sure the "error" part of the name is needed.  "status"
> should be ok.

That was because having a field called "state" and another called
"status" in the same struct seemed like it could be a bit confusing. In
any case, if we are going to move this to anv_batch that is no longer
an issue.

> One other thing we may want to do is to add a anv_batch_set_error
> helper and only take first error.  That way we can track
> OUT_OF_HOST_MEMORY vs. OUT_OF_DEVICE_MEMORY.

Yes, I was also thinking about doing like this to avoid stomping
previous errors. I'll do it.

> >  };
> > 
> >  VkResult anv_cmd_buffer_init_batch_bo_chain(struct anv_cmd_buffer
> > *cmd_buffer);
> > diff --git a/src/intel/vulkan/genX_cmd_buffer.c
> > b/src/intel/vulkan/genX_cmd_buffer.c
> > index b46a922..cbad144 100644
> > --- a/src/intel/vulkan/genX_cmd_buffer.c
> > +++ b/src/intel/vulkan/genX_cmd_buffer.c
> > @@ -401,8 +401,8 @@ genX(cmd_buffer_setup_attachments)(struct
> > anv_cmd_buffer *cmd_buffer,
> >                                        sizeof(state-
> > >attachments[0]),
> >                                   8,
> > VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
> >     if (state->attachments == NULL) {
> > -      /* FIXME: Propagate VK_ERROR_OUT_OF_HOST_MEMORY to
> > vkEndCommandBuffer */
> > -      return VK_ERROR_OUT_OF_HOST_MEMORY;
> > +      /* Propagate VK_ERROR_OUT_OF_HOST_MEMORY to
> > vkEndCommandBuffer */
> > +      return cmd_buffer->error_status =
> > VK_ERROR_OUT_OF_HOST_MEMORY;
> >     }
> > 
> >     bool need_null_state = false;
> > @@ -615,6 +615,9 @@ genX(EndCommandBuffer)(
> >  {
> >     ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
> > 
> > +   if (cmd_buffer->error_status != VK_SUCCESS)
> > +      return cmd_buffer->error_status;
> > +
> >     /* We want every command buffer to start with the PMA fix in a
> > known state,
> >      * so we disable it at the end of the command buffer.
> >      */
> > @@ -2470,7 +2473,14 @@ void genX(CmdBeginRenderPass)(
> >     cmd_buffer->state.framebuffer = framebuffer;
> >     cmd_buffer->state.pass = pass;
> >     cmd_buffer->state.render_area = pRenderPassBegin->renderArea;
> > -   genX(cmd_buffer_setup_attachments)(cmd_buffer, pass,
> > pRenderPassBegin);
> > +   VkResult result =
> > +      genX(cmd_buffer_setup_attachments)(cmd_buffer, pass,
> > pRenderPassBegin);
> > +
> > +   /* If we failed to setup the attachments we should not try to
> > go further */
> > +   if (result != VK_SUCCESS) {
> > +      assert(cmd_buffer->error_status != VK_SUCCESS);
> > +      return;
> > +   }
> > 
> >     genX(flush_pipeline_select_3d)(cmd_buffer);
> > 
> > @@ -2483,6 +2493,9 @@ void genX(CmdNextSubpass)(
> >  {
> >     ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
> > 
> > +   if (cmd_buffer->error_status != VK_SUCCESS)
> > +      return;
> > +
> >     assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
> > 
> >     anv_cmd_buffer_resolve_subpass(cmd_buffer);
> > @@ -2499,6 +2512,9 @@ void genX(CmdEndRenderPass)(
> >  {
> >     ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
> > 
> > +   if (cmd_buffer->error_status != VK_SUCCESS)
> > +      return;
> > +
> >     anv_cmd_buffer_resolve_subpass(cmd_buffer);
> > 
> >     /* Perform transitions to the final layout after all writes
> > have occurred.
> > --
> > 2.7.4
> > 
> > _______________________________________________
> > mesa-dev mailing list
> > mesa-dev at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/mesa-dev
> > 


More information about the mesa-dev mailing list