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 "VkFramebuffer.hpp"
16 
17 #include "VkImageView.hpp"
18 #include "VkRenderPass.hpp"
19 #include "VkStringify.hpp"
20 
21 #include <memory.h>
22 #include <algorithm>
23 
24 namespace vk {
25 
Framebuffer(const VkFramebufferCreateInfo * pCreateInfo,void * mem)26 Framebuffer::Framebuffer(const VkFramebufferCreateInfo *pCreateInfo, void *mem)
27     : attachments(reinterpret_cast<ImageView **>(mem))
28     , extent{ pCreateInfo->width, pCreateInfo->height, pCreateInfo->layers }
29 {
30 	const VkBaseInStructure *curInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
31 	const VkFramebufferAttachmentsCreateInfo *attachmentsCreateInfo = nullptr;
32 	while(curInfo)
33 	{
34 		switch(curInfo->sType)
35 		{
36 			case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO:
37 				attachmentsCreateInfo = reinterpret_cast<const VkFramebufferAttachmentsCreateInfo *>(curInfo);
38 				break;
39 			default:
40 				LOG_TRAP("pFramebufferCreateInfo->pNext->sType = %s", vk::Stringify(curInfo->sType).c_str());
41 				break;
42 		}
43 		curInfo = curInfo->pNext;
44 	}
45 
46 	if(pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT)
47 	{
48 		// If flags includes VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, the pNext chain **must**
49 		// include a VkFramebufferAttachmentsCreateInfo.
50 		ASSERT(attachmentsCreateInfo != nullptr);
51 		attachmentCount = attachmentsCreateInfo->attachmentImageInfoCount;
52 		for(uint32_t i = 0; i < attachmentCount; i++)
53 		{
54 			attachments[i] = nullptr;
55 		}
56 	}
57 	else
58 	{
59 		attachmentCount = pCreateInfo->attachmentCount;
60 		for(uint32_t i = 0; i < attachmentCount; i++)
61 		{
62 			attachments[i] = vk::Cast(pCreateInfo->pAttachments[i]);
63 		}
64 	}
65 }
66 
destroy(const VkAllocationCallbacks * pAllocator)67 void Framebuffer::destroy(const VkAllocationCallbacks *pAllocator)
68 {
69 	vk::deallocate(attachments, pAllocator);
70 }
71 
clear(const RenderPass * renderPass,uint32_t clearValueCount,const VkClearValue * pClearValues,const VkRect2D & renderArea)72 void Framebuffer::clear(const RenderPass *renderPass, uint32_t clearValueCount, const VkClearValue *pClearValues, const VkRect2D &renderArea)
73 {
74 	ASSERT(attachmentCount == renderPass->getAttachmentCount());
75 
76 	const uint32_t count = std::min(clearValueCount, attachmentCount);
77 	for(uint32_t i = 0; i < count; i++)
78 	{
79 		const VkAttachmentDescription attachment = renderPass->getAttachment(i);
80 
81 		VkImageAspectFlags aspectMask = Format(attachment.format).getAspects();
82 		if(attachment.loadOp != VK_ATTACHMENT_LOAD_OP_CLEAR)
83 			aspectMask &= VK_IMAGE_ASPECT_STENCIL_BIT;
84 		if(attachment.stencilLoadOp != VK_ATTACHMENT_LOAD_OP_CLEAR)
85 			aspectMask &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
86 
87 		if(!aspectMask || !renderPass->isAttachmentUsed(i))
88 		{
89 			continue;
90 		}
91 
92 		if(renderPass->isMultiView())
93 		{
94 			attachments[i]->clearWithLayerMask(pClearValues[i], aspectMask, renderArea,
95 			                                   renderPass->getAttachmentViewMask(i));
96 		}
97 		else
98 		{
99 			attachments[i]->clear(pClearValues[i], aspectMask, renderArea);
100 		}
101 	}
102 }
103 
clearAttachment(const RenderPass * renderPass,uint32_t subpassIndex,const VkClearAttachment & attachment,const VkClearRect & rect)104 void Framebuffer::clearAttachment(const RenderPass *renderPass, uint32_t subpassIndex, const VkClearAttachment &attachment, const VkClearRect &rect)
105 {
106 	VkSubpassDescription subpass = renderPass->getSubpass(subpassIndex);
107 
108 	if(attachment.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
109 	{
110 		ASSERT(attachment.colorAttachment < subpass.colorAttachmentCount);
111 		uint32_t attachmentIndex = subpass.pColorAttachments[attachment.colorAttachment].attachment;
112 
113 		if(attachmentIndex != VK_ATTACHMENT_UNUSED)
114 		{
115 			ASSERT(attachmentIndex < attachmentCount);
116 			ImageView *imageView = attachments[attachmentIndex];
117 
118 			if(renderPass->isMultiView())
119 			{
120 				imageView->clearWithLayerMask(attachment.clearValue, attachment.aspectMask, rect.rect,
121 				                              renderPass->getViewMask(subpassIndex));
122 			}
123 			else
124 			{
125 				imageView->clear(attachment.clearValue, attachment.aspectMask, rect);
126 			}
127 		}
128 	}
129 	else if(attachment.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
130 	{
131 		uint32_t attachmentIndex = subpass.pDepthStencilAttachment->attachment;
132 
133 		if(attachmentIndex != VK_ATTACHMENT_UNUSED)
134 		{
135 			ASSERT(attachmentIndex < attachmentCount);
136 			ImageView *imageView = attachments[attachmentIndex];
137 
138 			if(renderPass->isMultiView())
139 			{
140 				imageView->clearWithLayerMask(attachment.clearValue, attachment.aspectMask, rect.rect,
141 				                              renderPass->getViewMask(subpassIndex));
142 			}
143 			else
144 			{
145 				imageView->clear(attachment.clearValue, attachment.aspectMask, rect);
146 			}
147 		}
148 	}
149 }
150 
setAttachment(ImageView * imageView,uint32_t index)151 void Framebuffer::setAttachment(ImageView *imageView, uint32_t index)
152 {
153 	ASSERT(index < attachmentCount);
154 	ASSERT(attachments[index] == nullptr);
155 	attachments[index] = imageView;
156 }
157 
getAttachment(uint32_t index) const158 ImageView *Framebuffer::getAttachment(uint32_t index) const
159 {
160 	return attachments[index];
161 }
162 
resolve(const RenderPass * renderPass,uint32_t subpassIndex)163 void Framebuffer::resolve(const RenderPass *renderPass, uint32_t subpassIndex)
164 {
165 	auto const &subpass = renderPass->getSubpass(subpassIndex);
166 	if(subpass.pResolveAttachments)
167 	{
168 		for(uint32_t i = 0; i < subpass.colorAttachmentCount; i++)
169 		{
170 			uint32_t resolveAttachment = subpass.pResolveAttachments[i].attachment;
171 			if(resolveAttachment != VK_ATTACHMENT_UNUSED)
172 			{
173 				ImageView *imageView = attachments[subpass.pColorAttachments[i].attachment];
174 				if(renderPass->isMultiView())
175 				{
176 					imageView->resolveWithLayerMask(attachments[resolveAttachment],
177 					                                renderPass->getViewMask(subpassIndex));
178 				}
179 				else
180 				{
181 					imageView->resolve(attachments[resolveAttachment]);
182 				}
183 			}
184 		}
185 	}
186 }
187 
ComputeRequiredAllocationSize(const VkFramebufferCreateInfo * pCreateInfo)188 size_t Framebuffer::ComputeRequiredAllocationSize(const VkFramebufferCreateInfo *pCreateInfo)
189 {
190 	const VkBaseInStructure *curInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
191 	const VkFramebufferAttachmentsCreateInfo *attachmentsInfo = nullptr;
192 	while(curInfo)
193 	{
194 		switch(curInfo->sType)
195 		{
196 			case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO:
197 				attachmentsInfo = reinterpret_cast<const VkFramebufferAttachmentsCreateInfo *>(curInfo);
198 				break;
199 			default:
200 				LOG_TRAP("pFramebufferCreateInfo->pNext->sType = %s", vk::Stringify(curInfo->sType).c_str());
201 				break;
202 		}
203 
204 		curInfo = curInfo->pNext;
205 	}
206 
207 	if(pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT)
208 	{
209 		ASSERT(attachmentsInfo != nullptr);
210 		return attachmentsInfo->attachmentImageInfoCount * sizeof(void *);
211 	}
212 	else
213 	{
214 		return pCreateInfo->attachmentCount * sizeof(void *);
215 	}
216 }
217 
218 }  // namespace vk
219