1 /* Copyright (c) 2017-2018 Hans-Kristian Arntzen
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be
12 * included in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #pragma once
24
25 #include "cookie.hpp"
26 #include "vulkan_common.hpp"
27 #include "memory_allocator.hpp"
28
29 namespace Vulkan
30 {
31 class Device;
32
buffer_usage_to_possible_stages(VkBufferUsageFlags usage)33 static inline VkPipelineStageFlags buffer_usage_to_possible_stages(VkBufferUsageFlags usage)
34 {
35 VkPipelineStageFlags flags = 0;
36 if (usage & (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT))
37 flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
38 if (usage & (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT))
39 flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
40 if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT)
41 flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
42 if (usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
43 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
44 flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
45 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
46 if (usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
47 flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
48
49 return flags;
50 }
51
buffer_usage_to_possible_access(VkBufferUsageFlags usage)52 static inline VkAccessFlags buffer_usage_to_possible_access(VkBufferUsageFlags usage)
53 {
54 VkAccessFlags flags = 0;
55 if (usage & (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT))
56 flags |= VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
57 if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
58 flags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
59 if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT)
60 flags |= VK_ACCESS_INDEX_READ_BIT;
61 if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT)
62 flags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
63 if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
64 flags |= VK_ACCESS_UNIFORM_READ_BIT;
65 if (usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
66 flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
67
68 return flags;
69 }
70
71 enum class BufferDomain
72 {
73 Device, // Device local. Probably not visible from CPU.
74 LinkedDeviceHost, // On desktop, directly mapped VRAM over PCI.
75 Host, // Host-only, needs to be synced to GPU. Might be device local as well on iGPUs.
76 CachedHost // Host-only, used for readbacks.
77 };
78
79 enum BufferMiscFlagBits
80 {
81 BUFFER_MISC_ZERO_INITIALIZE_BIT = 1 << 0
82 };
83
84 using BufferMiscFlags = uint32_t;
85
86 struct BufferCreateInfo
87 {
88 BufferDomain domain = BufferDomain::Device;
89 VkDeviceSize size = 0;
90 VkBufferUsageFlags usage = 0;
91 BufferMiscFlags misc = 0;
92 };
93
94 class Buffer;
95 struct BufferDeleter
96 {
97 void operator()(Buffer *buffer);
98 };
99
100 class BufferView;
101 struct BufferViewDeleter
102 {
103 void operator()(BufferView *view);
104 };
105
106 class Buffer : public Util::IntrusivePtrEnabled<Buffer, BufferDeleter, HandleCounter>,
107 public Cookie, public InternalSyncEnabled
108 {
109 public:
110 friend struct BufferDeleter;
111 ~Buffer();
112
get_buffer() const113 VkBuffer get_buffer() const
114 {
115 return buffer;
116 }
117
get_create_info() const118 const BufferCreateInfo &get_create_info() const
119 {
120 return info;
121 }
122
get_allocation()123 DeviceAllocation &get_allocation()
124 {
125 return alloc;
126 }
127
get_allocation() const128 const DeviceAllocation &get_allocation() const
129 {
130 return alloc;
131 }
132
133 private:
134 friend class Util::ObjectPool<Buffer>;
135 Buffer(Device *device, VkBuffer buffer, const DeviceAllocation &alloc, const BufferCreateInfo &info);
136
137 Device *device;
138 VkBuffer buffer;
139 DeviceAllocation alloc;
140 BufferCreateInfo info;
141 };
142 using BufferHandle = Util::IntrusivePtr<Buffer>;
143
144 struct BufferViewCreateInfo
145 {
146 const Buffer *buffer;
147 VkFormat format;
148 VkDeviceSize offset;
149 VkDeviceSize range;
150 };
151
152 class BufferView : public Util::IntrusivePtrEnabled<BufferView, BufferViewDeleter, HandleCounter>,
153 public Cookie, public InternalSyncEnabled
154 {
155 public:
156 friend struct BufferViewDeleter;
157 ~BufferView();
158
get_view() const159 VkBufferView get_view() const
160 {
161 return view;
162 }
163
get_create_info()164 const BufferViewCreateInfo &get_create_info()
165 {
166 return info;
167 }
168
get_buffer() const169 const Buffer &get_buffer() const
170 {
171 return *info.buffer;
172 }
173
174 private:
175 friend class Util::ObjectPool<BufferView>;
176 BufferView(Device *device, VkBufferView view, const BufferViewCreateInfo &info);
177
178 Device *device;
179 VkBufferView view;
180 BufferViewCreateInfo info;
181 };
182 using BufferViewHandle = Util::IntrusivePtr<BufferView>;
183 }
184