9 #ifndef hifi_gpu_Buffer_h
10 #define hifi_gpu_Buffer_h
15 #include <QtCore/QDebug>
16 #include "GPULogging.h"
23 #include "PageManager.h"
28 static ContextMetricCount _bufferCPUCount;
29 static ContextMetricSize _bufferCPUMemSize;
32 using Flag = PageManager::Flag;
43 UniformBuffer = 0x0010,
44 ResourceBuffer = 0x0020,
46 VertexBuffer = 0x0080,
47 IndirectBuffer = 0x0100,
53 Update(
const Buffer& buffer);
54 Update(
const Update& other);
55 Update(Update&& other);
62 PageManager::Pages dirtyPages;
63 std::vector<uint8> dirtyData;
66 static uint32_t getBufferCPUCount();
67 static Size getBufferCPUMemSize();
70 Buffer(uint32_t usage, Size pageSize = PageManager::DEFAULT_PAGE_SIZE);
73 static Buffer* createBuffer(uint32_t usage,
const std::vector<T>& v) {
74 return new Buffer(usage,
sizeof(T) * v.size(), (
const gpu::Byte*)v.data());
77 Buffer(uint32_t usage, Size size,
const Byte* bytes, Size pageSize = PageManager::DEFAULT_PAGE_SIZE);
78 Buffer(
const Buffer& buf);
79 Buffer& operator=(
const Buffer& buf);
83 Size getSize()
const override;
85 Size getNumTypedElements()
const {
86 return getSize() /
sizeof(T);
89 const Byte* getData()
const {
return getSysmem().readData(); }
91 uint32_t getUsage()
const {
return _usage; }
95 Size resize(Size pSize);
99 Size setData(Size size,
const Byte* data);
103 Size setSubData(Size offset, Size size,
const Byte* data);
105 template <
typename T>
106 Size setSubData(Size index,
const T& t) {
107 Size offset = index *
sizeof(T);
108 Size size =
sizeof(T);
109 return setSubData(offset, size,
reinterpret_cast<const Byte*
>(&t));
112 template <
typename T>
113 Size setSubData(Size index,
const std::vector<T>& t) {
117 Size offset = index *
sizeof(T);
118 Size size = t.size() *
sizeof(T);
119 return setSubData(offset, size,
reinterpret_cast<const Byte*
>(&t[0]));
125 Size append(Size size,
const Byte* data);
127 template <
typename T>
128 Size append(
const T& t) {
129 return append(
sizeof(t),
reinterpret_cast<const Byte*
>(&t));
132 template <
typename T>
133 Size append(
const std::vector<T>& t) {
137 return append(
sizeof(T) * t.size(),
reinterpret_cast<const Byte*
>(&t[0]));
140 const GPUObjectPointer gpuObject{};
143 const Sysmem& getSysmem()
const {
return _sysmem; }
145 bool isDirty()
const {
return _pages(PageManager::DIRTY); }
147 void applyUpdate(
const Update& update);
150 Update getUpdate()
const;
158 mutable PageManager _renderPages;
159 mutable Sysmem _renderSysmem;
161 mutable std::atomic<size_t> _getUpdateCount{ 0 };
162 mutable std::atomic<size_t> _applyUpdateCount{ 0 };
164 void markDirty(Size offset, Size bytes);
166 template <
typename T>
167 void markDirty(Size index, Size count = 1) {
168 markDirty(
sizeof(T) * index,
sizeof(T) * count);
171 Sysmem& editSysmem() {
return _sysmem; }
172 Byte* editData() {
return editSysmem().editData(); }
174 mutable PageManager _pages;
177 const uint32_t _usage{ 0 };
179 friend class Serializer;
180 friend class Deserializer;
181 friend class BufferView;
186 friend class ::gpu::vk::VKBuffer;
187 friend class ::gpu::vk::VKBackend;
188 friend class gl::GLBackend;
189 friend class gl::GLBuffer;
190 friend class gl41::GL41Buffer;
191 friend class gl45::GL45Buffer;
192 friend class gles::GLESBuffer;
193 friend class vk::VKBuffer;
196 using BufferUpdates = std::vector<Buffer::Update>;
198 typedef std::shared_ptr<Buffer> BufferPointer;
199 typedef std::vector<BufferPointer> Buffers;
203 static const Resource::Size DEFAULT_OFFSET{ 0 };
204 static const Element DEFAULT_ELEMENT;
207 using Size = Resource::Size;
208 using Index = int32_t;
210 BufferPointer _buffer;
213 Element _element{ DEFAULT_ELEMENT };
216 BufferView(
const BufferView& view) =
default;
217 BufferView& operator=(
const BufferView& view) =
default;
220 BufferView(
const Element& element);
221 BufferView(Buffer* newBuffer,
const Element& element = DEFAULT_ELEMENT);
222 BufferView(
const BufferPointer& buffer,
const Element& element = DEFAULT_ELEMENT);
223 BufferView(
const BufferPointer& buffer, Size offset, Size size,
const Element& element = DEFAULT_ELEMENT);
224 BufferView(
const BufferPointer& buffer, Size offset, Size size, uint16 stride,
const Element& element = DEFAULT_ELEMENT);
226 Size getNumElements()
const {
return _size / _stride; }
232 using iterator_category = std::random_access_iterator_tag;
233 using value_type = T;
234 using difference_type = Index;
235 using pointer =
const value_type*;
236 using reference =
const value_type&;
238 Iterator(T* ptr = NULL,
int stride =
sizeof(T)): _ptr(ptr), _stride(stride) { }
239 Iterator(
const Iterator<T>& iterator) =
default;
242 Iterator<T>& operator=(
const Iterator<T>& iterator) =
default;
243 Iterator<T>& operator=(T* ptr) {
249 operator bool()
const {
256 bool operator==(
const Iterator<T>& iterator)
const {
return (_ptr == iterator.getConstPtr()); }
257 bool operator!=(
const Iterator<T>& iterator)
const {
return (_ptr != iterator.getConstPtr()); }
258 bool operator<(
const Iterator<T>& iterator)
const {
return (_ptr < iterator.getConstPtr()); }
259 bool operator>(
const Iterator<T>& iterator)
const {
return (_ptr > iterator.getConstPtr()); }
261 void movePtr(
const Index& movement) {
262 auto byteptr = ((Byte*)_ptr);
263 byteptr += _stride * movement;
267 Iterator<T>& operator+=(
const Index& movement) {
271 Iterator<T>& operator-=(
const Index& movement) {
275 Iterator<T>& operator++() {
279 Iterator<T>& operator--() {
283 Iterator<T> operator++(Index) {
288 Iterator<T> operator--(Index) {
293 Iterator<T> operator+(
const Index& movement) {
300 Iterator<T> operator-(
const Index& movement) {
308 Index operator-(
const Iterator<T>& iterator) {
return (iterator.getPtr() - this->getPtr()) /
sizeof(T); }
310 T& operator*() {
return *_ptr; }
311 const T& operator*()
const {
return *_ptr; }
312 T* operator->() {
return _ptr; }
314 T* getPtr()
const {
return _ptr; }
315 const T* getConstPtr()
const {
return _ptr; }
324 template <
typename T> Iterator<T> begin() {
return Iterator<T>(&edit<T>(0), _stride); }
325 template <
typename T> Iterator<T> end() {
return Iterator<T>(&edit<T>(getNum<T>()), _stride); }
327 template <
typename T>
328 Iterator<const T> begin()
const {
329 return Iterator<const T>(&get<T>(), _stride);
331 template <
typename T>
332 Iterator<const T> end()
const {
334 Resource::Size elementOffset = getNum<T>() * _stride + _offset;
335 return Iterator<const T>((
reinterpret_cast<const T*
>(_buffer->getData() + elementOffset)), _stride);
338 template <
typename T>
339 Iterator<const T> cbegin()
const {
340 return Iterator<const T>(&get<T>(), _stride);
342 template <
typename T>
343 Iterator<const T> cend()
const {
345 Resource::Size elementOffset = getNum<T>() * _stride + _offset;
346 return Iterator<const T>((
reinterpret_cast<const T*
>(_buffer->getData() + elementOffset)), _stride);
350 template <
typename T>
351 Index getNum()
const {
352 return Index(_size / _stride);
355 template <
typename T>
356 const T& get()
const {
359 qCDebug(gpulogging) <<
"Accessing null gpu::buffer!";
361 if (
sizeof(T) > (_buffer->getSize() - _offset)) {
362 qCDebug(gpulogging) <<
"Accessing buffer in non allocated memory, element size = " <<
sizeof(T)
363 <<
" available space in buffer at offset is = " << (_buffer->getSize() - _offset);
365 if (
sizeof(T) > _size) {
366 qCDebug(gpulogging) <<
"Accessing buffer outside the BufferView range, element size = " <<
sizeof(T)
367 <<
" when bufferView size = " << _size;
370 const T* t = (
reinterpret_cast<const T*
>(_buffer->getData() + _offset));
374 template <
typename T>
378 qCDebug(gpulogging) <<
"Accessing null gpu::buffer!";
380 if (
sizeof(T) > (_buffer->getSize() - _offset)) {
381 qCDebug(gpulogging) <<
"Accessing buffer in non allocated memory, element size = " <<
sizeof(T)
382 <<
" available space in buffer at offset is = " << (_buffer->getSize() - _offset);
384 if (
sizeof(T) > _size) {
385 qCDebug(gpulogging) <<
"Accessing buffer outside the BufferView range, element size = " <<
sizeof(T)
386 <<
" when bufferView size = " << _size;
389 _buffer->markDirty(_offset,
sizeof(T));
390 T* t = (
reinterpret_cast<T*
>(_buffer->editData() + _offset));
394 template <
typename T>
395 const T& get(
const Index index)
const {
396 Resource::Size elementOffset = index * _stride + _offset;
399 qCDebug(gpulogging) <<
"Accessing null gpu::buffer!";
401 if (
sizeof(T) > (_buffer->getSize() - elementOffset)) {
402 qCDebug(gpulogging) <<
"Accessing buffer in non allocated memory, index = " << index
403 <<
", element size = " <<
sizeof(T)
404 <<
" available space in buffer at offset is = " << (_buffer->getSize() - elementOffset);
406 if (index > getNum<T>()) {
407 qCDebug(gpulogging) <<
"Accessing buffer outside the BufferView range, index = " << index
408 <<
" number elements = " << getNum<T>();
411 return *(
reinterpret_cast<const T*
>(_buffer->getData() + elementOffset));
414 template <
typename T>
415 T& edit(
const Index index)
const {
416 Resource::Size elementOffset = index * _stride + _offset;
419 qCDebug(gpulogging) <<
"Accessing null gpu::buffer!";
421 if (
sizeof(T) > (_buffer->getSize() - elementOffset)) {
422 qCDebug(gpulogging) <<
"Accessing buffer in non allocated memory, index = " << index
423 <<
", element size = " <<
sizeof(T)
424 <<
" available space in buffer at offset is = " << (_buffer->getSize() - elementOffset);
426 if (index > getNum<T>()) {
427 qCDebug(gpulogging) <<
"Accessing buffer outside the BufferView range, index = " << index
428 <<
" number elements = " << getNum<T>();
431 _buffer->markDirty(elementOffset,
sizeof(T));
432 return *(
reinterpret_cast<T*
>(_buffer->editData() + elementOffset));
437 class StructBuffer :
public gpu::BufferView {
440 static BufferPointer makeBuffer(uint32_t usage = gpu::Buffer::UniformBuffer) {
442 return std::make_shared<gpu::Buffer>(usage,
sizeof(U), (
const gpu::Byte*)&t,
sizeof(U));
445 StructBuffer() : gpu::BufferView(makeBuffer<T>()) {}
447 T& edit() {
return BufferView::edit<T>(0); }
448 const T& get()
const {
return BufferView::get<T>(0); }
449 const T* operator->()
const {
return &get(); }
Base class for resources.
Definition: ResourceCache.h:415