OSDN Git Service

anv/pass: Move implicit dependency setup to anv_render_pass_compile
[android-x86/external-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 }