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 "VkStringify.hpp"
17 #include <cstring>
18
19 namespace {
20
21 template<class T>
ComputeRequiredAllocationSizeT(const T * pCreateInfo)22 size_t ComputeRequiredAllocationSizeT(const T *pCreateInfo)
23 {
24 size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription) + pCreateInfo->attachmentCount * sizeof(int) // first use
25 + pCreateInfo->attachmentCount * sizeof(uint32_t); // union of subpass view masks, per attachment
26 size_t subpassesSize = 0;
27 for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
28 {
29 const auto &subpass = pCreateInfo->pSubpasses[i];
30 uint32_t nbAttachments = subpass.inputAttachmentCount + subpass.colorAttachmentCount;
31 if(subpass.pResolveAttachments)
32 {
33 nbAttachments += subpass.colorAttachmentCount;
34 }
35 if(subpass.pDepthStencilAttachment)
36 {
37 nbAttachments += 1;
38 }
39 subpassesSize += sizeof(VkSubpassDescription) +
40 sizeof(VkAttachmentReference) * nbAttachments +
41 sizeof(uint32_t) * subpass.preserveAttachmentCount +
42 sizeof(uint32_t); // view mask
43 }
44 size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency);
45
46 return attachmentSize + subpassesSize + dependenciesSize;
47 }
48
49 template<class T>
CopySubpasses(VkSubpassDescription * dst,const T * src,uint32_t count)50 void CopySubpasses(VkSubpassDescription *dst, const T *src, uint32_t count)
51 {
52 for(uint32_t i = 0; i < count; ++i)
53 {
54 dst[i].flags = src[i].flags;
55 dst[i].pipelineBindPoint = src[i].pipelineBindPoint;
56 dst[i].inputAttachmentCount = src[i].inputAttachmentCount;
57 dst[i].pInputAttachments = nullptr;
58 dst[i].colorAttachmentCount = src[i].colorAttachmentCount;
59 dst[i].pColorAttachments = nullptr;
60 dst[i].pResolveAttachments = nullptr;
61 dst[i].pDepthStencilAttachment = nullptr;
62 dst[i].preserveAttachmentCount = src[i].preserveAttachmentCount;
63 dst[i].pPreserveAttachments = nullptr;
64 }
65 }
66
67 template<class T>
CopyAttachmentDescriptions(VkAttachmentDescription * dst,const T * src,uint32_t count)68 void CopyAttachmentDescriptions(VkAttachmentDescription *dst, const T *src, uint32_t count)
69 {
70 for(uint32_t i = 0; i < count; ++i)
71 {
72 dst[i].flags = src[i].flags;
73 dst[i].format = src[i].format;
74 dst[i].samples = src[i].samples;
75 dst[i].loadOp = src[i].loadOp;
76 dst[i].storeOp = src[i].storeOp;
77 dst[i].stencilLoadOp = src[i].stencilLoadOp;
78 dst[i].stencilStoreOp = src[i].stencilStoreOp;
79 dst[i].initialLayout = src[i].initialLayout;
80 dst[i].finalLayout = src[i].finalLayout;
81 }
82 }
83
84 template<class T>
CopyAttachmentReferences(VkAttachmentReference * dst,const T * src,uint32_t count)85 void CopyAttachmentReferences(VkAttachmentReference *dst, const T *src, uint32_t count)
86 {
87 for(uint32_t i = 0; i < count; ++i)
88 {
89 dst[i].attachment = src[i].attachment;
90 dst[i].layout = src[i].layout;
91 }
92 }
93
94 template<class T>
CopySubpassDependencies(VkSubpassDependency * dst,const T * src,uint32_t count)95 void CopySubpassDependencies(VkSubpassDependency *dst, const T *src, uint32_t count)
96 {
97 for(uint32_t i = 0; i < count; ++i)
98 {
99 dst[i].srcSubpass = src[i].srcSubpass;
100 dst[i].dstSubpass = src[i].dstSubpass;
101 dst[i].srcStageMask = src[i].srcStageMask;
102 dst[i].dstStageMask = src[i].dstStageMask;
103 dst[i].srcAccessMask = src[i].srcAccessMask;
104 dst[i].dstAccessMask = src[i].dstAccessMask;
105 dst[i].dependencyFlags = src[i].dependencyFlags;
106 }
107 }
108
GetViewMasks(const VkRenderPassCreateInfo * pCreateInfo,uint32_t * masks)109 bool GetViewMasks(const VkRenderPassCreateInfo *pCreateInfo, uint32_t *masks)
110 {
111 return false;
112 }
113
GetViewMasks(const VkRenderPassCreateInfo2KHR * pCreateInfo,uint32_t * masks)114 bool GetViewMasks(const VkRenderPassCreateInfo2KHR *pCreateInfo, uint32_t *masks)
115 {
116 for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
117 {
118 masks[i] = pCreateInfo->pSubpasses[i].viewMask;
119 }
120 return true;
121 }
122
123 } // namespace
124
125 namespace vk {
126
RenderPass(const VkRenderPassCreateInfo * pCreateInfo,void * mem)127 RenderPass::RenderPass(const VkRenderPassCreateInfo *pCreateInfo, void *mem)
128 : attachmentCount(pCreateInfo->attachmentCount)
129 , subpassCount(pCreateInfo->subpassCount)
130 , dependencyCount(pCreateInfo->dependencyCount)
131 {
132 init(pCreateInfo, mem);
133 }
134
RenderPass(const VkRenderPassCreateInfo2KHR * pCreateInfo,void * mem)135 RenderPass::RenderPass(const VkRenderPassCreateInfo2KHR *pCreateInfo, void *mem)
136 : attachmentCount(pCreateInfo->attachmentCount)
137 , subpassCount(pCreateInfo->subpassCount)
138 , dependencyCount(pCreateInfo->dependencyCount)
139 {
140 init(pCreateInfo, mem);
141 // Note: the init function above ignores:
142 // - pCorrelatedViewMasks: This provides a potential performance optimization
143 // - VkAttachmentReference2::aspectMask : This specifies which aspects may be used
144 // - VkSubpassDependency2::viewOffset : This is the same as VkRenderPassMultiviewCreateInfo::pViewOffsets, which is currently ignored
145 // - Any pNext pointer in VkRenderPassCreateInfo2KHR's internal structures
146 }
147
148 template<class T>
init(const T * pCreateInfo,void * mem)149 void RenderPass::init(const T *pCreateInfo, void *mem)
150 {
151 char *hostMemory = reinterpret_cast<char *>(mem);
152
153 // subpassCount must be greater than 0
154 ASSERT(pCreateInfo->subpassCount > 0);
155
156 size_t subpassesSize = pCreateInfo->subpassCount * sizeof(VkSubpassDescription);
157 subpasses = reinterpret_cast<VkSubpassDescription *>(hostMemory);
158 CopySubpasses(subpasses, pCreateInfo->pSubpasses, pCreateInfo->subpassCount);
159 hostMemory += subpassesSize;
160 uint32_t *masks = reinterpret_cast<uint32_t *>(hostMemory);
161 hostMemory += subpassCount * sizeof(uint32_t);
162
163 if(attachmentCount > 0)
164 {
165 size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription);
166 attachments = reinterpret_cast<VkAttachmentDescription *>(hostMemory);
167 CopyAttachmentDescriptions(attachments, pCreateInfo->pAttachments, pCreateInfo->attachmentCount);
168 hostMemory += attachmentSize;
169
170 size_t firstUseSize = pCreateInfo->attachmentCount * sizeof(int);
171 attachmentFirstUse = reinterpret_cast<int *>(hostMemory);
172 hostMemory += firstUseSize;
173
174 attachmentViewMasks = reinterpret_cast<uint32_t *>(hostMemory);
175 hostMemory += pCreateInfo->attachmentCount * sizeof(uint32_t);
176 for(auto i = 0u; i < pCreateInfo->attachmentCount; i++)
177 {
178 attachmentFirstUse[i] = -1;
179 attachmentViewMasks[i] = 0;
180 }
181 }
182
183 const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
184 while(extensionCreateInfo)
185 {
186 switch(extensionCreateInfo->sType)
187 {
188 case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
189 {
190 // Renderpass uses multiview if this structure is present AND some subpass specifies
191 // a nonzero view mask
192 auto const *multiviewCreateInfo = reinterpret_cast<VkRenderPassMultiviewCreateInfo const *>(extensionCreateInfo);
193 for(auto i = 0u; i < pCreateInfo->subpassCount; i++)
194 {
195 masks[i] = multiviewCreateInfo->pViewMasks[i];
196 // This is now a multiview renderpass, so make the masks available
197 if(masks[i])
198 {
199 viewMasks = masks;
200 }
201 }
202
203 break;
204 }
205 default:
206 WARN("pCreateInfo->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
207 break;
208 }
209
210 extensionCreateInfo = extensionCreateInfo->pNext;
211 }
212
213 if(!viewMasks && (GetViewMasks(pCreateInfo, masks)))
214 {
215 for(auto i = 0u; i < pCreateInfo->subpassCount; i++)
216 {
217 if(masks[i])
218 {
219 viewMasks = masks;
220 }
221 }
222 }
223
224 // Deep copy subpasses
225 for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
226 {
227 const auto &subpass = pCreateInfo->pSubpasses[i];
228
229 if(subpass.inputAttachmentCount > 0)
230 {
231 size_t inputAttachmentsSize = subpass.inputAttachmentCount * sizeof(VkAttachmentReference);
232 subpasses[i].pInputAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
233 CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pInputAttachments),
234 pCreateInfo->pSubpasses[i].pInputAttachments, subpass.inputAttachmentCount);
235 hostMemory += inputAttachmentsSize;
236
237 for(auto j = 0u; j < subpasses[i].inputAttachmentCount; j++)
238 {
239 if(subpass.pInputAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
240 MarkFirstUse(subpass.pInputAttachments[j].attachment, i);
241 }
242 }
243
244 if(subpass.colorAttachmentCount > 0)
245 {
246 size_t colorAttachmentsSize = subpass.colorAttachmentCount * sizeof(VkAttachmentReference);
247 subpasses[i].pColorAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
248 CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pColorAttachments),
249 subpass.pColorAttachments, subpass.colorAttachmentCount);
250 hostMemory += colorAttachmentsSize;
251
252 if(subpass.pResolveAttachments)
253 {
254 subpasses[i].pResolveAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
255 CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pResolveAttachments),
256 subpass.pResolveAttachments, subpass.colorAttachmentCount);
257 hostMemory += colorAttachmentsSize;
258 }
259
260 for(auto j = 0u; j < subpasses[i].colorAttachmentCount; j++)
261 {
262 if(subpass.pColorAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
263 MarkFirstUse(subpass.pColorAttachments[j].attachment, i);
264 if(subpass.pResolveAttachments &&
265 subpass.pResolveAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
266 MarkFirstUse(subpass.pResolveAttachments[j].attachment, i);
267 }
268 }
269
270 if(subpass.pDepthStencilAttachment)
271 {
272 subpasses[i].pDepthStencilAttachment = reinterpret_cast<VkAttachmentReference *>(hostMemory);
273 CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pDepthStencilAttachment),
274 subpass.pDepthStencilAttachment, 1);
275 hostMemory += sizeof(VkAttachmentReference);
276
277 if(subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
278 MarkFirstUse(subpass.pDepthStencilAttachment->attachment, i);
279 }
280
281 if(subpass.preserveAttachmentCount > 0)
282 {
283 size_t preserveAttachmentSize = subpass.preserveAttachmentCount * sizeof(uint32_t);
284 subpasses[i].pPreserveAttachments = reinterpret_cast<uint32_t *>(hostMemory);
285 for(uint32_t j = 0u; j < subpass.preserveAttachmentCount; j++)
286 {
287 const_cast<uint32_t *>(subpasses[i].pPreserveAttachments)[j] = pCreateInfo->pSubpasses[i].pPreserveAttachments[j];
288 }
289 hostMemory += preserveAttachmentSize;
290
291 for(auto j = 0u; j < subpasses[i].preserveAttachmentCount; j++)
292 {
293 if(subpass.pPreserveAttachments[j] != VK_ATTACHMENT_UNUSED)
294 MarkFirstUse(subpass.pPreserveAttachments[j], i);
295 }
296 }
297 }
298
299 if(pCreateInfo->dependencyCount > 0)
300 {
301 dependencies = reinterpret_cast<VkSubpassDependency *>(hostMemory);
302 CopySubpassDependencies(dependencies, pCreateInfo->pDependencies, pCreateInfo->dependencyCount);
303 }
304 }
305
destroy(const VkAllocationCallbacks * pAllocator)306 void RenderPass::destroy(const VkAllocationCallbacks *pAllocator)
307 {
308 vk::deallocate(subpasses, pAllocator); // attachments and dependencies are in the same allocation
309 }
310
ComputeRequiredAllocationSize(const VkRenderPassCreateInfo * pCreateInfo)311 size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo *pCreateInfo)
312 {
313 return ComputeRequiredAllocationSizeT(pCreateInfo);
314 }
315
ComputeRequiredAllocationSize(const VkRenderPassCreateInfo2KHR * pCreateInfo)316 size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo2KHR *pCreateInfo)
317 {
318 return ComputeRequiredAllocationSizeT(pCreateInfo);
319 }
320
getRenderAreaGranularity(VkExtent2D * pGranularity) const321 void RenderPass::getRenderAreaGranularity(VkExtent2D *pGranularity) const
322 {
323 pGranularity->width = 1;
324 pGranularity->height = 1;
325 }
326
MarkFirstUse(int attachment,int subpass)327 void RenderPass::MarkFirstUse(int attachment, int subpass)
328 {
329 // FIXME: we may not actually need to track attachmentFirstUse if we're going to eagerly
330 // clear attachments at the start of the renderpass; can use attachmentViewMasks always instead.
331
332 if(attachmentFirstUse[attachment] == -1)
333 attachmentFirstUse[attachment] = subpass;
334
335 if(isMultiView())
336 attachmentViewMasks[attachment] |= viewMasks[subpass];
337 }
338
339 } // namespace vk
340