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 <vector>
18
19 #include "src/make_unique.h"
20 #include "src/vulkan/command_buffer.h"
21 #include "src/vulkan/device.h"
22
23 namespace amber {
24 namespace vulkan {
25
BufferDescriptor(Buffer * buffer,DescriptorType type,Device * device,uint32_t desc_set,uint32_t binding)26 BufferDescriptor::BufferDescriptor(Buffer* buffer,
27 DescriptorType type,
28 Device* device,
29 uint32_t desc_set,
30 uint32_t binding)
31 : BufferBackedDescriptor(buffer, type, device, desc_set, binding) {}
32
33 BufferDescriptor::~BufferDescriptor() = default;
34
CreateResourceIfNeeded()35 Result BufferDescriptor::CreateResourceIfNeeded() {
36 if (!transfer_buffers_.empty()) {
37 return Result(
38 "Vulkan: BufferDescriptor::CreateResourceIfNeeded() must be called "
39 "only when |transfer_buffers| is empty");
40 }
41
42 transfer_buffers_.reserve(GetAmberBuffers().size());
43
44 for (const auto& amber_buffer : GetAmberBuffers()) {
45 if (amber_buffer->ValuePtr()->empty())
46 continue;
47
48 uint32_t size_in_bytes =
49 amber_buffer ? static_cast<uint32_t>(amber_buffer->ValuePtr()->size())
50 : 0;
51 transfer_buffers_.emplace_back(MakeUnique<TransferBuffer>(
52 device_, size_in_bytes, amber_buffer->GetFormat()));
53 VkBufferUsageFlags flags =
54 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
55 if (IsUniformBuffer() || IsUniformBufferDynamic()) {
56 flags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
57 } else if (IsStorageBuffer() || IsStorageBufferDynamic()) {
58 flags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
59 } else if (IsUniformTexelBuffer()) {
60 flags |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
61 } else if (IsStorageTexelBuffer()) {
62 flags |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
63 } else {
64 return Result("Unexpected buffer type when deciding usage flags");
65 }
66
67 Result r = transfer_buffers_.back()->Initialize(flags);
68 if (!r.IsSuccess())
69 return r;
70 }
71
72 is_descriptor_set_update_needed_ = true;
73 return {};
74 }
75
MoveResourceToBufferOutput()76 Result BufferDescriptor::MoveResourceToBufferOutput() {
77 Result r = BufferBackedDescriptor::MoveResourceToBufferOutput();
78
79 transfer_buffers_.clear();
80
81 return r;
82 }
83
UpdateDescriptorSetIfNeeded(VkDescriptorSet descriptor_set)84 void BufferDescriptor::UpdateDescriptorSetIfNeeded(
85 VkDescriptorSet descriptor_set) {
86 if (!is_descriptor_set_update_needed_)
87 return;
88
89 std::vector<VkDescriptorBufferInfo> buffer_infos;
90 std::vector<VkBufferView> buffer_views;
91
92 for (const auto& buffer : transfer_buffers_) {
93 VkDescriptorBufferInfo buffer_info;
94 buffer_info.buffer = buffer->GetVkBuffer();
95 buffer_info.offset = 0;
96 buffer_info.range = VK_WHOLE_SIZE;
97 buffer_infos.push_back(buffer_info);
98
99 if (IsUniformTexelBuffer() || IsStorageTexelBuffer()) {
100 buffer_views.push_back(*buffer->GetVkBufferView());
101 }
102 }
103
104 VkWriteDescriptorSet write = VkWriteDescriptorSet();
105 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
106 write.dstSet = descriptor_set;
107 write.dstBinding = binding_;
108 write.dstArrayElement = 0;
109 write.descriptorCount = static_cast<uint32_t>(buffer_infos.size());
110 write.descriptorType = GetVkDescriptorType();
111 write.pBufferInfo = buffer_infos.data();
112 write.pTexelBufferView = buffer_views.data();
113
114 device_->GetPtrs()->vkUpdateDescriptorSets(device_->GetVkDevice(), 1, &write,
115 0, nullptr);
116 is_descriptor_set_update_needed_ = false;
117 }
118
GetResources()119 std::vector<Resource*> BufferDescriptor::GetResources() {
120 std::vector<Resource*> ret;
121 for (auto& b : transfer_buffers_) {
122 ret.push_back(b.get());
123 }
124 return ret;
125 }
126
127 } // namespace vulkan
128 } // namespace amber
129