diff --git a/Examples/DepthMSAAExample.cs b/Examples/DepthMSAAExample.cs new file mode 100644 index 0000000..70fcb78 --- /dev/null +++ b/Examples/DepthMSAAExample.cs @@ -0,0 +1,279 @@ +using MoonWorks; +using MoonWorks.Math.Float; +using MoonWorks.Math; +using MoonWorks.Graphics; +using MoonWorks.Input; + +namespace MoonWorksGraphicsTests; + +class DepthMSAAExample : Example +{ + private GraphicsPipeline[] CubePipelines = new GraphicsPipeline[4]; + private Texture[] RenderTargets = new Texture[4]; + private Texture[] DepthRTs = new Texture[4]; + private GpuBuffer CubeVertexBuffer1; + private GpuBuffer CubeVertexBuffer2; + private GpuBuffer CubeIndexBuffer; + + private float cubeTimer; + private Quaternion cubeRotation; + private Quaternion previousCubeRotation; + private Vector3 camPos; + private SampleCount currentSampleCount; + + public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs) + { + Window = window; + GraphicsDevice = graphicsDevice; + Inputs = inputs; + + Window.SetTitle("DepthMSAA"); + + cubeTimer = 0; + cubeRotation = Quaternion.Identity; + previousCubeRotation = Quaternion.Identity; + camPos = new Vector3(0, 1.5f, 4); + currentSampleCount = SampleCount.Four; + + Logger.LogInfo("Press Left and Right to cycle between sample counts"); + Logger.LogInfo("Setting sample count to: " + currentSampleCount); + + // Create the cube pipelines + Shader cubeVertShader = new Shader( + GraphicsDevice, + TestUtils.GetShaderPath("PositionColorWithMatrix.vert"), + "main", + ShaderStage.Vertex, + ShaderFormat.SPIRV + ); + + Shader cubeFragShader = new Shader( + GraphicsDevice, + TestUtils.GetShaderPath("SolidColor.frag"), + "main", + ShaderStage.Fragment, + ShaderFormat.SPIRV + ); + + GraphicsPipelineCreateInfo pipelineCreateInfo = new GraphicsPipelineCreateInfo + { + AttachmentInfo = new GraphicsPipelineAttachmentInfo( + TextureFormat.D32_SFLOAT, + new ColorAttachmentDescription( + Window.SwapchainFormat, + ColorAttachmentBlendState.Opaque + ) + ), + DepthStencilState = DepthStencilState.DepthReadWrite, + VertexInputState = VertexInputState.CreateSingleBinding(), + PrimitiveType = PrimitiveType.TriangleList, + RasterizerState = RasterizerState.CW_CullBack, + MultisampleState = MultisampleState.None, + VertexShader = cubeVertShader, + VertexShaderResourceInfo = new GraphicsPipelineResourceInfo + { + UniformBufferCount = 1 + }, + FragmentShader = cubeFragShader + }; + + for (int i = 0; i < CubePipelines.Length; i += 1) + { + pipelineCreateInfo.MultisampleState.MultisampleCount = (SampleCount) i; + CubePipelines[i] = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo); + } + + // Create the MSAA render textures and depth textures + for (int i = 0; i < RenderTargets.Length; i += 1) + { + RenderTargets[i] = Texture.CreateTexture2D( + GraphicsDevice, + Window.Width, + Window.Height, + Window.SwapchainFormat, + TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler, + 1, + (SampleCount) i + ); + + DepthRTs[i] = Texture.CreateTexture2D( + GraphicsDevice, + Window.Width, + Window.Height, + TextureFormat.D32_SFLOAT, + TextureUsageFlags.DepthStencil, + 1, + (SampleCount) i + ); + } + + // Create the buffers + var resourceUploader = new ResourceUploader(GraphicsDevice); + + var cubeVertexData = new System.Span( + [ + new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0f)), + new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0f)), + new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0f, 0f)), + new PositionColorVertex(new Vector3(-1, 1, -1), new Color(1f, 0f, 0f)), + + new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 1f, 0f)), + new PositionColorVertex(new Vector3(1, -1, 1), new Color(0f, 1f, 0f)), + new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 1f, 0f)), + new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 1f, 0f)), + + new PositionColorVertex(new Vector3(-1, -1, -1), new Color(0f, 0f, 1f)), + new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0f, 1f)), + new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0f, 1f)), + new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 0f, 1f)), + + new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0.5f, 0f)), + new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0.5f, 0f)), + new PositionColorVertex(new Vector3(1, 1, 1), new Color(1f, 0.5f, 0f)), + new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0.5f, 0f)), + + new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0.5f)), + new PositionColorVertex(new Vector3(-1, -1, 1), new Color(1f, 0f, 0.5f)), + new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0f, 0.5f)), + new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0.5f)), + + new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0.5f, 0f)), + new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0.5f, 0f)), + new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 0.5f, 0f)), + new PositionColorVertex(new Vector3(1, 1, -1), new Color(0f, 0.5f, 0f)) + ]); + + CubeVertexBuffer1 = resourceUploader.CreateBuffer( + cubeVertexData, + BufferUsageFlags.Vertex + ); + + // Scoot all the verts slightly for the second cube... + for (int i = 0; i < cubeVertexData.Length; i += 1) + { + cubeVertexData[i].Position.Z += 3; + } + + CubeVertexBuffer2 = resourceUploader.CreateBuffer( + cubeVertexData, + BufferUsageFlags.Vertex + ); + + CubeIndexBuffer = resourceUploader.CreateBuffer( + [ + 0, 1, 2, 0, 2, 3, + 6, 5, 4, 7, 6, 4, + 8, 9, 10, 8, 10, 11, + 14, 13, 12, 15, 14, 12, + 16, 17, 18, 16, 18, 19, + 22, 21, 20, 23, 22, 20 + ], + BufferUsageFlags.Index + ); + + resourceUploader.Upload(); + resourceUploader.Dispose(); + } + + public override void Update(System.TimeSpan delta) + { + SampleCount prevSampleCount = currentSampleCount; + + if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left)) + { + currentSampleCount -= 1; + if (currentSampleCount < 0) + { + currentSampleCount = SampleCount.Eight; + } + } + if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right)) + { + currentSampleCount += 1; + if (currentSampleCount > SampleCount.Eight) + { + currentSampleCount = SampleCount.One; + } + } + + if (prevSampleCount != currentSampleCount) + { + Logger.LogInfo("Setting sample count to: " + currentSampleCount); + } + + // Rotate the cube + cubeTimer += (float) delta.TotalSeconds; + previousCubeRotation = cubeRotation; + cubeRotation = Quaternion.CreateFromYawPitchRoll(cubeTimer * 2f, 0, cubeTimer * 2f); + } + + public override void Draw(double alpha) + { + CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer(); + Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window); + if (swapchainTexture != null) + { + // Set up cube model-view-projection matrix + Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView( + MathHelper.ToRadians(75f), + (float) Window.Width / Window.Height, + 0.01f, + 100f + ); + Matrix4x4 view = Matrix4x4.CreateLookAt(camPos, Vector3.Zero, Vector3.Up); + Matrix4x4 model = Matrix4x4.CreateFromQuaternion( + Quaternion.Slerp( + previousCubeRotation, + cubeRotation, + (float) alpha + ) + ); + TransformVertexUniform cubeUniforms = new TransformVertexUniform(model * view * proj); + + // Begin the MSAA RT pass + int index = (int) currentSampleCount; + var renderPass = cmdbuf.BeginRenderPass( + new DepthStencilAttachmentInfo(DepthRTs[index], true, new DepthStencilValue(1, 0)), + new ColorAttachmentInfo(RenderTargets[index], true, Color.Black) + ); + renderPass.BindGraphicsPipeline(CubePipelines[index]); + + // Draw the first cube + renderPass.BindVertexBuffer(CubeVertexBuffer1); + renderPass.BindIndexBuffer(CubeIndexBuffer, IndexElementSize.ThirtyTwo); + renderPass.PushVertexUniformData(cubeUniforms); + renderPass.DrawIndexedPrimitives(0, 0, 12); + + // Draw the second cube + renderPass.BindVertexBuffer(CubeVertexBuffer2); + renderPass.BindIndexBuffer(CubeIndexBuffer, IndexElementSize.ThirtyTwo); + renderPass.PushVertexUniformData(cubeUniforms); + renderPass.DrawIndexedPrimitives(0, 0, 12); + + cmdbuf.EndRenderPass(renderPass); + + // Blit the MSAA RT to the backbuffer + cmdbuf.Blit( + RenderTargets[index], + swapchainTexture, + Filter.Nearest, + false + ); + } + GraphicsDevice.Submit(cmdbuf); + } + + public override void Destroy() + { + for (var i = 0; i < 4; i += 1) + { + CubePipelines[i].Dispose(); + RenderTargets[i].Dispose(); + DepthRTs[i].Dispose(); + } + + CubeVertexBuffer1.Dispose(); + CubeVertexBuffer2.Dispose(); + CubeIndexBuffer.Dispose(); + } +} diff --git a/Examples/DepthMSAAGame.cs b/Examples/DepthMSAAGame.cs deleted file mode 100644 index 833370d..0000000 --- a/Examples/DepthMSAAGame.cs +++ /dev/null @@ -1,250 +0,0 @@ -using MoonWorks; -using MoonWorks.Math.Float; -using MoonWorks.Math; -using MoonWorks.Graphics; - -namespace MoonWorks.Test -{ - class DepthMSAAGame : Game - { - private GraphicsPipeline[] cubePipelines = new GraphicsPipeline[4]; - private Texture[] renderTargets = new Texture[4]; - private Texture[] depthRTs = new Texture[4]; - private GpuBuffer cubeVertexBuffer1; - private GpuBuffer cubeVertexBuffer2; - private GpuBuffer cubeIndexBuffer; - - private float cubeTimer = 0f; - private Quaternion cubeRotation = Quaternion.Identity; - private Quaternion previousCubeRotation = Quaternion.Identity; - private Vector3 camPos = new Vector3(0, 1.5f, 4f); - - private SampleCount currentSampleCount = SampleCount.Four; - - public DepthMSAAGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), TestUtils.PreferredBackends, 60, true) - { - Logger.LogInfo("Press Left and Right to cycle between sample counts"); - Logger.LogInfo("Setting sample count to: " + currentSampleCount); - - // Create the cube pipelines - ShaderModule cubeVertShaderModule = new ShaderModule( - GraphicsDevice, - TestUtils.GetShaderPath("PositionColorWithMatrix.vert") - ); - ShaderModule cubeFragShaderModule = new ShaderModule( - GraphicsDevice, - TestUtils.GetShaderPath("SolidColor.frag") - ); - - GraphicsPipelineCreateInfo pipelineCreateInfo = new GraphicsPipelineCreateInfo - { - AttachmentInfo = new GraphicsPipelineAttachmentInfo( - TextureFormat.D32, - new ColorAttachmentDescription( - MainWindow.SwapchainFormat, - ColorAttachmentBlendState.Opaque - ) - ), - DepthStencilState = DepthStencilState.DepthReadWrite, - VertexShaderInfo = GraphicsShaderInfo.Create(cubeVertShaderModule, "main", 0), - VertexInputState = VertexInputState.CreateSingleBinding(), - PrimitiveType = PrimitiveType.TriangleList, - FragmentShaderInfo = GraphicsShaderInfo.Create(cubeFragShaderModule, "main", 0), - RasterizerState = RasterizerState.CW_CullBack, - MultisampleState = MultisampleState.None - }; - - for (int i = 0; i < cubePipelines.Length; i += 1) - { - pipelineCreateInfo.MultisampleState.MultisampleCount = (SampleCount) i; - cubePipelines[i] = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo); - } - - // Create the MSAA render textures and depth textures - for (int i = 0; i < renderTargets.Length; i += 1) - { - renderTargets[i] = Texture.CreateTexture2D( - GraphicsDevice, - MainWindow.Width, - MainWindow.Height, - TextureFormat.R8G8B8A8, - TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler, - 1, - (SampleCount) i - ); - - depthRTs[i] = Texture.CreateTexture2D( - GraphicsDevice, - MainWindow.Width, - MainWindow.Height, - TextureFormat.D32, - TextureUsageFlags.DepthStencilTarget, - 1, - (SampleCount) i - ); - } - - // Create the buffers - var resourceUploader = new ResourceUploader(GraphicsDevice); - - var cubeVertexData = new System.Span( - [ - new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0f)), - new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0f)), - new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0f, 0f)), - new PositionColorVertex(new Vector3(-1, 1, -1), new Color(1f, 0f, 0f)), - - new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 1f, 0f)), - new PositionColorVertex(new Vector3(1, -1, 1), new Color(0f, 1f, 0f)), - new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 1f, 0f)), - new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 1f, 0f)), - - new PositionColorVertex(new Vector3(-1, -1, -1), new Color(0f, 0f, 1f)), - new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0f, 1f)), - new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0f, 1f)), - new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 0f, 1f)), - - new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0.5f, 0f)), - new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0.5f, 0f)), - new PositionColorVertex(new Vector3(1, 1, 1), new Color(1f, 0.5f, 0f)), - new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0.5f, 0f)), - - new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0.5f)), - new PositionColorVertex(new Vector3(-1, -1, 1), new Color(1f, 0f, 0.5f)), - new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0f, 0.5f)), - new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0.5f)), - - new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0.5f, 0f)), - new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0.5f, 0f)), - new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 0.5f, 0f)), - new PositionColorVertex(new Vector3(1, 1, -1), new Color(0f, 0.5f, 0f)) - ]); - - cubeVertexBuffer1 = resourceUploader.CreateBuffer( - cubeVertexData, - BufferUsageFlags.Vertex - ); - - // Scoot all the verts slightly for the second cube... - for (int i = 0; i < cubeVertexData.Length; i += 1) - { - cubeVertexData[i].Position.Z += 3; - } - - cubeVertexBuffer2 = resourceUploader.CreateBuffer( - cubeVertexData, - BufferUsageFlags.Vertex - ); - - cubeIndexBuffer = resourceUploader.CreateBuffer( - [ - 0, 1, 2, 0, 2, 3, - 6, 5, 4, 7, 6, 4, - 8, 9, 10, 8, 10, 11, - 14, 13, 12, 15, 14, 12, - 16, 17, 18, 16, 18, 19, - 22, 21, 20, 23, 22, 20 - ], - BufferUsageFlags.Index - ); - - resourceUploader.Upload(); - resourceUploader.Dispose(); - } - - protected override void Update(System.TimeSpan delta) - { - SampleCount prevSampleCount = currentSampleCount; - - if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left)) - { - currentSampleCount -= 1; - if (currentSampleCount < 0) - { - currentSampleCount = SampleCount.Eight; - } - } - if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right)) - { - currentSampleCount += 1; - if (currentSampleCount > SampleCount.Eight) - { - currentSampleCount = SampleCount.One; - } - } - - if (prevSampleCount != currentSampleCount) - { - Logger.LogInfo("Setting sample count to: " + currentSampleCount); - } - - // Rotate the cube - cubeTimer += (float) delta.TotalSeconds; - previousCubeRotation = cubeRotation; - cubeRotation = Quaternion.CreateFromYawPitchRoll(cubeTimer * 2f, 0, cubeTimer * 2f); - } - - protected override void Draw(double alpha) - { - CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer(); - Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow); - if (backbuffer != null) - { - // Set up cube model-view-projection matrix - Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView( - MathHelper.ToRadians(75f), - (float) MainWindow.Width / MainWindow.Height, - 0.01f, - 100f - ); - Matrix4x4 view = Matrix4x4.CreateLookAt(camPos, Vector3.Zero, Vector3.Up); - Matrix4x4 model = Matrix4x4.CreateFromQuaternion( - Quaternion.Slerp( - previousCubeRotation, - cubeRotation, - (float) alpha - ) - ); - TransformVertexUniform cubeUniforms = new TransformVertexUniform(model * view * proj); - - // Begin the MSAA RT pass - int index = (int) currentSampleCount; - cmdbuf.BeginRenderPass( - new DepthStencilAttachmentInfo(depthRTs[index], WriteOptions.Cycle, new DepthStencilValue(1, 0)), - new ColorAttachmentInfo(renderTargets[index], WriteOptions.Cycle, Color.Black) - ); - cmdbuf.BindGraphicsPipeline(cubePipelines[index]); - - // Draw the first cube - cmdbuf.BindVertexBuffers(cubeVertexBuffer1); - cmdbuf.BindIndexBuffer(cubeIndexBuffer, IndexElementSize.ThirtyTwo); - cmdbuf.PushVertexShaderUniforms(cubeUniforms); - cmdbuf.DrawIndexedPrimitives(0, 0, 12); - - // Draw the second cube - cmdbuf.BindVertexBuffers(cubeVertexBuffer2); - cmdbuf.BindIndexBuffer(cubeIndexBuffer, IndexElementSize.ThirtyTwo); - cmdbuf.PushVertexShaderUniforms(cubeUniforms); - cmdbuf.DrawIndexedPrimitives(0, 0, 12); - - cmdbuf.EndRenderPass(); - - // Blit the MSAA RT to the backbuffer - // A copy would work fine here as well - cmdbuf.Blit( - renderTargets[index], - backbuffer, - Filter.Nearest, - WriteOptions.Safe - ); - } - GraphicsDevice.Submit(cmdbuf); - } - - public static void Main(string[] args) - { - DepthMSAAGame game = new DepthMSAAGame(); - game.Run(); - } - } -} diff --git a/MoonWorksGraphicsTests.csproj b/MoonWorksGraphicsTests.csproj index 1a8b13a..f95f752 100644 --- a/MoonWorksGraphicsTests.csproj +++ b/MoonWorksGraphicsTests.csproj @@ -34,6 +34,7 @@ + diff --git a/Program.cs b/Program.cs index bdc9b47..c44c680 100644 --- a/Program.cs +++ b/Program.cs @@ -17,7 +17,8 @@ class Program : Game new ComputeUniformsExample(), new CopyTextureExample(), new CubeExample(), - new CullFaceExample() + new CullFaceExample(), + new DepthMSAAExample() ]; int ExampleIndex = 0;