refactor RenderPass structure

sdl2_gpu
cosmonaut 2024-06-04 16:04:19 -07:00
parent 4e8653fb1f
commit eab282cdca
19 changed files with 913 additions and 1196 deletions

@ -1 +1 @@
Subproject commit 2866dd2a7d4ffd4366bd4885e04c68cf4b485b55
Subproject commit 60e2c21a7b224dc6aa6a457dbb71d798a4e66241

View File

@ -8,7 +8,7 @@ public readonly record struct BufferBinding(
GpuBuffer Buffer,
uint Offset
) {
public SDL_Gpu.BufferBinding ToRefresh()
public SDL_Gpu.BufferBinding ToSDL()
{
return new SDL_Gpu.BufferBinding
{

File diff suppressed because it is too large Load Diff

View File

@ -38,8 +38,9 @@ namespace MoonWorks.Graphics
public bool IsDisposed { get; private set; }
private readonly HashSet<GCHandle> resources = new HashSet<GCHandle>();
private FencePool FencePool;
private CommandBufferPool CommandBufferPool;
internal RenderPassPool RenderPassPool;
private FencePool FencePool;
internal unsafe GraphicsDevice(
Span<Backend> preferredBackends,
@ -149,12 +150,12 @@ namespace MoonWorks.Graphics
)
),
DepthStencilState = DepthStencilState.Disable,
VertexShaderInfo = GraphicsShaderInfo.Create(
VertexShaderResourceInfo = GraphicsShaderInfo.Create(
fullscreenVertShader,
"main",
0
),
FragmentShaderInfo = GraphicsShaderInfo.Create(
FragmentShaderResourceInfo = GraphicsShaderInfo.Create(
videoFragShader,
"main",
3
@ -177,12 +178,12 @@ namespace MoonWorks.Graphics
)
),
DepthStencilState = DepthStencilState.Disable,
VertexShaderInfo = GraphicsShaderInfo.Create(
VertexShaderResourceInfo = GraphicsShaderInfo.Create(
fullscreenVertShader,
"main",
0
),
FragmentShaderInfo = GraphicsShaderInfo.Create(
FragmentShaderResourceInfo = GraphicsShaderInfo.Create(
blitFragShader,
"main",
1

View File

@ -13,16 +13,17 @@ public class RenderPass
#if DEBUG
internal bool active;
internal uint colorAttachmentCount;
internal SampleCount colorAttachmentSampleCount;
internal TextureFormat colorFormatOne;
internal TextureFormat colorFormatTwo;
internal TextureFormat colorFormatThree;
internal TextureFormat colorFormatFour;
internal bool hasDepthStencilAttachment;
internal SampleCount depthStencilAttachmentSampleCount;
internal TextureFormat depthStencilFormat;
GraphicsPipeline currentGraphicsPipeline;
uint colorAttachmentCount;
SampleCount colorAttachmentSampleCount;
TextureFormat colorFormatOne;
TextureFormat colorFormatTwo;
TextureFormat colorFormatThree;
TextureFormat colorFormatFour;
bool hasDepthStencilAttachment;
SampleCount depthStencilAttachmentSampleCount;
TextureFormat depthStencilFormat;
#endif
internal void SetHandle(nint handle)
@ -79,7 +80,7 @@ public class RenderPass
SDL_Gpu.SDL_GpuSetViewport(
Handle,
viewport.ToRefresh()
viewport.ToSDL()
);
}
@ -99,7 +100,7 @@ public class RenderPass
SDL_Gpu.SDL_GpuSetScissor(
Handle,
scissor.ToRefresh()
scissor.ToSDL()
);
}
@ -108,7 +109,7 @@ public class RenderPass
/// </summary>
/// <param name="bufferBinding">Buffer to bind and associated offset.</param>
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
public unsafe void BindVertexBuffers(
public unsafe void BindVertexBuffer(
in BufferBinding bufferBinding,
uint firstBinding = 0
) {
@ -116,137 +117,16 @@ public class RenderPass
AssertGraphicsPipelineBound();
#endif
var bindingArray = stackalloc SDL_Gpu.BufferBinding[1];
bindingArray[0] = bufferBinding.ToRefresh();
var sdlBufferBinding = bufferBinding.ToSDL();
SDL_Gpu.SDL_GpuBindVertexBuffers(
Handle,
firstBinding,
bindingArray,
&sdlBufferBinding,
1
);
}
/// <summary>
/// Binds vertex buffers to be used by subsequent draw calls.
/// </summary>
/// <param name="bufferBindingOne">Buffer to bind and associated offset.</param>
/// <param name="bufferBindingTwo">Buffer to bind and associated offset.</param>
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
public unsafe void BindVertexBuffers(
in BufferBinding bufferBindingOne,
in BufferBinding bufferBindingTwo,
uint firstBinding = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
#endif
var bindingArray = stackalloc SDL_Gpu.BufferBinding[2];
bindingArray[0] = bufferBindingOne.ToRefresh();
bindingArray[1] = bufferBindingTwo.ToRefresh();
SDL_Gpu.SDL_GpuBindVertexBuffers(
Handle,
firstBinding,
bindingArray,
2
);
}
/// <summary>
/// Binds vertex buffers to be used by subsequent draw calls.
/// </summary>
/// <param name="bufferBindingOne">Buffer to bind and associated offset.</param>
/// <param name="bufferBindingTwo">Buffer to bind and associated offset.</param>
/// <param name="bufferBindingThree">Buffer to bind and associated offset.</param>
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
public unsafe void BindVertexBuffers(
in BufferBinding bufferBindingOne,
in BufferBinding bufferBindingTwo,
in BufferBinding bufferBindingThree,
uint firstBinding = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
#endif
var bindingArray = stackalloc SDL_Gpu.BufferBinding[3];
bindingArray[0] = bufferBindingOne.ToRefresh();
bindingArray[1] = bufferBindingTwo.ToRefresh();
bindingArray[2] = bufferBindingThree.ToRefresh();
SDL_Gpu.SDL_GpuBindVertexBuffers(
Handle,
firstBinding,
bindingArray,
3
);
}
/// <summary>
/// Binds vertex buffers to be used by subsequent draw calls.
/// </summary>
/// <param name="bufferBindingOne">Buffer to bind and associated offset.</param>
/// <param name="bufferBindingTwo">Buffer to bind and associated offset.</param>
/// <param name="bufferBindingThree">Buffer to bind and associated offset.</param>
/// <param name="bufferBindingFour">Buffer to bind and associated offset.</param>
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
public unsafe void BindVertexBuffers(
in BufferBinding bufferBindingOne,
in BufferBinding bufferBindingTwo,
in BufferBinding bufferBindingThree,
in BufferBinding bufferBindingFour,
uint firstBinding = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
#endif
var bindingArray = stackalloc SDL_Gpu.BufferBinding[4];
bindingArray[0] = bufferBindingOne.ToRefresh();
bindingArray[1] = bufferBindingTwo.ToRefresh();
bindingArray[2] = bufferBindingThree.ToRefresh();
bindingArray[3] = bufferBindingFour.ToRefresh();
SDL_Gpu.SDL_GpuBindVertexBuffers(
Handle,
firstBinding,
bindingArray,
4
);
}
/// <summary>
/// Binds vertex buffers to be used by subsequent draw calls.
/// </summary>
/// <param name="bufferBindings">Spawn of buffers to bind and their associated offsets.</param>
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
public unsafe void BindVertexBuffers(
in Span<BufferBinding> bufferBindings,
uint firstBinding = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
#endif
SDL_Gpu.BufferBinding* bufferBindingsArray = (SDL_Gpu.BufferBinding*) NativeMemory.Alloc((nuint) (Marshal.SizeOf<SDL_Gpu.BufferBinding>() * bufferBindings.Length));
for (var i = 0; i < bufferBindings.Length; i += 1)
{
bufferBindingsArray[i] = bufferBindings[i].ToRefresh();
}
SDL_Gpu.SDL_GpuBindVertexBuffers(
Handle,
firstBinding,
bufferBindingsArray,
(uint) bufferBindings.Length
);
NativeMemory.Free(bufferBindingsArray);
}
/// <summary>
/// Binds an index buffer to be used by subsequent draw calls.
/// </summary>
@ -264,7 +144,7 @@ public class RenderPass
SDL_Gpu.SDL_GpuBindIndexBuffer(
Handle,
bufferBinding.ToRefresh(),
bufferBinding.ToSDL(),
(SDL_Gpu.IndexElementSize) indexElementSize
);
}
@ -283,104 +163,280 @@ public class RenderPass
AssertTextureHasSamplerFlag(textureSamplerBinding.Texture);
#endif
var bindingArray = stackalloc SDL_Gpu.TextureSamplerBinding[1];
bindingArray[0] = textureSamplerBinding.ToSDL();
var sdlTextureSamplerBinding = textureSamplerBinding.ToSDL();
SDL_Gpu.SDL_GpuBindVertexSamplers(
Handle,
slot,
bindingArray,
&sdlTextureSamplerBinding,
1
);
}
public unsafe void BindVertexSamplers(
in Span<TextureSamplerBinding> textureSamplerBindings,
uint firstSlot = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
for (var i = 0; i < textureSamplerBindings.Length; i += 1)
{
AssertTextureSamplerBindingNonNull(textureSamplerBindings[i]);
AssertTextureHasSamplerFlag(textureSamplerBindings[i].Texture);
}
#endif
SDL_Gpu.TextureSamplerBinding* samplerBindingsArray =
(SDL_Gpu.TextureSamplerBinding*) NativeMemory.Alloc(
(nuint) (Marshal.SizeOf<SDL_Gpu.TextureSamplerBinding>() * textureSamplerBindings.Length)
);
for (var i = 0; i < textureSamplerBindings.Length; i += 1)
{
samplerBindingsArray[i] = textureSamplerBindings[i].ToSDL();
}
SDL_Gpu.SDL_GpuBindVertexSamplers(
Handle,
firstSlot,
samplerBindingsArray,
(uint) textureSamplerBindings.Length
);
NativeMemory.Free(samplerBindingsArray);
}
public unsafe void BindVertexStorageTexture(
in TextureSlice storageTextureSlice,
in TextureSlice textureSlice,
uint slot = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
AssertTextureNonNull(storageTextureSlice.Texture);
AssertTextureHasGraphicsStorageFlag(storageTextureSlice.Texture);
AssertTextureNonNull(textureSlice.Texture);
AssertTextureHasGraphicsStorageFlag(textureSlice.Texture);
#endif
var sliceArray = stackalloc SDL_Gpu.TextureSlice[1];
sliceArray[0] = storageTextureSlice.ToSDL();
var sdlTextureSlice = textureSlice.ToSDL();
SDL_Gpu.SDL_GpuBindVertexStorageTextures(
Handle,
slot,
sliceArray,
&sdlTextureSlice,
1
);
}
public unsafe void BindVertexStorageTextures(
in Span<TextureSlice> storageTextureSlices,
uint firstSlot = 0
public unsafe void BindVertexStorageBuffer(
GpuBuffer buffer,
uint slot = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
AssertBufferNonNull(buffer);
AssertBufferHasGraphicsStorageFlag(buffer);
#endif
var bufferHandle = buffer.Handle;
SDL_Gpu.SDL_GpuBindVertexStorageBuffers(
Handle,
slot,
&bufferHandle,
1
);
}
public unsafe void BindFragmentSamplers(
in TextureSamplerBinding textureSamplerBinding,
uint slot = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
AssertTextureSamplerBindingNonNull(textureSamplerBinding);
AssertTextureHasSamplerFlag(textureSamplerBinding.Texture);
#endif
var sdlTextureSamplerBinding = textureSamplerBinding.ToSDL();
SDL_Gpu.SDL_GpuBindFragmentSamplers(
Handle,
slot,
&sdlTextureSamplerBinding,
1
);
}
public unsafe void BindFragmentStorageTexture(
in TextureSlice textureSlice,
uint slot = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
AssertTextureNonNull(textureSlice.Texture);
AssertTextureHasGraphicsStorageFlag(textureSlice.Texture);
#endif
var sdlTextureSlice = textureSlice.ToSDL();
SDL_Gpu.SDL_GpuBindFragmentStorageTextures(
Handle,
slot,
&sdlTextureSlice,
1
);
}
public unsafe void BindFragmentStorageBuffer(
GpuBuffer buffer,
uint slot = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
AssertBufferNonNull(buffer);
AssertBufferHasGraphicsStorageFlag(buffer);
#endif
var bufferHandle = buffer.Handle;
SDL_Gpu.SDL_GpuBindFragmentStorageBuffers(
Handle,
slot,
&bufferHandle,
1
);
}
public unsafe void PushVertexUniformData(
void* uniformsPtr,
uint size,
uint slot = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
for (var i = 0; i < storageTextureSlices.Length; i += 1)
if (slot >= currentGraphicsPipeline.VertexShaderResourceInfo.UniformBufferCount)
{
AssertTextureNonNull(storageTextureSlices[i].Texture);
AssertTextureHasGraphicsStorageFlag(storageTextureSlices[i].Texture);
throw new System.ArgumentException($"Slot {slot} given, but {currentGraphicsPipeline.VertexShaderResourceInfo.UniformBufferCount} uniform buffers are used on the shader!");
}
#endif
SDL_Gpu.TextureSlice* sliceArray =
(SDL_Gpu.TextureSlice*) NativeMemory.Alloc(
(nuint) (Marshal.SizeOf<SDL_Gpu.TextureSlice>() * storageTextureSlices.Length)
SDL_Gpu.SDL_GpuPushVertexUniformData(
Handle,
slot,
(nint) uniformsPtr,
size
);
for (var i = 0; i < storageTextureSlices.Length; i += 1)
{
sliceArray[i] = storageTextureSlices[i].ToSDL();
}
SDL_Gpu.SDL_GpuBindVertexStorageTextures(
Handle,
firstSlot,
sliceArray,
(uint) storageTextureSlices.Length
);
public unsafe void PushVertexUniformData<T>(
in T uniforms
) where T : unmanaged
{
fixed (T* uniformsPtr = &uniforms)
{
PushVertexUniformData(uniformsPtr, (uint) Marshal.SizeOf<T>());
}
}
NativeMemory.Free(sliceArray);
public unsafe void PushFragmentUniformData(
void* uniformsPtr,
uint size,
uint slot = 0
) {
#if DEBUG
AssertGraphicsPipelineBound();
if (slot >= currentGraphicsPipeline.FragmentShaderResourceInfo.UniformBufferCount)
{
throw new System.ArgumentException($"Slot {slot} given, but {currentGraphicsPipeline.FragmentShaderResourceInfo.UniformBufferCount} uniform buffers are used on the shader!");
}
#endif
SDL_Gpu.SDL_GpuPushFragmentUniformData(
Handle,
slot,
(nint) uniformsPtr,
size
);
}
public unsafe void PushFragmentUniformData<T>(
in T uniforms
) where T : unmanaged
{
fixed (T* uniformsPtr = &uniforms)
{
PushFragmentUniformData(uniformsPtr, (uint) Marshal.SizeOf<T>());
}
}
/// <summary>
/// Draws using a vertex buffer and an index buffer, and an optional instance count.
/// </summary>
/// <param name="baseVertex">The starting index offset for the vertex buffer.</param>
/// <param name="startIndex">The starting index offset for the index buffer.</param>
/// <param name="primitiveCount">The number of primitives to draw.</param>
/// <param name="instanceCount">The number of instances to draw.</param>
public void DrawIndexedPrimitives(
uint baseVertex,
uint startIndex,
uint primitiveCount,
uint instanceCount = 1
) {
#if DEBUG
AssertGraphicsPipelineBound();
#endif
SDL_Gpu.SDL_GpuDrawIndexedPrimitives(
Handle,
baseVertex,
startIndex,
primitiveCount,
instanceCount
);
}
/// <summary>
/// Draws using a vertex buffer and an index buffer.
/// </summary>
/// <param name="baseVertex">The starting index offset for the vertex buffer.</param>
/// <param name="startIndex">The starting index offset for the index buffer.</param>
/// <param name="primitiveCount">The number of primitives to draw.</param>
public void DrawPrimitives(
uint vertexStart,
uint primitiveCount
)
{
#if DEBUG
AssertGraphicsPipelineBound();
#endif
SDL_Gpu.SDL_GpuDrawPrimitives(
Handle,
vertexStart,
primitiveCount
);
}
/// <summary>
/// Similar to DrawPrimitives, but parameters are set from a buffer.
/// The buffer must have the Indirect usage flag set.
/// </summary>
/// <param name="buffer">The draw parameters buffer.</param>
/// <param name="offsetInBytes">The offset to start reading from the draw parameters buffer.</param>
/// <param name="drawCount">The number of draw parameter sets that should be read from the buffer.</param>
/// <param name="stride">The byte stride between sets of draw parameters.</param>
public void DrawPrimitivesIndirect(
GpuBuffer buffer,
uint offsetInBytes,
uint drawCount,
uint stride
) {
#if DEBUG
AssertGraphicsPipelineBound();
#endif
SDL_Gpu.SDL_GpuDrawPrimitivesIndirect(
Handle,
buffer.Handle,
offsetInBytes,
drawCount,
stride
);
}
/// <summary>
/// Similar to DrawIndexedPrimitives, but parameters are set from a buffer.
/// The buffer must have the Indirect usage flag set.
/// </summary>
/// <param name="buffer">The draw parameters buffer.</param>
/// <param name="offsetInBytes">The offset to start reading from the draw parameters buffer.</param>
/// <param name="drawCount">The number of draw parameter sets that should be read from the buffer.</param>
/// <param name="stride">The byte stride between sets of draw parameters.</param>
public void DrawIndexedPrimitivesIndirect(
GpuBuffer buffer,
uint offsetInBytes,
uint drawCount,
uint stride
) {
#if DEBUG
AssertGraphicsPipelineBound();
#endif
SDL_Gpu.SDL_GpuDrawIndexedPrimitivesIndirect(
Handle,
buffer.Handle,
offsetInBytes,
drawCount,
stride
);
}
#if DEBUG
@ -481,5 +537,21 @@ public class RenderPass
throw new System.ArgumentException("The bound Texture's UsageFlags must include TextureUsageFlags.GraphicsStorage!");
}
}
private void AssertBufferNonNull(GpuBuffer buffer)
{
if (buffer == null || buffer.Handle == IntPtr.Zero)
{
throw new System.NullReferenceException("Buffer must not be null!");
}
}
private void AssertBufferHasGraphicsStorageFlag(GpuBuffer buffer)
{
if ((buffer.UsageFlags & BufferUsageFlags.GraphicsStorage) == 0)
{
throw new System.ArgumentException("The bound Buffer's UsageFlags must include BufferUsageFlag.GraphicsStorage!");
}
}
#endif
}

View File

@ -0,0 +1,26 @@
using System.Collections.Concurrent;
namespace MoonWorks.Graphics
{
internal class RenderPassPool
{
private ConcurrentQueue<RenderPass> RenderPasses = new ConcurrentQueue<RenderPass>();
public RenderPass Obtain()
{
if (RenderPasses.TryDequeue(out var renderPass))
{
return renderPass;
}
else
{
return new RenderPass();
}
}
public void Return(RenderPass renderPass)
{
RenderPasses.Enqueue(renderPass);
}
}
}

View File

@ -1,15 +1,17 @@
using System;
using System.Runtime.InteropServices;
using RefreshCS;
using SDL2_gpuCS;
namespace MoonWorks.Graphics;
namespace MoonWorks.Graphics
{
/// <summary>
/// GpuBuffers are generic data containers that can be used by the GPU.
/// </summary>
public class GpuBuffer : SDL_GpuResource
{
protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_QueueDestroyGpuBuffer;
protected override Action<IntPtr, IntPtr> ReleaseFunction => SDL_Gpu.SDL_GpuReleaseBuffer;
public BufferUsageFlags UsageFlags { get; }
/// <summary>
/// Size in bytes.
@ -25,7 +27,7 @@ namespace MoonWorks.Graphics
{
if (Device.DebugMode)
{
Refresh.Refresh_SetGpuBufferName(
SDL_Gpu.SDL_GpuSetBufferName(
Device.Handle,
Handle,
value
@ -69,11 +71,12 @@ namespace MoonWorks.Graphics
uint sizeInBytes
) : base(device)
{
Handle = Refresh.Refresh_CreateGpuBuffer(
Handle = SDL_Gpu.SDL_GpuCreateBuffer(
device.Handle,
(Refresh.BufferUsageFlags) usageFlags,
(SDL_Gpu.BufferUsageFlags) usageFlags,
sizeInBytes
);
UsageFlags = usageFlags;
Size = sizeInBytes;
name = "";
}
@ -83,4 +86,3 @@ namespace MoonWorks.Graphics
return new BufferBinding(b, 0);
}
}
}

View File

@ -1,6 +1,6 @@
using System;
using System.Runtime.InteropServices;
using RefreshCS;
using SDL2_gpuCS;
namespace MoonWorks.Graphics
{
@ -10,10 +10,10 @@ namespace MoonWorks.Graphics
/// </summary>
public class GraphicsPipeline : SDL_GpuResource
{
protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_QueueDestroyGraphicsPipeline;
protected override Action<IntPtr, IntPtr> ReleaseFunction => SDL_Gpu.SDL_GpuReleaseGraphicsPipeline;
public GraphicsShaderInfo VertexShaderInfo { get; }
public GraphicsShaderInfo FragmentShaderInfo { get; }
public GraphicsPipelineResourceInfo VertexShaderResourceInfo { get; }
public GraphicsPipelineResourceInfo FragmentShaderResourceInfo { get; }
public SampleCount SampleCount { get; }
#if DEBUG
@ -25,103 +25,78 @@ namespace MoonWorks.Graphics
in GraphicsPipelineCreateInfo graphicsPipelineCreateInfo
) : base(device)
{
DepthStencilState depthStencilState = graphicsPipelineCreateInfo.DepthStencilState;
GraphicsShaderInfo vertexShaderInfo = graphicsPipelineCreateInfo.VertexShaderInfo;
GraphicsShaderInfo fragmentShaderInfo = graphicsPipelineCreateInfo.FragmentShaderInfo;
MultisampleState multisampleState = graphicsPipelineCreateInfo.MultisampleState;
RasterizerState rasterizerState = graphicsPipelineCreateInfo.RasterizerState;
PrimitiveType primitiveType = graphicsPipelineCreateInfo.PrimitiveType;
VertexInputState vertexInputState = graphicsPipelineCreateInfo.VertexInputState;
GraphicsPipelineAttachmentInfo attachmentInfo = graphicsPipelineCreateInfo.AttachmentInfo;
BlendConstants blendConstants = graphicsPipelineCreateInfo.BlendConstants;
SDL_Gpu.GraphicsPipelineCreateInfo sdlGraphicsPipelineCreateInfo;
var vertexAttributesHandle = GCHandle.Alloc(
vertexInputState.VertexAttributes,
GCHandleType.Pinned
);
var vertexBindingsHandle = GCHandle.Alloc(
vertexInputState.VertexBindings,
GCHandleType.Pinned
var vertexAttributes = (SDL_Gpu.VertexAttribute*) NativeMemory.Alloc(
(nuint) (graphicsPipelineCreateInfo.VertexInputState.VertexAttributes.Length * Marshal.SizeOf<SDL_Gpu.VertexAttribute>())
);
var colorAttachmentDescriptions = stackalloc Refresh.ColorAttachmentDescription[
(int) attachmentInfo.ColorAttachmentDescriptions.Length
];
for (var i = 0; i < attachmentInfo.ColorAttachmentDescriptions.Length; i += 1)
for (var i = 0; i < graphicsPipelineCreateInfo.VertexInputState.VertexAttributes.Length; i += 1)
{
colorAttachmentDescriptions[i].format = (Refresh.TextureFormat) attachmentInfo.ColorAttachmentDescriptions[i].Format;
colorAttachmentDescriptions[i].blendState = attachmentInfo.ColorAttachmentDescriptions[i].BlendState.ToRefresh();
vertexAttributes[i] = graphicsPipelineCreateInfo.VertexInputState.VertexAttributes[i].ToSDL();
}
Refresh.GraphicsPipelineCreateInfo refreshGraphicsPipelineCreateInfo;
var vertexBindings = (SDL_Gpu.VertexBinding*) NativeMemory.Alloc(
(nuint) (graphicsPipelineCreateInfo.VertexInputState.VertexBindings.Length * Marshal.SizeOf<SDL_Gpu.VertexBinding>())
);
refreshGraphicsPipelineCreateInfo.blendConstants[0] = blendConstants.R;
refreshGraphicsPipelineCreateInfo.blendConstants[1] = blendConstants.G;
refreshGraphicsPipelineCreateInfo.blendConstants[2] = blendConstants.B;
refreshGraphicsPipelineCreateInfo.blendConstants[3] = blendConstants.A;
for (var i = 0; i < graphicsPipelineCreateInfo.VertexInputState.VertexBindings.Length; i += 1)
{
vertexBindings[i] = graphicsPipelineCreateInfo.VertexInputState.VertexBindings[i].ToSDL();
}
refreshGraphicsPipelineCreateInfo.depthStencilState.backStencilState = depthStencilState.BackStencilState.ToRefresh();
refreshGraphicsPipelineCreateInfo.depthStencilState.frontStencilState = depthStencilState.FrontStencilState.ToRefresh();
refreshGraphicsPipelineCreateInfo.depthStencilState.compareMask = depthStencilState.CompareMask;
refreshGraphicsPipelineCreateInfo.depthStencilState.writeMask = depthStencilState.WriteMask;
refreshGraphicsPipelineCreateInfo.depthStencilState.reference = depthStencilState.Reference;
refreshGraphicsPipelineCreateInfo.depthStencilState.compareOp = (Refresh.CompareOp) depthStencilState.CompareOp;
refreshGraphicsPipelineCreateInfo.depthStencilState.depthBoundsTestEnable = Conversions.BoolToByte(depthStencilState.DepthBoundsTestEnable);
refreshGraphicsPipelineCreateInfo.depthStencilState.depthTestEnable = Conversions.BoolToByte(depthStencilState.DepthTestEnable);
refreshGraphicsPipelineCreateInfo.depthStencilState.depthWriteEnable = Conversions.BoolToByte(depthStencilState.DepthWriteEnable);
refreshGraphicsPipelineCreateInfo.depthStencilState.maxDepthBounds = depthStencilState.MaxDepthBounds;
refreshGraphicsPipelineCreateInfo.depthStencilState.minDepthBounds = depthStencilState.MinDepthBounds;
refreshGraphicsPipelineCreateInfo.depthStencilState.stencilTestEnable = Conversions.BoolToByte(depthStencilState.StencilTestEnable);
var colorAttachmentDescriptions = stackalloc SDL_Gpu.ColorAttachmentDescription[
graphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions.Length
];
refreshGraphicsPipelineCreateInfo.vertexShaderInfo.entryPointName = vertexShaderInfo.EntryPointName;
refreshGraphicsPipelineCreateInfo.vertexShaderInfo.shaderModule = vertexShaderInfo.ShaderModule.Handle;
refreshGraphicsPipelineCreateInfo.vertexShaderInfo.uniformBufferSize = vertexShaderInfo.UniformBufferSize;
refreshGraphicsPipelineCreateInfo.vertexShaderInfo.samplerBindingCount = vertexShaderInfo.SamplerBindingCount;
for (var i = 0; i < graphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions.Length; i += 1)
{
colorAttachmentDescriptions[i].Format = (SDL_Gpu.TextureFormat) graphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions[i].Format;
colorAttachmentDescriptions[i].BlendState = graphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions[i].BlendState.ToSDL();
}
refreshGraphicsPipelineCreateInfo.fragmentShaderInfo.entryPointName = fragmentShaderInfo.EntryPointName;
refreshGraphicsPipelineCreateInfo.fragmentShaderInfo.shaderModule = fragmentShaderInfo.ShaderModule.Handle;
refreshGraphicsPipelineCreateInfo.fragmentShaderInfo.uniformBufferSize = fragmentShaderInfo.UniformBufferSize;
refreshGraphicsPipelineCreateInfo.fragmentShaderInfo.samplerBindingCount = fragmentShaderInfo.SamplerBindingCount;
sdlGraphicsPipelineCreateInfo.VertexShader = graphicsPipelineCreateInfo.VertexShader.Handle;
sdlGraphicsPipelineCreateInfo.FragmentShader = graphicsPipelineCreateInfo.FragmentShader.Handle;
refreshGraphicsPipelineCreateInfo.multisampleState.multisampleCount = (Refresh.SampleCount) multisampleState.MultisampleCount;
refreshGraphicsPipelineCreateInfo.multisampleState.sampleMask = multisampleState.SampleMask;
sdlGraphicsPipelineCreateInfo.VertexInputState.VertexAttributes = vertexAttributes;
sdlGraphicsPipelineCreateInfo.VertexInputState.VertexAttributeCount = (uint) graphicsPipelineCreateInfo.VertexInputState.VertexAttributes.Length;
sdlGraphicsPipelineCreateInfo.VertexInputState.VertexBindings = vertexBindings;
sdlGraphicsPipelineCreateInfo.VertexInputState.VertexBindingCount = (uint) graphicsPipelineCreateInfo.VertexInputState.VertexBindings.Length;
refreshGraphicsPipelineCreateInfo.rasterizerState.cullMode = (Refresh.CullMode) rasterizerState.CullMode;
refreshGraphicsPipelineCreateInfo.rasterizerState.depthBiasClamp = rasterizerState.DepthBiasClamp;
refreshGraphicsPipelineCreateInfo.rasterizerState.depthBiasConstantFactor = rasterizerState.DepthBiasConstantFactor;
refreshGraphicsPipelineCreateInfo.rasterizerState.depthBiasEnable = Conversions.BoolToByte(rasterizerState.DepthBiasEnable);
refreshGraphicsPipelineCreateInfo.rasterizerState.depthBiasSlopeFactor = rasterizerState.DepthBiasSlopeFactor;
refreshGraphicsPipelineCreateInfo.rasterizerState.fillMode = (Refresh.FillMode) rasterizerState.FillMode;
refreshGraphicsPipelineCreateInfo.rasterizerState.frontFace = (Refresh.FrontFace) rasterizerState.FrontFace;
sdlGraphicsPipelineCreateInfo.PrimitiveType = (SDL_Gpu.PrimitiveType) graphicsPipelineCreateInfo.PrimitiveType;
refreshGraphicsPipelineCreateInfo.vertexInputState.vertexAttributes = vertexAttributesHandle.AddrOfPinnedObject();
refreshGraphicsPipelineCreateInfo.vertexInputState.vertexAttributeCount = (uint) vertexInputState.VertexAttributes.Length;
refreshGraphicsPipelineCreateInfo.vertexInputState.vertexBindings = vertexBindingsHandle.AddrOfPinnedObject();
refreshGraphicsPipelineCreateInfo.vertexInputState.vertexBindingCount = (uint) vertexInputState.VertexBindings.Length;
sdlGraphicsPipelineCreateInfo.RasterizerState = graphicsPipelineCreateInfo.RasterizerState.ToSDL();
sdlGraphicsPipelineCreateInfo.MultisampleState = graphicsPipelineCreateInfo.MultisampleState.ToSDL();
sdlGraphicsPipelineCreateInfo.DepthStencilState = graphicsPipelineCreateInfo.DepthStencilState.ToSDL();
refreshGraphicsPipelineCreateInfo.primitiveType = (Refresh.PrimitiveType) primitiveType;
sdlGraphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentCount = (uint) graphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions.Length;
sdlGraphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions = colorAttachmentDescriptions;
sdlGraphicsPipelineCreateInfo.AttachmentInfo.DepthStencilFormat = (SDL_Gpu.TextureFormat) graphicsPipelineCreateInfo.AttachmentInfo.DepthStencilFormat;
sdlGraphicsPipelineCreateInfo.AttachmentInfo.HasDepthStencilAttachment = Conversions.BoolToInt(graphicsPipelineCreateInfo.AttachmentInfo.HasDepthStencilAttachment);
refreshGraphicsPipelineCreateInfo.attachmentInfo.colorAttachmentCount = (uint) attachmentInfo.ColorAttachmentDescriptions.Length;
refreshGraphicsPipelineCreateInfo.attachmentInfo.colorAttachmentDescriptions = (IntPtr) colorAttachmentDescriptions;
refreshGraphicsPipelineCreateInfo.attachmentInfo.depthStencilFormat = (Refresh.TextureFormat) attachmentInfo.DepthStencilFormat;
refreshGraphicsPipelineCreateInfo.attachmentInfo.hasDepthStencilAttachment = Conversions.BoolToByte(attachmentInfo.HasDepthStencilAttachment);
sdlGraphicsPipelineCreateInfo.VertexResourceInfo = graphicsPipelineCreateInfo.VertexShaderResourceInfo.ToSDL();
sdlGraphicsPipelineCreateInfo.FragmentResourceInfo = graphicsPipelineCreateInfo.FragmentShaderResourceInfo.ToSDL();
Handle = Refresh.Refresh_CreateGraphicsPipeline(device.Handle, refreshGraphicsPipelineCreateInfo);
sdlGraphicsPipelineCreateInfo.BlendConstants[0] = graphicsPipelineCreateInfo.BlendConstants.R;
sdlGraphicsPipelineCreateInfo.BlendConstants[1] = graphicsPipelineCreateInfo.BlendConstants.G;
sdlGraphicsPipelineCreateInfo.BlendConstants[2] = graphicsPipelineCreateInfo.BlendConstants.B;
sdlGraphicsPipelineCreateInfo.BlendConstants[3] = graphicsPipelineCreateInfo.BlendConstants.A;
Handle = SDL_Gpu.SDL_GpuCreateGraphicsPipeline(device.Handle, sdlGraphicsPipelineCreateInfo);
if (Handle == IntPtr.Zero)
{
throw new Exception("Could not create graphics pipeline!");
}
vertexAttributesHandle.Free();
vertexBindingsHandle.Free();
NativeMemory.Free(vertexAttributes);
NativeMemory.Free(vertexBindings);
VertexShaderInfo = vertexShaderInfo;
FragmentShaderInfo = fragmentShaderInfo;
SampleCount = multisampleState.MultisampleCount;
VertexShaderResourceInfo = graphicsPipelineCreateInfo.VertexShaderResourceInfo;
FragmentShaderResourceInfo = graphicsPipelineCreateInfo.FragmentShaderResourceInfo;
SampleCount = graphicsPipelineCreateInfo.MultisampleState.MultisampleCount;
#if DEBUG
AttachmentInfo = attachmentInfo;
AttachmentInfo = graphicsPipelineCreateInfo.AttachmentInfo;
#endif
}
}

View File

@ -1,6 +1,6 @@
using System;
using System.IO;
using RefreshCS;
using SDL2_gpuCS;
namespace MoonWorks.Graphics
{
@ -29,7 +29,7 @@ namespace MoonWorks.Graphics
{
if (Device.DebugMode)
{
Refresh.Refresh_SetTextureName(
SDL_Gpu.SDL_GpuSetTextureName(
Device.Handle,
Handle,
value
@ -41,7 +41,7 @@ namespace MoonWorks.Graphics
}
// FIXME: this allocates a delegate instance
protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_QueueDestroyTexture;
protected override Action<IntPtr, IntPtr> ReleaseFunction => SDL_Gpu.SDL_GpuReleaseTexture;
/// <summary>
/// Creates a 2D texture.
@ -179,9 +179,9 @@ namespace MoonWorks.Graphics
in TextureCreateInfo textureCreateInfo
) : base(device)
{
Handle = Refresh.Refresh_CreateTexture(
Handle = SDL_Gpu.SDL_GpuCreateTexture(
device.Handle,
textureCreateInfo.ToRefreshTextureCreateInfo()
textureCreateInfo.ToSDL()
);
Format = textureCreateInfo.Format;

View File

@ -251,10 +251,13 @@ public enum BlendFactor
[Flags]
public enum ColorComponentFlags
{
None = 0x0,
R = 0x1,
G = 0x2,
B = 0x4,
A = 0x8
A = 0x8,
RGB = R | G | B,
RGBA = R | G| B | A
}
public enum Filter
@ -366,7 +369,7 @@ public struct Rect
}
// FIXME: can we do an unsafe cast somehow?
public SDL_Gpu.Rect ToRefresh()
public SDL_Gpu.Rect ToSDL()
{
return new SDL_Gpu.Rect
{
@ -448,6 +451,16 @@ public struct VertexBinding
Stride = (uint) Marshal.SizeOf<T>()
};
}
public SDL_Gpu.VertexBinding ToSDL()
{
return new SDL_Gpu.VertexBinding
{
Binding = Binding,
Stride = Stride,
InputRate = (SDL_Gpu.VertexInputRate) InputRate
};
}
}
[StructLayout(LayoutKind.Sequential)]
@ -457,6 +470,17 @@ public struct VertexAttribute
public uint Binding;
public VertexElementFormat Format;
public uint Offset;
public SDL_Gpu.VertexAttribute ToSDL()
{
return new SDL_Gpu.VertexAttribute
{
Location = Location,
Binding = Binding,
Format = (SDL_Gpu.VertexElementFormat) Format,
Offset = Offset
};
}
}
[StructLayout(LayoutKind.Sequential)]
@ -797,3 +821,39 @@ public readonly record struct BufferImageCopy(
};
}
}
public readonly record struct GraphicsPipelineResourceInfo(
uint SamplerCount,
uint StorageBufferCount,
uint StorageTextureCount,
uint UniformBufferCount
) {
public SDL_Gpu.GraphicsPipelineResourceInfo ToSDL()
{
return new SDL_Gpu.GraphicsPipelineResourceInfo
{
SamplerCount = SamplerCount,
StorageBufferCount = StorageBufferCount,
StorageTextureCount = StorageTextureCount,
UniformBufferCount = UniformBufferCount
};
}
}
/// <summary>
/// All of the information that is used to create a GraphicsPipeline.
/// </summary>
public struct GraphicsPipelineCreateInfo
{
public Shader VertexShader;
public Shader FragmentShader;
public VertexInputState VertexInputState;
public PrimitiveType PrimitiveType;
public RasterizerState RasterizerState;
public MultisampleState MultisampleState;
public DepthStencilState DepthStencilState;
public GraphicsPipelineAttachmentInfo AttachmentInfo;
public GraphicsPipelineResourceInfo VertexShaderResourceInfo;
public GraphicsPipelineResourceInfo FragmentShaderResourceInfo;
public BlendConstants BlendConstants;
}

View File

@ -1,4 +1,4 @@
using RefreshCS;
using SDL2_gpuCS;
namespace MoonWorks.Graphics
{
@ -106,18 +106,18 @@ namespace MoonWorks.Graphics
ColorWriteMask = ColorComponentFlags.None
};
public Refresh.ColorAttachmentBlendState ToRefresh()
public SDL_Gpu.ColorAttachmentBlendState ToSDL()
{
return new Refresh.ColorAttachmentBlendState
return new SDL_Gpu.ColorAttachmentBlendState
{
blendEnable = Conversions.BoolToByte(BlendEnable),
alphaBlendOp = (Refresh.BlendOp) AlphaBlendOp,
colorBlendOp = (Refresh.BlendOp) ColorBlendOp,
colorWriteMask = (Refresh.ColorComponentFlags) ColorWriteMask,
destinationAlphaBlendFactor = (Refresh.BlendFactor) DestinationAlphaBlendFactor,
destinationColorBlendFactor = (Refresh.BlendFactor) DestinationColorBlendFactor,
sourceAlphaBlendFactor = (Refresh.BlendFactor) SourceAlphaBlendFactor,
sourceColorBlendFactor = (Refresh.BlendFactor) SourceColorBlendFactor
BlendEnable = Conversions.BoolToInt(BlendEnable),
AlphaBlendOp = (SDL_Gpu.BlendOp) AlphaBlendOp,
ColorBlendOp = (SDL_Gpu.BlendOp) ColorBlendOp,
ColorWriteMask = (SDL_Gpu.ColorComponentFlags) ColorWriteMask,
DestinationAlphaBlendFactor = (SDL_Gpu.BlendFactor) DestinationAlphaBlendFactor,
DestinationColorBlendFactor = (SDL_Gpu.BlendFactor) DestinationColorBlendFactor,
SourceAlphaBlendFactor = (SDL_Gpu.BlendFactor) SourceAlphaBlendFactor,
SourceColorBlendFactor = (SDL_Gpu.BlendFactor) SourceColorBlendFactor
};
}
}

View File

@ -1,4 +1,6 @@
namespace MoonWorks.Graphics
using SDL2_gpuCS;
namespace MoonWorks.Graphics
{
/// <summary>
/// Determines how data is written to and read from the depth/stencil buffer.
@ -90,5 +92,24 @@
DepthBoundsTestEnable = false,
StencilTestEnable = false
};
public SDL_Gpu.DepthStencilState ToSDL()
{
return new SDL_Gpu.DepthStencilState
{
DepthTestEnable = Conversions.BoolToInt(DepthTestEnable),
BackStencilState = BackStencilState.ToSDL(),
FrontStencilState = FrontStencilState.ToSDL(),
CompareMask = CompareMask,
WriteMask = WriteMask,
Reference = Reference,
CompareOp = (SDL_Gpu.CompareOp) CompareOp,
DepthBoundsTestEnable = Conversions.BoolToInt(DepthBoundsTestEnable),
DepthWriteEnable = Conversions.BoolToInt(DepthWriteEnable),
MinDepthBounds = MinDepthBounds,
MaxDepthBounds = MaxDepthBounds,
StencilTestEnable = Conversions.BoolToInt(StencilTestEnable)
};
}
}
}

View File

@ -14,7 +14,7 @@ namespace MoonWorks.Graphics
) {
ColorAttachmentDescriptions = colorAttachmentDescriptions;
HasDepthStencilAttachment = false;
DepthStencilFormat = TextureFormat.D16;
DepthStencilFormat = TextureFormat.D16_UNORM;
}
public GraphicsPipelineAttachmentInfo(

View File

@ -1,18 +0,0 @@
namespace MoonWorks.Graphics
{
/// <summary>
/// All of the information that is used to create a GraphicsPipeline.
/// </summary>
public struct GraphicsPipelineCreateInfo
{
public DepthStencilState DepthStencilState;
public GraphicsShaderInfo VertexShaderInfo;
public GraphicsShaderInfo FragmentShaderInfo;
public MultisampleState MultisampleState;
public RasterizerState RasterizerState;
public PrimitiveType PrimitiveType;
public VertexInputState VertexInputState;
public GraphicsPipelineAttachmentInfo AttachmentInfo;
public BlendConstants BlendConstants;
}
}

View File

@ -1,44 +0,0 @@
using System.Runtime.InteropServices;
namespace MoonWorks.Graphics
{
/// <summary>
/// Information that the pipeline needs about a graphics shader.
/// </summary>
public struct GraphicsShaderInfo
{
public ShaderModule ShaderModule;
public string EntryPointName;
public uint UniformBufferSize;
public uint SamplerBindingCount;
public unsafe static GraphicsShaderInfo Create<T>(
ShaderModule shaderModule,
string entryPointName,
uint samplerBindingCount
) where T : unmanaged
{
return new GraphicsShaderInfo
{
ShaderModule = shaderModule,
EntryPointName = entryPointName,
UniformBufferSize = (uint) Marshal.SizeOf<T>(),
SamplerBindingCount = samplerBindingCount
};
}
public static GraphicsShaderInfo Create(
ShaderModule shaderModule,
string entryPointName,
uint samplerBindingCount
) {
return new GraphicsShaderInfo
{
ShaderModule = shaderModule,
EntryPointName = entryPointName,
UniformBufferSize = 0,
SamplerBindingCount = samplerBindingCount
};
}
}
}

View File

@ -1,4 +1,6 @@
namespace MoonWorks.Graphics
using SDL2_gpuCS;
namespace MoonWorks.Graphics
{
/// <summary>
/// Specifies how many samples should be used in rasterization.
@ -21,5 +23,14 @@
MultisampleCount = sampleCount;
SampleMask = sampleMask;
}
public SDL_Gpu.MultisampleState ToSDL()
{
return new SDL_Gpu.MultisampleState
{
MultisampleCount = (SDL_Gpu.SampleCount) MultisampleCount,
SampleMask = SampleMask
};
}
}
}

View File

@ -1,5 +1,7 @@
namespace MoonWorks.Graphics
{
using SDL2_gpuCS;
namespace MoonWorks.Graphics;
/// <summary>
/// Specifies how the rasterizer should be configured for a graphics pipeline.
/// </summary>
@ -103,5 +105,18 @@
FillMode = FillMode.Line,
DepthBiasEnable = false
};
public SDL_Gpu.RasterizerState ToSDL()
{
return new SDL_Gpu.RasterizerState
{
CullMode = (SDL_Gpu.CullMode) CullMode,
DepthBiasClamp = DepthBiasClamp,
DepthBiasConstantFactor = DepthBiasConstantFactor,
DepthBiasEnable = Conversions.BoolToInt(DepthBiasEnable),
DepthBiasSlopeFactor = DepthBiasSlopeFactor,
FillMode = (SDL_Gpu.FillMode) FillMode,
FrontFace = (SDL_Gpu.FrontFace) FrontFace
};
}
}

View File

@ -1,4 +1,4 @@
using RefreshCS;
using SDL2_gpuCS;
namespace MoonWorks.Graphics
{
@ -17,19 +17,19 @@ namespace MoonWorks.Graphics
public TextureFormat Format;
public TextureUsageFlags UsageFlags;
public Refresh.TextureCreateInfo ToRefreshTextureCreateInfo()
public SDL_Gpu.TextureCreateInfo ToSDL()
{
return new Refresh.TextureCreateInfo
return new SDL_Gpu.TextureCreateInfo
{
width = Width,
height = Height,
depth = Depth,
isCube = Conversions.BoolToByte(IsCube),
layerCount = LayerCount,
levelCount = LevelCount,
sampleCount = (Refresh.SampleCount) SampleCount,
format = (Refresh.TextureFormat) Format,
usageFlags = (Refresh.TextureUsageFlags) UsageFlags
Width = Width,
Height = Height,
Depth = Depth,
IsCube = Conversions.BoolToInt(IsCube),
LayerCount = LayerCount,
LevelCount = LevelCount,
SampleCount = (SDL_Gpu.SampleCount) SampleCount,
Format = (SDL_Gpu.TextureFormat) Format,
UsageFlags = (SDL_Gpu.TextureUsageFlags) UsageFlags
};
}
}

View File

@ -1,4 +1,4 @@
using RefreshCS;
using SDL2_gpuCS;
namespace MoonWorks.Graphics
{
@ -29,17 +29,17 @@ namespace MoonWorks.Graphics
Depth = texture.Depth;
}
public Refresh.TextureRegion ToRefreshTextureRegion()
public SDL_Gpu.TextureRegion ToSDL()
{
return new Refresh.TextureRegion
return new SDL_Gpu.TextureRegion
{
textureSlice = TextureSlice.ToRefreshTextureSlice(),
x = X,
y = Y,
z = Z,
w = Width,
h = Height,
d = Depth
TextureSlice = TextureSlice.ToSDL(),
X = X,
Y = Y,
Z = Z,
W = Width,
H = Height,
D = Depth
};
}
}