// Copyright (c) 2012-2024 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, const 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, const 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);