-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsve_buffer.cpp
More file actions
202 lines (184 loc) · 6.7 KB
/
sve_buffer.cpp
File metadata and controls
202 lines (184 loc) · 6.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
* Encapsulates a vulkan buffer
*
* Initially based off VulkanBuffer by Sascha Willems -
* https://github.com/SaschaWillems/Vulkan/blob/master/base/VulkanBuffer.h
*/
#include "sve_buffer.hpp"
// std
#include <cassert>
#include <cstring>
namespace sve {
/**
* Returns the minimum instance size required to be compatible with devices minOffsetAlignment
*
* @param instanceSize The size of an instance
* @param minOffsetAlignment The minimum required alignment, in bytes, for the offset member (eg
* minUniformBufferOffsetAlignment)
*
* @return VkResult of the buffer mapping call
*/
VkDeviceSize SveBuffer::getAlignment(VkDeviceSize instanceSize, VkDeviceSize minOffsetAlignment) {
if (minOffsetAlignment > 0) {
return (instanceSize + minOffsetAlignment - 1) & ~(minOffsetAlignment - 1);
}
return instanceSize;
}
SveBuffer::SveBuffer(
SveDevice& device,
VkDeviceSize instanceSize,
uint32_t instanceCount,
VkBufferUsageFlags usageFlags,
VkMemoryPropertyFlags memoryPropertyFlags,
VkDeviceSize minOffsetAlignment)
: sveDevice{ device },
instanceSize{ instanceSize },
instanceCount{ instanceCount },
usageFlags{ usageFlags },
memoryPropertyFlags{ memoryPropertyFlags } {
alignmentSize = getAlignment(instanceSize, minOffsetAlignment);
bufferSize = alignmentSize * instanceCount;
device.createBuffer(bufferSize, usageFlags, memoryPropertyFlags, buffer, memory);
}
SveBuffer::~SveBuffer() {
unmap();
vkDestroyBuffer(sveDevice.device(), buffer, nullptr);
vkFreeMemory(sveDevice.device(), memory, nullptr);
}
/**
* Map a memory range of this buffer. If successful, mapped points to the specified buffer range.
*
* @param size (Optional) Size of the memory range to map. Pass VK_WHOLE_SIZE to map the complete
* buffer range.
* @param offset (Optional) Byte offset from beginning
*
* @return VkResult of the buffer mapping call
*/
VkResult SveBuffer::map(VkDeviceSize size, VkDeviceSize offset) {
assert(buffer && memory && "Called map on buffer before create");
return vkMapMemory(sveDevice.device(), memory, offset, size, 0, &mapped);
}
/**
* Unmap a mapped memory range
*
* @note Does not return a result as vkUnmapMemory can't fail
*/
void SveBuffer::unmap() {
if (mapped) {
vkUnmapMemory(sveDevice.device(), memory);
mapped = nullptr;
}
}
/**
* Copies the specified data to the mapped buffer. Default value writes whole buffer range
*
* @param data Pointer to the data to copy
* @param size (Optional) Size of the data to copy. Pass VK_WHOLE_SIZE to flush the complete buffer
* range.
* @param offset (Optional) Byte offset from beginning of mapped region
*
*/
void SveBuffer::writeToBuffer(void* data, VkDeviceSize size, VkDeviceSize offset) {
assert(mapped && "Cannot copy to unmapped buffer");
if (size == VK_WHOLE_SIZE) {
memcpy(mapped, data, bufferSize);
}
else {
char* memOffset = (char*)mapped;
memOffset += offset;
memcpy(memOffset, data, size);
}
}
/**
* Flush a memory range of the buffer to make it visible to the device
*
* @note Only required for non-coherent memory
*
* @param size (Optional) Size of the memory range to flush. Pass VK_WHOLE_SIZE to flush the
* complete buffer range.
* @param offset (Optional) Byte offset from beginning
*
* @return VkResult of the flush call
*/
VkResult SveBuffer::flush(VkDeviceSize size, VkDeviceSize offset) {
VkMappedMemoryRange mappedRange = {};
mappedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
mappedRange.memory = memory;
mappedRange.offset = offset;
mappedRange.size = size;
return vkFlushMappedMemoryRanges(sveDevice.device(), 1, &mappedRange);
}
/**
* Invalidate a memory range of the buffer to make it visible to the host
*
* @note Only required for non-coherent memory
*
* @param size (Optional) Size of the memory range to invalidate. Pass VK_WHOLE_SIZE to invalidate
* the complete buffer range.
* @param offset (Optional) Byte offset from beginning
*
* @return VkResult of the invalidate call
*/
VkResult SveBuffer::invalidate(VkDeviceSize size, VkDeviceSize offset) {
VkMappedMemoryRange mappedRange = {};
mappedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
mappedRange.memory = memory;
mappedRange.offset = offset;
mappedRange.size = size;
return vkInvalidateMappedMemoryRanges(sveDevice.device(), 1, &mappedRange);
}
/**
* Create a buffer info descriptor
*
* @param size (Optional) Size of the memory range of the descriptor
* @param offset (Optional) Byte offset from beginning
*
* @return VkDescriptorBufferInfo of specified offset and range
*/
VkDescriptorBufferInfo SveBuffer::descriptorInfo(VkDeviceSize size, VkDeviceSize offset) {
return VkDescriptorBufferInfo{
buffer,
offset,
size,
};
}
/**
* Copies "instanceSize" bytes of data to the mapped buffer at an offset of index * alignmentSize
*
* @param data Pointer to the data to copy
* @param index Used in offset calculation
*
*/
void SveBuffer::writeToIndex(void* data, int index) {
writeToBuffer(data, instanceSize, index * alignmentSize);
}
/**
* Flush the memory range at index * alignmentSize of the buffer to make it visible to the device
*
* @param index Used in offset calculation
*
*/
VkResult SveBuffer::flushIndex(int index) { return flush(alignmentSize, index * alignmentSize); }
/**
* Create a buffer info descriptor
*
* @param index Specifies the region given by index * alignmentSize
*
* @return VkDescriptorBufferInfo for instance at index
*/
VkDescriptorBufferInfo SveBuffer::descriptorInfoForIndex(int index) {
return descriptorInfo(alignmentSize, index * alignmentSize);
}
/**
* Invalidate a memory range of the buffer to make it visible to the host
*
* @note Only required for non-coherent memory
*
* @param index Specifies the region to invalidate: index * alignmentSize
*
* @return VkResult of the invalidate call
*/
VkResult SveBuffer::invalidateIndex(int index) {
return invalidate(alignmentSize, index * alignmentSize);
}
} // namespace sve