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