1 // Copyright 2018 The Amber Authors.
2 // Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 #include "src/vulkan/transfer_buffer.h"
17
18 #include "src/vulkan/command_buffer.h"
19 #include "src/vulkan/device.h"
20
21 namespace amber {
22 namespace vulkan {
23
TransferBuffer(Device * device,uint32_t size_in_bytes,Format * format)24 TransferBuffer::TransferBuffer(Device* device,
25 uint32_t size_in_bytes,
26 Format* format)
27 : Resource(device, size_in_bytes) {
28 if (format)
29 format_ = device->GetVkFormat(*format);
30 }
31
~TransferBuffer()32 TransferBuffer::~TransferBuffer() {
33 if (device_) {
34 device_->GetPtrs()->vkDestroyBufferView(device_->GetVkDevice(), view_,
35 nullptr);
36
37 if (memory_ != VK_NULL_HANDLE) {
38 UnMapMemory(memory_);
39 device_->GetPtrs()->vkFreeMemory(device_->GetVkDevice(), memory_,
40 nullptr);
41 }
42
43 device_->GetPtrs()->vkDestroyBuffer(device_->GetVkDevice(), buffer_,
44 nullptr);
45 }
46 }
47
Initialize()48 Result TransferBuffer::Initialize() {
49 if (buffer_) {
50 return Result(
51 "Vulkan: TransferBuffer::Initialize() transfer buffer already "
52 "initialized.");
53 }
54
55 Result r = CreateVkBuffer(&buffer_, usage_flags_);
56 if (!r.IsSuccess())
57 return r;
58
59 uint32_t memory_type_index = 0;
60 r = AllocateAndBindMemoryToVkBuffer(
61 buffer_, &memory_, GetMemoryPropertiesFlags(), true, &memory_type_index);
62 if (!r.IsSuccess())
63 return r;
64
65 // Create buffer view
66 if (usage_flags_ & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
67 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
68 VkBufferViewCreateInfo buffer_view_info = VkBufferViewCreateInfo();
69 buffer_view_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
70 buffer_view_info.buffer = buffer_;
71 buffer_view_info.format = format_;
72 buffer_view_info.offset = 0;
73 buffer_view_info.range = VK_WHOLE_SIZE;
74
75 if (device_->GetPtrs()->vkCreateBufferView(device_->GetVkDevice(),
76 &buffer_view_info, nullptr,
77 &view_) != VK_SUCCESS) {
78 return Result("Vulkan::Calling vkCreateBufferView Fail");
79 }
80 }
81
82 if (!device_->IsMemoryHostAccessible(memory_type_index) ||
83 !device_->IsMemoryHostCoherent(memory_type_index)) {
84 return Result(
85 "Vulkan: TransferBuffer::Initialize() buffer is not host accessible or"
86 " not host coherent.");
87 }
88
89 return MapMemory(memory_);
90 }
91
getBufferDeviceAddress()92 VkDeviceAddress TransferBuffer::getBufferDeviceAddress() {
93 const VkBufferDeviceAddressInfo bufferDeviceAddressInfo = {
94 VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR,
95 nullptr,
96 GetVkBuffer(),
97 };
98
99 return device_->GetPtrs()->vkGetBufferDeviceAddress(device_->GetVkDevice(),
100 &bufferDeviceAddressInfo);
101 }
102
CopyToDevice(CommandBuffer * command_buffer)103 void TransferBuffer::CopyToDevice(CommandBuffer* command_buffer) {
104 // This is redundant because this buffer is always host visible
105 // and coherent and vkQueueSubmit will make writes from host
106 // available (See chapter 6.9. "Host Write Ordering Guarantees" in
107 // Vulkan spec), but we prefer to keep it to simplify our own code.
108 MemoryBarrier(command_buffer);
109 }
110
CopyToHost(CommandBuffer * command_buffer)111 void TransferBuffer::CopyToHost(CommandBuffer* command_buffer) {
112 MemoryBarrier(command_buffer);
113 }
114
115 } // namespace vulkan
116 } // namespace amber
117