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
];
36 uint32_t color_sample_count
= 1, depth_sample_count
= 1;
38 /* We don't allow depth_stencil_attachment to be non-NULL and
39 * be VK_ATTACHMENT_UNUSED. This way something can just check
40 * for NULL and be guaranteed that they have a valid
43 if (subpass
->depth_stencil_attachment
&&
44 subpass
->depth_stencil_attachment
->attachment
== VK_ATTACHMENT_UNUSED
)
45 subpass
->depth_stencil_attachment
= NULL
;
47 for (uint32_t j
= 0; j
< subpass
->attachment_count
; j
++) {
48 struct radv_subpass_attachment
*subpass_att
=
49 &subpass
->attachments
[j
];
50 if (subpass_att
->attachment
== VK_ATTACHMENT_UNUSED
)
53 struct radv_render_pass_attachment
*pass_att
=
54 &pass
->attachments
[subpass_att
->attachment
];
56 pass_att
->last_subpass_idx
= i
;
59 for (uint32_t j
= 0; j
< subpass
->color_count
; j
++) {
60 struct radv_subpass_attachment
*subpass_att
=
61 &subpass
->color_attachments
[j
];
62 if (subpass_att
->attachment
== VK_ATTACHMENT_UNUSED
)
65 struct radv_render_pass_attachment
*pass_att
=
66 &pass
->attachments
[subpass_att
->attachment
];
68 color_sample_count
= pass_att
->samples
;
71 if (subpass
->depth_stencil_attachment
) {
73 subpass
->depth_stencil_attachment
->attachment
;
74 struct radv_render_pass_attachment
*pass_att
=
75 &pass
->attachments
[a
];
76 depth_sample_count
= pass_att
->samples
;
79 subpass
->max_sample_count
= MAX2(color_sample_count
,
82 /* We have to handle resolve attachments specially */
83 subpass
->has_resolve
= false;
84 if (subpass
->resolve_attachments
) {
85 for (uint32_t j
= 0; j
< subpass
->color_count
; j
++) {
86 struct radv_subpass_attachment
*resolve_att
=
87 &subpass
->resolve_attachments
[j
];
89 if (resolve_att
->attachment
== VK_ATTACHMENT_UNUSED
)
92 subpass
->has_resolve
= true;
99 radv_num_subpass_attachments(const VkSubpassDescription
*desc
)
101 return desc
->inputAttachmentCount
+
102 desc
->colorAttachmentCount
+
103 (desc
->pResolveAttachments
? desc
->colorAttachmentCount
: 0) +
104 (desc
->pDepthStencilAttachment
!= NULL
);
107 VkResult
radv_CreateRenderPass(
109 const VkRenderPassCreateInfo
* pCreateInfo
,
110 const VkAllocationCallbacks
* pAllocator
,
111 VkRenderPass
* pRenderPass
)
113 RADV_FROM_HANDLE(radv_device
, device
, _device
);
114 struct radv_render_pass
*pass
;
116 size_t attachments_offset
;
117 VkRenderPassMultiviewCreateInfo
*multiview_info
= NULL
;
119 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
);
121 size
= sizeof(*pass
);
122 size
+= pCreateInfo
->subpassCount
* sizeof(pass
->subpasses
[0]);
123 attachments_offset
= size
;
124 size
+= pCreateInfo
->attachmentCount
* sizeof(pass
->attachments
[0]);
126 pass
= vk_alloc2(&device
->alloc
, pAllocator
, size
, 8,
127 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
129 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
131 memset(pass
, 0, size
);
132 pass
->attachment_count
= pCreateInfo
->attachmentCount
;
133 pass
->subpass_count
= pCreateInfo
->subpassCount
;
134 pass
->attachments
= (void *) pass
+ attachments_offset
;
136 vk_foreach_struct(ext
, pCreateInfo
->pNext
) {
138 case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO
:
139 multiview_info
= (VkRenderPassMultiviewCreateInfo
*)ext
;
146 for (uint32_t i
= 0; i
< pCreateInfo
->attachmentCount
; i
++) {
147 struct radv_render_pass_attachment
*att
= &pass
->attachments
[i
];
149 att
->format
= pCreateInfo
->pAttachments
[i
].format
;
150 att
->samples
= pCreateInfo
->pAttachments
[i
].samples
;
151 att
->load_op
= pCreateInfo
->pAttachments
[i
].loadOp
;
152 att
->stencil_load_op
= pCreateInfo
->pAttachments
[i
].stencilLoadOp
;
153 att
->initial_layout
= pCreateInfo
->pAttachments
[i
].initialLayout
;
154 att
->final_layout
= pCreateInfo
->pAttachments
[i
].finalLayout
;
155 // att->store_op = pCreateInfo->pAttachments[i].storeOp;
156 // att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
158 uint32_t subpass_attachment_count
= 0;
159 struct radv_subpass_attachment
*p
;
160 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
161 subpass_attachment_count
+=
162 radv_num_subpass_attachments(&pCreateInfo
->pSubpasses
[i
]);
165 if (subpass_attachment_count
) {
166 pass
->subpass_attachments
=
167 vk_alloc2(&device
->alloc
, pAllocator
,
168 subpass_attachment_count
* sizeof(struct radv_subpass_attachment
), 8,
169 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
170 if (pass
->subpass_attachments
== NULL
) {
171 vk_free2(&device
->alloc
, pAllocator
, pass
);
172 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
175 pass
->subpass_attachments
= NULL
;
177 p
= pass
->subpass_attachments
;
178 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
179 const VkSubpassDescription
*desc
= &pCreateInfo
->pSubpasses
[i
];
180 struct radv_subpass
*subpass
= &pass
->subpasses
[i
];
182 subpass
->input_count
= desc
->inputAttachmentCount
;
183 subpass
->color_count
= desc
->colorAttachmentCount
;
184 subpass
->attachment_count
= radv_num_subpass_attachments(desc
);
185 subpass
->attachments
= p
;
188 subpass
->view_mask
= multiview_info
->pViewMasks
[i
];
190 if (desc
->inputAttachmentCount
> 0) {
191 subpass
->input_attachments
= p
;
192 p
+= desc
->inputAttachmentCount
;
194 for (uint32_t j
= 0; j
< desc
->inputAttachmentCount
; j
++) {
195 subpass
->input_attachments
[j
] = (struct radv_subpass_attachment
) {
196 .attachment
= desc
->pInputAttachments
[j
].attachment
,
197 .layout
= desc
->pInputAttachments
[j
].layout
,
202 if (desc
->colorAttachmentCount
> 0) {
203 subpass
->color_attachments
= p
;
204 p
+= desc
->colorAttachmentCount
;
206 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
207 subpass
->color_attachments
[j
] = (struct radv_subpass_attachment
) {
208 .attachment
= desc
->pColorAttachments
[j
].attachment
,
209 .layout
= desc
->pColorAttachments
[j
].layout
,
214 if (desc
->pResolveAttachments
) {
215 subpass
->resolve_attachments
= p
;
216 p
+= desc
->colorAttachmentCount
;
218 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
219 uint32_t a
= desc
->pResolveAttachments
[j
].attachment
;
220 subpass
->resolve_attachments
[j
] = (struct radv_subpass_attachment
) {
221 .attachment
= desc
->pResolveAttachments
[j
].attachment
,
222 .layout
= desc
->pResolveAttachments
[j
].layout
,
227 if (desc
->pDepthStencilAttachment
) {
228 subpass
->depth_stencil_attachment
= p
++;
230 *subpass
->depth_stencil_attachment
= (struct radv_subpass_attachment
) {
231 .attachment
= desc
->pDepthStencilAttachment
->attachment
,
232 .layout
= desc
->pDepthStencilAttachment
->layout
,
237 for (unsigned i
= 0; i
< pCreateInfo
->dependencyCount
; ++i
) {
238 uint32_t src
= pCreateInfo
->pDependencies
[i
].srcSubpass
;
239 uint32_t dst
= pCreateInfo
->pDependencies
[i
].dstSubpass
;
241 /* Ignore subpass self-dependencies as they allow the app to
242 * call vkCmdPipelineBarrier() inside the render pass and the
243 * driver should only do the barrier when called, not when
244 * starting the render pass.
249 if (dst
== VK_SUBPASS_EXTERNAL
) {
250 pass
->end_barrier
.src_stage_mask
= pCreateInfo
->pDependencies
[i
].srcStageMask
;
251 pass
->end_barrier
.src_access_mask
= pCreateInfo
->pDependencies
[i
].srcAccessMask
;
252 pass
->end_barrier
.dst_access_mask
= pCreateInfo
->pDependencies
[i
].dstAccessMask
;
254 pass
->subpasses
[dst
].start_barrier
.src_stage_mask
= pCreateInfo
->pDependencies
[i
].srcStageMask
;
255 pass
->subpasses
[dst
].start_barrier
.src_access_mask
= pCreateInfo
->pDependencies
[i
].srcAccessMask
;
256 pass
->subpasses
[dst
].start_barrier
.dst_access_mask
= pCreateInfo
->pDependencies
[i
].dstAccessMask
;
260 radv_render_pass_compile(pass
);
262 *pRenderPass
= radv_render_pass_to_handle(pass
);
268 radv_num_subpass_attachments2(const VkSubpassDescription2KHR
*desc
)
270 return desc
->inputAttachmentCount
+
271 desc
->colorAttachmentCount
+
272 (desc
->pResolveAttachments
? desc
->colorAttachmentCount
: 0) +
273 (desc
->pDepthStencilAttachment
!= NULL
);
276 VkResult
radv_CreateRenderPass2KHR(
278 const VkRenderPassCreateInfo2KHR
* pCreateInfo
,
279 const VkAllocationCallbacks
* pAllocator
,
280 VkRenderPass
* pRenderPass
)
282 RADV_FROM_HANDLE(radv_device
, device
, _device
);
283 struct radv_render_pass
*pass
;
285 size_t attachments_offset
;
287 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR
);
289 size
= sizeof(*pass
);
290 size
+= pCreateInfo
->subpassCount
* sizeof(pass
->subpasses
[0]);
291 attachments_offset
= size
;
292 size
+= pCreateInfo
->attachmentCount
* sizeof(pass
->attachments
[0]);
294 pass
= vk_alloc2(&device
->alloc
, pAllocator
, size
, 8,
295 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
297 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
299 memset(pass
, 0, size
);
300 pass
->attachment_count
= pCreateInfo
->attachmentCount
;
301 pass
->subpass_count
= pCreateInfo
->subpassCount
;
302 pass
->attachments
= (void *) pass
+ attachments_offset
;
304 for (uint32_t i
= 0; i
< pCreateInfo
->attachmentCount
; i
++) {
305 struct radv_render_pass_attachment
*att
= &pass
->attachments
[i
];
307 att
->format
= pCreateInfo
->pAttachments
[i
].format
;
308 att
->samples
= pCreateInfo
->pAttachments
[i
].samples
;
309 att
->load_op
= pCreateInfo
->pAttachments
[i
].loadOp
;
310 att
->stencil_load_op
= pCreateInfo
->pAttachments
[i
].stencilLoadOp
;
311 att
->initial_layout
= pCreateInfo
->pAttachments
[i
].initialLayout
;
312 att
->final_layout
= pCreateInfo
->pAttachments
[i
].finalLayout
;
313 // att->store_op = pCreateInfo->pAttachments[i].storeOp;
314 // att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
316 uint32_t subpass_attachment_count
= 0;
317 struct radv_subpass_attachment
*p
;
318 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
319 subpass_attachment_count
+=
320 radv_num_subpass_attachments2(&pCreateInfo
->pSubpasses
[i
]);
323 if (subpass_attachment_count
) {
324 pass
->subpass_attachments
=
325 vk_alloc2(&device
->alloc
, pAllocator
,
326 subpass_attachment_count
* sizeof(struct radv_subpass_attachment
), 8,
327 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
328 if (pass
->subpass_attachments
== NULL
) {
329 vk_free2(&device
->alloc
, pAllocator
, pass
);
330 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
333 pass
->subpass_attachments
= NULL
;
335 p
= pass
->subpass_attachments
;
336 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
337 const VkSubpassDescription2KHR
*desc
= &pCreateInfo
->pSubpasses
[i
];
338 struct radv_subpass
*subpass
= &pass
->subpasses
[i
];
340 subpass
->input_count
= desc
->inputAttachmentCount
;
341 subpass
->color_count
= desc
->colorAttachmentCount
;
342 subpass
->attachment_count
= radv_num_subpass_attachments2(desc
);
343 subpass
->attachments
= p
;
344 subpass
->view_mask
= desc
->viewMask
;
346 if (desc
->inputAttachmentCount
> 0) {
347 subpass
->input_attachments
= p
;
348 p
+= desc
->inputAttachmentCount
;
350 for (uint32_t j
= 0; j
< desc
->inputAttachmentCount
; j
++) {
351 subpass
->input_attachments
[j
] = (struct radv_subpass_attachment
) {
352 .attachment
= desc
->pInputAttachments
[j
].attachment
,
353 .layout
= desc
->pInputAttachments
[j
].layout
,
358 if (desc
->colorAttachmentCount
> 0) {
359 subpass
->color_attachments
= p
;
360 p
+= desc
->colorAttachmentCount
;
362 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
363 subpass
->color_attachments
[j
] = (struct radv_subpass_attachment
) {
364 .attachment
= desc
->pColorAttachments
[j
].attachment
,
365 .layout
= desc
->pColorAttachments
[j
].layout
,
370 if (desc
->pResolveAttachments
) {
371 subpass
->resolve_attachments
= p
;
372 p
+= desc
->colorAttachmentCount
;
374 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
375 uint32_t a
= desc
->pResolveAttachments
[j
].attachment
;
376 subpass
->resolve_attachments
[j
] = (struct radv_subpass_attachment
) {
377 .attachment
= desc
->pResolveAttachments
[j
].attachment
,
378 .layout
= desc
->pResolveAttachments
[j
].layout
,
383 if (desc
->pDepthStencilAttachment
) {
384 subpass
->depth_stencil_attachment
= p
++;
386 *subpass
->depth_stencil_attachment
= (struct radv_subpass_attachment
) {
387 .attachment
= desc
->pDepthStencilAttachment
->attachment
,
388 .layout
= desc
->pDepthStencilAttachment
->layout
,
393 for (unsigned i
= 0; i
< pCreateInfo
->dependencyCount
; ++i
) {
394 uint32_t src
= pCreateInfo
->pDependencies
[i
].srcSubpass
;
395 uint32_t dst
= pCreateInfo
->pDependencies
[i
].dstSubpass
;
397 /* Ignore subpass self-dependencies as they allow the app to
398 * call vkCmdPipelineBarrier() inside the render pass and the
399 * driver should only do the barrier when called, not when
400 * starting the render pass.
405 if (dst
== VK_SUBPASS_EXTERNAL
) {
406 pass
->end_barrier
.src_stage_mask
= pCreateInfo
->pDependencies
[i
].srcStageMask
;
407 pass
->end_barrier
.src_access_mask
= pCreateInfo
->pDependencies
[i
].srcAccessMask
;
408 pass
->end_barrier
.dst_access_mask
= pCreateInfo
->pDependencies
[i
].dstAccessMask
;
410 pass
->subpasses
[dst
].start_barrier
.src_stage_mask
= pCreateInfo
->pDependencies
[i
].srcStageMask
;
411 pass
->subpasses
[dst
].start_barrier
.src_access_mask
= pCreateInfo
->pDependencies
[i
].srcAccessMask
;
412 pass
->subpasses
[dst
].start_barrier
.dst_access_mask
= pCreateInfo
->pDependencies
[i
].dstAccessMask
;
416 radv_render_pass_compile(pass
);
418 *pRenderPass
= radv_render_pass_to_handle(pass
);
423 void radv_DestroyRenderPass(
426 const VkAllocationCallbacks
* pAllocator
)
428 RADV_FROM_HANDLE(radv_device
, device
, _device
);
429 RADV_FROM_HANDLE(radv_render_pass
, pass
, _pass
);
433 vk_free2(&device
->alloc
, pAllocator
, pass
->subpass_attachments
);
434 vk_free2(&device
->alloc
, pAllocator
, pass
);
437 void radv_GetRenderAreaGranularity(
439 VkRenderPass renderPass
,
440 VkExtent2D
* pGranularity
)
442 pGranularity
->width
= 1;
443 pGranularity
->height
= 1;