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