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