1 /*
2 * Copyright © 2020 Valve 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 "vk_render_pass.h"
25
26 #include "vk_alloc.h"
27 #include "vk_command_buffer.h"
28 #include "vk_common_entrypoints.h"
29 #include "vk_device.h"
30 #include "vk_format.h"
31 #include "vk_framebuffer.h"
32 #include "vk_image.h"
33 #include "vk_util.h"
34
35 #include "util/log.h"
36
37 static void
translate_references(VkAttachmentReference2 ** reference_ptr,uint32_t reference_count,const VkAttachmentReference * reference,const VkRenderPassCreateInfo * pass_info,bool is_input_attachment)38 translate_references(VkAttachmentReference2 **reference_ptr,
39 uint32_t reference_count,
40 const VkAttachmentReference *reference,
41 const VkRenderPassCreateInfo *pass_info,
42 bool is_input_attachment)
43 {
44 VkAttachmentReference2 *reference2 = *reference_ptr;
45 *reference_ptr += reference_count;
46 for (uint32_t i = 0; i < reference_count; i++) {
47 reference2[i] = (VkAttachmentReference2) {
48 .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
49 .pNext = NULL,
50 .attachment = reference[i].attachment,
51 .layout = reference[i].layout,
52 };
53
54 if (is_input_attachment &&
55 reference2[i].attachment != VK_ATTACHMENT_UNUSED) {
56 assert(reference2[i].attachment < pass_info->attachmentCount);
57 const VkAttachmentDescription *att =
58 &pass_info->pAttachments[reference2[i].attachment];
59 reference2[i].aspectMask = vk_format_aspects(att->format);
60 }
61 }
62 }
63
64 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateRenderPass(VkDevice _device,const VkRenderPassCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass)65 vk_common_CreateRenderPass(VkDevice _device,
66 const VkRenderPassCreateInfo *pCreateInfo,
67 const VkAllocationCallbacks *pAllocator,
68 VkRenderPass *pRenderPass)
69 {
70 VK_FROM_HANDLE(vk_device, device, _device);
71
72 uint32_t reference_count = 0;
73 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
74 reference_count += pCreateInfo->pSubpasses[i].inputAttachmentCount;
75 reference_count += pCreateInfo->pSubpasses[i].colorAttachmentCount;
76 if (pCreateInfo->pSubpasses[i].pResolveAttachments)
77 reference_count += pCreateInfo->pSubpasses[i].colorAttachmentCount;
78 if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment)
79 reference_count += 1;
80 }
81
82 VK_MULTIALLOC(ma);
83 VK_MULTIALLOC_DECL(&ma, VkRenderPassCreateInfo2, create_info, 1);
84 VK_MULTIALLOC_DECL(&ma, VkSubpassDescription2, subpasses,
85 pCreateInfo->subpassCount);
86 VK_MULTIALLOC_DECL(&ma, VkAttachmentDescription2, attachments,
87 pCreateInfo->attachmentCount);
88 VK_MULTIALLOC_DECL(&ma, VkSubpassDependency2, dependencies,
89 pCreateInfo->dependencyCount);
90 VK_MULTIALLOC_DECL(&ma, VkAttachmentReference2, references,
91 reference_count);
92 if (!vk_multialloc_alloc2(&ma, &device->alloc, pAllocator,
93 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND))
94 return VK_ERROR_OUT_OF_HOST_MEMORY;
95
96 VkAttachmentReference2 *reference_ptr = references;
97
98 const VkRenderPassMultiviewCreateInfo *multiview_info = NULL;
99 const VkRenderPassInputAttachmentAspectCreateInfo *aspect_info = NULL;
100 vk_foreach_struct_const(ext, pCreateInfo->pNext) {
101 switch (ext->sType) {
102 case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO:
103 aspect_info = (const VkRenderPassInputAttachmentAspectCreateInfo *)ext;
104 /* We don't care about this information */
105 break;
106
107 case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
108 multiview_info = (const VkRenderPassMultiviewCreateInfo*) ext;
109 break;
110
111 case VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT:
112 /* pass this through to CreateRenderPass2 */
113 break;
114
115 default:
116 mesa_logd("%s: ignored VkStructureType %u\n", __func__, ext->sType);
117 break;
118 }
119 }
120
121 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
122 attachments[i] = (VkAttachmentDescription2) {
123 .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
124 .pNext = NULL,
125 .flags = pCreateInfo->pAttachments[i].flags,
126 .format = pCreateInfo->pAttachments[i].format,
127 .samples = pCreateInfo->pAttachments[i].samples,
128 .loadOp = pCreateInfo->pAttachments[i].loadOp,
129 .storeOp = pCreateInfo->pAttachments[i].storeOp,
130 .stencilLoadOp = pCreateInfo->pAttachments[i].stencilLoadOp,
131 .stencilStoreOp = pCreateInfo->pAttachments[i].stencilStoreOp,
132 .initialLayout = pCreateInfo->pAttachments[i].initialLayout,
133 .finalLayout = pCreateInfo->pAttachments[i].finalLayout,
134 };
135 }
136
137 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
138 subpasses[i] = (VkSubpassDescription2) {
139 .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
140 .pNext = NULL,
141 .flags = pCreateInfo->pSubpasses[i].flags,
142 .pipelineBindPoint = pCreateInfo->pSubpasses[i].pipelineBindPoint,
143 .viewMask = 0,
144 .inputAttachmentCount = pCreateInfo->pSubpasses[i].inputAttachmentCount,
145 .colorAttachmentCount = pCreateInfo->pSubpasses[i].colorAttachmentCount,
146 .preserveAttachmentCount = pCreateInfo->pSubpasses[i].preserveAttachmentCount,
147 .pPreserveAttachments = pCreateInfo->pSubpasses[i].pPreserveAttachments,
148 };
149
150 if (multiview_info && multiview_info->subpassCount) {
151 assert(multiview_info->subpassCount == pCreateInfo->subpassCount);
152 subpasses[i].viewMask = multiview_info->pViewMasks[i];
153 }
154
155 subpasses[i].pInputAttachments = reference_ptr;
156 translate_references(&reference_ptr,
157 subpasses[i].inputAttachmentCount,
158 pCreateInfo->pSubpasses[i].pInputAttachments,
159 pCreateInfo, true);
160 subpasses[i].pColorAttachments = reference_ptr;
161 translate_references(&reference_ptr,
162 subpasses[i].colorAttachmentCount,
163 pCreateInfo->pSubpasses[i].pColorAttachments,
164 pCreateInfo, false);
165 subpasses[i].pResolveAttachments = NULL;
166 if (pCreateInfo->pSubpasses[i].pResolveAttachments) {
167 subpasses[i].pResolveAttachments = reference_ptr;
168 translate_references(&reference_ptr,
169 subpasses[i].colorAttachmentCount,
170 pCreateInfo->pSubpasses[i].pResolveAttachments,
171 pCreateInfo, false);
172 }
173 subpasses[i].pDepthStencilAttachment = NULL;
174 if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment) {
175 subpasses[i].pDepthStencilAttachment = reference_ptr;
176 translate_references(&reference_ptr, 1,
177 pCreateInfo->pSubpasses[i].pDepthStencilAttachment,
178 pCreateInfo, false);
179 }
180 }
181
182 assert(reference_ptr == references + reference_count);
183
184 if (aspect_info != NULL) {
185 for (uint32_t i = 0; i < aspect_info->aspectReferenceCount; i++) {
186 const VkInputAttachmentAspectReference *ref =
187 &aspect_info->pAspectReferences[i];
188
189 assert(ref->subpass < pCreateInfo->subpassCount);
190 VkSubpassDescription2 *subpass = &subpasses[ref->subpass];
191
192 assert(ref->inputAttachmentIndex < subpass->inputAttachmentCount);
193 VkAttachmentReference2 *att = (VkAttachmentReference2 *)
194 &subpass->pInputAttachments[ref->inputAttachmentIndex];
195
196 att->aspectMask = ref->aspectMask;
197 }
198 }
199
200 for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
201 dependencies[i] = (VkSubpassDependency2) {
202 .sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
203 .pNext = NULL,
204 .srcSubpass = pCreateInfo->pDependencies[i].srcSubpass,
205 .dstSubpass = pCreateInfo->pDependencies[i].dstSubpass,
206 .srcStageMask = pCreateInfo->pDependencies[i].srcStageMask,
207 .dstStageMask = pCreateInfo->pDependencies[i].dstStageMask,
208 .srcAccessMask = pCreateInfo->pDependencies[i].srcAccessMask,
209 .dstAccessMask = pCreateInfo->pDependencies[i].dstAccessMask,
210 .dependencyFlags = pCreateInfo->pDependencies[i].dependencyFlags,
211 .viewOffset = 0,
212 };
213
214 if (multiview_info && multiview_info->dependencyCount) {
215 assert(multiview_info->dependencyCount == pCreateInfo->dependencyCount);
216 dependencies[i].viewOffset = multiview_info->pViewOffsets[i];
217 }
218 }
219
220 *create_info = (VkRenderPassCreateInfo2) {
221 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
222 .pNext = pCreateInfo->pNext,
223 .flags = pCreateInfo->flags,
224 .attachmentCount = pCreateInfo->attachmentCount,
225 .pAttachments = attachments,
226 .subpassCount = pCreateInfo->subpassCount,
227 .pSubpasses = subpasses,
228 .dependencyCount = pCreateInfo->dependencyCount,
229 .pDependencies = dependencies,
230 };
231
232 if (multiview_info && multiview_info->correlationMaskCount > 0) {
233 create_info->correlatedViewMaskCount = multiview_info->correlationMaskCount;
234 create_info->pCorrelatedViewMasks = multiview_info->pCorrelationMasks;
235 }
236
237 VkResult result =
238 device->dispatch_table.CreateRenderPass2(_device, create_info,
239 pAllocator, pRenderPass);
240
241 vk_free2(&device->alloc, pAllocator, create_info);
242
243 return result;
244 }
245
246 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBeginRenderPass(VkCommandBuffer commandBuffer,const VkRenderPassBeginInfo * pRenderPassBegin,VkSubpassContents contents)247 vk_common_CmdBeginRenderPass(VkCommandBuffer commandBuffer,
248 const VkRenderPassBeginInfo* pRenderPassBegin,
249 VkSubpassContents contents)
250 {
251 /* We don't have a vk_command_buffer object but we can assume, since we're
252 * using common dispatch, that it's a vk_object of some sort.
253 */
254 struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
255
256 VkSubpassBeginInfo info = {
257 .sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
258 .contents = contents,
259 };
260
261 disp->device->dispatch_table.CmdBeginRenderPass2(commandBuffer,
262 pRenderPassBegin, &info);
263 }
264
265 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdEndRenderPass(VkCommandBuffer commandBuffer)266 vk_common_CmdEndRenderPass(VkCommandBuffer commandBuffer)
267 {
268 /* We don't have a vk_command_buffer object but we can assume, since we're
269 * using common dispatch, that it's a vk_object of some sort.
270 */
271 struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
272
273 VkSubpassEndInfo info = {
274 .sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
275 };
276
277 disp->device->dispatch_table.CmdEndRenderPass2(commandBuffer, &info);
278 }
279
280 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdNextSubpass(VkCommandBuffer commandBuffer,VkSubpassContents contents)281 vk_common_CmdNextSubpass(VkCommandBuffer commandBuffer,
282 VkSubpassContents contents)
283 {
284 /* We don't have a vk_command_buffer object but we can assume, since we're
285 * using common dispatch, that it's a vk_object of some sort.
286 */
287 struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
288
289 VkSubpassBeginInfo begin_info = {
290 .sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
291 .contents = contents,
292 };
293
294 VkSubpassEndInfo end_info = {
295 .sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
296 };
297
298 disp->device->dispatch_table.CmdNextSubpass2(commandBuffer, &begin_info,
299 &end_info);
300 }
301
302 static unsigned
num_subpass_attachments2(const VkSubpassDescription2 * desc)303 num_subpass_attachments2(const VkSubpassDescription2 *desc)
304 {
305 bool has_depth_stencil_attachment =
306 desc->pDepthStencilAttachment != NULL &&
307 desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED;
308
309 const VkSubpassDescriptionDepthStencilResolve *ds_resolve =
310 vk_find_struct_const(desc->pNext,
311 SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE);
312
313 bool has_depth_stencil_resolve_attachment =
314 ds_resolve != NULL && ds_resolve->pDepthStencilResolveAttachment &&
315 ds_resolve->pDepthStencilResolveAttachment->attachment != VK_ATTACHMENT_UNUSED;
316
317 const VkFragmentShadingRateAttachmentInfoKHR *fsr_att_info =
318 vk_find_struct_const(desc->pNext,
319 FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR);
320
321 bool has_fragment_shading_rate_attachment =
322 fsr_att_info && fsr_att_info->pFragmentShadingRateAttachment &&
323 fsr_att_info->pFragmentShadingRateAttachment->attachment != VK_ATTACHMENT_UNUSED;
324
325 return desc->inputAttachmentCount +
326 desc->colorAttachmentCount +
327 (desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
328 has_depth_stencil_attachment +
329 has_depth_stencil_resolve_attachment +
330 has_fragment_shading_rate_attachment;
331 }
332
333 static void
vk_render_pass_attachment_init(struct vk_render_pass_attachment * att,const VkAttachmentDescription2 * desc)334 vk_render_pass_attachment_init(struct vk_render_pass_attachment *att,
335 const VkAttachmentDescription2 *desc)
336 {
337 *att = (struct vk_render_pass_attachment) {
338 .format = desc->format,
339 .aspects = vk_format_aspects(desc->format),
340 .samples = desc->samples,
341 .view_mask = 0,
342 .load_op = desc->loadOp,
343 .store_op = desc->storeOp,
344 .stencil_load_op = desc->stencilLoadOp,
345 .stencil_store_op = desc->stencilStoreOp,
346 .initial_layout = desc->initialLayout,
347 .final_layout = desc->finalLayout,
348 .initial_stencil_layout = vk_att_desc_stencil_layout(desc, false),
349 .final_stencil_layout = vk_att_desc_stencil_layout(desc, true),
350 };
351 }
352
353 static void
vk_subpass_attachment_init(struct vk_subpass_attachment * att,struct vk_render_pass * pass,uint32_t subpass_idx,const VkAttachmentReference2 * ref,const VkAttachmentDescription2 * attachments,VkImageUsageFlagBits usage)354 vk_subpass_attachment_init(struct vk_subpass_attachment *att,
355 struct vk_render_pass *pass,
356 uint32_t subpass_idx,
357 const VkAttachmentReference2 *ref,
358 const VkAttachmentDescription2 *attachments,
359 VkImageUsageFlagBits usage)
360 {
361 if (ref->attachment >= pass->attachment_count) {
362 assert(ref->attachment == VK_ATTACHMENT_UNUSED);
363 *att = (struct vk_subpass_attachment) {
364 .attachment = VK_ATTACHMENT_UNUSED,
365 };
366 return;
367 }
368
369 struct vk_render_pass_attachment *pass_att =
370 &pass->attachments[ref->attachment];
371
372 *att = (struct vk_subpass_attachment) {
373 .attachment = ref->attachment,
374 .aspects = vk_format_aspects(pass_att->format),
375 .usage = usage,
376 .layout = ref->layout,
377 .stencil_layout = vk_att_ref_stencil_layout(ref, attachments),
378 };
379
380 switch (usage) {
381 case VK_IMAGE_USAGE_TRANSFER_DST_BIT:
382 break; /* No special aspect requirements */
383
384 case VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT:
385 /* From the Vulkan 1.2.184 spec:
386 *
387 * "aspectMask is ignored when this structure is used to describe
388 * anything other than an input attachment reference."
389 */
390 assert(!(ref->aspectMask & ~att->aspects));
391 att->aspects = ref->aspectMask;
392 break;
393
394 case VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:
395 case VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR:
396 assert(att->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
397 break;
398
399 case VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT:
400 assert(!(att->aspects & ~(VK_IMAGE_ASPECT_DEPTH_BIT |
401 VK_IMAGE_ASPECT_STENCIL_BIT)));
402 break;
403
404 default:
405 unreachable("Invalid subpass attachment usage");
406 }
407 }
408
409 static void
vk_subpass_attachment_link_resolve(struct vk_subpass_attachment * att,struct vk_subpass_attachment * resolve,const VkRenderPassCreateInfo2 * info)410 vk_subpass_attachment_link_resolve(struct vk_subpass_attachment *att,
411 struct vk_subpass_attachment *resolve,
412 const VkRenderPassCreateInfo2 *info)
413 {
414 if (resolve->attachment == VK_ATTACHMENT_UNUSED)
415 return;
416
417 assert(att->attachment != VK_ATTACHMENT_UNUSED);
418 att->resolve = resolve;
419 }
420
421 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateRenderPass2(VkDevice _device,const VkRenderPassCreateInfo2 * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass)422 vk_common_CreateRenderPass2(VkDevice _device,
423 const VkRenderPassCreateInfo2 *pCreateInfo,
424 const VkAllocationCallbacks *pAllocator,
425 VkRenderPass *pRenderPass)
426 {
427 VK_FROM_HANDLE(vk_device, device, _device);
428
429 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2);
430
431 VK_MULTIALLOC(ma);
432 VK_MULTIALLOC_DECL(&ma, struct vk_render_pass, pass, 1);
433 VK_MULTIALLOC_DECL(&ma, struct vk_render_pass_attachment, attachments,
434 pCreateInfo->attachmentCount);
435 VK_MULTIALLOC_DECL(&ma, struct vk_subpass, subpasses,
436 pCreateInfo->subpassCount);
437 VK_MULTIALLOC_DECL(&ma, struct vk_subpass_dependency, dependencies,
438 pCreateInfo->dependencyCount);
439
440 uint32_t subpass_attachment_count = 0;
441 uint32_t subpass_color_attachment_count = 0;
442 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
443 subpass_attachment_count +=
444 num_subpass_attachments2(&pCreateInfo->pSubpasses[i]);
445 subpass_color_attachment_count +=
446 pCreateInfo->pSubpasses[i].colorAttachmentCount;
447 }
448 VK_MULTIALLOC_DECL(&ma, struct vk_subpass_attachment, subpass_attachments,
449 subpass_attachment_count);
450 VK_MULTIALLOC_DECL(&ma, VkFormat, subpass_color_formats,
451 subpass_color_attachment_count);
452 VK_MULTIALLOC_DECL(&ma, VkSampleCountFlagBits, subpass_color_samples,
453 subpass_color_attachment_count);
454
455 if (!vk_object_multizalloc(device, &ma, pAllocator,
456 VK_OBJECT_TYPE_RENDER_PASS))
457 return VK_ERROR_OUT_OF_HOST_MEMORY;
458
459 pass->attachment_count = pCreateInfo->attachmentCount;
460 pass->attachments = attachments;
461 pass->subpass_count = pCreateInfo->subpassCount;
462 pass->subpasses = subpasses;
463 pass->dependency_count = pCreateInfo->dependencyCount;
464 pass->dependencies = dependencies;
465
466 for (uint32_t a = 0; a < pCreateInfo->attachmentCount; a++) {
467 vk_render_pass_attachment_init(&pass->attachments[a],
468 &pCreateInfo->pAttachments[a]);
469 }
470
471 struct vk_subpass_attachment *next_subpass_attachment = subpass_attachments;
472 VkFormat *next_subpass_color_format = subpass_color_formats;
473 VkSampleCountFlagBits *next_subpass_color_samples = subpass_color_samples;
474 for (uint32_t s = 0; s < pCreateInfo->subpassCount; s++) {
475 const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[s];
476 struct vk_subpass *subpass = &pass->subpasses[s];
477 const VkMultisampledRenderToSingleSampledInfoEXT *mrtss =
478 vk_find_struct_const(desc->pNext, MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT);
479 if (mrtss && !mrtss->multisampledRenderToSingleSampledEnable)
480 mrtss = NULL;
481
482 subpass->attachment_count = num_subpass_attachments2(desc);
483 subpass->attachments = next_subpass_attachment;
484
485 /* From the Vulkan 1.3.204 spec:
486 *
487 * VUID-VkRenderPassCreateInfo2-viewMask-03058
488 *
489 * "The VkSubpassDescription2::viewMask member of all elements of
490 * pSubpasses must either all be 0, or all not be 0"
491 */
492 if (desc->viewMask)
493 pass->is_multiview = true;
494 assert(pass->is_multiview == (desc->viewMask != 0));
495
496 /* For all view masks in the vk_render_pass data structure, we use a
497 * mask of 1 for non-multiview instead of a mask of 0.
498 */
499 subpass->view_mask = desc->viewMask ? desc->viewMask : 1;
500 pass->view_mask |= subpass->view_mask;
501
502 subpass->input_count = desc->inputAttachmentCount;
503 if (desc->inputAttachmentCount > 0) {
504 subpass->input_attachments = next_subpass_attachment;
505 next_subpass_attachment += desc->inputAttachmentCount;
506
507 for (uint32_t a = 0; a < desc->inputAttachmentCount; a++) {
508 vk_subpass_attachment_init(&subpass->input_attachments[a],
509 pass, s,
510 &desc->pInputAttachments[a],
511 pCreateInfo->pAttachments,
512 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
513 }
514 }
515
516 subpass->color_count = desc->colorAttachmentCount;
517 if (desc->colorAttachmentCount > 0) {
518 subpass->color_attachments = next_subpass_attachment;
519 next_subpass_attachment += desc->colorAttachmentCount;
520
521 for (uint32_t a = 0; a < desc->colorAttachmentCount; a++) {
522 vk_subpass_attachment_init(&subpass->color_attachments[a],
523 pass, s,
524 &desc->pColorAttachments[a],
525 pCreateInfo->pAttachments,
526 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
527 }
528 }
529
530 if (desc->pResolveAttachments) {
531 subpass->color_resolve_count = desc->colorAttachmentCount;
532 subpass->color_resolve_attachments = next_subpass_attachment;
533 next_subpass_attachment += desc->colorAttachmentCount;
534
535 for (uint32_t a = 0; a < desc->colorAttachmentCount; a++) {
536 vk_subpass_attachment_init(&subpass->color_resolve_attachments[a],
537 pass, s,
538 &desc->pResolveAttachments[a],
539 pCreateInfo->pAttachments,
540 VK_IMAGE_USAGE_TRANSFER_DST_BIT);
541 vk_subpass_attachment_link_resolve(&subpass->color_attachments[a],
542 &subpass->color_resolve_attachments[a],
543 pCreateInfo);
544 }
545 }
546
547 if (desc->pDepthStencilAttachment &&
548 desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
549 subpass->depth_stencil_attachment = next_subpass_attachment++;
550
551 vk_subpass_attachment_init(subpass->depth_stencil_attachment,
552 pass, s,
553 desc->pDepthStencilAttachment,
554 pCreateInfo->pAttachments,
555 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
556 }
557
558 const VkSubpassDescriptionDepthStencilResolve *ds_resolve =
559 vk_find_struct_const(desc->pNext,
560 SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE);
561
562 if (ds_resolve) {
563 if (ds_resolve->pDepthStencilResolveAttachment &&
564 ds_resolve->pDepthStencilResolveAttachment->attachment != VK_ATTACHMENT_UNUSED) {
565 subpass->depth_stencil_resolve_attachment = next_subpass_attachment++;
566
567 vk_subpass_attachment_init(subpass->depth_stencil_resolve_attachment,
568 pass, s,
569 ds_resolve->pDepthStencilResolveAttachment,
570 pCreateInfo->pAttachments,
571 VK_IMAGE_USAGE_TRANSFER_DST_BIT);
572 vk_subpass_attachment_link_resolve(subpass->depth_stencil_attachment,
573 subpass->depth_stencil_resolve_attachment,
574 pCreateInfo);
575 }
576 if (subpass->depth_stencil_resolve_attachment || mrtss) {
577 /* From the Vulkan 1.3.204 spec:
578 *
579 * VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03178
580 *
581 * "If pDepthStencilResolveAttachment is not NULL and does not
582 * have the value VK_ATTACHMENT_UNUSED, depthResolveMode and
583 * stencilResolveMode must not both be VK_RESOLVE_MODE_NONE"
584 */
585 assert(ds_resolve->depthResolveMode != VK_RESOLVE_MODE_NONE ||
586 ds_resolve->stencilResolveMode != VK_RESOLVE_MODE_NONE);
587
588 subpass->depth_resolve_mode = ds_resolve->depthResolveMode;
589 subpass->stencil_resolve_mode = ds_resolve->stencilResolveMode;
590 }
591 }
592
593 const VkFragmentShadingRateAttachmentInfoKHR *fsr_att_info =
594 vk_find_struct_const(desc->pNext,
595 FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR);
596
597 if (fsr_att_info && fsr_att_info->pFragmentShadingRateAttachment &&
598 fsr_att_info->pFragmentShadingRateAttachment->attachment != VK_ATTACHMENT_UNUSED) {
599 subpass->fragment_shading_rate_attachment = next_subpass_attachment++;
600 vk_subpass_attachment_init(subpass->fragment_shading_rate_attachment,
601 pass, s,
602 fsr_att_info->pFragmentShadingRateAttachment,
603 pCreateInfo->pAttachments,
604 VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR);
605 subpass->fragment_shading_rate_attachment_texel_size =
606 fsr_att_info->shadingRateAttachmentTexelSize;
607 subpass->pipeline_flags |=
608 VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
609 }
610
611 /* Figure out any self-dependencies */
612 assert(desc->colorAttachmentCount <= 32);
613 for (uint32_t a = 0; a < desc->inputAttachmentCount; a++) {
614 if (desc->pInputAttachments[a].attachment == VK_ATTACHMENT_UNUSED)
615 continue;
616
617 for (uint32_t c = 0; c < desc->colorAttachmentCount; c++) {
618 if (desc->pColorAttachments[c].attachment ==
619 desc->pInputAttachments[a].attachment) {
620 subpass->input_attachments[a].layout =
621 VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
622 subpass->color_attachments[c].layout =
623 VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
624 subpass->pipeline_flags |=
625 VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
626 }
627 }
628
629 if (desc->pDepthStencilAttachment != NULL &&
630 desc->pDepthStencilAttachment->attachment ==
631 desc->pInputAttachments[a].attachment) {
632 VkImageAspectFlags aspects =
633 subpass->input_attachments[a].aspects;
634 if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
635 subpass->input_attachments[a].layout =
636 VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
637 subpass->depth_stencil_attachment->layout =
638 VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
639 subpass->pipeline_flags |=
640 VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
641 }
642 if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
643 subpass->input_attachments[a].stencil_layout =
644 VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
645 subpass->depth_stencil_attachment->stencil_layout =
646 VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
647 subpass->pipeline_flags |=
648 VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
649 }
650 }
651 }
652
653 VkFormat *color_formats = NULL;
654 VkSampleCountFlagBits *color_samples = NULL;
655 VkSampleCountFlagBits samples = 0;
656 if (desc->colorAttachmentCount > 0) {
657 color_formats = next_subpass_color_format;
658 color_samples = next_subpass_color_samples;
659 for (uint32_t a = 0; a < desc->colorAttachmentCount; a++) {
660 const VkAttachmentReference2 *ref = &desc->pColorAttachments[a];
661 if (ref->attachment >= pCreateInfo->attachmentCount) {
662 color_formats[a] = VK_FORMAT_UNDEFINED;
663 color_samples[a] = VK_SAMPLE_COUNT_1_BIT;
664 } else {
665 const VkAttachmentDescription2 *att =
666 &pCreateInfo->pAttachments[ref->attachment];
667
668 color_formats[a] = att->format;
669 color_samples[a] = att->samples;
670
671 samples |= att->samples;
672 }
673 }
674 next_subpass_color_format += desc->colorAttachmentCount;
675 next_subpass_color_samples += desc->colorAttachmentCount;
676 }
677
678 VkFormat depth_format = VK_FORMAT_UNDEFINED;
679 VkFormat stencil_format = VK_FORMAT_UNDEFINED;
680 VkSampleCountFlagBits depth_stencil_samples = VK_SAMPLE_COUNT_1_BIT;
681 if (desc->pDepthStencilAttachment != NULL) {
682 const VkAttachmentReference2 *ref = desc->pDepthStencilAttachment;
683 if (ref->attachment < pCreateInfo->attachmentCount) {
684 const VkAttachmentDescription2 *att =
685 &pCreateInfo->pAttachments[ref->attachment];
686
687 if (vk_format_has_depth(att->format))
688 depth_format = att->format;
689 if (vk_format_has_stencil(att->format))
690 stencil_format = att->format;
691
692 depth_stencil_samples = att->samples;
693
694 samples |= att->samples;
695 }
696 }
697
698 subpass->sample_count_info_amd = (VkAttachmentSampleCountInfoAMD) {
699 .sType = VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD,
700 .pNext = NULL,
701 .colorAttachmentCount = desc->colorAttachmentCount,
702 .pColorAttachmentSamples = color_samples,
703 .depthStencilAttachmentSamples = depth_stencil_samples,
704 };
705
706 subpass->pipeline_info = (VkPipelineRenderingCreateInfo) {
707 .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
708 .pNext = &subpass->sample_count_info_amd,
709 .viewMask = desc->viewMask,
710 .colorAttachmentCount = desc->colorAttachmentCount,
711 .pColorAttachmentFormats = color_formats,
712 .depthAttachmentFormat = depth_format,
713 .stencilAttachmentFormat = stencil_format,
714 };
715
716 subpass->inheritance_info = (VkCommandBufferInheritanceRenderingInfo) {
717 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO,
718 .pNext = &subpass->sample_count_info_amd,
719 /* If we're inheriting, the contents are clearly in secondaries */
720 .flags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT,
721 .viewMask = desc->viewMask,
722 .colorAttachmentCount = desc->colorAttachmentCount,
723 .pColorAttachmentFormats = color_formats,
724 .depthAttachmentFormat = depth_format,
725 .stencilAttachmentFormat = stencil_format,
726 .rasterizationSamples = samples,
727 };
728
729 if (mrtss) {
730 assert(mrtss->multisampledRenderToSingleSampledEnable);
731 subpass->mrtss = (VkMultisampledRenderToSingleSampledInfoEXT) {
732 .sType = VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT,
733 .multisampledRenderToSingleSampledEnable = VK_TRUE,
734 .rasterizationSamples = mrtss->rasterizationSamples,
735 };
736 }
737 }
738 assert(next_subpass_attachment ==
739 subpass_attachments + subpass_attachment_count);
740 assert(next_subpass_color_format ==
741 subpass_color_formats + subpass_color_attachment_count);
742 assert(next_subpass_color_samples ==
743 subpass_color_samples + subpass_color_attachment_count);
744
745 /* Walk backwards over the subpasses to compute view masks and
746 * last_subpass masks for all attachments.
747 */
748 for (uint32_t s = 0; s < pCreateInfo->subpassCount; s++) {
749 struct vk_subpass *subpass =
750 &pass->subpasses[(pCreateInfo->subpassCount - 1) - s];
751
752 /* First, compute last_subpass for all the attachments */
753 for (uint32_t a = 0; a < subpass->attachment_count; a++) {
754 struct vk_subpass_attachment *att = &subpass->attachments[a];
755 if (att->attachment == VK_ATTACHMENT_UNUSED)
756 continue;
757
758 assert(att->attachment < pass->attachment_count);
759 const struct vk_render_pass_attachment *pass_att =
760 &pass->attachments[att->attachment];
761
762 att->last_subpass = subpass->view_mask & ~pass_att->view_mask;
763 }
764
765 /* Then compute pass_att->view_mask. We do the two separately so that
766 * we end up with the right last_subpass even if the same attachment is
767 * used twice within a subpass.
768 */
769 for (uint32_t a = 0; a < subpass->attachment_count; a++) {
770 const struct vk_subpass_attachment *att = &subpass->attachments[a];
771 if (att->attachment == VK_ATTACHMENT_UNUSED)
772 continue;
773
774 assert(att->attachment < pass->attachment_count);
775 struct vk_render_pass_attachment *pass_att =
776 &pass->attachments[att->attachment];
777
778 pass_att->view_mask |= subpass->view_mask;
779 }
780 }
781
782 pass->dependency_count = pCreateInfo->dependencyCount;
783 for (uint32_t d = 0; d < pCreateInfo->dependencyCount; d++) {
784 const VkSubpassDependency2 *dep = &pCreateInfo->pDependencies[d];
785
786 pass->dependencies[d] = (struct vk_subpass_dependency) {
787 .flags = dep->dependencyFlags,
788 .src_subpass = dep->srcSubpass,
789 .dst_subpass = dep->dstSubpass,
790 .src_stage_mask = (VkPipelineStageFlags2)dep->srcStageMask,
791 .dst_stage_mask = (VkPipelineStageFlags2)dep->dstStageMask,
792 .src_access_mask = (VkAccessFlags2)dep->srcAccessMask,
793 .dst_access_mask = (VkAccessFlags2)dep->dstAccessMask,
794 .view_offset = dep->viewOffset,
795 };
796
797 /* From the Vulkan 1.3.204 spec:
798 *
799 * "If a VkMemoryBarrier2 is included in the pNext chain,
800 * srcStageMask, dstStageMask, srcAccessMask, and dstAccessMask
801 * parameters are ignored. The synchronization and access scopes
802 * instead are defined by the parameters of VkMemoryBarrier2."
803 */
804 const VkMemoryBarrier2 *barrier =
805 vk_find_struct_const(dep->pNext, MEMORY_BARRIER_2);
806 if (barrier != NULL) {
807 pass->dependencies[d].src_stage_mask = barrier->srcStageMask;
808 pass->dependencies[d].dst_stage_mask = barrier->dstStageMask;
809 pass->dependencies[d].src_access_mask = barrier->srcAccessMask;
810 pass->dependencies[d].dst_access_mask = barrier->dstAccessMask;
811 }
812 }
813
814 const VkRenderPassFragmentDensityMapCreateInfoEXT *fdm_info =
815 vk_find_struct_const(pCreateInfo->pNext,
816 RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT);
817 if (fdm_info) {
818 pass->fragment_density_map = fdm_info->fragmentDensityMapAttachment;
819 } else {
820 pass->fragment_density_map.attachment = VK_ATTACHMENT_UNUSED;
821 pass->fragment_density_map.layout = VK_IMAGE_LAYOUT_UNDEFINED;
822 }
823
824 *pRenderPass = vk_render_pass_to_handle(pass);
825
826 return VK_SUCCESS;
827 }
828
829 const VkPipelineRenderingCreateInfo *
vk_get_pipeline_rendering_create_info(const VkGraphicsPipelineCreateInfo * info)830 vk_get_pipeline_rendering_create_info(const VkGraphicsPipelineCreateInfo *info)
831 {
832 VK_FROM_HANDLE(vk_render_pass, render_pass, info->renderPass);
833 if (render_pass != NULL) {
834 assert(info->subpass < render_pass->subpass_count);
835 return &render_pass->subpasses[info->subpass].pipeline_info;
836 }
837
838 return vk_find_struct_const(info->pNext, PIPELINE_RENDERING_CREATE_INFO);
839 }
840
841 VkPipelineCreateFlags
vk_get_pipeline_rendering_flags(const VkGraphicsPipelineCreateInfo * info)842 vk_get_pipeline_rendering_flags(const VkGraphicsPipelineCreateInfo *info)
843 {
844 VkPipelineCreateFlags rendering_flags = info->flags &
845 (VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
846 VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
847 VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
848 VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT);
849
850 VK_FROM_HANDLE(vk_render_pass, render_pass, info->renderPass);
851 if (render_pass != NULL) {
852 rendering_flags |= render_pass->subpasses[info->subpass].pipeline_flags;
853 if (render_pass->fragment_density_map.attachment != VK_ATTACHMENT_UNUSED)
854 rendering_flags |=
855 VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT;
856 }
857
858 return rendering_flags;
859 }
860
861 const VkAttachmentSampleCountInfoAMD *
vk_get_pipeline_sample_count_info_amd(const VkGraphicsPipelineCreateInfo * info)862 vk_get_pipeline_sample_count_info_amd(const VkGraphicsPipelineCreateInfo *info)
863 {
864 VK_FROM_HANDLE(vk_render_pass, render_pass, info->renderPass);
865 if (render_pass != NULL) {
866 assert(info->subpass < render_pass->subpass_count);
867 return &render_pass->subpasses[info->subpass].sample_count_info_amd;
868 }
869
870 return vk_find_struct_const(info->pNext, ATTACHMENT_SAMPLE_COUNT_INFO_AMD);
871 }
872
873 const VkCommandBufferInheritanceRenderingInfo *
vk_get_command_buffer_inheritance_rendering_info(VkCommandBufferLevel level,const VkCommandBufferBeginInfo * pBeginInfo)874 vk_get_command_buffer_inheritance_rendering_info(
875 VkCommandBufferLevel level,
876 const VkCommandBufferBeginInfo *pBeginInfo)
877 {
878 /* From the Vulkan 1.3.204 spec:
879 *
880 * "VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT specifies that a
881 * secondary command buffer is considered to be entirely inside a render
882 * pass. If this is a primary command buffer, then this bit is ignored."
883 *
884 * Since we're only concerned with the continue case here, we can ignore
885 * any primary command buffers.
886 */
887 if (level == VK_COMMAND_BUFFER_LEVEL_PRIMARY)
888 return NULL;
889
890 if (!(pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))
891 return NULL;
892
893 const VkCommandBufferInheritanceInfo *inheritance =
894 pBeginInfo->pInheritanceInfo;
895
896 /* From the Vulkan 1.3.204 spec:
897 *
898 * "If VkCommandBufferInheritanceInfo::renderPass is not VK_NULL_HANDLE,
899 * or VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT is not specified
900 * in VkCommandBufferBeginInfo::flags, parameters of this structure are
901 * ignored."
902 *
903 * If we have a render pass that wins, even if a
904 * VkCommandBufferInheritanceRenderingInfo struct is included in the pNext
905 * chain.
906 */
907 VK_FROM_HANDLE(vk_render_pass, render_pass, inheritance->renderPass);
908 if (render_pass != NULL) {
909 assert(inheritance->subpass < render_pass->subpass_count);
910 return &render_pass->subpasses[inheritance->subpass].inheritance_info;
911 }
912
913 return vk_find_struct_const(inheritance->pNext,
914 COMMAND_BUFFER_INHERITANCE_RENDERING_INFO);
915 }
916
917 const VkRenderingInfo *
vk_get_command_buffer_inheritance_as_rendering_resume(VkCommandBufferLevel level,const VkCommandBufferBeginInfo * pBeginInfo,void * stack_data)918 vk_get_command_buffer_inheritance_as_rendering_resume(
919 VkCommandBufferLevel level,
920 const VkCommandBufferBeginInfo *pBeginInfo,
921 void *stack_data)
922 {
923 struct vk_gcbiarr_data *data = stack_data;
924
925 /* From the Vulkan 1.3.204 spec:
926 *
927 * "VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT specifies that a
928 * secondary command buffer is considered to be entirely inside a render
929 * pass. If this is a primary command buffer, then this bit is ignored."
930 *
931 * Since we're only concerned with the continue case here, we can ignore
932 * any primary command buffers.
933 */
934 if (level == VK_COMMAND_BUFFER_LEVEL_PRIMARY)
935 return NULL;
936
937 if (!(pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))
938 return NULL;
939
940 const VkCommandBufferInheritanceInfo *inheritance =
941 pBeginInfo->pInheritanceInfo;
942
943 VK_FROM_HANDLE(vk_render_pass, pass, inheritance->renderPass);
944 if (pass == NULL)
945 return NULL;
946
947 assert(inheritance->subpass < pass->subpass_count);
948 const struct vk_subpass *subpass = &pass->subpasses[inheritance->subpass];
949
950 VK_FROM_HANDLE(vk_framebuffer, fb, inheritance->framebuffer);
951 if (fb == NULL || (fb->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT))
952 return NULL;
953
954 data->rendering = (VkRenderingInfo) {
955 .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
956 .flags = VK_RENDERING_RESUMING_BIT,
957 .renderArea = {
958 .offset = { 0, 0 },
959 .extent = { fb->width, fb->height },
960 },
961 .layerCount = fb->layers,
962 .viewMask = pass->is_multiview ? subpass->view_mask : 0,
963 };
964
965 VkRenderingAttachmentInfo *attachments = data->attachments;
966
967 for (unsigned i = 0; i < subpass->color_count; i++) {
968 const struct vk_subpass_attachment *sp_att =
969 &subpass->color_attachments[i];
970 if (sp_att->attachment == VK_ATTACHMENT_UNUSED) {
971 attachments[i] = (VkRenderingAttachmentInfo) {
972 .imageView = VK_NULL_HANDLE,
973 };
974 continue;
975 }
976
977 assert(sp_att->attachment < pass->attachment_count);
978 attachments[i] = (VkRenderingAttachmentInfo) {
979 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
980 .imageView = fb->attachments[sp_att->attachment],
981 .imageLayout = sp_att->layout,
982 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
983 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
984 };
985 }
986 data->rendering.colorAttachmentCount = subpass->color_count;
987 data->rendering.pColorAttachments = attachments;
988 attachments += subpass->color_count;
989
990 if (subpass->depth_stencil_attachment) {
991 const struct vk_subpass_attachment *sp_att =
992 subpass->depth_stencil_attachment;
993 assert(sp_att->attachment < pass->attachment_count);
994
995 VK_FROM_HANDLE(vk_image_view, iview, fb->attachments[sp_att->attachment]);
996 if (iview->image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
997 *attachments = (VkRenderingAttachmentInfo) {
998 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
999 .imageView = vk_image_view_to_handle(iview),
1000 .imageLayout = sp_att->layout,
1001 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
1002 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
1003 };
1004 data->rendering.pDepthAttachment = attachments++;
1005 }
1006
1007 if (iview->image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
1008 *attachments = (VkRenderingAttachmentInfo) {
1009 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
1010 .imageView = vk_image_view_to_handle(iview),
1011 .imageLayout = sp_att->stencil_layout,
1012 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
1013 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
1014 };
1015 data->rendering.pStencilAttachment = attachments++;
1016 }
1017 }
1018
1019 if (subpass->fragment_shading_rate_attachment) {
1020 const struct vk_subpass_attachment *sp_att =
1021 subpass->fragment_shading_rate_attachment;
1022 assert(sp_att->attachment < pass->attachment_count);
1023
1024 data->fsr_att = (VkRenderingFragmentShadingRateAttachmentInfoKHR) {
1025 .sType = VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,
1026 .imageView = fb->attachments[sp_att->attachment],
1027 .imageLayout = sp_att->layout,
1028 .shadingRateAttachmentTexelSize =
1029 subpass->fragment_shading_rate_attachment_texel_size,
1030 };
1031 __vk_append_struct(&data->rendering, &data->fsr_att);
1032 }
1033
1034 /* Append this one last because it lives in the subpass and we don't want
1035 * to be changed by appending other structures later.
1036 */
1037 if (subpass->mrtss.multisampledRenderToSingleSampledEnable)
1038 __vk_append_struct(&data->rendering, (void *)&subpass->mrtss);
1039
1040 return &data->rendering;
1041 }
1042
1043 VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyRenderPass(VkDevice _device,VkRenderPass renderPass,const VkAllocationCallbacks * pAllocator)1044 vk_common_DestroyRenderPass(VkDevice _device,
1045 VkRenderPass renderPass,
1046 const VkAllocationCallbacks *pAllocator)
1047 {
1048 VK_FROM_HANDLE(vk_device, device, _device);
1049 VK_FROM_HANDLE(vk_render_pass, pass, renderPass);
1050
1051 if (!pass)
1052 return;
1053
1054 vk_object_free(device, pAllocator, pass);
1055 }
1056
1057 VKAPI_ATTR void VKAPI_CALL
vk_common_GetRenderAreaGranularity(VkDevice device,VkRenderPass renderPass,VkExtent2D * pGranularity)1058 vk_common_GetRenderAreaGranularity(VkDevice device,
1059 VkRenderPass renderPass,
1060 VkExtent2D *pGranularity)
1061 {
1062 *pGranularity = (VkExtent2D){1, 1};
1063 }
1064
1065 VKAPI_ATTR void VKAPI_CALL
vk_common_GetRenderingAreaGranularityKHR(VkDevice _device,const VkRenderingAreaInfoKHR * pRenderingAreaInfo,VkExtent2D * pGranularity)1066 vk_common_GetRenderingAreaGranularityKHR(
1067 VkDevice _device, const VkRenderingAreaInfoKHR *pRenderingAreaInfo,
1068 VkExtent2D *pGranularity)
1069 {
1070 *pGranularity = (VkExtent2D) { 1, 1 };
1071 }
1072
1073 static VkRenderPassSampleLocationsBeginInfoEXT *
clone_rp_sample_locations(const VkRenderPassSampleLocationsBeginInfoEXT * loc)1074 clone_rp_sample_locations(const VkRenderPassSampleLocationsBeginInfoEXT *loc)
1075 {
1076 uint32_t sl_count = 0;
1077
1078 for (uint32_t i = 0; i < loc->attachmentInitialSampleLocationsCount; i++) {
1079 const VkAttachmentSampleLocationsEXT *att_sl_in =
1080 &loc->pAttachmentInitialSampleLocations[i];
1081 sl_count += att_sl_in->sampleLocationsInfo.sampleLocationsCount;
1082 }
1083 for (uint32_t i = 0; i < loc->postSubpassSampleLocationsCount; i++) {
1084 const VkSubpassSampleLocationsEXT *sp_sl_in =
1085 &loc->pPostSubpassSampleLocations[i];
1086 sl_count += sp_sl_in->sampleLocationsInfo.sampleLocationsCount;
1087 }
1088
1089 VK_MULTIALLOC(ma);
1090 VK_MULTIALLOC_DECL(&ma, VkRenderPassSampleLocationsBeginInfoEXT, new_loc, 1);
1091 VK_MULTIALLOC_DECL(&ma, VkAttachmentSampleLocationsEXT, new_att_sl,
1092 loc->attachmentInitialSampleLocationsCount);
1093 VK_MULTIALLOC_DECL(&ma, VkSubpassSampleLocationsEXT, new_sp_sl,
1094 loc->postSubpassSampleLocationsCount);
1095 VK_MULTIALLOC_DECL(&ma, VkSampleLocationEXT, sl, sl_count);
1096 if (!vk_multialloc_alloc(&ma, vk_default_allocator(),
1097 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
1098 return NULL;
1099
1100 VkSampleLocationEXT *next_sl = sl;
1101 for (uint32_t i = 0; i < loc->attachmentInitialSampleLocationsCount; i++) {
1102 const VkAttachmentSampleLocationsEXT *att_sl_in =
1103 &loc->pAttachmentInitialSampleLocations[i];
1104 const VkSampleLocationsInfoEXT *sli_in = &att_sl_in->sampleLocationsInfo;
1105
1106 typed_memcpy(next_sl, sli_in->pSampleLocations,
1107 sli_in->sampleLocationsCount);
1108
1109 new_att_sl[i] = (VkAttachmentSampleLocationsEXT) {
1110 .attachmentIndex = att_sl_in->attachmentIndex,
1111 .sampleLocationsInfo = {
1112 .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
1113 .sampleLocationsPerPixel = sli_in->sampleLocationsPerPixel,
1114 .sampleLocationGridSize = sli_in->sampleLocationGridSize,
1115 .sampleLocationsCount = sli_in->sampleLocationsCount,
1116 .pSampleLocations = next_sl,
1117 },
1118 };
1119
1120 next_sl += sli_in->sampleLocationsCount;
1121 }
1122
1123 for (uint32_t i = 0; i < loc->postSubpassSampleLocationsCount; i++) {
1124 const VkSubpassSampleLocationsEXT *sp_sl_in =
1125 &loc->pPostSubpassSampleLocations[i];
1126 const VkSampleLocationsInfoEXT *sli_in = &sp_sl_in->sampleLocationsInfo;
1127
1128 typed_memcpy(next_sl, sli_in->pSampleLocations,
1129 sli_in->sampleLocationsCount);
1130
1131 new_sp_sl[i] = (VkSubpassSampleLocationsEXT) {
1132 .subpassIndex = sp_sl_in->subpassIndex,
1133 .sampleLocationsInfo = {
1134 .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
1135 .sampleLocationsPerPixel = sli_in->sampleLocationsPerPixel,
1136 .sampleLocationGridSize = sli_in->sampleLocationGridSize,
1137 .sampleLocationsCount = sli_in->sampleLocationsCount,
1138 .pSampleLocations = next_sl,
1139 },
1140 };
1141
1142 next_sl += sli_in->sampleLocationsCount;
1143 }
1144
1145 assert(next_sl == sl + sl_count);
1146
1147 *new_loc = (VkRenderPassSampleLocationsBeginInfoEXT) {
1148 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT,
1149 .attachmentInitialSampleLocationsCount = loc->attachmentInitialSampleLocationsCount,
1150 .pAttachmentInitialSampleLocations = new_att_sl,
1151 .postSubpassSampleLocationsCount = loc->postSubpassSampleLocationsCount,
1152 .pPostSubpassSampleLocations = new_sp_sl,
1153 };
1154
1155 return new_loc;
1156 }
1157
1158 static const VkSampleLocationsInfoEXT *
get_subpass_sample_locations(const VkRenderPassSampleLocationsBeginInfoEXT * loc,uint32_t subpass_idx)1159 get_subpass_sample_locations(const VkRenderPassSampleLocationsBeginInfoEXT *loc,
1160 uint32_t subpass_idx)
1161 {
1162 for (uint32_t i = 0; i < loc->postSubpassSampleLocationsCount; i++) {
1163 if (loc->pPostSubpassSampleLocations[i].subpassIndex == subpass_idx)
1164 return &loc->pPostSubpassSampleLocations[i].sampleLocationsInfo;
1165 }
1166
1167 return NULL;
1168 }
1169
1170 static bool
vk_image_layout_supports_input_attachment(VkImageLayout layout)1171 vk_image_layout_supports_input_attachment(VkImageLayout layout)
1172 {
1173 switch (layout) {
1174 case VK_IMAGE_LAYOUT_GENERAL:
1175 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
1176 case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
1177 case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
1178 case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
1179 case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
1180 case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
1181 case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
1182 case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT:
1183 return true;
1184 default:
1185 return false;
1186 }
1187 }
1188
1189 struct stage_access {
1190 VkPipelineStageFlagBits2 stages;
1191 VkAccessFlagBits2 access;
1192 };
1193
1194 static bool
vk_image_layout_are_all_aspects_read_only(VkImageLayout layout,VkImageAspectFlags aspects)1195 vk_image_layout_are_all_aspects_read_only(VkImageLayout layout,
1196 VkImageAspectFlags aspects)
1197 {
1198 u_foreach_bit(a, aspects) {
1199 VkImageAspectFlagBits aspect = 1u << a;
1200 if (!vk_image_layout_is_read_only(layout, aspect))
1201 return false;
1202 }
1203 return true;
1204 }
1205
1206 static struct stage_access
stage_access_for_layout(VkImageLayout layout,VkImageAspectFlags aspects)1207 stage_access_for_layout(VkImageLayout layout, VkImageAspectFlags aspects)
1208 {
1209 VkPipelineStageFlagBits2 stages = 0;
1210 VkAccessFlagBits2 access = 0;
1211
1212 if (vk_image_layout_supports_input_attachment(layout)) {
1213 stages |= VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
1214 access |= VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT;
1215 }
1216
1217 if (aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
1218 stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
1219 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
1220 access |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
1221 if (!vk_image_layout_are_all_aspects_read_only(layout, aspects)) {
1222 access |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1223
1224 /* It might be a resolve attachment */
1225 stages |= VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT;
1226 access |= VK_ACCESS_2_TRANSFER_WRITE_BIT;
1227 }
1228 } else {
1229 /* Color */
1230 if (!vk_image_layout_are_all_aspects_read_only(layout, aspects)) {
1231 /* There are no read-only color attachments */
1232 stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1233 access |= VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT |
1234 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
1235
1236 /* It might be a resolve attachment */
1237 stages |= VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT;
1238 access |= VK_ACCESS_2_TRANSFER_WRITE_BIT;
1239 }
1240 }
1241
1242 return (struct stage_access) {
1243 .stages = stages,
1244 .access = access,
1245 };
1246 }
1247
1248 static void
transition_image_range(const struct vk_image_view * image_view,VkImageSubresourceRange range,VkImageLayout old_layout,VkImageLayout new_layout,VkImageLayout old_stencil_layout,VkImageLayout new_stencil_layout,const VkSampleLocationsInfoEXT * sample_locations,uint32_t * barrier_count,uint32_t max_barrier_count,VkImageMemoryBarrier2 * barriers)1249 transition_image_range(const struct vk_image_view *image_view,
1250 VkImageSubresourceRange range,
1251 VkImageLayout old_layout,
1252 VkImageLayout new_layout,
1253 VkImageLayout old_stencil_layout,
1254 VkImageLayout new_stencil_layout,
1255 const VkSampleLocationsInfoEXT *sample_locations,
1256 uint32_t *barrier_count,
1257 uint32_t max_barrier_count,
1258 VkImageMemoryBarrier2 *barriers)
1259 {
1260 VkImageAspectFlags aspects_left = range.aspectMask;
1261 while (aspects_left) {
1262 range.aspectMask = aspects_left;
1263
1264 /* If we have a depth/stencil image and one of the layouts doesn't match
1265 * between depth and stencil, we need two barriers. Restrict to depth
1266 * and we'll pick up stencil on the next iteration.
1267 */
1268 if (range.aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT |
1269 VK_IMAGE_ASPECT_STENCIL_BIT) &&
1270 (old_layout != old_stencil_layout ||
1271 new_layout != new_stencil_layout))
1272 range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
1273
1274 if (range.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT) {
1275 /* We're down to a single aspect bit so this is going to be the last
1276 * iteration and it's fine to stomp the input variables here.
1277 */
1278 old_layout = old_stencil_layout;
1279 new_layout = new_stencil_layout;
1280 }
1281
1282 if (new_layout != old_layout) {
1283 /* We could go about carefully calculating every possible way the
1284 * attachment may have been used in the render pass or we can break
1285 * out the big hammer and throw in any stage and access flags
1286 * possible for the given layouts.
1287 */
1288 struct stage_access src_sa, dst_sa;
1289 src_sa = stage_access_for_layout(old_layout, range.aspectMask);
1290 dst_sa = stage_access_for_layout(new_layout, range.aspectMask);
1291
1292 assert(*barrier_count < max_barrier_count);
1293 barriers[(*barrier_count)++] = (VkImageMemoryBarrier2) {
1294 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
1295 .pNext = sample_locations,
1296 .srcStageMask = src_sa.stages,
1297 .srcAccessMask = src_sa.access,
1298 .dstStageMask = dst_sa.stages,
1299 .dstAccessMask = dst_sa.access,
1300 .oldLayout = old_layout,
1301 .newLayout = new_layout,
1302 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1303 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1304 .image = vk_image_to_handle(image_view->image),
1305 .subresourceRange = range,
1306 };
1307 }
1308
1309 aspects_left &= ~range.aspectMask;
1310 }
1311 }
1312
1313 static bool
can_use_attachment_initial_layout(struct vk_command_buffer * cmd_buffer,uint32_t att_idx,uint32_t view_mask,VkImageLayout * layout_out,VkImageLayout * stencil_layout_out)1314 can_use_attachment_initial_layout(struct vk_command_buffer *cmd_buffer,
1315 uint32_t att_idx,
1316 uint32_t view_mask,
1317 VkImageLayout *layout_out,
1318 VkImageLayout *stencil_layout_out)
1319 {
1320 const struct vk_render_pass *pass = cmd_buffer->render_pass;
1321 const struct vk_framebuffer *framebuffer = cmd_buffer->framebuffer;
1322 const struct vk_render_pass_attachment *rp_att = &pass->attachments[att_idx];
1323 struct vk_attachment_state *att_state = &cmd_buffer->attachments[att_idx];
1324 const struct vk_image_view *image_view = att_state->image_view;
1325
1326 if ((rp_att->aspects & ~VK_IMAGE_ASPECT_STENCIL_BIT) &&
1327 rp_att->load_op != VK_ATTACHMENT_LOAD_OP_CLEAR)
1328 return false;
1329
1330 if ((rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
1331 rp_att->stencil_load_op != VK_ATTACHMENT_LOAD_OP_CLEAR)
1332 return false;
1333
1334 if (cmd_buffer->render_area.offset.x != 0 ||
1335 cmd_buffer->render_area.offset.y != 0 ||
1336 cmd_buffer->render_area.extent.width != image_view->extent.width ||
1337 cmd_buffer->render_area.extent.height != image_view->extent.height)
1338 return false;
1339
1340 if (image_view->image->image_type == VK_IMAGE_TYPE_3D) {
1341 /* For 3D images, the view has to be the whole thing */
1342 if (image_view->base_array_layer != 0)
1343 return false;
1344
1345 if (pass->is_multiview) {
1346 if (!util_is_power_of_two_or_zero(view_mask + 1) ||
1347 util_last_bit(view_mask) != image_view->layer_count)
1348 return false;
1349 } else {
1350 if (framebuffer->layers != image_view->layer_count)
1351 return false;
1352 }
1353 }
1354
1355 /* Finally, check if the entire thing is undefined. It's ok to smash the
1356 * view_mask now as the only thing using it will be the loop below.
1357 */
1358
1359 /* 3D is stupidly special. See transition_attachment() */
1360 if (image_view->image->image_type == VK_IMAGE_TYPE_3D)
1361 view_mask = 1;
1362
1363 VkImageLayout layout = VK_IMAGE_LAYOUT_MAX_ENUM;
1364 VkImageLayout stencil_layout = VK_IMAGE_LAYOUT_MAX_ENUM;
1365
1366 assert(view_mask != 0);
1367 u_foreach_bit(view, view_mask) {
1368 assert(view >= 0 && view < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT);
1369 struct vk_attachment_view_state *att_view_state = &att_state->views[view];
1370
1371 if (rp_att->aspects & ~VK_IMAGE_ASPECT_STENCIL_BIT) {
1372 if (layout == VK_IMAGE_LAYOUT_MAX_ENUM)
1373 layout = att_view_state->layout;
1374 else if (layout != att_view_state->layout)
1375 return false;
1376 }
1377
1378 if (rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
1379 if (stencil_layout == VK_IMAGE_LAYOUT_MAX_ENUM)
1380 stencil_layout = att_view_state->stencil_layout;
1381 else if (stencil_layout != att_view_state->stencil_layout)
1382 return false;
1383 }
1384 }
1385
1386 if (layout != VK_IMAGE_LAYOUT_MAX_ENUM)
1387 *layout_out = layout;
1388 else if (layout_out != NULL)
1389 *layout_out = VK_IMAGE_LAYOUT_UNDEFINED;
1390
1391 if (stencil_layout != VK_IMAGE_LAYOUT_MAX_ENUM)
1392 *stencil_layout_out = stencil_layout;
1393 else if (stencil_layout_out != NULL)
1394 *stencil_layout_out = VK_IMAGE_LAYOUT_UNDEFINED;
1395
1396 return true;
1397 }
1398
1399 static void
set_attachment_layout(struct vk_command_buffer * cmd_buffer,uint32_t att_idx,uint32_t view_mask,VkImageLayout layout,VkImageLayout stencil_layout)1400 set_attachment_layout(struct vk_command_buffer *cmd_buffer,
1401 uint32_t att_idx,
1402 uint32_t view_mask,
1403 VkImageLayout layout,
1404 VkImageLayout stencil_layout)
1405 {
1406 struct vk_attachment_state *att_state = &cmd_buffer->attachments[att_idx];
1407
1408 u_foreach_bit(view, view_mask) {
1409 assert(view >= 0 && view < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT);
1410 struct vk_attachment_view_state *att_view_state = &att_state->views[view];
1411
1412 att_view_state->layout = layout;
1413 att_view_state->stencil_layout = stencil_layout;
1414 }
1415 }
1416
1417 static void
transition_attachment(struct vk_command_buffer * cmd_buffer,uint32_t att_idx,uint32_t view_mask,VkImageLayout layout,VkImageLayout stencil_layout,uint32_t * barrier_count,uint32_t max_barrier_count,VkImageMemoryBarrier2 * barriers)1418 transition_attachment(struct vk_command_buffer *cmd_buffer,
1419 uint32_t att_idx,
1420 uint32_t view_mask,
1421 VkImageLayout layout,
1422 VkImageLayout stencil_layout,
1423 uint32_t *barrier_count,
1424 uint32_t max_barrier_count,
1425 VkImageMemoryBarrier2 *barriers)
1426 {
1427 const struct vk_render_pass *pass = cmd_buffer->render_pass;
1428 const struct vk_framebuffer *framebuffer = cmd_buffer->framebuffer;
1429 const struct vk_render_pass_attachment *pass_att =
1430 &pass->attachments[att_idx];
1431 struct vk_attachment_state *att_state = &cmd_buffer->attachments[att_idx];
1432 const struct vk_image_view *image_view = att_state->image_view;
1433
1434 /* 3D is stupidly special. From the Vulkan 1.3.204 spec:
1435 *
1436 * "When the VkImageSubresourceRange structure is used to select a
1437 * subset of the slices of a 3D image’s mip level in order to create
1438 * a 2D or 2D array image view of a 3D image created with
1439 * VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, baseArrayLayer and
1440 * layerCount specify the first slice index and the number of slices
1441 * to include in the created image view. Such an image view can be
1442 * used as a framebuffer attachment that refers only to the specified
1443 * range of slices of the selected mip level. However, any layout
1444 * transitions performed on such an attachment view during a render
1445 * pass instance still apply to the entire subresource referenced
1446 * which includes all the slices of the selected mip level."
1447 *
1448 * To deal with this, we expand out the layer range to include the
1449 * entire 3D image and treat them as having only a single view even when
1450 * multiview is enabled. This later part means that we effectively only
1451 * track one image layout for the entire attachment rather than one per
1452 * view like we do for all the others.
1453 */
1454 if (image_view->image->image_type == VK_IMAGE_TYPE_3D)
1455 view_mask = 1;
1456
1457 u_foreach_bit(view, view_mask) {
1458 assert(view >= 0 && view < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT);
1459 struct vk_attachment_view_state *att_view_state = &att_state->views[view];
1460
1461 /* First, check to see if we even need a transition */
1462 if (att_view_state->layout == layout &&
1463 att_view_state->stencil_layout == stencil_layout)
1464 continue;
1465
1466 VkImageSubresourceRange range = {
1467 .aspectMask = pass_att->aspects,
1468 .baseMipLevel = image_view->base_mip_level,
1469 .levelCount = 1,
1470 };
1471
1472 /* From the Vulkan 1.3.207 spec:
1473 *
1474 * "Automatic layout transitions apply to the entire image
1475 * subresource attached to the framebuffer. If multiview is not
1476 * enabled and the attachment is a view of a 1D or 2D image, the
1477 * automatic layout transitions apply to the number of layers
1478 * specified by VkFramebufferCreateInfo::layers. If multiview is
1479 * enabled and the attachment is a view of a 1D or 2D image, the
1480 * automatic layout transitions apply to the layers corresponding to
1481 * views which are used by some subpass in the render pass, even if
1482 * that subpass does not reference the given attachment. If the
1483 * attachment view is a 2D or 2D array view of a 3D image, even if
1484 * the attachment view only refers to a subset of the slices of the
1485 * selected mip level of the 3D image, automatic layout transitions
1486 * apply to the entire subresource referenced which is the entire mip
1487 * level in this case."
1488 */
1489 if (image_view->image->image_type == VK_IMAGE_TYPE_3D) {
1490 assert(view == 0);
1491 range.baseArrayLayer = 0;
1492 range.layerCount = image_view->extent.depth;
1493 } else if (pass->is_multiview) {
1494 range.baseArrayLayer = image_view->base_array_layer + view;
1495 range.layerCount = 1;
1496 } else {
1497 assert(view == 0);
1498 range.baseArrayLayer = image_view->base_array_layer;
1499 range.layerCount = framebuffer->layers;
1500 }
1501
1502 transition_image_range(image_view, range,
1503 att_view_state->layout, layout,
1504 att_view_state->stencil_layout, stencil_layout,
1505 att_view_state->sample_locations,
1506 barrier_count, max_barrier_count, barriers);
1507
1508 att_view_state->layout = layout;
1509 att_view_state->stencil_layout = stencil_layout;
1510 }
1511 }
1512
1513 static void
load_attachment(struct vk_command_buffer * cmd_buffer,uint32_t att_idx,uint32_t view_mask,VkImageLayout layout,VkImageLayout stencil_layout)1514 load_attachment(struct vk_command_buffer *cmd_buffer,
1515 uint32_t att_idx, uint32_t view_mask,
1516 VkImageLayout layout, VkImageLayout stencil_layout)
1517 {
1518 const struct vk_render_pass *pass = cmd_buffer->render_pass;
1519 const struct vk_framebuffer *framebuffer = cmd_buffer->framebuffer;
1520 const struct vk_render_pass_attachment *rp_att = &pass->attachments[att_idx];
1521 struct vk_attachment_state *att_state = &cmd_buffer->attachments[att_idx];
1522 struct vk_device_dispatch_table *disp =
1523 &cmd_buffer->base.device->dispatch_table;
1524
1525 /* Don't load any views we've already loaded */
1526 view_mask &= ~att_state->views_loaded;
1527 if (view_mask == 0)
1528 return;
1529
1530 /* From here on, if we return, we loaded the views */
1531 att_state->views_loaded |= view_mask;
1532
1533 /* We only need to load/store if there's a clear */
1534 bool need_load_store = false;
1535 if ((rp_att->aspects & ~VK_IMAGE_ASPECT_STENCIL_BIT) &&
1536 rp_att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR)
1537 need_load_store = true;
1538
1539 if ((rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
1540 rp_att->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR)
1541 need_load_store = true;
1542
1543 if (!need_load_store)
1544 return;
1545
1546 const VkRenderingAttachmentInfo att = {
1547 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
1548 .imageView = vk_image_view_to_handle(att_state->image_view),
1549 .imageLayout = layout,
1550 .loadOp = rp_att->load_op,
1551 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
1552 .clearValue = att_state->clear_value,
1553 };
1554
1555 const VkRenderingAttachmentInfo stencil_att = {
1556 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
1557 .imageView = vk_image_view_to_handle(att_state->image_view),
1558 .imageLayout = stencil_layout,
1559 .loadOp = rp_att->stencil_load_op,
1560 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
1561 .clearValue = att_state->clear_value,
1562 };
1563
1564 VkRenderingInfo render = {
1565 .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
1566 .renderArea = cmd_buffer->render_area,
1567 .layerCount = pass->is_multiview ? 1 : framebuffer->layers,
1568 .viewMask = pass->is_multiview ? view_mask : 0,
1569 };
1570
1571 if (rp_att->aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
1572 VK_IMAGE_ASPECT_STENCIL_BIT)) {
1573 if (rp_att->aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
1574 render.pDepthAttachment = &att;
1575 if (rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
1576 render.pStencilAttachment = &stencil_att;
1577 } else {
1578 render.colorAttachmentCount = 1;
1579 render.pColorAttachments = &att;
1580 }
1581
1582 disp->CmdBeginRendering(vk_command_buffer_to_handle(cmd_buffer), &render);
1583 disp->CmdEndRendering(vk_command_buffer_to_handle(cmd_buffer));
1584 }
1585
1586 static void
begin_subpass(struct vk_command_buffer * cmd_buffer,const VkSubpassBeginInfo * begin_info)1587 begin_subpass(struct vk_command_buffer *cmd_buffer,
1588 const VkSubpassBeginInfo *begin_info)
1589 {
1590 const struct vk_render_pass *pass = cmd_buffer->render_pass;
1591 const struct vk_framebuffer *framebuffer = cmd_buffer->framebuffer;
1592 const uint32_t subpass_idx = cmd_buffer->subpass_idx;
1593 assert(subpass_idx < pass->subpass_count);
1594 const struct vk_subpass *subpass = &pass->subpasses[subpass_idx];
1595 struct vk_device_dispatch_table *disp =
1596 &cmd_buffer->base.device->dispatch_table;
1597
1598 /* First, we figure out all our attachments and attempt to handle image
1599 * layout transitions and load ops as part of vkCmdBeginRendering if we
1600 * can. For any we can't handle this way, we'll need explicit barriers
1601 * or quick vkCmdBegin/EndRendering to do the load op.
1602 */
1603
1604 STACK_ARRAY(VkRenderingAttachmentInfo, color_attachments,
1605 subpass->color_count);
1606 STACK_ARRAY(VkRenderingAttachmentInitialLayoutInfoMESA,
1607 color_attachment_initial_layouts,
1608 subpass->color_count);
1609
1610 for (uint32_t i = 0; i < subpass->color_count; i++) {
1611 const struct vk_subpass_attachment *sp_att =
1612 &subpass->color_attachments[i];
1613 VkRenderingAttachmentInfo *color_attachment = &color_attachments[i];
1614
1615 if (sp_att->attachment == VK_ATTACHMENT_UNUSED) {
1616 *color_attachment = (VkRenderingAttachmentInfo) {
1617 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
1618 .imageView = VK_NULL_HANDLE,
1619 };
1620 continue;
1621 }
1622
1623 assert(sp_att->attachment < pass->attachment_count);
1624 const struct vk_render_pass_attachment *rp_att =
1625 &pass->attachments[sp_att->attachment];
1626 struct vk_attachment_state *att_state =
1627 &cmd_buffer->attachments[sp_att->attachment];
1628
1629 *color_attachment = (VkRenderingAttachmentInfo) {
1630 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
1631 .imageView = vk_image_view_to_handle(att_state->image_view),
1632 .imageLayout = sp_att->layout,
1633 };
1634
1635 if (!(subpass->view_mask & att_state->views_loaded)) {
1636 /* None of these views have been used before */
1637 color_attachment->loadOp = rp_att->load_op;
1638 color_attachment->clearValue = att_state->clear_value;
1639 att_state->views_loaded |= subpass->view_mask;
1640
1641 VkImageLayout initial_layout;
1642 if (can_use_attachment_initial_layout(cmd_buffer,
1643 sp_att->attachment,
1644 subpass->view_mask,
1645 &initial_layout, NULL) &&
1646 sp_att->layout != initial_layout) {
1647 assert(color_attachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);
1648
1649 VkRenderingAttachmentInitialLayoutInfoMESA *color_initial_layout =
1650 &color_attachment_initial_layouts[i];
1651 *color_initial_layout = (VkRenderingAttachmentInitialLayoutInfoMESA) {
1652 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA,
1653 .initialLayout = initial_layout,
1654 };
1655 __vk_append_struct(color_attachment, color_initial_layout);
1656
1657 set_attachment_layout(cmd_buffer, sp_att->attachment,
1658 subpass->view_mask,
1659 sp_att->layout, VK_IMAGE_LAYOUT_UNDEFINED);
1660 }
1661 } else {
1662 /* We've seen at least one of the views of this attachment before so
1663 * we need to LOAD_OP_LOAD.
1664 */
1665 color_attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1666 }
1667
1668 if (!(subpass->view_mask & ~sp_att->last_subpass)) {
1669 /* This is the last subpass for every view */
1670 color_attachment->storeOp = rp_att->store_op;
1671 } else {
1672 /* For at least one of our views, this isn't the last subpass
1673 *
1674 * In the edge case where we have lots of weird overlap between view
1675 * masks of different subThis may mean that we get STORE_OP_STORE in
1676 * some places where it may have wanted STORE_OP_NONE but that should
1677 * be harmless.
1678 */
1679 color_attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1680 }
1681
1682 if (sp_att->resolve != NULL) {
1683 assert(sp_att->resolve->attachment < pass->attachment_count);
1684 struct vk_attachment_state *res_att_state =
1685 &cmd_buffer->attachments[sp_att->resolve->attachment];
1686
1687 /* Resolve attachments are entirely overwritten by the resolve
1688 * operation so the load op really doesn't matter. We can consider
1689 * the resolve as being the load.
1690 */
1691 res_att_state->views_loaded |= subpass->view_mask;
1692
1693 if (vk_format_is_int(res_att_state->image_view->format))
1694 color_attachment->resolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1695 else
1696 color_attachment->resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
1697
1698 color_attachment->resolveImageView =
1699 vk_image_view_to_handle(res_att_state->image_view);
1700 color_attachment->resolveImageLayout = sp_att->resolve->layout;
1701 } else if (subpass->mrtss.multisampledRenderToSingleSampledEnable &&
1702 rp_att->samples == VK_SAMPLE_COUNT_1_BIT) {
1703 if (vk_format_is_int(att_state->image_view->format))
1704 color_attachment->resolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1705 else
1706 color_attachment->resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
1707 }
1708 }
1709
1710 VkRenderingAttachmentInfo depth_attachment = {
1711 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
1712 };
1713 VkRenderingAttachmentInfo stencil_attachment = {
1714 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
1715 };
1716 VkRenderingAttachmentInitialLayoutInfoMESA depth_initial_layout = {
1717 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA,
1718 };
1719 VkRenderingAttachmentInitialLayoutInfoMESA stencil_initial_layout = {
1720 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA,
1721 };
1722
1723 const VkSampleLocationsInfoEXT *sample_locations = NULL;
1724 if (subpass->depth_stencil_attachment != NULL) {
1725 const struct vk_subpass_attachment *sp_att =
1726 subpass->depth_stencil_attachment;
1727
1728 assert(sp_att->attachment < pass->attachment_count);
1729 const struct vk_render_pass_attachment *rp_att =
1730 &pass->attachments[sp_att->attachment];
1731 struct vk_attachment_state *att_state =
1732 &cmd_buffer->attachments[sp_att->attachment];
1733
1734 assert(sp_att->aspects == rp_att->aspects);
1735 if (rp_att->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
1736 depth_attachment.imageView =
1737 vk_image_view_to_handle(att_state->image_view);
1738 depth_attachment.imageLayout = sp_att->layout;
1739 }
1740
1741 if (rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
1742 stencil_attachment.imageView =
1743 vk_image_view_to_handle(att_state->image_view);
1744 stencil_attachment.imageLayout = sp_att->stencil_layout;
1745 }
1746
1747 if (!(subpass->view_mask & att_state->views_loaded)) {
1748 /* None of these views have been used before */
1749 depth_attachment.loadOp = rp_att->load_op;
1750 depth_attachment.clearValue = att_state->clear_value;
1751 stencil_attachment.loadOp = rp_att->stencil_load_op;
1752 stencil_attachment.clearValue = att_state->clear_value;
1753 att_state->views_loaded |= subpass->view_mask;
1754
1755 VkImageLayout initial_layout, initial_stencil_layout;
1756 if (can_use_attachment_initial_layout(cmd_buffer,
1757 sp_att->attachment,
1758 subpass->view_mask,
1759 &initial_layout,
1760 &initial_stencil_layout)) {
1761 if ((rp_att->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) &&
1762 sp_att->layout != initial_layout) {
1763 assert(depth_attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);
1764 depth_initial_layout.initialLayout = initial_layout;
1765 __vk_append_struct(&depth_attachment,
1766 &depth_initial_layout);
1767 }
1768
1769 if ((rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
1770 sp_att->stencil_layout != initial_stencil_layout) {
1771 assert(stencil_attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);
1772 stencil_initial_layout.initialLayout = initial_stencil_layout;
1773 __vk_append_struct(&stencil_attachment,
1774 &stencil_initial_layout);
1775 }
1776
1777 set_attachment_layout(cmd_buffer, sp_att->attachment,
1778 subpass->view_mask,
1779 sp_att->layout, sp_att->stencil_layout);
1780 }
1781 } else {
1782 /* We've seen at least one of the views of this attachment before so
1783 * we need to LOAD_OP_LOAD.
1784 */
1785 depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1786 stencil_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1787 }
1788
1789 if (!(subpass->view_mask & ~sp_att->last_subpass)) {
1790 /* This is the last subpass for every view */
1791 depth_attachment.storeOp = rp_att->store_op;
1792 stencil_attachment.storeOp = rp_att->stencil_store_op;
1793 } else {
1794 /* For at least one of our views, this isn't the last subpass
1795 *
1796 * In the edge case where we have lots of weird overlap between view
1797 * masks of different subThis may mean that we get STORE_OP_STORE in
1798 * some places where it may have wanted STORE_OP_NONE but that should
1799 * be harmless.
1800 */
1801 depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1802 stencil_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1803 }
1804
1805 /* From the Vulkan 1.3.212 spec:
1806 *
1807 * "If the current render pass does not use the attachment as a
1808 * depth/stencil attachment in any subpass that happens-before, the
1809 * automatic layout transition uses the sample locations state
1810 * specified in the sampleLocationsInfo member of the element of the
1811 * VkRenderPassSampleLocationsBeginInfoEXT::pAttachmentInitialSampleLocations
1812 * array for which the attachmentIndex member equals the attachment
1813 * index of the attachment, if one is specified. Otherwise, the
1814 * automatic layout transition uses the sample locations state
1815 * specified in the sampleLocationsInfo member of the element of the
1816 * VkRenderPassSampleLocationsBeginInfoEXT::pPostSubpassSampleLocations
1817 * array for which the subpassIndex member equals the index of the
1818 * subpass that last used the attachment as a depth/stencil
1819 * attachment, if one is specified."
1820 *
1821 * Unfortunately, this says nothing whatsoever about multiview.
1822 * However, since multiview render passes are described as a single-view
1823 * render pass repeated per-view, we assume this is per-view.
1824 */
1825 if (cmd_buffer->pass_sample_locations != NULL &&
1826 (att_state->image_view->image->create_flags &
1827 VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT)) {
1828 sample_locations =
1829 get_subpass_sample_locations(cmd_buffer->pass_sample_locations,
1830 subpass_idx);
1831
1832 u_foreach_bit(view, subpass->view_mask)
1833 att_state->views[view].sample_locations = sample_locations;
1834 }
1835
1836 if (sp_att->resolve != NULL ||
1837 (subpass->mrtss.multisampledRenderToSingleSampledEnable &&
1838 rp_att->samples == VK_SAMPLE_COUNT_1_BIT)) {
1839 const struct vk_subpass_attachment *res_sp_att = sp_att->resolve ? sp_att->resolve : sp_att;
1840 assert(res_sp_att->attachment < pass->attachment_count);
1841 const struct vk_render_pass_attachment *res_rp_att =
1842 &pass->attachments[res_sp_att->attachment];
1843 struct vk_attachment_state *res_att_state =
1844 &cmd_buffer->attachments[res_sp_att->attachment];
1845
1846 /* From the Vulkan 1.3.204 spec:
1847 *
1848 * "VkSubpassDescriptionDepthStencilResolve::depthResolveMode is
1849 * ignored if the VkFormat of the pDepthStencilResolveAttachment
1850 * does not have a depth component. Similarly,
1851 * VkSubpassDescriptionDepthStencilResolve::stencilResolveMode is
1852 * ignored if the VkFormat of the pDepthStencilResolveAttachment
1853 * does not have a stencil component."
1854 *
1855 * TODO: Should we handle this here or when we create the render
1856 * pass? Handling it here makes load ops "correct" in the sense
1857 * that, if we resolve to the wrong aspect, we will still consider
1858 * it bound and clear it if requested.
1859 */
1860 VkResolveModeFlagBits depth_resolve_mode = VK_RESOLVE_MODE_NONE;
1861 if (res_rp_att->aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
1862 depth_resolve_mode = subpass->depth_resolve_mode;
1863
1864 VkResolveModeFlagBits stencil_resolve_mode = VK_RESOLVE_MODE_NONE;
1865 if (res_rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
1866 stencil_resolve_mode = subpass->stencil_resolve_mode;
1867
1868 VkImageAspectFlags resolved_aspects = 0;
1869
1870 if (depth_resolve_mode != VK_RESOLVE_MODE_NONE) {
1871 depth_attachment.resolveMode = depth_resolve_mode;
1872 if (sp_att->resolve) {
1873 depth_attachment.resolveImageView =
1874 vk_image_view_to_handle(res_att_state->image_view);
1875 depth_attachment.resolveImageLayout =
1876 sp_att->resolve->layout;
1877 }
1878
1879 resolved_aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
1880 }
1881
1882 if (stencil_resolve_mode != VK_RESOLVE_MODE_NONE) {
1883 stencil_attachment.resolveMode = stencil_resolve_mode;
1884 if (sp_att->resolve) {
1885 stencil_attachment.resolveImageView =
1886 vk_image_view_to_handle(res_att_state->image_view);
1887 stencil_attachment.resolveImageLayout =
1888 sp_att->resolve->stencil_layout;
1889 }
1890
1891 resolved_aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
1892 }
1893
1894 if (sp_att->resolve && resolved_aspects == rp_att->aspects) {
1895 /* The resolve attachment is entirely overwritten by the
1896 * resolve operation so the load op really doesn't matter.
1897 * We can consider the resolve as being the load.
1898 */
1899 res_att_state->views_loaded |= subpass->view_mask;
1900 }
1901 }
1902 }
1903
1904 /* Next, handle any barriers we need. This may include a general
1905 * VkMemoryBarrier for subpass dependencies and it may include some
1906 * number of VkImageMemoryBarriers for layout transitions.
1907 */
1908
1909 bool needs_mem_barrier = false;
1910 VkMemoryBarrier2 mem_barrier = {
1911 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
1912 };
1913 for (uint32_t d = 0; d < pass->dependency_count; d++) {
1914 const struct vk_subpass_dependency *dep = &pass->dependencies[d];
1915 if (dep->dst_subpass != subpass_idx)
1916 continue;
1917
1918 if (dep->flags & VK_DEPENDENCY_VIEW_LOCAL_BIT) {
1919 /* From the Vulkan 1.3.204 spec:
1920 *
1921 * VUID-VkSubpassDependency2-dependencyFlags-03091
1922 *
1923 * "If dependencyFlags includes VK_DEPENDENCY_VIEW_LOCAL_BIT,
1924 * dstSubpass must not be equal to VK_SUBPASS_EXTERNAL"
1925 */
1926 assert(dep->src_subpass != VK_SUBPASS_EXTERNAL);
1927
1928 assert(dep->src_subpass < pass->subpass_count);
1929 const struct vk_subpass *src_subpass =
1930 &pass->subpasses[dep->src_subpass];
1931
1932 /* Figure out the set of views in the source subpass affected by this
1933 * dependency.
1934 */
1935 uint32_t src_dep_view_mask = subpass->view_mask;
1936 if (dep->view_offset >= 0)
1937 src_dep_view_mask <<= dep->view_offset;
1938 else
1939 src_dep_view_mask >>= -dep->view_offset;
1940
1941 /* From the Vulkan 1.3.204 spec:
1942 *
1943 * "If the dependency is view-local, then each view (dstView) in
1944 * the destination subpass depends on the view dstView +
1945 * pViewOffsets[dependency] in the source subpass. If there is not
1946 * such a view in the source subpass, then this dependency does
1947 * not affect that view in the destination subpass."
1948 */
1949 if (!(src_subpass->view_mask & src_dep_view_mask))
1950 continue;
1951 }
1952
1953 needs_mem_barrier = true;
1954 mem_barrier.srcStageMask |= dep->src_stage_mask;
1955 mem_barrier.srcAccessMask |= dep->src_access_mask;
1956 mem_barrier.dstStageMask |= dep->dst_stage_mask;
1957 mem_barrier.dstAccessMask |= dep->dst_access_mask;
1958 }
1959
1960 if (subpass_idx == 0) {
1961 /* From the Vulkan 1.3.232 spec:
1962 *
1963 * "If there is no subpass dependency from VK_SUBPASS_EXTERNAL to the
1964 * first subpass that uses an attachment, then an implicit subpass
1965 * dependency exists from VK_SUBPASS_EXTERNAL to the first subpass it
1966 * is used in. The implicit subpass dependency only exists if there
1967 * exists an automatic layout transition away from initialLayout. The
1968 * subpass dependency operates as if defined with the following
1969 * parameters:
1970 *
1971 * VkSubpassDependency implicitDependency = {
1972 * .srcSubpass = VK_SUBPASS_EXTERNAL;
1973 * .dstSubpass = firstSubpass; // First subpass attachment is used in
1974 * .srcStageMask = VK_PIPELINE_STAGE_NONE;
1975 * .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1976 * .srcAccessMask = 0;
1977 * .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
1978 * VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
1979 * VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1980 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1981 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1982 * .dependencyFlags = 0;
1983 * };"
1984 *
1985 * We could track individual subpasses and attachments and views to make
1986 * sure we only insert this barrier when it's absolutely necessary.
1987 * However, this is only going to happen for the first subpass and
1988 * you're probably going to take a stall in BeginRenderPass() anyway.
1989 * If this is ever a perf problem, we can re-evaluate and do something
1990 * more intellegent at that time.
1991 */
1992 needs_mem_barrier = true;
1993 mem_barrier.dstStageMask |= VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1994 mem_barrier.dstAccessMask |= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
1995 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
1996 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1997 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1998 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1999 }
2000
2001 uint32_t max_image_barrier_count = 0;
2002 for (uint32_t a = 0; a < subpass->attachment_count; a++) {
2003 const struct vk_subpass_attachment *sp_att = &subpass->attachments[a];
2004 if (sp_att->attachment == VK_ATTACHMENT_UNUSED)
2005 continue;
2006
2007 assert(sp_att->attachment < pass->attachment_count);
2008 const struct vk_render_pass_attachment *rp_att =
2009 &pass->attachments[sp_att->attachment];
2010
2011 max_image_barrier_count += util_bitcount(subpass->view_mask) *
2012 util_bitcount(rp_att->aspects);
2013 }
2014 if (pass->fragment_density_map.attachment != VK_ATTACHMENT_UNUSED)
2015 max_image_barrier_count += util_bitcount(subpass->view_mask);
2016 STACK_ARRAY(VkImageMemoryBarrier2, image_barriers, max_image_barrier_count);
2017 uint32_t image_barrier_count = 0;
2018
2019 for (uint32_t a = 0; a < subpass->attachment_count; a++) {
2020 const struct vk_subpass_attachment *sp_att = &subpass->attachments[a];
2021 if (sp_att->attachment == VK_ATTACHMENT_UNUSED)
2022 continue;
2023
2024 /* If we're using an initial layout, the attachment will already be
2025 * marked as transitioned and this will be a no-op.
2026 */
2027 transition_attachment(cmd_buffer, sp_att->attachment,
2028 subpass->view_mask,
2029 sp_att->layout, sp_att->stencil_layout,
2030 &image_barrier_count,
2031 max_image_barrier_count,
2032 image_barriers);
2033 }
2034 if (pass->fragment_density_map.attachment != VK_ATTACHMENT_UNUSED) {
2035 transition_attachment(cmd_buffer, pass->fragment_density_map.attachment,
2036 subpass->view_mask,
2037 pass->fragment_density_map.layout,
2038 VK_IMAGE_LAYOUT_UNDEFINED,
2039 &image_barrier_count,
2040 max_image_barrier_count,
2041 image_barriers);
2042 }
2043 assert(image_barrier_count <= max_image_barrier_count);
2044
2045 if (needs_mem_barrier || image_barrier_count > 0) {
2046 const VkDependencyInfo dependency_info = {
2047 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
2048 .dependencyFlags = 0,
2049 .memoryBarrierCount = needs_mem_barrier ? 1 : 0,
2050 .pMemoryBarriers = needs_mem_barrier ? &mem_barrier : NULL,
2051 .imageMemoryBarrierCount = image_barrier_count,
2052 .pImageMemoryBarriers = image_barrier_count > 0 ?
2053 image_barriers : NULL,
2054 };
2055 disp->CmdPipelineBarrier2(vk_command_buffer_to_handle(cmd_buffer),
2056 &dependency_info);
2057 }
2058
2059 STACK_ARRAY_FINISH(image_barriers);
2060
2061 /* Next, handle any VK_ATTACHMENT_LOAD_OP_CLEAR that we couldn't handle
2062 * directly by emitting a quick vkCmdBegin/EndRendering to do the load.
2063 */
2064 for (uint32_t a = 0; a < subpass->attachment_count; a++) {
2065 const struct vk_subpass_attachment *sp_att = &subpass->attachments[a];
2066 if (sp_att->attachment == VK_ATTACHMENT_UNUSED)
2067 continue;
2068
2069 load_attachment(cmd_buffer, sp_att->attachment, subpass->view_mask,
2070 sp_att->layout, sp_att->stencil_layout);
2071 }
2072
2073 /* TODO: Handle preserve attachments
2074 *
2075 * For immediate renderers, this isn't a big deal as LOAD_OP_LOAD and
2076 * STORE_OP_STORE are effectively free. However, before this gets used on
2077 * a tiling GPU, we should really hook up preserve attachments and use them
2078 * to determine when we can use LOAD/STORE_OP_DONT_CARE between subpasses.
2079 */
2080
2081 VkRenderingInfo rendering = {
2082 .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
2083 .renderArea = cmd_buffer->render_area,
2084 .layerCount = pass->is_multiview ? 1 : framebuffer->layers,
2085 .viewMask = pass->is_multiview ? subpass->view_mask : 0,
2086 .colorAttachmentCount = subpass->color_count,
2087 .pColorAttachments = color_attachments,
2088 .pDepthAttachment = &depth_attachment,
2089 .pStencilAttachment = &stencil_attachment,
2090 };
2091
2092 VkRenderingFragmentShadingRateAttachmentInfoKHR fsr_attachment;
2093 if (subpass->fragment_shading_rate_attachment) {
2094 const struct vk_subpass_attachment *sp_att =
2095 subpass->fragment_shading_rate_attachment;
2096
2097 assert(sp_att->attachment < pass->attachment_count);
2098 struct vk_attachment_state *att_state =
2099 &cmd_buffer->attachments[sp_att->attachment];
2100
2101 /* Fragment shading rate attachments have no loadOp (it's implicitly
2102 * LOAD_OP_LOAD) so we need to ensure the load op happens.
2103 */
2104 load_attachment(cmd_buffer, sp_att->attachment, subpass->view_mask,
2105 sp_att->layout, sp_att->stencil_layout);
2106
2107 fsr_attachment = (VkRenderingFragmentShadingRateAttachmentInfoKHR) {
2108 .sType = VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,
2109 .imageView = vk_image_view_to_handle(att_state->image_view),
2110 .imageLayout = sp_att->layout,
2111 .shadingRateAttachmentTexelSize =
2112 subpass->fragment_shading_rate_attachment_texel_size,
2113 };
2114 __vk_append_struct(&rendering, &fsr_attachment);
2115 }
2116
2117 VkRenderingFragmentDensityMapAttachmentInfoEXT fdm_attachment;
2118 if (pass->fragment_density_map.attachment != VK_ATTACHMENT_UNUSED) {
2119 assert(pass->fragment_density_map.attachment < pass->attachment_count);
2120 struct vk_attachment_state *att_state =
2121 &cmd_buffer->attachments[pass->fragment_density_map.attachment];
2122
2123 /* From the Vulkan 1.3.125 spec:
2124 *
2125 * VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-fragmentDensityMapAttachment-02550
2126 *
2127 * If fragmentDensityMapAttachment is not VK_ATTACHMENT_UNUSED,
2128 * fragmentDensityMapAttachment must reference an attachment with a
2129 * loadOp equal to VK_ATTACHMENT_LOAD_OP_LOAD or
2130 * VK_ATTACHMENT_LOAD_OP_DONT_CARE
2131 *
2132 * This means we don't have to implement the load op.
2133 */
2134
2135 fdm_attachment = (VkRenderingFragmentDensityMapAttachmentInfoEXT) {
2136 .sType = VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT,
2137 .imageView = vk_image_view_to_handle(att_state->image_view),
2138 .imageLayout = pass->fragment_density_map.layout,
2139 };
2140 __vk_append_struct(&rendering, &fdm_attachment);
2141 }
2142
2143 VkSampleLocationsInfoEXT sample_locations_tmp;
2144 if (sample_locations) {
2145 sample_locations_tmp = *sample_locations;
2146 __vk_append_struct(&rendering, &sample_locations_tmp);
2147 }
2148
2149 /* Append this one last because it lives in the subpass and we don't want
2150 * to be changed by appending other structures later.
2151 */
2152 if (subpass->mrtss.multisampledRenderToSingleSampledEnable)
2153 __vk_append_struct(&rendering, (void *)&subpass->mrtss);
2154
2155 disp->CmdBeginRendering(vk_command_buffer_to_handle(cmd_buffer),
2156 &rendering);
2157
2158 STACK_ARRAY_FINISH(color_attachments);
2159 STACK_ARRAY_FINISH(color_attachment_initial_layouts);
2160 }
2161
2162 static void
end_subpass(struct vk_command_buffer * cmd_buffer,const VkSubpassEndInfo * end_info)2163 end_subpass(struct vk_command_buffer *cmd_buffer,
2164 const VkSubpassEndInfo *end_info)
2165 {
2166 const struct vk_render_pass *pass = cmd_buffer->render_pass;
2167 const uint32_t subpass_idx = cmd_buffer->subpass_idx;
2168 struct vk_device_dispatch_table *disp =
2169 &cmd_buffer->base.device->dispatch_table;
2170
2171 disp->CmdEndRendering(vk_command_buffer_to_handle(cmd_buffer));
2172
2173 bool needs_mem_barrier = false;
2174 VkMemoryBarrier2 mem_barrier = {
2175 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
2176 };
2177 for (uint32_t d = 0; d < pass->dependency_count; d++) {
2178 const struct vk_subpass_dependency *dep = &pass->dependencies[d];
2179 if (dep->src_subpass != subpass_idx)
2180 continue;
2181
2182 if (dep->dst_subpass != VK_SUBPASS_EXTERNAL)
2183 continue;
2184
2185 needs_mem_barrier = true;
2186 mem_barrier.srcStageMask |= dep->src_stage_mask;
2187 mem_barrier.srcAccessMask |= dep->src_access_mask;
2188 mem_barrier.dstStageMask |= dep->dst_stage_mask;
2189 mem_barrier.dstAccessMask |= dep->dst_access_mask;
2190 }
2191
2192 if (subpass_idx == pass->subpass_count - 1) {
2193 /* From the Vulkan 1.3.232 spec:
2194 *
2195 * "Similarly, if there is no subpass dependency from the last
2196 * subpass that uses an attachment to VK_SUBPASS_EXTERNAL, then an
2197 * implicit subpass dependency exists from the last subpass it is
2198 * used in to VK_SUBPASS_EXTERNAL. The implicit subpass dependency
2199 * only exists if there exists an automatic layout transition into
2200 * finalLayout. The subpass dependency operates as if defined with
2201 * the following parameters:
2202 *
2203 * VkSubpassDependency implicitDependency = {
2204 * .srcSubpass = lastSubpass; // Last subpass attachment is used in
2205 * .dstSubpass = VK_SUBPASS_EXTERNAL;
2206 * .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
2207 * .dstStageMask = VK_PIPELINE_STAGE_NONE;
2208 * .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2209 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
2210 * .dstAccessMask = 0;
2211 * .dependencyFlags = 0;
2212 * };"
2213 *
2214 * We could track individual subpasses and attachments and views to make
2215 * sure we only insert this barrier when it's absolutely necessary.
2216 * However, this is only going to happen for the last subpass and
2217 * you're probably going to take a stall in EndRenderPass() anyway.
2218 * If this is ever a perf problem, we can re-evaluate and do something
2219 * more intellegent at that time.
2220 */
2221 needs_mem_barrier = true;
2222 mem_barrier.srcStageMask |= VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
2223 mem_barrier.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2224 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
2225 }
2226
2227 if (needs_mem_barrier) {
2228 const VkDependencyInfo dependency_info = {
2229 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
2230 .dependencyFlags = 0,
2231 .memoryBarrierCount = 1,
2232 .pMemoryBarriers = &mem_barrier,
2233 };
2234 disp->CmdPipelineBarrier2(vk_command_buffer_to_handle(cmd_buffer),
2235 &dependency_info);
2236 }
2237 }
2238
2239 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,const VkRenderPassBeginInfo * pRenderPassBeginInfo,const VkSubpassBeginInfo * pSubpassBeginInfo)2240 vk_common_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,
2241 const VkRenderPassBeginInfo *pRenderPassBeginInfo,
2242 const VkSubpassBeginInfo *pSubpassBeginInfo)
2243 {
2244 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
2245 VK_FROM_HANDLE(vk_render_pass, pass, pRenderPassBeginInfo->renderPass);
2246 VK_FROM_HANDLE(vk_framebuffer, framebuffer,
2247 pRenderPassBeginInfo->framebuffer);
2248
2249 assert(cmd_buffer->render_pass == NULL);
2250 cmd_buffer->render_pass = pass;
2251 cmd_buffer->subpass_idx = 0;
2252
2253 assert(cmd_buffer->framebuffer == NULL);
2254 cmd_buffer->framebuffer = framebuffer;
2255
2256 cmd_buffer->render_area = pRenderPassBeginInfo->renderArea;
2257
2258 assert(cmd_buffer->attachments == NULL);
2259 if (pass->attachment_count > ARRAY_SIZE(cmd_buffer->_attachments)) {
2260 cmd_buffer->attachments = malloc(pass->attachment_count *
2261 sizeof(*cmd_buffer->attachments));
2262 } else {
2263 cmd_buffer->attachments = cmd_buffer->_attachments;
2264 }
2265
2266 const VkRenderPassAttachmentBeginInfo *attach_begin =
2267 vk_find_struct_const(pRenderPassBeginInfo,
2268 RENDER_PASS_ATTACHMENT_BEGIN_INFO);
2269 if (!attach_begin)
2270 assert(pass->attachment_count == framebuffer->attachment_count);
2271
2272 const VkImageView *image_views;
2273 if (attach_begin && attach_begin->attachmentCount != 0) {
2274 assert(attach_begin->attachmentCount == pass->attachment_count);
2275 image_views = attach_begin->pAttachments;
2276 } else {
2277 assert(framebuffer->attachment_count >= pass->attachment_count);
2278 image_views = framebuffer->attachments;
2279 }
2280
2281 for (uint32_t a = 0; a < pass->attachment_count; ++a) {
2282 VK_FROM_HANDLE(vk_image_view, image_view, image_views[a]);
2283 const struct vk_render_pass_attachment *pass_att = &pass->attachments[a];
2284 struct vk_attachment_state *att_state = &cmd_buffer->attachments[a];
2285
2286 /* From the Vulkan 1.3.204 spec:
2287 *
2288 * VUID-VkFramebufferCreateInfo-pAttachments-00880
2289 *
2290 * "If renderpass is not VK_NULL_HANDLE and flags does not include
2291 * VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments
2292 * must have been created with a VkFormat value that matches the
2293 * VkFormat specified by the corresponding VkAttachmentDescription in
2294 * renderPass"
2295 *
2296 * and
2297 *
2298 * VUID-VkRenderPassBeginInfo-framebuffer-03216
2299 *
2300 * "If framebuffer was created with a VkFramebufferCreateInfo::flags
2301 * value that included VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each
2302 * element of the pAttachments member of a
2303 * VkRenderPassAttachmentBeginInfo structure included in the pNext
2304 * chain must be a VkImageView of an image created with a value of
2305 * VkImageViewCreateInfo::format equal to the corresponding value of
2306 * VkAttachmentDescription::format in renderPass"
2307 */
2308 assert(image_view->format == pass_att->format);
2309
2310 /* From the Vulkan 1.3.204 spec:
2311 *
2312 * VUID-VkFramebufferCreateInfo-pAttachments-00881
2313 *
2314 * "If renderpass is not VK_NULL_HANDLE and flags does not include
2315 * VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments
2316 * must have been created with a samples value that matches the
2317 * samples value specified by the corresponding
2318 * VkAttachmentDescription in renderPass"
2319 *
2320 * and
2321 *
2322 * UID-VkRenderPassBeginInfo-framebuffer-03217
2323 *
2324 * "If framebuffer was created with a VkFramebufferCreateInfo::flags
2325 * value that included VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each
2326 * element of the pAttachments member of a
2327 * VkRenderPassAttachmentBeginInfo structure included in the pNext
2328 * chain must be a VkImageView of an image created with a value of
2329 * VkImageCreateInfo::samples equal to the corresponding value of
2330 * VkAttachmentDescription::samples in renderPass"
2331 */
2332 assert(image_view->image->samples == pass_att->samples);
2333
2334 /* From the Vulkan 1.3.204 spec:
2335 *
2336 * If multiview is enabled and the shading rate attachment has
2337 * multiple layers, the shading rate attachment texel is selected
2338 * from the layer determined by the ViewIndex built-in. If multiview
2339 * is disabled, and both the shading rate attachment and the
2340 * framebuffer have multiple layers, the shading rate attachment
2341 * texel is selected from the layer determined by the Layer built-in.
2342 * Otherwise, the texel is unconditionally selected from the first
2343 * layer of the attachment.
2344 */
2345 if (!(image_view->usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR))
2346 assert(util_last_bit(pass_att->view_mask) <= image_view->layer_count);
2347
2348 *att_state = (struct vk_attachment_state) {
2349 .image_view = image_view,
2350 .views_loaded = 0,
2351 };
2352
2353 for (uint32_t v = 0; v < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT; v++) {
2354 att_state->views[v] = (struct vk_attachment_view_state) {
2355 .layout = pass_att->initial_layout,
2356 .stencil_layout = pass_att->initial_stencil_layout,
2357 };
2358 }
2359
2360 if (a < pRenderPassBeginInfo->clearValueCount)
2361 att_state->clear_value = pRenderPassBeginInfo->pClearValues[a];
2362 }
2363
2364 const VkRenderPassSampleLocationsBeginInfoEXT *rp_sl_info =
2365 vk_find_struct_const(pRenderPassBeginInfo->pNext,
2366 RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT);
2367 if (rp_sl_info) {
2368 cmd_buffer->pass_sample_locations = clone_rp_sample_locations(rp_sl_info);
2369 assert(cmd_buffer->pass_sample_locations);
2370
2371 for (uint32_t i = 0; i < rp_sl_info->attachmentInitialSampleLocationsCount; i++) {
2372 const VkAttachmentSampleLocationsEXT *att_sl =
2373 &rp_sl_info->pAttachmentInitialSampleLocations[i];
2374
2375 assert(att_sl->attachmentIndex < pass->attachment_count);
2376 struct vk_attachment_state *att_state =
2377 &cmd_buffer->attachments[att_sl->attachmentIndex];
2378
2379 /* Sample locations only matter for depth/stencil images created with
2380 * VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT
2381 */
2382 if (vk_format_is_depth_or_stencil(att_state->image_view->format) &&
2383 (att_state->image_view->image->create_flags &
2384 VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT)) {
2385 for (uint32_t v = 0; v < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT; v++)
2386 att_state->views[v].sample_locations = &att_sl->sampleLocationsInfo;
2387 }
2388 }
2389 }
2390
2391 begin_subpass(cmd_buffer, pSubpassBeginInfo);
2392 }
2393
2394 void
vk_command_buffer_reset_render_pass(struct vk_command_buffer * cmd_buffer)2395 vk_command_buffer_reset_render_pass(struct vk_command_buffer *cmd_buffer)
2396 {
2397 cmd_buffer->render_pass = NULL;
2398 cmd_buffer->subpass_idx = 0;
2399 cmd_buffer->framebuffer = NULL;
2400 if (cmd_buffer->attachments != cmd_buffer->_attachments)
2401 free(cmd_buffer->attachments);
2402 cmd_buffer->attachments = NULL;
2403 if (cmd_buffer->pass_sample_locations != NULL)
2404 vk_free(vk_default_allocator(), cmd_buffer->pass_sample_locations);
2405 cmd_buffer->pass_sample_locations = NULL;
2406 }
2407
2408 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdNextSubpass2(VkCommandBuffer commandBuffer,const VkSubpassBeginInfo * pSubpassBeginInfo,const VkSubpassEndInfo * pSubpassEndInfo)2409 vk_common_CmdNextSubpass2(VkCommandBuffer commandBuffer,
2410 const VkSubpassBeginInfo *pSubpassBeginInfo,
2411 const VkSubpassEndInfo *pSubpassEndInfo)
2412 {
2413 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
2414
2415 end_subpass(cmd_buffer, pSubpassEndInfo);
2416 cmd_buffer->subpass_idx++;
2417 begin_subpass(cmd_buffer, pSubpassBeginInfo);
2418 }
2419
2420 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdEndRenderPass2(VkCommandBuffer commandBuffer,const VkSubpassEndInfo * pSubpassEndInfo)2421 vk_common_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
2422 const VkSubpassEndInfo *pSubpassEndInfo)
2423 {
2424 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
2425 const struct vk_render_pass *pass = cmd_buffer->render_pass;
2426 struct vk_device_dispatch_table *disp =
2427 &cmd_buffer->base.device->dispatch_table;
2428
2429 end_subpass(cmd_buffer, pSubpassEndInfo);
2430
2431 /* Make sure all our attachments end up in their finalLayout */
2432
2433 uint32_t max_image_barrier_count = 0;
2434 for (uint32_t a = 0; a < pass->attachment_count; a++) {
2435 const struct vk_render_pass_attachment *rp_att = &pass->attachments[a];
2436
2437 max_image_barrier_count += util_bitcount(pass->view_mask) *
2438 util_bitcount(rp_att->aspects);
2439 }
2440 STACK_ARRAY(VkImageMemoryBarrier2, image_barriers, max_image_barrier_count);
2441 uint32_t image_barrier_count = 0;
2442
2443 for (uint32_t a = 0; a < pass->attachment_count; a++) {
2444 const struct vk_render_pass_attachment *rp_att = &pass->attachments[a];
2445
2446 transition_attachment(cmd_buffer, a, pass->view_mask,
2447 rp_att->final_layout,
2448 rp_att->final_stencil_layout,
2449 &image_barrier_count,
2450 max_image_barrier_count,
2451 image_barriers);
2452 }
2453 assert(image_barrier_count <= max_image_barrier_count);
2454
2455 if (image_barrier_count > 0) {
2456 const VkDependencyInfo dependency_info = {
2457 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
2458 .dependencyFlags = 0,
2459 .imageMemoryBarrierCount = image_barrier_count,
2460 .pImageMemoryBarriers = image_barriers,
2461 };
2462 disp->CmdPipelineBarrier2(vk_command_buffer_to_handle(cmd_buffer),
2463 &dependency_info);
2464 }
2465
2466 STACK_ARRAY_FINISH(image_barriers);
2467
2468 vk_command_buffer_reset_render_pass(cmd_buffer);
2469 }
2470