b70de87a82b1a1ece6c44d516b919c0860aefa17
[mesa.git] / src / intel / vulkan / anv_pass.c
1 /*
2 * Copyright © 2015 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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
21 * IN THE SOFTWARE.
22 */
23
24 #include "anv_private.h"
25
26 #include "vk_util.h"
27
28 static void
29 anv_render_pass_add_subpass_dep(struct anv_render_pass *pass,
30 const VkSubpassDependency2KHR *dep)
31 {
32 if (dep->dstSubpass == VK_SUBPASS_EXTERNAL) {
33 pass->subpass_flushes[pass->subpass_count] |=
34 anv_pipe_invalidate_bits_for_access_flags(dep->dstAccessMask);
35 } else {
36 assert(dep->dstSubpass < pass->subpass_count);
37 pass->subpass_flushes[dep->dstSubpass] |=
38 anv_pipe_invalidate_bits_for_access_flags(dep->dstAccessMask);
39 }
40
41 if (dep->srcSubpass == VK_SUBPASS_EXTERNAL) {
42 pass->subpass_flushes[0] |=
43 anv_pipe_flush_bits_for_access_flags(dep->srcAccessMask);
44 } else {
45 assert(dep->srcSubpass < pass->subpass_count);
46 pass->subpass_flushes[dep->srcSubpass + 1] |=
47 anv_pipe_flush_bits_for_access_flags(dep->srcAccessMask);
48 }
49 }
50
51 /* Do a second "compile" step on a render pass */
52 static void
53 anv_render_pass_compile(struct anv_render_pass *pass)
54 {
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
57 * do it again.
58 *
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;
62 * }
63 */
64
65 for (uint32_t i = 0; i < pass->subpass_count; i++) {
66 struct anv_subpass *subpass = &pass->subpasses[i];
67
68 for (uint32_t j = 0; j < subpass->attachment_count; j++) {
69 struct anv_subpass_attachment *subpass_att = &subpass->attachments[j];
70 if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
71 continue;
72
73 struct anv_render_pass_attachment *pass_att =
74 &pass->attachments[subpass_att->attachment];
75
76 assert(__builtin_popcount(subpass_att->usage) == 1);
77 pass_att->usage |= subpass_att->usage;
78 pass_att->last_subpass_idx = i;
79
80 if (pass_att->first_subpass_layout == VK_IMAGE_LAYOUT_UNDEFINED) {
81 pass_att->first_subpass_layout = subpass_att->layout;
82 assert(pass_att->first_subpass_layout != VK_IMAGE_LAYOUT_UNDEFINED);
83 }
84
85 if (subpass_att->usage == VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT &&
86 subpass_att->attachment == subpass->depth_stencil_attachment.attachment)
87 subpass->has_ds_self_dep = true;
88 }
89
90 /* We have to handle resolve attachments specially */
91 subpass->has_resolve = false;
92 if (subpass->resolve_attachments) {
93 for (uint32_t j = 0; j < subpass->color_count; j++) {
94 struct anv_subpass_attachment *color_att =
95 &subpass->color_attachments[j];
96 struct anv_subpass_attachment *resolve_att =
97 &subpass->resolve_attachments[j];
98 if (resolve_att->attachment == VK_ATTACHMENT_UNUSED)
99 continue;
100
101 subpass->has_resolve = true;
102
103 assert(resolve_att->usage == VK_IMAGE_USAGE_TRANSFER_DST_BIT);
104 color_att->usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
105 }
106 }
107 }
108 }
109
110 static unsigned
111 num_subpass_attachments(const VkSubpassDescription *desc)
112 {
113 return desc->inputAttachmentCount +
114 desc->colorAttachmentCount +
115 (desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
116 (desc->pDepthStencilAttachment != NULL);
117 }
118
119 VkResult anv_CreateRenderPass(
120 VkDevice _device,
121 const VkRenderPassCreateInfo* pCreateInfo,
122 const VkAllocationCallbacks* pAllocator,
123 VkRenderPass* pRenderPass)
124 {
125 ANV_FROM_HANDLE(anv_device, device, _device);
126
127 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
128
129 struct anv_render_pass *pass;
130 struct anv_subpass *subpasses;
131 struct anv_render_pass_attachment *attachments;
132 enum anv_pipe_bits *subpass_flushes;
133
134 ANV_MULTIALLOC(ma);
135 anv_multialloc_add(&ma, &pass, 1);
136 anv_multialloc_add(&ma, &subpasses, pCreateInfo->subpassCount);
137 anv_multialloc_add(&ma, &attachments, pCreateInfo->attachmentCount);
138 anv_multialloc_add(&ma, &subpass_flushes, pCreateInfo->subpassCount + 1);
139
140 struct anv_subpass_attachment *subpass_attachments;
141 uint32_t subpass_attachment_count = 0;
142 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
143 subpass_attachment_count +=
144 num_subpass_attachments(&pCreateInfo->pSubpasses[i]);
145 }
146 anv_multialloc_add(&ma, &subpass_attachments, subpass_attachment_count);
147
148 if (!anv_multialloc_alloc2(&ma, &device->alloc, pAllocator,
149 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
150 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
151
152 /* Clear the subpasses along with the parent pass. This required because
153 * each array member of anv_subpass must be a valid pointer if not NULL.
154 */
155 memset(pass, 0, ma.size);
156 pass->attachment_count = pCreateInfo->attachmentCount;
157 pass->subpass_count = pCreateInfo->subpassCount;
158 pass->attachments = attachments;
159 pass->subpass_flushes = subpass_flushes;
160
161 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
162 pass->attachments[i] = (struct anv_render_pass_attachment) {
163 .format = pCreateInfo->pAttachments[i].format,
164 .samples = pCreateInfo->pAttachments[i].samples,
165 .load_op = pCreateInfo->pAttachments[i].loadOp,
166 .store_op = pCreateInfo->pAttachments[i].storeOp,
167 .stencil_load_op = pCreateInfo->pAttachments[i].stencilLoadOp,
168 .initial_layout = pCreateInfo->pAttachments[i].initialLayout,
169 .final_layout = pCreateInfo->pAttachments[i].finalLayout,
170 };
171 }
172
173 bool has_color = false, has_depth = false, has_input = false;
174 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
175 const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i];
176 struct anv_subpass *subpass = &pass->subpasses[i];
177
178 subpass->input_count = desc->inputAttachmentCount;
179 subpass->color_count = desc->colorAttachmentCount;
180 subpass->attachment_count = num_subpass_attachments(desc);
181 subpass->attachments = subpass_attachments;
182 subpass->view_mask = 0;
183
184 if (desc->inputAttachmentCount > 0) {
185 subpass->input_attachments = subpass_attachments;
186 subpass_attachments += desc->inputAttachmentCount;
187
188 for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) {
189 uint32_t a = desc->pInputAttachments[j].attachment;
190 subpass->input_attachments[j] = (struct anv_subpass_attachment) {
191 .usage = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
192 .attachment = desc->pInputAttachments[j].attachment,
193 .layout = desc->pInputAttachments[j].layout,
194 };
195 if (a != VK_ATTACHMENT_UNUSED)
196 has_input = true;
197 }
198 }
199
200 if (desc->colorAttachmentCount > 0) {
201 subpass->color_attachments = subpass_attachments;
202 subpass_attachments += desc->colorAttachmentCount;
203
204 for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
205 uint32_t a = desc->pColorAttachments[j].attachment;
206 subpass->color_attachments[j] = (struct anv_subpass_attachment) {
207 .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
208 .attachment = desc->pColorAttachments[j].attachment,
209 .layout = desc->pColorAttachments[j].layout,
210 };
211 if (a != VK_ATTACHMENT_UNUSED)
212 has_color = true;
213 }
214 }
215
216 if (desc->pResolveAttachments) {
217 subpass->resolve_attachments = subpass_attachments;
218 subpass_attachments += desc->colorAttachmentCount;
219
220 for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
221 subpass->resolve_attachments[j] = (struct anv_subpass_attachment) {
222 .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT,
223 .attachment = desc->pResolveAttachments[j].attachment,
224 .layout = desc->pResolveAttachments[j].layout,
225 };
226 }
227 }
228
229 if (desc->pDepthStencilAttachment) {
230 uint32_t a = desc->pDepthStencilAttachment->attachment;
231 subpass->depth_stencil_attachment = (struct anv_subpass_attachment) {
232 .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
233 .attachment = desc->pDepthStencilAttachment->attachment,
234 .layout = desc->pDepthStencilAttachment->layout,
235 };
236 *subpass_attachments++ = subpass->depth_stencil_attachment;
237 if (a != VK_ATTACHMENT_UNUSED)
238 has_depth = true;
239 } else {
240 subpass->depth_stencil_attachment = (struct anv_subpass_attachment) {
241 .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
242 .attachment = VK_ATTACHMENT_UNUSED,
243 .layout = VK_IMAGE_LAYOUT_UNDEFINED,
244 };
245 }
246 }
247
248 for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
249 /* Convert to a Dependency2KHR */
250 struct VkSubpassDependency2KHR dep2 = {
251 .srcSubpass = pCreateInfo->pDependencies[i].srcSubpass,
252 .dstSubpass = pCreateInfo->pDependencies[i].dstSubpass,
253 .srcStageMask = pCreateInfo->pDependencies[i].srcStageMask,
254 .dstStageMask = pCreateInfo->pDependencies[i].dstStageMask,
255 .srcAccessMask = pCreateInfo->pDependencies[i].srcAccessMask,
256 .dstAccessMask = pCreateInfo->pDependencies[i].dstAccessMask,
257 .dependencyFlags = pCreateInfo->pDependencies[i].dependencyFlags,
258 };
259 anv_render_pass_add_subpass_dep(pass, &dep2);
260 }
261
262 /* From the Vulkan 1.0.39 spec:
263 *
264 * If there is no subpass dependency from VK_SUBPASS_EXTERNAL to the
265 * first subpass that uses an attachment, then an implicit subpass
266 * dependency exists from VK_SUBPASS_EXTERNAL to the first subpass it is
267 * used in. The subpass dependency operates as if defined with the
268 * following parameters:
269 *
270 * VkSubpassDependency implicitDependency = {
271 * .srcSubpass = VK_SUBPASS_EXTERNAL;
272 * .dstSubpass = firstSubpass; // First subpass attachment is used in
273 * .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
274 * .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
275 * .srcAccessMask = 0;
276 * .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
277 * VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
278 * VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
279 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
280 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
281 * .dependencyFlags = 0;
282 * };
283 *
284 * Similarly, if there is no subpass dependency from the last subpass
285 * that uses an attachment to VK_SUBPASS_EXTERNAL, then an implicit
286 * subpass dependency exists from the last subpass it is used in to
287 * VK_SUBPASS_EXTERNAL. The subpass dependency operates as if defined
288 * with the following parameters:
289 *
290 * VkSubpassDependency implicitDependency = {
291 * .srcSubpass = lastSubpass; // Last subpass attachment is used in
292 * .dstSubpass = VK_SUBPASS_EXTERNAL;
293 * .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
294 * .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
295 * .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
296 * VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
297 * VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
298 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
299 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
300 * .dstAccessMask = 0;
301 * .dependencyFlags = 0;
302 * };
303 *
304 * We could implement this by walking over all of the attachments and
305 * subpasses and checking to see if any of them don't have an external
306 * dependency. Or, we could just be lazy and add a couple extra flushes.
307 * We choose to be lazy.
308 */
309 if (has_input) {
310 pass->subpass_flushes[0] |=
311 ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT;
312 }
313 if (has_color) {
314 pass->subpass_flushes[pass->subpass_count] |=
315 ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT;
316 }
317 if (has_depth) {
318 pass->subpass_flushes[pass->subpass_count] |=
319 ANV_PIPE_DEPTH_CACHE_FLUSH_BIT;
320 }
321
322 vk_foreach_struct(ext, pCreateInfo->pNext) {
323 switch (ext->sType) {
324 case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR: {
325 VkRenderPassMultiviewCreateInfoKHR *mv = (void *)ext;
326
327 for (uint32_t i = 0; i < mv->subpassCount; i++) {
328 pass->subpasses[i].view_mask = mv->pViewMasks[i];
329 }
330 break;
331 }
332
333 default:
334 anv_debug_ignored_stype(ext->sType);
335 }
336 }
337
338 anv_render_pass_compile(pass);
339
340 *pRenderPass = anv_render_pass_to_handle(pass);
341
342 return VK_SUCCESS;
343 }
344
345 void anv_DestroyRenderPass(
346 VkDevice _device,
347 VkRenderPass _pass,
348 const VkAllocationCallbacks* pAllocator)
349 {
350 ANV_FROM_HANDLE(anv_device, device, _device);
351 ANV_FROM_HANDLE(anv_render_pass, pass, _pass);
352
353 vk_free2(&device->alloc, pAllocator, pass);
354 }
355
356 void anv_GetRenderAreaGranularity(
357 VkDevice device,
358 VkRenderPass renderPass,
359 VkExtent2D* pGranularity)
360 {
361 ANV_FROM_HANDLE(anv_render_pass, pass, renderPass);
362
363 /* This granularity satisfies HiZ fast clear alignment requirements
364 * for all sample counts.
365 */
366 for (unsigned i = 0; i < pass->subpass_count; ++i) {
367 if (pass->subpasses[i].depth_stencil_attachment.attachment !=
368 VK_ATTACHMENT_UNUSED) {
369 *pGranularity = (VkExtent2D) { .width = 8, .height = 4 };
370 return;
371 }
372 }
373
374 *pGranularity = (VkExtent2D) { 1, 1 };
375 }