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#include "VkImageView.hpp"
17#include "VkRenderPass.hpp"
18#include <algorithm>
19#include <memory.h>
20
21namespace vk
22{
23
24Framebuffer::Framebuffer(const VkFramebufferCreateInfo* pCreateInfo, void* mem) :
25 attachmentCount(pCreateInfo->attachmentCount),
26 attachments(reinterpret_cast<ImageView**>(mem)),
27 extent{pCreateInfo->width, pCreateInfo->height, pCreateInfo->layers}
28{
29 for(uint32_t i = 0; i < attachmentCount; i++)
30 {
31 attachments[i] = vk::Cast(pCreateInfo->pAttachments[i]);
32 }
33}
34
35void Framebuffer::destroy(const VkAllocationCallbacks* pAllocator)
36{
37 vk::deallocate(attachments, pAllocator);
38}
39
40void Framebuffer::clear(const RenderPass* renderPass, uint32_t clearValueCount, const VkClearValue* pClearValues, const VkRect2D& renderArea)
41{
42 ASSERT(attachmentCount == renderPass->getAttachmentCount());
43
44 const uint32_t count = std::min(clearValueCount, attachmentCount);
45 for (uint32_t i = 0; i < count; i++)
46 {
47 const VkAttachmentDescription attachment = renderPass->getAttachment(i);
48
49 VkImageAspectFlags aspectMask = Format(attachment.format).getAspects();
50 if (attachment.loadOp != VK_ATTACHMENT_LOAD_OP_CLEAR)
51 aspectMask &= VK_IMAGE_ASPECT_STENCIL_BIT;
52 if (attachment.stencilLoadOp != VK_ATTACHMENT_LOAD_OP_CLEAR)
53 aspectMask &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
54
55 if (!aspectMask || !renderPass->isAttachmentUsed(i))
56 {
57 continue;
58 }
59
60 if (renderPass->isMultiView())
61 {
62 attachments[i]->clearWithLayerMask(pClearValues[i], aspectMask, renderArea,
63 renderPass->getAttachmentViewMask(i));
64 }
65 else
66 {
67 attachments[i]->clear(pClearValues[i], aspectMask, renderArea);
68 }
69 }
70}
71
72void Framebuffer::clearAttachment(const RenderPass* renderPass, uint32_t subpassIndex, const VkClearAttachment& attachment, const VkClearRect& rect)
73{
74 VkSubpassDescription subpass = renderPass->getSubpass(subpassIndex);
75
76 if (attachment.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
77 {
78 ASSERT(attachment.colorAttachment < subpass.colorAttachmentCount);
79 uint32_t attachmentIndex = subpass.pColorAttachments[attachment.colorAttachment].attachment;
80
81 if (attachmentIndex != VK_ATTACHMENT_UNUSED)
82 {
83 ASSERT(attachmentIndex < attachmentCount);
84 ImageView *imageView = attachments[attachmentIndex];
85
86 if (renderPass->isMultiView())
87 {
88 imageView->clearWithLayerMask(attachment.clearValue, attachment.aspectMask, rect.rect,
89 renderPass->getViewMask(subpassIndex));
90 }
91 else
92 {
93 imageView->clear(attachment.clearValue, attachment.aspectMask, rect);
94 }
95 }
96 }
97 else if (attachment.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
98 {
99 uint32_t attachmentIndex = subpass.pDepthStencilAttachment->attachment;
100
101 if (attachmentIndex != VK_ATTACHMENT_UNUSED)
102 {
103 ASSERT(attachmentIndex < attachmentCount);
104 ImageView *imageView = attachments[attachmentIndex];
105
106 if (renderPass->isMultiView())
107 {
108 imageView->clearWithLayerMask(attachment.clearValue, attachment.aspectMask, rect.rect,
109 renderPass->getViewMask(subpassIndex));
110 }
111 else
112 {
113 imageView->clear(attachment.clearValue, attachment.aspectMask, rect);
114 }
115 }
116 }
117}
118
119ImageView *Framebuffer::getAttachment(uint32_t index) const
120{
121 return attachments[index];
122}
123
124void Framebuffer::resolve(const RenderPass* renderPass, uint32_t subpassIndex)
125{
126 auto const& subpass = renderPass->getSubpass(subpassIndex);
127 if(subpass.pResolveAttachments)
128 {
129 for(uint32_t i = 0; i < subpass.colorAttachmentCount; i++)
130 {
131 uint32_t resolveAttachment = subpass.pResolveAttachments[i].attachment;
132 if(resolveAttachment != VK_ATTACHMENT_UNUSED)
133 {
134 ImageView *imageView = attachments[subpass.pColorAttachments[i].attachment];
135 if (renderPass->isMultiView())
136 {
137 imageView->resolveWithLayerMask(attachments[resolveAttachment],
138 renderPass->getViewMask(subpassIndex));
139 }
140 else
141 {
142 imageView->resolve(attachments[resolveAttachment]);
143 }
144 }
145 }
146 }
147}
148
149size_t Framebuffer::ComputeRequiredAllocationSize(const VkFramebufferCreateInfo* pCreateInfo)
150{
151 return pCreateInfo->attachmentCount * sizeof(void*);
152}
153
154} // namespace vk
155