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