diff --git a/lib/SDL2_gpuCS b/lib/SDL2_gpuCS
index 60e2c21..70925aa 160000
--- a/lib/SDL2_gpuCS
+++ b/lib/SDL2_gpuCS
@@ -1 +1 @@
-Subproject commit 60e2c21a7b224dc6aa6a457dbb71d798a4e66241
+Subproject commit 70925aa394c0f24388f3cfb97f1c6ee1f91baf52
diff --git a/src/Graphics/Bindings/BufferBinding.cs b/src/Graphics/Bindings/BufferBinding.cs
deleted file mode 100644
index caadfb0..0000000
--- a/src/Graphics/Bindings/BufferBinding.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using SDL2_gpuCS;
-namespace MoonWorks.Graphics;
-
-///
-/// A buffer-offset pair to be used when binding buffers.
-///
-public readonly record struct BufferBinding(
- GpuBuffer Buffer,
- uint Offset
-) {
- public SDL_Gpu.BufferBinding ToSDL()
- {
- return new SDL_Gpu.BufferBinding
- {
- Buffer = Buffer.Handle,
- Offset = Offset
- };
- }
-}
diff --git a/src/Graphics/Bindings/ComputeBufferBinding.cs b/src/Graphics/Bindings/ComputeBufferBinding.cs
deleted file mode 100644
index 012dd44..0000000
--- a/src/Graphics/Bindings/ComputeBufferBinding.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using SDL2_gpuCS;
-
-namespace MoonWorks.Graphics;
-
-///
-/// Binding specification to be used when binding buffers for compute shaders.
-///
-/// The GpuBuffer to bind.
-///
-/// Specifies data dependency behavior when this buffer is written to in the shader.
-///
-/// Cycle:
-/// If this buffer has been used in commands that have not finished,
-/// the implementation may choose to prevent a dependency on those commands
-/// at the cost of increased memory usage.
-/// You may NOT assume that any of the previous data is retained.
-/// This may prevent stalls when frequently updating a resource.
-///
-/// SafeOverwrite:
-/// Overwrites the data safely using a GPU memory barrier.
-///
-public readonly record struct ComputeBufferBinding(
- GpuBuffer GpuBuffer,
- WriteOptions WriteOption
-) {
- public SDL_Gpu.BufferBinding ToRefresh()
- {
- return new Refresh.ComputeBufferBinding
- {
- gpuBuffer = GpuBuffer.Handle,
- writeOption = (Refresh.WriteOptions) WriteOption
- };
- }
-}
diff --git a/src/Graphics/Bindings/ComputeTextureBinding.cs b/src/Graphics/Bindings/ComputeTextureBinding.cs
deleted file mode 100644
index 4baa158..0000000
--- a/src/Graphics/Bindings/ComputeTextureBinding.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using RefreshCS;
-
-namespace MoonWorks.Graphics
-{
- ///
- /// Binding specification used for binding texture slices for compute shaders.
- ///
- /// The TextureSlice to bind.
- ///
- /// Specifies data dependency behavior when this texture is written to in the shader.
- ///
- /// Cycle:
- /// If this buffer has been used in commands that have not finished,
- /// the implementation may choose to prevent a dependency on those commands
- /// at the cost of increased memory usage.
- /// You may NOT assume that any of the previous data is retained.
- /// This may prevent stalls when frequently updating a resource.
- ///
- /// SafeOverwrite:
- /// Overwrites the data safely using a GPU memory barrier.
- ///
- public readonly record struct ComputeTextureBinding(
- TextureSlice TextureSlice,
- WriteOptions WriteOption
- ) {
- public Refresh.ComputeTextureBinding ToRefresh()
- {
- return new Refresh.ComputeTextureBinding
- {
- textureSlice = TextureSlice.ToRefreshTextureSlice(),
- writeOption = (Refresh.WriteOptions) WriteOption
- };
- }
- }
-}
diff --git a/src/Graphics/Bindings/TextureSamplerBinding.cs b/src/Graphics/Bindings/TextureSamplerBinding.cs
deleted file mode 100644
index 1a122dc..0000000
--- a/src/Graphics/Bindings/TextureSamplerBinding.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using SDL2_gpuCS;
-
-namespace MoonWorks.Graphics
-{
- ///
- /// A texture-sampler pair to be used when binding samplers.
- ///
- public readonly record struct TextureSamplerBinding(
- Texture Texture,
- Sampler Sampler
- ) {
- public SDL_Gpu.TextureSamplerBinding ToSDL()
- {
- return new SDL_Gpu.TextureSamplerBinding
- {
- Texture = Texture.Handle,
- Sampler = Sampler.Handle
- };
- }
- }
-}
diff --git a/src/Graphics/CommandBuffer.cs b/src/Graphics/CommandBuffer.cs
index 74b8719..229abf2 100644
--- a/src/Graphics/CommandBuffer.cs
+++ b/src/Graphics/CommandBuffer.cs
@@ -641,401 +641,106 @@ public class CommandBuffer
);
}
- public void BeginComputePass()
- {
+ public unsafe ComputePass BeginComputePass(
+ in StorageTextureReadWriteBinding readWriteTextureBinding
+ ) {
#if DEBUG
AssertNotSubmitted();
AssertNotInPass("Cannot begin compute pass while in another pass!");
computePassActive = true;
#endif
- Refresh.Refresh_BeginComputePass(
- Device.Handle,
- Handle
+ var sdlTextureBinding = readWriteTextureBinding.ToSDL();
+
+ var computePassHandle = SDL_Gpu.SDL_GpuBeginComputePass(
+ Handle,
+ &sdlTextureBinding,
+ 1,
+ (SDL_Gpu.StorageBufferReadWriteBinding*) nint.Size,
+ 0
);
+
+ var computePass = Device.ComputePassPool.Obtain();
+ computePass.SetHandle(computePassHandle);
+
+#if DEBUG
+ computePass.active = true;
+#endif
+
+ return computePass;
}
- ///
- /// Binds a compute pipeline so that compute work may be dispatched.
- ///
- /// The compute pipeline to bind.
- public void BindComputePipeline(
- ComputePipeline computePipeline
+ public unsafe ComputePass BeginComputePass(
+ in StorageBufferReadWriteBinding readWriteBufferBinding
) {
#if DEBUG
AssertNotSubmitted();
- AssertInComputePass("Cannot bind compute pipeline outside of compute pass!");
+ AssertNotInPass("Cannot begin compute pass while in another pass!");
+ computePassActive = true;
#endif
- Refresh.Refresh_BindComputePipeline(
- Device.Handle,
+ var sdlBufferBinding = readWriteBufferBinding.ToSDL();
+
+ var computePassHandle = SDL_Gpu.SDL_GpuBeginComputePass(
Handle,
- computePipeline.Handle
+ (SDL_Gpu.StorageTextureReadWriteBinding*) nint.Zero,
+ 0,
+ &sdlBufferBinding,
+ 1
);
+ var computePass = Device.ComputePassPool.Obtain();
+ computePass.SetHandle(computePassHandle);
+
#if DEBUG
- currentComputePipeline = computePipeline;
+ computePass.active = true;
#endif
+
+ return computePass;
}
- ///
- /// Binds a buffer to be used in the compute shader.
- ///
- public unsafe void BindComputeBuffers(
- ComputeBufferBinding binding
+ public unsafe ComputePass BeginComputePass(
+ in StorageTextureReadWriteBinding readWriteTextureBinding,
+ in StorageBufferReadWriteBinding readWriteBufferBinding
) {
#if DEBUG
AssertNotSubmitted();
- AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
- AssertComputePipelineBound();
- AssertComputeBufferCount(1);
+ AssertNotInPass("Cannot begin compute pass while in another pass!");
+ computePassActive = true;
#endif
- var bindingArray = stackalloc Refresh.ComputeBufferBinding[1];
- bindingArray[0] = binding.ToRefresh();
+ var sdlTextureBinding = readWriteTextureBinding.ToSDL();
+ var sdlBufferBinding = readWriteBufferBinding.ToSDL();
- Refresh.Refresh_BindComputeBuffers(
- Device.Handle,
+ var computePassHandle = SDL_Gpu.SDL_GpuBeginComputePass(
Handle,
- bindingArray
+ &sdlTextureBinding,
+ 1,
+ &sdlBufferBinding,
+ 1
);
- }
- ///
- /// Binds buffers to be used in the compute shader.
- ///
- public unsafe void BindComputeBuffers(
- ComputeBufferBinding bindingOne,
- ComputeBufferBinding bindingTwo
- ) {
+ var computePass = Device.ComputePassPool.Obtain();
+ computePass.SetHandle(computePassHandle);
+
#if DEBUG
- AssertNotSubmitted();
- AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
- AssertComputePipelineBound();
- AssertComputeBufferCount(2);
+ computePass.active = true;
#endif
- var bindingArray = stackalloc Refresh.ComputeBufferBinding[2];
- bindingArray[0] = bindingOne.ToRefresh();
- bindingArray[1] = bindingTwo.ToRefresh();
-
- Refresh.Refresh_BindComputeBuffers(
- Device.Handle,
- Handle,
- bindingArray
- );
+ return computePass;
}
- ///
- /// Binds buffers to be used in the compute shader.
- ///
- public unsafe void BindComputeBuffers(
- ComputeBufferBinding bindingOne,
- ComputeBufferBinding bindingTwo,
- ComputeBufferBinding bindingThree
- ) {
-#if DEBUG
- AssertNotSubmitted();
- AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
- AssertComputePipelineBound();
- AssertComputeBufferCount(3);
-#endif
-
- var bindingArray = stackalloc Refresh.ComputeBufferBinding[3];
- bindingArray[0] = bindingOne.ToRefresh();
- bindingArray[1] = bindingTwo.ToRefresh();
- bindingArray[2] = bindingThree.ToRefresh();
-
- Refresh.Refresh_BindComputeBuffers(
- Device.Handle,
- Handle,
- bindingArray
- );
- }
-
- ///
- /// Binds buffers to be used in the compute shader.
- ///
- public unsafe void BindComputeBuffers(
- ComputeBufferBinding bindingOne,
- ComputeBufferBinding bindingTwo,
- ComputeBufferBinding bindingThree,
- ComputeBufferBinding bindingFour
- ) {
-#if DEBUG
- AssertNotSubmitted();
- AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
- AssertComputePipelineBound();
- AssertComputeBufferCount(4);
-#endif
-
- var bindingArray = stackalloc Refresh.ComputeBufferBinding[4];
- bindingArray[0] = bindingOne.ToRefresh();
- bindingArray[1] = bindingTwo.ToRefresh();
- bindingArray[2] = bindingThree.ToRefresh();
- bindingArray[3] = bindingFour.ToRefresh();
-
- Refresh.Refresh_BindComputeBuffers(
- Device.Handle,
- Handle,
- bindingArray
- );
- }
-
- ///
- /// Binds buffers to be used in the compute shader.
- ///
- /// A Span of buffers to bind.
- public unsafe void BindComputeBuffers(
- in Span bindings
- ) {
-#if DEBUG
- AssertNotSubmitted();
- AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
- AssertComputePipelineBound();
- AssertComputeBufferCount(bindings.Length);
-#endif
-
- Refresh.ComputeBufferBinding* bindingArray = (Refresh.ComputeBufferBinding*) NativeMemory.Alloc(
- (nuint) (Marshal.SizeOf() * bindings.Length)
- );
-
- for (var i = 0; i < bindings.Length; i += 1)
- {
- bindingArray[i] = bindings[i].ToRefresh();
- }
-
- Refresh.Refresh_BindComputeBuffers(
- Device.Handle,
- Handle,
- bindingArray
- );
-
- NativeMemory.Free(bindingArray);
- }
-
- ///
- /// Binds a texture slice to be used in the compute shader.
- ///
- public unsafe void BindComputeTextures(
- ComputeTextureBinding binding
- ) {
-#if DEBUG
- AssertNotSubmitted();
- AssertInComputePass("Cannot bind compute textures outside of compute pass!");
- AssertComputePipelineBound();
- AssertComputeTextureCount(1);
-#endif
-
- var bindingArray = stackalloc Refresh.ComputeTextureBinding[1];
- bindingArray[0] = binding.ToRefresh();
-
- Refresh.Refresh_BindComputeTextures(
- Device.Handle,
- Handle,
- bindingArray
- );
- }
-
- ///
- /// Binds textures to be used in the compute shader.
- ///
- public unsafe void BindComputeTextures(
- ComputeTextureBinding bindingOne,
- ComputeTextureBinding bindingTwo
- ) {
-#if DEBUG
- AssertNotSubmitted();
- AssertInComputePass("Cannot bind compute textures outside of compute pass!");
- AssertComputePipelineBound();
- AssertComputeTextureCount(2);
-#endif
-
- var bindingArray = stackalloc Refresh.ComputeTextureBinding[2];
- bindingArray[0] = bindingOne.ToRefresh();
- bindingArray[1] = bindingTwo.ToRefresh();
-
- Refresh.Refresh_BindComputeTextures(
- Device.Handle,
- Handle,
- bindingArray
- );
- }
-
- ///
- /// Binds textures to be used in the compute shader.
- ///
- public unsafe void BindComputeTextures(
- ComputeTextureBinding bindingOne,
- ComputeTextureBinding bindingTwo,
- ComputeTextureBinding bindingThree
- ) {
-#if DEBUG
- AssertNotSubmitted();
- AssertInComputePass("Cannot bind compute textures outside of compute pass!");
- AssertComputePipelineBound();
- AssertComputeTextureCount(3);
-#endif
-
- var bindingArray = stackalloc Refresh.ComputeTextureBinding[3];
- bindingArray[0] = bindingOne.ToRefresh();
- bindingArray[1] = bindingTwo.ToRefresh();
- bindingArray[2] = bindingThree.ToRefresh();
-
- Refresh.Refresh_BindComputeTextures(
- Device.Handle,
- Handle,
- bindingArray
- );
- }
-
- ///
- /// Binds textures to be used in the compute shader.
- ///
- public unsafe void BindComputeTextures(
- ComputeTextureBinding bindingOne,
- ComputeTextureBinding bindingTwo,
- ComputeTextureBinding bindingThree,
- ComputeTextureBinding bindingFour
- ) {
-#if DEBUG
- AssertNotSubmitted();
- AssertInComputePass("Cannot bind compute textures outside of compute pass!");
- AssertComputePipelineBound();
- AssertComputeTextureCount(4);
-#endif
-
- var textureSlicePtrs = stackalloc Refresh.ComputeTextureBinding[4];
- textureSlicePtrs[0] = bindingOne.ToRefresh();
- textureSlicePtrs[1] = bindingTwo.ToRefresh();
- textureSlicePtrs[2] = bindingThree.ToRefresh();
- textureSlicePtrs[3] = bindingFour.ToRefresh();
-
- Refresh.Refresh_BindComputeTextures(
- Device.Handle,
- Handle,
- textureSlicePtrs
- );
- }
-
- ///
- /// Binds textures to be used in the compute shader.
- ///
- public unsafe void BindComputeTextures(
- in Span bindings
- ) {
-#if DEBUG
- AssertNotSubmitted();
- AssertInComputePass("Cannot bind compute textures outside of compute pass!");
- AssertComputePipelineBound();
- AssertComputeTextureCount(bindings.Length);
-#endif
-
- Refresh.ComputeTextureBinding* bindingArray = (Refresh.ComputeTextureBinding*) NativeMemory.Alloc(
- (nuint) (Marshal.SizeOf() * bindings.Length)
- );
-
- for (var i = 0; i < bindings.Length; i += 1)
- {
- bindingArray[i] = bindings[i].ToRefresh();
- }
-
- Refresh.Refresh_BindComputeTextures(
- Device.Handle,
- Handle,
- bindingArray
- );
-
- NativeMemory.Free(bindingArray);
- }
-
- ///
- /// Pushes compute shader uniforms to the device.
- ///
- /// A starting offset to be used with dispatch calls.
- public unsafe void PushComputeShaderUniforms(
- void* uniformsPtr,
- uint size
- ) {
-#if DEBUG
- AssertNotSubmitted();
- AssertComputePipelineBound();
-
- if (currentComputePipeline.ComputeShaderInfo.UniformBufferSize == 0)
- {
- throw new System.InvalidOperationException("The current compute shader does not take a uniform buffer!");
- }
-
- if (currentComputePipeline.ComputeShaderInfo.UniformBufferSize != size)
- {
- throw new InvalidOperationException("Compute uniform data size mismatch!");
- }
-#endif
-
- Refresh.Refresh_PushComputeShaderUniforms(
- Device.Handle,
- Handle,
- (IntPtr) uniformsPtr,
- size
- );
- }
-
- ///
- /// Pushes compute shader uniforms to the device.
- ///
- /// A starting offset to be used with dispatch calls.
- public unsafe void PushComputeShaderUniforms(
- in T uniforms
- ) where T : unmanaged
- {
- fixed (T* uniformsPtr = &uniforms)
- {
- PushComputeShaderUniforms(uniformsPtr, (uint) Marshal.SizeOf());
- }
- }
-
- ///
- /// Dispatches compute work.
- ///
- ///
- ///
- ///
- ///
- public void DispatchCompute(
- uint groupCountX,
- uint groupCountY,
- uint groupCountZ
- ) {
-#if DEBUG
- AssertNotSubmitted();
- AssertInComputePass("Cannot dispatch compute outside of compute pass!");
- AssertComputePipelineBound();
-
- if (groupCountX < 1 || groupCountY < 1 || groupCountZ < 1)
- {
- throw new ArgumentException("All dimensions for the compute work group must be >= 1!");
- }
-#endif
-
- Refresh.Refresh_DispatchCompute(
- Device.Handle,
- Handle,
- groupCountX,
- groupCountY,
- groupCountZ
- );
- }
-
- public void EndComputePass()
+ public void EndComputePass(ComputePass computePass)
{
#if DEBUG
+ AssertNotSubmitted();
AssertInComputePass("Cannot end compute pass while not in a compute pass!");
computePassActive = false;
+ computePass.active = false;
#endif
- Refresh.Refresh_EndComputePass(
- Device.Handle,
- Handle
+ SDL_Gpu.SDL_GpuEndComputePass(
+ computePass.Handle
);
}
diff --git a/src/Graphics/ComputePass.cs b/src/Graphics/ComputePass.cs
new file mode 100644
index 0000000..ad8fd97
--- /dev/null
+++ b/src/Graphics/ComputePass.cs
@@ -0,0 +1,213 @@
+using System.Runtime.InteropServices;
+using SDL2;
+using SDL2_gpuCS;
+
+namespace MoonWorks.Graphics;
+
+public class ComputePass
+{
+ public nint Handle { get; private set; }
+
+ internal void SetHandle(nint handle)
+ {
+ Handle = handle;
+ }
+
+#if DEBUG
+ internal bool active;
+
+ ComputePipeline currentComputePipeline;
+#endif
+
+ ///
+ /// Binds a compute pipeline so that compute work may be dispatched.
+ ///
+ /// The compute pipeline to bind.
+ public void BindComputePipeline(
+ ComputePipeline computePipeline
+ ) {
+#if DEBUG
+ AssertComputePassActive();
+
+ // TODO: validate formats?
+#endif
+
+ SDL_Gpu.SDL_GpuBindComputePipeline(
+ Handle,
+ computePipeline.Handle
+ );
+
+#if DEBUG
+ currentComputePipeline = computePipeline;
+#endif
+ }
+
+ ///
+ /// Binds a texture to be used in the compute shader.
+ /// This texture must have been created with the ComputeShaderRead usage flag.
+ ///
+ public unsafe void BindStorageTexture(
+ in TextureSlice textureSlice,
+ uint slot = 0
+ ) {
+#if DEBUG
+ AssertComputePassActive();
+ AssertComputePipelineBound();
+ AssertTextureNonNull(textureSlice.Texture);
+ AssertTextureHasComputeStorageReadFlag(textureSlice.Texture);
+#endif
+
+ var sdlTextureSlice = textureSlice.ToSDL();
+
+ SDL_Gpu.SDL_GpuBindComputeStorageTextures(
+ Handle,
+ slot,
+ &sdlTextureSlice,
+ 1
+ );
+ }
+
+ ///
+ /// Binds a buffer to be used in the compute shader.
+ /// This buffer must have been created with the ComputeShaderRead usage flag.
+ ///
+ public unsafe void BindStorageBuffer(
+ GpuBuffer buffer,
+ uint slot = 0
+ ) {
+#if DEBUG
+ AssertComputePassActive();
+ AssertComputePipelineBound();
+ AssertBufferNonNull(buffer);
+ AssertBufferHasComputeStorageReadFlag(buffer);
+#endif
+
+ var bufferHandle = buffer.Handle;
+
+ SDL_Gpu.SDL_GpuBindComputeStorageBuffers(
+ Handle,
+ slot,
+ &bufferHandle,
+ 1
+ );
+ }
+
+ ///
+ /// Pushes compute shader uniform data.
+ /// Subsequent draw calls will use this uniform data.
+ ///
+ public unsafe void PushUniformData(
+ void* uniformsPtr,
+ uint size,
+ uint slot = 0
+ ) {
+#if DEBUG
+ AssertComputePassActive();
+ AssertComputePipelineBound();
+
+ if (slot >= currentComputePipeline.ResourceInfo.UniformBufferCount)
+ {
+ throw new System.ArgumentException($"Slot {slot} given, but {currentComputePipeline.ResourceInfo.UniformBufferCount} uniform buffers are used on the shader!");
+ }
+#endif
+
+ SDL_Gpu.SDL_GpuPushComputeUniformData(
+ Handle,
+ slot,
+ (nint) uniformsPtr,
+ size
+ );
+ }
+
+ ///
+ /// Pushes compute shader uniform data.
+ /// Subsequent draw calls will use this uniform data.
+ ///
+ public unsafe void PushUniformData(
+ in T uniforms,
+ uint slot = 0
+ ) where T : unmanaged
+ {
+ fixed (T* uniformsPtr = &uniforms)
+ {
+ PushUniformData(uniformsPtr, (uint) Marshal.SizeOf(), slot);
+ }
+ }
+
+
+ ///
+ /// Dispatches compute work.
+ ///
+ public void Dispatch(
+ uint groupCountX,
+ uint groupCountY,
+ uint groupCountZ
+ ) {
+#if DEBUG
+ AssertComputePassActive();
+ AssertComputePipelineBound();
+
+ if (groupCountX < 1 || groupCountY < 1 || groupCountZ < 1)
+ {
+ throw new System.ArgumentException("All dimensions for the compute work groups must be >= 1!");
+ }
+#endif
+
+ SDL_Gpu.SDL_GpuDispatchCompute(
+ Handle,
+ groupCountX,
+ groupCountY,
+ groupCountZ
+ );
+ }
+
+#if DEBUG
+ private void AssertComputePassActive(string message = "Render pass is not active!")
+ {
+ if (!active)
+ {
+ throw new System.InvalidOperationException(message);
+ }
+ }
+
+ private void AssertComputePipelineBound(string message = "No compute pipeline is bound!")
+ {
+ if (currentComputePipeline == null)
+ {
+ throw new System.InvalidOperationException(message);
+ }
+ }
+
+ private void AssertTextureNonNull(in TextureSlice textureSlice)
+ {
+ if (textureSlice.Texture == null || textureSlice.Texture.Handle == nint.Zero)
+ {
+ throw new System.NullReferenceException("Texture must not be null!");
+ }
+ }
+
+ private void AssertTextureHasComputeStorageReadFlag(Texture texture)
+ {
+ if ((texture.UsageFlags & TextureUsageFlags.ComputeStorageRead) == 0)
+ {
+ throw new System.ArgumentException("The bound Texture's UsageFlags must include TextureUsageFlags.ComputeStorageRead!");
+ }
+ }
+
+ private void AssertBufferNonNull(GpuBuffer buffer)
+ {
+ if (buffer == null || buffer.Handle == nint.Zero)
+ {
+ throw new System.NullReferenceException("Buffer must not be null!");
+ }
+ }
+
+ private void AssertBufferHasComputeStorageReadFlag(GpuBuffer buffer)
+ {
+ if ((buffer.UsageFlags & BufferUsageFlags.ComputeStorageRead) == 0)
+ {
+ throw new System.ArgumentException("The bound Buffer's UsageFlags must include BufferUsageFlag.ComputeStorageRead!");
+ }
+ }
+#endif
+}
diff --git a/src/Graphics/ComputePassPool.cs b/src/Graphics/ComputePassPool.cs
new file mode 100644
index 0000000..da3a366
--- /dev/null
+++ b/src/Graphics/ComputePassPool.cs
@@ -0,0 +1,25 @@
+using System.Collections.Concurrent;
+
+namespace MoonWorks.Graphics;
+
+internal class ComputePassPool
+{
+ private ConcurrentQueue ComputePasses = new ConcurrentQueue();
+
+ public ComputePass Obtain()
+ {
+ if (ComputePasses.TryDequeue(out var computePass))
+ {
+ return computePass;
+ }
+ else
+ {
+ return new ComputePass();
+ }
+ }
+
+ public void Return(ComputePass computePass)
+ {
+ ComputePasses.Enqueue(computePass);
+ }
+}
diff --git a/src/Graphics/GraphicsDevice.cs b/src/Graphics/GraphicsDevice.cs
index 3a863eb..92abfd7 100644
--- a/src/Graphics/GraphicsDevice.cs
+++ b/src/Graphics/GraphicsDevice.cs
@@ -38,8 +38,9 @@ namespace MoonWorks.Graphics
private readonly HashSet resources = new HashSet();
private CommandBufferPool CommandBufferPool;
- internal RenderPassPool RenderPassPool;
private FencePool FencePool;
+ internal RenderPassPool RenderPassPool;
+ internal ComputePassPool ComputePassPool;
internal unsafe GraphicsDevice(
BackendFlags preferredBackends,
diff --git a/src/Graphics/RenderPass.cs b/src/Graphics/RenderPass.cs
index faa8cb5..e9aa9ca 100644
--- a/src/Graphics/RenderPass.cs
+++ b/src/Graphics/RenderPass.cs
@@ -9,7 +9,7 @@ namespace MoonWorks.Graphics;
///
public class RenderPass
{
- public nint Handle { get; internal set; }
+ public nint Handle { get; private set; }
#if DEBUG
internal bool active;
@@ -296,12 +296,13 @@ public class RenderPass
}
public unsafe void PushVertexUniformData(
- in T uniforms
+ in T uniforms,
+ uint slot = 0
) where T : unmanaged
{
fixed (T* uniformsPtr = &uniforms)
{
- PushVertexUniformData(uniformsPtr, (uint) Marshal.SizeOf());
+ PushVertexUniformData(uniformsPtr, (uint) Marshal.SizeOf(), slot);
}
}
@@ -328,12 +329,13 @@ public class RenderPass
}
public unsafe void PushFragmentUniformData(
- in T uniforms
+ in T uniforms,
+ uint slot = 0
) where T : unmanaged
{
fixed (T* uniformsPtr = &uniforms)
{
- PushFragmentUniformData(uniformsPtr, (uint) Marshal.SizeOf());
+ PushFragmentUniformData(uniformsPtr, (uint) Marshal.SizeOf(), slot);
}
}
diff --git a/src/Graphics/RenderPassPool.cs b/src/Graphics/RenderPassPool.cs
index d0bf0f3..b851069 100644
--- a/src/Graphics/RenderPassPool.cs
+++ b/src/Graphics/RenderPassPool.cs
@@ -1,26 +1,25 @@
using System.Collections.Concurrent;
-namespace MoonWorks.Graphics
+namespace MoonWorks.Graphics;
+
+internal class RenderPassPool
{
- internal class RenderPassPool
+ private ConcurrentQueue RenderPasses = new ConcurrentQueue();
+
+ public RenderPass Obtain()
{
- private ConcurrentQueue RenderPasses = new ConcurrentQueue();
-
- public RenderPass Obtain()
+ if (RenderPasses.TryDequeue(out var renderPass))
{
- if (RenderPasses.TryDequeue(out var renderPass))
- {
- return renderPass;
- }
- else
- {
- return new RenderPass();
- }
+ return renderPass;
}
-
- public void Return(RenderPass renderPass)
+ else
{
- RenderPasses.Enqueue(renderPass);
+ return new RenderPass();
}
}
+
+ public void Return(RenderPass renderPass)
+ {
+ RenderPasses.Enqueue(renderPass);
+ }
}
diff --git a/src/Graphics/Resources/ComputePipeline.cs b/src/Graphics/Resources/ComputePipeline.cs
index 89da094..5020565 100644
--- a/src/Graphics/Resources/ComputePipeline.cs
+++ b/src/Graphics/Resources/ComputePipeline.cs
@@ -1,4 +1,4 @@
-using RefreshCS;
+using SDL2_gpuCS;
using System;
namespace MoonWorks.Graphics
@@ -8,34 +8,33 @@ namespace MoonWorks.Graphics
///
public class ComputePipeline : SDL_GpuResource
{
- protected override Action ReleaseFunction => Refresh.Refresh_QueueDestroyComputePipeline;
+ protected override Action ReleaseFunction => SDL_Gpu.SDL_GpuReleaseComputePipeline;
- public ComputeShaderInfo ComputeShaderInfo { get; }
+ public ComputePipelineResourceInfo ResourceInfo { get; }
public unsafe ComputePipeline(
GraphicsDevice device,
- ComputeShaderInfo computeShaderInfo
+ Shader computeShader,
+ ComputePipelineResourceInfo resourceInfo
) : base(device)
{
- var refreshComputeShaderInfo = new Refresh.ComputeShaderInfo
+ var sdlComputePipelineCreateInfo = new SDL_Gpu.ComputePipelineCreateInfo
{
- entryPointName = computeShaderInfo.EntryPointName,
- shaderModule = computeShaderInfo.ShaderModule.Handle,
- uniformBufferSize = computeShaderInfo.UniformBufferSize,
- bufferBindingCount = computeShaderInfo.BufferBindingCount,
- imageBindingCount = computeShaderInfo.ImageBindingCount
+ ComputeShader = computeShader.Handle,
+ PipelineResourceInfo = resourceInfo.ToSDL()
};
- Handle = Refresh.Refresh_CreateComputePipeline(
+ Handle = SDL_Gpu.SDL_GpuCreateComputePipeline(
device.Handle,
- refreshComputeShaderInfo
+ sdlComputePipelineCreateInfo
);
+
if (Handle == IntPtr.Zero)
{
throw new Exception("Could not create compute pipeline!");
}
- ComputeShaderInfo = computeShaderInfo;
+ ResourceInfo = resourceInfo;
}
}
}
diff --git a/src/Graphics/Resources/Texture.cs b/src/Graphics/Resources/Texture.cs
index f601e73..81f71e0 100644
--- a/src/Graphics/Resources/Texture.cs
+++ b/src/Graphics/Resources/Texture.cs
@@ -230,10 +230,8 @@ namespace MoonWorks.Graphics
case TextureFormat.R8G8_SNORM:
case TextureFormat.R8G8_UINT:
case TextureFormat.R16_UINT:
- case TextureFormat.D16:
+ case TextureFormat.D16_UNORM:
return 2;
- case TextureFormat.D16S8:
- return 3;
case TextureFormat.R8G8B8A8:
case TextureFormat.B8G8R8A8:
case TextureFormat.R32_SFLOAT:
@@ -243,9 +241,10 @@ namespace MoonWorks.Graphics
case TextureFormat.A2R10G10B10:
case TextureFormat.R8G8B8A8_UINT:
case TextureFormat.R16G16_UINT:
- case TextureFormat.D32:
+ case TextureFormat.D24_UNORM_S8_UINT:
+ case TextureFormat.D32_SFLOAT:
return 4;
- case TextureFormat.D32S8:
+ case TextureFormat.D32_SFLOAT_S8_UINT:
return 5;
case TextureFormat.R16G16B16A16_SFLOAT:
case TextureFormat.R16G16B16A16:
@@ -311,10 +310,11 @@ namespace MoonWorks.Graphics
case TextureFormat.R16_UINT:
case TextureFormat.R16G16_UINT:
case TextureFormat.R16G16B16A16_UINT:
- case TextureFormat.D16:
- case TextureFormat.D32:
- case TextureFormat.D16S8:
- case TextureFormat.D32S8:
+ case TextureFormat.D16_UNORM:
+ case TextureFormat.D24_UNORM:
+ case TextureFormat.D24_UNORM_S8_UINT:
+ case TextureFormat.D32_SFLOAT:
+ case TextureFormat.D32_SFLOAT_S8_UINT:
return 1;
default:
Logger.LogError("Texture format not recognized!");
diff --git a/src/Graphics/SDL_GpuTypes.cs b/src/Graphics/SDL_GpuTypes.cs
index 34eac9d..d5ac12d 100644
--- a/src/Graphics/SDL_GpuTypes.cs
+++ b/src/Graphics/SDL_GpuTypes.cs
@@ -840,6 +840,88 @@ public readonly record struct GraphicsPipelineResourceInfo(
}
}
+public readonly record struct ComputePipelineResourceInfo(
+ uint ReadOnlyStorageTextureCount,
+ uint ReadOnlyStorageBufferCount,
+ uint ReadWriteStorageTextureCount,
+ uint ReadWriteStorageBufferCount,
+ uint UniformBufferCount
+) {
+ public SDL_Gpu.ComputePipelineResourceInfo ToSDL()
+ {
+ return new SDL_Gpu.ComputePipelineResourceInfo
+ {
+ ReadOnlyStorageTextureCount = ReadOnlyStorageTextureCount,
+ ReadOnlyStorageBufferCount = ReadOnlyStorageBufferCount,
+ ReadWriteStorageTextureCount = ReadWriteStorageTextureCount,
+ ReadWriteStorageBufferCount = ReadWriteStorageBufferCount,
+ UniformBufferCount = UniformBufferCount
+ };
+ }
+}
+
+///
+/// A buffer-offset pair to be used when binding buffers.
+///
+public readonly record struct BufferBinding(
+ GpuBuffer Buffer,
+ uint Offset
+) {
+ public SDL_Gpu.BufferBinding ToSDL()
+ {
+ return new SDL_Gpu.BufferBinding
+ {
+ Buffer = Buffer.Handle,
+ Offset = Offset
+ };
+ }
+}
+
+///
+/// A texture-sampler pair to be used when binding samplers.
+///
+public readonly record struct TextureSamplerBinding(
+ Texture Texture,
+ Sampler Sampler
+) {
+ public SDL_Gpu.TextureSamplerBinding ToSDL()
+ {
+ return new SDL_Gpu.TextureSamplerBinding
+ {
+ Texture = Texture.Handle,
+ Sampler = Sampler.Handle
+ };
+ }
+}
+
+public readonly record struct StorageBufferReadWriteBinding(
+ GpuBuffer Buffer,
+ bool cycle
+) {
+ public SDL_Gpu.StorageBufferReadWriteBinding ToSDL()
+ {
+ return new SDL_Gpu.StorageBufferReadWriteBinding
+ {
+ Buffer = Buffer.Handle,
+ Cycle = Conversions.BoolToInt(cycle)
+ };
+ }
+}
+
+public readonly record struct StorageTextureReadWriteBinding(
+ in TextureSlice TextureSlice,
+ bool cycle
+) {
+ public SDL_Gpu.StorageTextureReadWriteBinding ToSDL()
+ {
+ return new SDL_Gpu.StorageTextureReadWriteBinding
+ {
+ TextureSlice = TextureSlice.ToSDL(),
+ Cycle = Conversions.BoolToInt(cycle)
+ };
+ }
+}
+
///
/// All of the information that is used to create a GraphicsPipeline.
///
diff --git a/src/Graphics/State/ComputeShaderInfo.cs b/src/Graphics/State/ComputeShaderInfo.cs
deleted file mode 100644
index 72fbbb7..0000000
--- a/src/Graphics/State/ComputeShaderInfo.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace MoonWorks.Graphics
-{
- ///
- /// Information that the compute pipeline needs about a compute shader.
- ///
- public struct ComputeShaderInfo
- {
- public ShaderModule ShaderModule;
- public string EntryPointName;
- public uint UniformBufferSize;
- public uint BufferBindingCount;
- public uint ImageBindingCount;
-
- public unsafe static ComputeShaderInfo Create(
- ShaderModule shaderModule,
- string entryPointName,
- uint bufferBindingCount,
- uint imageBindingCount
- ) where T : unmanaged
- {
- return new ComputeShaderInfo
- {
- ShaderModule = shaderModule,
- EntryPointName = entryPointName,
- UniformBufferSize = (uint) Marshal.SizeOf(),
- BufferBindingCount = bufferBindingCount,
- ImageBindingCount = imageBindingCount
- };
- }
-
- public static ComputeShaderInfo Create(
- ShaderModule shaderModule,
- string entryPointName,
- uint bufferBindingCount,
- uint imageBindingCount
- )
- {
- return new ComputeShaderInfo
- {
- ShaderModule = shaderModule,
- EntryPointName = entryPointName,
- UniformBufferSize = 0,
- BufferBindingCount = bufferBindingCount,
- ImageBindingCount = imageBindingCount
- };
- }
- }
-}