1 /*
2  * Copyright © 2020 Valve 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 "vk_alloc.h"
25 #include "vk_common_entrypoints.h"
26 #include "vk_device.h"
27 #include "vk_format.h"
28 #include "vk_util.h"
29 
30 #include "util/log.h"
31 
32 static void
translate_references(VkAttachmentReference2 ** reference_ptr,uint32_t reference_count,const VkAttachmentReference * reference,const VkRenderPassCreateInfo * pass_info,bool is_input_attachment)33 translate_references(VkAttachmentReference2 **reference_ptr,
34                      uint32_t reference_count,
35                      const VkAttachmentReference *reference,
36                      const VkRenderPassCreateInfo *pass_info,
37                      bool is_input_attachment)
38 {
39    VkAttachmentReference2 *reference2 = *reference_ptr;
40    *reference_ptr += reference_count;
41    for (uint32_t i = 0; i < reference_count; i++) {
42       reference2[i] = (VkAttachmentReference2) {
43          .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
44          .pNext = NULL,
45          .attachment = reference[i].attachment,
46          .layout = reference[i].layout,
47       };
48 
49       if (is_input_attachment &&
50           reference2[i].attachment != VK_ATTACHMENT_UNUSED) {
51          assert(reference2[i].attachment < pass_info->attachmentCount);
52          const VkAttachmentDescription *att =
53             &pass_info->pAttachments[reference2[i].attachment];
54          reference2[i].aspectMask = vk_format_aspects(att->format);
55       }
56    }
57 }
58 
59 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateRenderPass(VkDevice _device,const VkRenderPassCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass)60 vk_common_CreateRenderPass(VkDevice _device,
61                            const VkRenderPassCreateInfo *pCreateInfo,
62                            const VkAllocationCallbacks *pAllocator,
63                            VkRenderPass *pRenderPass)
64 {
65    VK_FROM_HANDLE(vk_device, device, _device);
66 
67    uint32_t reference_count = 0;
68    for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
69       reference_count += pCreateInfo->pSubpasses[i].inputAttachmentCount;
70       reference_count += pCreateInfo->pSubpasses[i].colorAttachmentCount;
71       if (pCreateInfo->pSubpasses[i].pResolveAttachments)
72          reference_count += pCreateInfo->pSubpasses[i].colorAttachmentCount;
73       if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment)
74          reference_count += 1;
75    }
76 
77    VK_MULTIALLOC(ma);
78    VK_MULTIALLOC_DECL(&ma, VkRenderPassCreateInfo2, create_info, 1);
79    VK_MULTIALLOC_DECL(&ma, VkSubpassDescription2, subpasses,
80                            pCreateInfo->subpassCount);
81    VK_MULTIALLOC_DECL(&ma, VkAttachmentDescription2, attachments,
82                            pCreateInfo->attachmentCount);
83    VK_MULTIALLOC_DECL(&ma, VkSubpassDependency2, dependencies,
84                            pCreateInfo->dependencyCount);
85    VK_MULTIALLOC_DECL(&ma, VkAttachmentReference2, references,
86                            reference_count);
87    if (!vk_multialloc_alloc2(&ma, &device->alloc, pAllocator,
88                              VK_SYSTEM_ALLOCATION_SCOPE_COMMAND))
89       return VK_ERROR_OUT_OF_HOST_MEMORY;
90 
91    VkAttachmentReference2 *reference_ptr = references;
92 
93    const VkRenderPassMultiviewCreateInfo *multiview_info = NULL;
94    const VkRenderPassInputAttachmentAspectCreateInfo *aspect_info = NULL;
95    vk_foreach_struct(ext, pCreateInfo->pNext) {
96       switch (ext->sType) {
97       case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO:
98          aspect_info = (const VkRenderPassInputAttachmentAspectCreateInfo *)ext;
99          /* We don't care about this information */
100          break;
101 
102       case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
103          multiview_info = (const VkRenderPassMultiviewCreateInfo*) ext;
104          break;
105 
106       default:
107          mesa_logd("%s: ignored VkStructureType %u\n", __func__, ext->sType);
108          break;
109       }
110    }
111 
112    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
113       attachments[i] = (VkAttachmentDescription2) {
114          .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
115          .pNext = NULL,
116          .flags = pCreateInfo->pAttachments[i].flags,
117          .format = pCreateInfo->pAttachments[i].format,
118          .samples = pCreateInfo->pAttachments[i].samples,
119          .loadOp = pCreateInfo->pAttachments[i].loadOp,
120          .storeOp = pCreateInfo->pAttachments[i].storeOp,
121          .stencilLoadOp = pCreateInfo->pAttachments[i].stencilLoadOp,
122          .stencilStoreOp = pCreateInfo->pAttachments[i].stencilStoreOp,
123          .initialLayout = pCreateInfo->pAttachments[i].initialLayout,
124          .finalLayout = pCreateInfo->pAttachments[i].finalLayout,
125       };
126    }
127 
128    for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
129       subpasses[i] = (VkSubpassDescription2) {
130          .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
131          .pNext = NULL,
132          .flags = pCreateInfo->pSubpasses[i].flags,
133          .pipelineBindPoint = pCreateInfo->pSubpasses[i].pipelineBindPoint,
134          .viewMask = 0,
135          .inputAttachmentCount = pCreateInfo->pSubpasses[i].inputAttachmentCount,
136          .colorAttachmentCount = pCreateInfo->pSubpasses[i].colorAttachmentCount,
137          .preserveAttachmentCount = pCreateInfo->pSubpasses[i].preserveAttachmentCount,
138          .pPreserveAttachments = pCreateInfo->pSubpasses[i].pPreserveAttachments,
139       };
140 
141       if (multiview_info && multiview_info->subpassCount) {
142          assert(multiview_info->subpassCount == pCreateInfo->subpassCount);
143          subpasses[i].viewMask = multiview_info->pViewMasks[i];
144       }
145 
146       subpasses[i].pInputAttachments = reference_ptr;
147       translate_references(&reference_ptr,
148                            subpasses[i].inputAttachmentCount,
149                            pCreateInfo->pSubpasses[i].pInputAttachments,
150                            pCreateInfo, true);
151       subpasses[i].pColorAttachments = reference_ptr;
152       translate_references(&reference_ptr,
153                            subpasses[i].colorAttachmentCount,
154                            pCreateInfo->pSubpasses[i].pColorAttachments,
155                            pCreateInfo, false);
156       subpasses[i].pResolveAttachments = NULL;
157       if (pCreateInfo->pSubpasses[i].pResolveAttachments) {
158          subpasses[i].pResolveAttachments = reference_ptr;
159          translate_references(&reference_ptr,
160                               subpasses[i].colorAttachmentCount,
161                               pCreateInfo->pSubpasses[i].pResolveAttachments,
162                               pCreateInfo, false);
163       }
164       subpasses[i].pDepthStencilAttachment = NULL;
165       if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment) {
166          subpasses[i].pDepthStencilAttachment = reference_ptr;
167          translate_references(&reference_ptr, 1,
168                               pCreateInfo->pSubpasses[i].pDepthStencilAttachment,
169                               pCreateInfo, false);
170       }
171    }
172 
173    assert(reference_ptr == references + reference_count);
174 
175    if (aspect_info != NULL) {
176       for (uint32_t i = 0; i < aspect_info->aspectReferenceCount; i++) {
177          const VkInputAttachmentAspectReference *ref =
178             &aspect_info->pAspectReferences[i];
179 
180          assert(ref->subpass < pCreateInfo->subpassCount);
181          VkSubpassDescription2 *subpass = &subpasses[ref->subpass];
182 
183          assert(ref->inputAttachmentIndex < subpass->inputAttachmentCount);
184          VkAttachmentReference2 *att = (VkAttachmentReference2 *)
185             &subpass->pInputAttachments[ref->inputAttachmentIndex];
186 
187          att->aspectMask = ref->aspectMask;
188       }
189    }
190 
191    for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
192       dependencies[i] = (VkSubpassDependency2) {
193          .sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
194          .pNext = NULL,
195          .srcSubpass = pCreateInfo->pDependencies[i].srcSubpass,
196          .dstSubpass = pCreateInfo->pDependencies[i].dstSubpass,
197          .srcStageMask = pCreateInfo->pDependencies[i].srcStageMask,
198          .dstStageMask = pCreateInfo->pDependencies[i].dstStageMask,
199          .srcAccessMask = pCreateInfo->pDependencies[i].srcAccessMask,
200          .dstAccessMask = pCreateInfo->pDependencies[i].dstAccessMask,
201          .dependencyFlags = pCreateInfo->pDependencies[i].dependencyFlags,
202          .viewOffset = 0,
203       };
204 
205       if (multiview_info && multiview_info->dependencyCount) {
206          assert(multiview_info->dependencyCount == pCreateInfo->dependencyCount);
207          dependencies[i].viewOffset = multiview_info->pViewOffsets[i];
208       }
209    }
210 
211    *create_info = (VkRenderPassCreateInfo2) {
212       .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
213       .pNext = pCreateInfo->pNext,
214       .flags = pCreateInfo->flags,
215       .attachmentCount = pCreateInfo->attachmentCount,
216       .pAttachments = attachments,
217       .subpassCount = pCreateInfo->subpassCount,
218       .pSubpasses = subpasses,
219       .dependencyCount = pCreateInfo->dependencyCount,
220       .pDependencies = dependencies,
221    };
222 
223    if (multiview_info && multiview_info->correlationMaskCount > 0) {
224       create_info->correlatedViewMaskCount = multiview_info->correlationMaskCount;
225       create_info->pCorrelatedViewMasks = multiview_info->pCorrelationMasks;
226    }
227 
228    VkResult result =
229       device->dispatch_table.CreateRenderPass2(_device, create_info,
230                                                pAllocator, pRenderPass);
231 
232    vk_free2(&device->alloc, pAllocator, create_info);
233 
234    return result;
235 }
236 
237 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBeginRenderPass(VkCommandBuffer commandBuffer,const VkRenderPassBeginInfo * pRenderPassBegin,VkSubpassContents contents)238 vk_common_CmdBeginRenderPass(VkCommandBuffer commandBuffer,
239                              const VkRenderPassBeginInfo* pRenderPassBegin,
240                              VkSubpassContents contents)
241 {
242    /* We don't have a vk_command_buffer object but we can assume, since we're
243     * using common dispatch, that it's a vk_object of some sort.
244     */
245    struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
246 
247    VkSubpassBeginInfo info = {
248       .sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
249       .contents = contents,
250    };
251 
252    disp->device->dispatch_table.CmdBeginRenderPass2(commandBuffer,
253                                                     pRenderPassBegin, &info);
254 }
255 
256 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdEndRenderPass(VkCommandBuffer commandBuffer)257 vk_common_CmdEndRenderPass(VkCommandBuffer commandBuffer)
258 {
259    /* We don't have a vk_command_buffer object but we can assume, since we're
260     * using common dispatch, that it's a vk_object of some sort.
261     */
262    struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
263 
264    VkSubpassEndInfo info = {
265       .sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
266    };
267 
268    disp->device->dispatch_table.CmdEndRenderPass2(commandBuffer, &info);
269 }
270 
271 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdNextSubpass(VkCommandBuffer commandBuffer,VkSubpassContents contents)272 vk_common_CmdNextSubpass(VkCommandBuffer commandBuffer,
273                          VkSubpassContents contents)
274 {
275    /* We don't have a vk_command_buffer object but we can assume, since we're
276     * using common dispatch, that it's a vk_object of some sort.
277     */
278    struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
279 
280    VkSubpassBeginInfo begin_info = {
281       .sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
282       .contents = contents,
283    };
284 
285    VkSubpassEndInfo end_info = {
286       .sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
287    };
288 
289    disp->device->dispatch_table.CmdNextSubpass2(commandBuffer, &begin_info,
290                                                 &end_info);
291 }
292