From d83501437db2a463b2a69a39dd5e47befcf65a24 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 23 Feb 2024 15:53:49 -0800 Subject: [PATCH] rearrange methods in CommandBuffer --- src/Graphics/CommandBuffer.cs | 942 +++++++++++++++++----------------- 1 file changed, 471 insertions(+), 471 deletions(-) diff --git a/src/Graphics/CommandBuffer.cs b/src/Graphics/CommandBuffer.cs index 554bc53..2f2924b 100644 --- a/src/Graphics/CommandBuffer.cs +++ b/src/Graphics/CommandBuffer.cs @@ -76,6 +76,57 @@ namespace MoonWorks.Graphics } #endif + /// + /// Acquires a swapchain texture. + /// This texture will be presented to the given window when the command buffer is submitted. + /// Can return null if the swapchain is unavailable. The user should ALWAYS handle the case where this occurs. + /// If null is returned, presentation will not occur. + /// It is an error to acquire two swapchain textures from the same window in one command buffer. + /// It is an error to dispose the swapchain texture. If you do this your game WILL crash. DO NOT DO THIS. + /// + public Texture AcquireSwapchainTexture( + Window window + ) { +#if DEBUG + AssertNotSubmitted(); + + if (!window.Claimed) + { + throw new System.InvalidOperationException("Cannot acquire swapchain texture, window has not been claimed!"); + } + + if (swapchainTextureAcquired) + { + throw new System.InvalidOperationException("Cannot acquire two swapchain textures on the same command buffer!"); + } +#endif + + var texturePtr = Refresh.Refresh_AcquireSwapchainTexture( + Device.Handle, + Handle, + window.Handle, + out var width, + out var height + ); + + if (texturePtr == IntPtr.Zero) + { + return null; + } + + // Override the texture properties to avoid allocating a new texture instance! + window.SwapchainTexture.Handle = texturePtr; + window.SwapchainTexture.Width = width; + window.SwapchainTexture.Height = height; + window.SwapchainTexture.Format = window.SwapchainFormat; + +#if DEBUG + swapchainTextureAcquired = true; +#endif + + return window.SwapchainTexture; + } + /// /// Begins a render pass. /// All render state, resource binding, and draw commands must be made within a render pass. @@ -526,397 +577,6 @@ namespace MoonWorks.Graphics #endif } - public void BeginComputePass() - { -#if DEBUG - AssertNotSubmitted(); - AssertNotInPass("Cannot begin compute pass while in another pass!"); - computePassActive = true; -#endif - - Refresh.Refresh_BeginComputePass( - Device.Handle, - Handle - ); - } - - /// - /// Binds a compute pipeline so that compute work may be dispatched. - /// - /// The compute pipeline to bind. - public void BindComputePipeline( - ComputePipeline computePipeline - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInComputePass("Cannot bind compute pipeline outside of compute pass!"); -#endif - - Refresh.Refresh_BindComputePipeline( - Device.Handle, - Handle, - computePipeline.Handle - ); - -#if DEBUG - currentComputePipeline = computePipeline; -#endif - } - - /// - /// Binds a buffer to be used in the compute shader. - /// - /// A buffer to bind. - public unsafe void BindComputeBuffers( - GpuBuffer buffer - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInComputePass("Cannot bind compute buffers outside of compute pass!"); - AssertComputePipelineBound(); - AssertComputeBufferCount(1); -#endif - - var bufferPtrs = stackalloc IntPtr[1]; - bufferPtrs[0] = buffer.Handle; - - Refresh.Refresh_BindComputeBuffers( - Device.Handle, - Handle, - (IntPtr) bufferPtrs - ); - } - - /// - /// Binds buffers to be used in the compute shader. - /// - /// A buffer to bind. - /// A buffer to bind. - public unsafe void BindComputeBuffers( - GpuBuffer bufferOne, - GpuBuffer bufferTwo - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInComputePass("Cannot bind compute buffers outside of compute pass!"); - AssertComputePipelineBound(); - AssertComputeBufferCount(2); -#endif - - var bufferPtrs = stackalloc IntPtr[2]; - bufferPtrs[0] = bufferOne.Handle; - bufferPtrs[1] = bufferTwo.Handle; - - Refresh.Refresh_BindComputeBuffers( - Device.Handle, - Handle, - (IntPtr) bufferPtrs - ); - } - - /// - /// Binds buffers to be used in the compute shader. - /// - /// A buffer to bind. - /// A buffer to bind. - /// A buffer to bind. - public unsafe void BindComputeBuffers( - GpuBuffer bufferOne, - GpuBuffer bufferTwo, - GpuBuffer bufferThree - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInComputePass("Cannot bind compute buffers outside of compute pass!"); - AssertComputePipelineBound(); - AssertComputeBufferCount(3); -#endif - - var bufferPtrs = stackalloc IntPtr[3]; - bufferPtrs[0] = bufferOne.Handle; - bufferPtrs[1] = bufferTwo.Handle; - bufferPtrs[2] = bufferThree.Handle; - - Refresh.Refresh_BindComputeBuffers( - Device.Handle, - Handle, - (IntPtr) bufferPtrs - ); - } - - /// - /// Binds buffers to be used in the compute shader. - /// - /// A buffer to bind. - /// A buffer to bind. - /// A buffer to bind. - /// A buffer to bind. - public unsafe void BindComputeBuffers( - GpuBuffer bufferOne, - GpuBuffer bufferTwo, - GpuBuffer bufferThree, - GpuBuffer bufferFour - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInComputePass("Cannot bind compute buffers outside of compute pass!"); - AssertComputePipelineBound(); - AssertComputeBufferCount(4); -#endif - - var bufferPtrs = stackalloc IntPtr[4]; - bufferPtrs[0] = bufferOne.Handle; - bufferPtrs[1] = bufferTwo.Handle; - bufferPtrs[2] = bufferThree.Handle; - bufferPtrs[3] = bufferFour.Handle; - - Refresh.Refresh_BindComputeBuffers( - Device.Handle, - Handle, - (IntPtr) bufferPtrs - ); - } - - /// - /// Binds buffers to be used in the compute shader. - /// - /// A Span of buffers to bind. - public unsafe void BindComputeBuffers( - in Span buffers - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInComputePass("Cannot bind compute buffers outside of compute pass!"); - AssertComputePipelineBound(); - AssertComputeBufferCount(buffers.Length); -#endif - - 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 - ); - } - - /// - /// Binds a texture to be used in the compute shader. - /// - /// A texture-level pair to bind. - public unsafe void BindComputeTextures( - TextureLevelBinding binding - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInComputePass("Cannot bind compute textures outside of compute pass!"); - AssertComputePipelineBound(); - AssertComputeTextureCount(1); -#endif - - var texturePtrs = stackalloc IntPtr[1]; - texturePtrs[0] = binding.Texture.Handle; - - var mipLevels = stackalloc uint[1]; - mipLevels[0] = binding.MipLevel; - - Refresh.Refresh_BindComputeTextures( - Device.Handle, - Handle, - (IntPtr) texturePtrs, - (IntPtr) mipLevels - ); - } - - /// - /// Binds textures to be used in the compute shader. - /// - /// A texture-level pair to bind. - /// A texture-level pair to bind. - public unsafe void BindComputeTextures( - TextureLevelBinding bindingOne, - TextureLevelBinding bindingTwo - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInComputePass("Cannot bind compute textures outside of compute pass!"); - AssertComputePipelineBound(); - AssertComputeTextureCount(2); -#endif - - var texturePtrs = stackalloc IntPtr[2]; - texturePtrs[0] = bindingOne.Texture.Handle; - texturePtrs[1] = bindingTwo.Texture.Handle; - - var mipLevels = stackalloc uint[2]; - mipLevels[0] = bindingOne.MipLevel; - mipLevels[1] = bindingTwo.MipLevel; - - Refresh.Refresh_BindComputeTextures( - Device.Handle, - Handle, - (IntPtr) texturePtrs, - (IntPtr) mipLevels - ); - } - - /// - /// Binds textures to be used in the compute shader. - /// - /// A texture-level pair to bind. - /// A texture-level pair to bind. - /// A texture-level pair to bind. - public unsafe void BindComputeTextures( - TextureLevelBinding bindingOne, - TextureLevelBinding bindingTwo, - TextureLevelBinding bindingThree - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInComputePass("Cannot bind compute textures outside of compute pass!"); - AssertComputePipelineBound(); - AssertComputeTextureCount(3); -#endif - - var texturePtrs = stackalloc IntPtr[3]; - texturePtrs[0] = bindingOne.Texture.Handle; - texturePtrs[1] = bindingTwo.Texture.Handle; - texturePtrs[2] = bindingThree.Texture.Handle; - - var mipLevels = stackalloc uint[3]; - mipLevels[0] = bindingOne.MipLevel; - mipLevels[1] = bindingTwo.MipLevel; - mipLevels[2] = bindingThree.MipLevel; - - Refresh.Refresh_BindComputeTextures( - Device.Handle, - Handle, - (IntPtr) texturePtrs, - (IntPtr) mipLevels - ); - } - - /// - /// Binds textures to be used in the compute shader. - /// - /// A texture-level pair to bind. - /// A texture-level pair to bind. - /// A texture-level pair to bind. - /// A texture-level pair to bind. - public unsafe void BindComputeTextures( - TextureLevelBinding bindingOne, - TextureLevelBinding bindingTwo, - TextureLevelBinding bindingThree, - TextureLevelBinding bindingFour - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInComputePass("Cannot bind compute textures outside of compute pass!"); - AssertComputePipelineBound(); - AssertComputeTextureCount(4); -#endif - - var texturePtrs = stackalloc IntPtr[4]; - texturePtrs[0] = bindingOne.Texture.Handle; - texturePtrs[1] = bindingTwo.Texture.Handle; - texturePtrs[2] = bindingThree.Texture.Handle; - texturePtrs[3] = bindingFour.Texture.Handle; - - var mipLevels = stackalloc uint[4]; - mipLevels[0] = bindingOne.MipLevel; - mipLevels[1] = bindingTwo.MipLevel; - mipLevels[2] = bindingThree.MipLevel; - mipLevels[3] = bindingFour.MipLevel; - - Refresh.Refresh_BindComputeTextures( - Device.Handle, - Handle, - (IntPtr) texturePtrs, - (IntPtr) mipLevels - ); - } - - /// - /// Binds textures to be used in the compute shader. - /// - /// A set of texture-level pairs to bind. - public unsafe void BindComputeTextures( - in Span bindings - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInComputePass("Cannot bind compute textures outside of compute pass!"); - AssertComputePipelineBound(); - AssertComputeTextureCount(bindings.Length); -#endif - - var texturePtrs = stackalloc IntPtr[bindings.Length]; - var mipLevels = stackalloc uint[bindings.Length]; - - for (var i = 0; i < bindings.Length; i += 1) - { - texturePtrs[i] = bindings[i].Texture.Handle; - mipLevels[i] = bindings[i].MipLevel; - } - - Refresh.Refresh_BindComputeTextures( - Device.Handle, - Handle, - (IntPtr) texturePtrs, - (IntPtr) mipLevels - ); - } - - /// - /// 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() - { -#if DEBUG - AssertInComputePass("Cannot end compute pass while not in a compute pass!"); - computePassActive = false; -#endif - - Refresh.Refresh_EndComputePass( - Device.Handle, - Handle - ); - } - /// /// Binds a graphics pipeline so that rendering work may be performed. /// @@ -1671,51 +1331,6 @@ namespace MoonWorks.Graphics } } - /// - /// 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()); - } - } - /// /// Draws using instanced rendering. /// @@ -1865,55 +1480,440 @@ namespace MoonWorks.Graphics EndRenderPass(); } + public void BeginComputePass() + { +#if DEBUG + AssertNotSubmitted(); + AssertNotInPass("Cannot begin compute pass while in another pass!"); + computePassActive = true; +#endif + + Refresh.Refresh_BeginComputePass( + Device.Handle, + Handle + ); + } + /// - /// Acquires a swapchain texture. - /// This texture will be presented to the given window when the command buffer is submitted. - /// Can return null if the swapchain is unavailable. The user should ALWAYS handle the case where this occurs. - /// If null is returned, presentation will not occur. - /// It is an error to acquire two swapchain textures from the same window in one command buffer. - /// It is an error to dispose the swapchain texture. If you do this your game WILL crash. DO NOT DO THIS. + /// Binds a compute pipeline so that compute work may be dispatched. /// - public Texture AcquireSwapchainTexture( - Window window + /// The compute pipeline to bind. + public void BindComputePipeline( + ComputePipeline computePipeline ) { #if DEBUG AssertNotSubmitted(); - - if (!window.Claimed) - { - throw new System.InvalidOperationException("Cannot acquire swapchain texture, window has not been claimed!"); - } - - if (swapchainTextureAcquired) - { - throw new System.InvalidOperationException("Cannot acquire two swapchain textures on the same command buffer!"); - } + AssertInComputePass("Cannot bind compute pipeline outside of compute pass!"); #endif - var texturePtr = Refresh.Refresh_AcquireSwapchainTexture( + Refresh.Refresh_BindComputePipeline( Device.Handle, Handle, - window.Handle, - out var width, - out var height + computePipeline.Handle ); - if (texturePtr == IntPtr.Zero) - { - return null; - } - - // Override the texture properties to avoid allocating a new texture instance! - window.SwapchainTexture.Handle = texturePtr; - window.SwapchainTexture.Width = width; - window.SwapchainTexture.Height = height; - window.SwapchainTexture.Format = window.SwapchainFormat; - #if DEBUG - swapchainTextureAcquired = true; + currentComputePipeline = computePipeline; +#endif + } + + /// + /// Binds a buffer to be used in the compute shader. + /// + /// A buffer to bind. + public unsafe void BindComputeBuffers( + GpuBuffer buffer + ) { +#if DEBUG + AssertNotSubmitted(); + AssertInComputePass("Cannot bind compute buffers outside of compute pass!"); + AssertComputePipelineBound(); + AssertComputeBufferCount(1); #endif - return window.SwapchainTexture; + var bufferPtrs = stackalloc IntPtr[1]; + bufferPtrs[0] = buffer.Handle; + + Refresh.Refresh_BindComputeBuffers( + Device.Handle, + Handle, + (IntPtr) bufferPtrs + ); + } + + /// + /// Binds buffers to be used in the compute shader. + /// + /// A buffer to bind. + /// A buffer to bind. + public unsafe void BindComputeBuffers( + GpuBuffer bufferOne, + GpuBuffer bufferTwo + ) { +#if DEBUG + AssertNotSubmitted(); + AssertInComputePass("Cannot bind compute buffers outside of compute pass!"); + AssertComputePipelineBound(); + AssertComputeBufferCount(2); +#endif + + var bufferPtrs = stackalloc IntPtr[2]; + bufferPtrs[0] = bufferOne.Handle; + bufferPtrs[1] = bufferTwo.Handle; + + Refresh.Refresh_BindComputeBuffers( + Device.Handle, + Handle, + (IntPtr) bufferPtrs + ); + } + + /// + /// Binds buffers to be used in the compute shader. + /// + /// A buffer to bind. + /// A buffer to bind. + /// A buffer to bind. + public unsafe void BindComputeBuffers( + GpuBuffer bufferOne, + GpuBuffer bufferTwo, + GpuBuffer bufferThree + ) { +#if DEBUG + AssertNotSubmitted(); + AssertInComputePass("Cannot bind compute buffers outside of compute pass!"); + AssertComputePipelineBound(); + AssertComputeBufferCount(3); +#endif + + var bufferPtrs = stackalloc IntPtr[3]; + bufferPtrs[0] = bufferOne.Handle; + bufferPtrs[1] = bufferTwo.Handle; + bufferPtrs[2] = bufferThree.Handle; + + Refresh.Refresh_BindComputeBuffers( + Device.Handle, + Handle, + (IntPtr) bufferPtrs + ); + } + + /// + /// Binds buffers to be used in the compute shader. + /// + /// A buffer to bind. + /// A buffer to bind. + /// A buffer to bind. + /// A buffer to bind. + public unsafe void BindComputeBuffers( + GpuBuffer bufferOne, + GpuBuffer bufferTwo, + GpuBuffer bufferThree, + GpuBuffer bufferFour + ) { +#if DEBUG + AssertNotSubmitted(); + AssertInComputePass("Cannot bind compute buffers outside of compute pass!"); + AssertComputePipelineBound(); + AssertComputeBufferCount(4); +#endif + + var bufferPtrs = stackalloc IntPtr[4]; + bufferPtrs[0] = bufferOne.Handle; + bufferPtrs[1] = bufferTwo.Handle; + bufferPtrs[2] = bufferThree.Handle; + bufferPtrs[3] = bufferFour.Handle; + + Refresh.Refresh_BindComputeBuffers( + Device.Handle, + Handle, + (IntPtr) bufferPtrs + ); + } + + /// + /// Binds buffers to be used in the compute shader. + /// + /// A Span of buffers to bind. + public unsafe void BindComputeBuffers( + in Span buffers + ) { +#if DEBUG + AssertNotSubmitted(); + AssertInComputePass("Cannot bind compute buffers outside of compute pass!"); + AssertComputePipelineBound(); + AssertComputeBufferCount(buffers.Length); +#endif + + 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 + ); + } + + /// + /// Binds a texture to be used in the compute shader. + /// + /// A texture-level pair to bind. + public unsafe void BindComputeTextures( + TextureLevelBinding binding + ) { +#if DEBUG + AssertNotSubmitted(); + AssertInComputePass("Cannot bind compute textures outside of compute pass!"); + AssertComputePipelineBound(); + AssertComputeTextureCount(1); +#endif + + var texturePtrs = stackalloc IntPtr[1]; + texturePtrs[0] = binding.Texture.Handle; + + var mipLevels = stackalloc uint[1]; + mipLevels[0] = binding.MipLevel; + + Refresh.Refresh_BindComputeTextures( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) mipLevels + ); + } + + /// + /// Binds textures to be used in the compute shader. + /// + /// A texture-level pair to bind. + /// A texture-level pair to bind. + public unsafe void BindComputeTextures( + TextureLevelBinding bindingOne, + TextureLevelBinding bindingTwo + ) { +#if DEBUG + AssertNotSubmitted(); + AssertInComputePass("Cannot bind compute textures outside of compute pass!"); + AssertComputePipelineBound(); + AssertComputeTextureCount(2); +#endif + + var texturePtrs = stackalloc IntPtr[2]; + texturePtrs[0] = bindingOne.Texture.Handle; + texturePtrs[1] = bindingTwo.Texture.Handle; + + var mipLevels = stackalloc uint[2]; + mipLevels[0] = bindingOne.MipLevel; + mipLevels[1] = bindingTwo.MipLevel; + + Refresh.Refresh_BindComputeTextures( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) mipLevels + ); + } + + /// + /// Binds textures to be used in the compute shader. + /// + /// A texture-level pair to bind. + /// A texture-level pair to bind. + /// A texture-level pair to bind. + public unsafe void BindComputeTextures( + TextureLevelBinding bindingOne, + TextureLevelBinding bindingTwo, + TextureLevelBinding bindingThree + ) { +#if DEBUG + AssertNotSubmitted(); + AssertInComputePass("Cannot bind compute textures outside of compute pass!"); + AssertComputePipelineBound(); + AssertComputeTextureCount(3); +#endif + + var texturePtrs = stackalloc IntPtr[3]; + texturePtrs[0] = bindingOne.Texture.Handle; + texturePtrs[1] = bindingTwo.Texture.Handle; + texturePtrs[2] = bindingThree.Texture.Handle; + + var mipLevels = stackalloc uint[3]; + mipLevels[0] = bindingOne.MipLevel; + mipLevels[1] = bindingTwo.MipLevel; + mipLevels[2] = bindingThree.MipLevel; + + Refresh.Refresh_BindComputeTextures( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) mipLevels + ); + } + + /// + /// Binds textures to be used in the compute shader. + /// + /// A texture-level pair to bind. + /// A texture-level pair to bind. + /// A texture-level pair to bind. + /// A texture-level pair to bind. + public unsafe void BindComputeTextures( + TextureLevelBinding bindingOne, + TextureLevelBinding bindingTwo, + TextureLevelBinding bindingThree, + TextureLevelBinding bindingFour + ) { +#if DEBUG + AssertNotSubmitted(); + AssertInComputePass("Cannot bind compute textures outside of compute pass!"); + AssertComputePipelineBound(); + AssertComputeTextureCount(4); +#endif + + var texturePtrs = stackalloc IntPtr[4]; + texturePtrs[0] = bindingOne.Texture.Handle; + texturePtrs[1] = bindingTwo.Texture.Handle; + texturePtrs[2] = bindingThree.Texture.Handle; + texturePtrs[3] = bindingFour.Texture.Handle; + + var mipLevels = stackalloc uint[4]; + mipLevels[0] = bindingOne.MipLevel; + mipLevels[1] = bindingTwo.MipLevel; + mipLevels[2] = bindingThree.MipLevel; + mipLevels[3] = bindingFour.MipLevel; + + Refresh.Refresh_BindComputeTextures( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) mipLevels + ); + } + + /// + /// Binds textures to be used in the compute shader. + /// + /// A set of texture-level pairs to bind. + public unsafe void BindComputeTextures( + in Span bindings + ) { +#if DEBUG + AssertNotSubmitted(); + AssertInComputePass("Cannot bind compute textures outside of compute pass!"); + AssertComputePipelineBound(); + AssertComputeTextureCount(bindings.Length); +#endif + + var texturePtrs = stackalloc IntPtr[bindings.Length]; + var mipLevels = stackalloc uint[bindings.Length]; + + for (var i = 0; i < bindings.Length; i += 1) + { + texturePtrs[i] = bindings[i].Texture.Handle; + mipLevels[i] = bindings[i].MipLevel; + } + + Refresh.Refresh_BindComputeTextures( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) mipLevels + ); + } + + /// + /// 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() + { +#if DEBUG + AssertInComputePass("Cannot end compute pass while not in a compute pass!"); + computePassActive = false; +#endif + + Refresh.Refresh_EndComputePass( + Device.Handle, + Handle + ); } // Copy Pass