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