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 "Device/Surface.hpp"
19 #include <algorithm>
20 #include <memory.h>
21
22 namespace vk
23 {
24
Framebuffer(const VkFramebufferCreateInfo * pCreateInfo,void * mem)25 Framebuffer::Framebuffer(const VkFramebufferCreateInfo* pCreateInfo, void* mem) :
26 renderPass(Cast(pCreateInfo->renderPass)),
27 attachmentCount(pCreateInfo->attachmentCount),
28 attachments(reinterpret_cast<ImageView**>(mem))
29 {
30 for(uint32_t i = 0; i < attachmentCount; i++)
31 {
32 attachments[i] = Cast(pCreateInfo->pAttachments[i]);
33 }
34 }
35
destroy(const VkAllocationCallbacks * pAllocator)36 void Framebuffer::destroy(const VkAllocationCallbacks* pAllocator)
37 {
38 vk::deallocate(attachments, pAllocator);
39 }
40
clear(uint32_t clearValueCount,const VkClearValue * pClearValues,const VkRect2D & renderArea)41 void Framebuffer::clear(uint32_t clearValueCount, const VkClearValue* pClearValues, const VkRect2D& renderArea)
42 {
43 ASSERT(attachmentCount == renderPass->getAttachmentCount());
44
45 const uint32_t count = std::min(clearValueCount, attachmentCount);
46 for(uint32_t i = 0; i < count; i++)
47 {
48 const VkAttachmentDescription attachment = renderPass->getAttachment(i);
49 bool isDepth = sw::Surface::isDepth(attachment.format);
50 bool isStencil = sw::Surface::isStencil(attachment.format);
51
52 if(isDepth || isStencil)
53 {
54 bool clearDepth = (isDepth && (attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR));
55 bool clearStencil = (isStencil && (attachment.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR));
56
57 if(clearDepth || clearStencil)
58 {
59 attachments[i]->clear(pClearValues[i],
60 (clearDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) |
61 (clearStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : 0),
62 renderArea);
63 }
64 }
65 else if(attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
66 {
67 attachments[i]->clear(pClearValues[i], VK_IMAGE_ASPECT_COLOR_BIT, renderArea);
68 }
69 }
70 }
71
clear(const VkClearAttachment & attachment,const VkClearRect & rect)72 void Framebuffer::clear(const VkClearAttachment& attachment, const VkClearRect& rect)
73 {
74 if(attachment.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
75 {
76 if(attachment.colorAttachment != VK_ATTACHMENT_UNUSED)
77 {
78 VkSubpassDescription subpass = renderPass->getCurrentSubpass();
79
80 ASSERT(attachment.colorAttachment < subpass.colorAttachmentCount);
81 ASSERT(subpass.pColorAttachments[attachment.colorAttachment].attachment < attachmentCount);
82
83 attachments[subpass.pColorAttachments[attachment.colorAttachment].attachment]->clear(
84 attachment.clearValue, attachment.aspectMask, rect);
85 }
86 }
87 else if(attachment.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
88 {
89 VkSubpassDescription subpass = renderPass->getCurrentSubpass();
90
91 ASSERT(subpass.pDepthStencilAttachment->attachment < attachmentCount);
92
93 attachments[subpass.pDepthStencilAttachment->attachment]->clear(attachment.clearValue, attachment.aspectMask, rect);
94 }
95 }
96
ComputeRequiredAllocationSize(const VkFramebufferCreateInfo * pCreateInfo)97 size_t Framebuffer::ComputeRequiredAllocationSize(const VkFramebufferCreateInfo* pCreateInfo)
98 {
99 return pCreateInfo->attachmentCount * sizeof(void*);
100 }
101
102 } // namespace vk