// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "Enums.h" #include "PixelFormat.h" /// /// The GPU buffer usage flags. /// API_ENUM(Attributes="Flags") enum class GPUBufferFlags { /// /// Nothing /// None = 0x000, /// /// Create a buffer that can be bound as a shader resource. /// ShaderResource = 0x001, /// /// Create a buffer that can be bound as a vertex buffer. /// VertexBuffer = 0x002, /// /// Create a buffer that can be bound as a index buffer. /// IndexBuffer = 0x004, /// /// Create a buffer that can be bound as a unordered access. /// UnorderedAccess = 0x008, /// /// Flag for unordered access buffers that will use append feature. /// Append = 0x010, /// /// Flag for unordered access buffers that will use counter feature. /// Counter = 0x020, /// /// Flag for unordered access buffers that will be used as draw indirect argument buffer. /// Argument = 0x040, /// /// Flag for structured buffers. /// Structured = 0x080, /// /// Flag for raw buffers. /// RawBuffer = 0x100, /// /// Creates a structured buffer that supports unordered access and append. /// StructuredAppendBuffer = UnorderedAccess | Structured | Append, /// /// Creates a structured buffer that supports unordered access and counter. /// StructuredCounterBuffer = UnorderedAccess | Structured | Counter }; DECLARE_ENUM_OPERATORS(GPUBufferFlags); /// /// A common description for all GPU buffers. /// API_STRUCT() struct FLAXENGINE_API GPUBufferDescription { DECLARE_SCRIPTING_TYPE_MINIMAL(GPUBufferDescription); /// /// The buffer total size. /// API_FIELD() uint32 Size; /// /// The buffer structure stride (size in bytes per element). /// API_FIELD() uint32 Stride; /// /// The buffer flags. /// API_FIELD() GPUBufferFlags Flags; /// /// The format of the data in a buffer. /// API_FIELD() PixelFormat Format; /// /// The pointer to location of initial resource data. Null if not used. /// API_FIELD() const void* InitData; /// /// Value that identifies how the buffer is to be read from and written to. The most common value is ; see for all possible values. /// API_FIELD() GPUResourceUsage Usage; public: /// /// Gets the number elements in the buffer. /// FORCE_INLINE uint32 GetElementsCount() const { return Stride > 0 ? Size / Stride : 0; } /// /// Gets a value indicating whether this instance is a shader resource. /// FORCE_INLINE bool IsShaderResource() const { return (Flags & GPUBufferFlags::ShaderResource) != GPUBufferFlags::None; } /// /// Gets a value indicating whether this instance is a unordered access. /// FORCE_INLINE bool IsUnorderedAccess() const { return (Flags & GPUBufferFlags::UnorderedAccess) != GPUBufferFlags::None; } public: /// /// Creates the buffer description. /// /// The size (in bytes). /// The flags. /// The format. /// The initial data. /// The stride. /// The usage. /// The buffer description. static GPUBufferDescription Buffer(uint32 size, GPUBufferFlags flags, PixelFormat format = PixelFormat::Unknown, const void* initData = nullptr, uint32 stride = 0, GPUResourceUsage usage = GPUResourceUsage::Default); /// /// Creates typed buffer description. /// /// The elements count. /// The view format. /// True if use UAV, otherwise false. /// The usage. /// The buffer description. /// /// Example in HLSL: Buffer<float4>. /// static GPUBufferDescription Typed(int32 count, PixelFormat viewFormat, bool isUnorderedAccess = false, GPUResourceUsage usage = GPUResourceUsage::Default); /// /// Creates typed buffer description. /// /// The data. /// The elements count. /// The view format. /// True if use UAV, otherwise false. /// The usage. /// The buffer description. /// /// Example in HLSL: Buffer<float4>. /// static GPUBufferDescription Typed(const void* data, int32 count, PixelFormat viewFormat, bool isUnorderedAccess = false, GPUResourceUsage usage = GPUResourceUsage::Default); /// /// Creates vertex buffer description. /// /// The element stride. /// The elements count. /// The data. /// The buffer description. static GPUBufferDescription Vertex(int32 elementStride, int32 elementsCount, void* data) { return Buffer(elementsCount * elementStride, GPUBufferFlags::VertexBuffer, PixelFormat::Unknown, data, elementStride, GPUResourceUsage::Default); } /// /// Creates vertex buffer description. /// /// The element stride. /// The elements count. /// The usage mode. /// The buffer description. static GPUBufferDescription Vertex(int32 elementStride, int32 elementsCount, GPUResourceUsage usage = GPUResourceUsage::Default) { return Buffer(elementsCount * elementStride, GPUBufferFlags::VertexBuffer, PixelFormat::Unknown, nullptr, elementStride, usage); } /// /// Creates vertex buffer description. /// /// The size (in bytes). /// The usage mode. /// The buffer description. static GPUBufferDescription Vertex(int32 size, GPUResourceUsage usage = GPUResourceUsage::Default) { return Buffer(size, GPUBufferFlags::VertexBuffer, PixelFormat::Unknown, nullptr, 0, usage); } /// /// Creates index buffer description. /// /// The element stride. /// The elements count. /// The data. /// The buffer description. static GPUBufferDescription Index(int32 elementStride, int32 elementsCount, void* data) { const auto format = elementStride == 4 ? PixelFormat::R32_UInt : PixelFormat::R16_UInt; return Buffer(elementsCount * elementStride, GPUBufferFlags::IndexBuffer, format, data, elementStride, GPUResourceUsage::Default); } /// /// Creates index buffer description. /// /// The element stride. /// The elements count. /// The usage mode. /// The buffer description. static GPUBufferDescription Index(int32 elementStride, int32 elementsCount, GPUResourceUsage usage = GPUResourceUsage::Default) { const auto format = elementStride == 4 ? PixelFormat::R32_UInt : PixelFormat::R16_UInt; return Buffer(elementsCount * elementStride, GPUBufferFlags::IndexBuffer, format, nullptr, elementStride, usage); } /// /// Creates structured buffer description. /// /// The element count. /// Size of the element (in bytes). /// if set to true [is unordered access]. /// The buffer description. /// /// Example in HLSL: StructuredBuffer<float4> or RWStructuredBuffer<float4> for structured buffers supporting unordered access. /// static GPUBufferDescription Structured(int32 elementCount, int32 elementSize, bool isUnorderedAccess = false) { auto bufferFlags = GPUBufferFlags::Structured | GPUBufferFlags::ShaderResource; if (isUnorderedAccess) bufferFlags |= GPUBufferFlags::UnorderedAccess; return Buffer(elementCount * elementSize, bufferFlags, PixelFormat::Unknown, nullptr, elementSize); } /// /// Creates append buffer description (structured buffer). /// /// The element count. /// Size of the element (in bytes). /// The buffer description. /// /// Example in HLSL: AppendStructuredBuffer<float4> or ConsumeStructuredBuffer<float4>. /// static GPUBufferDescription StructuredAppend(int32 elementCount, int32 elementSize) { return Buffer(elementCount * elementSize, GPUBufferFlags::StructuredAppendBuffer | GPUBufferFlags::ShaderResource, PixelFormat::Unknown, nullptr, elementSize); } /// /// Creates counter buffer description (structured buffer). /// /// The element count. /// Size of the element (in bytes). /// The buffer description. /// /// Example in HLSL: StructuredBuffer<float4> or RWStructuredBuffer<float4> for structured buffers supporting unordered access. /// static GPUBufferDescription StructuredCounter(int32 elementCount, int32 elementSize) { return Buffer(elementCount * elementSize, GPUBufferFlags::StructuredCounterBuffer | GPUBufferFlags::ShaderResource, PixelFormat::Unknown, nullptr, elementSize); } /// /// Creates argument buffer description. /// /// The size (in bytes). /// The usage. /// The buffer description. static GPUBufferDescription Argument(int32 size, GPUResourceUsage usage = GPUResourceUsage::Default) { return Buffer(size, GPUBufferFlags::Argument, PixelFormat::Unknown, nullptr, 0, usage); } /// /// Creates argument buffer description. /// /// The initial data. /// The size (in bytes). /// The usage. /// The buffer description. static GPUBufferDescription Argument(const void* data, int32 size, GPUResourceUsage usage = GPUResourceUsage::Default) { return Buffer(size, GPUBufferFlags::Argument, PixelFormat::Unknown, data, 0, usage); } /// /// Creates raw buffer description. /// /// The size (in bytes). /// The additional bindings (for example, to create a combined raw/index buffer, pass ). /// The usage. /// The buffer description. static GPUBufferDescription Raw(int32 size, GPUBufferFlags additionalFlags = GPUBufferFlags::None, GPUResourceUsage usage = GPUResourceUsage::Default) { return Buffer(size, GPUBufferFlags::RawBuffer | additionalFlags, PixelFormat::R32_Typeless, nullptr, sizeof(float), usage); } /// /// Creates raw buffer description. /// /// The initial data. /// The size (in bytes). /// The additional bindings (for example, to create a combined raw/index buffer, pass ). /// The usage. /// The buffer description. static GPUBufferDescription Raw(const void* data, int32 size, GPUBufferFlags additionalFlags = GPUBufferFlags::None, GPUResourceUsage usage = GPUResourceUsage::Default) { return Buffer(size, GPUBufferFlags::RawBuffer | additionalFlags, PixelFormat::R32_Typeless, data, sizeof(float), usage); } public: void Clear(); GPUBufferDescription ToStagingUpload() const; GPUBufferDescription ToStagingReadback() const; bool Equals(const GPUBufferDescription& other) const; String ToString() const; public: FORCE_INLINE bool operator==(const GPUBufferDescription& other) const { return Equals(other); } FORCE_INLINE bool operator!=(const GPUBufferDescription& other) const { return !Equals(other); } }; uint32 GetHash(const GPUBufferDescription& key);