• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2019 Red Hat.
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 "lvp_private.h"
25 
26 static void
lvp_render_pass_compile(struct lvp_render_pass * pass)27 lvp_render_pass_compile(struct lvp_render_pass *pass)
28 {
29    for (uint32_t i = 0; i < pass->subpass_count; i++) {
30       struct lvp_subpass *subpass = &pass->subpasses[i];
31 
32       for (uint32_t j = 0; j < subpass->attachment_count; j++) {
33          struct lvp_subpass_attachment *subpass_att =
34             &subpass->attachments[j];
35          if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
36             continue;
37 
38          struct lvp_render_pass_attachment *pass_att =
39             &pass->attachments[subpass_att->attachment];
40 
41          pass_att->first_subpass_idx = UINT32_MAX;
42       }
43    }
44 
45    for (uint32_t i = 0; i < pass->subpass_count; i++) {
46       struct lvp_subpass *subpass = &pass->subpasses[i];
47       uint32_t color_sample_count = 1, depth_sample_count = 1;
48 
49       /* We don't allow depth_stencil_attachment to be non-NULL and
50        * be VK_ATTACHMENT_UNUSED.  This way something can just check
51        * for NULL and be guaranteed that they have a valid
52        * attachment.
53        */
54       if (subpass->depth_stencil_attachment &&
55           subpass->depth_stencil_attachment->attachment == VK_ATTACHMENT_UNUSED)
56          subpass->depth_stencil_attachment = NULL;
57 
58       if (subpass->ds_resolve_attachment &&
59           subpass->ds_resolve_attachment->attachment == VK_ATTACHMENT_UNUSED)
60          subpass->ds_resolve_attachment = NULL;
61 
62       for (uint32_t j = 0; j < subpass->attachment_count; j++) {
63          struct lvp_subpass_attachment *subpass_att =
64             &subpass->attachments[j];
65          if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
66             continue;
67 
68          struct lvp_render_pass_attachment *pass_att =
69             &pass->attachments[subpass_att->attachment];
70 
71          if (i < pass_att->first_subpass_idx)
72             pass_att->first_subpass_idx = i;
73          pass_att->last_subpass_idx = i;
74       }
75 
76       subpass->has_color_att = false;
77       for (uint32_t j = 0; j < subpass->color_count; j++) {
78          struct lvp_subpass_attachment *subpass_att =
79             &subpass->color_attachments[j];
80          if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
81             continue;
82 
83          subpass->has_color_att = true;
84 
85          struct lvp_render_pass_attachment *pass_att =
86             &pass->attachments[subpass_att->attachment];
87 
88          color_sample_count = pass_att->samples;
89       }
90 
91       if (subpass->depth_stencil_attachment) {
92          const uint32_t a =
93             subpass->depth_stencil_attachment->attachment;
94          struct lvp_render_pass_attachment *pass_att =
95             &pass->attachments[a];
96          depth_sample_count = pass_att->samples;
97       }
98 
99       subpass->max_sample_count = MAX2(color_sample_count,
100                                        depth_sample_count);
101 
102       /* We have to handle resolve attachments specially */
103       subpass->has_color_resolve = false;
104       if (subpass->resolve_attachments) {
105          for (uint32_t j = 0; j < subpass->color_count; j++) {
106             struct lvp_subpass_attachment *resolve_att =
107                &subpass->resolve_attachments[j];
108 
109             if (resolve_att->attachment == VK_ATTACHMENT_UNUSED)
110                continue;
111 
112             subpass->has_color_resolve = true;
113          }
114       }
115 
116       for (uint32_t j = 0; j < subpass->input_count; ++j) {
117          if (subpass->input_attachments[j].attachment == VK_ATTACHMENT_UNUSED)
118             continue;
119 
120          for (uint32_t k = 0; k < subpass->color_count; ++k) {
121             if (subpass->color_attachments[k].attachment == subpass->input_attachments[j].attachment) {
122                subpass->input_attachments[j].in_render_loop = true;
123                subpass->color_attachments[k].in_render_loop = true;
124             }
125          }
126 
127          if (subpass->depth_stencil_attachment &&
128              subpass->depth_stencil_attachment->attachment == subpass->input_attachments[j].attachment) {
129             subpass->input_attachments[j].in_render_loop = true;
130             subpass->depth_stencil_attachment->in_render_loop = true;
131          }
132       }
133    }
134 }
135 
136 static unsigned
lvp_num_subpass_attachments(const VkSubpassDescription * desc)137 lvp_num_subpass_attachments(const VkSubpassDescription *desc)
138 {
139    return desc->inputAttachmentCount +
140       desc->colorAttachmentCount +
141       (desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
142       (desc->pDepthStencilAttachment != NULL);
143 }
144 
lvp_CreateRenderPass(VkDevice _device,const VkRenderPassCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass)145 VkResult lvp_CreateRenderPass(
146    VkDevice                                    _device,
147    const VkRenderPassCreateInfo*               pCreateInfo,
148    const VkAllocationCallbacks*                pAllocator,
149    VkRenderPass*                               pRenderPass)
150 {
151    LVP_FROM_HANDLE(lvp_device, device, _device);
152    struct lvp_render_pass *pass;
153    size_t size;
154    size_t attachments_offset;
155 
156    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
157 
158    size = sizeof(*pass);
159    size += pCreateInfo->subpassCount * sizeof(pass->subpasses[0]);
160    attachments_offset = size;
161    size += pCreateInfo->attachmentCount * sizeof(pass->attachments[0]);
162 
163    pass = vk_alloc2(&device->vk.alloc, pAllocator, size, 8,
164                     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
165    if (pass == NULL)
166       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
167 
168    /* Clear the subpasses along with the parent pass. This required because
169     * each array member of lvp_subpass must be a valid pointer if not NULL.
170     */
171    memset(pass, 0, size);
172 
173    vk_object_base_init(&device->vk, &pass->base,
174                        VK_OBJECT_TYPE_RENDER_PASS);
175    pass->attachment_count = pCreateInfo->attachmentCount;
176    pass->subpass_count = pCreateInfo->subpassCount;
177    pass->attachments = (void *) pass + attachments_offset;
178 
179    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
180       struct lvp_render_pass_attachment *att = &pass->attachments[i];
181 
182       att->format = pCreateInfo->pAttachments[i].format;
183       att->samples = pCreateInfo->pAttachments[i].samples;
184       att->load_op = pCreateInfo->pAttachments[i].loadOp;
185       att->stencil_load_op = pCreateInfo->pAttachments[i].stencilLoadOp;
186       att->final_layout = pCreateInfo->pAttachments[i].finalLayout;
187       att->first_subpass_idx = UINT32_MAX;
188    }
189 
190    uint32_t subpass_attachment_count = 0;
191    for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
192       subpass_attachment_count += lvp_num_subpass_attachments(&pCreateInfo->pSubpasses[i]);
193    }
194 
195    if (subpass_attachment_count) {
196       pass->subpass_attachments =
197          vk_alloc2(&device->vk.alloc, pAllocator,
198                    subpass_attachment_count * sizeof(struct lvp_subpass_attachment), 8,
199                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
200       if (pass->subpass_attachments == NULL) {
201          vk_free2(&device->vk.alloc, pAllocator, pass);
202          return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
203       }
204    } else
205       pass->subpass_attachments = NULL;
206 
207    struct lvp_subpass_attachment *p = pass->subpass_attachments;
208    for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
209       const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i];
210       struct lvp_subpass *subpass = &pass->subpasses[i];
211 
212       subpass->input_count = desc->inputAttachmentCount;
213       subpass->color_count = desc->colorAttachmentCount;
214       subpass->attachment_count = lvp_num_subpass_attachments(desc);
215       subpass->attachments = p;
216 
217       if (desc->inputAttachmentCount > 0) {
218          subpass->input_attachments = p;
219          p += desc->inputAttachmentCount;
220 
221          for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) {
222             subpass->input_attachments[j] = (struct lvp_subpass_attachment) {
223                .attachment = desc->pInputAttachments[j].attachment,
224                .layout = desc->pInputAttachments[j].layout,
225             };
226          }
227       }
228 
229       if (desc->colorAttachmentCount > 0) {
230          subpass->color_attachments = p;
231          p += desc->colorAttachmentCount;
232 
233          for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
234             subpass->color_attachments[j] = (struct lvp_subpass_attachment) {
235                .attachment = desc->pColorAttachments[j].attachment,
236                .layout = desc->pColorAttachments[j].layout,
237             };
238          }
239       }
240 
241       if (desc->pResolveAttachments) {
242          subpass->resolve_attachments = p;
243          p += desc->colorAttachmentCount;
244 
245          for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
246             subpass->resolve_attachments[j] = (struct lvp_subpass_attachment) {
247                .attachment = desc->pResolveAttachments[j].attachment,
248                .layout = desc->pResolveAttachments[j].layout,
249             };
250          }
251       }
252 
253       if (desc->pDepthStencilAttachment) {
254          subpass->depth_stencil_attachment = p++;
255 
256          *subpass->depth_stencil_attachment = (struct lvp_subpass_attachment) {
257             .attachment = desc->pDepthStencilAttachment->attachment,
258             .layout = desc->pDepthStencilAttachment->layout,
259          };
260       }
261    }
262 
263    lvp_render_pass_compile(pass);
264    *pRenderPass = lvp_render_pass_to_handle(pass);
265 
266    return VK_SUCCESS;
267 }
268 
lvp_DestroyRenderPass(VkDevice _device,VkRenderPass _pass,const VkAllocationCallbacks * pAllocator)269 void lvp_DestroyRenderPass(
270    VkDevice                                    _device,
271    VkRenderPass                                _pass,
272    const VkAllocationCallbacks*                pAllocator)
273 {
274    LVP_FROM_HANDLE(lvp_device, device, _device);
275    LVP_FROM_HANDLE(lvp_render_pass, pass, _pass);
276 
277    if (!_pass)
278       return;
279    vk_object_base_finish(&pass->base);
280    vk_free2(&device->vk.alloc, pAllocator, pass->subpass_attachments);
281    vk_free2(&device->vk.alloc, pAllocator, pass);
282 }
283 
lvp_GetRenderAreaGranularity(VkDevice device,VkRenderPass renderPass,VkExtent2D * pGranularity)284 void lvp_GetRenderAreaGranularity(
285    VkDevice                                    device,
286    VkRenderPass                                renderPass,
287    VkExtent2D*                                 pGranularity)
288 {
289    *pGranularity = (VkExtent2D) { 1, 1 };
290 }
291