2 * Copyright © 2015 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #include "anv_private.h"
29 anv_render_pass_add_subpass_dep(struct anv_render_pass
*pass
,
30 const VkSubpassDependency2KHR
*dep
)
32 if (dep
->dstSubpass
== VK_SUBPASS_EXTERNAL
) {
33 pass
->subpass_flushes
[pass
->subpass_count
] |=
34 anv_pipe_invalidate_bits_for_access_flags(dep
->dstAccessMask
);
36 assert(dep
->dstSubpass
< pass
->subpass_count
);
37 pass
->subpass_flushes
[dep
->dstSubpass
] |=
38 anv_pipe_invalidate_bits_for_access_flags(dep
->dstAccessMask
);
41 if (dep
->srcSubpass
== VK_SUBPASS_EXTERNAL
) {
42 pass
->subpass_flushes
[0] |=
43 anv_pipe_flush_bits_for_access_flags(dep
->srcAccessMask
);
45 assert(dep
->srcSubpass
< pass
->subpass_count
);
46 pass
->subpass_flushes
[dep
->srcSubpass
+ 1] |=
47 anv_pipe_flush_bits_for_access_flags(dep
->srcAccessMask
);
51 /* Do a second "compile" step on a render pass */
53 anv_render_pass_compile(struct anv_render_pass
*pass
)
55 /* The CreateRenderPass code zeros the entire render pass and also uses a
56 * designated initializer for filling these out. There's no need for us to
59 * for (uint32_t i = 0; i < pass->attachment_count; i++) {
60 * pass->attachments[i].usage = 0;
61 * pass->attachments[i].first_subpass_layout = VK_IMAGE_LAYOUT_UNDEFINED;
65 VkImageUsageFlags all_usage
= 0;
66 for (uint32_t i
= 0; i
< pass
->subpass_count
; i
++) {
67 struct anv_subpass
*subpass
= &pass
->subpasses
[i
];
69 for (uint32_t j
= 0; j
< subpass
->attachment_count
; j
++) {
70 struct anv_subpass_attachment
*subpass_att
= &subpass
->attachments
[j
];
71 if (subpass_att
->attachment
== VK_ATTACHMENT_UNUSED
)
74 struct anv_render_pass_attachment
*pass_att
=
75 &pass
->attachments
[subpass_att
->attachment
];
77 assert(__builtin_popcount(subpass_att
->usage
) == 1);
78 pass_att
->usage
|= subpass_att
->usage
;
79 pass_att
->last_subpass_idx
= i
;
81 all_usage
|= subpass_att
->usage
;
83 if (pass_att
->first_subpass_layout
== VK_IMAGE_LAYOUT_UNDEFINED
) {
84 pass_att
->first_subpass_layout
= subpass_att
->layout
;
85 assert(pass_att
->first_subpass_layout
!= VK_IMAGE_LAYOUT_UNDEFINED
);
88 if (subpass_att
->usage
== VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
&&
89 subpass_att
->attachment
== subpass
->depth_stencil_attachment
.attachment
)
90 subpass
->has_ds_self_dep
= true;
93 /* We have to handle resolve attachments specially */
94 subpass
->has_resolve
= false;
95 if (subpass
->resolve_attachments
) {
96 for (uint32_t j
= 0; j
< subpass
->color_count
; j
++) {
97 struct anv_subpass_attachment
*color_att
=
98 &subpass
->color_attachments
[j
];
99 struct anv_subpass_attachment
*resolve_att
=
100 &subpass
->resolve_attachments
[j
];
101 if (resolve_att
->attachment
== VK_ATTACHMENT_UNUSED
)
104 subpass
->has_resolve
= true;
106 assert(resolve_att
->usage
== VK_IMAGE_USAGE_TRANSFER_DST_BIT
);
107 color_att
->usage
|= VK_IMAGE_USAGE_TRANSFER_SRC_BIT
;
112 /* From the Vulkan 1.0.39 spec:
114 * If there is no subpass dependency from VK_SUBPASS_EXTERNAL to the
115 * first subpass that uses an attachment, then an implicit subpass
116 * dependency exists from VK_SUBPASS_EXTERNAL to the first subpass it is
117 * used in. The subpass dependency operates as if defined with the
118 * following parameters:
120 * VkSubpassDependency implicitDependency = {
121 * .srcSubpass = VK_SUBPASS_EXTERNAL;
122 * .dstSubpass = firstSubpass; // First subpass attachment is used in
123 * .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
124 * .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
125 * .srcAccessMask = 0;
126 * .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
127 * VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
128 * VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
129 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
130 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
131 * .dependencyFlags = 0;
134 * Similarly, if there is no subpass dependency from the last subpass
135 * that uses an attachment to VK_SUBPASS_EXTERNAL, then an implicit
136 * subpass dependency exists from the last subpass it is used in to
137 * VK_SUBPASS_EXTERNAL. The subpass dependency operates as if defined
138 * with the following parameters:
140 * VkSubpassDependency implicitDependency = {
141 * .srcSubpass = lastSubpass; // Last subpass attachment is used in
142 * .dstSubpass = VK_SUBPASS_EXTERNAL;
143 * .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
144 * .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
145 * .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
146 * VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
147 * VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
148 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
149 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
150 * .dstAccessMask = 0;
151 * .dependencyFlags = 0;
154 * We could implement this by walking over all of the attachments and
155 * subpasses and checking to see if any of them don't have an external
156 * dependency. Or, we could just be lazy and add a couple extra flushes.
157 * We choose to be lazy.
159 if (all_usage
& VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
) {
160 pass
->subpass_flushes
[0] |=
161 ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT
;
163 if (all_usage
& VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
) {
164 pass
->subpass_flushes
[pass
->subpass_count
] |=
165 ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT
;
167 if (all_usage
& VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
) {
168 pass
->subpass_flushes
[pass
->subpass_count
] |=
169 ANV_PIPE_DEPTH_CACHE_FLUSH_BIT
;
174 num_subpass_attachments(const VkSubpassDescription
*desc
)
176 return desc
->inputAttachmentCount
+
177 desc
->colorAttachmentCount
+
178 (desc
->pResolveAttachments
? desc
->colorAttachmentCount
: 0) +
179 (desc
->pDepthStencilAttachment
!= NULL
);
182 VkResult
anv_CreateRenderPass(
184 const VkRenderPassCreateInfo
* pCreateInfo
,
185 const VkAllocationCallbacks
* pAllocator
,
186 VkRenderPass
* pRenderPass
)
188 ANV_FROM_HANDLE(anv_device
, device
, _device
);
190 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
);
192 struct anv_render_pass
*pass
;
193 struct anv_subpass
*subpasses
;
194 struct anv_render_pass_attachment
*attachments
;
195 enum anv_pipe_bits
*subpass_flushes
;
198 anv_multialloc_add(&ma
, &pass
, 1);
199 anv_multialloc_add(&ma
, &subpasses
, pCreateInfo
->subpassCount
);
200 anv_multialloc_add(&ma
, &attachments
, pCreateInfo
->attachmentCount
);
201 anv_multialloc_add(&ma
, &subpass_flushes
, pCreateInfo
->subpassCount
+ 1);
203 struct anv_subpass_attachment
*subpass_attachments
;
204 uint32_t subpass_attachment_count
= 0;
205 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
206 subpass_attachment_count
+=
207 num_subpass_attachments(&pCreateInfo
->pSubpasses
[i
]);
209 anv_multialloc_add(&ma
, &subpass_attachments
, subpass_attachment_count
);
211 if (!anv_multialloc_alloc2(&ma
, &device
->alloc
, pAllocator
,
212 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
))
213 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
215 /* Clear the subpasses along with the parent pass. This required because
216 * each array member of anv_subpass must be a valid pointer if not NULL.
218 memset(pass
, 0, ma
.size
);
219 pass
->attachment_count
= pCreateInfo
->attachmentCount
;
220 pass
->subpass_count
= pCreateInfo
->subpassCount
;
221 pass
->attachments
= attachments
;
222 pass
->subpass_flushes
= subpass_flushes
;
224 for (uint32_t i
= 0; i
< pCreateInfo
->attachmentCount
; i
++) {
225 pass
->attachments
[i
] = (struct anv_render_pass_attachment
) {
226 .format
= pCreateInfo
->pAttachments
[i
].format
,
227 .samples
= pCreateInfo
->pAttachments
[i
].samples
,
228 .load_op
= pCreateInfo
->pAttachments
[i
].loadOp
,
229 .store_op
= pCreateInfo
->pAttachments
[i
].storeOp
,
230 .stencil_load_op
= pCreateInfo
->pAttachments
[i
].stencilLoadOp
,
231 .initial_layout
= pCreateInfo
->pAttachments
[i
].initialLayout
,
232 .final_layout
= pCreateInfo
->pAttachments
[i
].finalLayout
,
236 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
237 const VkSubpassDescription
*desc
= &pCreateInfo
->pSubpasses
[i
];
238 struct anv_subpass
*subpass
= &pass
->subpasses
[i
];
240 subpass
->input_count
= desc
->inputAttachmentCount
;
241 subpass
->color_count
= desc
->colorAttachmentCount
;
242 subpass
->attachment_count
= num_subpass_attachments(desc
);
243 subpass
->attachments
= subpass_attachments
;
244 subpass
->view_mask
= 0;
246 if (desc
->inputAttachmentCount
> 0) {
247 subpass
->input_attachments
= subpass_attachments
;
248 subpass_attachments
+= desc
->inputAttachmentCount
;
250 for (uint32_t j
= 0; j
< desc
->inputAttachmentCount
; j
++) {
251 subpass
->input_attachments
[j
] = (struct anv_subpass_attachment
) {
252 .usage
= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
,
253 .attachment
= desc
->pInputAttachments
[j
].attachment
,
254 .layout
= desc
->pInputAttachments
[j
].layout
,
259 if (desc
->colorAttachmentCount
> 0) {
260 subpass
->color_attachments
= subpass_attachments
;
261 subpass_attachments
+= desc
->colorAttachmentCount
;
263 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
264 subpass
->color_attachments
[j
] = (struct anv_subpass_attachment
) {
265 .usage
= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
,
266 .attachment
= desc
->pColorAttachments
[j
].attachment
,
267 .layout
= desc
->pColorAttachments
[j
].layout
,
272 if (desc
->pResolveAttachments
) {
273 subpass
->resolve_attachments
= subpass_attachments
;
274 subpass_attachments
+= desc
->colorAttachmentCount
;
276 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
277 subpass
->resolve_attachments
[j
] = (struct anv_subpass_attachment
) {
278 .usage
= VK_IMAGE_USAGE_TRANSFER_DST_BIT
,
279 .attachment
= desc
->pResolveAttachments
[j
].attachment
,
280 .layout
= desc
->pResolveAttachments
[j
].layout
,
285 if (desc
->pDepthStencilAttachment
) {
286 subpass
->depth_stencil_attachment
= (struct anv_subpass_attachment
) {
287 .usage
= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
,
288 .attachment
= desc
->pDepthStencilAttachment
->attachment
,
289 .layout
= desc
->pDepthStencilAttachment
->layout
,
291 *subpass_attachments
++ = subpass
->depth_stencil_attachment
;
293 subpass
->depth_stencil_attachment
= (struct anv_subpass_attachment
) {
294 .usage
= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
,
295 .attachment
= VK_ATTACHMENT_UNUSED
,
296 .layout
= VK_IMAGE_LAYOUT_UNDEFINED
,
301 for (uint32_t i
= 0; i
< pCreateInfo
->dependencyCount
; i
++) {
302 /* Convert to a Dependency2KHR */
303 struct VkSubpassDependency2KHR dep2
= {
304 .srcSubpass
= pCreateInfo
->pDependencies
[i
].srcSubpass
,
305 .dstSubpass
= pCreateInfo
->pDependencies
[i
].dstSubpass
,
306 .srcStageMask
= pCreateInfo
->pDependencies
[i
].srcStageMask
,
307 .dstStageMask
= pCreateInfo
->pDependencies
[i
].dstStageMask
,
308 .srcAccessMask
= pCreateInfo
->pDependencies
[i
].srcAccessMask
,
309 .dstAccessMask
= pCreateInfo
->pDependencies
[i
].dstAccessMask
,
310 .dependencyFlags
= pCreateInfo
->pDependencies
[i
].dependencyFlags
,
312 anv_render_pass_add_subpass_dep(pass
, &dep2
);
315 vk_foreach_struct(ext
, pCreateInfo
->pNext
) {
316 switch (ext
->sType
) {
317 case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR
: {
318 VkRenderPassMultiviewCreateInfoKHR
*mv
= (void *)ext
;
320 for (uint32_t i
= 0; i
< mv
->subpassCount
; i
++) {
321 pass
->subpasses
[i
].view_mask
= mv
->pViewMasks
[i
];
327 anv_debug_ignored_stype(ext
->sType
);
331 anv_render_pass_compile(pass
);
333 *pRenderPass
= anv_render_pass_to_handle(pass
);
338 void anv_DestroyRenderPass(
341 const VkAllocationCallbacks
* pAllocator
)
343 ANV_FROM_HANDLE(anv_device
, device
, _device
);
344 ANV_FROM_HANDLE(anv_render_pass
, pass
, _pass
);
346 vk_free2(&device
->alloc
, pAllocator
, pass
);
349 void anv_GetRenderAreaGranularity(
351 VkRenderPass renderPass
,
352 VkExtent2D
* pGranularity
)
354 ANV_FROM_HANDLE(anv_render_pass
, pass
, renderPass
);
356 /* This granularity satisfies HiZ fast clear alignment requirements
357 * for all sample counts.
359 for (unsigned i
= 0; i
< pass
->subpass_count
; ++i
) {
360 if (pass
->subpasses
[i
].depth_stencil_attachment
.attachment
!=
361 VK_ATTACHMENT_UNUSED
) {
362 *pGranularity
= (VkExtent2D
) { .width
= 8, .height
= 4 };
367 *pGranularity
= (VkExtent2D
) { 1, 1 };