turnip: replace a memset(0) with zalloc in CreateRenderPass
[mesa.git] / src / freedreno / vulkan / tu_pass.c
1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 */
27 #include "tu_private.h"
28
29 #include "vk_util.h"
30 #include "vk_format.h"
31
32 static void
33 tu_render_pass_add_subpass_dep(struct tu_render_pass *pass,
34 const VkSubpassDependency2 *dep)
35 {
36 uint32_t src = dep->srcSubpass;
37 uint32_t dst = dep->dstSubpass;
38
39 /* Ignore subpass self-dependencies as they allow the app to call
40 * vkCmdPipelineBarrier() inside the render pass and the driver should only
41 * do the barrier when called, not when starting the render pass.
42 */
43 if (src == dst)
44 return;
45
46 struct tu_subpass_barrier *src_barrier;
47 if (src == VK_SUBPASS_EXTERNAL) {
48 src_barrier = &pass->subpasses[0].start_barrier;
49 } else if (src == pass->subpass_count - 1) {
50 src_barrier = &pass->end_barrier;
51 } else {
52 src_barrier = &pass->subpasses[src + 1].start_barrier;
53 }
54
55 struct tu_subpass_barrier *dst_barrier;
56 if (dst == VK_SUBPASS_EXTERNAL) {
57 dst_barrier = &pass->end_barrier;
58 } else {
59 dst_barrier = &pass->subpasses[dst].start_barrier;
60 }
61
62 if (dep->dstStageMask != VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT)
63 src_barrier->src_stage_mask |= dep->srcStageMask;
64 src_barrier->src_access_mask |= dep->srcAccessMask;
65 dst_barrier->dst_access_mask |= dep->dstAccessMask;
66 if (src == VK_SUBPASS_EXTERNAL)
67 pass->subpasses[dst].has_external_src = true;
68 if (dst == VK_SUBPASS_EXTERNAL)
69 pass->subpasses[src].has_external_dst = true;
70 }
71
72 /* We currently only care about undefined layouts, because we have to
73 * flush/invalidate CCU for those. PREINITIALIZED is the same thing as
74 * UNDEFINED for anything not linear tiled, but we don't know yet whether the
75 * images used are tiled, so just assume they are.
76 */
77
78 static bool
79 layout_undefined(VkImageLayout layout)
80 {
81 return layout == VK_IMAGE_LAYOUT_UNDEFINED ||
82 layout == VK_IMAGE_LAYOUT_PREINITIALIZED;
83 }
84
85 /* This implements the following bit of spec text:
86 *
87 * If there is no subpass dependency from VK_SUBPASS_EXTERNAL to the
88 * first subpass that uses an attachment, then an implicit subpass
89 * dependency exists from VK_SUBPASS_EXTERNAL to the first subpass it is
90 * used in. The implicit subpass dependency only exists if there
91 * exists an automatic layout transition away from initialLayout.
92 * The subpass dependency operates as if defined with the
93 * following parameters:
94 *
95 * VkSubpassDependency implicitDependency = {
96 * .srcSubpass = VK_SUBPASS_EXTERNAL;
97 * .dstSubpass = firstSubpass; // First subpass attachment is used in
98 * .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
99 * .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
100 * .srcAccessMask = 0;
101 * .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
102 * VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
103 * VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
104 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
105 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
106 * .dependencyFlags = 0;
107 * };
108 *
109 * Similarly, if there is no subpass dependency from the last subpass
110 * that uses an attachment to VK_SUBPASS_EXTERNAL, then an implicit
111 * subpass dependency exists from the last subpass it is used in to
112 * VK_SUBPASS_EXTERNAL. The implicit subpass dependency only exists
113 * if there exists an automatic layout transition into finalLayout.
114 * The subpass dependency operates as if defined with the following
115 * parameters:
116 *
117 * VkSubpassDependency implicitDependency = {
118 * .srcSubpass = lastSubpass; // Last subpass attachment is used in
119 * .dstSubpass = VK_SUBPASS_EXTERNAL;
120 * .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
121 * .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
122 * .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
123 * VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
124 * VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
125 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
126 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
127 * .dstAccessMask = 0;
128 * .dependencyFlags = 0;
129 * };
130 *
131 * Note: currently this is the only use we have for layout transitions,
132 * besides needing to invalidate CCU at the beginning, so we also flag
133 * transitions from UNDEFINED here.
134 */
135 static void
136 tu_render_pass_add_implicit_deps(struct tu_render_pass *pass)
137 {
138 bool att_used[pass->attachment_count];
139
140 memset(att_used, 0, sizeof(att_used));
141
142 for (unsigned i = 0; i < pass->subpass_count; i++) {
143 struct tu_subpass *subpass = &pass->subpasses[i];
144 if (!subpass->has_external_src)
145 continue;
146
147 bool src_implicit_dep = false;
148
149 for (unsigned j = 0; j < subpass->input_count; j++) {
150 unsigned att_idx = subpass->input_attachments[j].attachment;
151 if (att_idx == VK_ATTACHMENT_UNUSED)
152 continue;
153 struct tu_render_pass_attachment *att = &pass->attachments[att_idx];
154 if (att->initial_layout != subpass->input_attachments[j].layout &&
155 !att_used[att_idx]) {
156 src_implicit_dep = true;
157 }
158 att_used[att_idx] = true;
159 }
160
161 for (unsigned j = 0; j < subpass->color_count; j++) {
162 unsigned att_idx = subpass->color_attachments[j].attachment;
163 if (att_idx == VK_ATTACHMENT_UNUSED)
164 continue;
165 struct tu_render_pass_attachment *att = &pass->attachments[att_idx];
166 if (att->initial_layout != subpass->color_attachments[j].layout &&
167 !att_used[att_idx]) {
168 src_implicit_dep = true;
169 }
170 att_used[att_idx] = true;
171 }
172
173 if (subpass->resolve_attachments) {
174 for (unsigned j = 0; j < subpass->color_count; j++) {
175 unsigned att_idx = subpass->resolve_attachments[j].attachment;
176 if (att_idx == VK_ATTACHMENT_UNUSED)
177 continue;
178 struct tu_render_pass_attachment *att = &pass->attachments[att_idx];
179 if (att->initial_layout != subpass->resolve_attachments[j].layout &&
180 !att_used[att_idx]) {
181 src_implicit_dep = true;
182 }
183 att_used[att_idx] = true;
184 }
185 }
186
187 if (src_implicit_dep) {
188 tu_render_pass_add_subpass_dep(pass, &(VkSubpassDependency2KHR) {
189 .srcSubpass = VK_SUBPASS_EXTERNAL,
190 .dstSubpass = i,
191 .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
192 .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
193 .srcAccessMask = 0,
194 .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
195 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
196 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
197 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
198 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
199 .dependencyFlags = 0,
200 });
201 }
202 }
203
204 memset(att_used, 0, sizeof(att_used));
205
206 for (int i = pass->subpass_count - 1; i >= 0; i--) {
207 struct tu_subpass *subpass = &pass->subpasses[i];
208 if (!subpass->has_external_dst)
209 continue;
210
211 bool dst_implicit_dep = false;
212
213 for (unsigned j = 0; j < subpass->input_count; j++) {
214 unsigned att_idx = subpass->input_attachments[j].attachment;
215 if (att_idx == VK_ATTACHMENT_UNUSED)
216 continue;
217 struct tu_render_pass_attachment *att = &pass->attachments[att_idx];
218 if (att->final_layout != subpass->input_attachments[j].layout &&
219 !att_used[att_idx]) {
220 dst_implicit_dep = true;
221 }
222 att_used[att_idx] = true;
223 }
224
225 for (unsigned j = 0; j < subpass->color_count; j++) {
226 unsigned att_idx = subpass->color_attachments[j].attachment;
227 if (att_idx == VK_ATTACHMENT_UNUSED)
228 continue;
229 struct tu_render_pass_attachment *att = &pass->attachments[att_idx];
230 if (att->final_layout != subpass->color_attachments[j].layout &&
231 !att_used[att_idx]) {
232 dst_implicit_dep = true;
233 }
234 att_used[att_idx] = true;
235 }
236
237 if (subpass->resolve_attachments) {
238 for (unsigned j = 0; j < subpass->color_count; j++) {
239 unsigned att_idx = subpass->resolve_attachments[j].attachment;
240 if (att_idx == VK_ATTACHMENT_UNUSED)
241 continue;
242 struct tu_render_pass_attachment *att = &pass->attachments[att_idx];
243 if (att->final_layout != subpass->resolve_attachments[j].layout &&
244 !att_used[att_idx]) {
245 dst_implicit_dep = true;
246 }
247 att_used[att_idx] = true;
248 }
249 }
250
251 if (dst_implicit_dep) {
252 tu_render_pass_add_subpass_dep(pass, &(VkSubpassDependency2KHR) {
253 .srcSubpass = i,
254 .dstSubpass = VK_SUBPASS_EXTERNAL,
255 .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
256 .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
257 .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
258 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
259 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
260 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
261 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
262 .dstAccessMask = 0,
263 .dependencyFlags = 0,
264 });
265 }
266 }
267
268 /* Handle UNDEFINED transitions, similar to the handling in tu_barrier().
269 * Assume that if an attachment has an initial layout of UNDEFINED, it gets
270 * transitioned eventually.
271 */
272 for (unsigned i = 0; i < pass->attachment_count; i++) {
273 if (layout_undefined(pass->attachments[i].initial_layout)) {
274 if (vk_format_is_depth_or_stencil(pass->attachments[i].format)) {
275 pass->subpasses[0].start_barrier.incoherent_ccu_depth = true;
276 } else {
277 pass->subpasses[0].start_barrier.incoherent_ccu_color = true;
278 }
279 }
280 }
281 }
282
283 static void update_samples(struct tu_subpass *subpass,
284 VkSampleCountFlagBits samples)
285 {
286 assert(subpass->samples == 0 || subpass->samples == samples);
287 subpass->samples = samples;
288 }
289
290 static void
291 create_render_pass_common(struct tu_render_pass *pass,
292 const struct tu_physical_device *phys_dev)
293 {
294 uint32_t block_align_shift = 4; /* log2(gmem_align/(tile_align_w*tile_align_h)) */
295 uint32_t tile_align_w = phys_dev->tile_align_w;
296 uint32_t gmem_align = (1 << block_align_shift) * tile_align_w * TILE_ALIGN_H;
297
298 /* calculate total bytes per pixel */
299 uint32_t cpp_total = 0;
300 for (uint32_t i = 0; i < pass->attachment_count; i++) {
301 struct tu_render_pass_attachment *att = &pass->attachments[i];
302 if (att->gmem_offset >= 0) {
303 cpp_total += att->cpp;
304 /* texture pitch must be aligned to 64, use a tile_align_w that is
305 * a multiple of 64 for cpp==1 attachment to work as input attachment
306 */
307 if (att->cpp == 1 && tile_align_w % 64 != 0) {
308 tile_align_w *= 2;
309 block_align_shift -= 1;
310 }
311 }
312 }
313
314 pass->tile_align_w = tile_align_w;
315
316 /* no gmem attachments */
317 if (cpp_total == 0) {
318 /* any value non-zero value so tiling config works with no attachments */
319 pass->gmem_pixels = 1024*1024;
320 return;
321 }
322
323 /* TODO: using ccu_offset_gmem so that BLIT_OP_SCALE resolve path
324 * doesn't break things. maybe there is a better solution?
325 * TODO: this algorithm isn't optimal
326 * for example, two attachments with cpp = {1, 4}
327 * result: nblocks = {12, 52}, pixels = 196608
328 * optimal: nblocks = {13, 51}, pixels = 208896
329 */
330 uint32_t gmem_blocks = phys_dev->ccu_offset_gmem / gmem_align;
331 uint32_t offset = 0, pixels = ~0u;
332 for (uint32_t i = 0; i < pass->attachment_count; i++) {
333 struct tu_render_pass_attachment *att = &pass->attachments[i];
334 if (att->gmem_offset < 0)
335 continue;
336
337 att->gmem_offset = offset;
338
339 uint32_t align = MAX2(1, att->cpp >> block_align_shift);
340 uint32_t nblocks = MAX2((gmem_blocks * att->cpp / cpp_total) & ~(align - 1), align);
341
342 if (nblocks > gmem_blocks) {
343 pixels = 0;
344 break;
345 }
346
347 gmem_blocks -= nblocks;
348 cpp_total -= att->cpp;
349 offset += nblocks * gmem_align;
350 pixels = MIN2(pixels, nblocks * gmem_align / att->cpp);
351 }
352
353 pass->gmem_pixels = pixels;
354
355 for (uint32_t i = 0; i < pass->subpass_count; i++) {
356 struct tu_subpass *subpass = &pass->subpasses[i];
357
358 subpass->srgb_cntl = 0;
359
360 for (uint32_t i = 0; i < subpass->color_count; ++i) {
361 uint32_t a = subpass->color_attachments[i].attachment;
362 if (a == VK_ATTACHMENT_UNUSED)
363 continue;
364
365 if (vk_format_is_srgb(pass->attachments[a].format))
366 subpass->srgb_cntl |= 1 << i;
367 }
368 }
369
370 /* disable unused attachments */
371 for (uint32_t i = 0; i < pass->attachment_count; i++) {
372 struct tu_render_pass_attachment *att = &pass->attachments[i];
373 if (att->gmem_offset < 0) {
374 att->clear_mask = 0;
375 att->load = false;
376 }
377 }
378
379 tu_render_pass_add_implicit_deps(pass);
380 }
381
382 static void
383 attachment_set_ops(struct tu_render_pass_attachment *att,
384 VkAttachmentLoadOp load_op,
385 VkAttachmentLoadOp stencil_load_op,
386 VkAttachmentStoreOp store_op,
387 VkAttachmentStoreOp stencil_store_op)
388 {
389 /* load/store ops */
390 att->clear_mask =
391 (load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) ? VK_IMAGE_ASPECT_COLOR_BIT : 0;
392 att->load = (load_op == VK_ATTACHMENT_LOAD_OP_LOAD);
393 att->store = (store_op == VK_ATTACHMENT_STORE_OP_STORE);
394
395 bool stencil_clear = (stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR);
396 bool stencil_load = (stencil_load_op == VK_ATTACHMENT_LOAD_OP_LOAD);
397 bool stencil_store = (stencil_store_op == VK_ATTACHMENT_STORE_OP_STORE);
398
399 switch (att->format) {
400 case VK_FORMAT_D24_UNORM_S8_UINT: /* || stencil load/store */
401 if (att->clear_mask)
402 att->clear_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
403 if (stencil_clear)
404 att->clear_mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
405 if (stencil_load)
406 att->load = true;
407 if (stencil_store)
408 att->store = true;
409 break;
410 case VK_FORMAT_S8_UINT: /* replace load/store with stencil load/store */
411 att->clear_mask = stencil_clear ? VK_IMAGE_ASPECT_COLOR_BIT : 0;
412 att->load = stencil_load;
413 att->store = stencil_store;
414 break;
415 default:
416 break;
417 }
418 }
419
420 static void
421 translate_references(VkAttachmentReference2 **reference_ptr,
422 const VkAttachmentReference *reference,
423 uint32_t count)
424 {
425 VkAttachmentReference2 *reference2 = *reference_ptr;
426 *reference_ptr += count;
427 for (uint32_t i = 0; i < count; i++) {
428 reference2[i] = (VkAttachmentReference2) {
429 .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
430 .pNext = NULL,
431 .attachment = reference[i].attachment,
432 .layout = reference[i].layout,
433 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
434 };
435 }
436 }
437
438 VkResult
439 tu_CreateRenderPass(VkDevice device,
440 const VkRenderPassCreateInfo *pCreateInfo,
441 const VkAllocationCallbacks *pAllocator,
442 VkRenderPass *pRenderPass)
443 {
444 /* note: these counts shouldn't be excessively high, so allocating it all
445 * on the stack should be OK..
446 * also note preserve attachments aren't translated, currently unused
447 */
448 VkAttachmentDescription2 attachments[pCreateInfo->attachmentCount];
449 VkSubpassDescription2 subpasses[pCreateInfo->subpassCount];
450 VkSubpassDependency2 dependencies[pCreateInfo->dependencyCount];
451 uint32_t reference_count = 0;
452 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
453 reference_count += pCreateInfo->pSubpasses[i].inputAttachmentCount;
454 reference_count += pCreateInfo->pSubpasses[i].colorAttachmentCount;
455 if (pCreateInfo->pSubpasses[i].pResolveAttachments)
456 reference_count += pCreateInfo->pSubpasses[i].colorAttachmentCount;
457 if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment)
458 reference_count += 1;
459 }
460 VkAttachmentReference2 reference[reference_count];
461 VkAttachmentReference2 *reference_ptr = reference;
462
463 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
464 attachments[i] = (VkAttachmentDescription2) {
465 .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
466 .pNext = NULL,
467 .flags = pCreateInfo->pAttachments[i].flags,
468 .format = pCreateInfo->pAttachments[i].format,
469 .samples = pCreateInfo->pAttachments[i].samples,
470 .loadOp = pCreateInfo->pAttachments[i].loadOp,
471 .storeOp = pCreateInfo->pAttachments[i].storeOp,
472 .stencilLoadOp = pCreateInfo->pAttachments[i].stencilLoadOp,
473 .stencilStoreOp = pCreateInfo->pAttachments[i].stencilStoreOp,
474 .initialLayout = pCreateInfo->pAttachments[i].initialLayout,
475 .finalLayout = pCreateInfo->pAttachments[i].finalLayout,
476 };
477 }
478
479 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
480 subpasses[i] = (VkSubpassDescription2) {
481 .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
482 .pNext = NULL,
483 .flags = pCreateInfo->pSubpasses[i].flags,
484 .pipelineBindPoint = pCreateInfo->pSubpasses[i].pipelineBindPoint,
485 .viewMask = 0,
486 .inputAttachmentCount = pCreateInfo->pSubpasses[i].inputAttachmentCount,
487 .colorAttachmentCount = pCreateInfo->pSubpasses[i].colorAttachmentCount,
488 };
489
490 subpasses[i].pInputAttachments = reference_ptr;
491 translate_references(&reference_ptr,
492 pCreateInfo->pSubpasses[i].pInputAttachments,
493 subpasses[i].inputAttachmentCount);
494 subpasses[i].pColorAttachments = reference_ptr;
495 translate_references(&reference_ptr,
496 pCreateInfo->pSubpasses[i].pColorAttachments,
497 subpasses[i].colorAttachmentCount);
498 subpasses[i].pResolveAttachments = NULL;
499 if (pCreateInfo->pSubpasses[i].pResolveAttachments) {
500 subpasses[i].pResolveAttachments = reference_ptr;
501 translate_references(&reference_ptr,
502 pCreateInfo->pSubpasses[i].pResolveAttachments,
503 subpasses[i].colorAttachmentCount);
504 }
505 subpasses[i].pDepthStencilAttachment = NULL;
506 if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment) {
507 subpasses[i].pDepthStencilAttachment = reference_ptr;
508 translate_references(&reference_ptr,
509 pCreateInfo->pSubpasses[i].pDepthStencilAttachment,
510 1);
511 }
512 }
513
514 assert(reference_ptr == reference + reference_count);
515
516 for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
517 dependencies[i] = (VkSubpassDependency2) {
518 .sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
519 .pNext = NULL,
520 .srcSubpass = pCreateInfo->pDependencies[i].srcSubpass,
521 .dstSubpass = pCreateInfo->pDependencies[i].dstSubpass,
522 .srcStageMask = pCreateInfo->pDependencies[i].srcStageMask,
523 .dstStageMask = pCreateInfo->pDependencies[i].dstStageMask,
524 .srcAccessMask = pCreateInfo->pDependencies[i].srcAccessMask,
525 .dstAccessMask = pCreateInfo->pDependencies[i].dstAccessMask,
526 .dependencyFlags = pCreateInfo->pDependencies[i].dependencyFlags,
527 .viewOffset = 0,
528 };
529 }
530
531 VkRenderPassCreateInfo2 create_info = {
532 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
533 .pNext = pCreateInfo->pNext,
534 .flags = pCreateInfo->flags,
535 .attachmentCount = pCreateInfo->attachmentCount,
536 .pAttachments = attachments,
537 .subpassCount = pCreateInfo->subpassCount,
538 .pSubpasses = subpasses,
539 .dependencyCount = pCreateInfo->dependencyCount,
540 .pDependencies = dependencies,
541 };
542
543 return tu_CreateRenderPass2(device, &create_info, pAllocator, pRenderPass);
544 }
545
546 VkResult
547 tu_CreateRenderPass2(VkDevice _device,
548 const VkRenderPassCreateInfo2KHR *pCreateInfo,
549 const VkAllocationCallbacks *pAllocator,
550 VkRenderPass *pRenderPass)
551 {
552 TU_FROM_HANDLE(tu_device, device, _device);
553 struct tu_render_pass *pass;
554 size_t size;
555 size_t attachments_offset;
556
557 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR);
558
559 size = sizeof(*pass);
560 size += pCreateInfo->subpassCount * sizeof(pass->subpasses[0]);
561 attachments_offset = size;
562 size += pCreateInfo->attachmentCount * sizeof(pass->attachments[0]);
563
564 pass = vk_zalloc2(&device->alloc, pAllocator, size, 8,
565 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
566 if (pass == NULL)
567 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
568
569 pass->attachment_count = pCreateInfo->attachmentCount;
570 pass->subpass_count = pCreateInfo->subpassCount;
571 pass->attachments = (void *) pass + attachments_offset;
572
573 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
574 struct tu_render_pass_attachment *att = &pass->attachments[i];
575
576 att->format = pCreateInfo->pAttachments[i].format;
577 att->samples = pCreateInfo->pAttachments[i].samples;
578 att->cpp = vk_format_get_blocksize(att->format) * att->samples;
579 att->initial_layout = pCreateInfo->pAttachments[i].initialLayout;
580 att->final_layout = pCreateInfo->pAttachments[i].finalLayout;
581 att->gmem_offset = -1;
582
583 attachment_set_ops(att,
584 pCreateInfo->pAttachments[i].loadOp,
585 pCreateInfo->pAttachments[i].stencilLoadOp,
586 pCreateInfo->pAttachments[i].storeOp,
587 pCreateInfo->pAttachments[i].stencilStoreOp);
588 }
589 uint32_t subpass_attachment_count = 0;
590 struct tu_subpass_attachment *p;
591 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
592 const VkSubpassDescription2KHR *desc = &pCreateInfo->pSubpasses[i];
593
594 subpass_attachment_count +=
595 desc->inputAttachmentCount + desc->colorAttachmentCount +
596 (desc->pResolveAttachments ? desc->colorAttachmentCount : 0);
597 }
598
599 if (subpass_attachment_count) {
600 pass->subpass_attachments = vk_alloc2(
601 &device->alloc, pAllocator,
602 subpass_attachment_count * sizeof(struct tu_subpass_attachment), 8,
603 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
604 if (pass->subpass_attachments == NULL) {
605 vk_free2(&device->alloc, pAllocator, pass);
606 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
607 }
608 } else
609 pass->subpass_attachments = NULL;
610
611 p = pass->subpass_attachments;
612 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
613 const VkSubpassDescription2KHR *desc = &pCreateInfo->pSubpasses[i];
614 struct tu_subpass *subpass = &pass->subpasses[i];
615
616 subpass->input_count = desc->inputAttachmentCount;
617 subpass->color_count = desc->colorAttachmentCount;
618 subpass->samples = 0;
619
620 if (desc->inputAttachmentCount > 0) {
621 subpass->input_attachments = p;
622 p += desc->inputAttachmentCount;
623
624 for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) {
625 uint32_t a = desc->pInputAttachments[j].attachment;
626 subpass->input_attachments[j].attachment = a;
627 subpass->input_attachments[j].layout =
628 desc->pInputAttachments[j].layout;
629 if (a != VK_ATTACHMENT_UNUSED)
630 pass->attachments[a].gmem_offset = 0;
631 }
632 }
633
634 if (desc->colorAttachmentCount > 0) {
635 subpass->color_attachments = p;
636 p += desc->colorAttachmentCount;
637
638 for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
639 uint32_t a = desc->pColorAttachments[j].attachment;
640 subpass->color_attachments[j].attachment = a;
641 subpass->color_attachments[j].layout =
642 desc->pColorAttachments[j].layout;
643
644 if (a != VK_ATTACHMENT_UNUSED) {
645 pass->attachments[a].gmem_offset = 0;
646 update_samples(subpass, pCreateInfo->pAttachments[a].samples);
647 }
648 }
649 }
650
651 subpass->resolve_attachments = desc->pResolveAttachments ? p : NULL;
652 if (desc->pResolveAttachments) {
653 p += desc->colorAttachmentCount;
654 for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
655 subpass->resolve_attachments[j].attachment =
656 desc->pResolveAttachments[j].attachment;
657 subpass->resolve_attachments[j].layout =
658 desc->pResolveAttachments[j].layout;
659 }
660 }
661
662
663 uint32_t a = desc->pDepthStencilAttachment ?
664 desc->pDepthStencilAttachment->attachment : VK_ATTACHMENT_UNUSED;
665 subpass->depth_stencil_attachment.attachment = a;
666 if (a != VK_ATTACHMENT_UNUSED) {
667 pass->attachments[a].gmem_offset = 0;
668 subpass->depth_stencil_attachment.layout =
669 desc->pDepthStencilAttachment->layout;
670 update_samples(subpass, pCreateInfo->pAttachments[a].samples);
671 }
672
673 subpass->samples = subpass->samples ?: 1;
674 }
675
676 for (unsigned i = 0; i < pCreateInfo->dependencyCount; ++i) {
677 tu_render_pass_add_subpass_dep(pass, &pCreateInfo->pDependencies[i]);
678 }
679
680 *pRenderPass = tu_render_pass_to_handle(pass);
681
682 create_render_pass_common(pass, device->physical_device);
683
684 return VK_SUCCESS;
685 }
686
687 void
688 tu_DestroyRenderPass(VkDevice _device,
689 VkRenderPass _pass,
690 const VkAllocationCallbacks *pAllocator)
691 {
692 TU_FROM_HANDLE(tu_device, device, _device);
693 TU_FROM_HANDLE(tu_render_pass, pass, _pass);
694
695 if (!_pass)
696 return;
697
698 vk_free2(&device->alloc, pAllocator, pass->subpass_attachments);
699 vk_free2(&device->alloc, pAllocator, pass);
700 }
701
702 void
703 tu_GetRenderAreaGranularity(VkDevice _device,
704 VkRenderPass renderPass,
705 VkExtent2D *pGranularity)
706 {
707 pGranularity->width = GMEM_ALIGN_W;
708 pGranularity->height = GMEM_ALIGN_H;
709 }