<div dir="auto"><div><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jun 6, 2019, 10:07 AM Samuel Pitoiset <<a href="mailto:samuel.pitoiset@gmail.com">samuel.pitoiset@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
On 6/6/19 3:41 AM, Bas Nieuwenhuizen wrote:<br>
> On Wed, Jun 5, 2019 at 12:04 PM Samuel Pitoiset<br>
> <<a href="mailto:samuel.pitoiset@gmail.com" target="_blank" rel="noreferrer">samuel.pitoiset@gmail.com</a>> wrote:<br>
>><br>
>> On 6/5/19 2:51 AM, Bas Nieuwenhuizen wrote:<br>
>>> On Thu, May 30, 2019 at 4:02 PM Samuel Pitoiset<br>
>>> <<a href="mailto:samuel.pitoiset@gmail.com" target="_blank" rel="noreferrer">samuel.pitoiset@gmail.com</a>> wrote:<br>
>>>>   From the Vulkan spec 1.1.109:<br>
>>>><br>
>>>>      "Some implementations may need to evaluate depth image values<br>
>>>>       while performing image layout transitions. To accommodate this,<br>
>>>>       instances of the VkSampleLocationsInfoEXT structure can be<br>
>>>>       specified for each situation where an explicit or automatic<br>
>>>>       layout transition has to take place. [...] and<br>
>>>>       VkRenderPassSampleLocationsBeginInfoEXT can be chained from<br>
>>>>       VkRenderPassBeginInfo to provide sample locations for layout<br>
>>>>       transitions performed implicitly by a render pass instance."<br>
>>>><br>
>>>> Signed-off-by: Samuel Pitoiset <<a href="mailto:samuel.pitoiset@gmail.com" target="_blank" rel="noreferrer">samuel.pitoiset@gmail.com</a>><br>
>>>> ---<br>
>>>>    src/amd/vulkan/radv_cmd_buffer.c | 155 ++++++++++++++++++++++++++++---<br>
>>>>    src/amd/vulkan/radv_private.h    |   9 ++<br>
>>>>    2 files changed, 150 insertions(+), 14 deletions(-)<br>
>>>><br>
>>>> diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c<br>
>>>> index 570acaa0905..81b3f5f9886 100644<br>
>>>> --- a/src/amd/vulkan/radv_cmd_buffer.c<br>
>>>> +++ b/src/amd/vulkan/radv_cmd_buffer.c<br>
>>>> @@ -2645,11 +2645,55 @@ void radv_subpass_barrier(struct radv_cmd_buffer *cmd_buffer,<br>
>>>>                                                                 NULL);<br>
>>>>    }<br>
>>>><br>
>>>> +static uint32_t<br>
>>>> +radv_get_subpass_id(struct radv_cmd_buffer *cmd_buffer)<br>
>>>> +{<br>
>>>> +       struct radv_cmd_state *state = &cmd_buffer->state;<br>
>>>> +       uint32_t subpass_id = state->subpass - state->pass->subpasses;<br>
>>>> +<br>
>>>> +       /* The id of this subpass shouldn't exceed the number of subpasses in<br>
>>>> +        * this render pass minus 1.<br>
>>>> +        */<br>
>>>> +       assert(subpass_id < state->pass->subpass_count);<br>
>>>> +       return subpass_id;<br>
>>>> +}<br>
>>>> +<br>
>>>> +static struct radv_sample_locations_state *<br>
>>>> +radv_get_attachment_sample_locations(struct radv_cmd_buffer *cmd_buffer,<br>
>>>> +                                    uint32_t att_idx)<br>
>>>> +{<br>
>>>> +       struct radv_cmd_state *state = &cmd_buffer->state;<br>
>>>> +       uint32_t subpass_id = radv_get_subpass_id(cmd_buffer);<br>
>>> On the start of the first subpass this may not work as the subpass is<br>
>>> not set yet?<br>
>> Yes, this patch needs <a href="https://patchwork.freedesktop.org/series/61387/" rel="noreferrer noreferrer" target="_blank">https://patchwork.freedesktop.org/series/61387/</a><br>
>>>> +       struct radv_image_view *view = state->framebuffer->attachments[att_idx].attachment;<br>
>>>> +<br>
>>>> +       if (view->image->info.samples == 1)<br>
>>>> +               return NULL;<br>
>>>> +<br>
>>>> +       if (state->pass->attachments[att_idx].first_subpass_idx == subpass_id) {<br>
>>>> +               /* Return the initial sample locations if this is the initial<br>
>>>> +                * layout transition of the given subpass attachemnt.<br>
>>>> +                */<br>
>>>> +               if (state->attachments[att_idx].sample_location.count > 0)<br>
>>>> +                       return &state->attachments[att_idx].sample_location;<br>
>>>> +       } else {<br>
>>>> +               /* Otherwise return the subpass sample locations if defined. */<br>
>>>> +               if (state->subpass_sample_locs) {<br>
>>>> +                       for (uint32_t i = 0; i < state->num_subpass_sample_locs; i++) {<br>
>>>> +                               if (state->subpass_sample_locs[i].subpass_idx == subpass_id)<br>
>>>> +                                       return &state->subpass_sample_locs[i].sample_location;<br>
> I think there is an off-by-1 here with the subpass patch applied.<br>
><br>
> For the transition from subpass 0 to subpass 1, we should be using the<br>
> locations from subpass 0, but by setting the subpass before the<br>
> transitions, the subpass_id is 1.<br>
<br>
No?<br>
<br>
For the transition from subpass 0 to subpass 1, state->subpass should be <br>
equal to state->pass->subpasses, so radv_get_subpass_id() returns 0?<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
><br>
>>>> +                       }<br>
>>>> +               }<br>
>>>> +       }<br>
>>>> +<br>
>>>> +       return NULL;<br>
>>>> +}<br>
>>>> +<br>
>>>>    static void radv_handle_subpass_image_transition(struct radv_cmd_buffer *cmd_buffer,<br>
>>>>                                                    struct radv_subpass_attachment att)<br>
>>>>    {<br>
>>>>           unsigned idx = att.attachment;<br>
>>>>           struct radv_image_view *view = cmd_buffer->state.framebuffer->attachments[idx].attachment;<br>
>>>> +       struct radv_sample_locations_state *sample_locs;<br>
>>>>           VkImageSubresourceRange range;<br>
>>>>           range.aspectMask = 0;<br>
>>>>           range.baseMipLevel = view->base_mip;<br>
>>>> @@ -2668,10 +2712,15 @@ static void radv_handle_subpass_image_transition(struct radv_cmd_buffer *cmd_buf<br>
>>>>                   range.layerCount = util_last_bit(cmd_buffer->state.subpass->view_mask);<br>
>>>>           }<br>
>>>><br>
>>>> +       /* Get the subpass sample locations for the given attachment, if NULL<br>
>>>> +        * is returned the driver will use the default HW locations.<br>
>>>> +        */<br>
>>>> +       sample_locs = radv_get_attachment_sample_locations(cmd_buffer, idx);<br>
>>>> +<br>
>>>>           radv_handle_image_transition(cmd_buffer,<br>
>>>>                                        view->image,<br>
>>>>                                        cmd_buffer->state.attachments[idx].current_layout,<br>
>>>> -                                    att.layout, 0, 0, &range, NULL);<br>
>>>> +                                    att.layout, 0, 0, &range, sample_locs);<br>
>>>><br>
>>>>           cmd_buffer->state.attachments[idx].current_layout = att.layout;<br>
>>>><br>
>>>> @@ -2687,6 +2736,89 @@ radv_cmd_buffer_set_subpass(struct radv_cmd_buffer *cmd_buffer,<br>
>>>>           cmd_buffer->state.dirty |= RADV_CMD_DIRTY_FRAMEBUFFER;<br>
>>>>    }<br>
>>>><br>
>>>> +static VkResult<br>
>>>> +radv_cmd_state_setup_sample_locations(struct radv_cmd_buffer *cmd_buffer,<br>
>>>> +                                     struct radv_render_pass *pass,<br>
>>>> +                                     const VkRenderPassBeginInfo *info)<br>
>>>> +{<br>
>>>> +       const struct VkRenderPassSampleLocationsBeginInfoEXT *sample_locs =<br>
>>>> +               vk_find_struct_const(info->pNext,<br>
>>>> +                                    RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT);<br>
>>>> +       struct radv_cmd_state *state = &cmd_buffer->state;<br>
>>>> +       struct radv_framebuffer *framebuffer = state->framebuffer;<br>
>>>> +<br>
>>>> +       if (!sample_locs) {<br>
>>>> +               state->subpass_sample_locs = NULL;<br>
>>>> +               return VK_SUCCESS;<br>
>>>> +       }<br>
>>>> +<br>
>>>> +       for (uint32_t i = 0; i < sample_locs->attachmentInitialSampleLocationsCount; i++) {<br>
>>>> +               const VkAttachmentSampleLocationsEXT *att_sample_locs =<br>
>>>> +                       &sample_locs->pAttachmentInitialSampleLocations[i];<br>
>>>> +               uint32_t att_idx = att_sample_locs->attachmentIndex;<br>
>>>> +               struct radv_attachment_info *att = &framebuffer->attachments[att_idx];<br>
>>>> +               struct radv_image *image = att->attachment->image;<br>
>>>> +<br>
>>>> +               assert(vk_format_is_depth_or_stencil(image->vk_format));<br>
>>>> +<br>
>>>> +               /* From the Vulkan spec 1.1.108:<br>
>>>> +                *<br>
>>>> +                * "If the image referenced by the framebuffer attachment at<br>
>>>> +                *  index attachmentIndex was not created with<br>
>>>> +                *  VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT<br>
>>>> +                *  then the values specified in sampleLocationsInfo are<br>
>>>> +                *  ignored."<br>
>>>> +                */<br>
>>>> +               if (!(image->flags & VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT))<br>
>>>> +                       continue;<br>
>>>> +<br>
>>>> +               const VkSampleLocationsInfoEXT *sample_locs_info =<br>
>>>> +                       &att_sample_locs->sampleLocationsInfo;<br>
>>>> +<br>
>>>> +               state->attachments[att_idx].sample_location.per_pixel =<br>
>>>> +                       sample_locs_info->sampleLocationsPerPixel;<br>
>>>> +               state->attachments[att_idx].sample_location.grid_size =<br>
>>>> +                       sample_locs_info->sampleLocationGridSize;<br>
>>>> +               state->attachments[att_idx].sample_location.count =<br>
>>>> +                       sample_locs_info->sampleLocationsCount;<br>
>>>> +               typed_memcpy(&state->attachments[att_idx].sample_location.locations[0],<br>
>>>> +                            sample_locs_info->pSampleLocations,<br>
>>>> +                            sample_locs_info->sampleLocationsCount);<br>
>>>> +       }<br>
>>>> +<br>
>>>> +       state->subpass_sample_locs = vk_alloc(&cmd_buffer->pool->alloc,<br>
>>>> +                                             sample_locs->postSubpassSampleLocationsCount *<br>
>>>> +                                             sizeof(state->subpass_sample_locs[0]),<br>
>>>> +                                             8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);<br>
>>>> +       if (state->subpass_sample_locs == NULL) {<br>
>>>> +               cmd_buffer->record_result = VK_ERROR_OUT_OF_HOST_MEMORY;<br>
>>>> +               return cmd_buffer->record_result;<br>
>>>> +       }<br>
>>>> +<br>
>>>> +       state->num_subpass_sample_locs = sample_locs->postSubpassSampleLocationsCount;<br>
>>>> +<br>
>>>> +       for (uint32_t i = 0; i < sample_locs->postSubpassSampleLocationsCount; i++) {<br>
>>>> +               const VkSubpassSampleLocationsEXT *subpass_sample_locs_info =<br>
>>>> +                       &sample_locs->pPostSubpassSampleLocations[i];<br>
>>>> +               const VkSampleLocationsInfoEXT *sample_locs_info =<br>
>>>> +                       &subpass_sample_locs_info->sampleLocationsInfo;<br>
>>>> +<br>
>>>> +               state->subpass_sample_locs[i].subpass_idx =<br>
>>>> +                       subpass_sample_locs_info->subpassIndex;<br>
>>>> +               state->subpass_sample_locs[i].sample_location.per_pixel =<br>
>>>> +                       sample_locs_info->sampleLocationsPerPixel;<br>
>>>> +               state->subpass_sample_locs[i].sample_location.grid_size =<br>
>>>> +                       sample_locs_info->sampleLocationGridSize;<br>
>>>> +               state->subpass_sample_locs[i].sample_location.count =<br>
>>>> +                       sample_locs_info->sampleLocationsCount;<br>
>>>> +               typed_memcpy(&state->subpass_sample_locs[i].sample_location.locations[0],<br>
>>>> +                            sample_locs_info->pSampleLocations,<br>
>>>> +                            sample_locs_info->sampleLocationsCount);<br>
>>>> +       }<br>
>>>> +<br>
>>>> +       return VK_SUCCESS;<br>
>>>> +}<br>
>>>> +<br>
>>>>    static VkResult<br>
>>>>    radv_cmd_state_setup_attachments(struct radv_cmd_buffer *cmd_buffer,<br>
>>>>                                    struct radv_render_pass *pass,<br>
>>>> @@ -2741,6 +2873,7 @@ radv_cmd_state_setup_attachments(struct radv_cmd_buffer *cmd_buffer,<br>
>>>>                   }<br>
>>>><br>
>>>>                   state->attachments[i].current_layout = att->initial_layout;<br>
>>>> +               state->attachments[i].sample_location.count = 0;<br>
>>>>           }<br>
>>>><br>
>>>>           return VK_SUCCESS;<br>
>>>> @@ -3171,6 +3304,7 @@ VkResult radv_EndCommandBuffer(<br>
>>>>           si_cp_dma_wait_for_idle(cmd_buffer);<br>
>>>><br>
>>>>           vk_free(&cmd_buffer->pool->alloc, cmd_buffer->state.attachments);<br>
>>>> +       vk_free(&cmd_buffer->pool->alloc, cmd_buffer->state.subpass_sample_locs);<br>
>>>><br>
>>>>           if (!cmd_buffer->device->ws->cs_finalize(cmd_buffer->cs))<br>
>>>>                   return vk_error(cmd_buffer->device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);<br>
>>>> @@ -3669,19 +3803,6 @@ void radv_TrimCommandPool(<br>
>>>>           }<br>
>>>>    }<br>
>>>><br>
>>>> -static uint32_t<br>
>>>> -radv_get_subpass_id(struct radv_cmd_buffer *cmd_buffer)<br>
>>>> -{<br>
>>>> -       struct radv_cmd_state *state = &cmd_buffer->state;<br>
>>>> -       uint32_t subpass_id = state->subpass - state->pass->subpasses;<br>
>>>> -<br>
>>>> -       /* The id of this subpass shouldn't exceed the number of subpasses in<br>
>>>> -        * this render pass minus 1.<br>
>>>> -        */<br>
>>>> -       assert(subpass_id < state->pass->subpass_count);<br>
>>>> -       return subpass_id;<br>
>>>> -}<br>
>>>> -<br>
>>>>    static void<br>
>>>>    radv_cmd_buffer_begin_subpass(struct radv_cmd_buffer *cmd_buffer,<br>
>>>>                                 uint32_t subpass_id)<br>
>>>> @@ -3751,6 +3872,10 @@ void radv_CmdBeginRenderPass(<br>
>>>>           if (result != VK_SUCCESS)<br>
>>>>                   return;<br>
>>>><br>
>>>> +       result = radv_cmd_state_setup_sample_locations(cmd_buffer, pass, pRenderPassBegin);<br>
>>>> +       if (result != VK_SUCCESS)<br>
>>>> +               return;<br>
>>>> +<br>
>>>>           radv_cmd_buffer_begin_subpass(cmd_buffer, 0);<br>
>>>>    }<br>
>>>><br>
>>>> @@ -4593,11 +4718,13 @@ void radv_CmdEndRenderPass(<br>
>>>>           radv_cmd_buffer_end_subpass(cmd_buffer);<br>
>>>><br>
>>>>           vk_free(&cmd_buffer->pool->alloc, cmd_buffer->state.attachments);<br>
>>>> +       vk_free(&cmd_buffer->pool->alloc, cmd_buffer->state.subpass_sample_locs);<br>
>>>><br>
>>>>           cmd_buffer->state.pass = NULL;<br>
>>>>           cmd_buffer->state.subpass = NULL;<br>
>>>>           cmd_buffer->state.attachments = NULL;<br>
>>>>           cmd_buffer->state.framebuffer = NULL;<br>
>>>> +       cmd_buffer->state.subpass_sample_locs = NULL;<br>
>>>>    }<br>
>>>><br>
>>>>    void radv_CmdEndRenderPass2KHR(<br>
>>>> diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h<br>
>>>> index 180f8b976ab..76cc79b387d 100644<br>
>>>> --- a/src/amd/vulkan/radv_private.h<br>
>>>> +++ b/src/amd/vulkan/radv_private.h<br>
>>>> @@ -1024,6 +1024,7 @@ struct radv_attachment_state {<br>
>>>>           uint32_t                                     cleared_views;<br>
>>>>           VkClearValue                                 clear_value;<br>
>>>>           VkImageLayout                                current_layout;<br>
>>>> +       struct radv_sample_locations_state           sample_location;<br>
>>>>    };<br>
>>>><br>
>>>>    struct radv_descriptor_state {<br>
>>>> @@ -1035,6 +1036,11 @@ struct radv_descriptor_state {<br>
>>>>           uint32_t dynamic_buffers[4 * MAX_DYNAMIC_BUFFERS];<br>
>>>>    };<br>
>>>><br>
>>>> +struct radv_subpass_sample_locs_state {<br>
>>>> +       uint32_t subpass_idx;<br>
>>>> +       struct radv_sample_locations_state sample_location;<br>
>>>> +};<br>
>>>> +<br>
>>>>    struct radv_cmd_state {<br>
>>>>           /* Vertex descriptors */<br>
>>>>           uint64_t                                      vb_va;<br>
>>>> @@ -1057,6 +1063,9 @@ struct radv_cmd_state {<br>
>>>>           struct radv_streamout_state                  streamout;<br>
>>>>           VkRect2D                                     render_area;<br>
>>>><br>
>>>> +       uint32_t                                     num_subpass_sample_locs;<br>
>>>> +       struct radv_subpass_sample_locs_state *      subpass_sample_locs;<br>
>>>> +<br>
>>>>           /* Index buffer */<br>
>>>>           struct radv_buffer                           *index_buffer;<br>
>>>>           uint64_t                                     index_offset;<br>
>>>> --<br>
>>>> 2.21.0<br>
>>>><br>
>>>> _______________________________________________<br>
>>>> mesa-dev mailing list<br>
>>>> <a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank" rel="noreferrer">mesa-dev@lists.freedesktop.org</a><br>
>>>> <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</blockquote></div></div></div>