diff --git a/lib/SDL2_gpuCS b/lib/SDL2_gpuCS index b3cf918..2866dd2 160000 --- a/lib/SDL2_gpuCS +++ b/lib/SDL2_gpuCS @@ -1 +1 @@ -Subproject commit b3cf918f900a24d131b4eb130a87dd12b4e4ca8c +Subproject commit 2866dd2a7d4ffd4366bd4885e04c68cf4b485b55 diff --git a/src/Conversions.cs b/src/Conversions.cs index 5a5fb3f..d0b75b7 100644 --- a/src/Conversions.cs +++ b/src/Conversions.cs @@ -21,7 +21,7 @@ namespace MoonWorks { VertexElementFormat.NormalizedShort4, (uint) Marshal.SizeOf() }, { VertexElementFormat.Short2, (uint) Marshal.SizeOf() }, { VertexElementFormat.Short4, (uint) Marshal.SizeOf() }, - { VertexElementFormat.UInt, (uint) Marshal.SizeOf() }, + { VertexElementFormat.Uint, (uint) Marshal.SizeOf() }, { VertexElementFormat.Vector2, (uint) Marshal.SizeOf() }, { VertexElementFormat.Vector3, (uint) Marshal.SizeOf() }, { VertexElementFormat.Vector4, (uint) Marshal.SizeOf() } @@ -37,6 +37,16 @@ namespace MoonWorks return b != 0; } + public static int BoolToInt(bool b) + { + return b ? 1 : 0; + } + + public static bool IntToBool(int b) + { + return b != 0; + } + public static uint VertexElementFormatSize(VertexElementFormat format) { return Sizes[format]; diff --git a/src/Graphics/RefreshEnums.cs b/src/Graphics/RefreshEnums.cs deleted file mode 100644 index 0c89560..0000000 --- a/src/Graphics/RefreshEnums.cs +++ /dev/null @@ -1,326 +0,0 @@ -using System; - -namespace MoonWorks -{ - /// - /// Presentation mode for a window. - /// - public enum PresentMode - { - /// - /// Does not wait for v-blank to update the window. Can cause visible tearing. - /// - Immediate, - /// - /// Waits for v-blank and uses a queue to hold present requests. - /// Allows for low latency while preventing tearing. - /// May not be supported on non-Vulkan non-Linux systems or older hardware. - /// - Mailbox, - /// - /// Waits for v-blank and adds present requests to a queue. - /// Will probably cause latency. - /// Required to be supported by all compliant hardware. - /// - FIFO, - /// - /// Usually waits for v-blank, but if v-blank has passed since last update will update immediately. - /// May cause visible tearing. - /// - FIFORelaxed - } -} - -/* Recreate all the enums in here so we don't need to explicitly - * reference the RefreshCS namespace when using MoonWorks.Graphics - */ -namespace MoonWorks.Graphics -{ - public enum PrimitiveType - { - PointList, - LineList, - LineStrip, - TriangleList, - TriangleStrip - } - - /// - /// Describes the operation that a render pass will use when loading a render target. - /// - public enum LoadOp - { - Load, - Clear, - DontCare - } - - /// - /// Describes the operation that a render pass will use when storing a render target. - /// - public enum StoreOp - { - Store, - DontCare - } - - [Flags] - public enum ClearOptionsFlags : uint - { - Color = 1, - Depth = 2, - Stencil = 4, - DepthStencil = Depth | Stencil, - All = Color | Depth | Stencil - } - - public enum IndexElementSize - { - Sixteen, - ThirtyTwo - } - - public enum TextureFormat - { - R8G8B8A8, - B8G8R8A8, - R5G6B5, - A1R5G5B5, - B4G4R4A4, - A2R10G10B10, - R16G16, - R16G16B16A16, - R8, - BC1, - BC2, - BC3, - BC7, - R8G8_SNORM, - R8G8B8A8_SNORM, - R16_SFLOAT, - R16G16_SFLOAT, - R16G16B16A16_SFLOAT, - R32_SFLOAT, - R32G32_SFLOAT, - R32G32B32A32_SFLOAT, - - R8_UINT, - R8G8_UINT, - R8G8B8A8_UINT, - R16_UINT, - R16G16_UINT, - R16G16B16A16_UINT, - D16, - D32, - D16S8, - D32S8 - } - - [Flags] - public enum TextureUsageFlags : uint - { - Sampler = 1, - ColorTarget = 2, - DepthStencilTarget = 4, - Compute = 8 - } - - public enum SampleCount - { - One, - Two, - Four, - Eight - } - - public enum CubeMapFace : uint - { - PositiveX, - NegativeX, - PositiveY, - NegativeY, - PositiveZ, - NegativeZ - } - - [Flags] - public enum BufferUsageFlags : uint - { - Vertex = 1, - Index = 2, - Compute = 4, - Indirect = 8 - } - - 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 : uint - { - R = 1, - G = 2, - B = 4, - A = 8, - - RG = R | G, - RB = R | B, - RA = R | A, - GB = G | B, - GA = G | A, - BA = B | A, - - RGB = R | G | B, - RGA = R | G | A, - GBA = G | B | A, - - RGBA = R | G | B | A, - None = 0 - } - - public enum Filter - { - Nearest, - Linear - } - - public enum SamplerMipmapMode - { - Nearest, - Linear - } - - public enum SamplerAddressMode - { - Repeat, - MirroredRepeat, - ClampToEdge, - ClampToBorder - } - - public enum BorderColor - { - FloatTransparentBlack, - IntTransparentBlack, - FloatOpaqueBlack, - IntOpaqueBlack, - FloatOpaqueWhite, - IntOpaqueWhite - } - - public enum TransferUsage - { - Buffer, - Texture - } - - public enum TransferOptions - { - Cycle, - Unsafe - } - - public enum WriteOptions - { - Cycle, - Unsafe, - Safe - } - - public enum Backend - { - Vulkan, - D3D11, - PS5, - Invalid - } -} diff --git a/src/Graphics/RefreshStructs.cs b/src/Graphics/RefreshStructs.cs deleted file mode 100644 index 9d6d88a..0000000 --- a/src/Graphics/RefreshStructs.cs +++ /dev/null @@ -1,508 +0,0 @@ -using RefreshCS; -using System.Runtime.InteropServices; - -/* Recreate some structs in here so we don't need to explicitly - * reference the RefreshCS namespace when using MoonWorks.Graphics - */ -namespace MoonWorks.Graphics -{ - [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 static VertexBinding Create(uint binding = 0, VertexInputRate inputRate = VertexInputRate.Vertex) where T : unmanaged - { - return new VertexBinding - { - Binding = binding, - InputRate = inputRate, - Stride = (uint) Marshal.SizeOf() - }; - } - } - - [StructLayout(LayoutKind.Sequential)] - public struct VertexAttribute - { - public uint Location; - public uint Binding; - public VertexElementFormat Format; - public uint 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 - }; - } - } - - /// - /// Determines how a color texture will be read/written in a render pass. - /// - public struct ColorAttachmentInfo - { - public TextureSlice TextureSlice; - - /// - /// If LoadOp is set to Clear, the texture slice will be cleared to this color. - /// - public Color ClearColor; - - /// - /// Determines what is done with the texture slice memory - /// at the beginning of the render pass.
- /// - /// Load: - /// Loads the data currently in the texture slice.
- /// - /// Clear: - /// Clears the texture slice to a single color.
- /// - /// 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. - ///
- public LoadOp LoadOp; - - /// - /// Determines what is done with the texture slice memory - /// at the end of the render pass.
- /// - /// Store: - /// Stores the results of the render pass in the texture slice memory.
- /// - /// DontCare: - /// The driver will do whatever it wants with the texture slice memory. - ///
- public StoreOp StoreOp; - - /// - /// Specifies data dependency behavior. This option is ignored if LoadOp is Load.
- /// - /// Cycle: - /// If this texture slice has been used in commands that have not completed, - /// the implementation may prevent a dependency on those commands - /// at the cost of increased memory usage. - /// You may NOT assume that any of the previous texture (not slice!) data is retained. - /// This may prevent stalls when frequently reusing a texture slice in rendering.
- /// - /// SafeOverwrite: - /// Overwrites the data safely using a GPU memory barrier. - ///
- public WriteOptions WriteOption; - - public ColorAttachmentInfo( - TextureSlice textureSlice, - WriteOptions writeOption, - Color clearColor, - StoreOp storeOp = StoreOp.Store - ) { - TextureSlice = textureSlice; - ClearColor = clearColor; - LoadOp = LoadOp.Clear; - StoreOp = storeOp; - WriteOption = writeOption; - } - - public ColorAttachmentInfo( - TextureSlice textureSlice, - WriteOptions writeOption, - LoadOp loadOp = LoadOp.DontCare, - StoreOp storeOp = StoreOp.Store - ) { - TextureSlice = textureSlice; - ClearColor = Color.White; - LoadOp = loadOp; - StoreOp = storeOp; - WriteOption = writeOption; - } - - public Refresh.ColorAttachmentInfo ToRefresh() - { - return new Refresh.ColorAttachmentInfo - { - textureSlice = TextureSlice.ToRefreshTextureSlice(), - clearColor = new Refresh.Vec4 - { - x = ClearColor.R / 255f, - y = ClearColor.G / 255f, - z = ClearColor.B / 255f, - w = ClearColor.A / 255f - }, - loadOp = (Refresh.LoadOp) LoadOp, - storeOp = (Refresh.StoreOp) StoreOp, - writeOption = (Refresh.WriteOptions) WriteOption - }; - } - } - - /// - /// Determines how a depth/stencil texture will be read/written in a render pass. - /// - public struct DepthStencilAttachmentInfo - { - public TextureSlice TextureSlice; - - /// - /// If LoadOp is set to Clear, the texture slice depth will be cleared to this depth value.
- /// If StencilLoadOp is set to Clear, the texture slice stencil value will be cleared to this stencil value. - ///
- public DepthStencilValue DepthStencilClearValue; - - /// - /// Determines what is done with the texture slice depth values - /// at the beginning of the render pass.
- /// - /// Load: - /// Loads the data currently in the texture slice.
- /// - /// Clear: - /// Clears the texture slice to a single depth value.
- /// - /// 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. - ///
- public LoadOp LoadOp; - - /// - /// Determines what is done with the texture slice depth values - /// at the end of the render pass.
- /// - /// Store: - /// Stores the results of the render pass in the texture slice memory.
- /// - /// 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. - ///
- public StoreOp StoreOp; - - /// - /// Determines what is done with the texture slice stencil values - /// at the beginning of the render pass.
- /// - /// Load: - /// Loads the data currently in the texture slice.
- /// - /// Clear: - /// Clears the texture slice to a single stencil value.
- /// - /// 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. - ///
- public LoadOp StencilLoadOp; - - /// - /// Determines what is done with the texture slice stencil values - /// at the end of the render pass.
- /// - /// Store: - /// Stores the results of the render pass in the texture slice memory.
- /// - /// 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. - ///
- public StoreOp StencilStoreOp; - - /// - /// Specifies data dependency behavior. This option is ignored if LoadOp or StencilLoadOp is Load.
- /// - /// Cycle: - /// If this texture slice has been used in commands that have not completed, - /// the implementation may prevent a dependency on those commands - /// at the cost of increased memory usage. - /// You may NOT assume that any of the previous texture (not slice!) data is retained. - /// This may prevent stalls when frequently reusing a texture slice in rendering.
- /// - /// SafeOverwrite: - /// Overwrites the data safely using a GPU memory barrier. - ///
- public WriteOptions WriteOption; - - public DepthStencilAttachmentInfo( - TextureSlice textureSlice, - WriteOptions writeOption, - DepthStencilValue clearValue, - StoreOp depthStoreOp = StoreOp.DontCare, - StoreOp stencilStoreOp = StoreOp.DontCare - ){ - TextureSlice = textureSlice; - DepthStencilClearValue = clearValue; - LoadOp = LoadOp.Clear; - StoreOp = depthStoreOp; - StencilLoadOp = LoadOp.Clear; - StencilStoreOp = stencilStoreOp; - WriteOption = writeOption; - } - - public DepthStencilAttachmentInfo( - TextureSlice textureSlice, - WriteOptions writeOption, - 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; - WriteOption = writeOption; - } - - public DepthStencilAttachmentInfo( - TextureSlice textureSlice, - WriteOptions writeOption, - DepthStencilValue clearValue, - LoadOp loadOp, - StoreOp storeOp, - LoadOp stencilLoadOp, - StoreOp stencilStoreOp - ) { - TextureSlice = textureSlice; - DepthStencilClearValue = clearValue; - LoadOp = loadOp; - StoreOp = storeOp; - StencilLoadOp = stencilLoadOp; - StencilStoreOp = stencilStoreOp; - WriteOption = writeOption; - } - - public Refresh.DepthStencilAttachmentInfo ToRefresh() - { - return new Refresh.DepthStencilAttachmentInfo - { - textureSlice = TextureSlice.ToRefreshTextureSlice(), - depthStencilClearValue = DepthStencilClearValue.ToRefresh(), - loadOp = (Refresh.LoadOp) LoadOp, - storeOp = (Refresh.StoreOp) StoreOp, - stencilLoadOp = (Refresh.LoadOp) StencilLoadOp, - stencilStoreOp = (Refresh.StoreOp) StencilStoreOp, - writeOption = (Refresh.WriteOptions) WriteOption - }; - } - } - - [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; - } - } - - [StructLayout(LayoutKind.Sequential)] - public struct BufferCopy - { - public uint SrcOffset; - public uint DstOffset; - public uint Size; - - public BufferCopy( - uint srcOffset, - uint dstOffset, - uint size - ) { - SrcOffset = srcOffset; - DstOffset = dstOffset; - Size = size; - } - - public Refresh.BufferCopy ToRefresh() - { - return new Refresh.BufferCopy - { - srcOffset = SrcOffset, - dstOffset = DstOffset, - size = Size - }; - } - } - - /// - /// Parameters for a copy between buffer and image. - /// - /// The offset into the buffer. - /// If 0, image data is assumed tightly packed. - /// If 0, image data is assumed tightly packed. - [StructLayout(LayoutKind.Sequential)] - public readonly record struct BufferImageCopy( - uint BufferOffset, - uint BufferStride, - uint BufferImageHeight - ) { - public Refresh.BufferImageCopy ToRefresh() - { - return new Refresh.BufferImageCopy - { - bufferOffset = BufferOffset, - bufferStride = BufferStride, - bufferImageHeight = BufferImageHeight - }; - } - } -} diff --git a/src/Graphics/Resources/ComputePipeline.cs b/src/Graphics/Resources/ComputePipeline.cs index 19312c2..89da094 100644 --- a/src/Graphics/Resources/ComputePipeline.cs +++ b/src/Graphics/Resources/ComputePipeline.cs @@ -6,9 +6,9 @@ namespace MoonWorks.Graphics /// /// Compute pipelines perform arbitrary parallel processing on input data. /// - public class ComputePipeline : RefreshResource + public class ComputePipeline : SDL_GpuResource { - protected override Action QueueDestroyFunction => Refresh.Refresh_QueueDestroyComputePipeline; + protected override Action ReleaseFunction => Refresh.Refresh_QueueDestroyComputePipeline; public ComputeShaderInfo ComputeShaderInfo { get; } diff --git a/src/Graphics/Resources/Fence.cs b/src/Graphics/Resources/Fence.cs index 223620e..2f61fdf 100644 --- a/src/Graphics/Resources/Fence.cs +++ b/src/Graphics/Resources/Fence.cs @@ -10,9 +10,9 @@ namespace MoonWorks.Graphics /// The Fence object itself is basically just a wrapper for the Refresh_Fence.
/// The internal handle is replaced so that we can pool Fence objects to manage garbage. /// - public class Fence : RefreshResource + public class Fence : SDL_GpuResource { - protected override Action QueueDestroyFunction => Refresh.Refresh_ReleaseFence; + protected override Action ReleaseFunction => Refresh.Refresh_ReleaseFence; internal Fence(GraphicsDevice device) : base(device) { diff --git a/src/Graphics/Resources/GpuBuffer.cs b/src/Graphics/Resources/GpuBuffer.cs index 7a673cf..be07dd0 100644 --- a/src/Graphics/Resources/GpuBuffer.cs +++ b/src/Graphics/Resources/GpuBuffer.cs @@ -7,9 +7,9 @@ namespace MoonWorks.Graphics /// /// GpuBuffers are generic data containers that can be used by the GPU. /// - public class GpuBuffer : RefreshResource + public class GpuBuffer : SDL_GpuResource { - protected override Action QueueDestroyFunction => Refresh.Refresh_QueueDestroyGpuBuffer; + protected override Action ReleaseFunction => Refresh.Refresh_QueueDestroyGpuBuffer; /// /// Size in bytes. diff --git a/src/Graphics/Resources/GraphicsPipeline.cs b/src/Graphics/Resources/GraphicsPipeline.cs index a25995f..e69889c 100644 --- a/src/Graphics/Resources/GraphicsPipeline.cs +++ b/src/Graphics/Resources/GraphicsPipeline.cs @@ -8,9 +8,9 @@ namespace MoonWorks.Graphics /// Graphics pipelines encapsulate all of the render state in a single object.
/// These pipelines are bound before draw calls are issued. ///
- public class GraphicsPipeline : RefreshResource + public class GraphicsPipeline : SDL_GpuResource { - protected override Action QueueDestroyFunction => Refresh.Refresh_QueueDestroyGraphicsPipeline; + protected override Action ReleaseFunction => Refresh.Refresh_QueueDestroyGraphicsPipeline; public GraphicsShaderInfo VertexShaderInfo { get; } public GraphicsShaderInfo FragmentShaderInfo { get; } diff --git a/src/Graphics/Resources/Sampler.cs b/src/Graphics/Resources/Sampler.cs index ac52301..2386214 100644 --- a/src/Graphics/Resources/Sampler.cs +++ b/src/Graphics/Resources/Sampler.cs @@ -6,9 +6,9 @@ namespace MoonWorks.Graphics /// /// A sampler specifies how a texture will be sampled in a shader. /// - public class Sampler : RefreshResource + public class Sampler : SDL_GpuResource { - protected override Action QueueDestroyFunction => Refresh.Refresh_QueueDestroySampler; + protected override Action ReleaseFunction => Refresh.Refresh_QueueDestroySampler; public Sampler( GraphicsDevice device, diff --git a/src/Graphics/Resources/Shader.cs b/src/Graphics/Resources/Shader.cs new file mode 100644 index 0000000..8e1279f --- /dev/null +++ b/src/Graphics/Resources/Shader.cs @@ -0,0 +1,65 @@ +using SDL2_gpuCS; +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace MoonWorks.Graphics +{ + /// + /// Shader modules expect input in Refresh bytecode format. + /// + public class Shader : SDL_GpuResource + { + protected override Action ReleaseFunction => SDL_Gpu.SDL_GpuReleaseShader; + + public unsafe Shader( + GraphicsDevice device, + string filePath, + string entryPointName, + ShaderStage shaderStage, + ShaderFormat shaderFormat + ) : base(device) + { + using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); + Handle = CreateFromStream(device, stream, entryPointName, shaderStage, shaderFormat); + } + + public unsafe Shader( + GraphicsDevice device, + Stream stream, + string entryPointName, + ShaderStage shaderStage, + ShaderFormat shaderFormat + ) : base(device) + { + Handle = CreateFromStream(device, stream, entryPointName, shaderStage, shaderFormat); + } + + private static unsafe IntPtr CreateFromStream( + GraphicsDevice device, + Stream stream, + string entryPointName, + ShaderStage shaderStage, + ShaderFormat shaderFormat + ) { + var bytecodeBuffer = NativeMemory.Alloc((nuint) stream.Length); + var bytecodeSpan = new Span(bytecodeBuffer, (int) stream.Length); + stream.ReadExactly(bytecodeSpan); + + SDL_Gpu.ShaderCreateInfo shaderCreateInfo; + shaderCreateInfo.CodeSize = (nuint) stream.Length; + shaderCreateInfo.Code = (byte*) bytecodeBuffer; + shaderCreateInfo.EntryPointName = entryPointName; + shaderCreateInfo.Stage = (SDL_Gpu.ShaderStage) shaderStage; + shaderCreateInfo.Format = (SDL_Gpu.ShaderFormat) shaderFormat; + + var shaderModule = SDL_Gpu.SDL_GpuCreateShader( + device.Handle, + shaderCreateInfo + ); + + NativeMemory.Free(bytecodeBuffer); + return shaderModule; + } + } +} diff --git a/src/Graphics/Resources/ShaderModule.cs b/src/Graphics/Resources/ShaderModule.cs deleted file mode 100644 index fad27cb..0000000 --- a/src/Graphics/Resources/ShaderModule.cs +++ /dev/null @@ -1,42 +0,0 @@ -using RefreshCS; -using System; -using System.IO; -using System.Runtime.InteropServices; - -namespace MoonWorks.Graphics -{ - /// - /// Shader modules expect input in Refresh bytecode format. - /// - public class ShaderModule : RefreshResource - { - protected override Action QueueDestroyFunction => Refresh.Refresh_QueueDestroyShaderModule; - - public unsafe ShaderModule(GraphicsDevice device, string filePath) : base(device) - { - using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); - Handle = CreateFromStream(device, stream); - } - - public unsafe ShaderModule(GraphicsDevice device, Stream stream) : base(device) - { - Handle = CreateFromStream(device, stream); - } - - private static unsafe IntPtr CreateFromStream(GraphicsDevice device, Stream stream) - { - var bytecodeBuffer = NativeMemory.Alloc((nuint) stream.Length); - var bytecodeSpan = new Span(bytecodeBuffer, (int) stream.Length); - stream.ReadExactly(bytecodeSpan); - - Refresh.ShaderModuleCreateInfo shaderModuleCreateInfo; - shaderModuleCreateInfo.codeSize = (nuint) stream.Length; - shaderModuleCreateInfo.byteCode = (nint) bytecodeBuffer; - - var shaderModule = Refresh.Refresh_CreateShaderModule(device.Handle, shaderModuleCreateInfo); - - NativeMemory.Free(bytecodeBuffer); - return shaderModule; - } - } -} diff --git a/src/Graphics/Resources/Texture.cs b/src/Graphics/Resources/Texture.cs index 7648808..d6a8435 100644 --- a/src/Graphics/Resources/Texture.cs +++ b/src/Graphics/Resources/Texture.cs @@ -7,7 +7,7 @@ namespace MoonWorks.Graphics /// /// A container for pixel data. /// - public class Texture : RefreshResource + public class Texture : SDL_GpuResource { public uint Width { get; internal set; } public uint Height { get; internal set; } @@ -41,7 +41,7 @@ namespace MoonWorks.Graphics } // FIXME: this allocates a delegate instance - protected override Action QueueDestroyFunction => Refresh.Refresh_QueueDestroyTexture; + protected override Action ReleaseFunction => Refresh.Refresh_QueueDestroyTexture; /// /// Creates a 2D texture. diff --git a/src/Graphics/Resources/TransferBuffer.cs b/src/Graphics/Resources/TransferBuffer.cs index a58d3c3..3f2c070 100644 --- a/src/Graphics/Resources/TransferBuffer.cs +++ b/src/Graphics/Resources/TransferBuffer.cs @@ -4,9 +4,9 @@ using RefreshCS; namespace MoonWorks.Graphics { - public unsafe class TransferBuffer : RefreshResource + public unsafe class TransferBuffer : SDL_GpuResource { - protected override Action QueueDestroyFunction => Refresh.Refresh_QueueDestroyTransferBuffer; + protected override Action ReleaseFunction => Refresh.Refresh_QueueDestroyTransferBuffer; /// /// Size in bytes. diff --git a/src/Graphics/RefreshResource.cs b/src/Graphics/SDL_GpuResource.cs similarity index 54% rename from src/Graphics/RefreshResource.cs rename to src/Graphics/SDL_GpuResource.cs index 875d645..f2c672a 100644 --- a/src/Graphics/RefreshResource.cs +++ b/src/Graphics/SDL_GpuResource.cs @@ -1,17 +1,16 @@ using System; -using System.Runtime.InteropServices; using System.Threading; namespace MoonWorks.Graphics; -public abstract class RefreshResource : GraphicsResource +public abstract class SDL_GpuResource : GraphicsResource { public IntPtr Handle { get => handle; internal set => handle = value; } private IntPtr handle; - protected abstract Action QueueDestroyFunction { get; } + protected abstract Action ReleaseFunction { get; } - protected RefreshResource(GraphicsDevice device) : base(device) + protected SDL_GpuResource(GraphicsDevice device) : base(device) { } @@ -19,11 +18,11 @@ public abstract class RefreshResource : GraphicsResource { if (!IsDisposed) { - // Atomically call destroy function in case this is called from the finalizer thread + // Atomically call release function in case this is called from the finalizer thread var toDispose = Interlocked.Exchange(ref handle, IntPtr.Zero); if (toDispose != IntPtr.Zero) { - QueueDestroyFunction(Device.Handle, toDispose); + ReleaseFunction(Device.Handle, toDispose); } } base.Dispose(disposing); diff --git a/src/Graphics/SDL_GpuTypes.cs b/src/Graphics/SDL_GpuTypes.cs new file mode 100644 index 0000000..3cd3e02 --- /dev/null +++ b/src/Graphics/SDL_GpuTypes.cs @@ -0,0 +1,799 @@ +using System; +using System.Runtime.InteropServices; +using SDL2_gpuCS; + +namespace MoonWorks.Graphics; + +// Recreate certain types in here so we can hide the SDL_GpuCS 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 +} + +[Flags] +public enum TransferBufferMapFlags +{ + Read = 0x1, + Write = 0x2 +} + +public enum ShaderStage +{ + Vertex, + Fragment, + Compute +} + +public enum ShaderFormat +{ + Invalid, + SPIRV, + 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 +{ + R = 0x1, + G = 0x2, + B = 0x4, + A = 0x8 +} + +public enum Filter +{ + Nearest, + Linear +} + +public enum SamplerMipmapMode +{ + Nearest, + Linear +} + +public enum SamplerAddressMode +{ + Repeat, + MirroredRepeat, + ClampToEdge, + ClampToBorder +} + +public enum BorderColor +{ + FloatTransparentBlack, + IntTransparentBlack, + FloatOpaqueBlack, + IntOpaqueBlack, + FloatOpaqueWhite, + IntOpaqueWhite +} + +public enum TransferUsage +{ + Buffer, + Texture +} + +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 SDL_Gpu.DepthStencilValue ToSDL() + { + return new SDL_Gpu.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 SDL_Gpu.Rect ToRefresh() + { + return new SDL_Gpu.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 SDL_Gpu.Viewport ToSDL() + { + return new SDL_Gpu.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 static VertexBinding Create(uint binding = 0, VertexInputRate inputRate = VertexInputRate.Vertex) where T : unmanaged + { + return new VertexBinding + { + Binding = binding, + InputRate = inputRate, + Stride = (uint) Marshal.SizeOf() + }; + } +} + +[StructLayout(LayoutKind.Sequential)] +public struct VertexAttribute +{ + public uint Location; + public uint Binding; + public VertexElementFormat Format; + public uint Offset; +} + +[StructLayout(LayoutKind.Sequential)] +public struct StencilOpState +{ + public StencilOp FailOp; + public StencilOp PassOp; + public StencilOp DepthFailOp; + public CompareOp CompareOp; + + public SDL_Gpu.StencilOpState ToSDL() + { + return new SDL_Gpu.StencilOpState + { + FailOp = (SDL_Gpu.StencilOp) FailOp, + PassOp = (SDL_Gpu.StencilOp) PassOp, + DepthFailOp = (SDL_Gpu.StencilOp) DepthFailOp, + CompareOp = (SDL_Gpu.CompareOp) CompareOp + }; + } +} + +/// +/// Determines how a color texture will be read/written in a render pass. +/// +public struct ColorAttachmentInfo +{ + public TextureSlice TextureSlice; + + /// + /// If LoadOp is set to Clear, the texture slice will be cleared to this color. + /// + public Color ClearColor; + + /// + /// Determines what is done with the texture slice memory + /// at the beginning of the render pass.
+ /// + /// Load: + /// Loads the data currently in the texture slice.
+ /// + /// Clear: + /// Clears the texture slice to a single color.
+ /// + /// 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. + ///
+ public LoadOp LoadOp; + + /// + /// Determines what is done with the texture slice memory + /// at the end of the render pass.
+ /// + /// Store: + /// Stores the results of the render pass in the texture slice memory.
+ /// + /// DontCare: + /// The driver will do whatever it wants with the texture slice memory. + ///
+ public StoreOp StoreOp; + + /// + /// If true, cycles the texture if it is bound. + /// + 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 SDL_Gpu.ColorAttachmentInfo ToSDL() + { + return new SDL_Gpu.ColorAttachmentInfo + { + TextureSlice = TextureSlice.ToSDL(), + ClearColor = new SDL_Gpu.Color + { + R = ClearColor.R / 255f, + G = ClearColor.G / 255f, + B = ClearColor.B / 255f, + A = ClearColor.A / 255f + }, + LoadOp = (SDL_Gpu.LoadOp) LoadOp, + StoreOp = (SDL_Gpu.StoreOp) StoreOp, + Cycle = Conversions.BoolToInt(Cycle) + }; + } +} + +/// +/// Determines how a depth/stencil texture will be read/written in a render pass. +/// +public struct DepthStencilAttachmentInfo +{ + public TextureSlice TextureSlice; + + /// + /// If LoadOp is set to Clear, the texture slice depth will be cleared to this depth value.
+ /// If StencilLoadOp is set to Clear, the texture slice stencil value will be cleared to this stencil value. + ///
+ public DepthStencilValue DepthStencilClearValue; + + /// + /// Determines what is done with the texture slice depth values + /// at the beginning of the render pass.
+ /// + /// Load: + /// Loads the data currently in the texture slice.
+ /// + /// Clear: + /// Clears the texture slice to a single depth value.
+ /// + /// 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. + ///
+ public LoadOp LoadOp; + + /// + /// Determines what is done with the texture slice depth values + /// at the end of the render pass.
+ /// + /// Store: + /// Stores the results of the render pass in the texture slice memory.
+ /// + /// 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. + ///
+ public StoreOp StoreOp; + + /// + /// Determines what is done with the texture slice stencil values + /// at the beginning of the render pass.
+ /// + /// Load: + /// Loads the data currently in the texture slice.
+ /// + /// Clear: + /// Clears the texture slice to a single stencil value.
+ /// + /// 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. + ///
+ public LoadOp StencilLoadOp; + + /// + /// Determines what is done with the texture slice stencil values + /// at the end of the render pass.
+ /// + /// Store: + /// Stores the results of the render pass in the texture slice memory.
+ /// + /// 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. + ///
+ public StoreOp StencilStoreOp; + + /// + /// If true, cycles the texture if it is bound. + /// + 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 SDL_Gpu.DepthStencilAttachmentInfo ToSDL() + { + return new SDL_Gpu.DepthStencilAttachmentInfo + { + TextureSlice = TextureSlice.ToSDL(), + DepthStencilClearValue = DepthStencilClearValue.ToSDL(), + LoadOp = (SDL_Gpu.LoadOp) LoadOp, + StoreOp = (SDL_Gpu.StoreOp) StoreOp, + StencilLoadOp = (SDL_Gpu.LoadOp) StencilLoadOp, + StencilStoreOp = (SDL_Gpu.StoreOp) StencilStoreOp, + Cycle = Conversions.BoolToInt(Cycle) + }; + } +} + +[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; + } +} + +[StructLayout(LayoutKind.Sequential)] +public struct BufferCopy +{ + public uint SrcOffset; + public uint DstOffset; + public uint Size; + + public BufferCopy( + uint srcOffset, + uint dstOffset, + uint size + ) { + SrcOffset = srcOffset; + DstOffset = dstOffset; + Size = size; + } + + public SDL_Gpu.BufferCopy ToRefresh() + { + return new SDL_Gpu.BufferCopy + { + SourceOffset = SrcOffset, + DestinationOffset = DstOffset, + Size = Size + }; + } +} + +/// +/// Parameters for a copy between buffer and image. +/// +/// The offset into the buffer. +/// If 0, image data is assumed tightly packed. +/// If 0, image data is assumed tightly packed. +[StructLayout(LayoutKind.Sequential)] +public readonly record struct BufferImageCopy( + uint BufferOffset, + uint BufferStride, + uint BufferImageHeight +) { + public SDL_Gpu.BufferImageCopy ToRefresh() + { + return new SDL_Gpu.BufferImageCopy + { + BufferOffset = BufferOffset, + BufferStride = BufferStride, + BufferImageHeight = BufferImageHeight + }; + } +} diff --git a/src/Graphics/State/SamplerCreateInfo.cs b/src/Graphics/State/SamplerCreateInfo.cs index f680941..9ff00c6 100644 --- a/src/Graphics/State/SamplerCreateInfo.cs +++ b/src/Graphics/State/SamplerCreateInfo.cs @@ -1,174 +1,173 @@ -using RefreshCS; +using SDL2_gpuCS; -namespace MoonWorks.Graphics +namespace MoonWorks.Graphics; + +/// +/// All of the information that is used to create a sampler. +/// +public struct SamplerCreateInfo { /// - /// All of the information that is used to create a sampler. + /// Minification filter mode. Used when the image is downscaled. /// - public struct SamplerCreateInfo + public Filter MinFilter; + /// + /// Magnification filter mode. Used when the image is upscaled. + /// + public Filter MagFilter; + /// + /// Filter mode applied to mipmap lookups. + /// + public SamplerMipmapMode MipmapMode; + /// + /// Horizontal addressing mode. + /// + public SamplerAddressMode AddressModeU; + /// + /// Vertical addressing mode. + /// + public SamplerAddressMode AddressModeV; + /// + /// Depth addressing mode. + /// + public SamplerAddressMode AddressModeW; + /// + /// Bias value added to mipmap level of detail calculation. + /// + public float MipLodBias; + /// + /// Enables anisotropic filtering. + /// + public bool AnisotropyEnable; + /// + /// Maximum anisotropy value. + /// + public float MaxAnisotropy; + public bool CompareEnable; + public CompareOp CompareOp; + /// + /// Clamps the LOD value to a specified minimum. + /// + public float MinLod; + /// + /// Clamps the LOD value to a specified maximum. + /// + public float MaxLod; + /// + /// If an address mode is set to ClampToBorder, will replace color with this color when samples are outside the [0, 1) range. + /// + public BorderColor BorderColor; + + public static readonly SamplerCreateInfo AnisotropicClamp = new SamplerCreateInfo { - /// - /// Minification filter mode. Used when the image is downscaled. - /// - public Filter MinFilter; - /// - /// Magnification filter mode. Used when the image is upscaled. - /// - public Filter MagFilter; - /// - /// Filter mode applied to mipmap lookups. - /// - public SamplerMipmapMode MipmapMode; - /// - /// Horizontal addressing mode. - /// - public SamplerAddressMode AddressModeU; - /// - /// Vertical addressing mode. - /// - public SamplerAddressMode AddressModeV; - /// - /// Depth addressing mode. - /// - public SamplerAddressMode AddressModeW; - /// - /// Bias value added to mipmap level of detail calculation. - /// - public float MipLodBias; - /// - /// Enables anisotropic filtering. - /// - public bool AnisotropyEnable; - /// - /// Maximum anisotropy value. - /// - public float MaxAnisotropy; - public bool CompareEnable; - public CompareOp CompareOp; - /// - /// Clamps the LOD value to a specified minimum. - /// - public float MinLod; - /// - /// Clamps the LOD value to a specified maximum. - /// - public float MaxLod; - /// - /// If an address mode is set to ClampToBorder, will replace color with this color when samples are outside the [0, 1) range. - /// - public BorderColor BorderColor; + 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 AnisotropicClamp = new SamplerCreateInfo + 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 SDL_Gpu.SamplerCreateInfo ToSDL() + { + return new SDL_Gpu.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 */ + MinFilter = (SDL_Gpu.Filter) MinFilter, + MagFilter = (SDL_Gpu.Filter) MagFilter, + MipmapMode = (SDL_Gpu.SamplerMipmapMode) MipmapMode, + AddressModeU = (SDL_Gpu.SamplerAddressMode) AddressModeU, + AddressModeV = (SDL_Gpu.SamplerAddressMode) AddressModeV, + AddressModeW = (SDL_Gpu.SamplerAddressMode) AddressModeW, + MipLodBias = MipLodBias, + AnisotropyEnable = Conversions.BoolToByte(AnisotropyEnable), + MaxAnisotropy = MaxAnisotropy, + CompareEnable = Conversions.BoolToByte(CompareEnable), + CompareOp = (SDL_Gpu.CompareOp) CompareOp, + MinLod = MinLod, + MaxLod = MaxLod, + BorderColor = (SDL_Gpu.BorderColor) BorderColor }; - - 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.SamplerStateCreateInfo ToRefreshSamplerStateCreateInfo() - { - return new Refresh.SamplerStateCreateInfo - { - 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.BoolToByte(AnisotropyEnable), - maxAnisotropy = MaxAnisotropy, - compareEnable = Conversions.BoolToByte(CompareEnable), - compareOp = (Refresh.CompareOp) CompareOp, - minLod = MinLod, - maxLod = MaxLod, - borderColor = (Refresh.BorderColor) BorderColor - }; - } } }