• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Amber Authors.
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 "src/vulkan/frame_buffer.h"
16 
17 #include <algorithm>
18 #include <cstring>
19 #include <limits>
20 #include <vector>
21 
22 #include "src/make_unique.h"
23 #include "src/vulkan/command_buffer.h"
24 #include "src/vulkan/device.h"
25 
26 namespace amber {
27 namespace vulkan {
28 
FrameBuffer(Device * device,const std::vector<const amber::Pipeline::BufferInfo * > & color_attachments,amber::Pipeline::BufferInfo depth_stencil_attachment,uint32_t width,uint32_t height)29 FrameBuffer::FrameBuffer(
30     Device* device,
31     const std::vector<const amber::Pipeline::BufferInfo*>& color_attachments,
32     amber::Pipeline::BufferInfo depth_stencil_attachment,
33     uint32_t width,
34     uint32_t height)
35     : device_(device),
36       color_attachments_(color_attachments),
37       depth_stencil_attachment_(depth_stencil_attachment),
38       width_(width),
39       height_(height) {}
40 
~FrameBuffer()41 FrameBuffer::~FrameBuffer() {
42   if (frame_ != VK_NULL_HANDLE) {
43     device_->GetPtrs()->vkDestroyFramebuffer(device_->GetVkDevice(), frame_,
44                                              nullptr);
45   }
46 }
47 
Initialize(VkRenderPass render_pass)48 Result FrameBuffer::Initialize(VkRenderPass render_pass) {
49   std::vector<VkImageView> attachments;
50 
51   if (!color_attachments_.empty()) {
52     std::vector<int32_t> seen_idx(color_attachments_.size(), -1);
53     for (auto* info : color_attachments_) {
54       if (info->location >= color_attachments_.size())
55         return Result("color attachment locations must be sequential from 0");
56       if (seen_idx[info->location] != -1) {
57         return Result("duplicate attachment location: " +
58                       std::to_string(info->location));
59       }
60       seen_idx[info->location] = static_cast<int32_t>(info->location);
61     }
62 
63     attachments.resize(color_attachments_.size());
64     for (auto* info : color_attachments_) {
65       color_images_.push_back(MakeUnique<TransferImage>(
66           device_, *info->buffer->GetFormat(), VK_IMAGE_ASPECT_COLOR_BIT,
67           VK_IMAGE_TYPE_2D, width_ << info->base_mip_level,
68           height_ << info->base_mip_level, depth_, info->buffer->GetMipLevels(),
69           info->base_mip_level, 1u, 1u));
70 
71       Result r = color_images_.back()->Initialize(
72           VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
73           VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
74       if (!r.IsSuccess())
75         return r;
76 
77       attachments[info->location] = color_images_.back()->GetVkImageView();
78     }
79   }
80 
81   if (depth_stencil_attachment_.buffer &&
82       depth_stencil_attachment_.buffer->GetFormat()->IsFormatKnown()) {
83     VkImageAspectFlags aspect = 0;
84     if (depth_stencil_attachment_.buffer->GetFormat()->HasDepthComponent())
85       aspect |= VK_IMAGE_ASPECT_DEPTH_BIT;
86     if (depth_stencil_attachment_.buffer->GetFormat()->HasStencilComponent())
87       aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
88     assert(aspect != 0);
89 
90     depth_stencil_image_ = MakeUnique<TransferImage>(
91         device_, *depth_stencil_attachment_.buffer->GetFormat(), aspect,
92         VK_IMAGE_TYPE_2D, width_, height_, depth_, 1u, 0u, 1u, 1u);
93 
94     Result r = depth_stencil_image_->Initialize(
95         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
96         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
97     if (!r.IsSuccess())
98       return r;
99 
100     attachments.push_back(depth_stencil_image_->GetVkImageView());
101   }
102 
103   VkFramebufferCreateInfo frame_buffer_info = VkFramebufferCreateInfo();
104   frame_buffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
105   frame_buffer_info.renderPass = render_pass;
106   frame_buffer_info.attachmentCount = static_cast<uint32_t>(attachments.size());
107   frame_buffer_info.pAttachments = attachments.data();
108   frame_buffer_info.width = width_;
109   frame_buffer_info.height = height_;
110   frame_buffer_info.layers = 1;
111 
112   if (device_->GetPtrs()->vkCreateFramebuffer(device_->GetVkDevice(),
113                                               &frame_buffer_info, nullptr,
114                                               &frame_) != VK_SUCCESS) {
115     return Result("Vulkan::Calling vkCreateFramebuffer Fail");
116   }
117 
118   return {};
119 }
120 
ChangeFrameLayout(CommandBuffer * command,VkImageLayout color_layout,VkPipelineStageFlags color_stage,VkImageLayout depth_layout,VkPipelineStageFlags depth_stage)121 void FrameBuffer::ChangeFrameLayout(CommandBuffer* command,
122                                     VkImageLayout color_layout,
123                                     VkPipelineStageFlags color_stage,
124                                     VkImageLayout depth_layout,
125                                     VkPipelineStageFlags depth_stage) {
126   for (auto& img : color_images_)
127     img->ImageBarrier(command, color_layout, color_stage);
128 
129   if (depth_stencil_image_)
130     depth_stencil_image_->ImageBarrier(command, depth_layout, depth_stage);
131 }
132 
ChangeFrameToDrawLayout(CommandBuffer * command)133 void FrameBuffer::ChangeFrameToDrawLayout(CommandBuffer* command) {
134   ChangeFrameLayout(command,
135                     // Color attachments
136                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
137                     VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
138                     // Depth attachment
139                     VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
140                     VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
141 }
142 
ChangeFrameToProbeLayout(CommandBuffer * command)143 void FrameBuffer::ChangeFrameToProbeLayout(CommandBuffer* command) {
144   ChangeFrameLayout(
145       command,
146       // Color attachments
147       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
148       // Depth attachments
149       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT);
150 }
151 
ChangeFrameToWriteLayout(CommandBuffer * command)152 void FrameBuffer::ChangeFrameToWriteLayout(CommandBuffer* command) {
153   ChangeFrameLayout(
154       command,
155       // Color attachments
156       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
157       // Depth attachments
158       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT);
159 }
160 
TransferImagesToHost(CommandBuffer * command)161 void FrameBuffer::TransferImagesToHost(CommandBuffer* command) {
162   for (auto& img : color_images_)
163     img->CopyToHost(command);
164 
165   if (depth_stencil_image_)
166     depth_stencil_image_->CopyToHost(command);
167 }
168 
CopyImagesToBuffers()169 void FrameBuffer::CopyImagesToBuffers() {
170   for (size_t i = 0; i < color_images_.size(); ++i) {
171     auto& img = color_images_[i];
172     auto* info = color_attachments_[i];
173     auto* values = info->buffer->ValuePtr();
174     values->resize(info->buffer->GetSizeInBytes());
175     std::memcpy(values->data(), img->HostAccessibleMemoryPtr(),
176                 info->buffer->GetSizeInBytes());
177   }
178 
179   if (depth_stencil_image_) {
180     auto* values = depth_stencil_attachment_.buffer->ValuePtr();
181     values->resize(depth_stencil_attachment_.buffer->GetSizeInBytes());
182     std::memcpy(values->data(), depth_stencil_image_->HostAccessibleMemoryPtr(),
183                 depth_stencil_attachment_.buffer->GetSizeInBytes());
184   }
185 }
186 
TransferImagesToDevice(CommandBuffer * command)187 void FrameBuffer::TransferImagesToDevice(CommandBuffer* command) {
188   for (auto& img : color_images_)
189     img->CopyToDevice(command);
190 
191   if (depth_stencil_image_)
192     depth_stencil_image_->CopyToDevice(command);
193 }
194 
CopyBuffersToImages()195 void FrameBuffer::CopyBuffersToImages() {
196   for (size_t i = 0; i < color_images_.size(); ++i) {
197     auto& img = color_images_[i];
198     auto* info = color_attachments_[i];
199     auto* values = info->buffer->ValuePtr();
200     // Nothing to do if our local buffer is empty
201     if (values->empty())
202       continue;
203 
204     std::memcpy(img->HostAccessibleMemoryPtr(), values->data(),
205                 info->buffer->GetSizeInBytes());
206   }
207 
208   if (depth_stencil_image_) {
209     auto* values = depth_stencil_attachment_.buffer->ValuePtr();
210     // Nothing to do if our local buffer is empty
211     if (!values->empty()) {
212       std::memcpy(depth_stencil_image_->HostAccessibleMemoryPtr(),
213                   values->data(),
214                   depth_stencil_attachment_.buffer->GetSizeInBytes());
215     }
216   }
217 }
218 
219 }  // namespace vulkan
220 }  // namespace amber
221