9 #ifndef hifi_gpu_Buffer_h
10 #define hifi_gpu_Buffer_h
15 #include <QtCore/QDebug>
16 #include "GPULogging.h"
23 #include "PageManager.h"
40 using Flag = PageManager::Flag;
51 UniformBuffer = 0x0010,
52 ResourceBuffer = 0x0020,
54 VertexBuffer = 0x0080,
55 IndirectBuffer = 0x0100,
108 PageManager::Pages dirtyPages;
111 std::vector<uint8> dirtyData;
129 Buffer(uint32_t usage, Size pageSize = PageManager::DEFAULT_PAGE_SIZE);
138 template <
typename T>
140 return new Buffer(usage,
sizeof(T) * v.size(), (
const gpu::Byte*)v.data());
150 Buffer(uint32_t usage, Size size,
const Byte* bytes, Size pageSize = PageManager::DEFAULT_PAGE_SIZE);
183 template <
typename T>
213 Size
setData(Size size,
const Byte* data);
226 Size
setSubData(Size offset, Size size,
const Byte* data);
236 template <
typename T>
238 Size offset = index *
sizeof(T);
239 Size size =
sizeof(T);
240 return setSubData(offset, size,
reinterpret_cast<const Byte*
>(&t));
251 template <
typename T>
256 Size offset = index *
sizeof(T);
257 Size size = t.size() *
sizeof(T);
258 return setSubData(offset, size,
reinterpret_cast<const Byte*
>(&t[0]));
269 Size
append(Size size,
const Byte* data);
278 template <
typename T>
280 return append(
sizeof(t),
reinterpret_cast<const Byte*
>(&t));
290 template <
typename T>
295 return append(
sizeof(T) * t.size(),
reinterpret_cast<const Byte*
>(&t[0]));
387 template <
typename T>
389 markDirty(
sizeof(T) * index,
sizeof(T) * count);
427 friend class Serializer;
428 friend class Deserializer;
429 friend class BufferView;
434 friend class ::gpu::vk::VKBuffer;
435 friend class ::gpu::vk::VKBackend;
436 friend class gl::GLBackend;
437 friend class gl::GLBuffer;
438 friend class gl41::GL41Buffer;
439 friend class gl45::GL45Buffer;
440 friend class gles::GLESBuffer;
441 friend class vk::VKBuffer;
444 using BufferUpdates = std::vector<Buffer::Update>;
446 typedef std::shared_ptr<Buffer> BufferPointer;
447 typedef std::vector<BufferPointer> Buffers;
455 static const Resource::Size DEFAULT_OFFSET{ 0 };
458 static const Element DEFAULT_ELEMENT;
461 using Size = Resource::Size;
462 using Index = int32_t;
467 BufferPointer _buffer;
482 Element _element{ DEFAULT_ELEMENT };
489 BufferView(
const BufferView& view) =
default;
490 BufferView& operator=(
const BufferView& view) =
default;
501 BufferView(
const Element& element);
510 BufferView(Buffer* newBuffer,
const Element& element = DEFAULT_ELEMENT);
518 BufferView(
const BufferPointer& buffer,
const Element& element = DEFAULT_ELEMENT);
528 BufferView(
const BufferPointer& buffer, Size offset, Size size,
const Element& element = DEFAULT_ELEMENT);
538 BufferView(
const BufferPointer& buffer, Size offset, Size size, uint16 stride,
const Element& element = DEFAULT_ELEMENT);
543 Size getNumElements()
const {
return _size / _stride; }
549 template <
typename T>
552 using iterator_category = std::random_access_iterator_tag;
553 using value_type = T;
554 using difference_type = Index;
555 using pointer =
const value_type*;
556 using reference =
const value_type&;
558 Iterator(T* ptr = NULL,
int stride =
sizeof(T)): _ptr(ptr), _stride(stride) { }
569 operator bool()
const {
576 bool operator==(
const Iterator<T>& iterator)
const {
return (_ptr == iterator.getConstPtr()); }
577 bool operator!=(
const Iterator<T>& iterator)
const {
return (_ptr != iterator.getConstPtr()); }
578 bool operator<(
const Iterator<T>& iterator)
const {
return (_ptr < iterator.getConstPtr()); }
579 bool operator>(
const Iterator<T>& iterator)
const {
return (_ptr > iterator.getConstPtr()); }
581 void movePtr(
const Index& movement) {
582 auto byteptr = ((Byte*)_ptr);
583 byteptr += _stride * movement;
628 Index operator-(
const Iterator<T>& iterator) {
return (iterator.getPtr() - this->getPtr()) /
sizeof(T); }
630 T& operator*() {
return *_ptr; }
631 const T& operator*()
const {
return *_ptr; }
632 T* operator->() {
return _ptr; }
634 T* getPtr()
const {
return _ptr; }
635 const T* getConstPtr()
const {
return _ptr; }
645 template <
typename T> Iterator<T> end() {
return Iterator<T>(&edit<T>(getNum<T>()), _stride); }
647 template <
typename T>
648 Iterator<const T> begin()
const {
649 return Iterator<const T>(&get<T>(), _stride);
651 template <
typename T>
652 Iterator<const T> end()
const {
654 Resource::Size elementOffset = getNum<T>() * _stride + _offset;
655 return Iterator<const T>((
reinterpret_cast<const T*
>(_buffer->getData() + elementOffset)), _stride);
658 template <
typename T>
659 Iterator<const T> cbegin()
const {
660 return Iterator<const T>(&get<T>(), _stride);
662 template <
typename T>
663 Iterator<const T> cend()
const {
665 Resource::Size elementOffset = getNum<T>() * _stride + _offset;
666 return Iterator<const T>((
reinterpret_cast<const T*
>(_buffer->getData() + elementOffset)), _stride);
670 template <
typename T>
671 Index getNum()
const {
672 return Index(_size / _stride);
679 template <
typename T>
680 const T& get()
const {
683 qCDebug(gpulogging) <<
"Accessing null gpu::buffer!";
685 if (
sizeof(T) > (_buffer->getSize() - _offset)) {
686 qCDebug(gpulogging) <<
"Accessing buffer in non allocated memory, element size = " <<
sizeof(T)
687 <<
" available space in buffer at offset is = " << (_buffer->getSize() - _offset);
689 if (
sizeof(T) > _size) {
690 qCDebug(gpulogging) <<
"Accessing buffer outside the BufferView range, element size = " <<
sizeof(T)
691 <<
" when bufferView size = " << _size;
694 const T* t = (
reinterpret_cast<const T*
>(_buffer->getData() + _offset));
704 template <
typename T>
708 qCDebug(gpulogging) <<
"Accessing null gpu::buffer!";
710 if (
sizeof(T) > (_buffer->getSize() - _offset)) {
711 qCDebug(gpulogging) <<
"Accessing buffer in non allocated memory, element size = " <<
sizeof(T)
712 <<
" available space in buffer at offset is = " << (_buffer->getSize() - _offset);
714 if (
sizeof(T) > _size) {
715 qCDebug(gpulogging) <<
"Accessing buffer outside the BufferView range, element size = " <<
sizeof(T)
716 <<
" when bufferView size = " << _size;
719 _buffer->markDirty(_offset,
sizeof(T));
720 T* t = (
reinterpret_cast<T*
>(_buffer->editData() + _offset));
729 template <
typename T>
730 const T& get(
const Index index)
const {
731 Resource::Size elementOffset = index * _stride + _offset;
734 qCDebug(gpulogging) <<
"Accessing null gpu::buffer!";
736 if (
sizeof(T) > (_buffer->getSize() - elementOffset)) {
737 qCDebug(gpulogging) <<
"Accessing buffer in non allocated memory, index = " << index
738 <<
", element size = " <<
sizeof(T)
739 <<
" available space in buffer at offset is = " << (_buffer->getSize() - elementOffset);
741 if (index > getNum<T>()) {
742 qCDebug(gpulogging) <<
"Accessing buffer outside the BufferView range, index = " << index
743 <<
" number elements = " << getNum<T>();
746 return *(
reinterpret_cast<const T*
>(_buffer->getData() + elementOffset));
756 template <
typename T>
757 T& edit(
const Index index)
const {
758 Resource::Size elementOffset = index * _stride + _offset;
761 qCDebug(gpulogging) <<
"Accessing null gpu::buffer!";
763 if (
sizeof(T) > (_buffer->getSize() - elementOffset)) {
764 qCDebug(gpulogging) <<
"Accessing buffer in non allocated memory, index = " << index
765 <<
", element size = " <<
sizeof(T)
766 <<
" available space in buffer at offset is = " << (_buffer->getSize() - elementOffset);
768 if (index > getNum<T>()) {
769 qCDebug(gpulogging) <<
"Accessing buffer outside the BufferView range, index = " << index
770 <<
" number elements = " << getNum<T>();
773 _buffer->markDirty(elementOffset,
sizeof(T));
774 return *(
reinterpret_cast<T*
>(_buffer->editData() + elementOffset));
796 static BufferPointer
makeBuffer(uint32_t usage = gpu::Buffer::UniformBuffer) {
798 return std::make_shared<gpu::Buffer>(usage,
sizeof(U), (
const gpu::Byte*)&t,
sizeof(U));
801 StructBuffer() : gpu::BufferView(
makeBuffer<T>()) {}
808 T&
edit() {
return BufferView::edit<T>(0); }
813 const T&
get()
const {
return BufferView::get<T>(0); }
815 const T* operator->()
const {
return &
get(); }
void apply() const
Applies the update to the buffer.
Definition: Buffer.cpp:127
Update(const Buffer &buffer)
Generates an update object based on current dirty pages in the buffer.
Definition: Buffer.cpp:111
Size append(const T &t)
Append new data at the end of the current buffer from an object of a given type.
Definition: Buffer.h:279
const Sysmem & getSysmem() const
Access the sysmem object.
Definition: Buffer.h:311
Size setSubData(Size index, const std::vector< T > &t)
Set a subset of buffer's data using a vector of objects of a given type.
Definition: Buffer.h:252
void markDirty(Size index, Size count=1)
Marks pages on which data from a number of objects of a specified type range is stored as dirty.
Definition: Buffer.h:388
Sysmem & editSysmem()
Definition: Buffer.h:395
Byte * editData()
Returns pointer to data to be edited, but data still needs to be flagged as dirty with a separate mak...
Definition: Buffer.h:401
Size getNumTypedElements() const
Definition: Buffer.h:184
Size setData(Size size, const Byte *data)
Assign data bytes and size (allocate for size, then copy bytes if exists).
Definition: Buffer.cpp:166
const GPUObjectPointer gpuObject
Definition: Buffer.h:302
uint32_t getUsage() const
Definition: Buffer.h:196
PageManager _renderPages
Definition: Buffer.h:353
const Byte * getData() const
Definition: Buffer.h:191
Size append(const std::vector< T > &t)
Append new data at the end of the current buffer using a vector of objects of a given type.
Definition: Buffer.h:291
static Size getBufferCPUMemSize()
Definition: Buffer.cpp:43
void markDirty(Size offset, Size bytes)
Marks pages on which specified data range is stored as dirty.
Definition: Buffer.cpp:87
~Buffer()
Definition: Buffer.cpp:72
std::atomic< size_t > _applyUpdateCount
Definition: Buffer.h:369
std::atomic< size_t > _getUpdateCount
Definition: Buffer.h:364
Buffer(uint32_t usage, Size pageSize=PageManager::DEFAULT_PAGE_SIZE)
Definition: Buffer.cpp:47
PageManager _pages
Definition: Buffer.h:408
Size append(Size size, const Byte *data)
Append new data at the end of the current buffer.
Definition: Buffer.cpp:180
Sysmem _renderSysmem
Definition: Buffer.h:359
Size getSize() const override
Definition: Buffer.cpp:187
const uint32_t _usage
Definition: Buffer.h:425
Update getUpdate() const
Generate Update object from the current changes to the buffer.
Definition: Buffer.cpp:146
void incrementCreatedBufferCount()
Counter used for debugging excessive creation of buffers.
Definition: Buffer.cpp:19
Size _end
Definition: Buffer.h:413
static Buffer * createBuffer(uint32_t usage, const std::vector< T > &v)
Creates a buffer from std::vector.
Definition: Buffer.h:139
bool isDirty() const
Definition: Buffer.h:316
void applyUpdate(const Update &update)
Applies update to a buffer.
Definition: Buffer.cpp:150
Size resize(Size pSize)
Resizes buffer.
Definition: Buffer.cpp:77
void flush() const
Instantly applies current changes to a buffer without creating an Update object.
Definition: Buffer.cpp:154
static uint32_t getBufferCPUCount()
Definition: Buffer.cpp:39
Size setSubData(Size index, const T &t)
Set a subset of buffer's data using data of a given object.
Definition: Buffer.h:237
Buffer & operator=(const Buffer &buf)
Assignment constructor.
Definition: Buffer.cpp:66
Size setSubData(Size offset, Size size, const Byte *data)
Set a subset of buffer's data.
Definition: Buffer.cpp:172
Sysmem _sysmem
Definition: Buffer.h:419
Template iterator with random access on the buffer sysmem.
Definition: Buffer.h:550
Definition: gpu/src/gpu/Forward.h:134
Buffer and Texture inherits from this class.
Definition: Resource.h:19
A buffer contaning a single structure.
Definition: Buffer.h:785
const T & get() const
Definition: Buffer.h:813
T & edit()
Mark data as dirty and get a writeable reference to the stored structure.
Definition: Buffer.h:808
static BufferPointer makeBuffer(uint32_t usage=gpu::Buffer::UniformBuffer)
Creates a new buffer containing a give structure.
Definition: Buffer.h:796
Sysmem is the underneath cache for the data of a resource in CPU RAM.
Definition: Sysmem.h:18
Byte * editData()
Access the byte array for reading and writing.
Definition: Sysmem.h:99
const Byte * readData() const
Access the byte array.
Definition: Sysmem.h:93
Definition: PageManager.h:21