2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
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:
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
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 #include "radv_private.h"
32 radv_render_pass_compile(struct radv_render_pass
*pass
)
34 for (uint32_t i
= 0; i
< pass
->subpass_count
; i
++) {
35 struct radv_subpass
*subpass
= &pass
->subpasses
[i
];
37 /* We don't allow depth_stencil_attachment to be non-NULL and
38 * be VK_ATTACHMENT_UNUSED. This way something can just check
39 * for NULL and be guaranteed that they have a valid
42 if (subpass
->depth_stencil_attachment
&&
43 subpass
->depth_stencil_attachment
->attachment
== VK_ATTACHMENT_UNUSED
)
44 subpass
->depth_stencil_attachment
= NULL
;
46 for (uint32_t j
= 0; j
< subpass
->attachment_count
; j
++) {
47 struct radv_subpass_attachment
*subpass_att
=
48 &subpass
->attachments
[j
];
49 if (subpass_att
->attachment
== VK_ATTACHMENT_UNUSED
)
52 struct radv_render_pass_attachment
*pass_att
=
53 &pass
->attachments
[subpass_att
->attachment
];
55 pass_att
->last_subpass_idx
= i
;
61 radv_num_subpass_attachments(const VkSubpassDescription
*desc
)
63 return desc
->inputAttachmentCount
+
64 desc
->colorAttachmentCount
+
65 (desc
->pResolveAttachments
? desc
->colorAttachmentCount
: 0) +
66 (desc
->pDepthStencilAttachment
!= NULL
);
69 VkResult
radv_CreateRenderPass(
71 const VkRenderPassCreateInfo
* pCreateInfo
,
72 const VkAllocationCallbacks
* pAllocator
,
73 VkRenderPass
* pRenderPass
)
75 RADV_FROM_HANDLE(radv_device
, device
, _device
);
76 struct radv_render_pass
*pass
;
78 size_t attachments_offset
;
79 VkRenderPassMultiviewCreateInfo
*multiview_info
= NULL
;
81 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
);
84 size
+= pCreateInfo
->subpassCount
* sizeof(pass
->subpasses
[0]);
85 attachments_offset
= size
;
86 size
+= pCreateInfo
->attachmentCount
* sizeof(pass
->attachments
[0]);
88 pass
= vk_alloc2(&device
->alloc
, pAllocator
, size
, 8,
89 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
91 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
93 memset(pass
, 0, size
);
94 pass
->attachment_count
= pCreateInfo
->attachmentCount
;
95 pass
->subpass_count
= pCreateInfo
->subpassCount
;
96 pass
->attachments
= (void *) pass
+ attachments_offset
;
98 vk_foreach_struct(ext
, pCreateInfo
->pNext
) {
100 case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO
:
101 multiview_info
= (VkRenderPassMultiviewCreateInfo
*)ext
;
108 for (uint32_t i
= 0; i
< pCreateInfo
->attachmentCount
; i
++) {
109 struct radv_render_pass_attachment
*att
= &pass
->attachments
[i
];
111 att
->format
= pCreateInfo
->pAttachments
[i
].format
;
112 att
->samples
= pCreateInfo
->pAttachments
[i
].samples
;
113 att
->load_op
= pCreateInfo
->pAttachments
[i
].loadOp
;
114 att
->stencil_load_op
= pCreateInfo
->pAttachments
[i
].stencilLoadOp
;
115 att
->initial_layout
= pCreateInfo
->pAttachments
[i
].initialLayout
;
116 att
->final_layout
= pCreateInfo
->pAttachments
[i
].finalLayout
;
117 // att->store_op = pCreateInfo->pAttachments[i].storeOp;
118 // att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
120 uint32_t subpass_attachment_count
= 0;
121 struct radv_subpass_attachment
*p
;
122 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
123 subpass_attachment_count
+=
124 radv_num_subpass_attachments(&pCreateInfo
->pSubpasses
[i
]);
127 if (subpass_attachment_count
) {
128 pass
->subpass_attachments
=
129 vk_alloc2(&device
->alloc
, pAllocator
,
130 subpass_attachment_count
* sizeof(struct radv_subpass_attachment
), 8,
131 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
132 if (pass
->subpass_attachments
== NULL
) {
133 vk_free2(&device
->alloc
, pAllocator
, pass
);
134 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
137 pass
->subpass_attachments
= NULL
;
139 p
= pass
->subpass_attachments
;
140 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
141 const VkSubpassDescription
*desc
= &pCreateInfo
->pSubpasses
[i
];
142 uint32_t color_sample_count
= 1, depth_sample_count
= 1;
143 struct radv_subpass
*subpass
= &pass
->subpasses
[i
];
145 subpass
->input_count
= desc
->inputAttachmentCount
;
146 subpass
->color_count
= desc
->colorAttachmentCount
;
147 subpass
->attachment_count
= radv_num_subpass_attachments(desc
);
148 subpass
->attachments
= p
;
151 subpass
->view_mask
= multiview_info
->pViewMasks
[i
];
153 if (desc
->inputAttachmentCount
> 0) {
154 subpass
->input_attachments
= p
;
155 p
+= desc
->inputAttachmentCount
;
157 for (uint32_t j
= 0; j
< desc
->inputAttachmentCount
; j
++) {
158 subpass
->input_attachments
[j
] = (struct radv_subpass_attachment
) {
159 .attachment
= desc
->pInputAttachments
[j
].attachment
,
160 .layout
= desc
->pInputAttachments
[j
].layout
,
165 if (desc
->colorAttachmentCount
> 0) {
166 subpass
->color_attachments
= p
;
167 p
+= desc
->colorAttachmentCount
;
169 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
170 subpass
->color_attachments
[j
] = (struct radv_subpass_attachment
) {
171 .attachment
= desc
->pColorAttachments
[j
].attachment
,
172 .layout
= desc
->pColorAttachments
[j
].layout
,
174 if (desc
->pColorAttachments
[j
].attachment
!= VK_ATTACHMENT_UNUSED
) {
175 color_sample_count
= pCreateInfo
->pAttachments
[desc
->pColorAttachments
[j
].attachment
].samples
;
180 subpass
->has_resolve
= false;
181 if (desc
->pResolveAttachments
) {
182 subpass
->resolve_attachments
= p
;
183 p
+= desc
->colorAttachmentCount
;
185 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
186 uint32_t a
= desc
->pResolveAttachments
[j
].attachment
;
187 subpass
->resolve_attachments
[j
] = (struct radv_subpass_attachment
) {
188 .attachment
= desc
->pResolveAttachments
[j
].attachment
,
189 .layout
= desc
->pResolveAttachments
[j
].layout
,
191 if (a
!= VK_ATTACHMENT_UNUSED
) {
192 subpass
->has_resolve
= true;
197 if (desc
->pDepthStencilAttachment
) {
198 subpass
->depth_stencil_attachment
= p
++;
200 *subpass
->depth_stencil_attachment
= (struct radv_subpass_attachment
) {
201 .attachment
= desc
->pDepthStencilAttachment
->attachment
,
202 .layout
= desc
->pDepthStencilAttachment
->layout
,
204 if (desc
->pDepthStencilAttachment
->attachment
!= VK_ATTACHMENT_UNUSED
) {
205 depth_sample_count
= pCreateInfo
->pAttachments
[desc
->pDepthStencilAttachment
->attachment
].samples
;
209 subpass
->max_sample_count
= MAX2(color_sample_count
,
213 for (unsigned i
= 0; i
< pCreateInfo
->dependencyCount
; ++i
) {
214 uint32_t src
= pCreateInfo
->pDependencies
[i
].srcSubpass
;
215 uint32_t dst
= pCreateInfo
->pDependencies
[i
].dstSubpass
;
217 /* Ignore subpass self-dependencies as they allow the app to
218 * call vkCmdPipelineBarrier() inside the render pass and the
219 * driver should only do the barrier when called, not when
220 * starting the render pass.
225 if (dst
== VK_SUBPASS_EXTERNAL
) {
226 pass
->end_barrier
.src_stage_mask
= pCreateInfo
->pDependencies
[i
].srcStageMask
;
227 pass
->end_barrier
.src_access_mask
= pCreateInfo
->pDependencies
[i
].srcAccessMask
;
228 pass
->end_barrier
.dst_access_mask
= pCreateInfo
->pDependencies
[i
].dstAccessMask
;
230 pass
->subpasses
[dst
].start_barrier
.src_stage_mask
= pCreateInfo
->pDependencies
[i
].srcStageMask
;
231 pass
->subpasses
[dst
].start_barrier
.src_access_mask
= pCreateInfo
->pDependencies
[i
].srcAccessMask
;
232 pass
->subpasses
[dst
].start_barrier
.dst_access_mask
= pCreateInfo
->pDependencies
[i
].dstAccessMask
;
236 radv_render_pass_compile(pass
);
238 *pRenderPass
= radv_render_pass_to_handle(pass
);
244 radv_num_subpass_attachments2(const VkSubpassDescription2KHR
*desc
)
246 return desc
->inputAttachmentCount
+
247 desc
->colorAttachmentCount
+
248 (desc
->pResolveAttachments
? desc
->colorAttachmentCount
: 0) +
249 (desc
->pDepthStencilAttachment
!= NULL
);
252 VkResult
radv_CreateRenderPass2KHR(
254 const VkRenderPassCreateInfo2KHR
* pCreateInfo
,
255 const VkAllocationCallbacks
* pAllocator
,
256 VkRenderPass
* pRenderPass
)
258 RADV_FROM_HANDLE(radv_device
, device
, _device
);
259 struct radv_render_pass
*pass
;
261 size_t attachments_offset
;
263 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR
);
265 size
= sizeof(*pass
);
266 size
+= pCreateInfo
->subpassCount
* sizeof(pass
->subpasses
[0]);
267 attachments_offset
= size
;
268 size
+= pCreateInfo
->attachmentCount
* sizeof(pass
->attachments
[0]);
270 pass
= vk_alloc2(&device
->alloc
, pAllocator
, size
, 8,
271 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
273 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
275 memset(pass
, 0, size
);
276 pass
->attachment_count
= pCreateInfo
->attachmentCount
;
277 pass
->subpass_count
= pCreateInfo
->subpassCount
;
278 pass
->attachments
= (void *) pass
+ attachments_offset
;
280 for (uint32_t i
= 0; i
< pCreateInfo
->attachmentCount
; i
++) {
281 struct radv_render_pass_attachment
*att
= &pass
->attachments
[i
];
283 att
->format
= pCreateInfo
->pAttachments
[i
].format
;
284 att
->samples
= pCreateInfo
->pAttachments
[i
].samples
;
285 att
->load_op
= pCreateInfo
->pAttachments
[i
].loadOp
;
286 att
->stencil_load_op
= pCreateInfo
->pAttachments
[i
].stencilLoadOp
;
287 att
->initial_layout
= pCreateInfo
->pAttachments
[i
].initialLayout
;
288 att
->final_layout
= pCreateInfo
->pAttachments
[i
].finalLayout
;
289 // att->store_op = pCreateInfo->pAttachments[i].storeOp;
290 // att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
292 uint32_t subpass_attachment_count
= 0;
293 struct radv_subpass_attachment
*p
;
294 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
295 subpass_attachment_count
+=
296 radv_num_subpass_attachments2(&pCreateInfo
->pSubpasses
[i
]);
299 if (subpass_attachment_count
) {
300 pass
->subpass_attachments
=
301 vk_alloc2(&device
->alloc
, pAllocator
,
302 subpass_attachment_count
* sizeof(struct radv_subpass_attachment
), 8,
303 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
304 if (pass
->subpass_attachments
== NULL
) {
305 vk_free2(&device
->alloc
, pAllocator
, pass
);
306 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
309 pass
->subpass_attachments
= NULL
;
311 p
= pass
->subpass_attachments
;
312 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
313 const VkSubpassDescription2KHR
*desc
= &pCreateInfo
->pSubpasses
[i
];
314 uint32_t color_sample_count
= 1, depth_sample_count
= 1;
315 struct radv_subpass
*subpass
= &pass
->subpasses
[i
];
317 subpass
->input_count
= desc
->inputAttachmentCount
;
318 subpass
->color_count
= desc
->colorAttachmentCount
;
319 subpass
->attachment_count
= radv_num_subpass_attachments2(desc
);
320 subpass
->attachments
= p
;
321 subpass
->view_mask
= desc
->viewMask
;
323 if (desc
->inputAttachmentCount
> 0) {
324 subpass
->input_attachments
= p
;
325 p
+= desc
->inputAttachmentCount
;
327 for (uint32_t j
= 0; j
< desc
->inputAttachmentCount
; j
++) {
328 subpass
->input_attachments
[j
] = (struct radv_subpass_attachment
) {
329 .attachment
= desc
->pInputAttachments
[j
].attachment
,
330 .layout
= desc
->pInputAttachments
[j
].layout
,
335 if (desc
->colorAttachmentCount
> 0) {
336 subpass
->color_attachments
= p
;
337 p
+= desc
->colorAttachmentCount
;
339 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
340 subpass
->color_attachments
[j
] = (struct radv_subpass_attachment
) {
341 .attachment
= desc
->pColorAttachments
[j
].attachment
,
342 .layout
= desc
->pColorAttachments
[j
].layout
,
344 if (desc
->pColorAttachments
[j
].attachment
!= VK_ATTACHMENT_UNUSED
) {
345 color_sample_count
= pCreateInfo
->pAttachments
[desc
->pColorAttachments
[j
].attachment
].samples
;
350 subpass
->has_resolve
= false;
351 if (desc
->pResolveAttachments
) {
352 subpass
->resolve_attachments
= p
;
353 p
+= desc
->colorAttachmentCount
;
355 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
356 uint32_t a
= desc
->pResolveAttachments
[j
].attachment
;
357 subpass
->resolve_attachments
[j
] = (struct radv_subpass_attachment
) {
358 .attachment
= desc
->pResolveAttachments
[j
].attachment
,
359 .layout
= desc
->pResolveAttachments
[j
].layout
,
361 if (a
!= VK_ATTACHMENT_UNUSED
) {
362 subpass
->has_resolve
= true;
367 if (desc
->pDepthStencilAttachment
) {
368 subpass
->depth_stencil_attachment
= p
++;
370 *subpass
->depth_stencil_attachment
= (struct radv_subpass_attachment
) {
371 .attachment
= desc
->pDepthStencilAttachment
->attachment
,
372 .layout
= desc
->pDepthStencilAttachment
->layout
,
374 if (desc
->pDepthStencilAttachment
->attachment
!= VK_ATTACHMENT_UNUSED
) {
375 depth_sample_count
= pCreateInfo
->pAttachments
[desc
->pDepthStencilAttachment
->attachment
].samples
;
379 subpass
->max_sample_count
= MAX2(color_sample_count
,
383 for (unsigned i
= 0; i
< pCreateInfo
->dependencyCount
; ++i
) {
384 uint32_t src
= pCreateInfo
->pDependencies
[i
].srcSubpass
;
385 uint32_t dst
= pCreateInfo
->pDependencies
[i
].dstSubpass
;
387 /* Ignore subpass self-dependencies as they allow the app to
388 * call vkCmdPipelineBarrier() inside the render pass and the
389 * driver should only do the barrier when called, not when
390 * starting the render pass.
395 if (dst
== VK_SUBPASS_EXTERNAL
) {
396 pass
->end_barrier
.src_stage_mask
= pCreateInfo
->pDependencies
[i
].srcStageMask
;
397 pass
->end_barrier
.src_access_mask
= pCreateInfo
->pDependencies
[i
].srcAccessMask
;
398 pass
->end_barrier
.dst_access_mask
= pCreateInfo
->pDependencies
[i
].dstAccessMask
;
400 pass
->subpasses
[dst
].start_barrier
.src_stage_mask
= pCreateInfo
->pDependencies
[i
].srcStageMask
;
401 pass
->subpasses
[dst
].start_barrier
.src_access_mask
= pCreateInfo
->pDependencies
[i
].srcAccessMask
;
402 pass
->subpasses
[dst
].start_barrier
.dst_access_mask
= pCreateInfo
->pDependencies
[i
].dstAccessMask
;
406 radv_render_pass_compile(pass
);
408 *pRenderPass
= radv_render_pass_to_handle(pass
);
413 void radv_DestroyRenderPass(
416 const VkAllocationCallbacks
* pAllocator
)
418 RADV_FROM_HANDLE(radv_device
, device
, _device
);
419 RADV_FROM_HANDLE(radv_render_pass
, pass
, _pass
);
423 vk_free2(&device
->alloc
, pAllocator
, pass
->subpass_attachments
);
424 vk_free2(&device
->alloc
, pAllocator
, pass
);
427 void radv_GetRenderAreaGranularity(
429 VkRenderPass renderPass
,
430 VkExtent2D
* pGranularity
)
432 pGranularity
->width
= 1;
433 pGranularity
->height
= 1;