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