anv/pass: Move implicit dependency setup to anv_render_pass_compile
[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 VkImageUsageFlags all_usage = 0;
66 for (uint32_t i = 0; i < pass->subpass_count; i++) {
67 struct anv_subpass *subpass = &pass->subpasses[i];
68
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)
72 continue;
73
74 struct anv_render_pass_attachment *pass_att =
75 &pass->attachments[subpass_att->attachment];
76
77 assert(__builtin_popcount(subpass_att->usage) == 1);
78 pass_att->usage |= subpass_att->usage;
79 pass_att->last_subpass_idx = i;
80
81 all_usage |= subpass_att->usage;
82
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);
86 }
87
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;
91 }
92
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)
102 continue;
103
104 subpass->has_resolve = true;
105
106 assert(resolve_att->usage == VK_IMAGE_USAGE_TRANSFER_DST_BIT);
107 color_att->usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
108 }
109 }
110 }
111
112 /* From the Vulkan 1.0.39 spec:
113 *
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:
119 *
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;
132 * };
133 *
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:
139 *
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;
152 * };
153 *
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.
158 */
159 if (all_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
160 pass->subpass_flushes[0] |=
161 ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT;
162 }
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;
166 }
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;
170 }
171 }
172
173 static unsigned
174 num_subpass_attachments(const VkSubpassDescription *desc)
175 {
176 return desc->inputAttachmentCount +
177 desc->colorAttachmentCount +
178 (desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
179 (desc->pDepthStencilAttachment != NULL);
180 }
181
182 VkResult anv_CreateRenderPass(
183 VkDevice _device,
184 const VkRenderPassCreateInfo* pCreateInfo,
185 const VkAllocationCallbacks* pAllocator,
186 VkRenderPass* pRenderPass)
187 {
188 ANV_FROM_HANDLE(anv_device, device, _device);
189
190 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
191
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;
196
197 ANV_MULTIALLOC(ma);
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);
202
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]);
208 }
209 anv_multialloc_add(&ma, &subpass_attachments, subpass_attachment_count);
210
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);
214
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.
217 */
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;
223
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,
233 };
234 }
235
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];
239
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;
245
246 if (desc->inputAttachmentCount > 0) {
247 subpass->input_attachments = subpass_attachments;
248 subpass_attachments += desc->inputAttachmentCount;
249
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,
255 };
256 }
257 }
258
259 if (desc->colorAttachmentCount > 0) {
260 subpass->color_attachments = subpass_attachments;
261 subpass_attachments += desc->colorAttachmentCount;
262
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,
268 };
269 }
270 }
271
272 if (desc->pResolveAttachments) {
273 subpass->resolve_attachments = subpass_attachments;
274 subpass_attachments += desc->colorAttachmentCount;
275
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,
281 };
282 }
283 }
284
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,
290 };
291 *subpass_attachments++ = subpass->depth_stencil_attachment;
292 } else {
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,
297 };
298 }
299 }
300
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,
311 };
312 anv_render_pass_add_subpass_dep(pass, &dep2);
313 }
314
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;
319
320 for (uint32_t i = 0; i < mv->subpassCount; i++) {
321 pass->subpasses[i].view_mask = mv->pViewMasks[i];
322 }
323 break;
324 }
325
326 default:
327 anv_debug_ignored_stype(ext->sType);
328 }
329 }
330
331 anv_render_pass_compile(pass);
332
333 *pRenderPass = anv_render_pass_to_handle(pass);
334
335 return VK_SUCCESS;
336 }
337
338 void anv_DestroyRenderPass(
339 VkDevice _device,
340 VkRenderPass _pass,
341 const VkAllocationCallbacks* pAllocator)
342 {
343 ANV_FROM_HANDLE(anv_device, device, _device);
344 ANV_FROM_HANDLE(anv_render_pass, pass, _pass);
345
346 vk_free2(&device->alloc, pAllocator, pass);
347 }
348
349 void anv_GetRenderAreaGranularity(
350 VkDevice device,
351 VkRenderPass renderPass,
352 VkExtent2D* pGranularity)
353 {
354 ANV_FROM_HANDLE(anv_render_pass, pass, renderPass);
355
356 /* This granularity satisfies HiZ fast clear alignment requirements
357 * for all sample counts.
358 */
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 };
363 return;
364 }
365 }
366
367 *pGranularity = (VkExtent2D) { 1, 1 };
368 }