• 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,uint32_t width,uint32_t height)29 FrameBuffer::FrameBuffer(
30     Device* device,
31     const std::vector<const amber::Pipeline::BufferInfo*>& color_attachments,
32     uint32_t width,
33     uint32_t height)
34     : device_(device),
35       color_attachments_(color_attachments),
36       width_(width),
37       height_(height) {}
38 
~FrameBuffer()39 FrameBuffer::~FrameBuffer() {
40   if (frame_ != VK_NULL_HANDLE) {
41     device_->GetPtrs()->vkDestroyFramebuffer(device_->GetVkDevice(), frame_,
42                                              nullptr);
43   }
44 }
45 
Initialize(VkRenderPass render_pass,const Format * depth_format)46 Result FrameBuffer::Initialize(VkRenderPass render_pass,
47                                const Format* depth_format) {
48   std::vector<VkImageView> attachments;
49 
50   if (!color_attachments_.empty()) {
51     std::vector<int32_t> seen_idx(color_attachments_.size(), -1);
52     for (auto* info : color_attachments_) {
53       if (info->location >= color_attachments_.size())
54         return Result("color attachment locations must be sequential from 0");
55       if (seen_idx[info->location] != -1) {
56         return Result("duplicate attachment location: " +
57                       std::to_string(info->location));
58       }
59       seen_idx[info->location] = static_cast<int32_t>(info->location);
60     }
61 
62     attachments.resize(color_attachments_.size());
63     for (auto* info : color_attachments_) {
64       color_images_.push_back(MakeUnique<TransferImage>(
65           device_, *info->buffer->GetFormat(), VK_IMAGE_ASPECT_COLOR_BIT,
66           width_, height_, depth_));
67 
68       Result r = color_images_.back()->Initialize(
69           VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
70           VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
71       if (!r.IsSuccess())
72         return r;
73 
74       attachments[info->location] = color_images_.back()->GetVkImageView();
75     }
76   }
77 
78   if (depth_format && depth_format->IsFormatKnown()) {
79     depth_image_ = MakeUnique<TransferImage>(
80         device_, *depth_format,
81         static_cast<VkImageAspectFlags>(depth_format->HasStencilComponent()
82                                             ? VK_IMAGE_ASPECT_DEPTH_BIT |
83                                                   VK_IMAGE_ASPECT_STENCIL_BIT
84                                             : VK_IMAGE_ASPECT_DEPTH_BIT),
85         width_, height_, depth_);
86 
87     Result r = depth_image_->Initialize(
88         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
89         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
90     if (!r.IsSuccess())
91       return r;
92 
93     attachments.push_back(depth_image_->GetVkImageView());
94   }
95 
96   VkFramebufferCreateInfo frame_buffer_info = VkFramebufferCreateInfo();
97   frame_buffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
98   frame_buffer_info.renderPass = render_pass;
99   frame_buffer_info.attachmentCount = static_cast<uint32_t>(attachments.size());
100   frame_buffer_info.pAttachments = attachments.data();
101   frame_buffer_info.width = width_;
102   frame_buffer_info.height = height_;
103   frame_buffer_info.layers = 1;
104 
105   if (device_->GetPtrs()->vkCreateFramebuffer(device_->GetVkDevice(),
106                                               &frame_buffer_info, nullptr,
107                                               &frame_) != VK_SUCCESS) {
108     return Result("Vulkan::Calling vkCreateFramebuffer Fail");
109   }
110 
111   return {};
112 }
113 
ChangeFrameLayout(CommandBuffer * command,VkImageLayout color_layout,VkPipelineStageFlags color_stage,VkImageLayout depth_layout,VkPipelineStageFlags depth_stage)114 void FrameBuffer::ChangeFrameLayout(CommandBuffer* command,
115                                     VkImageLayout color_layout,
116                                     VkPipelineStageFlags color_stage,
117                                     VkImageLayout depth_layout,
118                                     VkPipelineStageFlags depth_stage) {
119   for (auto& img : color_images_)
120     img->ImageBarrier(command, color_layout, color_stage);
121 
122   if (depth_image_)
123     depth_image_->ImageBarrier(command, depth_layout, depth_stage);
124 }
125 
ChangeFrameToDrawLayout(CommandBuffer * command)126 void FrameBuffer::ChangeFrameToDrawLayout(CommandBuffer* command) {
127   ChangeFrameLayout(command,
128                     // Color attachments
129                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
130                     VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
131                     // Depth attachment
132                     VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
133                     VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
134 }
135 
ChangeFrameToProbeLayout(CommandBuffer * command)136 void FrameBuffer::ChangeFrameToProbeLayout(CommandBuffer* command) {
137   ChangeFrameLayout(
138       command,
139       // Color attachments
140       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
141       // Depth attachments
142       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT);
143 }
144 
ChangeFrameToWriteLayout(CommandBuffer * command)145 void FrameBuffer::ChangeFrameToWriteLayout(CommandBuffer* command) {
146   ChangeFrameLayout(
147       command,
148       // Color attachments
149       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
150       // Depth attachments
151       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT);
152 }
153 
TransferColorImagesToHost(CommandBuffer * command)154 void FrameBuffer::TransferColorImagesToHost(CommandBuffer* command) {
155   for (auto& img : color_images_)
156     img->CopyToHost(command);
157 }
158 
CopyImagesToBuffers()159 void FrameBuffer::CopyImagesToBuffers() {
160   for (size_t i = 0; i < color_images_.size(); ++i) {
161     auto& img = color_images_[i];
162     auto* info = color_attachments_[i];
163     auto* values = info->buffer->ValuePtr();
164     values->resize(info->buffer->GetSizeInBytes());
165     std::memcpy(values->data(), img->HostAccessibleMemoryPtr(),
166                 info->buffer->GetSizeInBytes());
167   }
168 }
169 
TransferColorImagesToDevice(CommandBuffer * command)170 void FrameBuffer::TransferColorImagesToDevice(CommandBuffer* command) {
171   for (auto& img : color_images_)
172     img->CopyToDevice(command);
173 }
174 
CopyBuffersToImages()175 void FrameBuffer::CopyBuffersToImages() {
176   for (size_t i = 0; i < color_images_.size(); ++i) {
177     auto& img = color_images_[i];
178     auto* info = color_attachments_[i];
179     auto* values = info->buffer->ValuePtr();
180     // Nothing to do if our local buffer is empty
181     if (values->empty())
182       continue;
183 
184     std::memcpy(img->HostAccessibleMemoryPtr(), values->data(),
185                 info->buffer->GetSizeInBytes());
186   }
187 }
188 
189 }  // namespace vulkan
190 }  // namespace amber
191