<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>