Nerfed/Nerfed.Runtime/Graphics/RefreshTypes.cs

1724 lines
38 KiB
C#
Raw Normal View History

using System;
using System.Runtime.InteropServices;
using RefreshCS;
namespace Nerfed.Runtime.Graphics;
// Recreate certain types in here so we can csharp-ify them and hide the Refresh namespace
public enum PrimitiveType
{
PointList,
LineList,
LineStrip,
TriangleList,
TriangleStrip
}
public enum LoadOp
{
Load,
Clear,
DontCare
}
public enum StoreOp
{
Store,
DontCare
}
public enum IndexElementSize
{
Sixteen,
ThirtyTwo
}
public enum TextureFormat
{
/* Unsigned Normalized Float Color Formats */
R8G8B8A8,
B8G8R8A8,
R5G6B5,
A1R5G5B5,
B4G4R4A4,
A2R10G10B10,
A2B10G10R10,
R16G16,
R16G16B16A16,
R8,
A8,
/* Compressed Unsigned Normalized Float Color Formats */
BC1,
BC2,
BC3,
BC7,
/* Signed Normalized Float Color Formats */
R8G8_SNORM,
R8G8B8A8_SNORM,
/* Signed Float Color Formats */
R16_SFLOAT,
R16G16_SFLOAT,
R16G16B16A16_SFLOAT,
R32_SFLOAT,
R32G32_SFLOAT,
R32G32B32A32_SFLOAT,
/* Unsigned Integer Color Formats */
R8_UINT,
R8G8_UINT,
R8G8B8A8_UINT,
R16_UINT,
R16G16_UINT,
R16G16B16A16_UINT,
/* SRGB Color Formats */
R8G8B8A8_SRGB,
B8G8R8A8_SRGB,
/* Compressed SRGB Color Formats */
BC3_SRGB,
BC7_SRGB,
/* Depth Formats */
D16_UNORM,
D24_UNORM,
D32_SFLOAT,
D24_UNORM_S8_UINT,
D32_SFLOAT_S8_UINT
}
[Flags]
public enum TextureUsageFlags
{
Sampler = 0x1,
ColorTarget = 0x2,
DepthStencil = 0x4,
GraphicsStorage = 0x8,
ComputeStorageRead = 0x20,
ComputeStorageWrite = 0x40
}
public enum TextureType
{
TwoD,
ThreeD,
Cube
}
public enum SampleCount
{
One,
Two,
Four,
Eight
}
public enum CubeMapFace
{
PositiveX,
NegativeX,
PositiveY,
NegativeY,
PositiveZ,
NegativeZ
}
[Flags]
public enum BufferUsageFlags
{
Vertex = 0x1,
Index = 0x2,
Indirect = 0x4,
GraphicsStorage = 0x8,
ComputeStorageRead = 0x20,
ComputeStorageWrite = 0x40
}
public enum TransferBufferUsage
{
Upload,
Download
}
public enum ShaderStage
{
Vertex,
Fragment
}
public enum ShaderFormat
{
Invalid,
SPIRV,
HLSL,
DXBC,
DXIL,
MSL,
METALLIB,
SECRET
}
public enum VertexElementFormat
{
Uint,
Float,
Vector2,
Vector3,
Vector4,
Color,
Byte4,
Short2,
Short4,
NormalizedShort2,
NormalizedShort4,
HalfVector2,
HalfVector4
}
public enum VertexInputRate
{
Vertex,
Instance
}
public enum FillMode
{
Fill,
Line
}
public enum CullMode
{
None,
Front,
Back
}
public enum FrontFace
{
CounterClockwise,
Clockwise
}
public enum CompareOp
{
Never,
Less,
Equal,
LessOrEqual,
Greater,
NotEqual,
GreaterOrEqual,
Always
}
public enum StencilOp
{
Keep,
Zero,
Replace,
IncrementAndClamp,
DecrementAndClamp,
Invert,
IncrementAndWrap,
DecrementAndWrap
}
public enum BlendOp
{
Add,
Subtract,
ReverseSubtract,
Min,
Max
}
public enum BlendFactor
{
Zero,
One,
SourceColor,
OneMinusSourceColor,
DestinationColor,
OneMinusDestinationColor,
SourceAlpha,
OneMinusSourceAlpha,
DestinationAlpha,
OneMinusDestinationAlpha,
ConstantColor,
OneMinusConstantColor,
SourceAlphaSaturate
}
[Flags]
public enum ColorComponentFlags
{
None = 0x0,
R = 0x1,
G = 0x2,
B = 0x4,
A = 0x8,
RGB = R | G | B,
RGBA = R | G| B | A
}
public enum Filter
{
Nearest,
Linear
}
public enum SamplerMipmapMode
{
Nearest,
Linear
}
public enum SamplerAddressMode
{
Repeat,
MirroredRepeat,
ClampToEdge
}
public enum PresentMode
{
VSync,
Immediate,
Mailbox
}
public enum SwapchainComposition
{
SDR,
SDRLinear,
HDRExtendedLinear,
HDR10_ST2084
}
[Flags]
public enum BackendFlags
{
Invalid = 0x0,
Vulkan = 0x1,
D3D11 = 0x2,
Metal = 0x4,
All = Vulkan | D3D11 | Metal
}
[StructLayout(LayoutKind.Sequential)]
public struct DepthStencilValue
{
public float Depth;
public uint Stencil;
public DepthStencilValue(float depth, uint stencil)
{
Depth = depth;
Stencil = stencil;
}
// FIXME: can we do an unsafe cast somehow?
public Refresh.DepthStencilValue ToRefresh()
{
return new Refresh.DepthStencilValue
{
Depth = Depth,
Stencil = Stencil
};
}
}
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int X;
public int Y;
public int W;
public int H;
public Rect(int x, int y, int w, int h)
{
X = x;
Y = y;
W = w;
H = h;
}
public Rect(int w, int h)
{
X = 0;
Y = 0;
W = w;
H = h;
}
// FIXME: can we do an unsafe cast somehow?
public Refresh.Rect ToRefresh()
{
return new Refresh.Rect
{
X = X,
Y = Y,
W = W,
H = H
};
}
}
[StructLayout(LayoutKind.Sequential)]
public struct Viewport
{
public float X;
public float Y;
public float W;
public float H;
public float MinDepth;
public float MaxDepth;
public Viewport(float w, float h)
{
X = 0;
Y = 0;
W = w;
H = h;
MinDepth = 0;
MaxDepth = 1;
}
public Viewport(float x, float y, float w, float h)
{
X = x;
Y = y;
W = w;
H = h;
MinDepth = 0;
MaxDepth = 1;
}
public Viewport(float x, float y, float w, float h, float minDepth, float maxDepth)
{
X = x;
Y = y;
W = w;
H = h;
MinDepth = minDepth;
MaxDepth = maxDepth;
}
public Refresh.Viewport ToRefresh()
{
return new Refresh.Viewport
{
X = X,
Y = Y,
W = W,
H = H,
MinDepth = MinDepth,
MaxDepth = MaxDepth
};
}
}
[StructLayout(LayoutKind.Sequential)]
public struct VertexBinding
{
public uint Binding;
public uint Stride;
public VertexInputRate InputRate;
public uint StepRate;
public static VertexBinding Create<T>(
uint binding = 0,
VertexInputRate inputRate = VertexInputRate.Vertex,
uint stepRate = 1
) where T : unmanaged
{
return new VertexBinding
{
Binding = binding,
InputRate = inputRate,
Stride = (uint) Marshal.SizeOf<T>(),
StepRate = stepRate
};
}
public Refresh.VertexBinding ToRefresh()
{
return new Refresh.VertexBinding
{
Binding = Binding,
Stride = Stride,
InputRate = (Refresh.VertexInputRate) InputRate,
StepRate = StepRate
};
}
}
[StructLayout(LayoutKind.Sequential)]
public struct VertexAttribute
{
public uint Location;
public uint Binding;
public VertexElementFormat Format;
public uint Offset;
public Refresh.VertexAttribute ToRefresh()
{
return new Refresh.VertexAttribute
{
Location = Location,
Binding = Binding,
Format = (Refresh.VertexElementFormat) Format,
Offset = Offset
};
}
}
[StructLayout(LayoutKind.Sequential)]
public struct StencilOpState
{
public StencilOp FailOp;
public StencilOp PassOp;
public StencilOp DepthFailOp;
public CompareOp CompareOp;
public Refresh.StencilOpState ToRefresh()
{
return new Refresh.StencilOpState
{
FailOp = (Refresh.StencilOp) FailOp,
PassOp = (Refresh.StencilOp) PassOp,
DepthFailOp = (Refresh.StencilOp) DepthFailOp,
CompareOp = (Refresh.CompareOp) CompareOp
};
}
}
/// <summary>
/// Determines how a color texture will be read/written in a render pass.
/// </summary>
public struct ColorAttachmentInfo
{
public TextureSlice TextureSlice;
/// <summary>
/// If LoadOp is set to Clear, the texture slice will be cleared to this color.
/// </summary>
public Color ClearColor;
/// <summary>
/// Determines what is done with the texture slice memory
/// at the beginning of the render pass. <br/>
///
/// Load:
/// Loads the data currently in the texture slice. <br/>
///
/// Clear:
/// Clears the texture slice to a single color. <br/>
///
/// DontCare:
/// The driver will do whatever it wants with the texture slice data.
/// This is a good option if you know that every single pixel will be written in the render pass.
/// </summary>
public LoadOp LoadOp;
/// <summary>
/// Determines what is done with the texture slice memory
/// at the end of the render pass. <br/>
///
/// Store:
/// Stores the results of the render pass in the texture slice memory. <br/>
///
/// DontCare:
/// The driver will do whatever it wants with the texture slice memory.
/// </summary>
public StoreOp StoreOp;
/// <summary>
/// If true, cycles the texture if it is bound.
/// </summary>
public bool Cycle;
public ColorAttachmentInfo(
TextureSlice textureSlice,
bool cycle,
Color clearColor,
StoreOp storeOp = StoreOp.Store
) {
TextureSlice = textureSlice;
ClearColor = clearColor;
LoadOp = LoadOp.Clear;
StoreOp = storeOp;
Cycle = cycle;
}
public ColorAttachmentInfo(
TextureSlice textureSlice,
bool cycle,
LoadOp loadOp = LoadOp.DontCare,
StoreOp storeOp = StoreOp.Store
) {
TextureSlice = textureSlice;
ClearColor = Color.White;
LoadOp = loadOp;
StoreOp = storeOp;
Cycle = cycle;
}
public Refresh.ColorAttachmentInfo ToRefresh()
{
return new Refresh.ColorAttachmentInfo
{
TextureSlice = TextureSlice.ToRefresh(),
ClearColor = new Refresh.Color
{
R = ClearColor.R / 255f,
G = ClearColor.G / 255f,
B = ClearColor.B / 255f,
A = ClearColor.A / 255f
},
LoadOp = (Refresh.LoadOp) LoadOp,
StoreOp = (Refresh.StoreOp) StoreOp,
Cycle = Conversions.BoolToInt(Cycle)
};
}
}
/// <summary>
/// Determines how a depth/stencil texture will be read/written in a render pass.
/// </summary>
public struct DepthStencilAttachmentInfo
{
public TextureSlice TextureSlice;
/// <summary>
/// If LoadOp is set to Clear, the texture slice depth will be cleared to this depth value. <br/>
/// If StencilLoadOp is set to Clear, the texture slice stencil value will be cleared to this stencil value.
/// </summary>
public DepthStencilValue DepthStencilClearValue;
/// <summary>
/// Determines what is done with the texture slice depth values
/// at the beginning of the render pass. <br/>
///
/// Load:
/// Loads the data currently in the texture slice. <br/>
///
/// Clear:
/// Clears the texture slice to a single depth value. <br/>
///
/// DontCare:
/// The driver will do whatever it wants with the texture slice data.
/// This is a good option if you know that every single pixel will be written in the render pass.
/// </summary>
public LoadOp LoadOp;
/// <summary>
/// Determines what is done with the texture slice depth values
/// at the end of the render pass. <br/>
///
/// Store:
/// Stores the results of the render pass in the texture slice memory. <br/>
///
/// DontCare:
/// The driver will do whatever it wants with the texture slice memory.
/// This is usually a good option for depth textures that don't need to be reused.
/// </summary>
public StoreOp StoreOp;
/// <summary>
/// Determines what is done with the texture slice stencil values
/// at the beginning of the render pass. <br/>
///
/// Load:
/// Loads the data currently in the texture slice. <br/>
///
/// Clear:
/// Clears the texture slice to a single stencil value. <br/>
///
/// DontCare:
/// The driver will do whatever it wants with the texture slice data.
/// This is a good option if you know that every single pixel will be written in the render pass.
/// </summary>
public LoadOp StencilLoadOp;
/// <summary>
/// Determines what is done with the texture slice stencil values
/// at the end of the render pass. <br/>
///
/// Store:
/// Stores the results of the render pass in the texture slice memory. <br/>
///
/// DontCare:
/// The driver will do whatever it wants with the texture slice memory.
/// This is usually a good option for stencil textures that don't need to be reused.
/// </summary>
public StoreOp StencilStoreOp;
/// <summary>
/// If true, cycles the texture if it is bound.
/// </summary>
public bool Cycle;
public DepthStencilAttachmentInfo(
TextureSlice textureSlice,
bool cycle,
DepthStencilValue clearValue,
StoreOp depthStoreOp = StoreOp.DontCare,
StoreOp stencilStoreOp = StoreOp.DontCare
){
TextureSlice = textureSlice;
DepthStencilClearValue = clearValue;
LoadOp = LoadOp.Clear;
StoreOp = depthStoreOp;
StencilLoadOp = LoadOp.Clear;
StencilStoreOp = stencilStoreOp;
Cycle = cycle;
}
public DepthStencilAttachmentInfo(
TextureSlice textureSlice,
bool cycle,
LoadOp loadOp = LoadOp.DontCare,
StoreOp storeOp = StoreOp.DontCare,
LoadOp stencilLoadOp = LoadOp.DontCare,
StoreOp stencilStoreOp = StoreOp.DontCare
) {
TextureSlice = textureSlice;
DepthStencilClearValue = new DepthStencilValue();
LoadOp = loadOp;
StoreOp = storeOp;
StencilLoadOp = stencilLoadOp;
StencilStoreOp = stencilStoreOp;
Cycle = cycle;
}
public DepthStencilAttachmentInfo(
TextureSlice textureSlice,
bool cycle,
DepthStencilValue clearValue,
LoadOp loadOp,
StoreOp storeOp,
LoadOp stencilLoadOp,
StoreOp stencilStoreOp
) {
TextureSlice = textureSlice;
DepthStencilClearValue = clearValue;
LoadOp = loadOp;
StoreOp = storeOp;
StencilLoadOp = stencilLoadOp;
StencilStoreOp = stencilStoreOp;
Cycle = cycle;
}
public Refresh.DepthStencilAttachmentInfo ToRefresh()
{
return new Refresh.DepthStencilAttachmentInfo
{
TextureSlice = TextureSlice.ToRefresh(),
DepthStencilClearValue = DepthStencilClearValue.ToRefresh(),
LoadOp = (Refresh.LoadOp) LoadOp,
StoreOp = (Refresh.StoreOp) StoreOp,
StencilLoadOp = (Refresh.LoadOp) StencilLoadOp,
StencilStoreOp = (Refresh.StoreOp) StencilStoreOp,
Cycle = Conversions.BoolToInt(Cycle)
};
}
}
/// <summary>
/// Defines how color blending will be performed in a GraphicsPipeline.
/// </summary>
public struct ColorAttachmentBlendState
{
/// <summary>
/// If disabled, no blending will occur.
/// </summary>
public bool BlendEnable;
/// <summary>
/// Selects which blend operation to use with alpha values.
/// </summary>
public BlendOp AlphaBlendOp;
/// <summary>
/// Selects which blend operation to use with color values.
/// </summary>
public BlendOp ColorBlendOp;
/// <summary>
/// Specifies which of the RGBA components are enabled for writing.
/// </summary>
public ColorComponentFlags ColorWriteMask;
/// <summary>
/// Selects which blend factor is used to determine the alpha destination factor.
/// </summary>
public BlendFactor DestinationAlphaBlendFactor;
/// <summary>
/// Selects which blend factor is used to determine the color destination factor.
/// </summary>
public BlendFactor DestinationColorBlendFactor;
/// <summary>
/// Selects which blend factor is used to determine the alpha source factor.
/// </summary>
public BlendFactor SourceAlphaBlendFactor;
/// <summary>
/// Selects which blend factor is used to determine the color source factor.
/// </summary>
public BlendFactor SourceColorBlendFactor;
public static readonly ColorAttachmentBlendState Additive = new ColorAttachmentBlendState
{
BlendEnable = true,
AlphaBlendOp = BlendOp.Add,
ColorBlendOp = BlendOp.Add,
ColorWriteMask = ColorComponentFlags.RGBA,
SourceColorBlendFactor = BlendFactor.SourceAlpha,
SourceAlphaBlendFactor = BlendFactor.SourceAlpha,
DestinationColorBlendFactor = BlendFactor.One,
DestinationAlphaBlendFactor = BlendFactor.One
};
public static readonly ColorAttachmentBlendState AlphaBlend = new ColorAttachmentBlendState
{
BlendEnable = true,
AlphaBlendOp = BlendOp.Add,
ColorBlendOp = BlendOp.Add,
ColorWriteMask = ColorComponentFlags.RGBA,
SourceColorBlendFactor = BlendFactor.One,
SourceAlphaBlendFactor = BlendFactor.One,
DestinationColorBlendFactor = BlendFactor.OneMinusSourceAlpha,
DestinationAlphaBlendFactor = BlendFactor.OneMinusSourceAlpha
};
public static readonly ColorAttachmentBlendState NonPremultiplied = new ColorAttachmentBlendState
{
BlendEnable = true,
AlphaBlendOp = BlendOp.Add,
ColorBlendOp = BlendOp.Add,
ColorWriteMask = ColorComponentFlags.RGBA,
SourceColorBlendFactor = BlendFactor.SourceAlpha,
SourceAlphaBlendFactor = BlendFactor.SourceAlpha,
DestinationColorBlendFactor = BlendFactor.OneMinusSourceAlpha,
DestinationAlphaBlendFactor = BlendFactor.OneMinusSourceAlpha
};
public static readonly ColorAttachmentBlendState Opaque = new ColorAttachmentBlendState
{
BlendEnable = true,
AlphaBlendOp = BlendOp.Add,
ColorBlendOp = BlendOp.Add,
ColorWriteMask = ColorComponentFlags.RGBA,
SourceColorBlendFactor = BlendFactor.One,
SourceAlphaBlendFactor = BlendFactor.One,
DestinationColorBlendFactor = BlendFactor.Zero,
DestinationAlphaBlendFactor = BlendFactor.Zero
};
public static readonly ColorAttachmentBlendState None = new ColorAttachmentBlendState
{
BlendEnable = false,
ColorWriteMask = ColorComponentFlags.RGBA
};
public static readonly ColorAttachmentBlendState Disable = new ColorAttachmentBlendState
{
BlendEnable = false,
ColorWriteMask = ColorComponentFlags.None
};
public Refresh.ColorAttachmentBlendState ToRefresh()
{
return new Refresh.ColorAttachmentBlendState
{
BlendEnable = Conversions.BoolToInt(BlendEnable),
AlphaBlendOp = (Refresh.BlendOp) AlphaBlendOp,
ColorBlendOp = (Refresh.BlendOp) ColorBlendOp,
ColorWriteMask = (Refresh.ColorComponentFlags) ColorWriteMask,
DestinationAlphaBlendFactor = (Refresh.BlendFactor) DestinationAlphaBlendFactor,
DestinationColorBlendFactor = (Refresh.BlendFactor) DestinationColorBlendFactor,
SourceAlphaBlendFactor = (Refresh.BlendFactor) SourceAlphaBlendFactor,
SourceColorBlendFactor = (Refresh.BlendFactor) SourceColorBlendFactor
};
}
}
[StructLayout(LayoutKind.Sequential)]
public struct ColorAttachmentDescription
{
public TextureFormat Format;
public ColorAttachmentBlendState BlendState;
public ColorAttachmentDescription(
TextureFormat format,
ColorAttachmentBlendState blendState
) {
Format = format;
BlendState = blendState;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct IndirectDrawCommand
{
public uint VertexCount;
public uint InstanceCount;
public uint FirstVertex;
public uint FirstInstance;
public IndirectDrawCommand(
uint vertexCount,
uint instanceCount,
uint firstVertex,
uint firstInstance
) {
VertexCount = vertexCount;
InstanceCount = instanceCount;
FirstVertex = firstVertex;
FirstInstance = firstInstance;
}
}
/// <summary>
/// A buffer location used when transferring data.
/// </summary>
public record struct BufferLocation(
Buffer Buffer,
uint Offset
) {
public Refresh.BufferLocation ToRefresh()
{
return new Refresh.BufferLocation
{
Buffer = Buffer.Handle,
Offset = Offset
};
}
}
/// <summary>
/// A buffer region used when transferring data.
/// </summary>
public record struct BufferRegion(
Buffer Buffer,
uint Offset,
uint Size
) {
public Refresh.BufferRegion ToRefresh()
{
return new Refresh.BufferRegion
{
Buffer = Buffer.Handle,
Offset = Offset,
Size = Size
};
}
}
/// <summary>
/// A buffer-offset pair to be used when binding buffers.
/// </summary>
public record struct BufferBinding(
Buffer Buffer,
uint Offset
) {
public Refresh.BufferBinding ToRefresh()
{
return new Refresh.BufferBinding
{
Buffer = Buffer.Handle,
Offset = Offset
};
}
}
/// <summary>
/// A texture-sampler pair to be used when binding samplers.
/// </summary>
public record struct TextureSamplerBinding(
Texture Texture,
Sampler Sampler
) {
public Refresh.TextureSamplerBinding ToRefresh()
{
return new Refresh.TextureSamplerBinding
{
Texture = Texture.Handle,
Sampler = Sampler.Handle
};
}
}
public record struct StorageBufferReadWriteBinding(
Buffer Buffer,
bool Cycle
) {
public Refresh.StorageBufferReadWriteBinding ToRefresh()
{
return new Refresh.StorageBufferReadWriteBinding
{
Buffer = Buffer.Handle,
Cycle = Conversions.BoolToInt(Cycle)
};
}
}
public record struct StorageTextureReadWriteBinding(
in TextureSlice TextureSlice,
bool Cycle
) {
public Refresh.StorageTextureReadWriteBinding ToRefresh()
{
return new Refresh.StorageTextureReadWriteBinding
{
TextureSlice = TextureSlice.ToRefresh(),
Cycle = Conversions.BoolToInt(Cycle)
};
}
}
/// <summary>
/// A convenience structure for pairing a vertex binding with its associated attributes.
/// </summary>
public struct VertexBindingAndAttributes
{
public VertexBinding VertexBinding { get; }
public VertexAttribute[] VertexAttributes { get; }
public VertexBindingAndAttributes(VertexBinding binding, VertexAttribute[] attributes)
{
VertexBinding = binding;
VertexAttributes = attributes;
}
public static VertexBindingAndAttributes Create<T>(uint bindingIndex, uint locationOffset = 0, VertexInputRate inputRate = VertexInputRate.Vertex) where T : unmanaged, IVertexType
{
VertexBinding binding = VertexBinding.Create<T>(bindingIndex, inputRate);
VertexAttribute[] attributes = new VertexAttribute[T.Formats.Length];
for (uint i = 0; i < T.Formats.Length; i += 1)
{
VertexElementFormat format = T.Formats[i];
uint offset = T.Offsets[i];
attributes[i] = new VertexAttribute
{
Binding = bindingIndex,
Location = locationOffset + i,
Format = format,
Offset = offset
};
}
return new VertexBindingAndAttributes(binding, attributes);
}
}
/// <summary>
/// Specifies how the vertex shader will interpet vertex data in a buffer.
/// </summary>
public struct VertexInputState
{
public VertexBinding[] VertexBindings;
public VertexAttribute[] VertexAttributes;
public static readonly VertexInputState Empty = new VertexInputState
{
VertexBindings = System.Array.Empty<VertexBinding>(),
VertexAttributes = System.Array.Empty<VertexAttribute>()
};
public VertexInputState(
VertexBinding vertexBinding,
VertexAttribute[] vertexAttributes
) {
VertexBindings = new VertexBinding[] { vertexBinding };
VertexAttributes = vertexAttributes;
}
public VertexInputState(
VertexBinding[] vertexBindings,
VertexAttribute[] vertexAttributes
) {
VertexBindings = vertexBindings;
VertexAttributes = vertexAttributes;
}
public VertexInputState(
VertexBindingAndAttributes bindingAndAttributes
) {
VertexBindings = new VertexBinding[] { bindingAndAttributes.VertexBinding };
VertexAttributes = bindingAndAttributes.VertexAttributes;
}
public VertexInputState(
VertexBindingAndAttributes[] bindingAndAttributesArray
) {
VertexBindings = new VertexBinding[bindingAndAttributesArray.Length];
int attributesLength = 0;
for (int i = 0; i < bindingAndAttributesArray.Length; i += 1)
{
VertexBindings[i] = bindingAndAttributesArray[i].VertexBinding;
attributesLength += bindingAndAttributesArray[i].VertexAttributes.Length;
}
VertexAttributes = new VertexAttribute[attributesLength];
int attributeIndex = 0;
for (int i = 0; i < bindingAndAttributesArray.Length; i += 1)
{
for (int j = 0; j < bindingAndAttributesArray[i].VertexAttributes.Length; j += 1)
{
VertexAttributes[attributeIndex] = bindingAndAttributesArray[i].VertexAttributes[j];
attributeIndex += 1;
}
}
}
public static VertexInputState CreateSingleBinding<T>() where T : unmanaged, IVertexType
{
return new VertexInputState(VertexBindingAndAttributes.Create<T>(0));
}
}
/// <summary>
/// Specifies how the rasterizer should be configured for a graphics pipeline.
/// </summary>
public struct RasterizerState
{
/// <summary>
/// Specifies whether front faces, back faces, none, or both should be culled.
/// </summary>
public CullMode CullMode;
/// <summary>
/// Specifies maximum depth bias of a fragment. Only applies if depth biasing is enabled.
/// </summary>
public float DepthBiasClamp;
/// <summary>
/// The constant depth value added to each fragment. Only applies if depth biasing is enabled.
/// </summary>
public float DepthBiasConstantFactor;
/// <summary>
/// Specifies whether depth biasing is enabled. Only applies if depth biasing is enabled.
/// </summary>
public bool DepthBiasEnable;
/// <summary>
/// Factor applied to a fragment's slope in depth bias calculations. Only applies if depth biasing is enabled.
/// </summary>
public float DepthBiasSlopeFactor;
/// <summary>
/// Specifies how triangles should be drawn.
/// </summary>
public FillMode FillMode;
/// <summary>
/// Specifies which triangle winding order is designated as front-facing.
/// </summary>
public FrontFace FrontFace;
public static readonly RasterizerState CW_CullFront = new RasterizerState
{
CullMode = CullMode.Front,
FrontFace = FrontFace.Clockwise,
FillMode = FillMode.Fill,
DepthBiasEnable = false
};
public static readonly RasterizerState CW_CullBack = new RasterizerState
{
CullMode = CullMode.Back,
FrontFace = FrontFace.Clockwise,
FillMode = FillMode.Fill,
DepthBiasEnable = false
};
public static readonly RasterizerState CW_CullNone = new RasterizerState
{
CullMode = CullMode.None,
FrontFace = FrontFace.Clockwise,
FillMode = FillMode.Fill,
DepthBiasEnable = false
};
public static readonly RasterizerState CW_Wireframe = new RasterizerState
{
CullMode = CullMode.None,
FrontFace = FrontFace.Clockwise,
FillMode = FillMode.Line,
DepthBiasEnable = false
};
public static readonly RasterizerState CCW_CullFront = new RasterizerState
{
CullMode = CullMode.Front,
FrontFace = FrontFace.CounterClockwise,
FillMode = FillMode.Fill,
DepthBiasEnable = false
};
public static readonly RasterizerState CCW_CullBack = new RasterizerState
{
CullMode = CullMode.Back,
FrontFace = FrontFace.CounterClockwise,
FillMode = FillMode.Fill,
DepthBiasEnable = false
};
public static readonly RasterizerState CCW_CullNone = new RasterizerState
{
CullMode = CullMode.None,
FrontFace = FrontFace.CounterClockwise,
FillMode = FillMode.Fill,
DepthBiasEnable = false
};
public static readonly RasterizerState CCW_Wireframe = new RasterizerState
{
CullMode = CullMode.None,
FrontFace = FrontFace.CounterClockwise,
FillMode = FillMode.Line,
DepthBiasEnable = false
};
public Refresh.RasterizerState ToRefresh()
{
return new Refresh.RasterizerState
{
CullMode = (Refresh.CullMode) CullMode,
DepthBiasClamp = DepthBiasClamp,
DepthBiasConstantFactor = DepthBiasConstantFactor,
DepthBiasEnable = Conversions.BoolToInt(DepthBiasEnable),
DepthBiasSlopeFactor = DepthBiasSlopeFactor,
FillMode = (Refresh.FillMode) FillMode,
FrontFace = (Refresh.FrontFace) FrontFace
};
}
}
/// <summary>
/// Specifies how many samples should be used in rasterization.
/// </summary>
public struct MultisampleState
{
public SampleCount MultisampleCount;
public uint SampleMask;
public static readonly MultisampleState None = new MultisampleState
{
MultisampleCount = SampleCount.One,
SampleMask = uint.MaxValue
};
public MultisampleState(
SampleCount sampleCount,
uint sampleMask = uint.MaxValue
) {
MultisampleCount = sampleCount;
SampleMask = sampleMask;
}
public Refresh.MultisampleState ToRefresh()
{
return new Refresh.MultisampleState
{
MultisampleCount = (Refresh.SampleCount) MultisampleCount,
SampleMask = SampleMask
};
}
}
/// <summary>
/// Determines how data is written to and read from the depth/stencil buffer.
/// </summary>
public struct DepthStencilState
{
/// <summary>
/// If disabled, no depth culling will occur.
/// </summary>
public bool DepthTestEnable;
/// <summary>
/// Describes the back-face stencil operation.
/// </summary>
public StencilOpState BackStencilState;
/// <summary>
/// Describes the front-face stencil operation.
/// </summary>
public StencilOpState FrontStencilState;
/// <summary>
/// The compare mask for stencil ops.
/// </summary>
public uint CompareMask;
/// <summary>
/// The write mask for stencil ops.
/// </summary>
public uint WriteMask;
/// <summary>
/// The stencil reference value.
/// </summary>
public uint Reference;
/// <summary>
/// The comparison operator used in the depth test.
/// </summary>
public CompareOp CompareOp;
/// <summary>
/// Specifies whether depth values will be written to the buffer during rendering.
/// </summary>
public bool DepthWriteEnable;
/// <summary>
/// If disabled, no stencil culling will occur.
/// </summary>
public bool StencilTestEnable;
public static readonly DepthStencilState DepthReadWrite = new DepthStencilState
{
DepthTestEnable = true,
DepthWriteEnable = true,
StencilTestEnable = false,
CompareOp = CompareOp.LessOrEqual
};
public static readonly DepthStencilState DepthRead = new DepthStencilState
{
DepthTestEnable = true,
DepthWriteEnable = false,
StencilTestEnable = false,
CompareOp = CompareOp.LessOrEqual
};
public static readonly DepthStencilState Disable = new DepthStencilState
{
DepthTestEnable = false,
DepthWriteEnable = false,
StencilTestEnable = false
};
public Refresh.DepthStencilState ToRefresh()
{
return new Refresh.DepthStencilState
{
DepthTestEnable = Conversions.BoolToInt(DepthTestEnable),
BackStencilState = BackStencilState.ToRefresh(),
FrontStencilState = FrontStencilState.ToRefresh(),
CompareMask = CompareMask,
WriteMask = WriteMask,
Reference = Reference,
CompareOp = (Refresh.CompareOp) CompareOp,
DepthWriteEnable = Conversions.BoolToInt(DepthWriteEnable),
StencilTestEnable = Conversions.BoolToInt(StencilTestEnable)
};
}
}
/// <summary>
/// Describes the kind of attachments that will be used with this pipeline.
/// </summary>
public struct GraphicsPipelineAttachmentInfo
{
public ColorAttachmentDescription[] ColorAttachmentDescriptions;
public bool HasDepthStencilAttachment;
public TextureFormat DepthStencilFormat;
public GraphicsPipelineAttachmentInfo(
params ColorAttachmentDescription[] colorAttachmentDescriptions
) {
ColorAttachmentDescriptions = colorAttachmentDescriptions;
HasDepthStencilAttachment = false;
DepthStencilFormat = TextureFormat.D16_UNORM;
}
public GraphicsPipelineAttachmentInfo(
TextureFormat depthStencilFormat,
params ColorAttachmentDescription[] colorAttachmentDescriptions
) {
ColorAttachmentDescriptions = colorAttachmentDescriptions;
HasDepthStencilAttachment = true;
DepthStencilFormat = depthStencilFormat;
}
}
public struct BlendConstants
{
public float R;
public float G;
public float B;
public float A;
}
/// <summary>
/// All of the information that is used to create a GraphicsPipeline.
/// </summary>
public struct GraphicsPipelineCreateInfo
{
public Shader VertexShader;
public Shader FragmentShader;
public VertexInputState VertexInputState;
public PrimitiveType PrimitiveType;
public RasterizerState RasterizerState;
public MultisampleState MultisampleState;
public DepthStencilState DepthStencilState;
public GraphicsPipelineAttachmentInfo AttachmentInfo;
public BlendConstants BlendConstants;
}
public struct ComputePipelineCreateInfo
{
public ShaderFormat ShaderFormat;
public uint ReadOnlyStorageTextureCount;
public uint ReadOnlyStorageBufferCount;
public uint ReadWriteStorageTextureCount;
public uint ReadWriteStorageBufferCount;
public uint UniformBufferCount;
public uint ThreadCountX;
public uint ThreadCountY;
public uint ThreadCountZ;
}
public struct ShaderCreateInfo
{
public ShaderStage ShaderStage;
public ShaderFormat ShaderFormat;
public uint SamplerCount;
public uint StorageTextureCount;
public uint StorageBufferCount;
public uint UniformBufferCount;
public static ShaderCreateInfo None = new ShaderCreateInfo();
}
/// <summary>
/// All of the information that is used to create a texture.
/// </summary>
public struct TextureCreateInfo
{
public uint Width;
public uint Height;
public uint Depth;
public bool IsCube;
public uint LayerCount;
public uint LevelCount;
public SampleCount SampleCount;
public TextureFormat Format;
public TextureUsageFlags UsageFlags;
public Refresh.TextureCreateInfo ToRefresh()
{
return new Refresh.TextureCreateInfo
{
Width = Width,
Height = Height,
Depth = Depth,
IsCube = Conversions.BoolToInt(IsCube),
LayerCount = LayerCount,
LevelCount = LevelCount,
SampleCount = (Refresh.SampleCount) SampleCount,
Format = (Refresh.TextureFormat) Format,
UsageFlags = (Refresh.TextureUsageFlags) UsageFlags
};
}
}
/// <summary>
/// All of the information that is used to create a sampler.
/// </summary>
public struct SamplerCreateInfo
{
/// <summary>
/// Minification filter mode. Used when the image is downscaled.
/// </summary>
public Filter MinFilter;
/// <summary>
/// Magnification filter mode. Used when the image is upscaled.
/// </summary>
public Filter MagFilter;
/// <summary>
/// Filter mode applied to mipmap lookups.
/// </summary>
public SamplerMipmapMode MipmapMode;
/// <summary>
/// Horizontal addressing mode.
/// </summary>
public SamplerAddressMode AddressModeU;
/// <summary>
/// Vertical addressing mode.
/// </summary>
public SamplerAddressMode AddressModeV;
/// <summary>
/// Depth addressing mode.
/// </summary>
public SamplerAddressMode AddressModeW;
/// <summary>
/// Bias value added to mipmap level of detail calculation.
/// </summary>
public float MipLodBias;
/// <summary>
/// Enables anisotropic filtering.
/// </summary>
public bool AnisotropyEnable;
/// <summary>
/// Maximum anisotropy value.
/// </summary>
public float MaxAnisotropy;
public bool CompareEnable;
public CompareOp CompareOp;
/// <summary>
/// Clamps the LOD value to a specified minimum.
/// </summary>
public float MinLod;
/// <summary>
/// Clamps the LOD value to a specified maximum.
/// </summary>
public float MaxLod;
public static readonly SamplerCreateInfo AnisotropicClamp = new SamplerCreateInfo
{
MinFilter = Filter.Linear,
MagFilter = Filter.Linear,
MipmapMode = SamplerMipmapMode.Linear,
AddressModeU = SamplerAddressMode.ClampToEdge,
AddressModeV = SamplerAddressMode.ClampToEdge,
AddressModeW = SamplerAddressMode.ClampToEdge,
CompareEnable = false,
AnisotropyEnable = true,
MaxAnisotropy = 4,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000 /* VK_LOD_CLAMP_NONE */
};
public static readonly SamplerCreateInfo AnisotropicWrap = new SamplerCreateInfo
{
MinFilter = Filter.Linear,
MagFilter = Filter.Linear,
MipmapMode = SamplerMipmapMode.Linear,
AddressModeU = SamplerAddressMode.Repeat,
AddressModeV = SamplerAddressMode.Repeat,
AddressModeW = SamplerAddressMode.Repeat,
CompareEnable = false,
AnisotropyEnable = true,
MaxAnisotropy = 4,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000 /* VK_LOD_CLAMP_NONE */
};
public static readonly SamplerCreateInfo LinearClamp = new SamplerCreateInfo
{
MinFilter = Filter.Linear,
MagFilter = Filter.Linear,
MipmapMode = SamplerMipmapMode.Linear,
AddressModeU = SamplerAddressMode.ClampToEdge,
AddressModeV = SamplerAddressMode.ClampToEdge,
AddressModeW = SamplerAddressMode.ClampToEdge,
CompareEnable = false,
AnisotropyEnable = false,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000
};
public static readonly SamplerCreateInfo LinearWrap = new SamplerCreateInfo
{
MinFilter = Filter.Linear,
MagFilter = Filter.Linear,
MipmapMode = SamplerMipmapMode.Linear,
AddressModeU = SamplerAddressMode.Repeat,
AddressModeV = SamplerAddressMode.Repeat,
AddressModeW = SamplerAddressMode.Repeat,
CompareEnable = false,
AnisotropyEnable = false,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000
};
public static readonly SamplerCreateInfo PointClamp = new SamplerCreateInfo
{
MinFilter = Filter.Nearest,
MagFilter = Filter.Nearest,
MipmapMode = SamplerMipmapMode.Nearest,
AddressModeU = SamplerAddressMode.ClampToEdge,
AddressModeV = SamplerAddressMode.ClampToEdge,
AddressModeW = SamplerAddressMode.ClampToEdge,
CompareEnable = false,
AnisotropyEnable = false,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000
};
public static readonly SamplerCreateInfo PointWrap = new SamplerCreateInfo
{
MinFilter = Filter.Nearest,
MagFilter = Filter.Nearest,
MipmapMode = SamplerMipmapMode.Nearest,
AddressModeU = SamplerAddressMode.Repeat,
AddressModeV = SamplerAddressMode.Repeat,
AddressModeW = SamplerAddressMode.Repeat,
CompareEnable = false,
AnisotropyEnable = false,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000
};
public Refresh.SamplerCreateInfo ToRefresh()
{
return new Refresh.SamplerCreateInfo
{
MinFilter = (Refresh.Filter) MinFilter,
MagFilter = (Refresh.Filter) MagFilter,
MipmapMode = (Refresh.SamplerMipmapMode) MipmapMode,
AddressModeU = (Refresh.SamplerAddressMode) AddressModeU,
AddressModeV = (Refresh.SamplerAddressMode) AddressModeV,
AddressModeW = (Refresh.SamplerAddressMode) AddressModeW,
MipLodBias = MipLodBias,
AnisotropyEnable = Conversions.BoolToInt(AnisotropyEnable),
MaxAnisotropy = MaxAnisotropy,
CompareEnable = Conversions.BoolToInt(CompareEnable),
CompareOp = (Refresh.CompareOp) CompareOp,
MinLod = MinLod,
MaxLod = MaxLod
};
}
}
/// <summary>
/// Contains data pertaining to a texture upload or download.
/// </summary>
public record struct TextureTransferInfo(
TransferBuffer TransferBuffer,
uint Offset = 0,
uint ImagePitch = 0,
uint ImageHeight = 0
) {
public Refresh.TextureTransferInfo ToRefresh()
{
return new Refresh.TextureTransferInfo
{
TransferBuffer = TransferBuffer.Handle,
Offset = Offset,
ImagePitch = ImagePitch,
ImageHeight = ImageHeight
};
}
}
public record struct TransferBufferLocation(
TransferBuffer TransferBuffer,
uint Offset = 0
) {
public Refresh.TransferBufferLocation ToRefresh()
{
return new Refresh.TransferBufferLocation
{
TransferBuffer = TransferBuffer.Handle,
Offset = Offset
};
}
}
public record struct TransferBufferRegion(
TransferBuffer TransferBuffer,
uint Offset,
uint Size
) {
public Refresh.TransferBufferRegion ToRefresh()
{
return new Refresh.TransferBufferRegion
{
TransferBuffer = TransferBuffer.Handle,
Offset = Offset,
Size = Size
};
}
}
/// <summary>
/// A texture slice specifies a subresource of a texture.
/// </summary>
public record struct TextureSlice(
Texture Texture,
uint MipLevel = 0,
uint Layer = 0
) {
public uint Size => (Texture.Width * Texture.Height * Texture.Depth * Texture.BytesPerPixel(Texture.Format) / Texture.BlockSizeSquared(Texture.Format)) >> (int) MipLevel;
public Refresh.TextureSlice ToRefresh()
{
return new Refresh.TextureSlice
{
Texture = Texture.Handle,
MipLevel = MipLevel,
Layer = Layer
};
}
}
public record struct TextureLocation
(
TextureSlice TextureSlice,
uint X = 0,
uint Y = 0,
uint Z = 0
) {
public Refresh.TextureLocation ToRefresh()
{
return new Refresh.TextureLocation
{
TextureSlice = TextureSlice.ToRefresh(),
X = X,
Y = Y,
Z = Z
};
}
}
/// <summary>
/// A texture region specifies a subregion of a texture.
/// These are used by copy commands.
/// </summary>
public record struct TextureRegion(
TextureSlice TextureSlice,
uint X,
uint Y,
uint Z,
uint Width,
uint Height,
uint Depth
) {
public uint Size => (Width * Height * Depth * Texture.BytesPerPixel(TextureSlice.Texture.Format) / Texture.BlockSizeSquared(TextureSlice.Texture.Format)) >> (int) TextureSlice.MipLevel;
public TextureRegion(Texture texture) : this(texture, 0, 0, 0, texture.Width, texture.Height, texture.Depth) { }
public Refresh.TextureRegion ToRefresh()
{
return new Refresh.TextureRegion
{
TextureSlice = TextureSlice.ToRefresh(),
X = X,
Y = Y,
Z = Z,
W = Width,
H = Height,
D = Depth
};
}
}