// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Runtime.CompilerServices;
using FlaxEngine.Interop;
namespace FlaxEngine
{
partial class GPUDevice
{
///
/// Gets the list with all active GPU resources.
///
public GPUResource[] Resources
{
get
{
IntPtr ptr = Internal_GetResourcesInternal(__unmanagedPtr);
ManagedArray array = Unsafe.As(ManagedHandle.FromIntPtr(ptr).Target);
return NativeInterop.GCHandleArrayToManagedArray(array);
}
}
///
/// Gets the list with all active GPU resources.
///
/// Output buffer to fill with resource pointers. Can be provided by a user to avoid memory allocation. Buffer might be larger than actual list size. Use for actual item count.>
/// Amount of valid items inside .
public void GetResources(ref GPUResource[] buffer, out int count)
{
count = 0;
IntPtr ptr = Internal_GetResourcesInternal(__unmanagedPtr);
ManagedArray array = Unsafe.As(ManagedHandle.FromIntPtr(ptr).Target);
buffer = NativeInterop.GCHandleArrayToManagedArray(array, buffer);
count = buffer.Length;
}
}
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;
desc.VertexLayout = null;
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;
desc.VertexLayout = null;
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 vertex buffer layout.
/// The element stride.
/// The elements count.
/// The data.
/// The buffer description.
public static GPUBufferDescription Vertex(GPUVertexLayout layout, int elementStride, int elementsCount, IntPtr data)
{
GPUBufferDescription desc;
desc.Size = (uint)(elementsCount * elementStride);
desc.Stride = (uint)elementStride;
desc.Flags = GPUBufferFlags.VertexBuffer;
desc.Format = PixelFormat.Unknown;
desc.InitData = data;
desc.Usage = GPUResourceUsage.Default;
desc.VertexLayout = layout;
return desc;
}
///
/// Creates vertex buffer description.
///
/// The vertex buffer layout.
/// The element stride.
/// The elements count.
/// The usage mode.
/// The buffer description.
public static GPUBufferDescription Vertex(GPUVertexLayout layout, int elementStride, int elementsCount, GPUResourceUsage usage = GPUResourceUsage.Default)
{
GPUBufferDescription desc;
desc.Size = (uint)(elementsCount * elementStride);
desc.Stride = (uint)elementStride;
desc.Flags = GPUBufferFlags.VertexBuffer;
desc.Format = PixelFormat.Unknown;
desc.InitData = new IntPtr();
desc.Usage = usage;
desc.VertexLayout = layout;
return desc;
}
///
/// Creates vertex buffer description.
///
/// The element stride.
/// The elements count.
/// The data.
/// The vertex buffer layout.
/// The buffer description.
[Obsolete("Use Vertex with vertex layout parameter instead")]
public static GPUBufferDescription Vertex(int elementStride, int elementsCount, IntPtr data, GPUVertexLayout layout = null)
{
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 vertex buffer layout.
/// The buffer description.
[Obsolete("Use Vertex with vertex layout parameter instead")]
public static GPUBufferDescription Vertex(int elementStride, int elementsCount, GPUResourceUsage usage = GPUResourceUsage.Default, GPUVertexLayout layout = null)
{
return Buffer(elementsCount * elementStride, GPUBufferFlags.VertexBuffer, PixelFormat.Unknown, new IntPtr(), elementStride, usage);
}
///
/// Creates vertex buffer description.
/// [Deprecated in v1.10]
///
/// The size (in bytes).
/// The usage mode.
/// The buffer description.
[Obsolete("Use Vertex with separate vertex stride and count instead")]
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 (CPU write) 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 (CPU read) 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;
}
///
/// Gets the staging (CPU read/write) description for this instance.
///
/// A staging buffer description
public GPUBufferDescription ToStaging()
{
var desc = this;
desc.Usage = GPUResourceUsage.Staging;
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 &&
VertexLayout == other.VertexLayout;
}
///
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;
if (VertexLayout != null)
hashCode = (hashCode * 397) ^ VertexLayout.GetHashCode();
return hashCode;
}
}
}
partial struct VertexElement : IEquatable
{
///
/// Creates the vertex element description.
///
/// Element type.
/// Vertex buffer bind slot.
/// Data byte offset.
/// True if element data is instanced.
/// Data format.
public VertexElement(Types type, byte slot, byte offset, bool perInstance, PixelFormat format)
{
Type = type;
Slot = slot;
Offset = offset;
PerInstance = (byte)(perInstance ? 1 : 0);
Format = format;
}
///
public override string ToString()
{
return string.Format("{0}, {1}, offset {2}, {3}, slot {3}", Type, Format, Offset, PerInstance != 0 ? "per-instance" : "per-vertex", Slot);
}
///
public bool Equals(VertexElement other)
{
return Type == other.Type &&
Slot == other.Slot &&
Offset == other.Offset &&
PerInstance == other.PerInstance &&
Format == other.Format;
}
///
public override bool Equals(object obj)
{
return obj is VertexElement other && Equals(other);
}
///
public override int GetHashCode()
{
unchecked
{
var hashCode = (int)Type;
hashCode = (hashCode * 397) ^ Slot;
hashCode = (hashCode * 397) ^ Offset;
hashCode = (hashCode * 397) ^ PerInstance;
hashCode = (hashCode * 397) ^ (int)Format;
return hashCode;
}
}
}
}