|  | // Copyright 2018 The SwiftShader Authors. All Rights Reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | #include "VkRenderPass.hpp" | 
|  | #include <cstring> | 
|  |  | 
|  | namespace | 
|  | { | 
|  | void MarkFirstUse(int& attachment, int subpass) | 
|  | { | 
|  | if (attachment == -1) | 
|  | attachment = subpass; | 
|  | } | 
|  | } | 
|  |  | 
|  | namespace vk | 
|  | { | 
|  |  | 
|  | RenderPass::RenderPass(const VkRenderPassCreateInfo* pCreateInfo, void* mem) : | 
|  | attachmentCount(pCreateInfo->attachmentCount), | 
|  | subpassCount(pCreateInfo->subpassCount), | 
|  | dependencyCount(pCreateInfo->dependencyCount) | 
|  | { | 
|  | char* hostMemory = reinterpret_cast<char*>(mem); | 
|  |  | 
|  | // subpassCount must be greater than 0 | 
|  | ASSERT(pCreateInfo->subpassCount > 0); | 
|  |  | 
|  | size_t subpassesSize = pCreateInfo->subpassCount * sizeof(VkSubpassDescription); | 
|  | subpasses = reinterpret_cast<VkSubpassDescription*>(hostMemory); | 
|  | memcpy(subpasses, pCreateInfo->pSubpasses, subpassesSize); | 
|  | hostMemory += subpassesSize; | 
|  |  | 
|  | if(pCreateInfo->attachmentCount > 0) | 
|  | { | 
|  | size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription); | 
|  | attachments = reinterpret_cast<VkAttachmentDescription*>(hostMemory); | 
|  | memcpy(attachments, pCreateInfo->pAttachments, attachmentSize); | 
|  | hostMemory += attachmentSize; | 
|  |  | 
|  | size_t firstUseSize = pCreateInfo->attachmentCount * sizeof(int); | 
|  | attachmentFirstUse = reinterpret_cast<int*>(hostMemory); | 
|  | for (auto i = 0u; i < pCreateInfo->attachmentCount; i++) | 
|  | attachmentFirstUse[i] = -1; | 
|  | hostMemory += firstUseSize; | 
|  | } | 
|  |  | 
|  | // Deep copy subpasses | 
|  | for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) | 
|  | { | 
|  | const auto& subpass = pCreateInfo->pSubpasses[i]; | 
|  | subpasses[i].pInputAttachments = nullptr; | 
|  | subpasses[i].pColorAttachments = nullptr; | 
|  | subpasses[i].pResolveAttachments = nullptr; | 
|  | subpasses[i].pDepthStencilAttachment = nullptr; | 
|  | subpasses[i].pPreserveAttachments = nullptr; | 
|  |  | 
|  | if(subpass.inputAttachmentCount > 0) | 
|  | { | 
|  | size_t inputAttachmentsSize = subpass.inputAttachmentCount * sizeof(VkAttachmentReference); | 
|  | subpasses[i].pInputAttachments = reinterpret_cast<VkAttachmentReference*>(hostMemory); | 
|  | memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pInputAttachments), | 
|  | pCreateInfo->pSubpasses[i].pInputAttachments, inputAttachmentsSize); | 
|  | hostMemory += inputAttachmentsSize; | 
|  |  | 
|  | for (auto j = 0u; j < subpasses[i].inputAttachmentCount; j++) | 
|  | { | 
|  | if (subpass.pInputAttachments[j].attachment != VK_ATTACHMENT_UNUSED) | 
|  | MarkFirstUse(attachmentFirstUse[subpass.pInputAttachments[j].attachment], i); | 
|  | } | 
|  | } | 
|  |  | 
|  | if(subpass.colorAttachmentCount > 0) | 
|  | { | 
|  | size_t colorAttachmentsSize = subpass.colorAttachmentCount * sizeof(VkAttachmentReference); | 
|  | subpasses[i].pColorAttachments = reinterpret_cast<VkAttachmentReference*>(hostMemory); | 
|  | memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pColorAttachments), | 
|  | subpass.pColorAttachments, colorAttachmentsSize); | 
|  | hostMemory += colorAttachmentsSize; | 
|  |  | 
|  | if(subpass.pResolveAttachments) | 
|  | { | 
|  | subpasses[i].pResolveAttachments = reinterpret_cast<VkAttachmentReference*>(hostMemory); | 
|  | memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pResolveAttachments), | 
|  | subpass.pResolveAttachments, colorAttachmentsSize); | 
|  | hostMemory += colorAttachmentsSize; | 
|  | } | 
|  |  | 
|  | for (auto j = 0u; j < subpasses[i].colorAttachmentCount; j++) | 
|  | { | 
|  | if (subpass.pColorAttachments[j].attachment != VK_ATTACHMENT_UNUSED) | 
|  | MarkFirstUse(attachmentFirstUse[subpass.pColorAttachments[j].attachment], i); | 
|  | if (subpass.pResolveAttachments && | 
|  | subpass.pResolveAttachments[j].attachment != VK_ATTACHMENT_UNUSED) | 
|  | MarkFirstUse(attachmentFirstUse[subpass.pResolveAttachments[j].attachment], i); | 
|  | } | 
|  | } | 
|  |  | 
|  | if(subpass.pDepthStencilAttachment) | 
|  | { | 
|  | subpasses[i].pDepthStencilAttachment = reinterpret_cast<VkAttachmentReference*>(hostMemory); | 
|  | memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pDepthStencilAttachment), | 
|  | subpass.pDepthStencilAttachment, sizeof(VkAttachmentReference)); | 
|  | hostMemory += sizeof(VkAttachmentReference); | 
|  |  | 
|  | if (subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) | 
|  | MarkFirstUse(attachmentFirstUse[subpass.pDepthStencilAttachment->attachment], i); | 
|  | } | 
|  |  | 
|  | if(subpass.preserveAttachmentCount > 0) | 
|  | { | 
|  | size_t preserveAttachmentSize = subpass.preserveAttachmentCount * sizeof(uint32_t); | 
|  | subpasses[i].pPreserveAttachments = reinterpret_cast<uint32_t*>(hostMemory); | 
|  | memcpy(const_cast<uint32_t*>(subpasses[i].pPreserveAttachments), | 
|  | pCreateInfo->pSubpasses[i].pPreserveAttachments, preserveAttachmentSize); | 
|  | hostMemory += preserveAttachmentSize; | 
|  |  | 
|  | for (auto j = 0u; j < subpasses[i].preserveAttachmentCount; j++) | 
|  | { | 
|  | if (subpass.pPreserveAttachments[j] != VK_ATTACHMENT_UNUSED) | 
|  | MarkFirstUse(attachmentFirstUse[subpass.pPreserveAttachments[j]], i); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if(pCreateInfo->dependencyCount > 0) | 
|  | { | 
|  | size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency); | 
|  | dependencies = reinterpret_cast<VkSubpassDependency*>(hostMemory); | 
|  | memcpy(dependencies, pCreateInfo->pDependencies, dependenciesSize); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderPass::destroy(const VkAllocationCallbacks* pAllocator) | 
|  | { | 
|  | vk::deallocate(subpasses, pAllocator); // attachments and dependencies are in the same allocation | 
|  | } | 
|  |  | 
|  | size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo* pCreateInfo) | 
|  | { | 
|  | size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription) | 
|  | + pCreateInfo->attachmentCount * sizeof(int); | 
|  | size_t subpassesSize = 0; | 
|  | for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) | 
|  | { | 
|  | const auto& subpass = pCreateInfo->pSubpasses[i]; | 
|  | uint32_t nbAttachments = subpass.inputAttachmentCount + subpass.colorAttachmentCount; | 
|  | if(subpass.pResolveAttachments) | 
|  | { | 
|  | nbAttachments += subpass.colorAttachmentCount; | 
|  | } | 
|  | if(subpass.pDepthStencilAttachment) | 
|  | { | 
|  | nbAttachments += 1; | 
|  | } | 
|  | subpassesSize += sizeof(VkSubpassDescription) + | 
|  | sizeof(VkAttachmentReference) * nbAttachments + | 
|  | sizeof(uint32_t) * subpass.preserveAttachmentCount; | 
|  | } | 
|  | size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency); | 
|  |  | 
|  | return attachmentSize + subpassesSize + dependenciesSize; | 
|  | } | 
|  |  | 
|  | void RenderPass::getRenderAreaGranularity(VkExtent2D* pGranularity) const | 
|  | { | 
|  | pGranularity->width = 1; | 
|  | pGranularity->height = 1; | 
|  | } | 
|  |  | 
|  | void RenderPass::begin() | 
|  | { | 
|  | currentSubpass = 0; | 
|  | } | 
|  |  | 
|  | void RenderPass::nextSubpass() | 
|  | { | 
|  | ++currentSubpass; | 
|  | ASSERT(currentSubpass < subpassCount); | 
|  | } | 
|  |  | 
|  | void RenderPass::end() | 
|  | { | 
|  | currentSubpass = 0; | 
|  | } | 
|  |  | 
|  | } // namespace vk |