<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Mar 30, 2017 at 1:59 PM, Nanley Chery <span dir="ltr"><<a href="mailto:nanleychery@gmail.com" target="_blank">nanleychery@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail-HOEnZb"><div class="gmail-h5">On Wed, Mar 15, 2017 at 12:01:16PM -0700, Jason Ekstrand wrote:<br>
> ---<br>
>  src/intel/vulkan/anv_pass.c    | 89 ++++++++++++++++++++++++++++++<wbr>++++++++++++<br>
>  src/intel/vulkan/anv_private.h |  2 +<br>
>  2 files changed, 91 insertions(+)<br>
><br>
> diff --git a/src/intel/vulkan/anv_pass.c b/src/intel/vulkan/anv_pass.c<br>
> index 8d1768d..0f71fb3 100644<br>
> --- a/src/intel/vulkan/anv_pass.c<br>
> +++ b/src/intel/vulkan/anv_pass.c<br>
> @@ -98,6 +98,7 @@ VkResult anv_CreateRenderPass(<br>
>     if (pass->subpass_attachments == NULL)<br>
>        goto fail_subpass_usages;<br>
><br>
> +   bool has_color = false, has_depth = false, has_input = false;<br>
>     p = pass->subpass_attachments;<br>
>     for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {<br>
>        const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i];<br>
> @@ -115,6 +116,7 @@ VkResult anv_CreateRenderPass(<br>
>              uint32_t a = desc->pInputAttachments[j].<wbr>attachment;<br>
>              subpass->input_attachments[j] = desc->pInputAttachments[j];<br>
>              if (a != VK_ATTACHMENT_UNUSED) {<br>
> +               has_input = true;<br>
>                 pass->attachments[a].usage |= VK_IMAGE_USAGE_INPUT_<wbr>ATTACHMENT_BIT;<br>
>                 pass->attachments[a].subpass_<wbr>usage[i] |= ANV_SUBPASS_USAGE_INPUT;<br>
>                 pass->attachments[a].last_<wbr>subpass_idx = i;<br>
> @@ -134,6 +136,7 @@ VkResult anv_CreateRenderPass(<br>
>              uint32_t a = desc->pColorAttachments[j].<wbr>attachment;<br>
>              subpass->color_attachments[j] = desc->pColorAttachments[j];<br>
>              if (a != VK_ATTACHMENT_UNUSED) {<br>
> +               has_color = true;<br>
>                 pass->attachments[a].usage |= VK_IMAGE_USAGE_COLOR_<wbr>ATTACHMENT_BIT;<br>
>                 pass->attachments[a].subpass_<wbr>usage[i] |= ANV_SUBPASS_USAGE_DRAW;<br>
>                 pass->attachments[a].last_<wbr>subpass_idx = i;<br>
> @@ -170,6 +173,7 @@ VkResult anv_CreateRenderPass(<br>
>           *p++ = subpass->depth_stencil_<wbr>attachment =<br>
>              *desc-><wbr>pDepthStencilAttachment;<br>
>           if (a != VK_ATTACHMENT_UNUSED) {<br>
> +            has_depth = true;<br>
>              pass->attachments[a].usage |=<br>
>                 VK_IMAGE_USAGE_DEPTH_STENCIL_<wbr>ATTACHMENT_BIT;<br>
>              pass->attachments[a].subpass_<wbr>usage[i] |= ANV_SUBPASS_USAGE_DRAW;<br>
> @@ -181,10 +185,94 @@ VkResult anv_CreateRenderPass(<br>
>        }<br>
>     }<br>
><br>
> +   pass->subpass_flushes =<br>
> +      vk_zalloc2(&device->alloc, pAllocator,<br>
> +                 (pass->subpass_count + 1) * sizeof(*pass->subpass_flushes)<wbr>,<br>
> +                 8, VK_SYSTEM_ALLOCATION_SCOPE_<wbr>OBJECT);<br>
> +   if (pass->subpass_flushes == NULL)<br>
> +      goto fail_subpass_attachments;<br>
> +<br>
<br>
</div></div>I think we should allocate this memory differently. We currently have<br>
two memory allocation methods in this function:<br>
   1. Allocate memory per data structure. This makes pointer<br>
      assignments simple and using gotos improves error handling in this<br>
      case.<br>
   2. Allocate one big block of memory and assign pointers for certain<br>
      offsets into this block. This is a more efficient usage of memory<br>
      and error handling is quite simple in this case.<br>
<br>
For this series, I think the memory allocation for ::subpass_flushes<br>
should be lumped into the allocation for the entire render pass object.<br>
It's simple to do because we know the size upfront and we can avoid<br>
having to add the goto infrastructure.<span class="gmail-"><br></span></blockquote><div><br></div><div>Yes, I debated back and forth with myself over what to do here.  There are a number of places in the Vulkan driver where we've tried to do a single allocation and every time it comes at the cost of having to figure out the size up-front (cost both in terms of compute time to do the calculation and also in terms of having the code split up).  Admittedly, that usually isn't a huge deal, but with something as big as subpass, it gets tricky fast.  When I was working on this, I considered creating a little helper data structure for doing these kinds of allocations that would make it significantly more reliable.  But then I realized that the only place we would use it was in the subpass and I didn't bother.  I'm willing to revive it if you'd like.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
> +   for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {<br>
> +      const VkSubpassDependency *dep = &pCreateInfo->pDependencies[i]<wbr>;<br>
> +      if (dep->dstSubpass != VK_SUBPASS_EXTERNAL) {<br>
> +         assert(dep->dstSubpass < pass->subpass_count);<br>
> +         pass->subpass_flushes[dep-><wbr>dstSubpass] |=<br>
> +            anv_pipe_invalidate_bits_for_<wbr>access_flags(dep-><wbr>dstAccessMask);<br>
> +      }<br>
> +<br>
> +      if (dep->srcSubpass != VK_SUBPASS_EXTERNAL) {<br>
> +         assert(dep->srcSubpass < pass->subpass_count);<br>
> +         pass->subpass_flushes[dep-><wbr>srcSubpass + 1] |=<br>
> +            anv_pipe_flush_bits_for_<wbr>access_flags(dep-><wbr>srcAccessMask);<br>
> +      }<br>
> +   }<br>
<br>
</span>Why set the flush bits at srcSubpass + 1? This can cause excessive<br>
flushing. We can avoid this excess by setting the flush bits at<br>
dstSubpass (like we do for the invalidate bits).<br></blockquote><div><br></div><div>How is this excessive?  If anything, by doing the flushing earlier, it's more likely to get pipelined and not require stalling the GPU.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
I see that the implicit dependency with VK_SUBPASS_EXTERNAL is covered<br>
below, but explicit dependencies should be covered as well. For example,<br>
the above doesn't handle the case where a user declares an external<br>
dependency that has VK_ACCESS_SHADER_WRITE_BIT set in the srcSubpass.<br>
According to PipelineBarrier, this would require a DATA_CACHE flush.<span class="gmail-HOEnZb"><font color="#888888"><br></font></span></blockquote><div><br></div><div>Right... I thought it was ok when I wrote the code, but you've made me question that conviction.  How about something like this:<br></div><div><br></div><div>if (dep->dstSubpass == VK_SUBPASS_EXTERNAL) {<br></div><div>   pass->subpass_flushes[pass->subpass_count] |=<br><span class="gmail-">      anv_pipe_invalidate_bits_for_<wbr>access_flags(dep-><wbr>dstAccessMask);<br></span></div><div><span class="gmail-">} else {</span><span class="gmail-"></span><span class="gmail-"><span class="gmail-"><br>   assert(dep->dstSubpass < pass->subpass_count);</span><br>   pass->subpass_flushes[dep->dstSubpass] |=<br><span class="gmail-">      anv_pipe_invalidate_bits_for_<wbr>access_flags(dep-><wbr>dstAccessMask);<br></span>}<br><br></span></div><div><span class="gmail-">--Jason<br></span></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-HOEnZb"><font color="#888888">
-Nanley<br>
</font></span><div class="gmail-HOEnZb"><div class="gmail-h5"><br>
> +<br>
> +   /* From the Vulkan 1.0.39 spec:<br>
> +    *<br>
> +    *    If there is no subpass dependency from VK_SUBPASS_EXTERNAL to the<br>
> +    *    first subpass that uses an attachment, then an implicit subpass<br>
> +    *    dependency exists from VK_SUBPASS_EXTERNAL to the first subpass it is<br>
> +    *    used in. The subpass dependency operates as if defined with the<br>
> +    *    following parameters:<br>
> +    *<br>
> +    *    VkSubpassDependency implicitDependency = {<br>
> +    *        .srcSubpass = VK_SUBPASS_EXTERNAL;<br>
> +    *        .dstSubpass = firstSubpass; // First subpass attachment is used in<br>
> +    *        .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_<wbr>BIT;<br>
> +    *        .dstStageMask = VK_PIPELINE_STAGE_ALL_<wbr>COMMANDS_BIT;<br>
> +    *        .srcAccessMask = 0;<br>
> +    *        .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_<wbr>READ_BIT |<br>
> +    *                         VK_ACCESS_COLOR_ATTACHMENT_<wbr>READ_BIT |<br>
> +    *                         VK_ACCESS_COLOR_ATTACHMENT_<wbr>WRITE_BIT |<br>
> +    *                         VK_ACCESS_DEPTH_STENCIL_<wbr>ATTACHMENT_READ_BIT |<br>
> +    *                         VK_ACCESS_DEPTH_STENCIL_<wbr>ATTACHMENT_WRITE_BIT;<br>
> +    *        .dependencyFlags = 0;<br>
> +    *    };<br>
> +    *<br>
> +    *    Similarly, if there is no subpass dependency from the last subpass<br>
> +    *    that uses an attachment to VK_SUBPASS_EXTERNAL, then an implicit<br>
> +    *    subpass dependency exists from the last subpass it is used in to<br>
> +    *    VK_SUBPASS_EXTERNAL. The subpass dependency operates as if defined<br>
> +    *    with the following parameters:<br>
> +    *<br>
> +    *    VkSubpassDependency implicitDependency = {<br>
> +    *        .srcSubpass = lastSubpass; // Last subpass attachment is used in<br>
> +    *        .dstSubpass = VK_SUBPASS_EXTERNAL;<br>
> +    *        .srcStageMask = VK_PIPELINE_STAGE_ALL_<wbr>COMMANDS_BIT;<br>
> +    *        .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_<wbr>PIPE_BIT;<br>
> +    *        .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_<wbr>READ_BIT |<br>
> +    *                         VK_ACCESS_COLOR_ATTACHMENT_<wbr>READ_BIT |<br>
> +    *                         VK_ACCESS_COLOR_ATTACHMENT_<wbr>WRITE_BIT |<br>
> +    *                         VK_ACCESS_DEPTH_STENCIL_<wbr>ATTACHMENT_READ_BIT |<br>
> +    *                         VK_ACCESS_DEPTH_STENCIL_<wbr>ATTACHMENT_WRITE_BIT;<br>
> +    *        .dstAccessMask = 0;<br>
> +    *        .dependencyFlags = 0;<br>
> +    *    };<br>
> +    *<br>
> +    * We could implement this by walking over all of the attachments and<br>
> +    * subpasses and checking to see if any of them don't have an external<br>
> +    * dependency.  Or, we could just be lazy and add a couple extra flushes.<br>
> +    * We choose to be lazy.<br>
> +    */<br>
> +   if (has_input) {<br>
> +      pass->subpass_flushes[0] |=<br>
> +         ANV_PIPE_TEXTURE_CACHE_<wbr>INVALIDATE_BIT;<br>
> +   }<br>
> +   if (has_color) {<br>
> +      pass->subpass_flushes[pass-><wbr>subpass_count] |=<br>
> +         ANV_PIPE_RENDER_TARGET_CACHE_<wbr>FLUSH_BIT;<br>
> +   }<br>
> +   if (has_depth) {<br>
> +      pass->subpass_flushes[pass-><wbr>subpass_count] |=<br>
> +         ANV_PIPE_DEPTH_CACHE_FLUSH_<wbr>BIT;<br>
> +   }<br>
> +<br>
>     *pRenderPass = anv_render_pass_to_handle(<wbr>pass);<br>
><br>
>     return VK_SUCCESS;<br>
><br>
> +fail_subpass_attachments:<br>
> +   vk_free2(&device->alloc, pAllocator, pass->subpass_attachments);<br>
>  fail_subpass_usages:<br>
>     vk_free2(&device->alloc, pAllocator, pass->subpass_usages);<br>
>  fail_pass:<br>
> @@ -204,6 +292,7 @@ void anv_DestroyRenderPass(<br>
>     if (!pass)<br>
>        return;<br>
><br>
> +   vk_free2(&device->alloc, pAllocator, pass->subpass_flushes);<br>
>     vk_free2(&device->alloc, pAllocator, pass->subpass_attachments);<br>
>     vk_free2(&device->alloc, pAllocator, pass->subpass_usages);<br>
>     vk_free2(&device->alloc, pAllocator, pass);<br>
> diff --git a/src/intel/vulkan/anv_<wbr>private.h b/src/intel/vulkan/anv_<wbr>private.h<br>
> index a0eefe3..53d39ee 100644<br>
> --- a/src/intel/vulkan/anv_<wbr>private.h<br>
> +++ b/src/intel/vulkan/anv_<wbr>private.h<br>
> @@ -2038,6 +2038,8 @@ struct anv_render_pass {<br>
>     uint32_t                                     attachment_count;<br>
>     uint32_t                                     subpass_count;<br>
>     VkAttachmentReference *                      subpass_attachments;<br>
> +   /* An array of subpass_count+1 flushes, one per subpass boundary */<br>
> +   enum anv_pipe_bits *                         subpass_flushes;<br>
>     enum anv_subpass_usage *                     subpass_usages;<br>
>     struct anv_render_pass_attachment *          attachments;<br>
>     struct anv_subpass                           subpasses[0];<br>
> --<br>
> 2.5.0.400.gff86faf<br>
><br>
</div></div><div class="gmail-HOEnZb"><div class="gmail-h5">> ______________________________<wbr>_________________<br>
> mesa-dev mailing list<br>
> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</div></div></blockquote></div><br></div></div>