diff --git a/lib/RefreshCS b/lib/RefreshCS index 1e8abe37..cb949b82 160000 --- a/lib/RefreshCS +++ b/lib/RefreshCS @@ -1 +1 @@ -Subproject commit 1e8abe379a0ccc891ce0f4d90793feac59d30948 +Subproject commit cb949b8205eb2454dd0c9f4c84d41c6647802408 diff --git a/src/Graphics/CommandBuffer.cs b/src/Graphics/CommandBuffer.cs index 3d80531b..b424c104 100644 --- a/src/Graphics/CommandBuffer.cs +++ b/src/Graphics/CommandBuffer.cs @@ -27,169 +27,187 @@ namespace MoonWorks.Graphics /// 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 render pass object to begin. - /// The framebuffer used by the render pass. + /// The color attachments to use in the render pass. public unsafe void BeginRenderPass( - RenderPass renderPass, - Framebuffer framebuffer + params ColorAttachmentInfo[] colorAttachmentInfos ) { - var renderArea = new Rect +#if DEBUG + if (colorAttachmentInfos.Length == 0) { - X = 0, - Y = 0, - W = (int) framebuffer.Width, - H = (int) framebuffer.Height - }; - - Refresh.Refresh_BeginRenderPass( - Device.Handle, - Handle, - renderPass.Handle, - framebuffer.Handle, - renderArea.ToRefresh(), - IntPtr.Zero, - 0, - IntPtr.Zero - ); - } - - /// - /// 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 render pass object to begin. - /// The framebuffer used by the render pass. - /// The screen area of the render pass. - public unsafe void BeginRenderPass( - RenderPass renderPass, - Framebuffer framebuffer, - in Rect renderArea - ) - { - Refresh.Refresh_BeginRenderPass( - Device.Handle, - Handle, - renderPass.Handle, - framebuffer.Handle, - renderArea.ToRefresh(), - IntPtr.Zero, - 0, - IntPtr.Zero - ); - } - - /// - /// 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 render pass object to begin. - /// The framebuffer used by the render pass. - /// The screen area of the render pass. - /// Color clear values for each render target in the framebuffer. - public unsafe void BeginRenderPass( - RenderPass renderPass, - Framebuffer framebuffer, - in Rect renderArea, - params Vector4[] clearColors - ) - { - Refresh.Vec4* colors = stackalloc Refresh.Vec4[clearColors.Length]; - - for (var i = 0; i < clearColors.Length; i++) - { - colors[i] = new Refresh.Vec4 - { - x = clearColors[i].X, - y = clearColors[i].Y, - z = clearColors[i].Z, - w = clearColors[i].W - }; + Logger.LogError("Render pass must contain at least one attachment!"); + return; } - Refresh.Refresh_BeginRenderPass( - Device.Handle, - Handle, - renderPass.Handle, - framebuffer.Handle, - renderArea.ToRefresh(), - (IntPtr) colors, - (uint) clearColors.Length, - IntPtr.Zero - ); - } - - /// - /// 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 render pass object to begin. - /// The framebuffer used by the render pass. - /// The screen area of the render pass. - /// Clear values for the depth/stencil buffer. This is ignored if the render pass does not clear. - public unsafe void BeginRenderPass( - RenderPass renderPass, - Framebuffer framebuffer, - in Rect renderArea, - in DepthStencilValue depthStencilClearValue - ) - { - Refresh.Refresh_BeginRenderPass( - Device.Handle, - Handle, - renderPass.Handle, - framebuffer.Handle, - renderArea.ToRefresh(), - IntPtr.Zero, - 0, - depthStencilClearValue.ToRefresh() - ); - } - - /// - /// 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 render pass object to begin. - /// The framebuffer used by the render pass. - /// The screen area of the render pass. - /// Clear values for the depth/stencil buffer. This is ignored if the render pass does not clear. - /// Color clear values for each render target in the framebuffer. - public unsafe void BeginRenderPass( - RenderPass renderPass, - Framebuffer framebuffer, - in Rect renderArea, - in DepthStencilValue depthStencilClearValue, - params Vector4[] clearColors - ) - { - Refresh.Vec4* colors = stackalloc Refresh.Vec4[clearColors.Length]; - - for (var i = 0; i < clearColors.Length; i++) + if (colorAttachmentInfos.Length > 4) { - colors[i] = new Refresh.Vec4 - { - x = clearColors[i].X, - y = clearColors[i].Y, - z = clearColors[i].Z, - w = clearColors[i].W - }; + Logger.LogError("Render pass cannot have more than 4 color attachments!"); + return; + } +#endif + + var refreshColorAttachmentInfos = new Refresh.ColorAttachmentInfo[colorAttachmentInfos.Length]; + + for (var i = 0; i < colorAttachmentInfos.Length; i += 1) + { + refreshColorAttachmentInfos[i] = colorAttachmentInfos[i].ToRefresh(); } - Refresh.Refresh_BeginRenderPass( - Device.Handle, - Handle, - renderPass.Handle, - framebuffer.Handle, - renderArea.ToRefresh(), - (IntPtr) colors, - (uint) clearColors.Length, - depthStencilClearValue.ToRefresh() - ); + fixed (Refresh.ColorAttachmentInfo* pColorAttachmentInfos = refreshColorAttachmentInfos) + { + Refresh.Refresh_BeginRenderPass( + Device.Handle, + Handle, + colorAttachmentInfos[0].renderTarget.TextureSlice.Rectangle.ToRefresh(), + (IntPtr) pColorAttachmentInfos, + (uint) colorAttachmentInfos.Length, + IntPtr.Zero + ); + } + } + + /// + /// 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 attachments to use in the render pass. + public unsafe void BeginRenderPass( + DepthStencilAttachmentInfo depthStencilAttachmentInfo, + params ColorAttachmentInfo[] colorAttachmentInfos + ) + { +#if DEBUG + if (colorAttachmentInfos.Length == 0) + { + Logger.LogError("Render pass must contain at least one attachment!"); + return; + } + + if (colorAttachmentInfos.Length > 4) + { + Logger.LogError("Render pass cannot have more than 4 color attachments!"); + return; + } +#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, + colorAttachmentInfos[0].renderTarget.TextureSlice.Rectangle.ToRefresh(), + pColorAttachmentInfos, + (uint) colorAttachmentInfos.Length, + &refreshDepthStencilAttachmentInfo + ); + } + } + + /// + /// 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 rectangle that should be drawn to on the attachments. + /// The color attachments to use in the render pass. + public unsafe void BeginRenderPass( + in Rect renderArea, + params ColorAttachmentInfo[] colorAttachmentInfos + ) + { +#if DEBUG + if (colorAttachmentInfos.Length == 0) + { + Logger.LogError("Render pass must contain at least one attachment!"); + return; + } + + if (colorAttachmentInfos.Length > 4) + { + Logger.LogError("Render pass cannot have more than 4 color attachments!"); + return; + } +#endif + + var refreshColorAttachmentInfos = new Refresh.ColorAttachmentInfo[colorAttachmentInfos.Length]; + + 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, + renderArea.ToRefresh(), + (IntPtr) pColorAttachmentInfos, + (uint) colorAttachmentInfos.Length, + IntPtr.Zero + ); + } + } + + /// + /// 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 rectangle that should be drawn to on the attachments. + /// The depth stencil attachment to use in the render pass. + /// The color attachments to use in the render pass. + public unsafe void BeginRenderPass( + in Rect renderArea, + DepthStencilAttachmentInfo depthStencilAttachmentInfo, + params ColorAttachmentInfo[] colorAttachmentInfos + ) + { +#if DEBUG + if (colorAttachmentInfos.Length == 0) + { + Logger.LogError("Render pass must contain at least one attachment!"); + return; + } + + if (colorAttachmentInfos.Length > 4) + { + Logger.LogError("Render pass cannot have more than 4 color attachments!"); + return; + } +#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, + renderArea.ToRefresh(), + pColorAttachmentInfos, + (uint) colorAttachmentInfos.Length, + &refreshDepthStencilAttachmentInfo + ); + } } /// diff --git a/src/Graphics/RefreshStructs.cs b/src/Graphics/RefreshStructs.cs index 890bff1a..e1ab2a98 100644 --- a/src/Graphics/RefreshStructs.cs +++ b/src/Graphics/RefreshStructs.cs @@ -72,25 +72,6 @@ namespace MoonWorks.Graphics public uint Offset; } - [StructLayout(LayoutKind.Sequential)] - public struct ColorTargetDescription - { - public TextureFormat Format; - public SampleCount MultisampleCount; - public LoadOp LoadOp; - public StoreOp StoreOp; - } - - [StructLayout(LayoutKind.Sequential)] - public struct DepthStencilTargetDescription - { - public TextureFormat Format; - public LoadOp LoadOp; - public StoreOp StoreOp; - public LoadOp StencilLoadOp; - public StoreOp StencilStoreOp; - } - [StructLayout(LayoutKind.Sequential)] public struct StencilOpState { @@ -117,4 +98,61 @@ namespace MoonWorks.Graphics }; } } + + [StructLayout(LayoutKind.Sequential)] + public struct ColorAttachmentInfo + { + public RenderTarget renderTarget; + public Color clearColor; + public LoadOp loadOp; + public StoreOp storeOp; + + public Refresh.ColorAttachmentInfo ToRefresh() + { + return new Refresh.ColorAttachmentInfo + { + renderTarget = renderTarget.Handle, + clearColor = new Refresh.Vec4 + { + x = clearColor.R, + y = clearColor.G, + z = clearColor.B, + w = clearColor.A + }, + loadOp = (Refresh.LoadOp) loadOp, + storeOp = (Refresh.StoreOp) storeOp + }; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct DepthStencilAttachmentInfo + { + public RenderTarget depthStencilTarget; + public DepthStencilValue depthStencilValue; + public LoadOp loadOp; + public StoreOp storeOp; + public LoadOp stencilLoadOp; + public StoreOp stencilStoreOp; + + public Refresh.DepthStencilAttachmentInfo ToRefresh() + { + return new Refresh.DepthStencilAttachmentInfo + { + depthStencilTarget = depthStencilTarget.Handle, + depthStencilValue = depthStencilValue.ToRefresh(), + loadOp = (Refresh.LoadOp) loadOp, + storeOp = (Refresh.StoreOp) storeOp, + stencilLoadOp = (Refresh.LoadOp) stencilLoadOp, + stencilStoreOp = (Refresh.StoreOp) stencilStoreOp + }; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct ColorAttachmentDescription + { + public TextureFormat format; + public SampleCount sampleCount; + } } diff --git a/src/Graphics/Resources/Framebuffer.cs b/src/Graphics/Resources/Framebuffer.cs deleted file mode 100644 index 223ee9ca..00000000 --- a/src/Graphics/Resources/Framebuffer.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections.Generic; -using RefreshCS; - -namespace MoonWorks.Graphics -{ - /// - /// A framebuffer is a collection of render targets that is rendered to during a render pass. - /// - public class Framebuffer : GraphicsResource - { - protected override Action QueueDestroyFunction => Refresh.Refresh_QueueDestroyFramebuffer; - - public RenderTarget DepthStencilTarget { get; } - - private RenderTarget[] colorTargets { get; } - public IEnumerable ColorTargets => colorTargets; - - public RenderPass RenderPass { get; } - public uint Width { get; } - public uint Height { get; } - - /// - /// Creates a framebuffer. - /// - /// An initialized GraphicsDevice. - /// The width of the framebuffer. - /// The height of the framebuffer. - /// The reference render pass for the framebuffer. - /// The depth stencil target. Can be null. - /// Anywhere from 0-4 color targets can be provided. - public unsafe Framebuffer( - GraphicsDevice device, - uint width, - uint height, - RenderPass renderPass, - RenderTarget depthStencilTarget, - params RenderTarget[] colorTargets - ) : base(device) - { - IntPtr[] colorTargetHandles = new IntPtr[colorTargets.Length]; - for (var i = 0; i < colorTargets.Length; i += 1) - { - colorTargetHandles[i] = colorTargets[i].Handle; - } - - IntPtr depthStencilTargetHandle; - if (depthStencilTarget == null) - { - depthStencilTargetHandle = IntPtr.Zero; - } - else - { - depthStencilTargetHandle = depthStencilTarget.Handle; - } - - fixed (IntPtr* colorTargetHandlesPtr = colorTargetHandles) - { - Refresh.FramebufferCreateInfo framebufferCreateInfo = new Refresh.FramebufferCreateInfo - { - width = width, - height = height, - colorTargetCount = (uint) colorTargets.Length, - pColorTargets = (IntPtr) colorTargetHandlesPtr, - depthStencilTarget = depthStencilTargetHandle, - renderPass = renderPass.Handle - }; - - Handle = Refresh.Refresh_CreateFramebuffer(device.Handle, framebufferCreateInfo); - } - - DepthStencilTarget = depthStencilTarget; - - this.colorTargets = new RenderTarget[colorTargets.Length]; - for (var i = 0; i < colorTargets.Length; i++) - { - this.colorTargets[i] = colorTargets[i]; - } - - RenderPass = renderPass; - - Width = width; - Height = height; - } - } -} diff --git a/src/Graphics/Resources/GraphicsPipeline.cs b/src/Graphics/Resources/GraphicsPipeline.cs index af0d67e0..e293229f 100644 --- a/src/Graphics/Resources/GraphicsPipeline.cs +++ b/src/Graphics/Resources/GraphicsPipeline.cs @@ -14,7 +14,6 @@ namespace MoonWorks.Graphics public ShaderStageState VertexShaderState { get; } public ShaderStageState FragmentShaderState { get; } - public RenderPass RenderPass { get; } public unsafe GraphicsPipeline( GraphicsDevice device, @@ -31,7 +30,7 @@ namespace MoonWorks.Graphics PrimitiveType primitiveType = graphicsPipelineCreateInfo.PrimitiveType; VertexInputState vertexInputState = graphicsPipelineCreateInfo.VertexInputState; ViewportState viewportState = graphicsPipelineCreateInfo.ViewportState; - RenderPass renderPass = graphicsPipelineCreateInfo.RenderPass; + GraphicsPipelineAttachmentInfo attachmentInfo = graphicsPipelineCreateInfo.AttachmentInfo; var vertexAttributesHandle = GCHandle.Alloc( vertexInputState.VertexAttributes, @@ -59,6 +58,16 @@ namespace MoonWorks.Graphics colorTargetBlendStates[i] = colorBlendState.ColorTargetBlendStates[i].ToRefreshColorTargetBlendState(); } + var colorAttachmentDescriptions = stackalloc Refresh.ColorAttachmentDescription[ + (int) attachmentInfo.colorAttachmentCount + ]; + + for (var i = 0; i < attachmentInfo.colorAttachmentCount; i += 1) + { + colorAttachmentDescriptions[i].format = (Refresh.TextureFormat) attachmentInfo.colorAttachmentDescriptions[i].format; + colorAttachmentDescriptions[i].sampleCount = (Refresh.SampleCount) attachmentInfo.colorAttachmentDescriptions[i].sampleCount; + } + Refresh.GraphicsPipelineCreateInfo refreshGraphicsPipelineCreateInfo; refreshGraphicsPipelineCreateInfo.colorBlendState.logicOpEnable = Conversions.BoolToByte(colorBlendState.LogicOpEnable); @@ -115,7 +124,11 @@ namespace MoonWorks.Graphics refreshGraphicsPipelineCreateInfo.viewportState.scissorCount = (uint) viewportState.Scissors.Length; refreshGraphicsPipelineCreateInfo.primitiveType = (Refresh.PrimitiveType) primitiveType; - refreshGraphicsPipelineCreateInfo.renderPass = renderPass.Handle; + + refreshGraphicsPipelineCreateInfo.attachmentInfo.colorAttachmentCount = attachmentInfo.colorAttachmentCount; + refreshGraphicsPipelineCreateInfo.attachmentInfo.colorAttachmentDescriptions = (IntPtr) colorAttachmentDescriptions; + refreshGraphicsPipelineCreateInfo.attachmentInfo.depthStencilFormat = (Refresh.TextureFormat) attachmentInfo.depthStencilFormat; + refreshGraphicsPipelineCreateInfo.attachmentInfo.hasDepthStencilAttachment = Conversions.BoolToByte(attachmentInfo.hasDepthStencilAttachment); Handle = Refresh.Refresh_CreateGraphicsPipeline(device.Handle, refreshGraphicsPipelineCreateInfo); @@ -126,7 +139,6 @@ namespace MoonWorks.Graphics VertexShaderState = vertexShaderState; FragmentShaderState = fragmentShaderState; - RenderPass = renderPass; } } } diff --git a/src/Graphics/Resources/RenderPass.cs b/src/Graphics/Resources/RenderPass.cs deleted file mode 100644 index 37cebef3..00000000 --- a/src/Graphics/Resources/RenderPass.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using RefreshCS; - -namespace MoonWorks.Graphics -{ - /// - /// A render pass describes the kind of render targets that will be used in rendering. - /// - public class RenderPass : GraphicsResource - { - protected override Action QueueDestroyFunction => Refresh.Refresh_QueueDestroyRenderPass; - - /// - /// Creates a render pass using color target descriptions. - /// - /// An initialized GraphicsDevice. - /// Up to 4 color target descriptions may be provided. - public unsafe RenderPass( - GraphicsDevice device, - params ColorTargetDescription[] colorTargetDescriptions - ) : base(device) - { - fixed (ColorTargetDescription* ptr = colorTargetDescriptions) - { - Refresh.RenderPassCreateInfo renderPassCreateInfo; - renderPassCreateInfo.colorTargetCount = (uint) colorTargetDescriptions.Length; - renderPassCreateInfo.colorTargetDescriptions = (IntPtr) ptr; - renderPassCreateInfo.depthStencilTargetDescription = IntPtr.Zero; - - Handle = Refresh.Refresh_CreateRenderPass(device.Handle, renderPassCreateInfo); - } - } - - /// - /// Creates a render pass using a depth/stencil target description and optional color target descriptions. - /// - /// An initialized GraphicsDevice. - /// A depth/stencil target description. - /// Up to 4 color target descriptions may be provided. - public unsafe RenderPass( - GraphicsDevice device, - in DepthStencilTargetDescription depthStencilTargetDescription, - params ColorTargetDescription[] colorTargetDescriptions - ) : base(device) - { - - fixed (DepthStencilTargetDescription* depthStencilPtr = &depthStencilTargetDescription) - fixed (ColorTargetDescription* colorPtr = colorTargetDescriptions) - { - Refresh.RenderPassCreateInfo renderPassCreateInfo; - renderPassCreateInfo.colorTargetCount = (uint) colorTargetDescriptions.Length; - renderPassCreateInfo.colorTargetDescriptions = (IntPtr) colorPtr; - renderPassCreateInfo.depthStencilTargetDescription = (IntPtr) depthStencilPtr; - - Handle = Refresh.Refresh_CreateRenderPass(device.Handle, renderPassCreateInfo); - } - } - } -} diff --git a/src/Graphics/Resources/RenderTarget.cs b/src/Graphics/Resources/RenderTarget.cs index ca84c1ad..06964c16 100644 --- a/src/Graphics/Resources/RenderTarget.cs +++ b/src/Graphics/Resources/RenderTarget.cs @@ -11,6 +11,9 @@ namespace MoonWorks.Graphics public TextureSlice TextureSlice { get; } public TextureFormat Format => TextureSlice.Texture.Format; + public uint Width => (uint) TextureSlice.Rectangle.W; + public uint Height => (uint) TextureSlice.Rectangle.H; + protected override Action QueueDestroyFunction => Refresh.Refresh_QueueDestroyRenderTarget; /// diff --git a/src/Graphics/State/GraphicsPipelineAttachmentInfo.cs b/src/Graphics/State/GraphicsPipelineAttachmentInfo.cs new file mode 100644 index 00000000..b45845fd --- /dev/null +++ b/src/Graphics/State/GraphicsPipelineAttachmentInfo.cs @@ -0,0 +1,13 @@ +namespace MoonWorks.Graphics +{ + /// + /// Describes the kind of attachments that will be used with this pipeline. + /// + public struct GraphicsPipelineAttachmentInfo + { + public ColorAttachmentDescription[] colorAttachmentDescriptions; + public uint colorAttachmentCount; + public bool hasDepthStencilAttachment; + public TextureFormat depthStencilFormat; + } +} diff --git a/src/Graphics/State/GraphicsPipelineCreateInfo.cs b/src/Graphics/State/GraphicsPipelineCreateInfo.cs index 67c0b7d1..f5b64367 100644 --- a/src/Graphics/State/GraphicsPipelineCreateInfo.cs +++ b/src/Graphics/State/GraphicsPipelineCreateInfo.cs @@ -12,6 +12,6 @@ public PrimitiveType PrimitiveType; public VertexInputState VertexInputState; public ViewportState ViewportState; - public RenderPass RenderPass; + public GraphicsPipelineAttachmentInfo AttachmentInfo; } } diff --git a/src/Graphics/Utility/Conversions.cs b/src/Graphics/Utility/Conversions.cs index aaadd6c2..5d05be93 100644 --- a/src/Graphics/Utility/Conversions.cs +++ b/src/Graphics/Utility/Conversions.cs @@ -9,7 +9,7 @@ public static bool ByteToBool(byte b) { - return b == 0 ? false : true; + return b != 0; } } }