// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Core/Collections/Array.h" #include "GPUBuffer.h" /// /// Dynamic GPU buffer that allows to update and use GPU data (index/vertex/other) during single frame (supports dynamic resizing) /// class FLAXENGINE_API DynamicBuffer { protected: GPUBuffer* _buffer; String _name; uint32 _stride; public: NON_COPYABLE(DynamicBuffer); /// /// Init /// /// Initial capacity of the buffer (in bytes) /// Stride in bytes /// Buffer name DynamicBuffer(uint32 initialCapacity, uint32 stride, const String& name); /// /// Destructor /// virtual ~DynamicBuffer(); public: /// /// The data container (raw bytes storage). /// Array Data; /// /// Gets buffer (may be null since it's using 'late init' feature) /// FORCE_INLINE GPUBuffer* GetBuffer() const { return _buffer; } /// /// Clear data (begin for writing) /// FORCE_INLINE void Clear() { Data.Clear(); } /// /// Write bytes to the buffer /// /// Data to write template FORCE_INLINE void Write(const T& data) { Data.Add((byte*)&data, sizeof(T)); } /// /// Write bytes to the buffer /// /// Pointer to data to write /// Amount of data to write (in bytes) FORCE_INLINE void Write(const void* bytes, int32 size) { Data.Add((byte*)bytes, size); } /// /// Allocates bytes in the buffer by resizing the buffer for new memory and returns the pointer to the start of the allocated space. /// /// Amount of data to allocate (in bytes) FORCE_INLINE byte* WriteReserve(int32 size) { const int32 start = Data.Count(); Data.AddUninitialized(size); return Data.Get() + start; } /// /// Allocates bytes in the buffer by resizing the buffer for new memory and returns the pointer to the start of the allocated space. /// /// Amount of items to allocate template FORCE_INLINE T* WriteReserve(int32 count) { return (T*)WriteReserve(count * sizeof(T)); } /// /// Unlock buffer and flush data with a buffer (it will be ready for an immediate draw). /// void Flush(); /// /// Unlock buffer and flush data with a buffer (it will be ready for a during next frame draw). /// /// The GPU command list context to use for data uploading. void Flush(class GPUContext* context); /// /// Disposes the buffer resource and clears the used memory. /// void Dispose(); protected: virtual void InitDesc(GPUBufferDescription& desc, int32 numElements) = 0; }; /// /// Dynamic vertex buffer that allows to render any vertices during single frame (supports dynamic resizing) /// class FLAXENGINE_API DynamicVertexBuffer : public DynamicBuffer { public: /// /// Init /// /// Initial capacity of the buffer (in bytes) /// Stride in bytes /// Buffer name DynamicVertexBuffer(uint32 initialCapacity, uint32 stride, const String& name = String::Empty) : DynamicBuffer(initialCapacity, stride, name) { } protected: // [DynamicBuffer] void InitDesc(GPUBufferDescription& desc, int32 numElements) override { desc = GPUBufferDescription::Vertex(_stride, numElements, GPUResourceUsage::Dynamic); } }; /// /// Dynamic index buffer that allows to render any indices during single frame (supports dynamic resizing) /// class FLAXENGINE_API DynamicIndexBuffer : public DynamicBuffer { public: /// /// Init /// /// Initial capacity of the buffer (in bytes) /// Stride in bytes /// Buffer name DynamicIndexBuffer(uint32 initialCapacity, uint32 stride, const String& name = String::Empty) : DynamicBuffer(initialCapacity, stride, name) { } protected: // [DynamicBuffer] void InitDesc(GPUBufferDescription& desc, int32 numElements) override { desc = GPUBufferDescription::Index(_stride, numElements, GPUResourceUsage::Dynamic); } }; /// /// Dynamic structured buffer that allows to upload data to the GPU from CPU (supports dynamic resizing). /// class FLAXENGINE_API DynamicStructuredBuffer : public DynamicBuffer { private: bool _isUnorderedAccess; public: /// /// Init /// /// Initial capacity of the buffer (in bytes). /// Stride in bytes. /// True if unordered access usage. /// Buffer name. DynamicStructuredBuffer(uint32 initialCapacity, uint32 stride, bool isUnorderedAccess = false, const String& name = String::Empty) : DynamicBuffer(initialCapacity, stride, name) , _isUnorderedAccess(isUnorderedAccess) { } protected: // [DynamicBuffer] void InitDesc(GPUBufferDescription& desc, int32 numElements) override; }; /// /// Dynamic Typed buffer that allows to upload data to the GPU from CPU (supports dynamic resizing). /// class FLAXENGINE_API DynamicTypedBuffer : public DynamicBuffer { private: PixelFormat _format; bool _isUnorderedAccess; public: /// /// Init /// /// Initial capacity of the buffer (in bytes). /// Format of the data. /// True if unordered access usage. /// Buffer name. DynamicTypedBuffer(uint32 initialCapacity, PixelFormat format, bool isUnorderedAccess = false, const String& name = String::Empty); protected: // [DynamicBuffer] void InitDesc(GPUBufferDescription& desc, int32 numElements) override; };