1// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "VkRenderPass.hpp"
16#include <cstring>
17
18namespace vk
19{
20
21RenderPass::RenderPass(const VkRenderPassCreateInfo* pCreateInfo, void* mem) :
22 attachmentCount(pCreateInfo->attachmentCount),
23 subpassCount(pCreateInfo->subpassCount),
24 dependencyCount(pCreateInfo->dependencyCount)
25{
26 char* hostMemory = reinterpret_cast<char*>(mem);
27
28 // subpassCount must be greater than 0
29 ASSERT(pCreateInfo->subpassCount > 0);
30
31 size_t subpassesSize = pCreateInfo->subpassCount * sizeof(VkSubpassDescription);
32 subpasses = reinterpret_cast<VkSubpassDescription*>(hostMemory);
33 memcpy(subpasses, pCreateInfo->pSubpasses, subpassesSize);
34 hostMemory += subpassesSize;
35 uint32_t *masks = reinterpret_cast<uint32_t *>(hostMemory);
36 hostMemory += pCreateInfo->subpassCount * sizeof(uint32_t);
37
38 if(pCreateInfo->attachmentCount > 0)
39 {
40 size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription);
41 attachments = reinterpret_cast<VkAttachmentDescription*>(hostMemory);
42 memcpy(attachments, pCreateInfo->pAttachments, attachmentSize);
43 hostMemory += attachmentSize;
44
45 size_t firstUseSize = pCreateInfo->attachmentCount * sizeof(int);
46 attachmentFirstUse = reinterpret_cast<int*>(hostMemory);
47 hostMemory += firstUseSize;
48
49 attachmentViewMasks = reinterpret_cast<uint32_t *>(hostMemory);
50 hostMemory += pCreateInfo->attachmentCount * sizeof(uint32_t);
51 for (auto i = 0u; i < pCreateInfo->attachmentCount; i++)
52 {
53 attachmentFirstUse[i] = -1;
54 attachmentViewMasks[i] = 0;
55 }
56 }
57
58 const VkBaseInStructure* extensionCreateInfo = reinterpret_cast<const VkBaseInStructure*>(pCreateInfo->pNext);
59 while (extensionCreateInfo)
60 {
61 switch (extensionCreateInfo->sType)
62 {
63 case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
64 {
65 // Renderpass uses multiview if this structure is present AND some subpass specifies
66 // a nonzero view mask
67 auto const *multiviewCreateInfo = reinterpret_cast<VkRenderPassMultiviewCreateInfo const *>(extensionCreateInfo);
68 for (auto i = 0u; i < pCreateInfo->subpassCount; i++)
69 {
70 masks[i] = multiviewCreateInfo->pViewMasks[i];
71 // This is now a multiview renderpass, so make the masks available
72 if (masks[i])
73 viewMasks = masks;
74 }
75
76 break;
77 }
78 default:
79 /* Unknown structure in pNext chain must be ignored */
80 break;
81 }
82
83 extensionCreateInfo = extensionCreateInfo->pNext;
84 }
85
86 // Deep copy subpasses
87 for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
88 {
89 const auto& subpass = pCreateInfo->pSubpasses[i];
90 subpasses[i].pInputAttachments = nullptr;
91 subpasses[i].pColorAttachments = nullptr;
92 subpasses[i].pResolveAttachments = nullptr;
93 subpasses[i].pDepthStencilAttachment = nullptr;
94 subpasses[i].pPreserveAttachments = nullptr;
95
96 if(subpass.inputAttachmentCount > 0)
97 {
98 size_t inputAttachmentsSize = subpass.inputAttachmentCount * sizeof(VkAttachmentReference);
99 subpasses[i].pInputAttachments = reinterpret_cast<VkAttachmentReference*>(hostMemory);
100 memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pInputAttachments),
101 pCreateInfo->pSubpasses[i].pInputAttachments, inputAttachmentsSize);
102 hostMemory += inputAttachmentsSize;
103
104 for (auto j = 0u; j < subpasses[i].inputAttachmentCount; j++)
105 {
106 if (subpass.pInputAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
107 MarkFirstUse(subpass.pInputAttachments[j].attachment, i);
108 }
109 }
110
111 if(subpass.colorAttachmentCount > 0)
112 {
113 size_t colorAttachmentsSize = subpass.colorAttachmentCount * sizeof(VkAttachmentReference);
114 subpasses[i].pColorAttachments = reinterpret_cast<VkAttachmentReference*>(hostMemory);
115 memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pColorAttachments),
116 subpass.pColorAttachments, colorAttachmentsSize);
117 hostMemory += colorAttachmentsSize;
118
119 if(subpass.pResolveAttachments)
120 {
121 subpasses[i].pResolveAttachments = reinterpret_cast<VkAttachmentReference*>(hostMemory);
122 memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pResolveAttachments),
123 subpass.pResolveAttachments, colorAttachmentsSize);
124 hostMemory += colorAttachmentsSize;
125 }
126
127 for (auto j = 0u; j < subpasses[i].colorAttachmentCount; j++)
128 {
129 if (subpass.pColorAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
130 MarkFirstUse(subpass.pColorAttachments[j].attachment, i);
131 if (subpass.pResolveAttachments &&
132 subpass.pResolveAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
133 MarkFirstUse(subpass.pResolveAttachments[j].attachment, i);
134 }
135 }
136
137 if(subpass.pDepthStencilAttachment)
138 {
139 subpasses[i].pDepthStencilAttachment = reinterpret_cast<VkAttachmentReference*>(hostMemory);
140 memcpy(const_cast<VkAttachmentReference*>(subpasses[i].pDepthStencilAttachment),
141 subpass.pDepthStencilAttachment, sizeof(VkAttachmentReference));
142 hostMemory += sizeof(VkAttachmentReference);
143
144 if (subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
145 MarkFirstUse(subpass.pDepthStencilAttachment->attachment, i);
146 }
147
148 if(subpass.preserveAttachmentCount > 0)
149 {
150 size_t preserveAttachmentSize = subpass.preserveAttachmentCount * sizeof(uint32_t);
151 subpasses[i].pPreserveAttachments = reinterpret_cast<uint32_t*>(hostMemory);
152 memcpy(const_cast<uint32_t*>(subpasses[i].pPreserveAttachments),
153 pCreateInfo->pSubpasses[i].pPreserveAttachments, preserveAttachmentSize);
154 hostMemory += preserveAttachmentSize;
155
156 for (auto j = 0u; j < subpasses[i].preserveAttachmentCount; j++)
157 {
158 if (subpass.pPreserveAttachments[j] != VK_ATTACHMENT_UNUSED)
159 MarkFirstUse(subpass.pPreserveAttachments[j], i);
160 }
161 }
162 }
163
164 if(pCreateInfo->dependencyCount > 0)
165 {
166 size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency);
167 dependencies = reinterpret_cast<VkSubpassDependency*>(hostMemory);
168 memcpy(dependencies, pCreateInfo->pDependencies, dependenciesSize);
169 }
170}
171
172void RenderPass::destroy(const VkAllocationCallbacks* pAllocator)
173{
174 vk::deallocate(subpasses, pAllocator); // attachments and dependencies are in the same allocation
175}
176
177size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo* pCreateInfo)
178{
179 size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription)
180 + pCreateInfo->attachmentCount * sizeof(int) // first use
181 + pCreateInfo->attachmentCount * sizeof(uint32_t); // union of subpass view masks, per attachment
182 size_t subpassesSize = 0;
183 for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
184 {
185 const auto& subpass = pCreateInfo->pSubpasses[i];
186 uint32_t nbAttachments = subpass.inputAttachmentCount + subpass.colorAttachmentCount;
187 if(subpass.pResolveAttachments)
188 {
189 nbAttachments += subpass.colorAttachmentCount;
190 }
191 if(subpass.pDepthStencilAttachment)
192 {
193 nbAttachments += 1;
194 }
195 subpassesSize += sizeof(VkSubpassDescription) +
196 sizeof(VkAttachmentReference) * nbAttachments +
197 sizeof(uint32_t) * subpass.preserveAttachmentCount +
198 sizeof(uint32_t); // view mask
199 }
200 size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency);
201
202 return attachmentSize + subpassesSize + dependenciesSize;
203}
204
205void RenderPass::getRenderAreaGranularity(VkExtent2D* pGranularity) const
206{
207 pGranularity->width = 1;
208 pGranularity->height = 1;
209}
210
211void RenderPass::MarkFirstUse(int attachment, int subpass)
212{
213 // FIXME: we may not actually need to track attachmentFirstUse if we're going to eagerly
214 // clear attachments at the start of the renderpass; can use attachmentViewMasks always instead.
215
216 if (attachmentFirstUse[attachment] == -1)
217 attachmentFirstUse[attachment] = subpass;
218
219 if (isMultiView())
220 attachmentViewMasks[attachment] |= viewMasks[subpass];
221}
222
223} // namespace vk