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/transfer_buffer.h"
16 
17 #include "src/vulkan/command_buffer.h"
18 #include "src/vulkan/device.h"
19 
20 namespace amber {
21 namespace vulkan {
22 
TransferBuffer(Device * device,uint32_t size_in_bytes,Format * format)23 TransferBuffer::TransferBuffer(Device* device,
24                                uint32_t size_in_bytes,
25                                Format* format)
26     : Resource(device, size_in_bytes) {
27   if (format)
28     format_ = device->GetVkFormat(*format);
29 }
30 
~TransferBuffer()31 TransferBuffer::~TransferBuffer() {
32   if (device_) {
33     device_->GetPtrs()->vkDestroyBufferView(device_->GetVkDevice(), view_,
34                                             nullptr);
35 
36     if (memory_ != VK_NULL_HANDLE) {
37       UnMapMemory(memory_);
38       device_->GetPtrs()->vkFreeMemory(device_->GetVkDevice(), memory_,
39                                        nullptr);
40     }
41 
42     device_->GetPtrs()->vkDestroyBuffer(device_->GetVkDevice(), buffer_,
43                                         nullptr);
44   }
45 }
46 
Initialize(const VkBufferUsageFlags usage)47 Result TransferBuffer::Initialize(const VkBufferUsageFlags usage) {
48   Result r = CreateVkBuffer(&buffer_, usage);
49   if (!r.IsSuccess())
50     return r;
51 
52   uint32_t memory_type_index = 0;
53   r = AllocateAndBindMemoryToVkBuffer(buffer_, &memory_,
54                                       VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
55                                           VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
56                                       true, &memory_type_index);
57   if (!r.IsSuccess())
58     return r;
59 
60   // Create buffer view
61   if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
62                VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
63     VkBufferViewCreateInfo buffer_view_info = VkBufferViewCreateInfo();
64     buffer_view_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
65     buffer_view_info.buffer = buffer_;
66     buffer_view_info.format = format_;
67     buffer_view_info.offset = 0;
68     buffer_view_info.range = VK_WHOLE_SIZE;
69 
70     if (device_->GetPtrs()->vkCreateBufferView(device_->GetVkDevice(),
71                                                &buffer_view_info, nullptr,
72                                                &view_) != VK_SUCCESS) {
73       return Result("Vulkan::Calling vkCreateBufferView Fail");
74     }
75   }
76 
77   if (!device_->IsMemoryHostAccessible(memory_type_index) ||
78       !device_->IsMemoryHostCoherent(memory_type_index)) {
79     return Result(
80         "Vulkan: TransferBuffer::Initialize() buffer is not host accessible or"
81         " not host coherent.");
82   }
83 
84   return MapMemory(memory_);
85 }
86 
CopyToDevice(CommandBuffer * command_buffer)87 void TransferBuffer::CopyToDevice(CommandBuffer* command_buffer) {
88   // This is redundant because this buffer is always host visible
89   // and coherent and vkQueueSubmit will make writes from host
90   // available (See chapter 6.9. "Host Write Ordering Guarantees" in
91   // Vulkan spec), but we prefer to keep it to simplify our own code.
92   MemoryBarrier(command_buffer);
93 }
94 
CopyToHost(CommandBuffer * command_buffer)95 void TransferBuffer::CopyToHost(CommandBuffer* command_buffer) {
96   MemoryBarrier(command_buffer);
97 }
98 
99 }  // namespace vulkan
100 }  // namespace amber
101