• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 		case VK_STRUCTURE_TYPE_MAX_ENUM:
40 			// dEQP tests that this value is ignored.
41 			break;
42 		default:
43 			UNSUPPORTED("pFramebufferCreateInfo->pNext->sType = %s", vk::Stringify(curInfo->sType).c_str());
44 			break;
45 		}
46 		curInfo = curInfo->pNext;
47 	}
48 
49 	if(pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT)
50 	{
51 		// If flags includes VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, the pNext chain **must**
52 		// include a VkFramebufferAttachmentsCreateInfo.
53 		ASSERT(attachmentsCreateInfo != nullptr);
54 		attachmentCount = attachmentsCreateInfo->attachmentImageInfoCount;
55 		for(uint32_t i = 0; i < attachmentCount; i++)
56 		{
57 			attachments[i] = nullptr;
58 		}
59 	}
60 	else
61 	{
62 		attachmentCount = pCreateInfo->attachmentCount;
63 		for(uint32_t i = 0; i < attachmentCount; i++)
64 		{
65 			attachments[i] = vk::Cast(pCreateInfo->pAttachments[i]);
66 		}
67 	}
68 }
69 
destroy(const VkAllocationCallbacks * pAllocator)70 void Framebuffer::destroy(const VkAllocationCallbacks *pAllocator)
71 {
72 	vk::freeHostMemory(attachments, pAllocator);
73 }
74 
executeLoadOp(const RenderPass * renderPass,uint32_t clearValueCount,const VkClearValue * pClearValues,const VkRect2D & renderArea)75 void Framebuffer::executeLoadOp(const RenderPass *renderPass, uint32_t clearValueCount, const VkClearValue *pClearValues, const VkRect2D &renderArea)
76 {
77 	// This gets called at the start of a renderpass. Logically the `loadOp` gets executed at the
78 	// subpass where an attachment is first used, but since we don't discard contents between subpasses,
79 	// we can execute it sooner. Only clear operations have an effect.
80 
81 	ASSERT(attachmentCount == renderPass->getAttachmentCount());
82 
83 	const uint32_t count = std::min(clearValueCount, attachmentCount);
84 	for(uint32_t i = 0; i < count; i++)
85 	{
86 		const VkAttachmentDescription attachment = renderPass->getAttachment(i);
87 		VkImageAspectFlags clearMask = 0;
88 
89 		switch(attachment.loadOp)
90 		{
91 		case VK_ATTACHMENT_LOAD_OP_CLEAR:
92 			clearMask |= VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
93 			break;
94 		case VK_ATTACHMENT_LOAD_OP_LOAD:
95 		case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
96 		case VK_ATTACHMENT_LOAD_OP_NONE_EXT:
97 			// Don't clear the attachment's color or depth aspect.
98 			break;
99 		default:
100 			UNSUPPORTED("attachment.loadOp %d", attachment.loadOp);
101 		}
102 
103 		switch(attachment.stencilLoadOp)
104 		{
105 		case VK_ATTACHMENT_LOAD_OP_CLEAR:
106 			clearMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
107 			break;
108 		case VK_ATTACHMENT_LOAD_OP_LOAD:
109 		case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
110 		case VK_ATTACHMENT_LOAD_OP_NONE_EXT:
111 			// Don't clear the attachment's stencil aspect.
112 			break;
113 		default:
114 			UNSUPPORTED("attachment.stencilLoadOp %d", attachment.stencilLoadOp);
115 		}
116 
117 		// Image::clear() demands that we only specify existing aspects.
118 		clearMask &= Format(attachment.format).getAspects();
119 
120 		if(!clearMask || !renderPass->isAttachmentUsed(i))
121 		{
122 			continue;
123 		}
124 
125 		if(renderPass->isMultiView())
126 		{
127 			attachments[i]->clearWithLayerMask(pClearValues[i], clearMask, renderArea,
128 			                                   renderPass->getAttachmentViewMask(i));
129 		}
130 		else
131 		{
132 			attachments[i]->clear(pClearValues[i], clearMask, renderArea);
133 		}
134 	}
135 }
136 
clearAttachment(const RenderPass * renderPass,uint32_t subpassIndex,const VkClearAttachment & attachment,const VkClearRect & rect)137 void Framebuffer::clearAttachment(const RenderPass *renderPass, uint32_t subpassIndex, const VkClearAttachment &attachment, const VkClearRect &rect)
138 {
139 	VkSubpassDescription subpass = renderPass->getSubpass(subpassIndex);
140 
141 	if(attachment.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
142 	{
143 		ASSERT(attachment.colorAttachment < subpass.colorAttachmentCount);
144 		uint32_t attachmentIndex = subpass.pColorAttachments[attachment.colorAttachment].attachment;
145 
146 		if(attachmentIndex != VK_ATTACHMENT_UNUSED)
147 		{
148 			ASSERT(attachmentIndex < attachmentCount);
149 			ImageView *imageView = attachments[attachmentIndex];
150 
151 			if(renderPass->isMultiView())
152 			{
153 				imageView->clearWithLayerMask(attachment.clearValue, attachment.aspectMask, rect.rect,
154 				                              renderPass->getViewMask(subpassIndex));
155 			}
156 			else
157 			{
158 				imageView->clear(attachment.clearValue, attachment.aspectMask, rect);
159 			}
160 		}
161 	}
162 	else if(attachment.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
163 	{
164 		uint32_t attachmentIndex = subpass.pDepthStencilAttachment->attachment;
165 
166 		if(attachmentIndex != VK_ATTACHMENT_UNUSED)
167 		{
168 			ASSERT(attachmentIndex < attachmentCount);
169 			ImageView *imageView = attachments[attachmentIndex];
170 
171 			if(renderPass->isMultiView())
172 			{
173 				imageView->clearWithLayerMask(attachment.clearValue, attachment.aspectMask, rect.rect,
174 				                              renderPass->getViewMask(subpassIndex));
175 			}
176 			else
177 			{
178 				imageView->clear(attachment.clearValue, attachment.aspectMask, rect);
179 			}
180 		}
181 	}
182 	else
183 		UNSUPPORTED("attachment.aspectMask %X", attachment.aspectMask);
184 }
185 
setAttachment(ImageView * imageView,uint32_t index)186 void Framebuffer::setAttachment(ImageView *imageView, uint32_t index)
187 {
188 	ASSERT(index < attachmentCount);
189 	ASSERT(attachments[index] == nullptr);
190 	attachments[index] = imageView;
191 }
192 
getAttachment(uint32_t index) const193 ImageView *Framebuffer::getAttachment(uint32_t index) const
194 {
195 	return attachments[index];
196 }
197 
resolve(const RenderPass * renderPass,uint32_t subpassIndex)198 void Framebuffer::resolve(const RenderPass *renderPass, uint32_t subpassIndex)
199 {
200 	auto const &subpass = renderPass->getSubpass(subpassIndex);
201 	if(subpass.pResolveAttachments)
202 	{
203 		for(uint32_t i = 0; i < subpass.colorAttachmentCount; i++)
204 		{
205 			uint32_t resolveAttachment = subpass.pResolveAttachments[i].attachment;
206 			if(resolveAttachment != VK_ATTACHMENT_UNUSED)
207 			{
208 				ImageView *imageView = attachments[subpass.pColorAttachments[i].attachment];
209 				if(renderPass->isMultiView())
210 				{
211 					imageView->resolveWithLayerMask(attachments[resolveAttachment],
212 					                                renderPass->getViewMask(subpassIndex));
213 				}
214 				else
215 				{
216 					imageView->resolve(attachments[resolveAttachment]);
217 				}
218 			}
219 		}
220 	}
221 
222 	if(renderPass->hasDepthStencilResolve() && subpass.pDepthStencilAttachment != nullptr)
223 	{
224 		VkSubpassDescriptionDepthStencilResolve dsResolve = renderPass->getSubpassDepthStencilResolve(subpassIndex);
225 		uint32_t depthStencilAttachment = subpass.pDepthStencilAttachment->attachment;
226 		if(depthStencilAttachment != VK_ATTACHMENT_UNUSED)
227 		{
228 			ImageView *imageView = attachments[depthStencilAttachment];
229 			imageView->resolveDepthStencil(attachments[dsResolve.pDepthStencilResolveAttachment->attachment], dsResolve);
230 		}
231 	}
232 }
233 
ComputeRequiredAllocationSize(const VkFramebufferCreateInfo * pCreateInfo)234 size_t Framebuffer::ComputeRequiredAllocationSize(const VkFramebufferCreateInfo *pCreateInfo)
235 {
236 	const VkBaseInStructure *curInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
237 	const VkFramebufferAttachmentsCreateInfo *attachmentsInfo = nullptr;
238 	while(curInfo)
239 	{
240 		switch(curInfo->sType)
241 		{
242 		case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO:
243 			attachmentsInfo = reinterpret_cast<const VkFramebufferAttachmentsCreateInfo *>(curInfo);
244 			break;
245 		case VK_STRUCTURE_TYPE_MAX_ENUM:
246 			// dEQP tests that this value is ignored.
247 			break;
248 		default:
249 			UNSUPPORTED("pFramebufferCreateInfo->pNext->sType = %s", vk::Stringify(curInfo->sType).c_str());
250 			break;
251 		}
252 
253 		curInfo = curInfo->pNext;
254 	}
255 
256 	if(pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT)
257 	{
258 		ASSERT(attachmentsInfo != nullptr);
259 		return attachmentsInfo->attachmentImageInfoCount * sizeof(void *);
260 	}
261 	else
262 	{
263 		return pCreateInfo->attachmentCount * sizeof(void *);
264 	}
265 }
266 
267 }  // namespace vk
268