blob: 0830709de714fa6979934588d205f409cf476fd1 [file] [log] [blame]
Alexis Hetub16f9892018-11-15 15:18:41 -05001// 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"
Alexis Hetu7b29abf2019-11-21 17:26:17 -050016#include "VkStringify.hpp"
Alexis Hetu238af152019-01-18 10:35:51 -050017#include <cstring>
Alexis Hetub16f9892018-11-15 15:18:41 -050018
Alexis Hetu9f8337e2020-02-07 11:07:43 -050019namespace {
20
21template<class T>
22size_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
49template<class T>
50void 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
67template<class T>
68void 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
84template<class T>
85void 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
94template<class T>
95void 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
109bool GetViewMasks(const VkRenderPassCreateInfo *pCreateInfo, uint32_t *masks)
110{
111 return false;
112}
113
114bool 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
Nicolas Capens157ba262019-12-10 17:49:14 -0500125namespace vk {
Alexis Hetub16f9892018-11-15 15:18:41 -0500126
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000127RenderPass::RenderPass(const VkRenderPassCreateInfo *pCreateInfo, void *mem)
128 : attachmentCount(pCreateInfo->attachmentCount)
129 , subpassCount(pCreateInfo->subpassCount)
130 , dependencyCount(pCreateInfo->dependencyCount)
Alexis Hetub16f9892018-11-15 15:18:41 -0500131{
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500132 init(pCreateInfo, mem);
133}
134
135RenderPass::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
148template<class T>
149void RenderPass::init(const T *pCreateInfo, void *mem)
150{
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000151 char *hostMemory = reinterpret_cast<char *>(mem);
Alexis Hetu238af152019-01-18 10:35:51 -0500152
153 // subpassCount must be greater than 0
154 ASSERT(pCreateInfo->subpassCount > 0);
155
156 size_t subpassesSize = pCreateInfo->subpassCount * sizeof(VkSubpassDescription);
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000157 subpasses = reinterpret_cast<VkSubpassDescription *>(hostMemory);
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500158 CopySubpasses(subpasses, pCreateInfo->pSubpasses, pCreateInfo->subpassCount);
Alexis Hetu238af152019-01-18 10:35:51 -0500159 hostMemory += subpassesSize;
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700160 uint32_t *masks = reinterpret_cast<uint32_t *>(hostMemory);
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500161 hostMemory += subpassCount * sizeof(uint32_t);
Alexis Hetu238af152019-01-18 10:35:51 -0500162
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500163 if(attachmentCount > 0)
Alexis Hetu238af152019-01-18 10:35:51 -0500164 {
165 size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription);
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000166 attachments = reinterpret_cast<VkAttachmentDescription *>(hostMemory);
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500167 CopyAttachmentDescriptions(attachments, pCreateInfo->pAttachments, pCreateInfo->attachmentCount);
Alexis Hetu238af152019-01-18 10:35:51 -0500168 hostMemory += attachmentSize;
Chris Forbes65b1e972019-05-13 11:01:56 -0700169
170 size_t firstUseSize = pCreateInfo->attachmentCount * sizeof(int);
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000171 attachmentFirstUse = reinterpret_cast<int *>(hostMemory);
Chris Forbes65b1e972019-05-13 11:01:56 -0700172 hostMemory += firstUseSize;
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700173
174 attachmentViewMasks = reinterpret_cast<uint32_t *>(hostMemory);
175 hostMemory += pCreateInfo->attachmentCount * sizeof(uint32_t);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500176 for(auto i = 0u; i < pCreateInfo->attachmentCount; i++)
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700177 {
178 attachmentFirstUse[i] = -1;
179 attachmentViewMasks[i] = 0;
180 }
181 }
182
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000183 const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500184 while(extensionCreateInfo)
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700185 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500186 switch(extensionCreateInfo->sType)
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700187 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000188 case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700189 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000190 // 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])
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500198 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000199 viewMasks = masks;
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500200 }
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000201 }
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700202
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000203 break;
204 }
205 default:
206 WARN("pCreateInfo->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
207 break;
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700208 }
209
210 extensionCreateInfo = extensionCreateInfo->pNext;
Alexis Hetu238af152019-01-18 10:35:51 -0500211 }
212
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500213 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
Alexis Hetu238af152019-01-18 10:35:51 -0500224 // Deep copy subpasses
225 for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
226 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000227 const auto &subpass = pCreateInfo->pSubpasses[i];
Alexis Hetu238af152019-01-18 10:35:51 -0500228
229 if(subpass.inputAttachmentCount > 0)
230 {
231 size_t inputAttachmentsSize = subpass.inputAttachmentCount * sizeof(VkAttachmentReference);
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000232 subpasses[i].pInputAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500233 CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pInputAttachments),
234 pCreateInfo->pSubpasses[i].pInputAttachments, subpass.inputAttachmentCount);
Alexis Hetu238af152019-01-18 10:35:51 -0500235 hostMemory += inputAttachmentsSize;
Chris Forbes65b1e972019-05-13 11:01:56 -0700236
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500237 for(auto j = 0u; j < subpasses[i].inputAttachmentCount; j++)
Chris Forbes65b1e972019-05-13 11:01:56 -0700238 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500239 if(subpass.pInputAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700240 MarkFirstUse(subpass.pInputAttachments[j].attachment, i);
Chris Forbes65b1e972019-05-13 11:01:56 -0700241 }
Alexis Hetu238af152019-01-18 10:35:51 -0500242 }
243
244 if(subpass.colorAttachmentCount > 0)
245 {
246 size_t colorAttachmentsSize = subpass.colorAttachmentCount * sizeof(VkAttachmentReference);
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000247 subpasses[i].pColorAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500248 CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pColorAttachments),
249 subpass.pColorAttachments, subpass.colorAttachmentCount);
Alexis Hetu238af152019-01-18 10:35:51 -0500250 hostMemory += colorAttachmentsSize;
251
Alexis Hetu2d77aea2019-06-17 13:43:50 -0400252 if(subpass.pResolveAttachments)
Alexis Hetu238af152019-01-18 10:35:51 -0500253 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000254 subpasses[i].pResolveAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500255 CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pResolveAttachments),
256 subpass.pResolveAttachments, subpass.colorAttachmentCount);
Alexis Hetu238af152019-01-18 10:35:51 -0500257 hostMemory += colorAttachmentsSize;
258 }
Chris Forbes65b1e972019-05-13 11:01:56 -0700259
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500260 for(auto j = 0u; j < subpasses[i].colorAttachmentCount; j++)
Chris Forbes65b1e972019-05-13 11:01:56 -0700261 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500262 if(subpass.pColorAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700263 MarkFirstUse(subpass.pColorAttachments[j].attachment, i);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500264 if(subpass.pResolveAttachments &&
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000265 subpass.pResolveAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700266 MarkFirstUse(subpass.pResolveAttachments[j].attachment, i);
Chris Forbes65b1e972019-05-13 11:01:56 -0700267 }
Alexis Hetu238af152019-01-18 10:35:51 -0500268 }
269
Alexis Hetu2d77aea2019-06-17 13:43:50 -0400270 if(subpass.pDepthStencilAttachment)
Alexis Hetu238af152019-01-18 10:35:51 -0500271 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000272 subpasses[i].pDepthStencilAttachment = reinterpret_cast<VkAttachmentReference *>(hostMemory);
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500273 CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pDepthStencilAttachment),
274 subpass.pDepthStencilAttachment, 1);
Alexis Hetu238af152019-01-18 10:35:51 -0500275 hostMemory += sizeof(VkAttachmentReference);
Chris Forbes65b1e972019-05-13 11:01:56 -0700276
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500277 if(subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700278 MarkFirstUse(subpass.pDepthStencilAttachment->attachment, i);
Alexis Hetu238af152019-01-18 10:35:51 -0500279 }
280
281 if(subpass.preserveAttachmentCount > 0)
282 {
283 size_t preserveAttachmentSize = subpass.preserveAttachmentCount * sizeof(uint32_t);
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000284 subpasses[i].pPreserveAttachments = reinterpret_cast<uint32_t *>(hostMemory);
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500285 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 }
Alexis Hetu238af152019-01-18 10:35:51 -0500289 hostMemory += preserveAttachmentSize;
Chris Forbes65b1e972019-05-13 11:01:56 -0700290
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500291 for(auto j = 0u; j < subpasses[i].preserveAttachmentCount; j++)
Chris Forbes65b1e972019-05-13 11:01:56 -0700292 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500293 if(subpass.pPreserveAttachments[j] != VK_ATTACHMENT_UNUSED)
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700294 MarkFirstUse(subpass.pPreserveAttachments[j], i);
Chris Forbes65b1e972019-05-13 11:01:56 -0700295 }
Alexis Hetu238af152019-01-18 10:35:51 -0500296 }
297 }
298
299 if(pCreateInfo->dependencyCount > 0)
300 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000301 dependencies = reinterpret_cast<VkSubpassDependency *>(hostMemory);
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500302 CopySubpassDependencies(dependencies, pCreateInfo->pDependencies, pCreateInfo->dependencyCount);
Alexis Hetu238af152019-01-18 10:35:51 -0500303 }
Alexis Hetub16f9892018-11-15 15:18:41 -0500304}
305
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000306void RenderPass::destroy(const VkAllocationCallbacks *pAllocator)
Alexis Hetub16f9892018-11-15 15:18:41 -0500307{
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000308 vk::deallocate(subpasses, pAllocator); // attachments and dependencies are in the same allocation
Alexis Hetub16f9892018-11-15 15:18:41 -0500309}
310
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000311size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo *pCreateInfo)
Alexis Hetub16f9892018-11-15 15:18:41 -0500312{
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500313 return ComputeRequiredAllocationSizeT(pCreateInfo);
314}
Alexis Hetu238af152019-01-18 10:35:51 -0500315
Alexis Hetu9f8337e2020-02-07 11:07:43 -0500316size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo2KHR *pCreateInfo)
317{
318 return ComputeRequiredAllocationSizeT(pCreateInfo);
Alexis Hetub16f9892018-11-15 15:18:41 -0500319}
320
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000321void RenderPass::getRenderAreaGranularity(VkExtent2D *pGranularity) const
Chris Forbes65b1e972019-05-13 11:01:56 -0700322{
323 pGranularity->width = 1;
324 pGranularity->height = 1;
325}
Alexis Hetu6d74ab82019-02-15 14:42:38 -0500326
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700327void 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
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500332 if(attachmentFirstUse[attachment] == -1)
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700333 attachmentFirstUse[attachment] = subpass;
334
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500335 if(isMultiView())
Chris Forbes02d4c0d2019-08-21 12:04:34 -0700336 attachmentViewMasks[attachment] |= viewMasks[subpass];
337}
338
Nicolas Capens157ba262019-12-10 17:49:14 -0500339} // namespace vk