• 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/vertex_buffer.h"
16 
17 #include <cassert>
18 #include <cstring>
19 
20 #include "src/make_unique.h"
21 #include "src/vulkan/command_buffer.h"
22 #include "src/vulkan/device.h"
23 
24 namespace amber {
25 namespace vulkan {
26 namespace {
27 
GetVkInputRate(InputRate rate)28 VkVertexInputRate GetVkInputRate(InputRate rate) {
29   return rate == InputRate::kVertex ? VK_VERTEX_INPUT_RATE_VERTEX
30                                     : VK_VERTEX_INPUT_RATE_INSTANCE;
31 }
32 
33 }  // namespace
34 
VertexBuffer(Device * device)35 VertexBuffer::VertexBuffer(Device* device) : device_(device) {}
36 
37 VertexBuffer::~VertexBuffer() = default;
38 
SetData(uint8_t location,Buffer * buffer,InputRate rate,Format * format,uint32_t offset,uint32_t stride)39 void VertexBuffer::SetData(uint8_t location,
40                            Buffer* buffer,
41                            InputRate rate,
42                            Format* format,
43                            uint32_t offset,
44                            uint32_t stride) {
45   const uint32_t binding = static_cast<uint32_t>(vertex_attr_desc_.size());
46   vertex_attr_desc_.emplace_back();
47   vertex_attr_desc_.back().binding = binding;
48   vertex_attr_desc_.back().location = location;
49   vertex_attr_desc_.back().offset = offset;
50   vertex_attr_desc_.back().format = device_->GetVkFormat(*format);
51 
52   vertex_binding_desc_.emplace_back();
53   vertex_binding_desc_.back().binding = binding;
54   vertex_binding_desc_.back().stride = stride;
55   vertex_binding_desc_.back().inputRate = GetVkInputRate(rate);
56 
57   data_.push_back(buffer);
58 }
59 
BindToCommandBuffer(CommandBuffer * command)60 void VertexBuffer::BindToCommandBuffer(CommandBuffer* command) {
61   std::vector<VkBuffer> buffers;
62   std::vector<VkDeviceSize> offsets;
63 
64   for (const auto& buf : data_) {
65     buffers.push_back(buffer_to_vk_buffer_[buf]);
66     offsets.push_back(0);
67   }
68   device_->GetPtrs()->vkCmdBindVertexBuffers(
69       command->GetVkCommandBuffer(), 0, static_cast<uint32_t>(buffers.size()),
70       buffers.data(), offsets.data());
71 }
72 
SendVertexData(CommandBuffer * command)73 Result VertexBuffer::SendVertexData(CommandBuffer* command) {
74   if (!is_vertex_data_pending_)
75     return Result("Vulkan::Vertices data was already sent");
76 
77   buffer_to_vk_buffer_.clear();
78 
79   for (const auto& buf : data_) {
80     if (buffer_to_vk_buffer_.count(buf) != 0) {
81       continue;
82     }
83 
84     // Create a new transfer buffer to hold vertex data.
85     uint32_t bytes = buf->GetSizeInBytes();
86     transfer_buffers_.push_back(
87         MakeUnique<TransferBuffer>(device_, bytes, nullptr));
88     Result r = transfer_buffers_.back()->Initialize(
89         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
90 
91     std::memcpy(transfer_buffers_.back()->HostAccessibleMemoryPtr(),
92                 buf->GetValues<void>(), bytes);
93     transfer_buffers_.back()->CopyToDevice(command);
94 
95     if (!r.IsSuccess())
96       return r;
97 
98     buffer_to_vk_buffer_[buf] = transfer_buffers_.back()->GetVkBuffer();
99   }
100 
101   is_vertex_data_pending_ = false;
102   return {};
103 }
104 
105 }  // namespace vulkan
106 }  // namespace amber
107