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 if (dst
== VK_SUBPASS_EXTERNAL
) {
46 pass
->end_barrier
.src_stage_mask
|= dep
->srcStageMask
;
47 pass
->end_barrier
.src_access_mask
|= dep
->srcAccessMask
;
48 pass
->end_barrier
.dst_access_mask
|= dep
->dstAccessMask
;
50 pass
->subpasses
[dst
].start_barrier
.src_stage_mask
|= dep
->srcStageMask
;
51 pass
->subpasses
[dst
].start_barrier
.src_access_mask
|= dep
->srcAccessMask
;
52 pass
->subpasses
[dst
].start_barrier
.dst_access_mask
|= dep
->dstAccessMask
;
57 radv_render_pass_compile(struct radv_render_pass
*pass
)
59 for (uint32_t i
= 0; i
< pass
->subpass_count
; i
++) {
60 struct radv_subpass
*subpass
= &pass
->subpasses
[i
];
61 uint32_t color_sample_count
= 1, depth_sample_count
= 1;
63 /* We don't allow depth_stencil_attachment to be non-NULL and
64 * be VK_ATTACHMENT_UNUSED. This way something can just check
65 * for NULL and be guaranteed that they have a valid
68 if (subpass
->depth_stencil_attachment
&&
69 subpass
->depth_stencil_attachment
->attachment
== VK_ATTACHMENT_UNUSED
)
70 subpass
->depth_stencil_attachment
= NULL
;
72 for (uint32_t j
= 0; j
< subpass
->attachment_count
; j
++) {
73 struct radv_subpass_attachment
*subpass_att
=
74 &subpass
->attachments
[j
];
75 if (subpass_att
->attachment
== VK_ATTACHMENT_UNUSED
)
78 struct radv_render_pass_attachment
*pass_att
=
79 &pass
->attachments
[subpass_att
->attachment
];
81 pass_att
->last_subpass_idx
= i
;
84 subpass
->has_color_att
= false;
85 for (uint32_t j
= 0; j
< subpass
->color_count
; j
++) {
86 struct radv_subpass_attachment
*subpass_att
=
87 &subpass
->color_attachments
[j
];
88 if (subpass_att
->attachment
== VK_ATTACHMENT_UNUSED
)
91 subpass
->has_color_att
= true;
93 struct radv_render_pass_attachment
*pass_att
=
94 &pass
->attachments
[subpass_att
->attachment
];
96 color_sample_count
= pass_att
->samples
;
99 if (subpass
->depth_stencil_attachment
) {
101 subpass
->depth_stencil_attachment
->attachment
;
102 struct radv_render_pass_attachment
*pass_att
=
103 &pass
->attachments
[a
];
104 depth_sample_count
= pass_att
->samples
;
107 subpass
->max_sample_count
= MAX2(color_sample_count
,
110 /* We have to handle resolve attachments specially */
111 subpass
->has_resolve
= false;
112 if (subpass
->resolve_attachments
) {
113 for (uint32_t j
= 0; j
< subpass
->color_count
; j
++) {
114 struct radv_subpass_attachment
*resolve_att
=
115 &subpass
->resolve_attachments
[j
];
117 if (resolve_att
->attachment
== VK_ATTACHMENT_UNUSED
)
120 subpass
->has_resolve
= true;
127 radv_num_subpass_attachments(const VkSubpassDescription
*desc
)
129 return desc
->inputAttachmentCount
+
130 desc
->colorAttachmentCount
+
131 (desc
->pResolveAttachments
? desc
->colorAttachmentCount
: 0) +
132 (desc
->pDepthStencilAttachment
!= NULL
);
135 VkResult
radv_CreateRenderPass(
137 const VkRenderPassCreateInfo
* pCreateInfo
,
138 const VkAllocationCallbacks
* pAllocator
,
139 VkRenderPass
* pRenderPass
)
141 RADV_FROM_HANDLE(radv_device
, device
, _device
);
142 struct radv_render_pass
*pass
;
144 size_t attachments_offset
;
145 VkRenderPassMultiviewCreateInfo
*multiview_info
= NULL
;
147 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
);
149 size
= sizeof(*pass
);
150 size
+= pCreateInfo
->subpassCount
* sizeof(pass
->subpasses
[0]);
151 attachments_offset
= size
;
152 size
+= pCreateInfo
->attachmentCount
* sizeof(pass
->attachments
[0]);
154 pass
= vk_alloc2(&device
->alloc
, pAllocator
, size
, 8,
155 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
157 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
159 memset(pass
, 0, size
);
160 pass
->attachment_count
= pCreateInfo
->attachmentCount
;
161 pass
->subpass_count
= pCreateInfo
->subpassCount
;
162 pass
->attachments
= (void *) pass
+ attachments_offset
;
164 vk_foreach_struct(ext
, pCreateInfo
->pNext
) {
166 case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO
:
167 multiview_info
= (VkRenderPassMultiviewCreateInfo
*)ext
;
174 for (uint32_t i
= 0; i
< pCreateInfo
->attachmentCount
; i
++) {
175 struct radv_render_pass_attachment
*att
= &pass
->attachments
[i
];
177 att
->format
= pCreateInfo
->pAttachments
[i
].format
;
178 att
->samples
= pCreateInfo
->pAttachments
[i
].samples
;
179 att
->load_op
= pCreateInfo
->pAttachments
[i
].loadOp
;
180 att
->stencil_load_op
= pCreateInfo
->pAttachments
[i
].stencilLoadOp
;
181 att
->initial_layout
= pCreateInfo
->pAttachments
[i
].initialLayout
;
182 att
->final_layout
= pCreateInfo
->pAttachments
[i
].finalLayout
;
183 // att->store_op = pCreateInfo->pAttachments[i].storeOp;
184 // att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
186 uint32_t subpass_attachment_count
= 0;
187 struct radv_subpass_attachment
*p
;
188 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
189 subpass_attachment_count
+=
190 radv_num_subpass_attachments(&pCreateInfo
->pSubpasses
[i
]);
193 if (subpass_attachment_count
) {
194 pass
->subpass_attachments
=
195 vk_alloc2(&device
->alloc
, pAllocator
,
196 subpass_attachment_count
* sizeof(struct radv_subpass_attachment
), 8,
197 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
198 if (pass
->subpass_attachments
== NULL
) {
199 vk_free2(&device
->alloc
, pAllocator
, pass
);
200 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
203 pass
->subpass_attachments
= NULL
;
205 p
= pass
->subpass_attachments
;
206 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
207 const VkSubpassDescription
*desc
= &pCreateInfo
->pSubpasses
[i
];
208 struct radv_subpass
*subpass
= &pass
->subpasses
[i
];
210 subpass
->input_count
= desc
->inputAttachmentCount
;
211 subpass
->color_count
= desc
->colorAttachmentCount
;
212 subpass
->attachment_count
= radv_num_subpass_attachments(desc
);
213 subpass
->attachments
= p
;
216 subpass
->view_mask
= multiview_info
->pViewMasks
[i
];
218 if (desc
->inputAttachmentCount
> 0) {
219 subpass
->input_attachments
= p
;
220 p
+= desc
->inputAttachmentCount
;
222 for (uint32_t j
= 0; j
< desc
->inputAttachmentCount
; j
++) {
223 subpass
->input_attachments
[j
] = (struct radv_subpass_attachment
) {
224 .attachment
= desc
->pInputAttachments
[j
].attachment
,
225 .layout
= desc
->pInputAttachments
[j
].layout
,
230 if (desc
->colorAttachmentCount
> 0) {
231 subpass
->color_attachments
= p
;
232 p
+= desc
->colorAttachmentCount
;
234 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
235 subpass
->color_attachments
[j
] = (struct radv_subpass_attachment
) {
236 .attachment
= desc
->pColorAttachments
[j
].attachment
,
237 .layout
= desc
->pColorAttachments
[j
].layout
,
242 if (desc
->pResolveAttachments
) {
243 subpass
->resolve_attachments
= p
;
244 p
+= desc
->colorAttachmentCount
;
246 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
247 uint32_t a
= desc
->pResolveAttachments
[j
].attachment
;
248 subpass
->resolve_attachments
[j
] = (struct radv_subpass_attachment
) {
249 .attachment
= desc
->pResolveAttachments
[j
].attachment
,
250 .layout
= desc
->pResolveAttachments
[j
].layout
,
255 if (desc
->pDepthStencilAttachment
) {
256 subpass
->depth_stencil_attachment
= p
++;
258 *subpass
->depth_stencil_attachment
= (struct radv_subpass_attachment
) {
259 .attachment
= desc
->pDepthStencilAttachment
->attachment
,
260 .layout
= desc
->pDepthStencilAttachment
->layout
,
265 for (unsigned i
= 0; i
< pCreateInfo
->dependencyCount
; ++i
) {
266 /* Convert to a Dependency2KHR */
267 struct VkSubpassDependency2KHR dep2
= {
268 .srcSubpass
= pCreateInfo
->pDependencies
[i
].srcSubpass
,
269 .dstSubpass
= pCreateInfo
->pDependencies
[i
].dstSubpass
,
270 .srcStageMask
= pCreateInfo
->pDependencies
[i
].srcStageMask
,
271 .dstStageMask
= pCreateInfo
->pDependencies
[i
].dstStageMask
,
272 .srcAccessMask
= pCreateInfo
->pDependencies
[i
].srcAccessMask
,
273 .dstAccessMask
= pCreateInfo
->pDependencies
[i
].dstAccessMask
,
274 .dependencyFlags
= pCreateInfo
->pDependencies
[i
].dependencyFlags
,
276 radv_render_pass_add_subpass_dep(pass
, &dep2
);
279 radv_render_pass_compile(pass
);
281 *pRenderPass
= radv_render_pass_to_handle(pass
);
287 radv_num_subpass_attachments2(const VkSubpassDescription2KHR
*desc
)
289 return desc
->inputAttachmentCount
+
290 desc
->colorAttachmentCount
+
291 (desc
->pResolveAttachments
? desc
->colorAttachmentCount
: 0) +
292 (desc
->pDepthStencilAttachment
!= NULL
);
295 VkResult
radv_CreateRenderPass2KHR(
297 const VkRenderPassCreateInfo2KHR
* pCreateInfo
,
298 const VkAllocationCallbacks
* pAllocator
,
299 VkRenderPass
* pRenderPass
)
301 RADV_FROM_HANDLE(radv_device
, device
, _device
);
302 struct radv_render_pass
*pass
;
304 size_t attachments_offset
;
306 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR
);
308 size
= sizeof(*pass
);
309 size
+= pCreateInfo
->subpassCount
* sizeof(pass
->subpasses
[0]);
310 attachments_offset
= size
;
311 size
+= pCreateInfo
->attachmentCount
* sizeof(pass
->attachments
[0]);
313 pass
= vk_alloc2(&device
->alloc
, pAllocator
, size
, 8,
314 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
316 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
318 memset(pass
, 0, size
);
319 pass
->attachment_count
= pCreateInfo
->attachmentCount
;
320 pass
->subpass_count
= pCreateInfo
->subpassCount
;
321 pass
->attachments
= (void *) pass
+ attachments_offset
;
323 for (uint32_t i
= 0; i
< pCreateInfo
->attachmentCount
; i
++) {
324 struct radv_render_pass_attachment
*att
= &pass
->attachments
[i
];
326 att
->format
= pCreateInfo
->pAttachments
[i
].format
;
327 att
->samples
= pCreateInfo
->pAttachments
[i
].samples
;
328 att
->load_op
= pCreateInfo
->pAttachments
[i
].loadOp
;
329 att
->stencil_load_op
= pCreateInfo
->pAttachments
[i
].stencilLoadOp
;
330 att
->initial_layout
= pCreateInfo
->pAttachments
[i
].initialLayout
;
331 att
->final_layout
= pCreateInfo
->pAttachments
[i
].finalLayout
;
332 // att->store_op = pCreateInfo->pAttachments[i].storeOp;
333 // att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
335 uint32_t subpass_attachment_count
= 0;
336 struct radv_subpass_attachment
*p
;
337 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
338 subpass_attachment_count
+=
339 radv_num_subpass_attachments2(&pCreateInfo
->pSubpasses
[i
]);
342 if (subpass_attachment_count
) {
343 pass
->subpass_attachments
=
344 vk_alloc2(&device
->alloc
, pAllocator
,
345 subpass_attachment_count
* sizeof(struct radv_subpass_attachment
), 8,
346 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
347 if (pass
->subpass_attachments
== NULL
) {
348 vk_free2(&device
->alloc
, pAllocator
, pass
);
349 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
352 pass
->subpass_attachments
= NULL
;
354 p
= pass
->subpass_attachments
;
355 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
356 const VkSubpassDescription2KHR
*desc
= &pCreateInfo
->pSubpasses
[i
];
357 struct radv_subpass
*subpass
= &pass
->subpasses
[i
];
359 subpass
->input_count
= desc
->inputAttachmentCount
;
360 subpass
->color_count
= desc
->colorAttachmentCount
;
361 subpass
->attachment_count
= radv_num_subpass_attachments2(desc
);
362 subpass
->attachments
= p
;
363 subpass
->view_mask
= desc
->viewMask
;
365 if (desc
->inputAttachmentCount
> 0) {
366 subpass
->input_attachments
= p
;
367 p
+= desc
->inputAttachmentCount
;
369 for (uint32_t j
= 0; j
< desc
->inputAttachmentCount
; j
++) {
370 subpass
->input_attachments
[j
] = (struct radv_subpass_attachment
) {
371 .attachment
= desc
->pInputAttachments
[j
].attachment
,
372 .layout
= desc
->pInputAttachments
[j
].layout
,
377 if (desc
->colorAttachmentCount
> 0) {
378 subpass
->color_attachments
= p
;
379 p
+= desc
->colorAttachmentCount
;
381 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
382 subpass
->color_attachments
[j
] = (struct radv_subpass_attachment
) {
383 .attachment
= desc
->pColorAttachments
[j
].attachment
,
384 .layout
= desc
->pColorAttachments
[j
].layout
,
389 if (desc
->pResolveAttachments
) {
390 subpass
->resolve_attachments
= p
;
391 p
+= desc
->colorAttachmentCount
;
393 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
394 uint32_t a
= desc
->pResolveAttachments
[j
].attachment
;
395 subpass
->resolve_attachments
[j
] = (struct radv_subpass_attachment
) {
396 .attachment
= desc
->pResolveAttachments
[j
].attachment
,
397 .layout
= desc
->pResolveAttachments
[j
].layout
,
402 if (desc
->pDepthStencilAttachment
) {
403 subpass
->depth_stencil_attachment
= p
++;
405 *subpass
->depth_stencil_attachment
= (struct radv_subpass_attachment
) {
406 .attachment
= desc
->pDepthStencilAttachment
->attachment
,
407 .layout
= desc
->pDepthStencilAttachment
->layout
,
412 for (unsigned i
= 0; i
< pCreateInfo
->dependencyCount
; ++i
) {
413 radv_render_pass_add_subpass_dep(pass
,
414 &pCreateInfo
->pDependencies
[i
]);
417 radv_render_pass_compile(pass
);
419 *pRenderPass
= radv_render_pass_to_handle(pass
);
424 void radv_DestroyRenderPass(
427 const VkAllocationCallbacks
* pAllocator
)
429 RADV_FROM_HANDLE(radv_device
, device
, _device
);
430 RADV_FROM_HANDLE(radv_render_pass
, pass
, _pass
);
434 vk_free2(&device
->alloc
, pAllocator
, pass
->subpass_attachments
);
435 vk_free2(&device
->alloc
, pAllocator
, pass
);
438 void radv_GetRenderAreaGranularity(
440 VkRenderPass renderPass
,
441 VkExtent2D
* pGranularity
)
443 pGranularity
->width
= 1;
444 pGranularity
->height
= 1;