1/*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#include "anv_private.h"
25
26#include "vk_format.h"
27#include "vk_util.h"
28
29static void
30anv_render_pass_add_subpass_dep(struct anv_device *device,
31                                struct anv_render_pass *pass,
32                                const VkSubpassDependency2KHR *dep)
33{
34   /* From the Vulkan 1.2.195 spec:
35    *
36    *    "If an instance of VkMemoryBarrier2 is included in the pNext chain,
37    *    srcStageMask, dstStageMask, srcAccessMask, and dstAccessMask
38    *    parameters are ignored. The synchronization and access scopes instead
39    *    are defined by the parameters of VkMemoryBarrier2."
40    */
41   const VkMemoryBarrier2KHR *barrier =
42      vk_find_struct_const(dep->pNext, MEMORY_BARRIER_2_KHR);
43   VkAccessFlags2KHR src_access_mask =
44      barrier ? barrier->srcAccessMask : dep->srcAccessMask;
45   VkAccessFlags2KHR dst_access_mask =
46      barrier ? barrier->dstAccessMask : dep->dstAccessMask;
47
48   if (dep->dstSubpass == VK_SUBPASS_EXTERNAL) {
49      pass->subpass_flushes[pass->subpass_count] |=
50         anv_pipe_invalidate_bits_for_access_flags(device, dst_access_mask);
51   } else {
52      assert(dep->dstSubpass < pass->subpass_count);
53      pass->subpass_flushes[dep->dstSubpass] |=
54         anv_pipe_invalidate_bits_for_access_flags(device, dst_access_mask);
55   }
56
57   if (dep->srcSubpass == VK_SUBPASS_EXTERNAL) {
58      pass->subpass_flushes[0] |=
59         anv_pipe_flush_bits_for_access_flags(device, src_access_mask);
60   } else {
61      assert(dep->srcSubpass < pass->subpass_count);
62      pass->subpass_flushes[dep->srcSubpass + 1] |=
63         anv_pipe_flush_bits_for_access_flags(device, src_access_mask);
64   }
65}
66
67/* Do a second "compile" step on a render pass */
68static void
69anv_render_pass_compile(struct anv_render_pass *pass)
70{
71   /* The CreateRenderPass code zeros the entire render pass and also uses a
72    * designated initializer for filling these out.  There's no need for us to
73    * do it again.
74    *
75    * for (uint32_t i = 0; i < pass->attachment_count; i++) {
76    *    pass->attachments[i].usage = 0;
77    *    pass->attachments[i].first_subpass_layout = VK_IMAGE_LAYOUT_UNDEFINED;
78    * }
79    */
80
81   VkImageUsageFlags all_usage = 0;
82   for (uint32_t i = 0; i < pass->subpass_count; i++) {
83      struct anv_subpass *subpass = &pass->subpasses[i];
84
85      /* We don't allow depth_stencil_attachment to be non-NULL and be
86       * VK_ATTACHMENT_UNUSED.  This way something can just check for NULL
87       * and be guaranteed that they have a valid attachment.
88       */
89      if (subpass->depth_stencil_attachment &&
90          subpass->depth_stencil_attachment->attachment == VK_ATTACHMENT_UNUSED)
91         subpass->depth_stencil_attachment = NULL;
92
93      if (subpass->ds_resolve_attachment &&
94          subpass->ds_resolve_attachment->attachment == VK_ATTACHMENT_UNUSED)
95         subpass->ds_resolve_attachment = NULL;
96
97      for (uint32_t j = 0; j < subpass->attachment_count; j++) {
98         struct anv_subpass_attachment *subpass_att = &subpass->attachments[j];
99         if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
100            continue;
101
102         struct anv_render_pass_attachment *pass_att =
103            &pass->attachments[subpass_att->attachment];
104
105         pass_att->usage |= subpass_att->usage;
106         pass_att->last_subpass_idx = i;
107
108         all_usage |= subpass_att->usage;
109
110         /* first_subpass_layout only applies to color and depth.
111          * See genX(cmd_buffer_setup_attachments)
112          */
113         if (vk_format_aspects(pass_att->format) != VK_IMAGE_ASPECT_STENCIL_BIT &&
114             pass_att->first_subpass_layout == VK_IMAGE_LAYOUT_UNDEFINED) {
115            pass_att->first_subpass_layout = subpass_att->layout;
116            assert(pass_att->first_subpass_layout != VK_IMAGE_LAYOUT_UNDEFINED);
117         }
118
119         if (subpass_att->usage == VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT &&
120             subpass->depth_stencil_attachment &&
121             subpass_att->attachment == subpass->depth_stencil_attachment->attachment)
122            subpass->has_ds_self_dep = true;
123      }
124
125      /* We have to handle resolve attachments specially */
126      subpass->has_color_resolve = false;
127      if (subpass->resolve_attachments) {
128         for (uint32_t j = 0; j < subpass->color_count; j++) {
129            struct anv_subpass_attachment *color_att =
130               &subpass->color_attachments[j];
131            struct anv_subpass_attachment *resolve_att =
132               &subpass->resolve_attachments[j];
133            if (resolve_att->attachment == VK_ATTACHMENT_UNUSED)
134               continue;
135
136            subpass->has_color_resolve = true;
137
138            assert(color_att->attachment < pass->attachment_count);
139            struct anv_render_pass_attachment *color_pass_att =
140               &pass->attachments[color_att->attachment];
141
142            assert(resolve_att->usage == VK_IMAGE_USAGE_TRANSFER_DST_BIT);
143            assert(color_att->usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
144            color_pass_att->usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
145         }
146      }
147
148      if (subpass->ds_resolve_attachment) {
149         struct anv_subpass_attachment *ds_att =
150            subpass->depth_stencil_attachment;
151         UNUSED struct anv_subpass_attachment *resolve_att =
152            subpass->ds_resolve_attachment;
153
154         assert(ds_att->attachment < pass->attachment_count);
155         struct anv_render_pass_attachment *ds_pass_att =
156            &pass->attachments[ds_att->attachment];
157
158         assert(resolve_att->usage == VK_IMAGE_USAGE_TRANSFER_DST_BIT);
159         assert(ds_att->usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
160         ds_pass_att->usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
161      }
162
163      for (uint32_t j = 0; j < subpass->attachment_count; j++)
164         assert(__builtin_popcount(subpass->attachments[j].usage) == 1);
165   }
166
167   /* From the Vulkan 1.0.39 spec:
168    *
169    *    If there is no subpass dependency from VK_SUBPASS_EXTERNAL to the
170    *    first subpass that uses an attachment, then an implicit subpass
171    *    dependency exists from VK_SUBPASS_EXTERNAL to the first subpass it is
172    *    used in. The subpass dependency operates as if defined with the
173    *    following parameters:
174    *
175    *    VkSubpassDependency implicitDependency = {
176    *        .srcSubpass = VK_SUBPASS_EXTERNAL;
177    *        .dstSubpass = firstSubpass; // First subpass attachment is used in
178    *        .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
179    *        .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
180    *        .srcAccessMask = 0;
181    *        .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
182    *                         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
183    *                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
184    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
185    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
186    *        .dependencyFlags = 0;
187    *    };
188    *
189    *    Similarly, if there is no subpass dependency from the last subpass
190    *    that uses an attachment to VK_SUBPASS_EXTERNAL, then an implicit
191    *    subpass dependency exists from the last subpass it is used in to
192    *    VK_SUBPASS_EXTERNAL. The subpass dependency operates as if defined
193    *    with the following parameters:
194    *
195    *    VkSubpassDependency implicitDependency = {
196    *        .srcSubpass = lastSubpass; // Last subpass attachment is used in
197    *        .dstSubpass = VK_SUBPASS_EXTERNAL;
198    *        .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
199    *        .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
200    *        .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
201    *                         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
202    *                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
203    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
204    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
205    *        .dstAccessMask = 0;
206    *        .dependencyFlags = 0;
207    *    };
208    *
209    * We could implement this by walking over all of the attachments and
210    * subpasses and checking to see if any of them don't have an external
211    * dependency.  Or, we could just be lazy and add a couple extra flushes.
212    * We choose to be lazy.
213    *
214    * From the documentation for vkCmdNextSubpass:
215    *
216    *    "Moving to the next subpass automatically performs any multisample
217    *    resolve operations in the subpass being ended. End-of-subpass
218    *    multisample resolves are treated as color attachment writes for the
219    *    purposes of synchronization. This applies to resolve operations for
220    *    both color and depth/stencil attachments. That is, they are
221    *    considered to execute in the
222    *    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT pipeline stage and
223    *    their writes are synchronized with
224    *    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT."
225    *
226    * Therefore, the above flags concerning color attachments also apply to
227    * color and depth/stencil resolve attachments.
228    */
229   if (all_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
230      pass->subpass_flushes[0] |=
231         ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT;
232   }
233   if (all_usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
234                    VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
235      pass->subpass_flushes[pass->subpass_count] |=
236         ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT;
237   }
238   if (all_usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
239      pass->subpass_flushes[pass->subpass_count] |=
240         ANV_PIPE_DEPTH_CACHE_FLUSH_BIT;
241   }
242}
243
244static unsigned
245num_subpass_attachments2(const VkSubpassDescription2KHR *desc)
246{
247   const VkSubpassDescriptionDepthStencilResolveKHR *ds_resolve =
248      vk_find_struct_const(desc->pNext,
249                           SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR);
250
251   return desc->inputAttachmentCount +
252          desc->colorAttachmentCount +
253          (desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
254          (desc->pDepthStencilAttachment != NULL) +
255          (ds_resolve && ds_resolve->pDepthStencilResolveAttachment);
256}
257
258static bool
259vk_image_layout_depth_only(VkImageLayout layout)
260{
261   switch (layout) {
262   case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
263   case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
264      return true;
265
266   default:
267      return false;
268   }
269}
270
271/* From the Vulkan Specification 1.2.166 - VkAttachmentReference2:
272 *
273 *   "If layout only specifies the layout of the depth aspect of the
274 *    attachment, the layout of the stencil aspect is specified by the
275 *    stencilLayout member of a VkAttachmentReferenceStencilLayout structure
276 *    included in the pNext chain. Otherwise, layout describes the layout for
277 *    all relevant image aspects."
278 */
279static VkImageLayout
280stencil_ref_layout(const VkAttachmentReference2KHR *att_ref)
281{
282   if (!vk_image_layout_depth_only(att_ref->layout))
283      return att_ref->layout;
284
285   const VkAttachmentReferenceStencilLayoutKHR *stencil_ref =
286      vk_find_struct_const(att_ref->pNext,
287                           ATTACHMENT_REFERENCE_STENCIL_LAYOUT_KHR);
288   if (!stencil_ref)
289      return VK_IMAGE_LAYOUT_UNDEFINED;
290   return stencil_ref->stencilLayout;
291}
292
293/* From the Vulkan Specification 1.2.166 - VkAttachmentDescription2:
294 *
295 *   "If format is a depth/stencil format, and initialLayout only specifies
296 *    the initial layout of the depth aspect of the attachment, the initial
297 *    layout of the stencil aspect is specified by the stencilInitialLayout
298 *    member of a VkAttachmentDescriptionStencilLayout structure included in
299 *    the pNext chain. Otherwise, initialLayout describes the initial layout
300 *    for all relevant image aspects."
301 */
302static VkImageLayout
303stencil_desc_layout(const VkAttachmentDescription2KHR *att_desc, bool final)
304{
305   if (!vk_format_has_stencil(att_desc->format))
306      return VK_IMAGE_LAYOUT_UNDEFINED;
307
308   const VkImageLayout main_layout =
309      final ? att_desc->finalLayout : att_desc->initialLayout;
310   if (!vk_image_layout_depth_only(main_layout))
311      return main_layout;
312
313   const VkAttachmentDescriptionStencilLayoutKHR *stencil_desc =
314      vk_find_struct_const(att_desc->pNext,
315                           ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR);
316   assert(stencil_desc);
317   return final ?
318      stencil_desc->stencilFinalLayout :
319      stencil_desc->stencilInitialLayout;
320}
321
322VkResult anv_CreateRenderPass2(
323    VkDevice                                    _device,
324    const VkRenderPassCreateInfo2KHR*           pCreateInfo,
325    const VkAllocationCallbacks*                pAllocator,
326    VkRenderPass*                               pRenderPass)
327{
328   ANV_FROM_HANDLE(anv_device, device, _device);
329
330   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR);
331
332   VK_MULTIALLOC(ma);
333   VK_MULTIALLOC_DECL(&ma, struct anv_render_pass, pass, 1);
334   VK_MULTIALLOC_DECL(&ma, struct anv_subpass, subpasses,
335                           pCreateInfo->subpassCount);
336   VK_MULTIALLOC_DECL(&ma, struct anv_render_pass_attachment, attachments,
337                           pCreateInfo->attachmentCount);
338   VK_MULTIALLOC_DECL(&ma, enum anv_pipe_bits, subpass_flushes,
339                           pCreateInfo->subpassCount + 1);
340
341   uint32_t subpass_attachment_count = 0;
342   for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
343      subpass_attachment_count +=
344         num_subpass_attachments2(&pCreateInfo->pSubpasses[i]);
345   }
346   VK_MULTIALLOC_DECL(&ma, struct anv_subpass_attachment, subpass_attachments,
347                      subpass_attachment_count);
348
349   if (!vk_object_multizalloc(&device->vk, &ma, pAllocator,
350                              VK_OBJECT_TYPE_RENDER_PASS))
351      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
352
353   /* Clear the subpasses along with the parent pass. This required because
354    * each array member of anv_subpass must be a valid pointer if not NULL.
355    */
356   pass->attachment_count = pCreateInfo->attachmentCount;
357   pass->subpass_count = pCreateInfo->subpassCount;
358   pass->attachments = attachments;
359   pass->subpass_flushes = subpass_flushes;
360
361   for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
362      pass->attachments[i] = (struct anv_render_pass_attachment) {
363         .format                 = pCreateInfo->pAttachments[i].format,
364         .samples                = pCreateInfo->pAttachments[i].samples,
365         .load_op                = pCreateInfo->pAttachments[i].loadOp,
366         .store_op               = pCreateInfo->pAttachments[i].storeOp,
367         .stencil_load_op        = pCreateInfo->pAttachments[i].stencilLoadOp,
368         .initial_layout         = pCreateInfo->pAttachments[i].initialLayout,
369         .final_layout           = pCreateInfo->pAttachments[i].finalLayout,
370
371         .stencil_initial_layout = stencil_desc_layout(&pCreateInfo->pAttachments[i],
372                                                       false),
373         .stencil_final_layout   = stencil_desc_layout(&pCreateInfo->pAttachments[i],
374                                                       true),
375      };
376   }
377
378   for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
379      const VkSubpassDescription2KHR *desc = &pCreateInfo->pSubpasses[i];
380      struct anv_subpass *subpass = &pass->subpasses[i];
381
382      subpass->input_count = desc->inputAttachmentCount;
383      subpass->color_count = desc->colorAttachmentCount;
384      subpass->attachment_count = num_subpass_attachments2(desc);
385      subpass->attachments = subpass_attachments;
386      subpass->view_mask = desc->viewMask;
387
388      if (desc->inputAttachmentCount > 0) {
389         subpass->input_attachments = subpass_attachments;
390         subpass_attachments += desc->inputAttachmentCount;
391
392         for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) {
393            subpass->input_attachments[j] = (struct anv_subpass_attachment) {
394               .usage =          VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
395               .attachment =     desc->pInputAttachments[j].attachment,
396               .layout =         desc->pInputAttachments[j].layout,
397               .stencil_layout = stencil_ref_layout(&desc->pInputAttachments[j]),
398            };
399         }
400      }
401
402      if (desc->colorAttachmentCount > 0) {
403         subpass->color_attachments = subpass_attachments;
404         subpass_attachments += desc->colorAttachmentCount;
405
406         for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
407            subpass->color_attachments[j] = (struct anv_subpass_attachment) {
408               .usage =       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
409               .attachment =  desc->pColorAttachments[j].attachment,
410               .layout =      desc->pColorAttachments[j].layout,
411            };
412         }
413      }
414
415      if (desc->pResolveAttachments) {
416         subpass->resolve_attachments = subpass_attachments;
417         subpass_attachments += desc->colorAttachmentCount;
418
419         for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
420            subpass->resolve_attachments[j] = (struct anv_subpass_attachment) {
421               .usage =       VK_IMAGE_USAGE_TRANSFER_DST_BIT,
422               .attachment =  desc->pResolveAttachments[j].attachment,
423               .layout =      desc->pResolveAttachments[j].layout,
424            };
425         }
426      }
427
428      if (desc->pDepthStencilAttachment) {
429         subpass->depth_stencil_attachment = subpass_attachments++;
430
431         *subpass->depth_stencil_attachment = (struct anv_subpass_attachment) {
432            .usage =          VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
433            .attachment =     desc->pDepthStencilAttachment->attachment,
434            .layout =         desc->pDepthStencilAttachment->layout,
435            .stencil_layout = stencil_ref_layout(desc->pDepthStencilAttachment),
436         };
437      }
438
439      const VkSubpassDescriptionDepthStencilResolveKHR *ds_resolve =
440         vk_find_struct_const(desc->pNext,
441                              SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR);
442
443      if (ds_resolve && ds_resolve->pDepthStencilResolveAttachment) {
444         subpass->ds_resolve_attachment = subpass_attachments++;
445
446         *subpass->ds_resolve_attachment = (struct anv_subpass_attachment) {
447            .usage =          VK_IMAGE_USAGE_TRANSFER_DST_BIT,
448            .attachment =     ds_resolve->pDepthStencilResolveAttachment->attachment,
449            .layout =         ds_resolve->pDepthStencilResolveAttachment->layout,
450            .stencil_layout = stencil_ref_layout(ds_resolve->pDepthStencilResolveAttachment),
451         };
452         subpass->depth_resolve_mode = ds_resolve->depthResolveMode;
453         subpass->stencil_resolve_mode = ds_resolve->stencilResolveMode;
454      }
455   }
456
457   for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
458      anv_render_pass_add_subpass_dep(device, pass,
459                                      &pCreateInfo->pDependencies[i]);
460   }
461
462   vk_foreach_struct(ext, pCreateInfo->pNext) {
463      switch (ext->sType) {
464      default:
465         anv_debug_ignored_stype(ext->sType);
466      }
467   }
468
469   anv_render_pass_compile(pass);
470
471   *pRenderPass = anv_render_pass_to_handle(pass);
472
473   return VK_SUCCESS;
474}
475
476void anv_DestroyRenderPass(
477    VkDevice                                    _device,
478    VkRenderPass                                _pass,
479    const VkAllocationCallbacks*                pAllocator)
480{
481   ANV_FROM_HANDLE(anv_device, device, _device);
482   ANV_FROM_HANDLE(anv_render_pass, pass, _pass);
483
484   if (!pass)
485      return;
486
487   vk_object_free(&device->vk, pAllocator, pass);
488}
489
490void anv_GetRenderAreaGranularity(
491    VkDevice                                    device,
492    VkRenderPass                                renderPass,
493    VkExtent2D*                                 pGranularity)
494{
495   ANV_FROM_HANDLE(anv_render_pass, pass, renderPass);
496
497   /* This granularity satisfies HiZ fast clear alignment requirements
498    * for all sample counts.
499    */
500   for (unsigned i = 0; i < pass->subpass_count; ++i) {
501      if (pass->subpasses[i].depth_stencil_attachment) {
502         *pGranularity = (VkExtent2D) { .width = 8, .height = 4 };
503         return;
504      }
505   }
506
507   *pGranularity = (VkExtent2D) { 1, 1 };
508}
509