1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2016 Red Hat.
3bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * based in part on anv driver which is:
6bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation
7bf215546Sopenharmony_ci *
8bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
9bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
10bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
11bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
13bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
16bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
17bf215546Sopenharmony_ci * Software.
18bf215546Sopenharmony_ci *
19bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25bf215546Sopenharmony_ci * IN THE SOFTWARE.
26bf215546Sopenharmony_ci */
27bf215546Sopenharmony_ci#include "radv_private.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "vk_util.h"
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_cistatic void
32bf215546Sopenharmony_ciradv_render_pass_add_subpass_dep(struct radv_render_pass *pass, const VkSubpassDependency2 *dep)
33bf215546Sopenharmony_ci{
34bf215546Sopenharmony_ci   uint32_t src = dep->srcSubpass;
35bf215546Sopenharmony_ci   uint32_t dst = dep->dstSubpass;
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci   /* Ignore subpass self-dependencies as they allow the app to call
38bf215546Sopenharmony_ci    * vkCmdPipelineBarrier() inside the render pass and the driver should
39bf215546Sopenharmony_ci    * only do the barrier when called, not when starting the render pass.
40bf215546Sopenharmony_ci    */
41bf215546Sopenharmony_ci   if (src == dst)
42bf215546Sopenharmony_ci      return;
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci   /* Accumulate all ingoing external dependencies to the first subpass. */
45bf215546Sopenharmony_ci   if (src == VK_SUBPASS_EXTERNAL)
46bf215546Sopenharmony_ci      dst = 0;
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   /* From the Vulkan 1.2.195 spec:
50bf215546Sopenharmony_ci    *
51bf215546Sopenharmony_ci    * "If an instance of VkMemoryBarrier2 is included in the pNext chain, srcStageMask,
52bf215546Sopenharmony_ci    *  dstStageMask, srcAccessMask, and dstAccessMask parameters are ignored. The synchronization
53bf215546Sopenharmony_ci    *  and access scopes instead are defined by the parameters of VkMemoryBarrier2."
54bf215546Sopenharmony_ci    */
55bf215546Sopenharmony_ci   const VkMemoryBarrier2 *barrier =
56bf215546Sopenharmony_ci      vk_find_struct_const(dep->pNext, MEMORY_BARRIER_2);
57bf215546Sopenharmony_ci   VkPipelineStageFlags2 src_stage_mask = barrier ? barrier->srcStageMask : dep->srcStageMask;
58bf215546Sopenharmony_ci   VkAccessFlags2 src_access_mask = barrier ? barrier->srcAccessMask : dep->srcAccessMask;
59bf215546Sopenharmony_ci   VkPipelineStageFlags2 dst_stage_mask = barrier ? barrier->dstStageMask : dep->dstStageMask;
60bf215546Sopenharmony_ci   VkAccessFlags2 dst_access_mask = barrier ? barrier->dstAccessMask : dep->dstAccessMask;
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci   if (dst == VK_SUBPASS_EXTERNAL) {
63bf215546Sopenharmony_ci      if (dst_stage_mask != VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT) {
64bf215546Sopenharmony_ci         pass->end_barrier.src_stage_mask |= src_stage_mask;
65bf215546Sopenharmony_ci         pass->end_barrier.dst_stage_mask |= dst_stage_mask;
66bf215546Sopenharmony_ci      }
67bf215546Sopenharmony_ci      pass->end_barrier.src_access_mask |= src_access_mask;
68bf215546Sopenharmony_ci      pass->end_barrier.dst_access_mask |= dst_access_mask;
69bf215546Sopenharmony_ci   } else {
70bf215546Sopenharmony_ci      if (dst_stage_mask != VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT) {
71bf215546Sopenharmony_ci         pass->subpasses[dst].start_barrier.src_stage_mask |= src_stage_mask;
72bf215546Sopenharmony_ci         pass->subpasses[dst].start_barrier.dst_stage_mask |= dst_stage_mask;
73bf215546Sopenharmony_ci      }
74bf215546Sopenharmony_ci      pass->subpasses[dst].start_barrier.src_access_mask |= src_access_mask;
75bf215546Sopenharmony_ci      pass->subpasses[dst].start_barrier.dst_access_mask |= dst_access_mask;
76bf215546Sopenharmony_ci   }
77bf215546Sopenharmony_ci}
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_cistatic void
80bf215546Sopenharmony_ciradv_render_pass_add_implicit_deps(struct radv_render_pass *pass)
81bf215546Sopenharmony_ci{
82bf215546Sopenharmony_ci   /* From the Vulkan 1.0.39 spec:
83bf215546Sopenharmony_ci    *
84bf215546Sopenharmony_ci    *    If there is no subpass dependency from VK_SUBPASS_EXTERNAL to the
85bf215546Sopenharmony_ci    *    first subpass that uses an attachment, then an implicit subpass
86bf215546Sopenharmony_ci    *    dependency exists from VK_SUBPASS_EXTERNAL to the first subpass it is
87bf215546Sopenharmony_ci    *    used in. The implicit subpass dependency only exists if there
88bf215546Sopenharmony_ci    *    exists an automatic layout transition away from initialLayout.
89bf215546Sopenharmony_ci    *    The subpass dependency operates as if defined with the
90bf215546Sopenharmony_ci    *    following parameters:
91bf215546Sopenharmony_ci    *
92bf215546Sopenharmony_ci    *    VkSubpassDependency implicitDependency = {
93bf215546Sopenharmony_ci    *        .srcSubpass = VK_SUBPASS_EXTERNAL;
94bf215546Sopenharmony_ci    *        .dstSubpass = firstSubpass; // First subpass attachment is used in
95bf215546Sopenharmony_ci    *        .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
96bf215546Sopenharmony_ci    *        .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
97bf215546Sopenharmony_ci    *        .srcAccessMask = 0;
98bf215546Sopenharmony_ci    *        .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
99bf215546Sopenharmony_ci    *                         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
100bf215546Sopenharmony_ci    *                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
101bf215546Sopenharmony_ci    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
102bf215546Sopenharmony_ci    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
103bf215546Sopenharmony_ci    *        .dependencyFlags = 0;
104bf215546Sopenharmony_ci    *    };
105bf215546Sopenharmony_ci    *
106bf215546Sopenharmony_ci    *    Similarly, if there is no subpass dependency from the last subpass
107bf215546Sopenharmony_ci    *    that uses an attachment to VK_SUBPASS_EXTERNAL, then an implicit
108bf215546Sopenharmony_ci    *    subpass dependency exists from the last subpass it is used in to
109bf215546Sopenharmony_ci    *    VK_SUBPASS_EXTERNAL. The implicit subpass dependency only exists
110bf215546Sopenharmony_ci    *    if there exists an automatic layout transition into finalLayout.
111bf215546Sopenharmony_ci    *    The subpass dependency operates as if defined with the following
112bf215546Sopenharmony_ci    *    parameters:
113bf215546Sopenharmony_ci    *
114bf215546Sopenharmony_ci    *    VkSubpassDependency implicitDependency = {
115bf215546Sopenharmony_ci    *        .srcSubpass = lastSubpass; // Last subpass attachment is used in
116bf215546Sopenharmony_ci    *        .dstSubpass = VK_SUBPASS_EXTERNAL;
117bf215546Sopenharmony_ci    *        .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
118bf215546Sopenharmony_ci    *        .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
119bf215546Sopenharmony_ci    *        .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
120bf215546Sopenharmony_ci    *                         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
121bf215546Sopenharmony_ci    *                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
122bf215546Sopenharmony_ci    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
123bf215546Sopenharmony_ci    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
124bf215546Sopenharmony_ci    *        .dstAccessMask = 0;
125bf215546Sopenharmony_ci    *        .dependencyFlags = 0;
126bf215546Sopenharmony_ci    *    };
127bf215546Sopenharmony_ci    */
128bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pass->subpass_count; i++) {
129bf215546Sopenharmony_ci      struct radv_subpass *subpass = &pass->subpasses[i];
130bf215546Sopenharmony_ci      bool add_ingoing_dep = false, add_outgoing_dep = false;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci      for (uint32_t j = 0; j < subpass->attachment_count; j++) {
133bf215546Sopenharmony_ci         struct radv_subpass_attachment *subpass_att = &subpass->attachments[j];
134bf215546Sopenharmony_ci         if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
135bf215546Sopenharmony_ci            continue;
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci         struct radv_render_pass_attachment *pass_att = &pass->attachments[subpass_att->attachment];
138bf215546Sopenharmony_ci         uint32_t initial_layout = pass_att->initial_layout;
139bf215546Sopenharmony_ci         uint32_t stencil_initial_layout = pass_att->stencil_initial_layout;
140bf215546Sopenharmony_ci         uint32_t final_layout = pass_att->final_layout;
141bf215546Sopenharmony_ci         uint32_t stencil_final_layout = pass_att->stencil_final_layout;
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci         /* The implicit subpass dependency only exists if
144bf215546Sopenharmony_ci          * there exists an automatic layout transition away
145bf215546Sopenharmony_ci          * from initialLayout.
146bf215546Sopenharmony_ci          */
147bf215546Sopenharmony_ci         if (pass_att->first_subpass_idx == i && !subpass->has_ingoing_dep &&
148bf215546Sopenharmony_ci             ((subpass_att->layout != initial_layout) ||
149bf215546Sopenharmony_ci              (subpass_att->stencil_layout != stencil_initial_layout))) {
150bf215546Sopenharmony_ci            add_ingoing_dep = true;
151bf215546Sopenharmony_ci         }
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci         /* The implicit subpass dependency only exists if
154bf215546Sopenharmony_ci          * there exists an automatic layout transition into
155bf215546Sopenharmony_ci          * finalLayout.
156bf215546Sopenharmony_ci          */
157bf215546Sopenharmony_ci         if (pass_att->last_subpass_idx == i && !subpass->has_outgoing_dep &&
158bf215546Sopenharmony_ci             ((subpass_att->layout != final_layout) ||
159bf215546Sopenharmony_ci              (subpass_att->stencil_layout != stencil_final_layout))) {
160bf215546Sopenharmony_ci            add_outgoing_dep = true;
161bf215546Sopenharmony_ci         }
162bf215546Sopenharmony_ci      }
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci      if (add_ingoing_dep) {
165bf215546Sopenharmony_ci         const VkSubpassDependency2 implicit_ingoing_dep = {
166bf215546Sopenharmony_ci            .srcSubpass = VK_SUBPASS_EXTERNAL,
167bf215546Sopenharmony_ci            .dstSubpass = i, /* first subpass attachment is used in */
168bf215546Sopenharmony_ci            .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
169bf215546Sopenharmony_ci            .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
170bf215546Sopenharmony_ci            .srcAccessMask = 0,
171bf215546Sopenharmony_ci            .dstAccessMask =
172bf215546Sopenharmony_ci               VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
173bf215546Sopenharmony_ci               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
174bf215546Sopenharmony_ci               VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
175bf215546Sopenharmony_ci            .dependencyFlags = 0,
176bf215546Sopenharmony_ci         };
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci         radv_render_pass_add_subpass_dep(pass, &implicit_ingoing_dep);
179bf215546Sopenharmony_ci      }
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci      if (add_outgoing_dep) {
182bf215546Sopenharmony_ci         const VkSubpassDependency2 implicit_outgoing_dep = {
183bf215546Sopenharmony_ci            .srcSubpass = i, /* last subpass attachment is used in */
184bf215546Sopenharmony_ci            .dstSubpass = VK_SUBPASS_EXTERNAL,
185bf215546Sopenharmony_ci            .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
186bf215546Sopenharmony_ci            .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
187bf215546Sopenharmony_ci            .srcAccessMask =
188bf215546Sopenharmony_ci               VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
189bf215546Sopenharmony_ci               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
190bf215546Sopenharmony_ci               VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
191bf215546Sopenharmony_ci            .dstAccessMask = 0,
192bf215546Sopenharmony_ci            .dependencyFlags = 0,
193bf215546Sopenharmony_ci         };
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci         radv_render_pass_add_subpass_dep(pass, &implicit_outgoing_dep);
196bf215546Sopenharmony_ci      }
197bf215546Sopenharmony_ci   }
198bf215546Sopenharmony_ci}
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_cistatic void
201bf215546Sopenharmony_ciradv_render_pass_compile(struct radv_render_pass *pass)
202bf215546Sopenharmony_ci{
203bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pass->subpass_count; i++) {
204bf215546Sopenharmony_ci      struct radv_subpass *subpass = &pass->subpasses[i];
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci      for (uint32_t j = 0; j < subpass->attachment_count; j++) {
207bf215546Sopenharmony_ci         struct radv_subpass_attachment *subpass_att = &subpass->attachments[j];
208bf215546Sopenharmony_ci         if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
209bf215546Sopenharmony_ci            continue;
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci         struct radv_render_pass_attachment *pass_att = &pass->attachments[subpass_att->attachment];
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci         pass_att->first_subpass_idx = VK_SUBPASS_EXTERNAL;
214bf215546Sopenharmony_ci         pass_att->last_subpass_idx = VK_SUBPASS_EXTERNAL;
215bf215546Sopenharmony_ci      }
216bf215546Sopenharmony_ci   }
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pass->subpass_count; i++) {
219bf215546Sopenharmony_ci      struct radv_subpass *subpass = &pass->subpasses[i];
220bf215546Sopenharmony_ci      uint32_t color_sample_count = 1, depth_sample_count = 1;
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci      /* We don't allow depth_stencil_attachment to be non-NULL and
223bf215546Sopenharmony_ci       * be VK_ATTACHMENT_UNUSED.  This way something can just check
224bf215546Sopenharmony_ci       * for NULL and be guaranteed that they have a valid
225bf215546Sopenharmony_ci       * attachment.
226bf215546Sopenharmony_ci       */
227bf215546Sopenharmony_ci      if (subpass->depth_stencil_attachment &&
228bf215546Sopenharmony_ci          subpass->depth_stencil_attachment->attachment == VK_ATTACHMENT_UNUSED)
229bf215546Sopenharmony_ci         subpass->depth_stencil_attachment = NULL;
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci      if (subpass->ds_resolve_attachment &&
232bf215546Sopenharmony_ci          subpass->ds_resolve_attachment->attachment == VK_ATTACHMENT_UNUSED)
233bf215546Sopenharmony_ci         subpass->ds_resolve_attachment = NULL;
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci      if (subpass->vrs_attachment && subpass->vrs_attachment->attachment == VK_ATTACHMENT_UNUSED)
236bf215546Sopenharmony_ci         subpass->vrs_attachment = NULL;
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci      for (uint32_t j = 0; j < subpass->attachment_count; j++) {
239bf215546Sopenharmony_ci         struct radv_subpass_attachment *subpass_att = &subpass->attachments[j];
240bf215546Sopenharmony_ci         if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
241bf215546Sopenharmony_ci            continue;
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci         struct radv_render_pass_attachment *pass_att = &pass->attachments[subpass_att->attachment];
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci         if (i < pass_att->first_subpass_idx)
246bf215546Sopenharmony_ci            pass_att->first_subpass_idx = i;
247bf215546Sopenharmony_ci         pass_att->last_subpass_idx = i;
248bf215546Sopenharmony_ci      }
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci      for (uint32_t j = 0; j < subpass->color_count; j++) {
251bf215546Sopenharmony_ci         struct radv_subpass_attachment *subpass_att = &subpass->color_attachments[j];
252bf215546Sopenharmony_ci         if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
253bf215546Sopenharmony_ci            continue;
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci         struct radv_render_pass_attachment *pass_att = &pass->attachments[subpass_att->attachment];
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci         color_sample_count = pass_att->samples;
259bf215546Sopenharmony_ci      }
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ci      if (subpass->depth_stencil_attachment) {
262bf215546Sopenharmony_ci         const uint32_t a = subpass->depth_stencil_attachment->attachment;
263bf215546Sopenharmony_ci         struct radv_render_pass_attachment *pass_att = &pass->attachments[a];
264bf215546Sopenharmony_ci         depth_sample_count = pass_att->samples;
265bf215546Sopenharmony_ci      }
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci      subpass->max_sample_count = MAX2(color_sample_count, depth_sample_count);
268bf215546Sopenharmony_ci      subpass->color_sample_count = color_sample_count;
269bf215546Sopenharmony_ci      subpass->depth_sample_count = depth_sample_count;
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci      /* We have to handle resolve attachments specially */
272bf215546Sopenharmony_ci      subpass->has_color_resolve = false;
273bf215546Sopenharmony_ci      if (subpass->resolve_attachments) {
274bf215546Sopenharmony_ci         for (uint32_t j = 0; j < subpass->color_count; j++) {
275bf215546Sopenharmony_ci            struct radv_subpass_attachment *resolve_att = &subpass->resolve_attachments[j];
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci            if (resolve_att->attachment == VK_ATTACHMENT_UNUSED)
278bf215546Sopenharmony_ci               continue;
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci            subpass->has_color_resolve = true;
281bf215546Sopenharmony_ci         }
282bf215546Sopenharmony_ci      }
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci      for (uint32_t j = 0; j < subpass->input_count; ++j) {
285bf215546Sopenharmony_ci         if (subpass->input_attachments[j].attachment == VK_ATTACHMENT_UNUSED)
286bf215546Sopenharmony_ci            continue;
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci         for (uint32_t k = 0; k < subpass->color_count; ++k) {
289bf215546Sopenharmony_ci            if (subpass->color_attachments[k].attachment ==
290bf215546Sopenharmony_ci                subpass->input_attachments[j].attachment) {
291bf215546Sopenharmony_ci               subpass->input_attachments[j].in_render_loop = true;
292bf215546Sopenharmony_ci               subpass->color_attachments[k].in_render_loop = true;
293bf215546Sopenharmony_ci            }
294bf215546Sopenharmony_ci         }
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci         if (subpass->depth_stencil_attachment && subpass->depth_stencil_attachment->attachment ==
297bf215546Sopenharmony_ci                                                     subpass->input_attachments[j].attachment) {
298bf215546Sopenharmony_ci            subpass->input_attachments[j].in_render_loop = true;
299bf215546Sopenharmony_ci            subpass->depth_stencil_attachment->in_render_loop = true;
300bf215546Sopenharmony_ci         }
301bf215546Sopenharmony_ci      }
302bf215546Sopenharmony_ci   }
303bf215546Sopenharmony_ci}
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_cistatic void
306bf215546Sopenharmony_ciradv_destroy_render_pass(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
307bf215546Sopenharmony_ci                         struct radv_render_pass *pass)
308bf215546Sopenharmony_ci{
309bf215546Sopenharmony_ci   vk_object_base_finish(&pass->base);
310bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, pass->subpass_attachments);
311bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, pass);
312bf215546Sopenharmony_ci}
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_cistatic unsigned
315bf215546Sopenharmony_ciradv_num_subpass_attachments2(const VkSubpassDescription2 *desc)
316bf215546Sopenharmony_ci{
317bf215546Sopenharmony_ci   const VkSubpassDescriptionDepthStencilResolve *ds_resolve =
318bf215546Sopenharmony_ci      vk_find_struct_const(desc->pNext, SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE);
319bf215546Sopenharmony_ci   const VkFragmentShadingRateAttachmentInfoKHR *vrs =
320bf215546Sopenharmony_ci      vk_find_struct_const(desc->pNext, FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR);
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci   return desc->inputAttachmentCount + desc->colorAttachmentCount +
323bf215546Sopenharmony_ci          (desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
324bf215546Sopenharmony_ci          (desc->pDepthStencilAttachment != NULL) +
325bf215546Sopenharmony_ci          (ds_resolve && ds_resolve->pDepthStencilResolveAttachment) +
326bf215546Sopenharmony_ci          (vrs && vrs->pFragmentShadingRateAttachment);
327bf215546Sopenharmony_ci}
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
330bf215546Sopenharmony_ciradv_CreateRenderPass2(VkDevice _device, const VkRenderPassCreateInfo2 *pCreateInfo,
331bf215546Sopenharmony_ci                       const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass)
332bf215546Sopenharmony_ci{
333bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
334bf215546Sopenharmony_ci   struct radv_render_pass *pass;
335bf215546Sopenharmony_ci   size_t size;
336bf215546Sopenharmony_ci   size_t attachments_offset;
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2);
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci   size = sizeof(*pass);
341bf215546Sopenharmony_ci   size += pCreateInfo->subpassCount * sizeof(pass->subpasses[0]);
342bf215546Sopenharmony_ci   attachments_offset = size;
343bf215546Sopenharmony_ci   size += pCreateInfo->attachmentCount * sizeof(pass->attachments[0]);
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   pass = vk_alloc2(&device->vk.alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
346bf215546Sopenharmony_ci   if (pass == NULL)
347bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci   memset(pass, 0, size);
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &pass->base, VK_OBJECT_TYPE_RENDER_PASS);
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci   pass->attachment_count = pCreateInfo->attachmentCount;
354bf215546Sopenharmony_ci   pass->subpass_count = pCreateInfo->subpassCount;
355bf215546Sopenharmony_ci   pass->attachments = (struct radv_render_pass_attachment *)((uint8_t *)pass + attachments_offset);
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
358bf215546Sopenharmony_ci      struct radv_render_pass_attachment *att = &pass->attachments[i];
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci      att->format = pCreateInfo->pAttachments[i].format;
361bf215546Sopenharmony_ci      att->samples = pCreateInfo->pAttachments[i].samples;
362bf215546Sopenharmony_ci      att->load_op = pCreateInfo->pAttachments[i].loadOp;
363bf215546Sopenharmony_ci      att->stencil_load_op = pCreateInfo->pAttachments[i].stencilLoadOp;
364bf215546Sopenharmony_ci      att->initial_layout = pCreateInfo->pAttachments[i].initialLayout;
365bf215546Sopenharmony_ci      att->final_layout = pCreateInfo->pAttachments[i].finalLayout;
366bf215546Sopenharmony_ci      att->stencil_initial_layout = vk_att_desc_stencil_layout(&pCreateInfo->pAttachments[i], false);
367bf215546Sopenharmony_ci      att->stencil_final_layout = vk_att_desc_stencil_layout(&pCreateInfo->pAttachments[i], true);
368bf215546Sopenharmony_ci      // att->store_op = pCreateInfo->pAttachments[i].storeOp;
369bf215546Sopenharmony_ci      // att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
370bf215546Sopenharmony_ci   }
371bf215546Sopenharmony_ci   uint32_t subpass_attachment_count = 0;
372bf215546Sopenharmony_ci   struct radv_subpass_attachment *p;
373bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
374bf215546Sopenharmony_ci      subpass_attachment_count += radv_num_subpass_attachments2(&pCreateInfo->pSubpasses[i]);
375bf215546Sopenharmony_ci   }
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_ci   if (subpass_attachment_count) {
378bf215546Sopenharmony_ci      pass->subpass_attachments =
379bf215546Sopenharmony_ci         vk_alloc2(&device->vk.alloc, pAllocator,
380bf215546Sopenharmony_ci                   subpass_attachment_count * sizeof(struct radv_subpass_attachment), 8,
381bf215546Sopenharmony_ci                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
382bf215546Sopenharmony_ci      if (pass->subpass_attachments == NULL) {
383bf215546Sopenharmony_ci         radv_destroy_render_pass(device, pAllocator, pass);
384bf215546Sopenharmony_ci         return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
385bf215546Sopenharmony_ci      }
386bf215546Sopenharmony_ci   } else
387bf215546Sopenharmony_ci      pass->subpass_attachments = NULL;
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci   p = pass->subpass_attachments;
390bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
391bf215546Sopenharmony_ci      const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[i];
392bf215546Sopenharmony_ci      struct radv_subpass *subpass = &pass->subpasses[i];
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci      subpass->input_count = desc->inputAttachmentCount;
395bf215546Sopenharmony_ci      subpass->color_count = desc->colorAttachmentCount;
396bf215546Sopenharmony_ci      subpass->attachment_count = radv_num_subpass_attachments2(desc);
397bf215546Sopenharmony_ci      subpass->attachments = p;
398bf215546Sopenharmony_ci      subpass->view_mask = desc->viewMask;
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci      if (desc->inputAttachmentCount > 0) {
401bf215546Sopenharmony_ci         subpass->input_attachments = p;
402bf215546Sopenharmony_ci         p += desc->inputAttachmentCount;
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_ci         for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) {
405bf215546Sopenharmony_ci            subpass->input_attachments[j] = (struct radv_subpass_attachment){
406bf215546Sopenharmony_ci               .attachment = desc->pInputAttachments[j].attachment,
407bf215546Sopenharmony_ci               .layout = desc->pInputAttachments[j].layout,
408bf215546Sopenharmony_ci               .stencil_layout = vk_att_ref_stencil_layout(&desc->pInputAttachments[j],
409bf215546Sopenharmony_ci                                                           pCreateInfo->pAttachments),
410bf215546Sopenharmony_ci            };
411bf215546Sopenharmony_ci         }
412bf215546Sopenharmony_ci      }
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci      if (desc->colorAttachmentCount > 0) {
415bf215546Sopenharmony_ci         subpass->color_attachments = p;
416bf215546Sopenharmony_ci         p += desc->colorAttachmentCount;
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci         for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
419bf215546Sopenharmony_ci            subpass->color_attachments[j] = (struct radv_subpass_attachment){
420bf215546Sopenharmony_ci               .attachment = desc->pColorAttachments[j].attachment,
421bf215546Sopenharmony_ci               .layout = desc->pColorAttachments[j].layout,
422bf215546Sopenharmony_ci            };
423bf215546Sopenharmony_ci         }
424bf215546Sopenharmony_ci      }
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci      if (desc->pResolveAttachments) {
427bf215546Sopenharmony_ci         subpass->resolve_attachments = p;
428bf215546Sopenharmony_ci         p += desc->colorAttachmentCount;
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci         for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
431bf215546Sopenharmony_ci            subpass->resolve_attachments[j] = (struct radv_subpass_attachment){
432bf215546Sopenharmony_ci               .attachment = desc->pResolveAttachments[j].attachment,
433bf215546Sopenharmony_ci               .layout = desc->pResolveAttachments[j].layout,
434bf215546Sopenharmony_ci            };
435bf215546Sopenharmony_ci         }
436bf215546Sopenharmony_ci      }
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_ci      if (desc->pDepthStencilAttachment) {
439bf215546Sopenharmony_ci         subpass->depth_stencil_attachment = p++;
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_ci         *subpass->depth_stencil_attachment = (struct radv_subpass_attachment){
442bf215546Sopenharmony_ci            .attachment = desc->pDepthStencilAttachment->attachment,
443bf215546Sopenharmony_ci            .layout = desc->pDepthStencilAttachment->layout,
444bf215546Sopenharmony_ci            .stencil_layout = vk_att_ref_stencil_layout(desc->pDepthStencilAttachment,
445bf215546Sopenharmony_ci                                                        pCreateInfo->pAttachments),
446bf215546Sopenharmony_ci         };
447bf215546Sopenharmony_ci      }
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci      const VkSubpassDescriptionDepthStencilResolve *ds_resolve =
450bf215546Sopenharmony_ci         vk_find_struct_const(desc->pNext, SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE);
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci      if (ds_resolve && ds_resolve->pDepthStencilResolveAttachment) {
453bf215546Sopenharmony_ci         subpass->ds_resolve_attachment = p++;
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci         *subpass->ds_resolve_attachment = (struct radv_subpass_attachment){
456bf215546Sopenharmony_ci            .attachment = ds_resolve->pDepthStencilResolveAttachment->attachment,
457bf215546Sopenharmony_ci            .layout = ds_resolve->pDepthStencilResolveAttachment->layout,
458bf215546Sopenharmony_ci            .stencil_layout = vk_att_ref_stencil_layout(ds_resolve->pDepthStencilResolveAttachment,
459bf215546Sopenharmony_ci                                                        pCreateInfo->pAttachments),
460bf215546Sopenharmony_ci         };
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci         subpass->depth_resolve_mode = ds_resolve->depthResolveMode;
463bf215546Sopenharmony_ci         subpass->stencil_resolve_mode = ds_resolve->stencilResolveMode;
464bf215546Sopenharmony_ci      }
465bf215546Sopenharmony_ci
466bf215546Sopenharmony_ci      const VkFragmentShadingRateAttachmentInfoKHR *vrs =
467bf215546Sopenharmony_ci         vk_find_struct_const(desc->pNext, FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR);
468bf215546Sopenharmony_ci
469bf215546Sopenharmony_ci      if (vrs && vrs->pFragmentShadingRateAttachment) {
470bf215546Sopenharmony_ci         subpass->vrs_attachment = p++;
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_ci         *subpass->vrs_attachment = (struct radv_subpass_attachment){
473bf215546Sopenharmony_ci            .attachment = vrs->pFragmentShadingRateAttachment->attachment,
474bf215546Sopenharmony_ci            .layout = vrs->pFragmentShadingRateAttachment->layout,
475bf215546Sopenharmony_ci         };
476bf215546Sopenharmony_ci      }
477bf215546Sopenharmony_ci   }
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   for (unsigned i = 0; i < pCreateInfo->dependencyCount; ++i) {
480bf215546Sopenharmony_ci      const VkSubpassDependency2 *dep = &pCreateInfo->pDependencies[i];
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci      radv_render_pass_add_subpass_dep(pass, &pCreateInfo->pDependencies[i]);
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci      /* Determine if the subpass has explicit dependencies from/to
485bf215546Sopenharmony_ci       * VK_SUBPASS_EXTERNAL.
486bf215546Sopenharmony_ci       */
487bf215546Sopenharmony_ci      if (dep->srcSubpass == VK_SUBPASS_EXTERNAL && dep->dstSubpass != VK_SUBPASS_EXTERNAL) {
488bf215546Sopenharmony_ci         pass->subpasses[dep->dstSubpass].has_ingoing_dep = true;
489bf215546Sopenharmony_ci      }
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci      if (dep->dstSubpass == VK_SUBPASS_EXTERNAL && dep->srcSubpass != VK_SUBPASS_EXTERNAL) {
492bf215546Sopenharmony_ci         pass->subpasses[dep->srcSubpass].has_outgoing_dep = true;
493bf215546Sopenharmony_ci      }
494bf215546Sopenharmony_ci   }
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci   radv_render_pass_compile(pass);
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci   radv_render_pass_add_implicit_deps(pass);
499bf215546Sopenharmony_ci
500bf215546Sopenharmony_ci   *pRenderPass = radv_render_pass_to_handle(pass);
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci   return VK_SUCCESS;
503bf215546Sopenharmony_ci}
504bf215546Sopenharmony_ci
505bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
506bf215546Sopenharmony_ciradv_DestroyRenderPass(VkDevice _device, VkRenderPass _pass,
507bf215546Sopenharmony_ci                       const VkAllocationCallbacks *pAllocator)
508bf215546Sopenharmony_ci{
509bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
510bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_render_pass, pass, _pass);
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_ci   if (!_pass)
513bf215546Sopenharmony_ci      return;
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci   radv_destroy_render_pass(device, pAllocator, pass);
516bf215546Sopenharmony_ci}
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
519bf215546Sopenharmony_ciradv_GetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D *pGranularity)
520bf215546Sopenharmony_ci{
521bf215546Sopenharmony_ci   pGranularity->width = 1;
522bf215546Sopenharmony_ci   pGranularity->height = 1;
523bf215546Sopenharmony_ci}
524