diff --git a/src/Graphics/CommandBuffer.cs b/src/Graphics/CommandBuffer.cs index 2d72e4f..dd2e61a 100644 --- a/src/Graphics/CommandBuffer.cs +++ b/src/Graphics/CommandBuffer.cs @@ -12,58 +12,214 @@ namespace MoonWorks.Graphics public GraphicsDevice Device { get; } public IntPtr Handle { get; } - // some state for debug validation +#if DEBUG GraphicsPipeline currentGraphicsPipeline; ComputePipeline currentComputePipeline; bool renderPassActive; SampleCount currentSampleCount; + TextureFormat colorFormatOne; + TextureFormat colorFormatTwo; + TextureFormat colorFormatThree; + TextureFormat colorFormatFour; + TextureFormat depthStencilFormat; +#endif // called from RefreshDevice internal CommandBuffer(GraphicsDevice device, IntPtr handle) { Device = device; Handle = handle; + +#if DEBUG currentGraphicsPipeline = null; currentComputePipeline = null; renderPassActive = false; currentSampleCount = SampleCount.One; + colorFormatOne = TextureFormat.R8G8B8A8; + colorFormatTwo = TextureFormat.R8G8B8A8; + colorFormatThree = TextureFormat.R8G8B8A8; + colorFormatFour = TextureFormat.R8G8B8A8; + depthStencilFormat = TextureFormat.D16; +#endif } - // 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 attachments to use in the render pass. + /// The color attachment to use in the render pass. public unsafe void BeginRenderPass( - params ColorAttachmentInfo[] colorAttachmentInfos - ) - { + in ColorAttachmentInfo colorAttachmentInfo + ) { #if DEBUG - AssertValidColorAttachments(colorAttachmentInfos, true); + AssertTextureNotNull(colorAttachmentInfo); + AssertColorTarget(colorAttachmentInfo); #endif - var refreshColorAttachmentInfos = new Refresh.ColorAttachmentInfo[colorAttachmentInfos.Length]; + var refreshColorAttachmentInfos = stackalloc Refresh.ColorAttachmentInfo[1]; + refreshColorAttachmentInfos[0] = colorAttachmentInfo.ToRefresh(); - for (var i = 0; i < colorAttachmentInfos.Length; i += 1) - { - refreshColorAttachmentInfos[i] = colorAttachmentInfos[i].ToRefresh(); - } - - fixed (Refresh.ColorAttachmentInfo* pColorAttachmentInfos = refreshColorAttachmentInfos) - { - Refresh.Refresh_BeginRenderPass( - Device.Handle, - Handle, - (IntPtr) pColorAttachmentInfos, - (uint) colorAttachmentInfos.Length, - IntPtr.Zero - ); - } + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + (IntPtr) refreshColorAttachmentInfos, + 1, + IntPtr.Zero + ); +#if DEBUG renderPassActive = true; + currentSampleCount = colorAttachmentInfo.SampleCount; + colorFormatOne = colorAttachmentInfo.Texture.Format; +#endif + } + + /// + /// 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. + public unsafe void BeginRenderPass( + in ColorAttachmentInfo colorAttachmentInfoOne, + in ColorAttachmentInfo colorAttachmentInfoTwo + ) { +#if DEBUG + 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(); + + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + (IntPtr) refreshColorAttachmentInfos, + 2, + IntPtr.Zero + ); + +#if DEBUG + renderPassActive = true; + currentSampleCount = colorAttachmentInfoOne.SampleCount; + colorFormatOne = colorAttachmentInfoOne.Texture.Format; + colorFormatTwo = colorAttachmentInfoTwo.Texture.Format; +#endif + } + + /// + /// 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( + in ColorAttachmentInfo colorAttachmentInfoOne, + in ColorAttachmentInfo colorAttachmentInfoTwo, + in 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 + ); + +#if DEBUG + renderPassActive = true; + currentSampleCount = colorAttachmentInfoOne.SampleCount; + colorFormatOne = colorAttachmentInfoOne.Texture.Format; + colorFormatTwo = colorAttachmentInfoTwo.Texture.Format; + colorFormatThree = colorAttachmentInfoThree.Texture.Format; +#endif + } + + /// + /// 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( + in ColorAttachmentInfo colorAttachmentInfoOne, + in ColorAttachmentInfo colorAttachmentInfoTwo, + in ColorAttachmentInfo colorAttachmentInfoThree, + in 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 + ); + +#if DEBUG + renderPassActive = true; + currentSampleCount = colorAttachmentInfoOne.SampleCount; + colorFormatOne = colorAttachmentInfoOne.Texture.Format; + colorFormatTwo = colorAttachmentInfoTwo.Texture.Format; + colorFormatThree = colorAttachmentInfoThree.Texture.Format; + colorFormatFour = colorAttachmentInfoFour.Texture.Format; +#endif } /// @@ -72,38 +228,234 @@ 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 - ) - { + in 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 + ); +#if DEBUG renderPassActive = true; + depthStencilFormat = depthStencilAttachmentInfo.Texture.Format; +#endif + } + + /// + /// 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( + in DepthStencilAttachmentInfo depthStencilAttachmentInfo, + in 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 + ); + +#if DEBUG + renderPassActive = true; + currentSampleCount = colorAttachmentInfo.SampleCount; + colorFormatOne = colorAttachmentInfo.Texture.Format; + depthStencilFormat = depthStencilAttachmentInfo.Texture.Format; +#endif + } + + /// + /// 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( + in DepthStencilAttachmentInfo depthStencilAttachmentInfo, + in ColorAttachmentInfo colorAttachmentInfoOne, + in 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 + ); + +#if DEBUG + renderPassActive = true; + currentSampleCount = colorAttachmentInfoOne.SampleCount; + colorFormatOne = colorAttachmentInfoOne.Texture.Format; + colorFormatTwo = colorAttachmentInfoTwo.Texture.Format; + depthStencilFormat = depthStencilAttachmentInfo.Texture.Format; +#endif + } + + /// + /// 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( + in DepthStencilAttachmentInfo depthStencilAttachmentInfo, + in ColorAttachmentInfo colorAttachmentInfoOne, + in ColorAttachmentInfo colorAttachmentInfoTwo, + in 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 + ); + +#if DEBUG + renderPassActive = true; + currentSampleCount = colorAttachmentInfoOne.SampleCount; + colorFormatOne = colorAttachmentInfoOne.Texture.Format; + colorFormatTwo = colorAttachmentInfoTwo.Texture.Format; + colorFormatThree = colorAttachmentInfoThree.Texture.Format; + depthStencilFormat = depthStencilAttachmentInfo.Texture.Format; +#endif + } + + /// + /// 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( + in DepthStencilAttachmentInfo depthStencilAttachmentInfo, + in ColorAttachmentInfo colorAttachmentInfoOne, + in ColorAttachmentInfo colorAttachmentInfoTwo, + in ColorAttachmentInfo colorAttachmentInfoThree, + in 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 + ); + +#if DEBUG + renderPassActive = true; + currentSampleCount = colorAttachmentInfoOne.SampleCount; + colorFormatOne = colorAttachmentInfoOne.Texture.Format; + colorFormatTwo = colorAttachmentInfoTwo.Texture.Format; + colorFormatThree = colorAttachmentInfoThree.Texture.Format; + colorFormatFour = colorAttachmentInfoFour.Texture.Format; + depthStencilFormat = depthStencilAttachmentInfo.Texture.Format; +#endif } /// @@ -112,37 +464,134 @@ namespace MoonWorks.Graphics /// The compute pipeline to bind. public void BindComputePipeline( ComputePipeline computePipeline - ) - { + ) { 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( + Buffer buffer + ) { +#if DEBUG + 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 set of buffers to bind. + /// A buffer to bind. + /// A buffer to bind. public unsafe void BindComputeBuffers( - params Buffer[] buffers - ) - { + Buffer bufferOne, + Buffer bufferTwo + ) { #if DEBUG AssertComputePipelineBound(); + AssertComputeBufferCount(2); +#endif - if (currentComputePipeline.ComputeShaderInfo.BufferBindingCount == 0) - { - throw new System.InvalidOperationException("The current compute shader does not take any buffers!"); - } + var bufferPtrs = stackalloc IntPtr[2]; + bufferPtrs[0] = bufferOne.Handle; + bufferPtrs[1] = bufferTwo.Handle; - if (currentComputePipeline.ComputeShaderInfo.BufferBindingCount < buffers.Length) - { - throw new System.InvalidOperationException("Buffer count exceeds the amount used by the current compute shader!"); - } + 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( + Buffer bufferOne, + Buffer bufferTwo, + Buffer bufferThree + ) { +#if DEBUG + 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( + Buffer bufferOne, + Buffer bufferTwo, + Buffer bufferThree, + Buffer bufferFour + ) { +#if DEBUG + 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 + AssertComputePipelineBound(); + AssertComputeBufferCount(buffers.Length); #endif var bufferPtrs = stackalloc IntPtr[buffers.Length]; @@ -159,26 +608,122 @@ namespace MoonWorks.Graphics ); } + /// + /// Binds a texture to be used in the compute shader. + /// + /// A texture to bind. + public unsafe void BindComputeTextures( + Texture texture + ) { +#if DEBUG + AssertComputePipelineBound(); + AssertComputeTextureCount(1); +#endif + + var texturePtrs = stackalloc IntPtr[1]; + texturePtrs[0] = texture.Handle; + + Refresh.Refresh_BindComputeTextures( + Device.Handle, + Handle, + (IntPtr) texturePtrs + ); + } + + /// + /// Binds textures to be used in the compute shader. + /// + /// A texture to bind. + /// A texture to bind. + public unsafe void BindComputeTextures( + Texture textureOne, + Texture textureTwo + ) { +#if DEBUG + AssertComputePipelineBound(); + AssertComputeTextureCount(2); +#endif + + var texturePtrs = stackalloc IntPtr[2]; + texturePtrs[0] = textureOne.Handle; + texturePtrs[1] = textureTwo.Handle; + + Refresh.Refresh_BindComputeTextures( + Device.Handle, + Handle, + (IntPtr) texturePtrs + ); + } + + /// + /// Binds textures to be used in the compute shader. + /// + /// A texture to bind. + /// A texture to bind. + /// A texture to bind. + public unsafe void BindComputeTextures( + Texture textureOne, + Texture textureTwo, + Texture textureThree + ) { +#if DEBUG + AssertComputePipelineBound(); + AssertComputeTextureCount(3); +#endif + + var texturePtrs = stackalloc IntPtr[3]; + texturePtrs[0] = textureOne.Handle; + texturePtrs[1] = textureTwo.Handle; + texturePtrs[2] = textureThree.Handle; + + Refresh.Refresh_BindComputeTextures( + Device.Handle, + Handle, + (IntPtr) texturePtrs + ); + } + + /// + /// Binds textures to be used in the compute shader. + /// + /// A texture to bind. + /// A texture to bind. + /// A texture to bind. + /// A texture to bind. + public unsafe void BindComputeTextures( + Texture textureOne, + Texture textureTwo, + Texture textureThree, + Texture textureFour + ) { +#if DEBUG + AssertComputePipelineBound(); + AssertComputeTextureCount(4); +#endif + + var texturePtrs = stackalloc IntPtr[4]; + texturePtrs[0] = textureOne.Handle; + texturePtrs[1] = textureTwo.Handle; + texturePtrs[2] = textureThree.Handle; + texturePtrs[3] = textureFour.Handle; + + Refresh.Refresh_BindComputeTextures( + Device.Handle, + Handle, + (IntPtr) texturePtrs + ); + } + /// /// Binds textures to be used in the compute shader. /// /// A set of textures to bind. public unsafe void BindComputeTextures( - params Texture[] textures - ) - { + in Span textures + ) { #if DEBUG AssertComputePipelineBound(); - - if (currentComputePipeline.ComputeShaderInfo.ImageBindingCount == 0) - { - throw new System.InvalidOperationException("The current compute shader does not take any textures!"); - } - - if (currentComputePipeline.ComputeShaderInfo.ImageBindingCount < textures.Length) - { - throw new System.InvalidOperationException("Texture count exceeds the amount used by the current compute shader!"); - } + AssertComputeTextureCount(textures.Length); #endif var texturePtrs = stackalloc IntPtr[textures.Length]; @@ -207,8 +752,7 @@ namespace MoonWorks.Graphics uint groupCountY, uint groupCountZ, uint computeParamOffset - ) - { + ) { #if DEBUG AssertComputePipelineBound(); @@ -234,10 +778,10 @@ namespace MoonWorks.Graphics /// The graphics pipeline to bind. public void BindGraphicsPipeline( GraphicsPipeline graphicsPipeline - ) - { + ) { #if DEBUG AssertRenderPassActive(); + AssertRenderPassPipelineFormatMatch(graphicsPipeline); if (graphicsPipeline.SampleCount != currentSampleCount) { @@ -251,13 +795,15 @@ namespace MoonWorks.Graphics graphicsPipeline.Handle ); +#if DEBUG currentGraphicsPipeline = graphicsPipeline; +#endif } /// /// Sets the viewport. Only valid during a render pass. /// - public void SetViewport(Viewport viewport) + public void SetViewport(in Viewport viewport) { #if DEBUG AssertRenderPassActive(); @@ -273,7 +819,7 @@ namespace MoonWorks.Graphics /// /// Sets the scissor area. Only valid during a render pass. /// - public void SetScissor(Rect scissor) + public void SetScissor(in Rect scissor) { #if DEBUG AssertRenderPassActive(); @@ -289,13 +835,139 @@ namespace MoonWorks.Graphics /// /// Binds vertex buffers to be used by subsequent draw calls. /// - /// The index of the first buffer to bind. - /// Buffers to bind and their associated offsets. + /// Buffer to bind and associated offset. + /// The index of the first vertex input binding whose state is updated by the command. public unsafe void BindVertexBuffers( - uint firstBinding, - params BufferBinding[] bufferBindings - ) - { + in BufferBinding bufferBinding, + uint firstBinding = 0 + ) { + var bufferPtrs = stackalloc IntPtr[1]; + var offsets = stackalloc ulong[1]; + + bufferPtrs[0] = bufferBinding.Buffer.Handle; + offsets[0] = bufferBinding.Offset; + + Refresh.Refresh_BindVertexBuffers( + Device.Handle, + Handle, + firstBinding, + 1, + (IntPtr) bufferPtrs, + (IntPtr) offsets + ); + } + + /// + /// Binds vertex buffers to be used by subsequent draw calls. + /// + /// Buffer to bind and associated offset. + /// Buffer to bind and associated offset. + /// The index of the first vertex input binding whose state is updated by the command. + public unsafe void BindVertexBuffers( + in BufferBinding bufferBindingOne, + in BufferBinding bufferBindingTwo, + uint firstBinding = 0 + ) { + var bufferPtrs = stackalloc IntPtr[2]; + var offsets = stackalloc ulong[2]; + + bufferPtrs[0] = bufferBindingOne.Buffer.Handle; + bufferPtrs[1] = bufferBindingTwo.Buffer.Handle; + + offsets[0] = bufferBindingOne.Offset; + offsets[1] = bufferBindingTwo.Offset; + + Refresh.Refresh_BindVertexBuffers( + Device.Handle, + Handle, + firstBinding, + 2, + (IntPtr) bufferPtrs, + (IntPtr) offsets + ); + } + + /// + /// Binds vertex buffers to be used by subsequent draw calls. + /// + /// Buffer to bind and associated offset. + /// Buffer to bind and associated offset. + /// Buffer to bind and associated offset. + /// The index of the first vertex input binding whose state is updated by the command. + public unsafe void BindVertexBuffers( + in BufferBinding bufferBindingOne, + in BufferBinding bufferBindingTwo, + in BufferBinding bufferBindingThree, + uint firstBinding = 0 + ) { + var bufferPtrs = stackalloc IntPtr[3]; + var offsets = stackalloc ulong[3]; + + bufferPtrs[0] = bufferBindingOne.Buffer.Handle; + bufferPtrs[1] = bufferBindingTwo.Buffer.Handle; + bufferPtrs[2] = bufferBindingThree.Buffer.Handle; + + offsets[0] = bufferBindingOne.Offset; + offsets[1] = bufferBindingTwo.Offset; + offsets[2] = bufferBindingThree.Offset; + + Refresh.Refresh_BindVertexBuffers( + Device.Handle, + Handle, + firstBinding, + 3, + (IntPtr) bufferPtrs, + (IntPtr) offsets + ); + } + + /// + /// Binds vertex buffers to be used by subsequent draw calls. + /// + /// Buffer to bind and associated offset. + /// Buffer to bind and associated offset. + /// Buffer to bind and associated offset. + /// Buffer to bind and associated offset. + /// The index of the first vertex input binding whose state is updated by the command. + public unsafe void BindVertexBuffers( + in BufferBinding bufferBindingOne, + in BufferBinding bufferBindingTwo, + in BufferBinding bufferBindingThree, + in BufferBinding bufferBindingFour, + uint firstBinding = 0 + ) { + var bufferPtrs = stackalloc IntPtr[4]; + var offsets = stackalloc ulong[4]; + + bufferPtrs[0] = bufferBindingOne.Buffer.Handle; + bufferPtrs[1] = bufferBindingTwo.Buffer.Handle; + bufferPtrs[2] = bufferBindingThree.Buffer.Handle; + bufferPtrs[3] = bufferBindingFour.Buffer.Handle; + + offsets[0] = bufferBindingOne.Offset; + offsets[1] = bufferBindingTwo.Offset; + offsets[2] = bufferBindingThree.Offset; + offsets[3] = bufferBindingFour.Offset; + + Refresh.Refresh_BindVertexBuffers( + Device.Handle, + Handle, + firstBinding, + 4, + (IntPtr) bufferPtrs, + (IntPtr) offsets + ); + } + + /// + /// Binds vertex buffers to be used by subsequent draw calls. + /// + /// Spawn of buffers to bind and their associated offsets. + /// The index of the first vertex input binding whose state is updated by the command. + public unsafe void BindVertexBuffers( + in Span bufferBindings, + uint firstBinding = 0 + ) { var bufferPtrs = stackalloc IntPtr[bufferBindings.Length]; var offsets = stackalloc ulong[bufferBindings.Length]; @@ -315,33 +987,6 @@ namespace MoonWorks.Graphics ); } - /// - /// Binds vertex buffers to be used by subsequent draw calls. - /// - /// The buffers to bind. - public unsafe void BindVertexBuffers( - params Buffer[] buffers - ) - { - var bufferPtrs = stackalloc IntPtr[buffers.Length]; - var offsets = stackalloc ulong[buffers.Length]; - - for (var i = 0; i < buffers.Length; i += 1) - { - bufferPtrs[i] = buffers[i].Handle; - offsets[i] = 0; - } - - Refresh.Refresh_BindVertexBuffers( - Device.Handle, - Handle, - 0, - (uint) buffers.Length, - (IntPtr) bufferPtrs, - (IntPtr) offsets - ); - } - /// /// Binds an index buffer to be used by subsequent draw calls. /// @@ -366,29 +1011,170 @@ namespace MoonWorks.Graphics /// /// Binds samplers to be used by the vertex shader. /// - /// The texture-sampler pairs to bind. + /// The texture-sampler to bind. public unsafe void BindVertexSamplers( - ArraySegment textureSamplerBindings - ) - { + in TextureSamplerBinding textureSamplerBinding + ) { #if DEBUG AssertGraphicsPipelineBound(); - - if (currentGraphicsPipeline.VertexShaderInfo.SamplerBindingCount == 0) - { - throw new System.InvalidOperationException("The vertex shader of the current graphics pipeline does not take any samplers!"); - } - - if (currentGraphicsPipeline.VertexShaderInfo.SamplerBindingCount < textureSamplerBindings.Count) - { - throw new System.InvalidOperationException("Vertex sampler count exceeds the amount used by the vertex shader!"); - } + AssertVertexSamplerCount(1); + AssertTextureSamplerBindingNonNull(textureSamplerBinding); + AssertTextureBindingUsageFlags(textureSamplerBinding.Texture); #endif - var texturePtrs = stackalloc IntPtr[textureSamplerBindings.Count]; - var samplerPtrs = stackalloc IntPtr[textureSamplerBindings.Count]; + var texturePtrs = stackalloc IntPtr[1]; + var samplerPtrs = stackalloc IntPtr[1]; - for (var i = 0; i < textureSamplerBindings.Count; i += 1) + texturePtrs[0] = textureSamplerBinding.Texture.Handle; + samplerPtrs[0] = textureSamplerBinding.Sampler.Handle; + + Refresh.Refresh_BindVertexSamplers( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) samplerPtrs + ); + } + + /// + /// Binds samplers to be used by the vertex shader. + /// + /// The first texture-sampler to bind. + /// The second texture-sampler to bind. + public unsafe void BindVertexSamplers( + in TextureSamplerBinding textureSamplerBindingOne, + in TextureSamplerBinding textureSamplerBindingTwo + ) { +#if DEBUG + AssertGraphicsPipelineBound(); + AssertVertexSamplerCount(2); + AssertTextureSamplerBindingNonNull(textureSamplerBindingOne); + AssertTextureSamplerBindingNonNull(textureSamplerBindingTwo); + AssertTextureBindingUsageFlags(textureSamplerBindingOne.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingTwo.Texture); +#endif + + var texturePtrs = stackalloc IntPtr[2]; + var samplerPtrs = stackalloc IntPtr[2]; + + texturePtrs[0] = textureSamplerBindingOne.Texture.Handle; + texturePtrs[1] = textureSamplerBindingTwo.Texture.Handle; + + samplerPtrs[0] = textureSamplerBindingOne.Sampler.Handle; + samplerPtrs[1] = textureSamplerBindingTwo.Sampler.Handle; + + Refresh.Refresh_BindVertexSamplers( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) samplerPtrs + ); + } + + /// + /// Binds samplers to be used by the vertex shader. + /// + /// The first texture-sampler to bind. + /// The second texture-sampler to bind. + /// The third texture-sampler to bind. + public unsafe void BindVertexSamplers( + in TextureSamplerBinding textureSamplerBindingOne, + in TextureSamplerBinding textureSamplerBindingTwo, + in TextureSamplerBinding textureSamplerBindingThree + ) { +#if DEBUG + AssertGraphicsPipelineBound(); + AssertVertexSamplerCount(3); + AssertTextureSamplerBindingNonNull(textureSamplerBindingOne); + AssertTextureSamplerBindingNonNull(textureSamplerBindingTwo); + AssertTextureSamplerBindingNonNull(textureSamplerBindingThree); + AssertTextureBindingUsageFlags(textureSamplerBindingOne.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingTwo.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingThree.Texture); +#endif + + var texturePtrs = stackalloc IntPtr[3]; + var samplerPtrs = stackalloc IntPtr[3]; + + texturePtrs[0] = textureSamplerBindingOne.Texture.Handle; + texturePtrs[1] = textureSamplerBindingTwo.Texture.Handle; + texturePtrs[2] = textureSamplerBindingThree.Texture.Handle; + + samplerPtrs[0] = textureSamplerBindingOne.Sampler.Handle; + samplerPtrs[1] = textureSamplerBindingTwo.Sampler.Handle; + samplerPtrs[2] = textureSamplerBindingThree.Sampler.Handle; + + Refresh.Refresh_BindVertexSamplers( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) samplerPtrs + ); + } + + /// + /// Binds samplers to be used by the vertex shader. + /// + /// The first texture-sampler to bind. + /// The second texture-sampler to bind. + /// The third texture-sampler to bind. + /// The fourth texture-sampler to bind. + public unsafe void BindVertexSamplers( + in TextureSamplerBinding textureSamplerBindingOne, + in TextureSamplerBinding textureSamplerBindingTwo, + in TextureSamplerBinding textureSamplerBindingThree, + in TextureSamplerBinding textureSamplerBindingFour + ) { +#if DEBUG + AssertGraphicsPipelineBound(); + AssertVertexSamplerCount(4); + AssertTextureSamplerBindingNonNull(textureSamplerBindingOne); + AssertTextureSamplerBindingNonNull(textureSamplerBindingTwo); + AssertTextureSamplerBindingNonNull(textureSamplerBindingThree); + AssertTextureSamplerBindingNonNull(textureSamplerBindingFour); + AssertTextureBindingUsageFlags(textureSamplerBindingOne.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingTwo.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingThree.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingFour.Texture); +#endif + + var texturePtrs = stackalloc IntPtr[4]; + var samplerPtrs = stackalloc IntPtr[4]; + + texturePtrs[0] = textureSamplerBindingOne.Texture.Handle; + texturePtrs[1] = textureSamplerBindingTwo.Texture.Handle; + texturePtrs[2] = textureSamplerBindingThree.Texture.Handle; + texturePtrs[3] = textureSamplerBindingFour.Texture.Handle; + + samplerPtrs[0] = textureSamplerBindingOne.Sampler.Handle; + samplerPtrs[1] = textureSamplerBindingTwo.Sampler.Handle; + samplerPtrs[2] = textureSamplerBindingThree.Sampler.Handle; + samplerPtrs[3] = textureSamplerBindingFour.Sampler.Handle; + + Refresh.Refresh_BindVertexSamplers( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) samplerPtrs + ); + } + + /// + /// Binds samplers to be used by the vertex shader. + /// + /// The texture-sampler pairs to bind. + public unsafe void BindVertexSamplers( + in Span textureSamplerBindings + ) { +#if DEBUG + AssertGraphicsPipelineBound(); + AssertVertexSamplerCount(textureSamplerBindings.Length); +#endif + + var texturePtrs = stackalloc IntPtr[textureSamplerBindings.Length]; + var samplerPtrs = stackalloc IntPtr[textureSamplerBindings.Length]; + + for (var i = 0; i < textureSamplerBindings.Length; i += 1) { #if DEBUG AssertTextureSamplerBindingNonNull(textureSamplerBindings[i]); @@ -408,42 +1194,172 @@ namespace MoonWorks.Graphics } /// - /// Binds samplers to be used by the vertex shader. + /// Binds samplers to be used by the fragment shader. /// - /// The texture-sampler pairs to bind. - public unsafe void BindVertexSamplers( - params TextureSamplerBinding[] textureSamplerBindings - ) - { - BindVertexSamplers(new ArraySegment(textureSamplerBindings)); + /// The texture-sampler to bind. + public unsafe void BindFragmentSamplers( + in TextureSamplerBinding textureSamplerBinding + ) { +#if DEBUG + AssertGraphicsPipelineBound(); + AssertFragmentSamplerCount(1); + AssertTextureSamplerBindingNonNull(textureSamplerBinding); + AssertTextureBindingUsageFlags(textureSamplerBinding.Texture); +#endif + + var texturePtrs = stackalloc IntPtr[1]; + var samplerPtrs = stackalloc IntPtr[1]; + + texturePtrs[0] = textureSamplerBinding.Texture.Handle; + samplerPtrs[0] = textureSamplerBinding.Sampler.Handle; + + Refresh.Refresh_BindFragmentSamplers( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) samplerPtrs + ); } /// - /// Binds samplers to be used by the vertex shader. + /// Binds samplers to be used by the fragment shader. + /// + /// The first texture-sampler to bind. + /// The second texture-sampler to bind. + public unsafe void BindFragmentSamplers( + in TextureSamplerBinding textureSamplerBindingOne, + in TextureSamplerBinding textureSamplerBindingTwo + ) { +#if DEBUG + AssertGraphicsPipelineBound(); + AssertFragmentSamplerCount(2); + AssertTextureSamplerBindingNonNull(textureSamplerBindingOne); + AssertTextureSamplerBindingNonNull(textureSamplerBindingTwo); + AssertTextureBindingUsageFlags(textureSamplerBindingOne.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingTwo.Texture); +#endif + + var texturePtrs = stackalloc IntPtr[2]; + var samplerPtrs = stackalloc IntPtr[2]; + + texturePtrs[0] = textureSamplerBindingOne.Texture.Handle; + texturePtrs[1] = textureSamplerBindingTwo.Texture.Handle; + + samplerPtrs[0] = textureSamplerBindingOne.Sampler.Handle; + samplerPtrs[1] = textureSamplerBindingTwo.Sampler.Handle; + + Refresh.Refresh_BindFragmentSamplers( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) samplerPtrs + ); + } + + /// + /// Binds samplers to be used by the fragment shader. + /// + /// The first texture-sampler to bind. + /// The second texture-sampler to bind. + /// The third texture-sampler to bind. + public unsafe void BindFragmentSamplers( + in TextureSamplerBinding textureSamplerBindingOne, + in TextureSamplerBinding textureSamplerBindingTwo, + in TextureSamplerBinding textureSamplerBindingThree + ) { +#if DEBUG + AssertGraphicsPipelineBound(); + AssertFragmentSamplerCount(3); + AssertTextureSamplerBindingNonNull(textureSamplerBindingOne); + AssertTextureSamplerBindingNonNull(textureSamplerBindingTwo); + AssertTextureSamplerBindingNonNull(textureSamplerBindingThree); + AssertTextureBindingUsageFlags(textureSamplerBindingOne.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingTwo.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingThree.Texture); +#endif + + var texturePtrs = stackalloc IntPtr[3]; + var samplerPtrs = stackalloc IntPtr[3]; + + texturePtrs[0] = textureSamplerBindingOne.Texture.Handle; + texturePtrs[1] = textureSamplerBindingTwo.Texture.Handle; + texturePtrs[2] = textureSamplerBindingThree.Texture.Handle; + + samplerPtrs[0] = textureSamplerBindingOne.Sampler.Handle; + samplerPtrs[1] = textureSamplerBindingTwo.Sampler.Handle; + samplerPtrs[2] = textureSamplerBindingThree.Sampler.Handle; + + Refresh.Refresh_BindFragmentSamplers( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) samplerPtrs + ); + } + + /// + /// Binds samplers to be used by the fragment shader. + /// + /// The first texture-sampler to bind. + /// The second texture-sampler to bind. + /// The third texture-sampler to bind. + /// The fourth texture-sampler to bind. + public unsafe void BindFragmentSamplers( + in TextureSamplerBinding textureSamplerBindingOne, + in TextureSamplerBinding textureSamplerBindingTwo, + in TextureSamplerBinding textureSamplerBindingThree, + in TextureSamplerBinding textureSamplerBindingFour + ) { +#if DEBUG + AssertGraphicsPipelineBound(); + AssertFragmentSamplerCount(4); + AssertTextureSamplerBindingNonNull(textureSamplerBindingOne); + AssertTextureSamplerBindingNonNull(textureSamplerBindingTwo); + AssertTextureSamplerBindingNonNull(textureSamplerBindingThree); + AssertTextureSamplerBindingNonNull(textureSamplerBindingFour); + AssertTextureBindingUsageFlags(textureSamplerBindingOne.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingTwo.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingThree.Texture); + AssertTextureBindingUsageFlags(textureSamplerBindingFour.Texture); +#endif + + var texturePtrs = stackalloc IntPtr[4]; + var samplerPtrs = stackalloc IntPtr[4]; + + texturePtrs[0] = textureSamplerBindingOne.Texture.Handle; + texturePtrs[1] = textureSamplerBindingTwo.Texture.Handle; + texturePtrs[2] = textureSamplerBindingThree.Texture.Handle; + texturePtrs[3] = textureSamplerBindingFour.Texture.Handle; + + samplerPtrs[0] = textureSamplerBindingOne.Sampler.Handle; + samplerPtrs[1] = textureSamplerBindingTwo.Sampler.Handle; + samplerPtrs[2] = textureSamplerBindingThree.Sampler.Handle; + samplerPtrs[3] = textureSamplerBindingFour.Sampler.Handle; + + Refresh.Refresh_BindFragmentSamplers( + Device.Handle, + Handle, + (IntPtr) texturePtrs, + (IntPtr) samplerPtrs + ); + } + + /// + /// Binds samplers to be used by the fragment shader. /// /// The texture-sampler pairs to bind. public unsafe void BindFragmentSamplers( - ArraySegment textureSamplerBindings - ) - { + in Span textureSamplerBindings + ) { #if DEBUG AssertGraphicsPipelineBound(); - - if (currentGraphicsPipeline.FragmentShaderInfo.SamplerBindingCount == 0) - { - throw new System.InvalidOperationException("The fragment shader of the current graphics pipeline does not take any samplers!"); - } - - if (currentGraphicsPipeline.FragmentShaderInfo.SamplerBindingCount < textureSamplerBindings.Count) - { - throw new System.InvalidOperationException("Fragment sampler count exceeds the amount used by the fragment shader!"); - } + AssertFragmentSamplerCount(textureSamplerBindings.Length); #endif - var texturePtrs = stackalloc IntPtr[textureSamplerBindings.Count]; - var samplerPtrs = stackalloc IntPtr[textureSamplerBindings.Count]; + var texturePtrs = stackalloc IntPtr[textureSamplerBindings.Length]; + var samplerPtrs = stackalloc IntPtr[textureSamplerBindings.Length]; - for (var i = 0; i < textureSamplerBindings.Count; i += 1) + for (var i = 0; i < textureSamplerBindings.Length; i += 1) { #if DEBUG AssertTextureSamplerBindingNonNull(textureSamplerBindings[i]); @@ -462,23 +1378,12 @@ namespace MoonWorks.Graphics ); } - /// - /// Binds samplers to be used by the fragment shader. - /// - /// An array of texture-sampler pairs to bind. - public unsafe void BindFragmentSamplers( - params TextureSamplerBinding[] textureSamplerBindings - ) - { - BindFragmentSamplers(new ArraySegment(textureSamplerBindings)); - } - /// /// Pushes vertex shader uniforms to the device. /// /// A starting offset value to be used with draw calls. public unsafe uint PushVertexShaderUniforms( - params T[] uniforms + in T uniforms ) where T : unmanaged { #if DEBUG @@ -490,13 +1395,13 @@ namespace MoonWorks.Graphics } #endif - fixed (T* ptr = &uniforms[0]) + fixed (T* uniformsPtr = &uniforms) { return Refresh.Refresh_PushVertexShaderUniforms( Device.Handle, Handle, - (IntPtr) ptr, - (uint) (uniforms.Length * sizeof(T)) + (IntPtr) uniformsPtr, + (uint) sizeof(T) ); } } @@ -506,7 +1411,7 @@ namespace MoonWorks.Graphics /// /// A starting offset to be used with draw calls. public unsafe uint PushFragmentShaderUniforms( - params T[] uniforms + in T uniforms ) where T : unmanaged { #if DEBUG @@ -517,14 +1422,13 @@ namespace MoonWorks.Graphics throw new InvalidOperationException("The current fragment shader does not take a uniform buffer!"); } #endif - - fixed (T* ptr = &uniforms[0]) + fixed (T* uniformsPtr = &uniforms) { return Refresh.Refresh_PushFragmentShaderUniforms( Device.Handle, Handle, - (IntPtr) ptr, - (uint) (uniforms.Length * sizeof(T)) + (IntPtr) uniformsPtr, + (uint) sizeof(T) ); } } @@ -534,7 +1438,7 @@ namespace MoonWorks.Graphics /// /// A starting offset to be used with dispatch calls. public unsafe uint PushComputeShaderUniforms( - params T[] uniforms + in T uniforms ) where T : unmanaged { #if DEBUG @@ -546,13 +1450,13 @@ namespace MoonWorks.Graphics } #endif - fixed (T* ptr = &uniforms[0]) + fixed (T* uniformsPtr = &uniforms) { return Refresh.Refresh_PushComputeShaderUniforms( Device.Handle, Handle, - (IntPtr) ptr, - (uint) (uniforms.Length * sizeof(T)) + (IntPtr) uniformsPtr, + (uint) sizeof(T) ); } } @@ -696,8 +1600,10 @@ namespace MoonWorks.Graphics Handle ); +#if DEBUG currentGraphicsPipeline = null; renderPassActive = false; +#endif } /// @@ -707,7 +1613,7 @@ namespace MoonWorks.Graphics /// 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. /// - public Texture? AcquireSwapchainTexture( + public Texture AcquireSwapchainTexture( Window window ) { @@ -1011,6 +1917,58 @@ namespace MoonWorks.Graphics } } + private void AssertRenderPassPipelineFormatMatch(GraphicsPipeline graphicsPipeline) + { + for (var i = 0; i < graphicsPipeline.AttachmentInfo.ColorAttachmentDescriptions.Length; i += 1) + { + TextureFormat format; + if (i == 0) + { + format = colorFormatOne; + } + else if (i == 1) + { + format = colorFormatTwo; + } + else if (i == 2) + { + format = colorFormatThree; + } + else + { + format = colorFormatFour; + } + + var pipelineFormat = graphicsPipeline.AttachmentInfo.ColorAttachmentDescriptions[i].Format; + if (pipelineFormat != format) + { + throw new System.InvalidOperationException($"Color texture format mismatch! Pipeline expects {pipelineFormat}, render pass attachment is {format}"); + } + } + + var pipelineDepthFormat = graphicsPipeline.AttachmentInfo.DepthStencilFormat; + if (pipelineDepthFormat != depthStencilFormat) + { + throw new System.InvalidOperationException($"Depth texture format mismatch! Pipeline expects {pipelineDepthFormat}, render pass attachment is {depthStencilFormat}"); + } + } + + private void AssertVertexSamplerCount(int count) + { + if (currentGraphicsPipeline.VertexShaderInfo.SamplerBindingCount != count) + { + throw new System.InvalidOperationException($"Vertex sampler expected {currentGraphicsPipeline.VertexShaderInfo.SamplerBindingCount} samplers, but received {count}"); + } + } + + private void AssertFragmentSamplerCount(int count) + { + if (currentGraphicsPipeline.FragmentShaderInfo.SamplerBindingCount != count) + { + throw new System.InvalidOperationException($"Fragment sampler expected {currentGraphicsPipeline.FragmentShaderInfo.SamplerBindingCount} samplers, but received {count}"); + } + } + private void AssertComputePipelineBound(string message = "No compute pipeline is bound!") { if (currentComputePipeline == null) @@ -1019,37 +1977,43 @@ namespace MoonWorks.Graphics } } - private void AssertValidColorAttachments(ColorAttachmentInfo[] colorAttachmentInfos, bool atLeastOneRequired) + private void AssertComputeBufferCount(int count) { - if (atLeastOneRequired && colorAttachmentInfos.Length == 0) + if (currentComputePipeline.ComputeShaderInfo.BufferBindingCount != count) { - throw new System.ArgumentException("Render pass must contain at least one attachment!"); + throw new System.InvalidOperationException($"Compute pipeline expects {currentComputePipeline.ComputeShaderInfo.BufferBindingCount} buffers, but received {count}"); } + } - currentSampleCount = (colorAttachmentInfos.Length > 0) ? colorAttachmentInfos[0].SampleCount : SampleCount.One; - - if (colorAttachmentInfos.Length > 4) + private void AssertComputeTextureCount(int count) + { + if (currentComputePipeline.ComputeShaderInfo.ImageBindingCount != count) { - throw new System.ArgumentException("Render pass cannot have more than 4 color attachments!"); + throw new System.InvalidOperationException($"Compute pipeline expects {currentComputePipeline.ComputeShaderInfo.ImageBindingCount} textures, but received {count}"); } + } - for (int i = 0; i < colorAttachmentInfos.Length; i += 1) + private void AssertTextureNotNull(ColorAttachmentInfo colorAttachmentInfo) + { + if (colorAttachmentInfo.Texture == null || colorAttachmentInfo.Texture.Handle == IntPtr.Zero) { - if (colorAttachmentInfos[i].Texture == null || - colorAttachmentInfos[i].Texture.Handle == IntPtr.Zero) - { - throw new System.ArgumentException("Render pass color attachment Texture cannot be null!"); - } + 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!"); - } + private void AssertColorTarget(ColorAttachmentInfo colorAttachmentInfo) + { + if ((colorAttachmentInfo.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!"); - } + private void AssertSameSampleCount(ColorAttachmentInfo a, ColorAttachmentInfo b) + { + if (a.SampleCount != b.SampleCount) + { + throw new System.ArgumentException("All color attachments in a render pass must have the same SampleCount!"); } } diff --git a/src/Graphics/Resources/Buffer.cs b/src/Graphics/Resources/Buffer.cs index bd737db..24047aa 100644 --- a/src/Graphics/Resources/Buffer.cs +++ b/src/Graphics/Resources/Buffer.cs @@ -1,5 +1,4 @@ using System; -using System.Runtime.InteropServices; using RefreshCS; namespace MoonWorks.Graphics @@ -78,5 +77,10 @@ namespace MoonWorks.Graphics ); } } + + public static implicit operator BufferBinding(Buffer b) + { + return new BufferBinding(b, 0); + } } } diff --git a/src/Graphics/Resources/GraphicsPipeline.cs b/src/Graphics/Resources/GraphicsPipeline.cs index ccf88cd..eb992ae 100644 --- a/src/Graphics/Resources/GraphicsPipeline.cs +++ b/src/Graphics/Resources/GraphicsPipeline.cs @@ -14,7 +14,11 @@ namespace MoonWorks.Graphics public GraphicsShaderInfo VertexShaderInfo { get; } public GraphicsShaderInfo FragmentShaderInfo { get; } - internal SampleCount SampleCount { get; } + public SampleCount SampleCount { get; } + +#if DEBUG + internal GraphicsPipelineAttachmentInfo AttachmentInfo { get; } +#endif public unsafe GraphicsPipeline( GraphicsDevice device, @@ -113,6 +117,10 @@ namespace MoonWorks.Graphics VertexShaderInfo = vertexShaderInfo; FragmentShaderInfo = fragmentShaderInfo; SampleCount = multisampleState.MultisampleCount; + +#if DEBUG + AttachmentInfo = attachmentInfo; +#endif } } }