• 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,const std::vector<const amber::Pipeline::BufferInfo * > & resolve_targets,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     const std::vector<const amber::Pipeline::BufferInfo*>& resolve_targets,
34     uint32_t width,
35     uint32_t height)
36     : device_(device),
37       color_attachments_(color_attachments),
38       resolve_targets_(resolve_targets),
39       depth_stencil_attachment_(depth_stencil_attachment),
40       width_(width),
41       height_(height) {}
42 
~FrameBuffer()43 FrameBuffer::~FrameBuffer() {
44   if (frame_ != VK_NULL_HANDLE) {
45     device_->GetPtrs()->vkDestroyFramebuffer(device_->GetVkDevice(), frame_,
46                                              nullptr);
47   }
48 }
49 
Initialize(VkRenderPass render_pass)50 Result FrameBuffer::Initialize(VkRenderPass render_pass) {
51   std::vector<VkImageView> attachments;
52 
53   if (!color_attachments_.empty()) {
54     std::vector<int32_t> seen_idx(color_attachments_.size(), -1);
55     for (auto* info : color_attachments_) {
56       if (info->location >= color_attachments_.size())
57         return Result("color attachment locations must be sequential from 0");
58       if (seen_idx[info->location] != -1) {
59         return Result("duplicate attachment location: " +
60                       std::to_string(info->location));
61       }
62       seen_idx[info->location] = static_cast<int32_t>(info->location);
63     }
64 
65     attachments.resize(color_attachments_.size());
66     for (auto* info : color_attachments_) {
67       const VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
68                                             VK_IMAGE_USAGE_TRANSFER_DST_BIT |
69                                             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
70       color_images_.push_back(MakeUnique<TransferImage>(
71           device_, *info->buffer->GetFormat(), VK_IMAGE_ASPECT_COLOR_BIT,
72           VK_IMAGE_TYPE_2D, usage_flags, width_ << info->base_mip_level,
73           height_ << info->base_mip_level, depth_, info->buffer->GetMipLevels(),
74           info->base_mip_level, 1u, info->buffer->GetSamples()));
75 
76       Result r = color_images_.back()->Initialize();
77       if (!r.IsSuccess())
78         return r;
79 
80       attachments[info->location] = color_images_.back()->GetVkImageView();
81     }
82   }
83 
84   if (depth_stencil_attachment_.buffer &&
85       depth_stencil_attachment_.buffer->GetFormat()->IsFormatKnown()) {
86     VkImageAspectFlags aspect = 0;
87     if (depth_stencil_attachment_.buffer->GetFormat()->HasDepthComponent())
88       aspect |= VK_IMAGE_ASPECT_DEPTH_BIT;
89     if (depth_stencil_attachment_.buffer->GetFormat()->HasStencilComponent())
90       aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
91     assert(aspect != 0);
92 
93     const VkImageUsageFlags usage_flags =
94         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
95         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
96 
97     depth_stencil_image_ = MakeUnique<TransferImage>(
98         device_, *depth_stencil_attachment_.buffer->GetFormat(), aspect,
99         VK_IMAGE_TYPE_2D, usage_flags, width_, height_, depth_, 1u, 0u, 1u, 1u);
100 
101     Result r = depth_stencil_image_->Initialize();
102     if (!r.IsSuccess())
103       return r;
104 
105     attachments.push_back(depth_stencil_image_->GetVkImageView());
106   }
107 
108   for (auto* info : resolve_targets_) {
109     const VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
110                                           VK_IMAGE_USAGE_TRANSFER_DST_BIT |
111                                           VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
112     resolve_images_.push_back(MakeUnique<TransferImage>(
113         device_, *info->buffer->GetFormat(), VK_IMAGE_ASPECT_COLOR_BIT,
114         VK_IMAGE_TYPE_2D, usage_flags, width_, height_, depth_, 1u, 0u, 1u,
115         1u));
116 
117     Result r = resolve_images_.back()->Initialize();
118     if (!r.IsSuccess())
119       return r;
120 
121     attachments.push_back(resolve_images_.back()->GetVkImageView());
122   }
123 
124   VkFramebufferCreateInfo frame_buffer_info = VkFramebufferCreateInfo();
125   frame_buffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
126   frame_buffer_info.renderPass = render_pass;
127   frame_buffer_info.attachmentCount = static_cast<uint32_t>(attachments.size());
128   frame_buffer_info.pAttachments = attachments.data();
129   frame_buffer_info.width = width_;
130   frame_buffer_info.height = height_;
131   frame_buffer_info.layers = 1;
132 
133   if (device_->GetPtrs()->vkCreateFramebuffer(device_->GetVkDevice(),
134                                               &frame_buffer_info, nullptr,
135                                               &frame_) != VK_SUCCESS) {
136     return Result("Vulkan::Calling vkCreateFramebuffer Fail");
137   }
138 
139   return {};
140 }
141 
ChangeFrameLayout(CommandBuffer * command,VkImageLayout color_layout,VkPipelineStageFlags color_stage,VkImageLayout depth_layout,VkPipelineStageFlags depth_stage)142 void FrameBuffer::ChangeFrameLayout(CommandBuffer* command,
143                                     VkImageLayout color_layout,
144                                     VkPipelineStageFlags color_stage,
145                                     VkImageLayout depth_layout,
146                                     VkPipelineStageFlags depth_stage) {
147   for (auto& img : color_images_)
148     img->ImageBarrier(command, color_layout, color_stage);
149 
150   for (auto& img : resolve_images_)
151     img->ImageBarrier(command, color_layout, color_stage);
152 
153   if (depth_stencil_image_)
154     depth_stencil_image_->ImageBarrier(command, depth_layout, depth_stage);
155 }
156 
ChangeFrameToDrawLayout(CommandBuffer * command)157 void FrameBuffer::ChangeFrameToDrawLayout(CommandBuffer* command) {
158   ChangeFrameLayout(command,
159                     // Color attachments
160                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
161                     VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
162                     // Depth attachment
163                     VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
164                     VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
165 }
166 
ChangeFrameToProbeLayout(CommandBuffer * command)167 void FrameBuffer::ChangeFrameToProbeLayout(CommandBuffer* command) {
168   ChangeFrameLayout(
169       command,
170       // Color attachments
171       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
172       // Depth attachments
173       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT);
174 }
175 
ChangeFrameToWriteLayout(CommandBuffer * command)176 void FrameBuffer::ChangeFrameToWriteLayout(CommandBuffer* command) {
177   ChangeFrameLayout(
178       command,
179       // Color attachments
180       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT,
181       // Depth attachments
182       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT);
183 }
184 
TransferImagesToHost(CommandBuffer * command)185 void FrameBuffer::TransferImagesToHost(CommandBuffer* command) {
186   for (auto& img : color_images_)
187     img->CopyToHost(command);
188 
189   for (auto& img : resolve_images_)
190     img->CopyToHost(command);
191 
192   if (depth_stencil_image_)
193     depth_stencil_image_->CopyToHost(command);
194 }
195 
CopyImagesToBuffers()196 void FrameBuffer::CopyImagesToBuffers() {
197   for (size_t i = 0; i < color_images_.size(); ++i) {
198     auto& img = color_images_[i];
199     auto* info = color_attachments_[i];
200     auto* values = info->buffer->ValuePtr();
201     values->resize(info->buffer->GetSizeInBytes());
202     std::memcpy(values->data(), img->HostAccessibleMemoryPtr(),
203                 info->buffer->GetSizeInBytes());
204   }
205 
206   for (size_t i = 0; i < resolve_images_.size(); ++i) {
207     auto& img = resolve_images_[i];
208     auto* info = resolve_targets_[i];
209     auto* values = info->buffer->ValuePtr();
210     values->resize(info->buffer->GetSizeInBytes());
211     std::memcpy(values->data(), img->HostAccessibleMemoryPtr(),
212                 info->buffer->GetSizeInBytes());
213   }
214 
215   if (depth_stencil_image_) {
216     auto* values = depth_stencil_attachment_.buffer->ValuePtr();
217     values->resize(depth_stencil_attachment_.buffer->GetSizeInBytes());
218     std::memcpy(values->data(), depth_stencil_image_->HostAccessibleMemoryPtr(),
219                 depth_stencil_attachment_.buffer->GetSizeInBytes());
220   }
221 }
222 
TransferImagesToDevice(CommandBuffer * command)223 void FrameBuffer::TransferImagesToDevice(CommandBuffer* command) {
224   for (auto& img : color_images_)
225     img->CopyToDevice(command);
226 
227   if (depth_stencil_image_)
228     depth_stencil_image_->CopyToDevice(command);
229 }
230 
CopyBuffersToImages()231 void FrameBuffer::CopyBuffersToImages() {
232   for (size_t i = 0; i < color_images_.size(); ++i) {
233     auto& img = color_images_[i];
234     auto* info = color_attachments_[i];
235     auto* values = info->buffer->ValuePtr();
236     // Nothing to do if our local buffer is empty
237     if (values->empty())
238       continue;
239 
240     std::memcpy(img->HostAccessibleMemoryPtr(), values->data(),
241                 info->buffer->GetSizeInBytes());
242   }
243 
244   for (size_t i = 0; i < resolve_images_.size(); ++i) {
245     auto& img = resolve_images_[i];
246     auto* info = resolve_targets_[i];
247     auto* values = info->buffer->ValuePtr();
248     // Nothing to do if our local buffer is empty
249     if (values->empty())
250       continue;
251 
252     std::memcpy(img->HostAccessibleMemoryPtr(), values->data(),
253                 info->buffer->GetSizeInBytes());
254   }
255 
256   if (depth_stencil_image_) {
257     auto* values = depth_stencil_attachment_.buffer->ValuePtr();
258     // Nothing to do if our local buffer is empty
259     if (!values->empty()) {
260       std::memcpy(depth_stencil_image_->HostAccessibleMemoryPtr(),
261                   values->data(),
262                   depth_stencil_attachment_.buffer->GetSizeInBytes());
263     }
264   }
265 }
266 
267 }  // namespace vulkan
268 }  // namespace amber
269