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 | |
18 | namespace vk |
19 | { |
20 | |
21 | RenderPass::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 | |
172 | void RenderPass::destroy(const VkAllocationCallbacks* pAllocator) |
173 | { |
174 | vk::deallocate(subpasses, pAllocator); // attachments and dependencies are in the same allocation |
175 | } |
176 | |
177 | size_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 | |
205 | void RenderPass::getRenderAreaGranularity(VkExtent2D* pGranularity) const |
206 | { |
207 | pGranularity->width = 1; |
208 | pGranularity->height = 1; |
209 | } |
210 | |
211 | void 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 |