xref: /aosp_15_r20/external/swiftshader/src/Vulkan/VkRenderPass.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 	char *hostMemory = reinterpret_cast<char *>(mem);
148 
149 	// Handle the extensions in each subpass
150 	for(uint32_t i = 0; i < subpassCount; i++)
151 	{
152 		const auto &subpass = pCreateInfo->pSubpasses[i];
153 		const auto *extension = reinterpret_cast<const VkBaseInStructure *>(subpass.pNext);
154 		while(extension)
155 		{
156 			switch(extension->sType)
157 			{
158 			case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE:
159 				{
160 					const auto *ext = reinterpret_cast<const VkSubpassDescriptionDepthStencilResolve *>(extension);
161 					// If any subpass includes depthStencilResolve, allocate a DSR struct for each subpass
162 					// This allows us to index into subpassDepthStencilResolves using the subpass index.
163 					if(ext->pDepthStencilResolveAttachment != nullptr && ext->pDepthStencilResolveAttachment->attachment != VK_ATTACHMENT_UNUSED)
164 					{
165 						if(subpassDepthStencilResolves == nullptr)
166 						{
167 							// Align host memory to 8-bytes
168 							const intptr_t memoryAsInt = reinterpret_cast<intptr_t>(hostMemory);
169 							const intptr_t alignment = alignof(VkSubpassDescriptionDepthStencilResolve);
170 							const intptr_t padding = (alignment - memoryAsInt % alignment) % alignment;
171 							hostMemory += padding;
172 
173 							subpassDepthStencilResolves = reinterpret_cast<VkSubpassDescriptionDepthStencilResolve *>(hostMemory);
174 							hostMemory += subpassCount * sizeof(VkSubpassDescriptionDepthStencilResolve);
175 							for(uint32_t subpass = 0; subpass < subpassCount; subpass++)
176 							{
177 								subpassDepthStencilResolves[subpass].sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;
178 								subpassDepthStencilResolves[subpass].pNext = nullptr;
179 								subpassDepthStencilResolves[subpass].depthResolveMode = VK_RESOLVE_MODE_NONE;
180 								subpassDepthStencilResolves[subpass].stencilResolveMode = VK_RESOLVE_MODE_NONE;
181 								subpassDepthStencilResolves[subpass].pDepthStencilResolveAttachment = nullptr;
182 							}
183 						}
184 
185 						VkAttachmentReference2 *reference = reinterpret_cast<VkAttachmentReference2 *>(hostMemory);
186 						hostMemory += sizeof(VkAttachmentReference2);
187 
188 						subpassDepthStencilResolves[i].depthResolveMode = ext->depthResolveMode;
189 						subpassDepthStencilResolves[i].stencilResolveMode = ext->stencilResolveMode;
190 						reference->pNext = nullptr;
191 						reference->sType = ext->pDepthStencilResolveAttachment->sType;
192 						reference->attachment = ext->pDepthStencilResolveAttachment->attachment;
193 						reference->layout = ext->pDepthStencilResolveAttachment->layout;
194 						reference->aspectMask = ext->pDepthStencilResolveAttachment->aspectMask;
195 						subpassDepthStencilResolves[i].pDepthStencilResolveAttachment = reinterpret_cast<const VkAttachmentReference2 *>(reference);
196 
197 						MarkFirstUse(reference->attachment, i);
198 					}
199 				}
200 				break;
201 			default:
202 				UNSUPPORTED("VkRenderPassCreateInfo2KHR->subpass[%d]->pNext sType: %s",
203 				            i, vk::Stringify(extension->sType).c_str());
204 				break;
205 			}
206 
207 			extension = extension->pNext;
208 		}
209 	}
210 }
211 
212 template<class T>
init(const T * pCreateInfo,void ** mem)213 void RenderPass::init(const T *pCreateInfo, void **mem)
214 {
215 	char *hostMemory = reinterpret_cast<char *>(*mem);
216 
217 	// subpassCount must be greater than 0
218 	ASSERT(pCreateInfo->subpassCount > 0);
219 
220 	size_t subpassesSize = pCreateInfo->subpassCount * sizeof(VkSubpassDescription);
221 	subpasses = reinterpret_cast<VkSubpassDescription *>(hostMemory);
222 	CopySubpasses(subpasses, pCreateInfo->pSubpasses, pCreateInfo->subpassCount);
223 	hostMemory += subpassesSize;
224 	uint32_t *masks = reinterpret_cast<uint32_t *>(hostMemory);
225 	hostMemory += subpassCount * sizeof(uint32_t);
226 
227 	if(attachmentCount > 0)
228 	{
229 		size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription);
230 		attachments = reinterpret_cast<VkAttachmentDescription *>(hostMemory);
231 		CopyAttachmentDescriptions(attachments, pCreateInfo->pAttachments, pCreateInfo->attachmentCount);
232 		hostMemory += attachmentSize;
233 
234 		size_t firstUseSize = pCreateInfo->attachmentCount * sizeof(int);
235 		attachmentFirstUse = reinterpret_cast<int *>(hostMemory);
236 		hostMemory += firstUseSize;
237 
238 		attachmentViewMasks = reinterpret_cast<uint32_t *>(hostMemory);
239 		hostMemory += pCreateInfo->attachmentCount * sizeof(uint32_t);
240 		for(auto i = 0u; i < pCreateInfo->attachmentCount; i++)
241 		{
242 			attachmentFirstUse[i] = -1;
243 			attachmentViewMasks[i] = 0;
244 		}
245 	}
246 
247 	const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
248 	while(extensionCreateInfo)
249 	{
250 		switch(extensionCreateInfo->sType)
251 		{
252 		case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
253 			{
254 				// Renderpass uses multiview if this structure is present AND some subpass specifies
255 				// a nonzero view mask
256 				const auto *multiviewCreateInfo = reinterpret_cast<const VkRenderPassMultiviewCreateInfo *>(extensionCreateInfo);
257 				for(auto i = 0u; i < pCreateInfo->subpassCount; i++)
258 				{
259 					masks[i] = multiviewCreateInfo->pViewMasks[i];
260 					// This is now a multiview renderpass, so make the masks available
261 					if(masks[i])
262 					{
263 						viewMasks = masks;
264 					}
265 				}
266 			}
267 			break;
268 		case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO:
269 			// VkRenderPassInputAttachmentAspectCreateInfo has already been handled in libvulkan.
270 			break;
271 		case VK_STRUCTURE_TYPE_MAX_ENUM:
272 			// dEQP tests that this value is ignored.
273 			break;
274 		default:
275 			UNSUPPORTED("pCreateInfo->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
276 			break;
277 		}
278 
279 		extensionCreateInfo = extensionCreateInfo->pNext;
280 	}
281 
282 	if(!viewMasks && (GetViewMasks(pCreateInfo, masks)))
283 	{
284 		for(auto i = 0u; i < pCreateInfo->subpassCount; i++)
285 		{
286 			if(masks[i])
287 			{
288 				viewMasks = masks;
289 			}
290 		}
291 	}
292 
293 	// Deep copy subpasses
294 	for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
295 	{
296 		const auto &subpass = pCreateInfo->pSubpasses[i];
297 
298 		if(subpass.inputAttachmentCount > 0)
299 		{
300 			size_t inputAttachmentsSize = subpass.inputAttachmentCount * sizeof(VkAttachmentReference);
301 			subpasses[i].pInputAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
302 			CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pInputAttachments),
303 			                         pCreateInfo->pSubpasses[i].pInputAttachments, subpass.inputAttachmentCount);
304 			hostMemory += inputAttachmentsSize;
305 
306 			for(auto j = 0u; j < subpasses[i].inputAttachmentCount; j++)
307 			{
308 				if(subpass.pInputAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
309 					MarkFirstUse(subpass.pInputAttachments[j].attachment, i);
310 			}
311 		}
312 
313 		if(subpass.colorAttachmentCount > 0)
314 		{
315 			size_t colorAttachmentsSize = subpass.colorAttachmentCount * sizeof(VkAttachmentReference);
316 			subpasses[i].pColorAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
317 			CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pColorAttachments),
318 			                         subpass.pColorAttachments, subpass.colorAttachmentCount);
319 			hostMemory += colorAttachmentsSize;
320 
321 			if(subpass.pResolveAttachments)
322 			{
323 				subpasses[i].pResolveAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
324 				CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pResolveAttachments),
325 				                         subpass.pResolveAttachments, subpass.colorAttachmentCount);
326 				hostMemory += colorAttachmentsSize;
327 			}
328 
329 			for(auto j = 0u; j < subpasses[i].colorAttachmentCount; j++)
330 			{
331 				if(subpass.pColorAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
332 					MarkFirstUse(subpass.pColorAttachments[j].attachment, i);
333 				if(subpass.pResolveAttachments &&
334 				   subpass.pResolveAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
335 					MarkFirstUse(subpass.pResolveAttachments[j].attachment, i);
336 			}
337 		}
338 
339 		if(subpass.pDepthStencilAttachment)
340 		{
341 			subpasses[i].pDepthStencilAttachment = reinterpret_cast<VkAttachmentReference *>(hostMemory);
342 			CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pDepthStencilAttachment),
343 			                         subpass.pDepthStencilAttachment, 1);
344 			hostMemory += sizeof(VkAttachmentReference);
345 
346 			if(subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
347 				MarkFirstUse(subpass.pDepthStencilAttachment->attachment, i);
348 		}
349 
350 		if(subpass.preserveAttachmentCount > 0)
351 		{
352 			size_t preserveAttachmentSize = subpass.preserveAttachmentCount * sizeof(uint32_t);
353 			subpasses[i].pPreserveAttachments = reinterpret_cast<uint32_t *>(hostMemory);
354 			for(uint32_t j = 0u; j < subpass.preserveAttachmentCount; j++)
355 			{
356 				const_cast<uint32_t *>(subpasses[i].pPreserveAttachments)[j] = pCreateInfo->pSubpasses[i].pPreserveAttachments[j];
357 			}
358 			hostMemory += preserveAttachmentSize;
359 
360 			for(auto j = 0u; j < subpasses[i].preserveAttachmentCount; j++)
361 			{
362 				if(subpass.pPreserveAttachments[j] != VK_ATTACHMENT_UNUSED)
363 					MarkFirstUse(subpass.pPreserveAttachments[j], i);
364 			}
365 		}
366 	}
367 
368 	if(pCreateInfo->dependencyCount > 0)
369 	{
370 		dependencies = reinterpret_cast<VkSubpassDependency *>(hostMemory);
371 		CopySubpassDependencies(dependencies, pCreateInfo->pDependencies, pCreateInfo->dependencyCount);
372 		hostMemory += dependencyCount * sizeof(VkSubpassDependency);
373 	}
374 	*mem = hostMemory;
375 }
376 
destroy(const VkAllocationCallbacks * pAllocator)377 void RenderPass::destroy(const VkAllocationCallbacks *pAllocator)
378 {
379 	vk::freeHostMemory(subpasses, pAllocator);  // attachments and dependencies are in the same allocation
380 }
381 
ComputeRequiredAllocationSize(const VkRenderPassCreateInfo * pCreateInfo)382 size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo *pCreateInfo)
383 {
384 	return ComputeRequiredAllocationSizeT(pCreateInfo);
385 }
386 
ComputeRequiredAllocationSize(const VkRenderPassCreateInfo2KHR * pCreateInfo)387 size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo2KHR *pCreateInfo)
388 {
389 	size_t requiredMemory = ComputeRequiredAllocationSizeT(pCreateInfo);
390 
391 	// Calculate the memory required to handle depth stencil resolves
392 	bool usesDSR = false;
393 	for(uint32_t i = 0; i < pCreateInfo->subpassCount; i++)
394 	{
395 		const auto &subpass = pCreateInfo->pSubpasses[i];
396 		const VkBaseInStructure *extension = reinterpret_cast<const VkBaseInStructure *>(subpass.pNext);
397 		while(extension)
398 		{
399 			switch(extension->sType)
400 			{
401 			case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE:
402 				{
403 					const auto *ext = reinterpret_cast<const VkSubpassDescriptionDepthStencilResolve *>(extension);
404 					if(ext->pDepthStencilResolveAttachment != nullptr && ext->pDepthStencilResolveAttachment->attachment != VK_ATTACHMENT_UNUSED)
405 					{
406 						if(!usesDSR)
407 						{
408 							// If any subpass uses DSR, then allocate a VkSubpassDescriptionDepthStencilResolve
409 							// for all subpasses. This allows us to index into our DSR structs using the subpass index.
410 							//
411 							// Add a few bytes for alignment if necessary
412 							requiredMemory += sizeof(VkSubpassDescriptionDepthStencilResolve) * pCreateInfo->subpassCount + alignof(VkSubpassDescriptionDepthStencilResolve);
413 							usesDSR = true;
414 						}
415 						// For each subpass that actually uses DSR, allocate a VkAttachmentReference2.
416 						requiredMemory += sizeof(VkAttachmentReference2);
417 					}
418 				}
419 				break;
420 			default:
421 				UNSUPPORTED("VkRenderPassCreateInfo2KHR->subpass[%d]->pNext sType: %s",
422 				            i, vk::Stringify(extension->sType).c_str());
423 				break;
424 			}
425 
426 			extension = extension->pNext;
427 		}
428 	}
429 
430 	return requiredMemory;
431 }
432 
getRenderAreaGranularity(VkExtent2D * pGranularity) const433 void RenderPass::getRenderAreaGranularity(VkExtent2D *pGranularity) const
434 {
435 	pGranularity->width = 1;
436 	pGranularity->height = 1;
437 }
438 
MarkFirstUse(int attachment,int subpass)439 void RenderPass::MarkFirstUse(int attachment, int subpass)
440 {
441 	// FIXME: we may not actually need to track attachmentFirstUse if we're going to eagerly
442 	//  clear attachments at the start of the renderpass; can use attachmentViewMasks always instead.
443 
444 	if(attachmentFirstUse[attachment] == -1)
445 		attachmentFirstUse[attachment] = subpass;
446 
447 	if(isMultiView())
448 		attachmentViewMasks[attachment] |= viewMasks[subpass];
449 }
450 
451 }  // namespace vk
452