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
32static void
33translate_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
59VKAPI_ATTR VkResult VKAPI_CALL
60vk_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
237VKAPI_ATTR void VKAPI_CALL
238vk_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
256VKAPI_ATTR void VKAPI_CALL
257vk_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
271VKAPI_ATTR void VKAPI_CALL
272vk_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