diff --git a/src/broadcom/vulkan/v3dv_pass.c b/src/broadcom/vulkan/v3dv_pass.c index 7c8184b603b..7ec389e1f70 100644 --- a/src/broadcom/vulkan/v3dv_pass.c +++ b/src/broadcom/vulkan/v3dv_pass.c @@ -23,11 +23,138 @@ #include "v3dv_private.h" +static uint32_t +num_subpass_attachments(const VkSubpassDescription *desc) +{ + return desc->inputAttachmentCount + + desc->colorAttachmentCount + + (desc->pResolveAttachments ? desc->colorAttachmentCount : 0) + + (desc->pDepthStencilAttachment != NULL); +} + VkResult -v3dv_CreateRenderPass(VkDevice device, +v3dv_CreateRenderPass(VkDevice _device, const VkRenderPassCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) { + V3DV_FROM_HANDLE(v3dv_device, device, _device); + struct v3dv_render_pass *pass; + + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO); + + size_t size = sizeof(*pass); + size_t subpasses_offset = size; + size += pCreateInfo->subpassCount * sizeof(pass->subpasses[0]); + size_t attachments_offset = size; + size += pCreateInfo->attachmentCount * sizeof(pass->attachments[0]); + + pass = vk_alloc2(&device->alloc, pAllocator, size, 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (pass == NULL) + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); + + memset(pass, 0, size); + pass->attachment_count = pCreateInfo->attachmentCount; + pass->attachments = (void *) pass + attachments_offset; + pass->subpass_count = pCreateInfo->subpassCount; + pass->subpasses = (void *) pass + subpasses_offset; + + for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) + pass->attachments[i].desc = pCreateInfo->pAttachments[i]; + + uint32_t subpass_attachment_count = 0; + for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) { + const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i]; + subpass_attachment_count += num_subpass_attachments(desc); + } + + if (subpass_attachment_count) { + const size_t subpass_attachment_bytes = + subpass_attachment_count * sizeof(struct v3dv_subpass_attachment); + pass->subpass_attachments = + vk_alloc2(&device->alloc, pAllocator, subpass_attachment_bytes, 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (pass->subpass_attachments == NULL) { + vk_free2(&device->alloc, pAllocator, pass); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); + } + } else { + pass->subpass_attachments = NULL; + } + + struct v3dv_subpass_attachment *p = pass->subpass_attachments; + for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) { + const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i]; + struct v3dv_subpass *subpass = &pass->subpasses[i]; + + subpass->input_count = desc->inputAttachmentCount; + subpass->color_count = desc->colorAttachmentCount; + + if (desc->inputAttachmentCount > 0) { + subpass->input_attachments = p; + p += desc->inputAttachmentCount; + + for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) { + subpass->input_attachments[j] = (struct v3dv_subpass_attachment) { + .attachment = desc->pInputAttachments[j].attachment, + .layout = desc->pInputAttachments[j].layout, + }; + } + } + + if (desc->colorAttachmentCount > 0) { + subpass->color_attachments = p; + p += desc->colorAttachmentCount; + + for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) { + subpass->color_attachments[j] = (struct v3dv_subpass_attachment) { + .attachment = desc->pColorAttachments[j].attachment, + .layout = desc->pColorAttachments[j].layout, + }; + } + } + + if (desc->pResolveAttachments) { + subpass->resolve_attachments = p; + p += desc->colorAttachmentCount; + + for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) { + subpass->resolve_attachments[j] = (struct v3dv_subpass_attachment) { + .attachment = desc->pResolveAttachments[j].attachment, + .layout = desc->pResolveAttachments[j].layout, + }; + } + } + + if (desc->pDepthStencilAttachment) { + subpass->ds_attachment = (struct v3dv_subpass_attachment) { + .attachment = desc->pDepthStencilAttachment->attachment, + .layout = desc->pDepthStencilAttachment->layout, + }; + } else { + subpass->ds_attachment.attachment = VK_ATTACHMENT_UNUSED; + } + } + + /* FIXME: handle subpass dependencies */ + + *pRenderPass = v3dv_render_pass_to_handle(pass); + return VK_SUCCESS; } + +void +v3dv_DestroyRenderPass(VkDevice _device, + VkRenderPass _pass, + const VkAllocationCallbacks *pAllocator) +{ + V3DV_FROM_HANDLE(v3dv_device, device, _device); + V3DV_FROM_HANDLE(v3dv_render_pass, pass, _pass); + + if (!_pass) + return; + + vk_free2(&device->alloc, pAllocator, pass->subpass_attachments); + vk_free2(&device->alloc, pAllocator, pass); +} diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index 991561f59af..7abc25284e5 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -304,6 +304,36 @@ struct v3dv_buffer { VkDeviceSize mem_offset; }; +struct v3dv_subpass_attachment { + uint32_t attachment; + VkImageLayout layout; +}; + +struct v3dv_subpass { + uint32_t input_count; + struct v3dv_subpass_attachment *input_attachments; + + uint32_t color_count; + struct v3dv_subpass_attachment *color_attachments; + struct v3dv_subpass_attachment *resolve_attachments; + + struct v3dv_subpass_attachment ds_attachment; +}; + +struct v3dv_render_pass_attachment { + VkAttachmentDescription desc; +}; + +struct v3dv_render_pass { + uint32_t attachment_count; + struct v3dv_render_pass_attachment *attachments; + + uint32_t subpass_count; + struct v3dv_subpass *subpasses; + + struct v3dv_subpass_attachment *subpass_attachments; +}; + struct v3dv_shader_module { unsigned char sha1[20]; uint32_t size;