// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. using System; namespace FlaxEngine { partial struct GPUBufferDescription : IEquatable { /// /// Gets the number elements in the buffer. /// public uint ElementsCount => Stride > 0 ? Size / Stride : 0; /// /// Gets a value indicating whether this instance is a shader resource. /// public bool IsShaderResource => (Flags & GPUBufferFlags.ShaderResource) != 0; /// /// Gets a value indicating whether this instance is a unordered access. /// public bool IsUnorderedAccess => (Flags & GPUBufferFlags.UnorderedAccess) != 0; /// /// Clears description. /// public void Clear() { this = new GPUBufferDescription(); } /// /// Creates the buffer description. /// /// The size (in bytes). /// The flags. /// The format. /// The initial data. /// The stride. /// The usage. /// The buffer description. public static GPUBufferDescription Buffer(uint size, GPUBufferFlags flags, PixelFormat format = PixelFormat.Unknown, IntPtr initData = new IntPtr(), uint stride = 0, GPUResourceUsage usage = GPUResourceUsage.Default) { GPUBufferDescription desc; desc.Size = size; desc.Stride = stride; desc.Flags = flags; desc.Format = format; desc.InitData = initData; desc.Usage = usage; return desc; } /// /// Creates the buffer description. /// /// The size (in bytes). /// The flags. /// The format. /// The initial data. /// The stride. /// The usage. /// The buffer description. public static GPUBufferDescription Buffer(int size, GPUBufferFlags flags, PixelFormat format = PixelFormat.Unknown, IntPtr initData = new IntPtr(), int stride = 0, GPUResourceUsage usage = GPUResourceUsage.Default) { GPUBufferDescription desc; desc.Size = (uint)size; desc.Stride = (uint)stride; desc.Flags = flags; desc.Format = format; desc.InitData = initData; desc.Usage = usage; return desc; } /// /// 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>. /// public static GPUBufferDescription Typed(int count, PixelFormat viewFormat, bool isUnorderedAccess = false, GPUResourceUsage usage = GPUResourceUsage.Default) { var bufferFlags = GPUBufferFlags.ShaderResource; if (isUnorderedAccess) bufferFlags |= GPUBufferFlags.UnorderedAccess; var stride = PixelFormatExtensions.SizeInBytes(viewFormat); return Buffer(count * stride, bufferFlags, viewFormat, IntPtr.Zero, stride, usage); } /// /// 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>. /// public static GPUBufferDescription Typed(IntPtr data, int count, PixelFormat viewFormat, bool isUnorderedAccess = false, GPUResourceUsage usage = GPUResourceUsage.Default) { var bufferFlags = GPUBufferFlags.ShaderResource; if (isUnorderedAccess) bufferFlags |= GPUBufferFlags.UnorderedAccess; var stride = PixelFormatExtensions.SizeInBytes(viewFormat); return Buffer(count * stride, bufferFlags, viewFormat, data, stride, usage); } /// /// Creates vertex buffer description. /// /// The element stride. /// The elements count. /// The data. /// The buffer description. public static GPUBufferDescription Vertex(int elementStride, int elementsCount, IntPtr 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. public static GPUBufferDescription Vertex(int elementStride, int elementsCount, GPUResourceUsage usage = GPUResourceUsage.Default) { return Buffer(elementsCount * elementStride, GPUBufferFlags.VertexBuffer, PixelFormat.Unknown, new IntPtr(), elementStride, usage); } /// /// Creates vertex buffer description. /// /// The size (in bytes). /// The usage mode. /// The buffer description. public static GPUBufferDescription Vertex(int size, GPUResourceUsage usage = GPUResourceUsage.Default) { return Buffer(size, GPUBufferFlags.VertexBuffer, PixelFormat.Unknown, new IntPtr(), 0, usage); } /// /// Creates index buffer description. /// /// The element stride. /// The elements count. /// The data. /// The buffer description. public static GPUBufferDescription Index(int elementStride, int elementsCount, IntPtr data) { var 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. public static GPUBufferDescription Index(int elementStride, int elementsCount, GPUResourceUsage usage = GPUResourceUsage.Default) { var format = elementStride == 4 ? PixelFormat.R32_UInt : PixelFormat.R16_UInt; return Buffer(elementsCount * elementStride, GPUBufferFlags.IndexBuffer, format, new IntPtr(), 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. /// public static GPUBufferDescription Structured(int elementCount, int elementSize, bool isUnorderedAccess = false) { var bufferFlags = GPUBufferFlags.Structured | GPUBufferFlags.ShaderResource; if (isUnorderedAccess) bufferFlags |= GPUBufferFlags.UnorderedAccess; return Buffer(elementCount * elementSize, bufferFlags, PixelFormat.Unknown, new IntPtr(), 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>. /// public static GPUBufferDescription StructuredAppend(int elementCount, int elementSize) { return Buffer(elementCount * elementSize, GPUBufferFlags.StructuredAppendBuffer | GPUBufferFlags.ShaderResource, PixelFormat.Unknown, new IntPtr(), 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. /// public static GPUBufferDescription StructuredCounter(int elementCount, int elementSize) { return Buffer(elementCount * elementSize, GPUBufferFlags.StructuredCounterBuffer | GPUBufferFlags.ShaderResource, PixelFormat.Unknown, new IntPtr(), elementSize); } /// /// Creates argument buffer description. /// /// The size (in bytes). /// The usage. /// The buffer description. public static GPUBufferDescription Argument(int size, GPUResourceUsage usage = GPUResourceUsage.Default) { return Buffer(size, GPUBufferFlags.Argument, PixelFormat.Unknown, new IntPtr(), 0, usage); } /// /// Creates argument buffer description. /// /// The initial data. /// The size (in bytes). /// The usage. /// The buffer description. public static GPUBufferDescription Argument(IntPtr data, int 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. public static GPUBufferDescription Raw(int size, GPUBufferFlags additionalFlags = GPUBufferFlags.None, GPUResourceUsage usage = GPUResourceUsage.Default) { return Buffer(size, GPUBufferFlags.RawBuffer | additionalFlags, PixelFormat.R32_Typeless, new IntPtr(), 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. public static GPUBufferDescription Raw(IntPtr data, int size, GPUBufferFlags additionalFlags = GPUBufferFlags.None, GPUResourceUsage usage = GPUResourceUsage.Default) { return Buffer(size, GPUBufferFlags.RawBuffer | additionalFlags, PixelFormat.R32_Typeless, data, sizeof(float), usage); } /// /// Gets the staging upload description for this instance. /// /// A staging buffer description public GPUBufferDescription ToStagingUpload() { var desc = this; desc.Usage = GPUResourceUsage.StagingUpload; desc.Flags = GPUBufferFlags.None; desc.InitData = IntPtr.Zero; return desc; } /// /// Gets the staging readback description for this instance. /// /// A staging buffer description public GPUBufferDescription ToStagingReadback() { var desc = this; desc.Usage = GPUResourceUsage.StagingReadback; desc.Flags = GPUBufferFlags.None; desc.InitData = IntPtr.Zero; return desc; } /// public bool Equals(GPUBufferDescription other) { return Size == other.Size && Stride == other.Stride && Flags == other.Flags && Format == other.Format && InitData.Equals(other.InitData) && Usage == other.Usage; } /// public override bool Equals(object obj) { return obj is GPUBufferDescription other && Equals(other); } /// public override int GetHashCode() { unchecked { var hashCode = (int)Size; hashCode = (hashCode * 397) ^ (int)Stride; hashCode = (hashCode * 397) ^ (int)Flags; hashCode = (hashCode * 397) ^ (int)Format; hashCode = (hashCode * 397) ^ InitData.GetHashCode(); hashCode = (hashCode * 397) ^ (int)Usage; return hashCode; } } } }