• 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/buffer_descriptor.h"
16 
17 #include <algorithm>
18 #include <cassert>
19 #include <cstring>
20 #include <utility>
21 #include <vector>
22 
23 #include "src/engine.h"
24 #include "src/make_unique.h"
25 #include "src/vulkan/command_buffer.h"
26 #include "src/vulkan/device.h"
27 
28 namespace amber {
29 namespace vulkan {
30 
BufferDescriptor(Buffer * buffer,DescriptorType type,Device * device,uint32_t desc_set,uint32_t binding)31 BufferDescriptor::BufferDescriptor(Buffer* buffer,
32                                    DescriptorType type,
33                                    Device* device,
34                                    uint32_t desc_set,
35                                    uint32_t binding)
36     : device_(device),
37       amber_buffer_(buffer),
38       type_(type),
39       descriptor_set_(desc_set),
40       binding_(binding) {}
41 
42 BufferDescriptor::~BufferDescriptor() = default;
43 
CreateResourceIfNeeded()44 Result BufferDescriptor::CreateResourceIfNeeded() {
45   if (transfer_buffer_) {
46     return Result(
47         "Vulkan: BufferDescriptor::CreateResourceIfNeeded() must be called "
48         "only when |transfer_buffer| is empty");
49   }
50 
51   if (amber_buffer_ && amber_buffer_->ValuePtr()->empty())
52     return {};
53 
54   uint32_t size_in_bytes =
55       amber_buffer_ ? static_cast<uint32_t>(amber_buffer_->ValuePtr()->size())
56                     : 0;
57   transfer_buffer_ = MakeUnique<TransferBuffer>(device_, size_in_bytes);
58 
59   Result r = transfer_buffer_->Initialize(
60       (IsStorageBuffer() ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
61                          : VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) |
62       VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
63   if (!r.IsSuccess())
64     return r;
65 
66   is_descriptor_set_update_needed_ = true;
67   return {};
68 }
69 
RecordCopyDataToResourceIfNeeded(CommandBuffer * command)70 void BufferDescriptor::RecordCopyDataToResourceIfNeeded(
71     CommandBuffer* command) {
72   if (!transfer_buffer_)
73     return;
74 
75   if (amber_buffer_ && !amber_buffer_->ValuePtr()->empty()) {
76     transfer_buffer_->UpdateMemoryWithRawData(*amber_buffer_->ValuePtr());
77     amber_buffer_->ValuePtr()->clear();
78   }
79 
80   transfer_buffer_->CopyToDevice(command);
81 }
82 
RecordCopyDataToHost(CommandBuffer * command)83 Result BufferDescriptor::RecordCopyDataToHost(CommandBuffer* command) {
84   if (!transfer_buffer_) {
85     return Result(
86         "Vulkan: BufferDescriptor::RecordCopyDataToHost() no transfer buffer");
87   }
88 
89   transfer_buffer_->CopyToHost(command);
90   return {};
91 }
92 
MoveResourceToBufferOutput()93 Result BufferDescriptor::MoveResourceToBufferOutput() {
94   if (!transfer_buffer_) {
95     return Result(
96         "Vulkan: BufferDescriptor::MoveResourceToBufferOutput() no transfer"
97         " buffer");
98   }
99 
100   // Only need to copy the buffer back if we have an attached amber buffer to
101   // write too.
102   if (amber_buffer_) {
103     void* resource_memory_ptr = transfer_buffer_->HostAccessibleMemoryPtr();
104     if (!resource_memory_ptr) {
105       return Result(
106           "Vulkan: BufferDescriptor::MoveResourceToBufferOutput() "
107           "no host accessible memory pointer");
108     }
109 
110     if (!amber_buffer_->ValuePtr()->empty()) {
111       return Result(
112           "Vulkan: BufferDescriptor::MoveResourceToBufferOutput() "
113           "output buffer is not empty");
114     }
115 
116     auto size_in_bytes = transfer_buffer_->GetSizeInBytes();
117     amber_buffer_->SetElementCount(size_in_bytes /
118                                    amber_buffer_->GetFormat()->SizeInBytes());
119     amber_buffer_->ValuePtr()->resize(size_in_bytes);
120     std::memcpy(amber_buffer_->ValuePtr()->data(), resource_memory_ptr,
121                 size_in_bytes);
122   }
123 
124   transfer_buffer_ = nullptr;
125   return {};
126 }
127 
UpdateDescriptorSetIfNeeded(VkDescriptorSet descriptor_set)128 void BufferDescriptor::UpdateDescriptorSetIfNeeded(
129     VkDescriptorSet descriptor_set) {
130   if (!is_descriptor_set_update_needed_)
131     return;
132 
133   VkDescriptorBufferInfo buffer_info = VkDescriptorBufferInfo();
134   buffer_info.buffer = transfer_buffer_->GetVkBuffer();
135   buffer_info.offset = 0;
136   buffer_info.range = VK_WHOLE_SIZE;
137 
138   VkWriteDescriptorSet write = VkWriteDescriptorSet();
139   write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
140   write.dstSet = descriptor_set;
141   write.dstBinding = binding_;
142   write.dstArrayElement = 0;
143   write.descriptorCount = 1;
144   write.descriptorType = IsStorageBuffer() ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
145                                            : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
146   write.pBufferInfo = &buffer_info;
147 
148   device_->GetPtrs()->vkUpdateDescriptorSets(device_->GetVkDevice(), 1, &write,
149                                              0, nullptr);
150   is_descriptor_set_update_needed_ = false;
151 }
152 
SetSizeInElements(uint32_t element_count)153 Result BufferDescriptor::SetSizeInElements(uint32_t element_count) {
154   if (!amber_buffer_)
155     return Result("missing amber_buffer for SetSizeInElements call");
156 
157   amber_buffer_->SetSizeInElements(element_count);
158   return {};
159 }
160 
AddToBuffer(const std::vector<Value> & values,uint32_t offset)161 Result BufferDescriptor::AddToBuffer(const std::vector<Value>& values,
162                                      uint32_t offset) {
163   if (!amber_buffer_)
164     return Result("missing amber_buffer for AddToBuffer call");
165 
166   return amber_buffer_->SetDataWithOffset(values, offset);
167 }
168 
GetVkDescriptorType() const169 VkDescriptorType BufferDescriptor::GetVkDescriptorType() const {
170   return IsStorageBuffer() ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
171                            : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
172 }
173 
174 }  // namespace vulkan
175 }  // namespace amber
176