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_add_subpass_dep(struct radv_render_pass
*pass
,
33 const VkSubpassDependency2KHR
*dep
)
35 uint32_t src
= dep
->srcSubpass
;
36 uint32_t dst
= dep
->dstSubpass
;
38 /* Ignore subpass self-dependencies as they allow the app to call
39 * vkCmdPipelineBarrier() inside the render pass and the driver should
40 * only do the barrier when called, not when starting the render pass.
45 /* Accumulate all ingoing external dependencies to the first subpass. */
46 if (src
== VK_SUBPASS_EXTERNAL
)
49 if (dst
== VK_SUBPASS_EXTERNAL
) {
50 if (dep
->dstStageMask
!= VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
)
51 pass
->end_barrier
.src_stage_mask
|= dep
->srcStageMask
;
52 pass
->end_barrier
.src_access_mask
|= dep
->srcAccessMask
;
53 pass
->end_barrier
.dst_access_mask
|= dep
->dstAccessMask
;
55 if (dep
->dstStageMask
!= VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
)
56 pass
->subpasses
[dst
].start_barrier
.src_stage_mask
|= dep
->srcStageMask
;
57 pass
->subpasses
[dst
].start_barrier
.src_access_mask
|= dep
->srcAccessMask
;
58 pass
->subpasses
[dst
].start_barrier
.dst_access_mask
|= dep
->dstAccessMask
;
63 radv_render_pass_compile(struct radv_render_pass
*pass
)
65 for (uint32_t i
= 0; i
< pass
->subpass_count
; i
++) {
66 struct radv_subpass
*subpass
= &pass
->subpasses
[i
];
67 uint32_t color_sample_count
= 1, depth_sample_count
= 1;
69 /* We don't allow depth_stencil_attachment to be non-NULL and
70 * be VK_ATTACHMENT_UNUSED. This way something can just check
71 * for NULL and be guaranteed that they have a valid
74 if (subpass
->depth_stencil_attachment
&&
75 subpass
->depth_stencil_attachment
->attachment
== VK_ATTACHMENT_UNUSED
)
76 subpass
->depth_stencil_attachment
= NULL
;
78 for (uint32_t j
= 0; j
< subpass
->attachment_count
; j
++) {
79 struct radv_subpass_attachment
*subpass_att
=
80 &subpass
->attachments
[j
];
81 if (subpass_att
->attachment
== VK_ATTACHMENT_UNUSED
)
84 struct radv_render_pass_attachment
*pass_att
=
85 &pass
->attachments
[subpass_att
->attachment
];
87 pass_att
->last_subpass_idx
= i
;
90 subpass
->has_color_att
= false;
91 for (uint32_t j
= 0; j
< subpass
->color_count
; j
++) {
92 struct radv_subpass_attachment
*subpass_att
=
93 &subpass
->color_attachments
[j
];
94 if (subpass_att
->attachment
== VK_ATTACHMENT_UNUSED
)
97 subpass
->has_color_att
= true;
99 struct radv_render_pass_attachment
*pass_att
=
100 &pass
->attachments
[subpass_att
->attachment
];
102 color_sample_count
= pass_att
->samples
;
105 if (subpass
->depth_stencil_attachment
) {
107 subpass
->depth_stencil_attachment
->attachment
;
108 struct radv_render_pass_attachment
*pass_att
=
109 &pass
->attachments
[a
];
110 depth_sample_count
= pass_att
->samples
;
113 subpass
->max_sample_count
= MAX2(color_sample_count
,
116 /* We have to handle resolve attachments specially */
117 subpass
->has_resolve
= false;
118 if (subpass
->resolve_attachments
) {
119 for (uint32_t j
= 0; j
< subpass
->color_count
; j
++) {
120 struct radv_subpass_attachment
*resolve_att
=
121 &subpass
->resolve_attachments
[j
];
123 if (resolve_att
->attachment
== VK_ATTACHMENT_UNUSED
)
126 subpass
->has_resolve
= true;
133 radv_num_subpass_attachments(const VkSubpassDescription
*desc
)
135 return desc
->inputAttachmentCount
+
136 desc
->colorAttachmentCount
+
137 (desc
->pResolveAttachments
? desc
->colorAttachmentCount
: 0) +
138 (desc
->pDepthStencilAttachment
!= NULL
);
141 VkResult
radv_CreateRenderPass(
143 const VkRenderPassCreateInfo
* pCreateInfo
,
144 const VkAllocationCallbacks
* pAllocator
,
145 VkRenderPass
* pRenderPass
)
147 RADV_FROM_HANDLE(radv_device
, device
, _device
);
148 struct radv_render_pass
*pass
;
150 size_t attachments_offset
;
151 VkRenderPassMultiviewCreateInfo
*multiview_info
= NULL
;
153 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
);
155 size
= sizeof(*pass
);
156 size
+= pCreateInfo
->subpassCount
* sizeof(pass
->subpasses
[0]);
157 attachments_offset
= size
;
158 size
+= pCreateInfo
->attachmentCount
* sizeof(pass
->attachments
[0]);
160 pass
= vk_alloc2(&device
->alloc
, pAllocator
, size
, 8,
161 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
163 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
165 memset(pass
, 0, size
);
166 pass
->attachment_count
= pCreateInfo
->attachmentCount
;
167 pass
->subpass_count
= pCreateInfo
->subpassCount
;
168 pass
->attachments
= (void *) pass
+ attachments_offset
;
170 vk_foreach_struct(ext
, pCreateInfo
->pNext
) {
172 case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO
:
173 multiview_info
= (VkRenderPassMultiviewCreateInfo
*)ext
;
180 for (uint32_t i
= 0; i
< pCreateInfo
->attachmentCount
; i
++) {
181 struct radv_render_pass_attachment
*att
= &pass
->attachments
[i
];
183 att
->format
= pCreateInfo
->pAttachments
[i
].format
;
184 att
->samples
= pCreateInfo
->pAttachments
[i
].samples
;
185 att
->load_op
= pCreateInfo
->pAttachments
[i
].loadOp
;
186 att
->stencil_load_op
= pCreateInfo
->pAttachments
[i
].stencilLoadOp
;
187 att
->initial_layout
= pCreateInfo
->pAttachments
[i
].initialLayout
;
188 att
->final_layout
= pCreateInfo
->pAttachments
[i
].finalLayout
;
189 // att->store_op = pCreateInfo->pAttachments[i].storeOp;
190 // att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
192 uint32_t subpass_attachment_count
= 0;
193 struct radv_subpass_attachment
*p
;
194 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
195 subpass_attachment_count
+=
196 radv_num_subpass_attachments(&pCreateInfo
->pSubpasses
[i
]);
199 if (subpass_attachment_count
) {
200 pass
->subpass_attachments
=
201 vk_alloc2(&device
->alloc
, pAllocator
,
202 subpass_attachment_count
* sizeof(struct radv_subpass_attachment
), 8,
203 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
204 if (pass
->subpass_attachments
== NULL
) {
205 vk_free2(&device
->alloc
, pAllocator
, pass
);
206 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
209 pass
->subpass_attachments
= NULL
;
211 p
= pass
->subpass_attachments
;
212 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
213 const VkSubpassDescription
*desc
= &pCreateInfo
->pSubpasses
[i
];
214 struct radv_subpass
*subpass
= &pass
->subpasses
[i
];
216 subpass
->input_count
= desc
->inputAttachmentCount
;
217 subpass
->color_count
= desc
->colorAttachmentCount
;
218 subpass
->attachment_count
= radv_num_subpass_attachments(desc
);
219 subpass
->attachments
= p
;
222 subpass
->view_mask
= multiview_info
->pViewMasks
[i
];
224 if (desc
->inputAttachmentCount
> 0) {
225 subpass
->input_attachments
= p
;
226 p
+= desc
->inputAttachmentCount
;
228 for (uint32_t j
= 0; j
< desc
->inputAttachmentCount
; j
++) {
229 subpass
->input_attachments
[j
] = (struct radv_subpass_attachment
) {
230 .attachment
= desc
->pInputAttachments
[j
].attachment
,
231 .layout
= desc
->pInputAttachments
[j
].layout
,
236 if (desc
->colorAttachmentCount
> 0) {
237 subpass
->color_attachments
= p
;
238 p
+= desc
->colorAttachmentCount
;
240 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
241 subpass
->color_attachments
[j
] = (struct radv_subpass_attachment
) {
242 .attachment
= desc
->pColorAttachments
[j
].attachment
,
243 .layout
= desc
->pColorAttachments
[j
].layout
,
248 if (desc
->pResolveAttachments
) {
249 subpass
->resolve_attachments
= p
;
250 p
+= desc
->colorAttachmentCount
;
252 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
253 uint32_t a
= desc
->pResolveAttachments
[j
].attachment
;
254 subpass
->resolve_attachments
[j
] = (struct radv_subpass_attachment
) {
255 .attachment
= desc
->pResolveAttachments
[j
].attachment
,
256 .layout
= desc
->pResolveAttachments
[j
].layout
,
261 if (desc
->pDepthStencilAttachment
) {
262 subpass
->depth_stencil_attachment
= p
++;
264 *subpass
->depth_stencil_attachment
= (struct radv_subpass_attachment
) {
265 .attachment
= desc
->pDepthStencilAttachment
->attachment
,
266 .layout
= desc
->pDepthStencilAttachment
->layout
,
271 for (unsigned i
= 0; i
< pCreateInfo
->dependencyCount
; ++i
) {
272 /* Convert to a Dependency2KHR */
273 struct VkSubpassDependency2KHR dep2
= {
274 .srcSubpass
= pCreateInfo
->pDependencies
[i
].srcSubpass
,
275 .dstSubpass
= pCreateInfo
->pDependencies
[i
].dstSubpass
,
276 .srcStageMask
= pCreateInfo
->pDependencies
[i
].srcStageMask
,
277 .dstStageMask
= pCreateInfo
->pDependencies
[i
].dstStageMask
,
278 .srcAccessMask
= pCreateInfo
->pDependencies
[i
].srcAccessMask
,
279 .dstAccessMask
= pCreateInfo
->pDependencies
[i
].dstAccessMask
,
280 .dependencyFlags
= pCreateInfo
->pDependencies
[i
].dependencyFlags
,
282 radv_render_pass_add_subpass_dep(pass
, &dep2
);
285 radv_render_pass_compile(pass
);
287 *pRenderPass
= radv_render_pass_to_handle(pass
);
293 radv_num_subpass_attachments2(const VkSubpassDescription2KHR
*desc
)
295 return desc
->inputAttachmentCount
+
296 desc
->colorAttachmentCount
+
297 (desc
->pResolveAttachments
? desc
->colorAttachmentCount
: 0) +
298 (desc
->pDepthStencilAttachment
!= NULL
);
301 VkResult
radv_CreateRenderPass2KHR(
303 const VkRenderPassCreateInfo2KHR
* pCreateInfo
,
304 const VkAllocationCallbacks
* pAllocator
,
305 VkRenderPass
* pRenderPass
)
307 RADV_FROM_HANDLE(radv_device
, device
, _device
);
308 struct radv_render_pass
*pass
;
310 size_t attachments_offset
;
312 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR
);
314 size
= sizeof(*pass
);
315 size
+= pCreateInfo
->subpassCount
* sizeof(pass
->subpasses
[0]);
316 attachments_offset
= size
;
317 size
+= pCreateInfo
->attachmentCount
* sizeof(pass
->attachments
[0]);
319 pass
= vk_alloc2(&device
->alloc
, pAllocator
, size
, 8,
320 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
322 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
324 memset(pass
, 0, size
);
325 pass
->attachment_count
= pCreateInfo
->attachmentCount
;
326 pass
->subpass_count
= pCreateInfo
->subpassCount
;
327 pass
->attachments
= (void *) pass
+ attachments_offset
;
329 for (uint32_t i
= 0; i
< pCreateInfo
->attachmentCount
; i
++) {
330 struct radv_render_pass_attachment
*att
= &pass
->attachments
[i
];
332 att
->format
= pCreateInfo
->pAttachments
[i
].format
;
333 att
->samples
= pCreateInfo
->pAttachments
[i
].samples
;
334 att
->load_op
= pCreateInfo
->pAttachments
[i
].loadOp
;
335 att
->stencil_load_op
= pCreateInfo
->pAttachments
[i
].stencilLoadOp
;
336 att
->initial_layout
= pCreateInfo
->pAttachments
[i
].initialLayout
;
337 att
->final_layout
= pCreateInfo
->pAttachments
[i
].finalLayout
;
338 // att->store_op = pCreateInfo->pAttachments[i].storeOp;
339 // att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
341 uint32_t subpass_attachment_count
= 0;
342 struct radv_subpass_attachment
*p
;
343 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
344 subpass_attachment_count
+=
345 radv_num_subpass_attachments2(&pCreateInfo
->pSubpasses
[i
]);
348 if (subpass_attachment_count
) {
349 pass
->subpass_attachments
=
350 vk_alloc2(&device
->alloc
, pAllocator
,
351 subpass_attachment_count
* sizeof(struct radv_subpass_attachment
), 8,
352 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
353 if (pass
->subpass_attachments
== NULL
) {
354 vk_free2(&device
->alloc
, pAllocator
, pass
);
355 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
358 pass
->subpass_attachments
= NULL
;
360 p
= pass
->subpass_attachments
;
361 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
362 const VkSubpassDescription2KHR
*desc
= &pCreateInfo
->pSubpasses
[i
];
363 struct radv_subpass
*subpass
= &pass
->subpasses
[i
];
365 subpass
->input_count
= desc
->inputAttachmentCount
;
366 subpass
->color_count
= desc
->colorAttachmentCount
;
367 subpass
->attachment_count
= radv_num_subpass_attachments2(desc
);
368 subpass
->attachments
= p
;
369 subpass
->view_mask
= desc
->viewMask
;
371 if (desc
->inputAttachmentCount
> 0) {
372 subpass
->input_attachments
= p
;
373 p
+= desc
->inputAttachmentCount
;
375 for (uint32_t j
= 0; j
< desc
->inputAttachmentCount
; j
++) {
376 subpass
->input_attachments
[j
] = (struct radv_subpass_attachment
) {
377 .attachment
= desc
->pInputAttachments
[j
].attachment
,
378 .layout
= desc
->pInputAttachments
[j
].layout
,
383 if (desc
->colorAttachmentCount
> 0) {
384 subpass
->color_attachments
= p
;
385 p
+= desc
->colorAttachmentCount
;
387 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
388 subpass
->color_attachments
[j
] = (struct radv_subpass_attachment
) {
389 .attachment
= desc
->pColorAttachments
[j
].attachment
,
390 .layout
= desc
->pColorAttachments
[j
].layout
,
395 if (desc
->pResolveAttachments
) {
396 subpass
->resolve_attachments
= p
;
397 p
+= desc
->colorAttachmentCount
;
399 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
400 uint32_t a
= desc
->pResolveAttachments
[j
].attachment
;
401 subpass
->resolve_attachments
[j
] = (struct radv_subpass_attachment
) {
402 .attachment
= desc
->pResolveAttachments
[j
].attachment
,
403 .layout
= desc
->pResolveAttachments
[j
].layout
,
408 if (desc
->pDepthStencilAttachment
) {
409 subpass
->depth_stencil_attachment
= p
++;
411 *subpass
->depth_stencil_attachment
= (struct radv_subpass_attachment
) {
412 .attachment
= desc
->pDepthStencilAttachment
->attachment
,
413 .layout
= desc
->pDepthStencilAttachment
->layout
,
418 for (unsigned i
= 0; i
< pCreateInfo
->dependencyCount
; ++i
) {
419 radv_render_pass_add_subpass_dep(pass
,
420 &pCreateInfo
->pDependencies
[i
]);
423 radv_render_pass_compile(pass
);
425 *pRenderPass
= radv_render_pass_to_handle(pass
);
430 void radv_DestroyRenderPass(
433 const VkAllocationCallbacks
* pAllocator
)
435 RADV_FROM_HANDLE(radv_device
, device
, _device
);
436 RADV_FROM_HANDLE(radv_render_pass
, pass
, _pass
);
440 vk_free2(&device
->alloc
, pAllocator
, pass
->subpass_attachments
);
441 vk_free2(&device
->alloc
, pAllocator
, pass
);
444 void radv_GetRenderAreaGranularity(
446 VkRenderPass renderPass
,
447 VkExtent2D
* pGranularity
)
449 pGranularity
->width
= 1;
450 pGranularity
->height
= 1;