[Mesa-dev] [PATCH 6/8] radv: handle sample locations during automatic layout transitions

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Thu Jun 6 18:33:43 UTC 2019


On Thu, Jun 6, 2019, 10:07 AM Samuel Pitoiset <samuel.pitoiset at gmail.com>
wrote:

>
> On 6/6/19 3:41 AM, Bas Nieuwenhuizen wrote:
> > On Wed, Jun 5, 2019 at 12:04 PM Samuel Pitoiset
> > <samuel.pitoiset at gmail.com> wrote:
> >>
> >> On 6/5/19 2:51 AM, Bas Nieuwenhuizen wrote:
> >>> On Thu, May 30, 2019 at 4:02 PM Samuel Pitoiset
> >>> <samuel.pitoiset at gmail.com> wrote:
> >>>>   From the Vulkan spec 1.1.109:
> >>>>
> >>>>      "Some implementations may need to evaluate depth image values
> >>>>       while performing image layout transitions. To accommodate this,
> >>>>       instances of the VkSampleLocationsInfoEXT structure can be
> >>>>       specified for each situation where an explicit or automatic
> >>>>       layout transition has to take place. [...] and
> >>>>       VkRenderPassSampleLocationsBeginInfoEXT can be chained from
> >>>>       VkRenderPassBeginInfo to provide sample locations for layout
> >>>>       transitions performed implicitly by a render pass instance."
> >>>>
> >>>> Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
> >>>> ---
> >>>>    src/amd/vulkan/radv_cmd_buffer.c | 155
> ++++++++++++++++++++++++++++---
> >>>>    src/amd/vulkan/radv_private.h    |   9 ++
> >>>>    2 files changed, 150 insertions(+), 14 deletions(-)
> >>>>
> >>>> diff --git a/src/amd/vulkan/radv_cmd_buffer.c
> b/src/amd/vulkan/radv_cmd_buffer.c
> >>>> index 570acaa0905..81b3f5f9886 100644
> >>>> --- a/src/amd/vulkan/radv_cmd_buffer.c
> >>>> +++ b/src/amd/vulkan/radv_cmd_buffer.c
> >>>> @@ -2645,11 +2645,55 @@ void radv_subpass_barrier(struct
> radv_cmd_buffer *cmd_buffer,
> >>>>                                                                 NULL);
> >>>>    }
> >>>>
> >>>> +static uint32_t
> >>>> +radv_get_subpass_id(struct radv_cmd_buffer *cmd_buffer)
> >>>> +{
> >>>> +       struct radv_cmd_state *state = &cmd_buffer->state;
> >>>> +       uint32_t subpass_id = state->subpass - state->pass->subpasses;
> >>>> +
> >>>> +       /* The id of this subpass shouldn't exceed the number of
> subpasses in
> >>>> +        * this render pass minus 1.
> >>>> +        */
> >>>> +       assert(subpass_id < state->pass->subpass_count);
> >>>> +       return subpass_id;
> >>>> +}
> >>>> +
> >>>> +static struct radv_sample_locations_state *
> >>>> +radv_get_attachment_sample_locations(struct radv_cmd_buffer
> *cmd_buffer,
> >>>> +                                    uint32_t att_idx)
> >>>> +{
> >>>> +       struct radv_cmd_state *state = &cmd_buffer->state;
> >>>> +       uint32_t subpass_id = radv_get_subpass_id(cmd_buffer);
> >>> On the start of the first subpass this may not work as the subpass is
> >>> not set yet?
> >> Yes, this patch needs https://patchwork.freedesktop.org/series/61387/
> >>>> +       struct radv_image_view *view =
> state->framebuffer->attachments[att_idx].attachment;
> >>>> +
> >>>> +       if (view->image->info.samples == 1)
> >>>> +               return NULL;
> >>>> +
> >>>> +       if (state->pass->attachments[att_idx].first_subpass_idx ==
> subpass_id) {
> >>>> +               /* Return the initial sample locations if this is the
> initial
> >>>> +                * layout transition of the given subpass attachemnt.
> >>>> +                */
> >>>> +               if (state->attachments[att_idx].sample_location.count
> > 0)
> >>>> +                       return
> &state->attachments[att_idx].sample_location;
> >>>> +       } else {
> >>>> +               /* Otherwise return the subpass sample locations if
> defined. */
> >>>> +               if (state->subpass_sample_locs) {
> >>>> +                       for (uint32_t i = 0; i <
> state->num_subpass_sample_locs; i++) {
> >>>> +                               if
> (state->subpass_sample_locs[i].subpass_idx == subpass_id)
> >>>> +                                       return
> &state->subpass_sample_locs[i].sample_location;
> > I think there is an off-by-1 here with the subpass patch applied.
> >
> > For the transition from subpass 0 to subpass 1, we should be using the
> > locations from subpass 0, but by setting the subpass before the
> > transitions, the subpass_id is 1.
>
> No?
>
> For the transition from subpass 0 to subpass 1, state->subpass should be
> equal to state->pass->subpasses, so radv_get_subpass_id() returns 0?
>

The 0->1 transitions happen in the begin of subpass 1. If you set the
subpass before image transitions, the subpass_id is going to be 1.

>
> >
> >>>> +                       }
> >>>> +               }
> >>>> +       }
> >>>> +
> >>>> +       return NULL;
> >>>> +}
> >>>> +
> >>>>    static void radv_handle_subpass_image_transition(struct
> radv_cmd_buffer *cmd_buffer,
> >>>>                                                    struct
> radv_subpass_attachment att)
> >>>>    {
> >>>>           unsigned idx = att.attachment;
> >>>>           struct radv_image_view *view =
> cmd_buffer->state.framebuffer->attachments[idx].attachment;
> >>>> +       struct radv_sample_locations_state *sample_locs;
> >>>>           VkImageSubresourceRange range;
> >>>>           range.aspectMask = 0;
> >>>>           range.baseMipLevel = view->base_mip;
> >>>> @@ -2668,10 +2712,15 @@ static void
> radv_handle_subpass_image_transition(struct radv_cmd_buffer *cmd_buf
> >>>>                   range.layerCount =
> util_last_bit(cmd_buffer->state.subpass->view_mask);
> >>>>           }
> >>>>
> >>>> +       /* Get the subpass sample locations for the given attachment,
> if NULL
> >>>> +        * is returned the driver will use the default HW locations.
> >>>> +        */
> >>>> +       sample_locs =
> radv_get_attachment_sample_locations(cmd_buffer, idx);
> >>>> +
> >>>>           radv_handle_image_transition(cmd_buffer,
> >>>>                                        view->image,
> >>>>
> cmd_buffer->state.attachments[idx].current_layout,
> >>>> -                                    att.layout, 0, 0, &range, NULL);
> >>>> +                                    att.layout, 0, 0, &range,
> sample_locs);
> >>>>
> >>>>           cmd_buffer->state.attachments[idx].current_layout =
> att.layout;
> >>>>
> >>>> @@ -2687,6 +2736,89 @@ radv_cmd_buffer_set_subpass(struct
> radv_cmd_buffer *cmd_buffer,
> >>>>           cmd_buffer->state.dirty |= RADV_CMD_DIRTY_FRAMEBUFFER;
> >>>>    }
> >>>>
> >>>> +static VkResult
> >>>> +radv_cmd_state_setup_sample_locations(struct radv_cmd_buffer
> *cmd_buffer,
> >>>> +                                     struct radv_render_pass *pass,
> >>>> +                                     const VkRenderPassBeginInfo
> *info)
> >>>> +{
> >>>> +       const struct VkRenderPassSampleLocationsBeginInfoEXT
> *sample_locs =
> >>>> +               vk_find_struct_const(info->pNext,
> >>>> +
> RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT);
> >>>> +       struct radv_cmd_state *state = &cmd_buffer->state;
> >>>> +       struct radv_framebuffer *framebuffer = state->framebuffer;
> >>>> +
> >>>> +       if (!sample_locs) {
> >>>> +               state->subpass_sample_locs = NULL;
> >>>> +               return VK_SUCCESS;
> >>>> +       }
> >>>> +
> >>>> +       for (uint32_t i = 0; i <
> sample_locs->attachmentInitialSampleLocationsCount; i++) {
> >>>> +               const VkAttachmentSampleLocationsEXT *att_sample_locs
> =
> >>>> +
>  &sample_locs->pAttachmentInitialSampleLocations[i];
> >>>> +               uint32_t att_idx = att_sample_locs->attachmentIndex;
> >>>> +               struct radv_attachment_info *att =
> &framebuffer->attachments[att_idx];
> >>>> +               struct radv_image *image = att->attachment->image;
> >>>> +
> >>>> +
>  assert(vk_format_is_depth_or_stencil(image->vk_format));
> >>>> +
> >>>> +               /* From the Vulkan spec 1.1.108:
> >>>> +                *
> >>>> +                * "If the image referenced by the framebuffer
> attachment at
> >>>> +                *  index attachmentIndex was not created with
> >>>> +                *
> VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT
> >>>> +                *  then the values specified in sampleLocationsInfo
> are
> >>>> +                *  ignored."
> >>>> +                */
> >>>> +               if (!(image->flags &
> VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT))
> >>>> +                       continue;
> >>>> +
> >>>> +               const VkSampleLocationsInfoEXT *sample_locs_info =
> >>>> +                       &att_sample_locs->sampleLocationsInfo;
> >>>> +
> >>>> +               state->attachments[att_idx].sample_location.per_pixel
> =
> >>>> +                       sample_locs_info->sampleLocationsPerPixel;
> >>>> +               state->attachments[att_idx].sample_location.grid_size
> =
> >>>> +                       sample_locs_info->sampleLocationGridSize;
> >>>> +               state->attachments[att_idx].sample_location.count =
> >>>> +                       sample_locs_info->sampleLocationsCount;
> >>>> +
>  typed_memcpy(&state->attachments[att_idx].sample_location.locations[0],
> >>>> +                            sample_locs_info->pSampleLocations,
> >>>> +                            sample_locs_info->sampleLocationsCount);
> >>>> +       }
> >>>> +
> >>>> +       state->subpass_sample_locs =
> vk_alloc(&cmd_buffer->pool->alloc,
> >>>> +
>  sample_locs->postSubpassSampleLocationsCount *
> >>>> +
>  sizeof(state->subpass_sample_locs[0]),
> >>>> +                                             8,
> VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
> >>>> +       if (state->subpass_sample_locs == NULL) {
> >>>> +               cmd_buffer->record_result =
> VK_ERROR_OUT_OF_HOST_MEMORY;
> >>>> +               return cmd_buffer->record_result;
> >>>> +       }
> >>>> +
> >>>> +       state->num_subpass_sample_locs =
> sample_locs->postSubpassSampleLocationsCount;
> >>>> +
> >>>> +       for (uint32_t i = 0; i <
> sample_locs->postSubpassSampleLocationsCount; i++) {
> >>>> +               const VkSubpassSampleLocationsEXT
> *subpass_sample_locs_info =
> >>>> +                       &sample_locs->pPostSubpassSampleLocations[i];
> >>>> +               const VkSampleLocationsInfoEXT *sample_locs_info =
> >>>> +
>  &subpass_sample_locs_info->sampleLocationsInfo;
> >>>> +
> >>>> +               state->subpass_sample_locs[i].subpass_idx =
> >>>> +                       subpass_sample_locs_info->subpassIndex;
> >>>> +
>  state->subpass_sample_locs[i].sample_location.per_pixel =
> >>>> +                       sample_locs_info->sampleLocationsPerPixel;
> >>>> +
>  state->subpass_sample_locs[i].sample_location.grid_size =
> >>>> +                       sample_locs_info->sampleLocationGridSize;
> >>>> +               state->subpass_sample_locs[i].sample_location.count =
> >>>> +                       sample_locs_info->sampleLocationsCount;
> >>>> +
>  typed_memcpy(&state->subpass_sample_locs[i].sample_location.locations[0],
> >>>> +                            sample_locs_info->pSampleLocations,
> >>>> +                            sample_locs_info->sampleLocationsCount);
> >>>> +       }
> >>>> +
> >>>> +       return VK_SUCCESS;
> >>>> +}
> >>>> +
> >>>>    static VkResult
> >>>>    radv_cmd_state_setup_attachments(struct radv_cmd_buffer
> *cmd_buffer,
> >>>>                                    struct radv_render_pass *pass,
> >>>> @@ -2741,6 +2873,7 @@ radv_cmd_state_setup_attachments(struct
> radv_cmd_buffer *cmd_buffer,
> >>>>                   }
> >>>>
> >>>>                   state->attachments[i].current_layout =
> att->initial_layout;
> >>>> +               state->attachments[i].sample_location.count = 0;
> >>>>           }
> >>>>
> >>>>           return VK_SUCCESS;
> >>>> @@ -3171,6 +3304,7 @@ VkResult radv_EndCommandBuffer(
> >>>>           si_cp_dma_wait_for_idle(cmd_buffer);
> >>>>
> >>>>           vk_free(&cmd_buffer->pool->alloc,
> cmd_buffer->state.attachments);
> >>>> +       vk_free(&cmd_buffer->pool->alloc,
> cmd_buffer->state.subpass_sample_locs);
> >>>>
> >>>>           if (!cmd_buffer->device->ws->cs_finalize(cmd_buffer->cs))
> >>>>                   return vk_error(cmd_buffer->device->instance,
> VK_ERROR_OUT_OF_DEVICE_MEMORY);
> >>>> @@ -3669,19 +3803,6 @@ void radv_TrimCommandPool(
> >>>>           }
> >>>>    }
> >>>>
> >>>> -static uint32_t
> >>>> -radv_get_subpass_id(struct radv_cmd_buffer *cmd_buffer)
> >>>> -{
> >>>> -       struct radv_cmd_state *state = &cmd_buffer->state;
> >>>> -       uint32_t subpass_id = state->subpass - state->pass->subpasses;
> >>>> -
> >>>> -       /* The id of this subpass shouldn't exceed the number of
> subpasses in
> >>>> -        * this render pass minus 1.
> >>>> -        */
> >>>> -       assert(subpass_id < state->pass->subpass_count);
> >>>> -       return subpass_id;
> >>>> -}
> >>>> -
> >>>>    static void
> >>>>    radv_cmd_buffer_begin_subpass(struct radv_cmd_buffer *cmd_buffer,
> >>>>                                 uint32_t subpass_id)
> >>>> @@ -3751,6 +3872,10 @@ void radv_CmdBeginRenderPass(
> >>>>           if (result != VK_SUCCESS)
> >>>>                   return;
> >>>>
> >>>> +       result = radv_cmd_state_setup_sample_locations(cmd_buffer,
> pass, pRenderPassBegin);
> >>>> +       if (result != VK_SUCCESS)
> >>>> +               return;
> >>>> +
> >>>>           radv_cmd_buffer_begin_subpass(cmd_buffer, 0);
> >>>>    }
> >>>>
> >>>> @@ -4593,11 +4718,13 @@ void radv_CmdEndRenderPass(
> >>>>           radv_cmd_buffer_end_subpass(cmd_buffer);
> >>>>
> >>>>           vk_free(&cmd_buffer->pool->alloc,
> cmd_buffer->state.attachments);
> >>>> +       vk_free(&cmd_buffer->pool->alloc,
> cmd_buffer->state.subpass_sample_locs);
> >>>>
> >>>>           cmd_buffer->state.pass = NULL;
> >>>>           cmd_buffer->state.subpass = NULL;
> >>>>           cmd_buffer->state.attachments = NULL;
> >>>>           cmd_buffer->state.framebuffer = NULL;
> >>>> +       cmd_buffer->state.subpass_sample_locs = NULL;
> >>>>    }
> >>>>
> >>>>    void radv_CmdEndRenderPass2KHR(
> >>>> diff --git a/src/amd/vulkan/radv_private.h
> b/src/amd/vulkan/radv_private.h
> >>>> index 180f8b976ab..76cc79b387d 100644
> >>>> --- a/src/amd/vulkan/radv_private.h
> >>>> +++ b/src/amd/vulkan/radv_private.h
> >>>> @@ -1024,6 +1024,7 @@ struct radv_attachment_state {
> >>>>           uint32_t                                     cleared_views;
> >>>>           VkClearValue                                 clear_value;
> >>>>           VkImageLayout                                current_layout;
> >>>> +       struct radv_sample_locations_state           sample_location;
> >>>>    };
> >>>>
> >>>>    struct radv_descriptor_state {
> >>>> @@ -1035,6 +1036,11 @@ struct radv_descriptor_state {
> >>>>           uint32_t dynamic_buffers[4 * MAX_DYNAMIC_BUFFERS];
> >>>>    };
> >>>>
> >>>> +struct radv_subpass_sample_locs_state {
> >>>> +       uint32_t subpass_idx;
> >>>> +       struct radv_sample_locations_state sample_location;
> >>>> +};
> >>>> +
> >>>>    struct radv_cmd_state {
> >>>>           /* Vertex descriptors */
> >>>>           uint64_t                                      vb_va;
> >>>> @@ -1057,6 +1063,9 @@ struct radv_cmd_state {
> >>>>           struct radv_streamout_state                  streamout;
> >>>>           VkRect2D                                     render_area;
> >>>>
> >>>> +       uint32_t
>  num_subpass_sample_locs;
> >>>> +       struct radv_subpass_sample_locs_state *
> subpass_sample_locs;
> >>>> +
> >>>>           /* Index buffer */
> >>>>           struct radv_buffer                           *index_buffer;
> >>>>           uint64_t                                     index_offset;
> >>>> --
> >>>> 2.21.0
> >>>>
> >>>> _______________________________________________
> >>>> mesa-dev mailing list
> >>>> mesa-dev at lists.freedesktop.org
> >>>> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20190606/86f7f4c9/attachment-0001.html>


More information about the mesa-dev mailing list