replace Campari with MoonWorks.Graphics

main
cosmonaut 2021-01-19 19:33:27 -08:00
parent 2b58edb257
commit 2cabaa6186
37 changed files with 1727 additions and 20 deletions

6
.gitmodules vendored
View File

@ -1,9 +1,9 @@
[submodule "lib/SDL2-CS"]
path = lib/SDL2-CS
url = https://github.com/flibitijibibo/SDL2-CS.git
[submodule "lib/Campari"]
path = lib/Campari
url = https://gitea.moonside.games/MoonsideGames/Campari.git
[submodule "lib/FAudio"]
path = lib/FAudio
url = https://github.com/FNA-XNA/FAudio.git
[submodule "lib/RefreshCS"]
path = lib/RefreshCS
url = https://gitea.moonside.games/MoonsideGames/RefreshCS.git

View File

@ -12,8 +12,7 @@
<ItemGroup>
<ProjectReference Include=".\lib\SDL2-CS\SDL2-CS.Core.csproj" />
<ProjectReference Include=".\lib\Campari\Campari.csproj" />
<ProjectReference Include=".\lib\Campari\lib\RefreshCS\RefreshCS.csproj" />
<ProjectReference Include=".\lib\RefreshCS\RefreshCS.csproj" />
<ProjectReference Include=".\lib\FAudio\csharp\FAudio-CS.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -10,12 +10,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MoonWorks", "MoonWorks.cspr
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SDL2-CS.Core", "lib\SDL2-CS\SDL2-CS.Core.csproj", "{0929F2D8-8FE4-4452-AD1E-50760A1A19A5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Campari", "lib\Campari\Campari.csproj", "{D09577DE-99F5-4C30-9165-4012C37CE0CE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RefreshCS", "lib\Campari\lib\RefreshCS\RefreshCS.csproj", "{66116A40-B360-4BA3-966A-A54F3E562EC1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FAudio-CS.Core", "lib\FAudio\csharp\FAudio-CS.Core.csproj", "{608AA31D-F163-4096-B4EF-B9C7D21D52BB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RefreshCS", "lib\RefreshCS\RefreshCS.csproj", "{AD7C94E4-0AFA-44CA-889C-110142369893}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -30,18 +28,14 @@ Global
{0929F2D8-8FE4-4452-AD1E-50760A1A19A5}.Debug|x64.Build.0 = Debug|x64
{0929F2D8-8FE4-4452-AD1E-50760A1A19A5}.Release|x64.ActiveCfg = Release|x64
{0929F2D8-8FE4-4452-AD1E-50760A1A19A5}.Release|x64.Build.0 = Release|x64
{D09577DE-99F5-4C30-9165-4012C37CE0CE}.Debug|x64.ActiveCfg = Debug|x64
{D09577DE-99F5-4C30-9165-4012C37CE0CE}.Debug|x64.Build.0 = Debug|x64
{D09577DE-99F5-4C30-9165-4012C37CE0CE}.Release|x64.ActiveCfg = Release|x64
{D09577DE-99F5-4C30-9165-4012C37CE0CE}.Release|x64.Build.0 = Release|x64
{66116A40-B360-4BA3-966A-A54F3E562EC1}.Debug|x64.ActiveCfg = Debug|x64
{66116A40-B360-4BA3-966A-A54F3E562EC1}.Debug|x64.Build.0 = Debug|x64
{66116A40-B360-4BA3-966A-A54F3E562EC1}.Release|x64.ActiveCfg = Release|x64
{66116A40-B360-4BA3-966A-A54F3E562EC1}.Release|x64.Build.0 = Release|x64
{608AA31D-F163-4096-B4EF-B9C7D21D52BB}.Debug|x64.ActiveCfg = Debug|x64
{608AA31D-F163-4096-B4EF-B9C7D21D52BB}.Debug|x64.Build.0 = Debug|x64
{608AA31D-F163-4096-B4EF-B9C7D21D52BB}.Release|x64.ActiveCfg = Release|x64
{608AA31D-F163-4096-B4EF-B9C7D21D52BB}.Release|x64.Build.0 = Release|x64
{AD7C94E4-0AFA-44CA-889C-110142369893}.Debug|x64.ActiveCfg = Debug|x64
{AD7C94E4-0AFA-44CA-889C-110142369893}.Debug|x64.Build.0 = Debug|x64
{AD7C94E4-0AFA-44CA-889C-110142369893}.Release|x64.ActiveCfg = Release|x64
{AD7C94E4-0AFA-44CA-889C-110142369893}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -1 +0,0 @@
Subproject commit f01b9a3a9acff8672e0d7da253ee2402fcdaa281

1
lib/RefreshCS Submodule

@ -0,0 +1 @@
Subproject commit ba183e8c0f9d21e4397d76941078b4969d4f6686

View File

@ -1,5 +1,5 @@
using SDL2;
using Campari;
using MoonWorks.Graphics;
using System.Collections.Generic;
using MoonWorks.Audio;

View File

@ -0,0 +1,10 @@
namespace MoonWorks.Graphics
{
public struct BlendConstants
{
public float R;
public float G;
public float B;
public float A;
}
}

73
src/Graphics/Buffer.cs Normal file
View File

@ -0,0 +1,73 @@
using System;
using RefreshCS;
namespace MoonWorks.Graphics
{
public class Buffer : GraphicsResource
{
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyBuffer;
public Buffer(
GraphicsDevice device,
Refresh.BufferUsageFlags usageFlags,
uint sizeInBytes
) : base(device)
{
Handle = Refresh.Refresh_CreateBuffer(
device.Handle,
usageFlags,
sizeInBytes
);
}
public unsafe void SetData<T>(
uint offsetInBytes,
T[] data,
uint dataLengthInBytes
) where T : unmanaged
{
fixed (T* ptr = &data[0])
{
Refresh.Refresh_SetBufferData(
Device.Handle,
Handle,
offsetInBytes,
(IntPtr) ptr,
dataLengthInBytes
);
}
}
public unsafe void SetData<T>(
uint offsetInBytes,
T* data,
uint dataLengthInBytes
) where T : unmanaged
{
Refresh.Refresh_SetBufferData(
Device.Handle,
Handle,
offsetInBytes,
(IntPtr) data,
dataLengthInBytes
);
}
// NOTE: You want to wait on the device before calling this
public unsafe void GetData<T>(
T[] data,
uint dataLengthInBytes
) where T : unmanaged
{
fixed (T* ptr = &data[0])
{
Refresh.Refresh_GetBufferData(
Device.Handle,
Handle,
(IntPtr)ptr,
dataLengthInBytes
);
}
}
}
}

View File

@ -0,0 +1,14 @@
namespace MoonWorks.Graphics
{
public struct BufferBinding
{
public Buffer Buffer;
public ulong Offset;
public BufferBinding(Buffer buffer, ulong offset)
{
Buffer = buffer;
Offset = offset;
}
}
}

33
src/Graphics/Bytecode.cs Normal file
View File

@ -0,0 +1,33 @@
using System.IO;
namespace MoonWorks.Graphics
{
public static class Bytecode
{
public static uint[] ReadBytecode(FileInfo fileInfo)
{
byte[] data;
int size;
using (FileStream stream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read))
{
size = (int)stream.Length;
data = new byte[size];
stream.Read(data, 0, size);
}
uint[] uintData = new uint[size / 4];
using (var memoryStream = new MemoryStream(data))
{
using (var reader = new BinaryReader(memoryStream))
{
for (int i = 0; i < size / 4; i++)
{
uintData[i] = reader.ReadUInt32();
}
}
}
return uintData;
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using RefreshCS;
namespace MoonWorks.Graphics
{
public class ColorTarget : GraphicsResource
{
public uint Width { get; }
public uint Height { get; }
public Texture Texture { get; }
public Refresh.ColorFormat Format => Texture.Format;
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyColorTarget;
public static ColorTarget CreateBackedColorTarget2D(
GraphicsDevice device,
uint width,
uint height,
Refresh.ColorFormat format,
bool canBeSampled,
Refresh.SampleCount sampleCount = Refresh.SampleCount.One,
uint levelCount = 1
)
{
var flags = Refresh.TextureUsageFlags.ColorTargetBit;
if (canBeSampled) { flags |= Refresh.TextureUsageFlags.SamplerBit; }
var texture = Texture.CreateTexture2D(
device,
width,
height,
format,
flags,
sampleCount,
levelCount
);
var textureSlice = new TextureSlice(texture);
return new ColorTarget(device, sampleCount, ref textureSlice);
}
public ColorTarget(GraphicsDevice device, Refresh.SampleCount sampleCount, ref TextureSlice textureSlice) : base(device)
{
var refreshTextureSlice = textureSlice.ToRefreshTextureSlice();
Handle = Refresh.Refresh_CreateColorTarget(device.Handle, sampleCount, ref refreshTextureSlice);
}
}
}

View File

@ -0,0 +1,414 @@
using System;
using System.Runtime.InteropServices;
using RefreshCS;
namespace MoonWorks.Graphics
{
public class CommandBuffer
{
public GraphicsDevice Device { get; }
public IntPtr Handle { get; internal set; }
// called from RefreshDevice
internal CommandBuffer(GraphicsDevice device)
{
Device = device;
Handle = IntPtr.Zero;
}
public unsafe void BeginRenderPass(
RenderPass renderPass,
Framebuffer framebuffer,
ref Refresh.Rect renderArea,
ref Refresh.DepthStencilValue depthStencilClearValue,
params Refresh.Color[] clearColors
) {
fixed (Refresh.Color* clearColorPtr = &clearColors[0])
{
Refresh.Refresh_BeginRenderPass(
Device.Handle,
Handle,
renderPass.Handle,
framebuffer.Handle,
ref renderArea,
(IntPtr) clearColorPtr,
(uint)clearColors.Length,
ref depthStencilClearValue
);
}
}
public unsafe void BeginRenderPass(
RenderPass renderPass,
Framebuffer framebuffer,
ref Refresh.Rect renderArea,
params Refresh.Color[] clearColors
) {
fixed (Refresh.Color* clearColorPtr = &clearColors[0])
{
Refresh.Refresh_BeginRenderPass(
Device.Handle,
Handle,
renderPass.Handle,
framebuffer.Handle,
ref renderArea,
(IntPtr) clearColorPtr,
(uint) clearColors.Length,
IntPtr.Zero
);
}
}
public void BindComputePipeline(
ComputePipeline computePipeline
) {
Refresh.Refresh_BindComputePipeline(
Device.Handle,
Handle,
computePipeline.Handle
);
}
public unsafe uint PushComputeShaderParams<T>(
params T[] uniforms
) where T : unmanaged
{
fixed (T* ptr = &uniforms[0])
{
return Refresh.Refresh_PushComputeShaderParams(
Device.Handle,
Handle,
(IntPtr) ptr,
(uint) uniforms.Length
);
}
}
public unsafe void BindComputeBuffers(
params Buffer[] buffers
) {
var bufferPtrs = stackalloc IntPtr[buffers.Length];
for (var i = 0; i < buffers.Length; i += 1)
{
bufferPtrs[i] = buffers[i].Handle;
}
Refresh.Refresh_BindComputeBuffers(
Device.Handle,
Handle,
(IntPtr) bufferPtrs
);
}
public unsafe void BindComputeTextures(
params Texture[] textures
) {
var texturePtrs = stackalloc IntPtr[textures.Length];
for (var i = 0; i < textures.Length; i += 1)
{
texturePtrs[i] = textures[i].Handle;
}
Refresh.Refresh_BindComputeTextures(
Device.Handle,
Handle,
(IntPtr) texturePtrs
);
}
public void BindGraphicsPipeline(
GraphicsPipeline graphicsPipeline
) {
Refresh.Refresh_BindGraphicsPipeline(
Device.Handle,
Handle,
graphicsPipeline.Handle
);
}
public unsafe uint PushVertexShaderParams<T>(
params T[] uniforms
) where T : unmanaged
{
fixed (T* ptr = &uniforms[0])
{
return Refresh.Refresh_PushVertexShaderParams(
Device.Handle,
Handle,
(IntPtr) ptr,
(uint) uniforms.Length
);
}
}
public unsafe uint PushFragmentShaderParams<T>(
params T[] uniforms
) where T : unmanaged
{
fixed (T* ptr = &uniforms[0])
{
return Refresh.Refresh_PushFragmentShaderParams(
Device.Handle,
Handle,
(IntPtr) ptr,
(uint) uniforms.Length
);
}
}
public unsafe void BindVertexBuffers(
uint firstBinding,
params BufferBinding[] bufferBindings
) {
var bufferPtrs = stackalloc IntPtr[bufferBindings.Length];
var offsets = stackalloc ulong[bufferBindings.Length];
for (var i = 0; i < bufferBindings.Length; i += 1)
{
bufferPtrs[i] = bufferBindings[i].Buffer.Handle;
offsets[i] = bufferBindings[i].Offset;
}
Refresh.Refresh_BindVertexBuffers(
Device.Handle,
Handle,
firstBinding,
(uint) bufferBindings.Length,
(IntPtr) bufferPtrs,
(IntPtr) offsets
);
}
public void BindIndexBuffer(
Buffer indexBuffer,
uint offset,
Refresh.IndexElementSize indexElementSize
) {
Refresh.Refresh_BindIndexBuffer(
Device.Handle,
Handle,
indexBuffer.Handle,
offset,
indexElementSize
);
}
public unsafe void BindVertexSamplers(
Texture[] textures,
Sampler[] samplers
) {
var texturePtrs = stackalloc IntPtr[textures.Length];
var samplerPtrs = stackalloc IntPtr[samplers.Length];
for (var i = 0; i < textures.Length; i += 1)
{
texturePtrs[i] = textures[i].Handle;
}
for (var i = 0; i < samplers.Length; i += 1)
{
samplerPtrs[i] = samplers[i].Handle;
}
Refresh.Refresh_BindVertexSamplers(
Device.Handle,
Handle,
(IntPtr) texturePtrs,
(IntPtr) samplerPtrs
);
}
public unsafe void BindFragmentSamplers(
params TextureSamplerBinding[] textureSamplerBindings
) {
var texturePtrs = stackalloc IntPtr[textureSamplerBindings.Length];
var samplerPtrs = stackalloc IntPtr[textureSamplerBindings.Length];
for (var i = 0; i < textureSamplerBindings.Length; i += 1)
{
texturePtrs[i] = textureSamplerBindings[i].Texture.Handle;
samplerPtrs[i] = textureSamplerBindings[i].Sampler.Handle;
}
Refresh.Refresh_BindFragmentSamplers(
Device.Handle,
Handle,
(IntPtr) texturePtrs,
(IntPtr) samplerPtrs
);
}
public void Clear(
ref Refresh.Rect clearRect,
Refresh.ClearOptionsFlags clearOptions,
ref Refresh.Color[] colors,
float depth,
int stencil
) {
Refresh.Refresh_Clear(
Device.Handle,
Handle,
ref clearRect,
clearOptions,
ref colors,
(uint) colors.Length,
depth,
stencil
);
}
public void DrawInstancedPrimitives(
uint baseVertex,
uint startIndex,
uint primitiveCount,
uint instanceCount,
uint vertexParamOffset,
uint fragmentParamOffset
) {
Refresh.Refresh_DrawInstancedPrimitives(
Device.Handle,
Handle,
baseVertex,
startIndex,
primitiveCount,
instanceCount,
vertexParamOffset,
fragmentParamOffset
);
}
public void DrawIndexedPrimitives(
uint baseVertex,
uint startIndex,
uint primitiveCount,
uint vertexParamOffset,
uint fragmentParamOffset
) {
Refresh.Refresh_DrawIndexedPrimitives(
Device.Handle,
Handle,
baseVertex,
startIndex,
primitiveCount,
vertexParamOffset,
fragmentParamOffset
);
}
public void DrawPrimitives(
uint vertexStart,
uint primitiveCount,
uint vertexParamOffset,
uint fragmentParamOffset
) {
Refresh.Refresh_DrawPrimitives(
Device.Handle,
Handle,
vertexStart,
primitiveCount,
vertexParamOffset,
fragmentParamOffset
);
}
public void EndRenderPass()
{
Refresh.Refresh_EndRenderPass(
Device.Handle,
Handle
);
}
public void QueuePresent(
ref TextureSlice textureSlice,
ref Refresh.Rect destinationRectangle,
Refresh.Filter filter
) {
var refreshTextureSlice = textureSlice.ToRefreshTextureSlice();
Refresh.Refresh_QueuePresent(
Device.Handle,
Handle,
ref refreshTextureSlice,
ref destinationRectangle,
filter
);
}
public void QueuePresent(
ref TextureSlice textureSlice,
Refresh.Filter filter
) {
var refreshTextureSlice = textureSlice.ToRefreshTextureSlice();
Refresh.Refresh_QueuePresent(
Device.Handle,
Handle,
ref refreshTextureSlice,
IntPtr.Zero,
filter
);
}
public void QueuePresent(
Texture texture,
Refresh.Filter filter
) {
var refreshTextureSlice = new Refresh.TextureSlice
{
texture = texture.Handle,
rectangle = new Refresh.Rect
{
x = 0,
y = 0,
w = (int) texture.Width,
h = (int) texture.Height
},
layer = 0,
level = 0,
depth = 0
};
Refresh.Refresh_QueuePresent(
Device.Handle,
Handle,
ref refreshTextureSlice,
IntPtr.Zero,
filter
);
}
public void CopyTextureToTexture(
ref TextureSlice sourceTextureSlice,
ref TextureSlice destinationTextureSlice,
Refresh.Filter filter
) {
var sourceRefreshTextureSlice = sourceTextureSlice.ToRefreshTextureSlice();
var destRefreshTextureSlice = destinationTextureSlice.ToRefreshTextureSlice();
Refresh.Refresh_CopyTextureToTexture(
Device.Handle,
Handle,
ref sourceRefreshTextureSlice,
ref destRefreshTextureSlice,
filter
);
}
public void CopyTextureToBuffer(
ref TextureSlice textureSlice,
Buffer buffer
) {
var refreshTextureSlice = textureSlice.ToRefreshTextureSlice();
Refresh.Refresh_CopyTextureToBuffer(
Device.Handle,
Handle,
ref refreshTextureSlice,
buffer.Handle
);
}
}
}

View File

@ -0,0 +1,39 @@
using RefreshCS;
using System;
namespace MoonWorks.Graphics
{
public class ComputePipeline : GraphicsResource
{
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyComputePipeline;
public unsafe ComputePipeline(
GraphicsDevice device,
ShaderStageState computeShaderState,
uint bufferBindingCount,
uint imageBindingCount
) : base(device) {
var computePipelineLayoutCreateInfo = new Refresh.ComputePipelineLayoutCreateInfo
{
bufferBindingCount = bufferBindingCount,
imageBindingCount = imageBindingCount
};
var computePipelineCreateInfo = new Refresh.ComputePipelineCreateInfo
{
pipelineLayoutCreateInfo = computePipelineLayoutCreateInfo,
computeShaderState = new Refresh.ShaderStageState
{
entryPointName = computeShaderState.EntryPointName,
shaderModule = computeShaderState.ShaderModule.Handle,
uniformBufferSize = computeShaderState.UniformBufferSize
}
};
Handle = Refresh.Refresh_CreateComputePipeline(
device.Handle,
ref computePipelineCreateInfo
);
}
}
}

View File

@ -0,0 +1,10 @@
namespace MoonWorks.Graphics
{
public static class Conversions
{
public static byte BoolToByte(bool b)
{
return (byte)(b ? 1 : 0);
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using RefreshCS;
namespace MoonWorks.Graphics
{
public class DepthStencilTarget : GraphicsResource
{
public uint Width { get; }
public uint Height { get; }
public Refresh.DepthFormat Format { get; }
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyDepthStencilTarget;
public DepthStencilTarget(
GraphicsDevice device,
uint width,
uint height,
Refresh.DepthFormat depthFormat
) : base(device)
{
Handle = Refresh.Refresh_CreateDepthStencilTarget(device.Handle, width, height, depthFormat);
Width = width;
Height = height;
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using RefreshCS;
namespace MoonWorks.Graphics
{
public class Framebuffer : GraphicsResource
{
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyFramebuffer;
public unsafe Framebuffer(
GraphicsDevice device,
uint width,
uint height,
RenderPass renderPass,
DepthStencilTarget depthStencilTarget, /* can be NULL */
params ColorTarget[] colorTargets
) : base(device)
{
IntPtr[] colorTargetHandles = new IntPtr[colorTargets.Length];
for (var i = 0; i < colorTargets.Length; i += 1)
{
colorTargetHandles[i] = colorTargets[i].Handle;
}
IntPtr depthStencilTargetHandle;
if (depthStencilTarget == null)
{
depthStencilTargetHandle = IntPtr.Zero;
}
else
{
depthStencilTargetHandle = depthStencilTarget.Handle;
}
fixed (IntPtr* colorTargetHandlesPtr = colorTargetHandles)
{
Refresh.FramebufferCreateInfo framebufferCreateInfo = new Refresh.FramebufferCreateInfo
{
width = width,
height = height,
colorTargetCount = (uint) colorTargets.Length,
pColorTargets = (IntPtr) colorTargetHandlesPtr,
depthStencilTarget = depthStencilTargetHandle,
renderPass = renderPass.Handle
};
Handle = Refresh.Refresh_CreateFramebuffer(device.Handle, ref framebufferCreateInfo);
}
}
}
}

View File

@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using RefreshCS;
namespace MoonWorks.Graphics
{
public class GraphicsDevice : IDisposable
{
public IntPtr Handle { get; }
public bool IsDisposed { get; private set; }
private readonly Queue<CommandBuffer> commandBufferPool;
public GraphicsDevice(
IntPtr deviceWindowHandle,
Refresh.PresentMode presentMode,
bool debugMode,
int initialCommandBufferPoolSize = 4
) {
var presentationParameters = new Refresh.PresentationParameters
{
deviceWindowHandle = deviceWindowHandle,
presentMode = presentMode
};
Handle = Refresh.Refresh_CreateDevice(
ref presentationParameters,
Conversions.BoolToByte(debugMode)
);
commandBufferPool = new Queue<CommandBuffer>(initialCommandBufferPoolSize);
for (var i = 0; i < initialCommandBufferPoolSize; i += 1)
{
commandBufferPool.Enqueue(new CommandBuffer(this));
}
}
public CommandBuffer AcquireCommandBuffer()
{
var commandBufferHandle = Refresh.Refresh_AcquireCommandBuffer(Handle, 0);
if (commandBufferPool.Count == 0)
{
commandBufferPool.Enqueue(new CommandBuffer(this));
}
var commandBuffer = commandBufferPool.Dequeue();
commandBuffer.Handle = commandBufferHandle;
return commandBuffer;
}
public unsafe void Submit(params CommandBuffer[] commandBuffers)
{
var commandBufferPtrs = stackalloc IntPtr[commandBuffers.Length];
for (var i = 0; i < commandBuffers.Length; i += 1)
{
commandBufferPtrs[i] = commandBuffers[i].Handle;
}
Refresh.Refresh_Submit(
Handle,
(uint) commandBuffers.Length,
(IntPtr) commandBufferPtrs
);
// return to pool
for (var i = 0; i < commandBuffers.Length; i += 1)
{
commandBuffers[i].Handle = IntPtr.Zero;
commandBufferPool.Enqueue(commandBuffers[i]);
}
}
public void Wait()
{
Refresh.Refresh_Wait(Handle);
}
protected virtual void Dispose(bool disposing)
{
if (!IsDisposed)
{
if (disposing)
{
// TODO: dispose managed state (managed objects)
}
Refresh.Refresh_DestroyDevice(Handle);
IsDisposed = true;
}
}
// TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
~GraphicsDevice()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: false);
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}

View File

@ -0,0 +1,104 @@
using System;
using System.Runtime.InteropServices;
using RefreshCS;
namespace MoonWorks.Graphics
{
public class GraphicsPipeline : GraphicsResource
{
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyGraphicsPipeline;
public unsafe GraphicsPipeline(
GraphicsDevice device,
ColorBlendState colorBlendState,
DepthStencilState depthStencilState,
ShaderStageState vertexShaderState,
ShaderStageState fragmentShaderState,
MultisampleState multisampleState,
GraphicsPipelineLayoutCreateInfo pipelineLayoutCreateInfo,
RasterizerState rasterizerState,
Refresh.PrimitiveType primitiveType,
VertexInputState vertexInputState,
ViewportState viewportState,
RenderPass renderPass
) : base(device)
{
var vertexAttributesHandle = GCHandle.Alloc(vertexInputState.VertexAttributes, GCHandleType.Pinned);
var vertexBindingsHandle = GCHandle.Alloc(vertexInputState.VertexBindings, GCHandleType.Pinned);
var viewportHandle = GCHandle.Alloc(viewportState.Viewports, GCHandleType.Pinned);
var scissorHandle = GCHandle.Alloc(viewportState.Scissors, GCHandleType.Pinned);
var colorTargetBlendStates = stackalloc Refresh.ColorTargetBlendState[colorBlendState.ColorTargetBlendStates.Length];
for (var i = 0; i < colorBlendState.ColorTargetBlendStates.Length; i += 1)
{
colorTargetBlendStates[i] = colorBlendState.ColorTargetBlendStates[i].ToRefreshColorTargetBlendState();
}
Refresh.GraphicsPipelineCreateInfo graphicsPipelineCreateInfo;
graphicsPipelineCreateInfo.colorBlendState.logicOpEnable = Conversions.BoolToByte(colorBlendState.LogicOpEnable);
graphicsPipelineCreateInfo.colorBlendState.logicOp = colorBlendState.LogicOp;
graphicsPipelineCreateInfo.colorBlendState.blendStates = (IntPtr) colorTargetBlendStates;
graphicsPipelineCreateInfo.colorBlendState.blendStateCount = (uint) colorBlendState.ColorTargetBlendStates.Length;
graphicsPipelineCreateInfo.colorBlendState.blendConstants[0] = colorBlendState.BlendConstants.R;
graphicsPipelineCreateInfo.colorBlendState.blendConstants[1] = colorBlendState.BlendConstants.G;
graphicsPipelineCreateInfo.colorBlendState.blendConstants[2] = colorBlendState.BlendConstants.B;
graphicsPipelineCreateInfo.colorBlendState.blendConstants[3] = colorBlendState.BlendConstants.A;
graphicsPipelineCreateInfo.depthStencilState.backStencilState = depthStencilState.BackStencilState;
graphicsPipelineCreateInfo.depthStencilState.compareOp = depthStencilState.CompareOp;
graphicsPipelineCreateInfo.depthStencilState.depthBoundsTestEnable = Conversions.BoolToByte(depthStencilState.DepthBoundsTestEnable);
graphicsPipelineCreateInfo.depthStencilState.depthTestEnable = Conversions.BoolToByte(depthStencilState.DepthTestEnable);
graphicsPipelineCreateInfo.depthStencilState.depthWriteEnable = Conversions.BoolToByte(depthStencilState.DepthWriteEnable);
graphicsPipelineCreateInfo.depthStencilState.frontStencilState = depthStencilState.FrontStencilState;
graphicsPipelineCreateInfo.depthStencilState.maxDepthBounds = depthStencilState.MaxDepthBounds;
graphicsPipelineCreateInfo.depthStencilState.minDepthBounds = depthStencilState.MinDepthBounds;
graphicsPipelineCreateInfo.depthStencilState.stencilTestEnable = Conversions.BoolToByte(depthStencilState.StencilTestEnable);
graphicsPipelineCreateInfo.vertexShaderState.entryPointName = vertexShaderState.EntryPointName;
graphicsPipelineCreateInfo.vertexShaderState.shaderModule = vertexShaderState.ShaderModule.Handle;
graphicsPipelineCreateInfo.vertexShaderState.uniformBufferSize = vertexShaderState.UniformBufferSize;
graphicsPipelineCreateInfo.fragmentShaderState.entryPointName = fragmentShaderState.EntryPointName;
graphicsPipelineCreateInfo.fragmentShaderState.shaderModule = fragmentShaderState.ShaderModule.Handle;
graphicsPipelineCreateInfo.fragmentShaderState.uniformBufferSize = fragmentShaderState.UniformBufferSize;
graphicsPipelineCreateInfo.multisampleState.multisampleCount = multisampleState.MultisampleCount;
graphicsPipelineCreateInfo.multisampleState.sampleMask = multisampleState.SampleMask;
graphicsPipelineCreateInfo.pipelineLayoutCreateInfo.vertexSamplerBindingCount = pipelineLayoutCreateInfo.VertexSamplerBindingCount;
graphicsPipelineCreateInfo.pipelineLayoutCreateInfo.fragmentSamplerBindingCount = pipelineLayoutCreateInfo.FragmentSamplerBindingCount;
graphicsPipelineCreateInfo.rasterizerState.cullMode = rasterizerState.CullMode;
graphicsPipelineCreateInfo.rasterizerState.depthBiasClamp = rasterizerState.DepthBiasClamp;
graphicsPipelineCreateInfo.rasterizerState.depthBiasConstantFactor = rasterizerState.DepthBiasConstantFactor;
graphicsPipelineCreateInfo.rasterizerState.depthBiasEnable = Conversions.BoolToByte(rasterizerState.DepthBiasEnable);
graphicsPipelineCreateInfo.rasterizerState.depthBiasSlopeFactor = rasterizerState.DepthBiasSlopeFactor;
graphicsPipelineCreateInfo.rasterizerState.depthClampEnable = Conversions.BoolToByte(rasterizerState.DepthClampEnable);
graphicsPipelineCreateInfo.rasterizerState.fillMode = rasterizerState.FillMode;
graphicsPipelineCreateInfo.rasterizerState.frontFace = rasterizerState.FrontFace;
graphicsPipelineCreateInfo.rasterizerState.lineWidth = rasterizerState.LineWidth;
graphicsPipelineCreateInfo.vertexInputState.vertexAttributes = vertexAttributesHandle.AddrOfPinnedObject();
graphicsPipelineCreateInfo.vertexInputState.vertexAttributeCount = (uint) vertexInputState.VertexAttributes.Length;
graphicsPipelineCreateInfo.vertexInputState.vertexBindings = vertexBindingsHandle.AddrOfPinnedObject();
graphicsPipelineCreateInfo.vertexInputState.vertexBindingCount = (uint) vertexInputState.VertexBindings.Length;
graphicsPipelineCreateInfo.viewportState.viewports = viewportHandle.AddrOfPinnedObject();
graphicsPipelineCreateInfo.viewportState.viewportCount = (uint) viewportState.Viewports.Length;
graphicsPipelineCreateInfo.viewportState.scissors = scissorHandle.AddrOfPinnedObject();
graphicsPipelineCreateInfo.viewportState.scissorCount = (uint) viewportState.Scissors.Length;
graphicsPipelineCreateInfo.primitiveType = primitiveType;
graphicsPipelineCreateInfo.renderPass = renderPass.Handle;
Handle = Refresh.Refresh_CreateGraphicsPipeline(device.Handle, ref graphicsPipelineCreateInfo);
vertexAttributesHandle.Free();
vertexBindingsHandle.Free();
viewportHandle.Free();
scissorHandle.Free();
}
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MoonWorks.Graphics
{
public abstract class GraphicsResource : IDisposable
{
public GraphicsDevice Device { get; }
public IntPtr Handle { get; protected set; }
public bool IsDisposed { get; private set; }
protected abstract Action<IntPtr, IntPtr> QueueDestroyFunction { get; }
public GraphicsResource(GraphicsDevice device)
{
Device = device;
}
protected virtual void Dispose(bool disposing)
{
if (!IsDisposed)
{
QueueDestroyFunction(Device.Handle, Handle);
IsDisposed = true;
}
}
~GraphicsResource()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: false);
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}

View File

@ -0,0 +1,45 @@
using System;
using RefreshCS;
namespace MoonWorks.Graphics
{
public class RenderPass : GraphicsResource
{
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyRenderPass;
public unsafe RenderPass(
GraphicsDevice device,
params Refresh.ColorTargetDescription[] colorTargetDescriptions
) : base(device)
{
fixed (Refresh.ColorTargetDescription* ptr = colorTargetDescriptions)
{
Refresh.RenderPassCreateInfo renderPassCreateInfo;
renderPassCreateInfo.colorTargetCount = (uint) colorTargetDescriptions.Length;
renderPassCreateInfo.colorTargetDescriptions = (IntPtr) ptr;
renderPassCreateInfo.depthStencilTargetDescription = IntPtr.Zero;
Handle = Refresh.Refresh_CreateRenderPass(device.Handle, ref renderPassCreateInfo);
}
}
public unsafe RenderPass(
GraphicsDevice device,
Refresh.DepthStencilTargetDescription depthStencilTargetDescription,
params Refresh.ColorTargetDescription[] colorTargetDescriptions
) : base(device)
{
Refresh.DepthStencilTargetDescription* depthStencilPtr = &depthStencilTargetDescription;
fixed (Refresh.ColorTargetDescription* colorPtr = colorTargetDescriptions)
{
Refresh.RenderPassCreateInfo renderPassCreateInfo;
renderPassCreateInfo.colorTargetCount = (uint)colorTargetDescriptions.Length;
renderPassCreateInfo.colorTargetDescriptions = (IntPtr)colorPtr;
renderPassCreateInfo.depthStencilTargetDescription = (IntPtr) depthStencilPtr;
Handle = Refresh.Refresh_CreateRenderPass(device.Handle, ref renderPassCreateInfo);
}
}
}
}

23
src/Graphics/Sampler.cs Normal file
View File

@ -0,0 +1,23 @@
using System;
using RefreshCS;
namespace MoonWorks.Graphics
{
public class Sampler : GraphicsResource
{
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroySampler;
public Sampler(
GraphicsDevice device,
ref SamplerState samplerState
) : base(device)
{
var refreshSamplerStateCreateInfo = samplerState.ToRefreshSamplerStateCreateInfo();
Handle = Refresh.Refresh_CreateSampler(
device.Handle,
ref refreshSamplerStateCreateInfo
);
}
}
}

View File

@ -0,0 +1,23 @@
using RefreshCS;
using System;
using System.IO;
namespace MoonWorks.Graphics
{
public class ShaderModule : GraphicsResource
{
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyShaderModule;
public unsafe ShaderModule(GraphicsDevice device, FileInfo fileInfo) : base(device)
{
fixed (uint* ptr = Bytecode.ReadBytecode(fileInfo))
{
Refresh.ShaderModuleCreateInfo shaderModuleCreateInfo;
shaderModuleCreateInfo.codeSize = (UIntPtr) fileInfo.Length;
shaderModuleCreateInfo.byteCode = (IntPtr) ptr;
Handle = Refresh.Refresh_CreateShaderModule(device.Handle, ref shaderModuleCreateInfo);
}
}
}
}

View File

@ -0,0 +1,12 @@
using RefreshCS;
namespace MoonWorks.Graphics
{
public unsafe struct ColorBlendState
{
public bool LogicOpEnable;
public Refresh.LogicOp LogicOp;
public BlendConstants BlendConstants;
public ColorTargetBlendState[] ColorTargetBlendStates;
}
}

View File

@ -0,0 +1,85 @@
using RefreshCS;
namespace MoonWorks.Graphics
{
public struct ColorTargetBlendState
{
public bool BlendEnable;
public Refresh.BlendOp AlphaBlendOp;
public Refresh.BlendOp ColorBlendOp;
public Refresh.ColorComponentFlags ColorWriteMask;
public Refresh.BlendFactor DestinationAlphaBlendFactor;
public Refresh.BlendFactor DestinationColorBlendFactor;
public Refresh.BlendFactor SourceAlphaBlendFactor;
public Refresh.BlendFactor SourceColorBlendFactor;
public static readonly ColorTargetBlendState Additive = new ColorTargetBlendState
{
BlendEnable = true,
AlphaBlendOp = Refresh.BlendOp.Add,
ColorBlendOp = Refresh.BlendOp.Add,
ColorWriteMask = Refresh.ColorComponentFlags.RGBA,
SourceColorBlendFactor = Refresh.BlendFactor.SourceAlpha,
SourceAlphaBlendFactor = Refresh.BlendFactor.SourceAlpha,
DestinationColorBlendFactor = Refresh.BlendFactor.One,
DestinationAlphaBlendFactor = Refresh.BlendFactor.One
};
public static readonly ColorTargetBlendState AlphaBlend = new ColorTargetBlendState
{
BlendEnable = true,
AlphaBlendOp = Refresh.BlendOp.Add,
ColorBlendOp = Refresh.BlendOp.Add,
ColorWriteMask = Refresh.ColorComponentFlags.RGBA,
SourceColorBlendFactor = Refresh.BlendFactor.One,
SourceAlphaBlendFactor = Refresh.BlendFactor.One,
DestinationColorBlendFactor = Refresh.BlendFactor.OneMinusSourceAlpha,
DestinationAlphaBlendFactor = Refresh.BlendFactor.OneMinusSourceAlpha
};
public static readonly ColorTargetBlendState NonPremultiplied = new ColorTargetBlendState
{
BlendEnable = true,
AlphaBlendOp = Refresh.BlendOp.Add,
ColorBlendOp = Refresh.BlendOp.Add,
ColorWriteMask = Refresh.ColorComponentFlags.RGBA,
SourceColorBlendFactor = Refresh.BlendFactor.SourceAlpha,
SourceAlphaBlendFactor = Refresh.BlendFactor.SourceAlpha,
DestinationColorBlendFactor = Refresh.BlendFactor.OneMinusSourceAlpha,
DestinationAlphaBlendFactor = Refresh.BlendFactor.OneMinusSourceAlpha
};
public static readonly ColorTargetBlendState Opaque = new ColorTargetBlendState
{
BlendEnable = true,
AlphaBlendOp = Refresh.BlendOp.Add,
ColorBlendOp = Refresh.BlendOp.Add,
ColorWriteMask = Refresh.ColorComponentFlags.RGBA,
SourceColorBlendFactor = Refresh.BlendFactor.One,
SourceAlphaBlendFactor = Refresh.BlendFactor.One,
DestinationColorBlendFactor = Refresh.BlendFactor.Zero,
DestinationAlphaBlendFactor = Refresh.BlendFactor.Zero
};
public static readonly ColorTargetBlendState None = new ColorTargetBlendState
{
BlendEnable = false,
ColorWriteMask = Refresh.ColorComponentFlags.RGBA
};
public Refresh.ColorTargetBlendState ToRefreshColorTargetBlendState()
{
return new Refresh.ColorTargetBlendState
{
blendEnable = Conversions.BoolToByte(BlendEnable),
alphaBlendOp = AlphaBlendOp,
colorBlendOp = ColorBlendOp,
colorWriteMask = ColorWriteMask,
destinationAlphaBlendFactor = DestinationAlphaBlendFactor,
destinationColorBlendFactor = DestinationColorBlendFactor,
sourceAlphaBlendFactor = SourceAlphaBlendFactor,
sourceColorBlendFactor = SourceColorBlendFactor
};
}
}
}

View File

@ -0,0 +1,43 @@
using RefreshCS;
namespace MoonWorks.Graphics
{
public struct DepthStencilState
{
public bool DepthTestEnable;
public Refresh.StencilOpState BackStencilState;
public Refresh.StencilOpState FrontStencilState;
public Refresh.CompareOp CompareOp;
public bool DepthBoundsTestEnable;
public bool DepthWriteEnable;
public float MinDepthBounds;
public float MaxDepthBounds;
public bool StencilTestEnable;
public static readonly DepthStencilState DepthReadWrite = new DepthStencilState
{
DepthTestEnable = true,
DepthWriteEnable = true,
DepthBoundsTestEnable = false,
StencilTestEnable = false,
CompareOp = Refresh.CompareOp.LessOrEqual
};
public static readonly DepthStencilState DepthRead = new DepthStencilState
{
DepthTestEnable = true,
DepthWriteEnable = false,
DepthBoundsTestEnable = false,
StencilTestEnable = false,
CompareOp = Refresh.CompareOp.LessOrEqual
};
public static readonly DepthStencilState Disable = new DepthStencilState
{
DepthTestEnable = false,
DepthWriteEnable = false,
DepthBoundsTestEnable = false,
StencilTestEnable = false
};
}
}

View File

@ -0,0 +1,8 @@
namespace MoonWorks.Graphics
{
public struct GraphicsPipelineLayoutCreateInfo
{
public uint VertexSamplerBindingCount;
public uint FragmentSamplerBindingCount;
}
}

View File

@ -0,0 +1,16 @@
using RefreshCS;
namespace MoonWorks.Graphics
{
public struct MultisampleState
{
public Refresh.SampleCount MultisampleCount;
public uint SampleMask;
public static readonly MultisampleState None = new MultisampleState
{
MultisampleCount = Refresh.SampleCount.One,
SampleMask = uint.MaxValue
};
}
}

View File

@ -0,0 +1,53 @@
using RefreshCS;
namespace MoonWorks.Graphics
{
public struct RasterizerState
{
public Refresh.CullMode CullMode;
public float DepthBiasClamp;
public float DepthBiasConstantFactor;
public bool DepthBiasEnable;
public float DepthBiasSlopeFactor;
public bool DepthClampEnable;
public Refresh.FillMode FillMode;
public Refresh.FrontFace FrontFace;
public float LineWidth;
public static readonly RasterizerState CullClockwise = new RasterizerState
{
CullMode = Refresh.CullMode.Front,
FrontFace = Refresh.FrontFace.Clockwise,
FillMode = Refresh.FillMode.Fill,
DepthBiasEnable = false,
LineWidth = 1f
};
public static readonly RasterizerState CullCounterClockwise = new RasterizerState
{
CullMode = Refresh.CullMode.Back,
FrontFace = Refresh.FrontFace.Clockwise,
FillMode = Refresh.FillMode.Fill,
DepthBiasEnable = false,
LineWidth = 1f
};
public static readonly RasterizerState CullNone = new RasterizerState
{
CullMode = Refresh.CullMode.None,
FrontFace = Refresh.FrontFace.Clockwise,
FillMode = Refresh.FillMode.Fill,
DepthBiasEnable = false,
LineWidth = 1f
};
public static readonly RasterizerState Wireframe = new RasterizerState
{
CullMode = Refresh.CullMode.None,
FrontFace = Refresh.FrontFace.Clockwise,
FillMode = Refresh.FillMode.Fill,
DepthBiasEnable = false,
LineWidth = 1f
};
}
}

View File

@ -0,0 +1,135 @@
using RefreshCS;
namespace MoonWorks.Graphics
{
public struct SamplerState
{
public Refresh.Filter MinFilter;
public Refresh.Filter MagFilter;
public Refresh.SamplerMipmapMode MipmapMode;
public Refresh.SamplerAddressMode AddressModeU;
public Refresh.SamplerAddressMode AddressModeV;
public Refresh.SamplerAddressMode AddressModeW;
public float MipLodBias;
public bool AnisotropyEnable;
public float MaxAnisotropy;
public bool CompareEnable;
public Refresh.CompareOp CompareOp;
public float MinLod;
public float MaxLod;
public Refresh.BorderColor BorderColor;
public static readonly SamplerState AnisotropicClamp = new SamplerState
{
MinFilter = Refresh.Filter.Linear,
MagFilter = Refresh.Filter.Linear,
MipmapMode = Refresh.SamplerMipmapMode.Linear,
AddressModeU = Refresh.SamplerAddressMode.ClampToEdge,
AddressModeV = Refresh.SamplerAddressMode.ClampToEdge,
AddressModeW = Refresh.SamplerAddressMode.ClampToEdge,
CompareEnable = false,
AnisotropyEnable = true,
MaxAnisotropy = 4,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000 /* VK_LOD_CLAMP_NONE */
};
public static readonly SamplerState AnisotropicWrap = new SamplerState
{
MinFilter = Refresh.Filter.Linear,
MagFilter = Refresh.Filter.Linear,
MipmapMode = Refresh.SamplerMipmapMode.Linear,
AddressModeU = Refresh.SamplerAddressMode.Repeat,
AddressModeV = Refresh.SamplerAddressMode.Repeat,
AddressModeW = Refresh.SamplerAddressMode.Repeat,
CompareEnable = false,
AnisotropyEnable = true,
MaxAnisotropy = 4,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000 /* VK_LOD_CLAMP_NONE */
};
public static readonly SamplerState LinearClamp = new SamplerState
{
MinFilter = Refresh.Filter.Linear,
MagFilter = Refresh.Filter.Linear,
MipmapMode = Refresh.SamplerMipmapMode.Linear,
AddressModeU = Refresh.SamplerAddressMode.ClampToEdge,
AddressModeV = Refresh.SamplerAddressMode.ClampToEdge,
AddressModeW = Refresh.SamplerAddressMode.ClampToEdge,
CompareEnable = false,
AnisotropyEnable = false,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000
};
public static readonly SamplerState LinearWrap = new SamplerState
{
MinFilter = Refresh.Filter.Linear,
MagFilter = Refresh.Filter.Linear,
MipmapMode = Refresh.SamplerMipmapMode.Linear,
AddressModeU = Refresh.SamplerAddressMode.Repeat,
AddressModeV = Refresh.SamplerAddressMode.Repeat,
AddressModeW = Refresh.SamplerAddressMode.Repeat,
CompareEnable = false,
AnisotropyEnable = false,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000
};
public static readonly SamplerState PointClamp = new SamplerState
{
MinFilter = Refresh.Filter.Nearest,
MagFilter = Refresh.Filter.Nearest,
MipmapMode = Refresh.SamplerMipmapMode.Nearest,
AddressModeU = Refresh.SamplerAddressMode.ClampToEdge,
AddressModeV = Refresh.SamplerAddressMode.ClampToEdge,
AddressModeW = Refresh.SamplerAddressMode.ClampToEdge,
CompareEnable = false,
AnisotropyEnable = false,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000
};
public static readonly SamplerState PointWrap = new SamplerState
{
MinFilter = Refresh.Filter.Nearest,
MagFilter = Refresh.Filter.Nearest,
MipmapMode = Refresh.SamplerMipmapMode.Nearest,
AddressModeU = Refresh.SamplerAddressMode.Repeat,
AddressModeV = Refresh.SamplerAddressMode.Repeat,
AddressModeW = Refresh.SamplerAddressMode.Repeat,
CompareEnable = false,
AnisotropyEnable = false,
MipLodBias = 0f,
MinLod = 0,
MaxLod = 1000
};
public Refresh.SamplerStateCreateInfo ToRefreshSamplerStateCreateInfo()
{
return new Refresh.SamplerStateCreateInfo
{
minFilter = MinFilter,
magFilter = MagFilter,
mipmapMode = MipmapMode,
addressModeU = AddressModeU,
addressModeV = AddressModeV,
addressModeW = AddressModeW,
mipLodBias = MipLodBias,
anisotropyEnable = Conversions.BoolToByte(AnisotropyEnable),
maxAnisotropy = MaxAnisotropy,
compareEnable = Conversions.BoolToByte(CompareEnable),
compareOp = CompareOp,
minLod = MinLod,
maxLod = MaxLod,
borderColor = BorderColor
};
}
}
}

View File

@ -0,0 +1,9 @@
namespace MoonWorks.Graphics
{
public struct ShaderStageState
{
public ShaderModule ShaderModule;
public string EntryPointName;
public uint UniformBufferSize;
}
}

View File

@ -0,0 +1,31 @@
using RefreshCS;
namespace MoonWorks.Graphics
{
public struct TextureCreateInfo
{
public uint Width;
public uint Height;
public uint Depth;
public bool IsCube;
public Refresh.SampleCount SampleCount;
public uint LevelCount;
public Refresh.ColorFormat Format;
public Refresh.TextureUsageFlags UsageFlags;
public Refresh.TextureCreateInfo ToRefreshTextureCreateInfo()
{
return new Refresh.TextureCreateInfo
{
width = Width,
height = Height,
depth = Depth,
isCube = Conversions.BoolToByte(IsCube),
sampleCount = SampleCount,
levelCount = LevelCount,
format = Format,
usageFlags = UsageFlags
};
}
}
}

View File

@ -0,0 +1,10 @@
using RefreshCS;
namespace MoonWorks.Graphics
{
public struct VertexInputState
{
public Refresh.VertexBinding[] VertexBindings;
public Refresh.VertexAttribute[] VertexAttributes;
}
}

View File

@ -0,0 +1,10 @@
using RefreshCS;
namespace MoonWorks.Graphics
{
public struct ViewportState
{
public Refresh.Viewport[] Viewports;
public Refresh.Rect[] Scissors;
}
}

171
src/Graphics/Texture.cs Normal file
View File

@ -0,0 +1,171 @@
using System;
using System.IO;
using RefreshCS;
namespace MoonWorks.Graphics
{
public class Texture : GraphicsResource
{
public uint Width { get; }
public uint Height { get; }
public Refresh.ColorFormat Format { get; }
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyTexture;
public static Texture LoadPNG(GraphicsDevice device, FileInfo fileInfo)
{
var pixels = Refresh.Refresh_Image_Load(
fileInfo.FullName,
out var width,
out var height,
out var channels
);
MoonWorks.Graphics.TextureCreateInfo textureCreateInfo;
textureCreateInfo.Width = (uint)width;
textureCreateInfo.Height = (uint)height;
textureCreateInfo.Depth = 1;
textureCreateInfo.Format = Refresh.ColorFormat.R8G8B8A8;
textureCreateInfo.IsCube = false;
textureCreateInfo.LevelCount = 1;
textureCreateInfo.SampleCount = Refresh.SampleCount.One;
textureCreateInfo.UsageFlags = Refresh.TextureUsageFlags.SamplerBit;
var texture = new Texture(device, ref textureCreateInfo);
texture.SetData(pixels, (uint)(width * height * 4));
Refresh.Refresh_Image_Free(pixels);
return texture;
}
public unsafe static void SavePNG(string path, int width, int height, byte[] pixels)
{
fixed (byte* ptr = &pixels[0])
{
Refresh.Refresh_Image_SavePNG(path, width, height, (IntPtr) ptr);
}
}
public static Texture CreateTexture2D(
GraphicsDevice device,
uint width,
uint height,
Refresh.ColorFormat format,
Refresh.TextureUsageFlags usageFlags,
Refresh.SampleCount sampleCount = Refresh.SampleCount.One,
uint levelCount = 1
)
{
var textureCreateInfo = new MoonWorks.Graphics.TextureCreateInfo
{
Width = width,
Height = height,
Depth = 1,
IsCube = false,
SampleCount = sampleCount,
LevelCount = levelCount,
Format = format,
UsageFlags = usageFlags
};
return new Texture(device, ref textureCreateInfo);
}
public static Texture CreateTexture3D(
GraphicsDevice device,
uint width,
uint height,
uint depth,
Refresh.ColorFormat format,
Refresh.TextureUsageFlags usageFlags,
Refresh.SampleCount sampleCount = Refresh.SampleCount.One,
uint levelCount = 1
)
{
var textureCreateInfo = new MoonWorks.Graphics.TextureCreateInfo
{
Width = width,
Height = height,
Depth = depth,
IsCube = false,
SampleCount = sampleCount,
LevelCount = levelCount,
Format = format,
UsageFlags = usageFlags
};
return new Texture(device, ref textureCreateInfo);
}
public static Texture CreateTextureCube(
GraphicsDevice device,
uint size,
Refresh.ColorFormat format,
Refresh.TextureUsageFlags usageFlags,
Refresh.SampleCount sampleCount = Refresh.SampleCount.One,
uint levelCount = 1
)
{
var textureCreateInfo = new MoonWorks.Graphics.TextureCreateInfo
{
Width = size,
Height = size,
Depth = 1,
IsCube = true,
SampleCount = sampleCount,
LevelCount = levelCount,
Format = format,
UsageFlags = usageFlags
};
return new Texture(device, ref textureCreateInfo);
}
public Texture(GraphicsDevice device, ref MoonWorks.Graphics.TextureCreateInfo textureCreateInfo) : base(device)
{
var refreshTextureCreateInfo = textureCreateInfo.ToRefreshTextureCreateInfo();
Handle = Refresh.Refresh_CreateTexture(
device.Handle,
ref refreshTextureCreateInfo
);
Format = textureCreateInfo.Format;
Width = textureCreateInfo.Width;
Height = textureCreateInfo.Height;
}
public void SetData(IntPtr data, uint dataLengthInBytes)
{
Refresh.TextureSlice textureSlice;
textureSlice.texture = Handle;
textureSlice.rectangle.x = 0;
textureSlice.rectangle.y = 0;
textureSlice.rectangle.w = (int)Width;
textureSlice.rectangle.h = (int)Height;
textureSlice.level = 0;
textureSlice.layer = 0;
textureSlice.depth = 0;
Refresh.Refresh_SetTextureData(
Device.Handle,
ref textureSlice,
data,
dataLengthInBytes
);
}
public void SetData(ref TextureSlice textureSlice, IntPtr data, uint dataLengthInBytes)
{
var refreshTextureSlice = textureSlice.ToRefreshTextureSlice();
Refresh.Refresh_SetTextureData(
Device.Handle,
ref refreshTextureSlice,
data,
dataLengthInBytes
);
}
}
}

View File

@ -0,0 +1,14 @@
namespace MoonWorks.Graphics
{
public struct TextureSamplerBinding
{
public Texture Texture;
public Sampler Sampler;
public TextureSamplerBinding(Texture texture, Sampler sampler)
{
Texture = texture;
Sampler = sampler;
}
}
}

View File

@ -0,0 +1,51 @@
using RefreshCS;
namespace MoonWorks.Graphics
{
public struct TextureSlice
{
public Texture Texture { get; }
public Refresh.Rect Rectangle { get; }
public uint Depth { get; }
public uint Layer { get; }
public uint Level { get; }
public TextureSlice(Texture texture)
{
Texture = texture;
Rectangle = new Refresh.Rect
{
x = 0,
y = 0,
w = (int) texture.Width,
h = (int) texture.Height
};
Depth = 0;
Layer = 0;
Level = 0;
}
public TextureSlice(Texture texture, Refresh.Rect rectangle, uint depth = 0, uint layer = 0, uint level = 0)
{
Texture = texture;
Rectangle = rectangle;
Depth = depth;
Layer = layer;
Level = level;
}
public RefreshCS.Refresh.TextureSlice ToRefreshTextureSlice()
{
RefreshCS.Refresh.TextureSlice textureSlice = new RefreshCS.Refresh.TextureSlice
{
texture = Texture.Handle,
rectangle = Rectangle,
depth = Depth,
layer = Layer,
level = Level
};
return textureSlice;
}
}
}

View File

@ -24,7 +24,7 @@ namespace MoonWorks
ScreenMode = windowCreateInfo.ScreenMode;
Handle = SDL.SDL_CreateWindow(
"CampariTest",
"MoonWorks.GraphicsTest",
SDL.SDL_WINDOWPOS_UNDEFINED,
SDL.SDL_WINDOWPOS_UNDEFINED,
(int)windowCreateInfo.WindowWidth,