diff --git a/lib/RefreshCS b/lib/RefreshCS index 2e3871a..fbed91b 160000 --- a/lib/RefreshCS +++ b/lib/RefreshCS @@ -1 +1 @@ -Subproject commit 2e3871a03d99e413f84748e40bdb6c03df2ecd1c +Subproject commit fbed91bfd6f09ae7864193ae620363547382f2fc diff --git a/src/Buffer.cs b/src/Buffer.cs index 43f67a5..c1f610e 100644 --- a/src/Buffer.cs +++ b/src/Buffer.cs @@ -37,5 +37,22 @@ namespace Campari ); } } + + // NOTE: You want to wait on the device before calling this + public unsafe void GetData( + T[] data, + uint dataLengthInBytes + ) where T : unmanaged + { + fixed (T* ptr = &data[0]) + { + Refresh.Refresh_GetBufferData( + Device.Handle, + Handle, + (IntPtr)ptr, + dataLengthInBytes + ); + } + } } } diff --git a/src/CommandBuffer.cs b/src/CommandBuffer.cs index fdbc218..2235187 100644 --- a/src/CommandBuffer.cs +++ b/src/CommandBuffer.cs @@ -62,6 +62,65 @@ namespace Campari } + public void BindComputePipeline( + ComputePipeline computePipeline + ) { + Refresh.Refresh_BindComputePipeline( + Device.Handle, + Handle, + computePipeline.Handle + ); + } + + public unsafe uint PushComputeShaderParams( + 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 ) { @@ -142,6 +201,31 @@ namespace Campari ); } + 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( Texture[] textures, Sampler[] samplers @@ -167,6 +251,63 @@ namespace Campari ); } + 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, @@ -191,17 +332,66 @@ namespace Campari ); } - public void QueuePresent(ref TextureSlice textureSlice, ref Refresh.Rect rectangle, Refresh.Filter filter) - { + 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 rectangle, + 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 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 + ); + } } } diff --git a/src/ComputePipeline.cs b/src/ComputePipeline.cs new file mode 100644 index 0000000..2c2b527 --- /dev/null +++ b/src/ComputePipeline.cs @@ -0,0 +1,39 @@ +using RefreshCS; +using System; + +namespace Campari +{ + public class ComputePipeline : GraphicsResource + { + protected override Action 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 + ); + } + } +} diff --git a/src/GraphicsDevice.cs b/src/GraphicsDevice.cs index 8e207d2..bb3fa79 100644 --- a/src/GraphicsDevice.cs +++ b/src/GraphicsDevice.cs @@ -10,7 +10,7 @@ namespace Campari public bool IsDisposed { get; private set; } - private Queue commandBufferPool; + private readonly Queue commandBufferPool; public GraphicsDevice( IntPtr deviceWindowHandle, @@ -73,6 +73,11 @@ namespace Campari } } + public void Wait() + { + Refresh.Refresh_Wait(Handle); + } + protected virtual void Dispose(bool disposing) { if (!IsDisposed)