xref: /aosp_15_r20/external/swiftshader/src/Vulkan/VkFramebuffer.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "VkFramebuffer.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "VkImageView.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "VkRenderPass.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "VkStringify.hpp"
20*03ce13f7SAndroid Build Coastguard Worker 
21*03ce13f7SAndroid Build Coastguard Worker #include <memory.h>
22*03ce13f7SAndroid Build Coastguard Worker #include <algorithm>
23*03ce13f7SAndroid Build Coastguard Worker 
24*03ce13f7SAndroid Build Coastguard Worker namespace vk {
25*03ce13f7SAndroid Build Coastguard Worker 
Framebuffer(const VkFramebufferCreateInfo * pCreateInfo,void * mem)26*03ce13f7SAndroid Build Coastguard Worker Framebuffer::Framebuffer(const VkFramebufferCreateInfo *pCreateInfo, void *mem)
27*03ce13f7SAndroid Build Coastguard Worker     : attachments(reinterpret_cast<ImageView **>(mem))
28*03ce13f7SAndroid Build Coastguard Worker     , extent{ pCreateInfo->width, pCreateInfo->height }
29*03ce13f7SAndroid Build Coastguard Worker {
30*03ce13f7SAndroid Build Coastguard Worker 	const VkBaseInStructure *curInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
31*03ce13f7SAndroid Build Coastguard Worker 	const VkFramebufferAttachmentsCreateInfo *attachmentsCreateInfo = nullptr;
32*03ce13f7SAndroid Build Coastguard Worker 	while(curInfo)
33*03ce13f7SAndroid Build Coastguard Worker 	{
34*03ce13f7SAndroid Build Coastguard Worker 		switch(curInfo->sType)
35*03ce13f7SAndroid Build Coastguard Worker 		{
36*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO:
37*03ce13f7SAndroid Build Coastguard Worker 			attachmentsCreateInfo = reinterpret_cast<const VkFramebufferAttachmentsCreateInfo *>(curInfo);
38*03ce13f7SAndroid Build Coastguard Worker 			break;
39*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_MAX_ENUM:
40*03ce13f7SAndroid Build Coastguard Worker 			// dEQP tests that this value is ignored.
41*03ce13f7SAndroid Build Coastguard Worker 			break;
42*03ce13f7SAndroid Build Coastguard Worker 		default:
43*03ce13f7SAndroid Build Coastguard Worker 			UNSUPPORTED("pFramebufferCreateInfo->pNext->sType = %s", vk::Stringify(curInfo->sType).c_str());
44*03ce13f7SAndroid Build Coastguard Worker 			break;
45*03ce13f7SAndroid Build Coastguard Worker 		}
46*03ce13f7SAndroid Build Coastguard Worker 		curInfo = curInfo->pNext;
47*03ce13f7SAndroid Build Coastguard Worker 	}
48*03ce13f7SAndroid Build Coastguard Worker 
49*03ce13f7SAndroid Build Coastguard Worker 	if(pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT)
50*03ce13f7SAndroid Build Coastguard Worker 	{
51*03ce13f7SAndroid Build Coastguard Worker 		// If flags includes VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, the pNext chain **must**
52*03ce13f7SAndroid Build Coastguard Worker 		// include a VkFramebufferAttachmentsCreateInfo.
53*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(attachmentsCreateInfo != nullptr);
54*03ce13f7SAndroid Build Coastguard Worker 		attachmentCount = attachmentsCreateInfo->attachmentImageInfoCount;
55*03ce13f7SAndroid Build Coastguard Worker 		for(uint32_t i = 0; i < attachmentCount; i++)
56*03ce13f7SAndroid Build Coastguard Worker 		{
57*03ce13f7SAndroid Build Coastguard Worker 			attachments[i] = nullptr;
58*03ce13f7SAndroid Build Coastguard Worker 		}
59*03ce13f7SAndroid Build Coastguard Worker 	}
60*03ce13f7SAndroid Build Coastguard Worker 	else
61*03ce13f7SAndroid Build Coastguard Worker 	{
62*03ce13f7SAndroid Build Coastguard Worker 		attachmentCount = pCreateInfo->attachmentCount;
63*03ce13f7SAndroid Build Coastguard Worker 		for(uint32_t i = 0; i < attachmentCount; i++)
64*03ce13f7SAndroid Build Coastguard Worker 		{
65*03ce13f7SAndroid Build Coastguard Worker 			attachments[i] = vk::Cast(pCreateInfo->pAttachments[i]);
66*03ce13f7SAndroid Build Coastguard Worker 		}
67*03ce13f7SAndroid Build Coastguard Worker 	}
68*03ce13f7SAndroid Build Coastguard Worker }
69*03ce13f7SAndroid Build Coastguard Worker 
destroy(const VkAllocationCallbacks * pAllocator)70*03ce13f7SAndroid Build Coastguard Worker void Framebuffer::destroy(const VkAllocationCallbacks *pAllocator)
71*03ce13f7SAndroid Build Coastguard Worker {
72*03ce13f7SAndroid Build Coastguard Worker 	vk::freeHostMemory(attachments, pAllocator);
73*03ce13f7SAndroid Build Coastguard Worker }
74*03ce13f7SAndroid Build Coastguard Worker 
executeLoadOp(const RenderPass * renderPass,uint32_t clearValueCount,const VkClearValue * pClearValues,const VkRect2D & renderArea)75*03ce13f7SAndroid Build Coastguard Worker void Framebuffer::executeLoadOp(const RenderPass *renderPass, uint32_t clearValueCount, const VkClearValue *pClearValues, const VkRect2D &renderArea)
76*03ce13f7SAndroid Build Coastguard Worker {
77*03ce13f7SAndroid Build Coastguard Worker 	// This gets called at the start of a renderpass. Logically the `loadOp` gets executed at the
78*03ce13f7SAndroid Build Coastguard Worker 	// subpass where an attachment is first used, but since we don't discard contents between subpasses,
79*03ce13f7SAndroid Build Coastguard Worker 	// we can execute it sooner. Only clear operations have an effect.
80*03ce13f7SAndroid Build Coastguard Worker 
81*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(attachmentCount == renderPass->getAttachmentCount());
82*03ce13f7SAndroid Build Coastguard Worker 
83*03ce13f7SAndroid Build Coastguard Worker 	const uint32_t count = std::min(clearValueCount, attachmentCount);
84*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t i = 0; i < count; i++)
85*03ce13f7SAndroid Build Coastguard Worker 	{
86*03ce13f7SAndroid Build Coastguard Worker 		const VkAttachmentDescription attachment = renderPass->getAttachment(i);
87*03ce13f7SAndroid Build Coastguard Worker 		VkImageAspectFlags clearMask = 0;
88*03ce13f7SAndroid Build Coastguard Worker 
89*03ce13f7SAndroid Build Coastguard Worker 		switch(attachment.loadOp)
90*03ce13f7SAndroid Build Coastguard Worker 		{
91*03ce13f7SAndroid Build Coastguard Worker 		case VK_ATTACHMENT_LOAD_OP_CLEAR:
92*03ce13f7SAndroid Build Coastguard Worker 			clearMask |= VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
93*03ce13f7SAndroid Build Coastguard Worker 			break;
94*03ce13f7SAndroid Build Coastguard Worker 		case VK_ATTACHMENT_LOAD_OP_LOAD:
95*03ce13f7SAndroid Build Coastguard Worker 		case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
96*03ce13f7SAndroid Build Coastguard Worker 		case VK_ATTACHMENT_LOAD_OP_NONE_EXT:
97*03ce13f7SAndroid Build Coastguard Worker 			// Don't clear the attachment's color or depth aspect.
98*03ce13f7SAndroid Build Coastguard Worker 			break;
99*03ce13f7SAndroid Build Coastguard Worker 		default:
100*03ce13f7SAndroid Build Coastguard Worker 			UNSUPPORTED("attachment.loadOp %d", attachment.loadOp);
101*03ce13f7SAndroid Build Coastguard Worker 		}
102*03ce13f7SAndroid Build Coastguard Worker 
103*03ce13f7SAndroid Build Coastguard Worker 		switch(attachment.stencilLoadOp)
104*03ce13f7SAndroid Build Coastguard Worker 		{
105*03ce13f7SAndroid Build Coastguard Worker 		case VK_ATTACHMENT_LOAD_OP_CLEAR:
106*03ce13f7SAndroid Build Coastguard Worker 			clearMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
107*03ce13f7SAndroid Build Coastguard Worker 			break;
108*03ce13f7SAndroid Build Coastguard Worker 		case VK_ATTACHMENT_LOAD_OP_LOAD:
109*03ce13f7SAndroid Build Coastguard Worker 		case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
110*03ce13f7SAndroid Build Coastguard Worker 		case VK_ATTACHMENT_LOAD_OP_NONE_EXT:
111*03ce13f7SAndroid Build Coastguard Worker 			// Don't clear the attachment's stencil aspect.
112*03ce13f7SAndroid Build Coastguard Worker 			break;
113*03ce13f7SAndroid Build Coastguard Worker 		default:
114*03ce13f7SAndroid Build Coastguard Worker 			UNSUPPORTED("attachment.stencilLoadOp %d", attachment.stencilLoadOp);
115*03ce13f7SAndroid Build Coastguard Worker 		}
116*03ce13f7SAndroid Build Coastguard Worker 
117*03ce13f7SAndroid Build Coastguard Worker 		// Image::clear() demands that we only specify existing aspects.
118*03ce13f7SAndroid Build Coastguard Worker 		clearMask &= Format(attachment.format).getAspects();
119*03ce13f7SAndroid Build Coastguard Worker 
120*03ce13f7SAndroid Build Coastguard Worker 		if(!clearMask || !renderPass->isAttachmentUsed(i))
121*03ce13f7SAndroid Build Coastguard Worker 		{
122*03ce13f7SAndroid Build Coastguard Worker 			continue;
123*03ce13f7SAndroid Build Coastguard Worker 		}
124*03ce13f7SAndroid Build Coastguard Worker 
125*03ce13f7SAndroid Build Coastguard Worker 		uint32_t viewMask = renderPass->isMultiView() ? renderPass->getAttachmentViewMask(i) : 0;
126*03ce13f7SAndroid Build Coastguard Worker 		attachments[i]->clear(pClearValues[i], clearMask, renderArea, viewMask);
127*03ce13f7SAndroid Build Coastguard Worker 	}
128*03ce13f7SAndroid Build Coastguard Worker }
129*03ce13f7SAndroid Build Coastguard Worker 
clearAttachment(const RenderPass * renderPass,uint32_t subpassIndex,const VkClearAttachment & attachment,const VkClearRect & rect)130*03ce13f7SAndroid Build Coastguard Worker void Framebuffer::clearAttachment(const RenderPass *renderPass, uint32_t subpassIndex, const VkClearAttachment &attachment, const VkClearRect &rect)
131*03ce13f7SAndroid Build Coastguard Worker {
132*03ce13f7SAndroid Build Coastguard Worker 	VkSubpassDescription subpass = renderPass->getSubpass(subpassIndex);
133*03ce13f7SAndroid Build Coastguard Worker 	uint32_t viewMask = renderPass->getViewMask(subpassIndex);
134*03ce13f7SAndroid Build Coastguard Worker 
135*03ce13f7SAndroid Build Coastguard Worker 	if(attachment.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
136*03ce13f7SAndroid Build Coastguard Worker 	{
137*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(attachment.colorAttachment < subpass.colorAttachmentCount);
138*03ce13f7SAndroid Build Coastguard Worker 		uint32_t attachmentIndex = subpass.pColorAttachments[attachment.colorAttachment].attachment;
139*03ce13f7SAndroid Build Coastguard Worker 
140*03ce13f7SAndroid Build Coastguard Worker 		if(attachmentIndex != VK_ATTACHMENT_UNUSED)
141*03ce13f7SAndroid Build Coastguard Worker 		{
142*03ce13f7SAndroid Build Coastguard Worker 			ASSERT(attachmentIndex < attachmentCount);
143*03ce13f7SAndroid Build Coastguard Worker 			ImageView *imageView = attachments[attachmentIndex];
144*03ce13f7SAndroid Build Coastguard Worker 
145*03ce13f7SAndroid Build Coastguard Worker 			imageView->clear(attachment.clearValue, attachment.aspectMask, rect, viewMask);
146*03ce13f7SAndroid Build Coastguard Worker 		}
147*03ce13f7SAndroid Build Coastguard Worker 	}
148*03ce13f7SAndroid Build Coastguard Worker 	else if(attachment.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
149*03ce13f7SAndroid Build Coastguard Worker 	{
150*03ce13f7SAndroid Build Coastguard Worker 		uint32_t attachmentIndex = subpass.pDepthStencilAttachment->attachment;
151*03ce13f7SAndroid Build Coastguard Worker 
152*03ce13f7SAndroid Build Coastguard Worker 		if(attachmentIndex != VK_ATTACHMENT_UNUSED)
153*03ce13f7SAndroid Build Coastguard Worker 		{
154*03ce13f7SAndroid Build Coastguard Worker 			ASSERT(attachmentIndex < attachmentCount);
155*03ce13f7SAndroid Build Coastguard Worker 			ImageView *imageView = attachments[attachmentIndex];
156*03ce13f7SAndroid Build Coastguard Worker 
157*03ce13f7SAndroid Build Coastguard Worker 			imageView->clear(attachment.clearValue, attachment.aspectMask, rect, viewMask);
158*03ce13f7SAndroid Build Coastguard Worker 		}
159*03ce13f7SAndroid Build Coastguard Worker 	}
160*03ce13f7SAndroid Build Coastguard Worker 	else
161*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("attachment.aspectMask %X", attachment.aspectMask);
162*03ce13f7SAndroid Build Coastguard Worker }
163*03ce13f7SAndroid Build Coastguard Worker 
setAttachment(ImageView * imageView,uint32_t index)164*03ce13f7SAndroid Build Coastguard Worker void Framebuffer::setAttachment(ImageView *imageView, uint32_t index)
165*03ce13f7SAndroid Build Coastguard Worker {
166*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(index < attachmentCount);
167*03ce13f7SAndroid Build Coastguard Worker 	attachments[index] = imageView;
168*03ce13f7SAndroid Build Coastguard Worker }
169*03ce13f7SAndroid Build Coastguard Worker 
getAttachment(uint32_t index) const170*03ce13f7SAndroid Build Coastguard Worker ImageView *Framebuffer::getAttachment(uint32_t index) const
171*03ce13f7SAndroid Build Coastguard Worker {
172*03ce13f7SAndroid Build Coastguard Worker 	return attachments[index];
173*03ce13f7SAndroid Build Coastguard Worker }
174*03ce13f7SAndroid Build Coastguard Worker 
resolve(const RenderPass * renderPass,uint32_t subpassIndex)175*03ce13f7SAndroid Build Coastguard Worker void Framebuffer::resolve(const RenderPass *renderPass, uint32_t subpassIndex)
176*03ce13f7SAndroid Build Coastguard Worker {
177*03ce13f7SAndroid Build Coastguard Worker 	const auto &subpass = renderPass->getSubpass(subpassIndex);
178*03ce13f7SAndroid Build Coastguard Worker 	uint32_t viewMask = renderPass->getViewMask(subpassIndex);
179*03ce13f7SAndroid Build Coastguard Worker 
180*03ce13f7SAndroid Build Coastguard Worker 	if(subpass.pResolveAttachments)
181*03ce13f7SAndroid Build Coastguard Worker 	{
182*03ce13f7SAndroid Build Coastguard Worker 		for(uint32_t i = 0; i < subpass.colorAttachmentCount; i++)
183*03ce13f7SAndroid Build Coastguard Worker 		{
184*03ce13f7SAndroid Build Coastguard Worker 			uint32_t resolveAttachment = subpass.pResolveAttachments[i].attachment;
185*03ce13f7SAndroid Build Coastguard Worker 			if(resolveAttachment != VK_ATTACHMENT_UNUSED)
186*03ce13f7SAndroid Build Coastguard Worker 			{
187*03ce13f7SAndroid Build Coastguard Worker 				ImageView *imageView = attachments[subpass.pColorAttachments[i].attachment];
188*03ce13f7SAndroid Build Coastguard Worker 				imageView->resolve(attachments[resolveAttachment], viewMask);
189*03ce13f7SAndroid Build Coastguard Worker 			}
190*03ce13f7SAndroid Build Coastguard Worker 		}
191*03ce13f7SAndroid Build Coastguard Worker 	}
192*03ce13f7SAndroid Build Coastguard Worker 
193*03ce13f7SAndroid Build Coastguard Worker 	if(renderPass->hasDepthStencilResolve() && subpass.pDepthStencilAttachment != nullptr)
194*03ce13f7SAndroid Build Coastguard Worker 	{
195*03ce13f7SAndroid Build Coastguard Worker 		VkSubpassDescriptionDepthStencilResolve dsResolve = renderPass->getSubpassDepthStencilResolve(subpassIndex);
196*03ce13f7SAndroid Build Coastguard Worker 		uint32_t depthStencilAttachment = subpass.pDepthStencilAttachment->attachment;
197*03ce13f7SAndroid Build Coastguard Worker 		if((depthStencilAttachment != VK_ATTACHMENT_UNUSED) && (dsResolve.pDepthStencilResolveAttachment != nullptr))
198*03ce13f7SAndroid Build Coastguard Worker 		{
199*03ce13f7SAndroid Build Coastguard Worker 			ImageView *imageView = attachments[depthStencilAttachment];
200*03ce13f7SAndroid Build Coastguard Worker 			imageView->resolveDepthStencil(attachments[dsResolve.pDepthStencilResolveAttachment->attachment],
201*03ce13f7SAndroid Build Coastguard Worker 			                               dsResolve.depthResolveMode, dsResolve.stencilResolveMode);
202*03ce13f7SAndroid Build Coastguard Worker 		}
203*03ce13f7SAndroid Build Coastguard Worker 	}
204*03ce13f7SAndroid Build Coastguard Worker }
205*03ce13f7SAndroid Build Coastguard Worker 
ComputeRequiredAllocationSize(const VkFramebufferCreateInfo * pCreateInfo)206*03ce13f7SAndroid Build Coastguard Worker size_t Framebuffer::ComputeRequiredAllocationSize(const VkFramebufferCreateInfo *pCreateInfo)
207*03ce13f7SAndroid Build Coastguard Worker {
208*03ce13f7SAndroid Build Coastguard Worker 	const VkBaseInStructure *curInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
209*03ce13f7SAndroid Build Coastguard Worker 	const VkFramebufferAttachmentsCreateInfo *attachmentsInfo = nullptr;
210*03ce13f7SAndroid Build Coastguard Worker 	while(curInfo)
211*03ce13f7SAndroid Build Coastguard Worker 	{
212*03ce13f7SAndroid Build Coastguard Worker 		switch(curInfo->sType)
213*03ce13f7SAndroid Build Coastguard Worker 		{
214*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO:
215*03ce13f7SAndroid Build Coastguard Worker 			attachmentsInfo = reinterpret_cast<const VkFramebufferAttachmentsCreateInfo *>(curInfo);
216*03ce13f7SAndroid Build Coastguard Worker 			break;
217*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_MAX_ENUM:
218*03ce13f7SAndroid Build Coastguard Worker 			// dEQP tests that this value is ignored.
219*03ce13f7SAndroid Build Coastguard Worker 			break;
220*03ce13f7SAndroid Build Coastguard Worker 		default:
221*03ce13f7SAndroid Build Coastguard Worker 			UNSUPPORTED("pFramebufferCreateInfo->pNext->sType = %s", vk::Stringify(curInfo->sType).c_str());
222*03ce13f7SAndroid Build Coastguard Worker 			break;
223*03ce13f7SAndroid Build Coastguard Worker 		}
224*03ce13f7SAndroid Build Coastguard Worker 
225*03ce13f7SAndroid Build Coastguard Worker 		curInfo = curInfo->pNext;
226*03ce13f7SAndroid Build Coastguard Worker 	}
227*03ce13f7SAndroid Build Coastguard Worker 
228*03ce13f7SAndroid Build Coastguard Worker 	if(pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT)
229*03ce13f7SAndroid Build Coastguard Worker 	{
230*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(attachmentsInfo != nullptr);
231*03ce13f7SAndroid Build Coastguard Worker 		return attachmentsInfo->attachmentImageInfoCount * sizeof(void *);
232*03ce13f7SAndroid Build Coastguard Worker 	}
233*03ce13f7SAndroid Build Coastguard Worker 	else
234*03ce13f7SAndroid Build Coastguard Worker 	{
235*03ce13f7SAndroid Build Coastguard Worker 		return pCreateInfo->attachmentCount * sizeof(void *);
236*03ce13f7SAndroid Build Coastguard Worker 	}
237*03ce13f7SAndroid Build Coastguard Worker }
238*03ce13f7SAndroid Build Coastguard Worker 
239*03ce13f7SAndroid Build Coastguard Worker }  // namespace vk
240