From 99a7064e2ed5967a7f70cbc5d110e0b75ec4f844 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 17 Nov 2022 00:12:50 -0800 Subject: [PATCH] remove params from BeginRenderPass and PushUniforms --- src/Graphics/CommandBuffer.cs | 464 +++++++++++++++++++++++++++------- 1 file changed, 371 insertions(+), 93 deletions(-) diff --git a/src/Graphics/CommandBuffer.cs b/src/Graphics/CommandBuffer.cs index 2d72e4f..2af1524 100644 --- a/src/Graphics/CommandBuffer.cs +++ b/src/Graphics/CommandBuffer.cs @@ -29,39 +29,163 @@ namespace MoonWorks.Graphics currentSampleCount = SampleCount.One; } - // FIXME: we can probably use the NativeMemory functions to not have to generate arrays here + /// + /// Begins a render pass. + /// All render state, resource binding, and draw commands must be made within a render pass. + /// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass. + /// + /// The color attachment to use in the render pass. + public unsafe void BeginRenderPass( + ColorAttachmentInfo colorAttachmentInfo + ) + { +#if DEBUG + AssertTextureNotNull(colorAttachmentInfo); + AssertColorTarget(colorAttachmentInfo); +#endif + + var refreshColorAttachmentInfos = stackalloc Refresh.ColorAttachmentInfo[1]; + refreshColorAttachmentInfos[0] = colorAttachmentInfo.ToRefresh(); + + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + (IntPtr) refreshColorAttachmentInfos, + 1, + IntPtr.Zero + ); + + renderPassActive = true; + } /// /// Begins a render pass. /// All render state, resource binding, and draw commands must be made within a render pass. /// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass. /// - /// The color attachments to use in the render pass. + /// The first color attachment to use in the render pass. + /// The second color attachment to use in the render pass. public unsafe void BeginRenderPass( - params ColorAttachmentInfo[] colorAttachmentInfos + ColorAttachmentInfo colorAttachmentInfoOne, + ColorAttachmentInfo colorAttachmentInfoTwo ) { #if DEBUG - AssertValidColorAttachments(colorAttachmentInfos, true); + AssertTextureNotNull(colorAttachmentInfoOne); + AssertColorTarget(colorAttachmentInfoOne); + + AssertTextureNotNull(colorAttachmentInfoTwo); + AssertColorTarget(colorAttachmentInfoTwo); + + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoTwo); #endif - var refreshColorAttachmentInfos = new Refresh.ColorAttachmentInfo[colorAttachmentInfos.Length]; + var refreshColorAttachmentInfos = stackalloc Refresh.ColorAttachmentInfo[2]; + refreshColorAttachmentInfos[0] = colorAttachmentInfoOne.ToRefresh(); + refreshColorAttachmentInfos[1] = colorAttachmentInfoTwo.ToRefresh(); - for (var i = 0; i < colorAttachmentInfos.Length; i += 1) - { - refreshColorAttachmentInfos[i] = colorAttachmentInfos[i].ToRefresh(); - } + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + (IntPtr) refreshColorAttachmentInfos, + 2, + IntPtr.Zero + ); - fixed (Refresh.ColorAttachmentInfo* pColorAttachmentInfos = refreshColorAttachmentInfos) - { - Refresh.Refresh_BeginRenderPass( - Device.Handle, - Handle, - (IntPtr) pColorAttachmentInfos, - (uint) colorAttachmentInfos.Length, - IntPtr.Zero - ); - } + renderPassActive = true; + } + + /// + /// Begins a render pass. + /// All render state, resource binding, and draw commands must be made within a render pass. + /// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass. + /// + /// The first color attachment to use in the render pass. + /// The second color attachment to use in the render pass. + /// The third color attachment to use in the render pass. + public unsafe void BeginRenderPass( + ColorAttachmentInfo colorAttachmentInfoOne, + ColorAttachmentInfo colorAttachmentInfoTwo, + ColorAttachmentInfo colorAttachmentInfoThree + ) + { +#if DEBUG + AssertTextureNotNull(colorAttachmentInfoOne); + AssertColorTarget(colorAttachmentInfoOne); + + AssertTextureNotNull(colorAttachmentInfoTwo); + AssertColorTarget(colorAttachmentInfoTwo); + + AssertTextureNotNull(colorAttachmentInfoThree); + AssertColorTarget(colorAttachmentInfoThree); + + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoTwo); + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoThree); +#endif + + var refreshColorAttachmentInfos = stackalloc Refresh.ColorAttachmentInfo[3]; + refreshColorAttachmentInfos[0] = colorAttachmentInfoOne.ToRefresh(); + refreshColorAttachmentInfos[1] = colorAttachmentInfoTwo.ToRefresh(); + refreshColorAttachmentInfos[2] = colorAttachmentInfoThree.ToRefresh(); + + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + (IntPtr) refreshColorAttachmentInfos, + 3, + IntPtr.Zero + ); + + renderPassActive = true; + } + + /// + /// Begins a render pass. + /// All render state, resource binding, and draw commands must be made within a render pass. + /// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass. + /// + /// The first color attachment to use in the render pass. + /// The second color attachment to use in the render pass. + /// The third color attachment to use in the render pass. + /// The four color attachment to use in the render pass. + public unsafe void BeginRenderPass( + ColorAttachmentInfo colorAttachmentInfoOne, + ColorAttachmentInfo colorAttachmentInfoTwo, + ColorAttachmentInfo colorAttachmentInfoThree, + ColorAttachmentInfo colorAttachmentInfoFour + ) + { +#if DEBUG + AssertTextureNotNull(colorAttachmentInfoOne); + AssertColorTarget(colorAttachmentInfoOne); + + AssertTextureNotNull(colorAttachmentInfoTwo); + AssertColorTarget(colorAttachmentInfoTwo); + + AssertTextureNotNull(colorAttachmentInfoThree); + AssertColorTarget(colorAttachmentInfoThree); + + AssertTextureNotNull(colorAttachmentInfoFour); + AssertColorTarget(colorAttachmentInfoFour); + + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoTwo); + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoThree); + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoFour); +#endif + + var refreshColorAttachmentInfos = stackalloc Refresh.ColorAttachmentInfo[4]; + refreshColorAttachmentInfos[0] = colorAttachmentInfoOne.ToRefresh(); + refreshColorAttachmentInfos[1] = colorAttachmentInfoTwo.ToRefresh(); + refreshColorAttachmentInfos[2] = colorAttachmentInfoThree.ToRefresh(); + refreshColorAttachmentInfos[3] = colorAttachmentInfoFour.ToRefresh(); + + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + (IntPtr) refreshColorAttachmentInfos, + 4, + IntPtr.Zero + ); renderPassActive = true; } @@ -72,36 +196,208 @@ namespace MoonWorks.Graphics /// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass. /// /// The depth stencil attachment to use in the render pass. - /// The color attachments to use in the render pass. public unsafe void BeginRenderPass( - DepthStencilAttachmentInfo depthStencilAttachmentInfo, - params ColorAttachmentInfo[] colorAttachmentInfos + DepthStencilAttachmentInfo depthStencilAttachmentInfo ) { #if DEBUG AssertValidDepthAttachment(depthStencilAttachmentInfo); - AssertValidColorAttachments(colorAttachmentInfos, false); #endif - var refreshColorAttachmentInfos = new Refresh.ColorAttachmentInfo[colorAttachmentInfos.Length]; - - for (var i = 0; i < colorAttachmentInfos.Length; i += 1) - { - refreshColorAttachmentInfos[i] = colorAttachmentInfos[i].ToRefresh(); - } - var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo.ToRefresh(); - fixed (Refresh.ColorAttachmentInfo* pColorAttachmentInfos = refreshColorAttachmentInfos) - { - Refresh.Refresh_BeginRenderPass( - Device.Handle, - Handle, - pColorAttachmentInfos, - (uint) colorAttachmentInfos.Length, - &refreshDepthStencilAttachmentInfo - ); - } + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + (Refresh.ColorAttachmentInfo*) IntPtr.Zero, + 0, + &refreshDepthStencilAttachmentInfo + ); + + renderPassActive = true; + } + + /// + /// Begins a render pass. + /// All render state, resource binding, and draw commands must be made within a render pass. + /// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass. + /// + /// The depth stencil attachment to use in the render pass. + /// The color attachment to use in the render pass. + public unsafe void BeginRenderPass( + DepthStencilAttachmentInfo depthStencilAttachmentInfo, + ColorAttachmentInfo colorAttachmentInfo + ) + { +#if DEBUG + AssertValidDepthAttachment(depthStencilAttachmentInfo); + + AssertTextureNotNull(colorAttachmentInfo); + AssertColorTarget(colorAttachmentInfo); +#endif + + var refreshColorAttachmentInfos = stackalloc Refresh.ColorAttachmentInfo[1]; + refreshColorAttachmentInfos[0] = colorAttachmentInfo.ToRefresh(); + + var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo.ToRefresh(); + + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + refreshColorAttachmentInfos, + 1, + &refreshDepthStencilAttachmentInfo + ); + + renderPassActive = true; + } + + /// + /// Begins a render pass. + /// All render state, resource binding, and draw commands must be made within a render pass. + /// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass. + /// + /// The depth stencil attachment to use in the render pass. + /// The first color attachment to use in the render pass. + /// The second color attachment to use in the render pass. + public unsafe void BeginRenderPass( + DepthStencilAttachmentInfo depthStencilAttachmentInfo, + ColorAttachmentInfo colorAttachmentInfoOne, + ColorAttachmentInfo colorAttachmentInfoTwo + ) + { +#if DEBUG + AssertValidDepthAttachment(depthStencilAttachmentInfo); + + AssertTextureNotNull(colorAttachmentInfoOne); + AssertColorTarget(colorAttachmentInfoOne); + + AssertTextureNotNull(colorAttachmentInfoTwo); + AssertColorTarget(colorAttachmentInfoTwo); + + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoTwo); +#endif + + var refreshColorAttachmentInfos = stackalloc Refresh.ColorAttachmentInfo[2]; + refreshColorAttachmentInfos[0] = colorAttachmentInfoOne.ToRefresh(); + refreshColorAttachmentInfos[1] = colorAttachmentInfoTwo.ToRefresh(); + + var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo.ToRefresh(); + + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + refreshColorAttachmentInfos, + 2, + &refreshDepthStencilAttachmentInfo + ); + + renderPassActive = true; + } + + /// + /// Begins a render pass. + /// All render state, resource binding, and draw commands must be made within a render pass. + /// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass. + /// + /// The depth stencil attachment to use in the render pass. + /// The first color attachment to use in the render pass. + /// The second color attachment to use in the render pass. + /// The third color attachment to use in the render pass. + public unsafe void BeginRenderPass( + DepthStencilAttachmentInfo depthStencilAttachmentInfo, + ColorAttachmentInfo colorAttachmentInfoOne, + ColorAttachmentInfo colorAttachmentInfoTwo, + ColorAttachmentInfo colorAttachmentInfoThree + ) + { +#if DEBUG + AssertValidDepthAttachment(depthStencilAttachmentInfo); + + AssertTextureNotNull(colorAttachmentInfoOne); + AssertColorTarget(colorAttachmentInfoOne); + + AssertTextureNotNull(colorAttachmentInfoTwo); + AssertColorTarget(colorAttachmentInfoTwo); + + AssertTextureNotNull(colorAttachmentInfoThree); + AssertColorTarget(colorAttachmentInfoThree); + + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoTwo); + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoTwo); +#endif + + var refreshColorAttachmentInfos = stackalloc Refresh.ColorAttachmentInfo[3]; + refreshColorAttachmentInfos[0] = colorAttachmentInfoOne.ToRefresh(); + refreshColorAttachmentInfos[1] = colorAttachmentInfoTwo.ToRefresh(); + refreshColorAttachmentInfos[2] = colorAttachmentInfoThree.ToRefresh(); + + var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo.ToRefresh(); + + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + refreshColorAttachmentInfos, + 3, + &refreshDepthStencilAttachmentInfo + ); + + renderPassActive = true; + } + + /// + /// Begins a render pass. + /// All render state, resource binding, and draw commands must be made within a render pass. + /// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass. + /// + /// The depth stencil attachment to use in the render pass. + /// The first color attachment to use in the render pass. + /// The second color attachment to use in the render pass. + /// The third color attachment to use in the render pass. + /// The four color attachment to use in the render pass. + public unsafe void BeginRenderPass( + DepthStencilAttachmentInfo depthStencilAttachmentInfo, + ColorAttachmentInfo colorAttachmentInfoOne, + ColorAttachmentInfo colorAttachmentInfoTwo, + ColorAttachmentInfo colorAttachmentInfoThree, + ColorAttachmentInfo colorAttachmentInfoFour + ) + { +#if DEBUG + AssertValidDepthAttachment(depthStencilAttachmentInfo); + + AssertTextureNotNull(colorAttachmentInfoOne); + AssertColorTarget(colorAttachmentInfoOne); + + AssertTextureNotNull(colorAttachmentInfoTwo); + AssertColorTarget(colorAttachmentInfoTwo); + + AssertTextureNotNull(colorAttachmentInfoThree); + AssertColorTarget(colorAttachmentInfoThree); + + AssertTextureNotNull(colorAttachmentInfoFour); + AssertColorTarget(colorAttachmentInfoFour); + + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoTwo); + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoThree); + AssertSameSampleCount(colorAttachmentInfoOne, colorAttachmentInfoFour); +#endif + + var refreshColorAttachmentInfos = stackalloc Refresh.ColorAttachmentInfo[4]; + refreshColorAttachmentInfos[0] = colorAttachmentInfoOne.ToRefresh(); + refreshColorAttachmentInfos[1] = colorAttachmentInfoTwo.ToRefresh(); + refreshColorAttachmentInfos[2] = colorAttachmentInfoThree.ToRefresh(); + refreshColorAttachmentInfos[3] = colorAttachmentInfoFour.ToRefresh(); + + var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo.ToRefresh(); + + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + refreshColorAttachmentInfos, + 4, + &refreshDepthStencilAttachmentInfo + ); renderPassActive = true; } @@ -478,7 +774,7 @@ namespace MoonWorks.Graphics /// /// A starting offset value to be used with draw calls. public unsafe uint PushVertexShaderUniforms( - params T[] uniforms + T uniforms ) where T : unmanaged { #if DEBUG @@ -490,15 +786,12 @@ namespace MoonWorks.Graphics } #endif - fixed (T* ptr = &uniforms[0]) - { - return Refresh.Refresh_PushVertexShaderUniforms( - Device.Handle, - Handle, - (IntPtr) ptr, - (uint) (uniforms.Length * sizeof(T)) - ); - } + return Refresh.Refresh_PushVertexShaderUniforms( + Device.Handle, + Handle, + (IntPtr) (&uniforms), + (uint) sizeof(T) + ); } /// @@ -506,7 +799,7 @@ namespace MoonWorks.Graphics /// /// A starting offset to be used with draw calls. public unsafe uint PushFragmentShaderUniforms( - params T[] uniforms + T uniforms ) where T : unmanaged { #if DEBUG @@ -518,15 +811,12 @@ namespace MoonWorks.Graphics } #endif - fixed (T* ptr = &uniforms[0]) - { - return Refresh.Refresh_PushFragmentShaderUniforms( - Device.Handle, - Handle, - (IntPtr) ptr, - (uint) (uniforms.Length * sizeof(T)) - ); - } + return Refresh.Refresh_PushFragmentShaderUniforms( + Device.Handle, + Handle, + (IntPtr) (&uniforms), + (uint) sizeof(T) + ); } /// @@ -534,7 +824,7 @@ namespace MoonWorks.Graphics /// /// A starting offset to be used with dispatch calls. public unsafe uint PushComputeShaderUniforms( - params T[] uniforms + T uniforms ) where T : unmanaged { #if DEBUG @@ -546,15 +836,13 @@ namespace MoonWorks.Graphics } #endif - fixed (T* ptr = &uniforms[0]) - { - return Refresh.Refresh_PushComputeShaderUniforms( - Device.Handle, - Handle, - (IntPtr) ptr, - (uint) (uniforms.Length * sizeof(T)) - ); - } + return Refresh.Refresh_PushComputeShaderUniforms( + Device.Handle, + Handle, + (IntPtr) (&uniforms), + (uint) sizeof(T) + ); + } /// @@ -1019,37 +1307,27 @@ namespace MoonWorks.Graphics } } - private void AssertValidColorAttachments(ColorAttachmentInfo[] colorAttachmentInfos, bool atLeastOneRequired) + private void AssertTextureNotNull(ColorAttachmentInfo colorAttachmentInfo) { - if (atLeastOneRequired && colorAttachmentInfos.Length == 0) + if (colorAttachmentInfo.Texture == null || colorAttachmentInfo.Texture.Handle == IntPtr.Zero) { - throw new System.ArgumentException("Render pass must contain at least one attachment!"); + throw new System.ArgumentException("Render pass color attachment Texture cannot be null!"); } + } - currentSampleCount = (colorAttachmentInfos.Length > 0) ? colorAttachmentInfos[0].SampleCount : SampleCount.One; - - if (colorAttachmentInfos.Length > 4) + private void AssertColorTarget(ColorAttachmentInfo colorAttachmentInfo) + { + if ((colorAttachmentInfo.Texture.UsageFlags & TextureUsageFlags.ColorTarget) == 0) { - throw new System.ArgumentException("Render pass cannot have more than 4 color attachments!"); + throw new System.ArgumentException("Render pass color attachment UsageFlags must include TextureUsageFlags.ColorTarget!"); } + } - for (int i = 0; i < colorAttachmentInfos.Length; i += 1) + private void AssertSameSampleCount(ColorAttachmentInfo a, ColorAttachmentInfo b) + { + if (a.SampleCount != b.SampleCount) { - if (colorAttachmentInfos[i].Texture == null || - colorAttachmentInfos[i].Texture.Handle == IntPtr.Zero) - { - throw new System.ArgumentException("Render pass color attachment Texture cannot be null!"); - } - - if ((colorAttachmentInfos[i].Texture.UsageFlags & TextureUsageFlags.ColorTarget) == 0) - { - throw new System.ArgumentException("Render pass color attachment UsageFlags must include TextureUsageFlags.ColorTarget!"); - } - - if (colorAttachmentInfos[i].SampleCount != currentSampleCount) - { - throw new System.ArgumentException("All color attachments in a render pass must have the same SampleCount!"); - } + throw new System.ArgumentException("All color attachments in a render pass must have the same SampleCount!"); } }