diff --git a/.gitignore b/.gitignore
index 03c9b93..796b6e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
bin/
obj/
.vs/
+*.csproj.user
diff --git a/MoonWorks.csproj b/MoonWorks.csproj
index a20c72a..8c55535 100644
--- a/MoonWorks.csproj
+++ b/MoonWorks.csproj
@@ -7,7 +7,7 @@
- $(DefaultItemExcludes);lib\**\*
+ $(DefaultItemExcludes);lib\**\*;tests\**\*
diff --git a/MoonWorks.sln b/MoonWorks.sln
index 748c5d4..c5e500c 100644
--- a/MoonWorks.sln
+++ b/MoonWorks.sln
@@ -5,6 +5,26 @@ VisualStudioVersion = 16.0.30717.126
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MoonWorks", "MoonWorks.csproj", "{DDC9BA9B-4440-4CB3-BDB4-D5F91DE1686B}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{734B6C25-40FE-4688-9B3C-7B3D3A343257}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MoonWorks.Test.Common", "tests\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj", "{47BC8A83-B1A5-454C-AED0-461B535D664B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScreen", "tests\ClearScreen\ClearScreen.csproj", "{C37E4CF1-4899-48BC-BF58-2074420077BC}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicTriangle", "tests\BasicTriangle\BasicTriangle.csproj", "{F34E6D95-887D-49C0-AC74-560EBD0D23C5}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TriangleVertexBuffer", "tests\TriangleVertexBuffer\TriangleVertexBuffer.csproj", "{944D4FDC-1635-46B6-84FA-8161F8E43AC4}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TexturedQuad", "tests\TexturedQuad\TexturedQuad.csproj", "{845DA751-5072-43C8-B9E6-4E2A32D99161}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CullFace", "tests\CullFace\CullFace.csproj", "{96986050-5136-4680-B388-EDD1207F9212}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScreen_MultiWindow", "tests\ClearScreen_MultiWindow\ClearScreen_MultiWindow.csproj", "{F6283B5C-051B-427C-AE7E-9DB9E0313769}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TexturedAnimatedQuad", "tests\TexturedAnimatedQuad\TexturedAnimatedQuad.csproj", "{F022FB5F-FD61-4956-A7CE-7B428DB80A39}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MSAA", "tests\MSAA\MSAA.csproj", "{D97DED9B-4CC4-45F6-A9A9-E8C589036A85}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -15,10 +35,50 @@ Global
{DDC9BA9B-4440-4CB3-BDB4-D5F91DE1686B}.Debug|x64.Build.0 = Debug|x64
{DDC9BA9B-4440-4CB3-BDB4-D5F91DE1686B}.Release|x64.ActiveCfg = Release|x64
{DDC9BA9B-4440-4CB3-BDB4-D5F91DE1686B}.Release|x64.Build.0 = Release|x64
+ {47BC8A83-B1A5-454C-AED0-461B535D664B}.Debug|x64.ActiveCfg = Debug|x64
+ {47BC8A83-B1A5-454C-AED0-461B535D664B}.Debug|x64.Build.0 = Debug|x64
+ {47BC8A83-B1A5-454C-AED0-461B535D664B}.Release|x64.ActiveCfg = Release|x64
+ {C37E4CF1-4899-48BC-BF58-2074420077BC}.Debug|x64.ActiveCfg = Debug|x64
+ {C37E4CF1-4899-48BC-BF58-2074420077BC}.Debug|x64.Build.0 = Debug|x64
+ {C37E4CF1-4899-48BC-BF58-2074420077BC}.Release|x64.ActiveCfg = Release|x64
+ {F34E6D95-887D-49C0-AC74-560EBD0D23C5}.Debug|x64.ActiveCfg = Debug|x64
+ {F34E6D95-887D-49C0-AC74-560EBD0D23C5}.Debug|x64.Build.0 = Debug|x64
+ {F34E6D95-887D-49C0-AC74-560EBD0D23C5}.Release|x64.ActiveCfg = Release|x64
+ {944D4FDC-1635-46B6-84FA-8161F8E43AC4}.Debug|x64.ActiveCfg = Debug|x64
+ {944D4FDC-1635-46B6-84FA-8161F8E43AC4}.Debug|x64.Build.0 = Debug|x64
+ {944D4FDC-1635-46B6-84FA-8161F8E43AC4}.Release|x64.ActiveCfg = Release|x64
+ {845DA751-5072-43C8-B9E6-4E2A32D99161}.Debug|x64.ActiveCfg = Debug|x64
+ {845DA751-5072-43C8-B9E6-4E2A32D99161}.Debug|x64.Build.0 = Debug|x64
+ {845DA751-5072-43C8-B9E6-4E2A32D99161}.Release|x64.ActiveCfg = Release|x64
+ {96986050-5136-4680-B388-EDD1207F9212}.Debug|x64.ActiveCfg = Debug|x64
+ {96986050-5136-4680-B388-EDD1207F9212}.Debug|x64.Build.0 = Debug|x64
+ {96986050-5136-4680-B388-EDD1207F9212}.Release|x64.ActiveCfg = Release|x64
+ {F6283B5C-051B-427C-AE7E-9DB9E0313769}.Debug|x64.ActiveCfg = Debug|x64
+ {F6283B5C-051B-427C-AE7E-9DB9E0313769}.Debug|x64.Build.0 = Debug|x64
+ {F6283B5C-051B-427C-AE7E-9DB9E0313769}.Release|x64.ActiveCfg = Release|x64
+ {F022FB5F-FD61-4956-A7CE-7B428DB80A39}.Debug|x64.ActiveCfg = Debug|x64
+ {F022FB5F-FD61-4956-A7CE-7B428DB80A39}.Debug|x64.Build.0 = Debug|x64
+ {F022FB5F-FD61-4956-A7CE-7B428DB80A39}.Release|x64.ActiveCfg = Release|Any CPU
+ {F022FB5F-FD61-4956-A7CE-7B428DB80A39}.Release|x64.Build.0 = Release|Any CPU
+ {D97DED9B-4CC4-45F6-A9A9-E8C589036A85}.Debug|x64.ActiveCfg = Debug|x64
+ {D97DED9B-4CC4-45F6-A9A9-E8C589036A85}.Debug|x64.Build.0 = Debug|x64
+ {D97DED9B-4CC4-45F6-A9A9-E8C589036A85}.Release|x64.ActiveCfg = Release|Any CPU
+ {D97DED9B-4CC4-45F6-A9A9-E8C589036A85}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {47BC8A83-B1A5-454C-AED0-461B535D664B} = {734B6C25-40FE-4688-9B3C-7B3D3A343257}
+ {C37E4CF1-4899-48BC-BF58-2074420077BC} = {734B6C25-40FE-4688-9B3C-7B3D3A343257}
+ {F34E6D95-887D-49C0-AC74-560EBD0D23C5} = {734B6C25-40FE-4688-9B3C-7B3D3A343257}
+ {944D4FDC-1635-46B6-84FA-8161F8E43AC4} = {734B6C25-40FE-4688-9B3C-7B3D3A343257}
+ {845DA751-5072-43C8-B9E6-4E2A32D99161} = {734B6C25-40FE-4688-9B3C-7B3D3A343257}
+ {96986050-5136-4680-B388-EDD1207F9212} = {734B6C25-40FE-4688-9B3C-7B3D3A343257}
+ {F6283B5C-051B-427C-AE7E-9DB9E0313769} = {734B6C25-40FE-4688-9B3C-7B3D3A343257}
+ {F022FB5F-FD61-4956-A7CE-7B428DB80A39} = {734B6C25-40FE-4688-9B3C-7B3D3A343257}
+ {D97DED9B-4CC4-45F6-A9A9-E8C589036A85} = {734B6C25-40FE-4688-9B3C-7B3D3A343257}
+ EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3D68FAA-3165-43C7-95B3-D845F0DAA918}
EndGlobalSection
diff --git a/tests/BasicTriangle/BasicTriangle.csproj b/tests/BasicTriangle/BasicTriangle.csproj
new file mode 100644
index 0000000..9538ed1
--- /dev/null
+++ b/tests/BasicTriangle/BasicTriangle.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+ Exe
+ net6.0
+ enable
+ x64
+
+
+
+
+ Content\%(RecursiveDir)%(Filename)%(Extension)
+ Always
+
+
+
+
diff --git a/tests/BasicTriangle/BasicTriangleGame.cs b/tests/BasicTriangle/BasicTriangleGame.cs
new file mode 100644
index 0000000..2986993
--- /dev/null
+++ b/tests/BasicTriangle/BasicTriangleGame.cs
@@ -0,0 +1,85 @@
+using MoonWorks;
+using MoonWorks.Graphics;
+
+namespace MoonWorks.Test
+{
+ class BasicTriangleGame : Game
+ {
+ private GraphicsPipeline fillPipeline;
+ private GraphicsPipeline linePipeline;
+ private ShaderModule vertShaderModule;
+ private ShaderModule fragShaderModule;
+
+ private Viewport smallViewport = new Viewport(160, 120, 320, 240);
+ private Rect scissorRect = new Rect(320, 240, 320, 240);
+
+ private bool useWireframeMode;
+ private bool useSmallViewport;
+ private bool useScissorRect;
+
+ public BasicTriangleGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
+ {
+ Logger.LogInfo("Press A to toggle wireframe mode\nPress S to toggle small viewport\nPress D to toggle scissor rect");
+
+ vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("RawTriangleVertices.spv"));
+ fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.spv"));
+
+ GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(vertShaderModule, fragShaderModule);
+ fillPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ pipelineCreateInfo.RasterizerState.FillMode = FillMode.Line;
+ linePipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+ }
+
+ protected override void Update(System.TimeSpan delta)
+ {
+ if (Inputs.Keyboard.IsPressed(Input.KeyCode.A))
+ {
+ useWireframeMode = !useWireframeMode;
+ Logger.LogInfo("Using wireframe mode: " + useWireframeMode);
+ }
+
+ if (Inputs.Keyboard.IsPressed(Input.KeyCode.S))
+ {
+ useSmallViewport = !useSmallViewport;
+ Logger.LogInfo("Using small viewport: " + useSmallViewport);
+ }
+
+ if (Inputs.Keyboard.IsPressed(Input.KeyCode.D))
+ {
+ useScissorRect = !useScissorRect;
+ Logger.LogInfo("Using scissor rect: " + useScissorRect);
+ }
+ }
+
+ protected override void Draw(double alpha)
+ {
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
+ if (backbuffer != null)
+ {
+ cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black));
+ cmdbuf.BindGraphicsPipeline(useWireframeMode ? linePipeline : fillPipeline);
+
+ if (useSmallViewport)
+ {
+ cmdbuf.SetViewport(smallViewport);
+ }
+ if (useScissorRect)
+ {
+ cmdbuf.SetScissor(scissorRect);
+ }
+
+ cmdbuf.DrawPrimitives(0, 1, 0, 0);
+ cmdbuf.EndRenderPass();
+ }
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ public static void Main(string[] args)
+ {
+ BasicTriangleGame game = new BasicTriangleGame();
+ game.Run();
+ }
+ }
+}
diff --git a/tests/ClearScreen/ClearScreen.csproj b/tests/ClearScreen/ClearScreen.csproj
new file mode 100644
index 0000000..fd2ff3e
--- /dev/null
+++ b/tests/ClearScreen/ClearScreen.csproj
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+ Exe
+ net6.0
+ enable
+ x64
+
+
+
diff --git a/tests/ClearScreen/ClearScreenGame.cs b/tests/ClearScreen/ClearScreenGame.cs
new file mode 100644
index 0000000..63ac285
--- /dev/null
+++ b/tests/ClearScreen/ClearScreenGame.cs
@@ -0,0 +1,29 @@
+using MoonWorks;
+using MoonWorks.Graphics;
+
+namespace MoonWorks.Test
+{
+ class ClearScreenGame : Game
+ {
+ public ClearScreenGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true) { }
+ protected override void Update(System.TimeSpan delta) { }
+
+ protected override void Draw(double alpha)
+ {
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
+ if (backbuffer != null)
+ {
+ cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.CornflowerBlue));
+ cmdbuf.EndRenderPass();
+ }
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ public static void Main(string[] args)
+ {
+ ClearScreenGame game = new ClearScreenGame();
+ game.Run();
+ }
+ }
+}
diff --git a/tests/ClearScreen_MultiWindow/ClearScreen_MultiWindow.csproj b/tests/ClearScreen_MultiWindow/ClearScreen_MultiWindow.csproj
new file mode 100644
index 0000000..fd2ff3e
--- /dev/null
+++ b/tests/ClearScreen_MultiWindow/ClearScreen_MultiWindow.csproj
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+ Exe
+ net6.0
+ enable
+ x64
+
+
+
diff --git a/tests/ClearScreen_MultiWindow/ClearScreen_MultiWindowGame.cs b/tests/ClearScreen_MultiWindow/ClearScreen_MultiWindowGame.cs
new file mode 100644
index 0000000..fa955fd
--- /dev/null
+++ b/tests/ClearScreen_MultiWindow/ClearScreen_MultiWindowGame.cs
@@ -0,0 +1,51 @@
+using MoonWorks;
+using MoonWorks.Graphics;
+
+namespace MoonWorks.Test
+{
+ class ClearScreen_MultiWindowGame : Game
+ {
+ private Window secondaryWindow;
+
+ public ClearScreen_MultiWindowGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
+ {
+ secondaryWindow = new Window(
+ new WindowCreateInfo("Secondary Window", 640, 480, ScreenMode.Windowed, PresentMode.FIFO, false, false),
+ GraphicsDevice.WindowFlags
+ );
+ GraphicsDevice.ClaimWindow(secondaryWindow, PresentMode.FIFO);
+ }
+
+ protected override void Update(System.TimeSpan delta) { }
+
+ protected override void Draw(double alpha)
+ {
+ CommandBuffer cmdbuf;
+ Texture? backbuffer;
+
+ cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
+ if (backbuffer != null)
+ {
+ cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.CornflowerBlue));
+ cmdbuf.EndRenderPass();
+ }
+ GraphicsDevice.Submit(cmdbuf);
+
+ cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ backbuffer = cmdbuf.AcquireSwapchainTexture(secondaryWindow);
+ if (backbuffer != null)
+ {
+ cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Aquamarine));
+ cmdbuf.EndRenderPass();
+ }
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ public static void Main(string[] args)
+ {
+ ClearScreen_MultiWindowGame game = new ClearScreen_MultiWindowGame();
+ game.Run();
+ }
+ }
+}
diff --git a/tests/CullFace/CullFace.csproj b/tests/CullFace/CullFace.csproj
new file mode 100644
index 0000000..9538ed1
--- /dev/null
+++ b/tests/CullFace/CullFace.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+ Exe
+ net6.0
+ enable
+ x64
+
+
+
+
+ Content\%(RecursiveDir)%(Filename)%(Extension)
+ Always
+
+
+
+
diff --git a/tests/CullFace/CullFaceGame.cs b/tests/CullFace/CullFaceGame.cs
new file mode 100644
index 0000000..81beb3e
--- /dev/null
+++ b/tests/CullFace/CullFaceGame.cs
@@ -0,0 +1,144 @@
+using MoonWorks;
+using MoonWorks.Graphics;
+using MoonWorks.Math.Float;
+
+namespace MoonWorks.Test
+{
+ internal class CullFaceGame : Game
+ {
+ private GraphicsPipeline CW_CullNonePipeline;
+ private GraphicsPipeline CW_CullFrontPipeline;
+ private GraphicsPipeline CW_CullBackPipeline;
+ private GraphicsPipeline CCW_CullNonePipeline;
+ private GraphicsPipeline CCW_CullFrontPipeline;
+ private GraphicsPipeline CCW_CullBackPipeline;
+ private ShaderModule vertShaderModule;
+ private ShaderModule fragShaderModule;
+ private Buffer cwVertexBuffer;
+ private Buffer ccwVertexBuffer;
+
+ private bool useClockwiseWinding;
+
+ public CullFaceGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
+ {
+ Logger.LogInfo("Press A to toggle the winding order of the triangles (default is counter-clockwise)");
+
+ // Load the shaders
+ vertShaderModule = new ShaderModule(GraphicsDevice, "Content/Shaders/Compiled/PositionColorVert.spv");
+ fragShaderModule = new ShaderModule(GraphicsDevice, "Content/Shaders/Compiled/SolidColor.spv");
+
+ // Create the graphics pipelines
+ GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(vertShaderModule, fragShaderModule);
+ pipelineCreateInfo.VertexInputState = new VertexInputState(
+ VertexBinding.Create(),
+ VertexAttribute.Create("Position", 0),
+ VertexAttribute.Create("Color", 1)
+ );
+
+ pipelineCreateInfo.RasterizerState = RasterizerState.CW_CullNone;
+ CW_CullNonePipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ pipelineCreateInfo.RasterizerState = RasterizerState.CW_CullFront;
+ CW_CullFrontPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ pipelineCreateInfo.RasterizerState = RasterizerState.CW_CullBack;
+ CW_CullBackPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ pipelineCreateInfo.RasterizerState = RasterizerState.CCW_CullNone;
+ CCW_CullNonePipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ pipelineCreateInfo.RasterizerState = RasterizerState.CCW_CullFront;
+ CCW_CullFrontPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ pipelineCreateInfo.RasterizerState = RasterizerState.CCW_CullBack;
+ CCW_CullBackPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ // Create and populate the vertex buffers
+ cwVertexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Vertex, 3);
+ ccwVertexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Vertex, 3);
+
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ cmdbuf.SetBufferData(
+ cwVertexBuffer,
+ new PositionColorVertex[]
+ {
+ new PositionColorVertex(new Vector3(0, -1, 0), Color.Blue),
+ new PositionColorVertex(new Vector3(1, 1, 0), Color.Green),
+ new PositionColorVertex(new Vector3(-1, 1, 0), Color.Red),
+ }
+ );
+ cmdbuf.SetBufferData(
+ ccwVertexBuffer,
+ new PositionColorVertex[]
+ {
+ new PositionColorVertex(new Vector3(-1, 1, 0), Color.Red),
+ new PositionColorVertex(new Vector3(1, 1, 0), Color.Green),
+ new PositionColorVertex(new Vector3(0, -1, 0), Color.Blue),
+ }
+ );
+ GraphicsDevice.Submit(cmdbuf);
+ GraphicsDevice.Wait();
+ }
+
+ protected override void Update(System.TimeSpan delta)
+ {
+ if (Inputs.Keyboard.IsPressed(Input.KeyCode.A))
+ {
+ useClockwiseWinding = !useClockwiseWinding;
+ Logger.LogInfo("Using clockwise winding: " + useClockwiseWinding);
+ }
+ }
+
+ protected override void Draw(double alpha)
+ {
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
+ if (backbuffer != null)
+ {
+ cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black));
+
+ if (useClockwiseWinding)
+ {
+ cmdbuf.BindVertexBuffers(cwVertexBuffer);
+ }
+ else
+ {
+ cmdbuf.BindVertexBuffers(ccwVertexBuffer);
+ }
+
+ cmdbuf.SetViewport(new Viewport(0, 0, 213, 240));
+ cmdbuf.BindGraphicsPipeline(CW_CullNonePipeline);
+ cmdbuf.DrawPrimitives(0, 1, 0, 0);
+
+ cmdbuf.SetViewport(new Viewport(213, 0, 213, 240));
+ cmdbuf.BindGraphicsPipeline(CW_CullFrontPipeline);
+ cmdbuf.DrawPrimitives(0, 1, 0, 0);
+
+ cmdbuf.SetViewport(new Viewport(426, 0, 213, 240));
+ cmdbuf.BindGraphicsPipeline(CW_CullBackPipeline);
+ cmdbuf.DrawPrimitives(0, 1, 0, 0);
+
+ cmdbuf.SetViewport(new Viewport(0, 240, 213, 240));
+ cmdbuf.BindGraphicsPipeline(CCW_CullNonePipeline);
+ cmdbuf.DrawPrimitives(0, 1, 0, 0);
+
+ cmdbuf.SetViewport(new Viewport(213, 240, 213, 240));
+ cmdbuf.BindGraphicsPipeline(CCW_CullFrontPipeline);
+ cmdbuf.DrawPrimitives(0, 1, 0, 0);
+
+ cmdbuf.SetViewport(new Viewport(426, 240, 213, 240));
+ cmdbuf.BindGraphicsPipeline(CCW_CullBackPipeline);
+ cmdbuf.DrawPrimitives(0, 1, 0, 0);
+
+ cmdbuf.EndRenderPass();
+ }
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ public static void Main(string[] args)
+ {
+ CullFaceGame game = new CullFaceGame();
+ game.Run();
+ }
+ }
+}
diff --git a/tests/MSAA/MSAA.csproj b/tests/MSAA/MSAA.csproj
new file mode 100644
index 0000000..9538ed1
--- /dev/null
+++ b/tests/MSAA/MSAA.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+ Exe
+ net6.0
+ enable
+ x64
+
+
+
+
+ Content\%(RecursiveDir)%(Filename)%(Extension)
+ Always
+
+
+
+
diff --git a/tests/MSAA/MSAAGame.cs b/tests/MSAA/MSAAGame.cs
new file mode 100644
index 0000000..b98e1f5
--- /dev/null
+++ b/tests/MSAA/MSAAGame.cs
@@ -0,0 +1,159 @@
+using MoonWorks;
+using MoonWorks.Math.Float;
+using MoonWorks.Graphics;
+
+namespace MoonWorks.Test
+{
+ class MSAAGame : Game
+ {
+ private GraphicsPipeline[] msaaPipelines = new GraphicsPipeline[4];
+
+ private ShaderModule triangleVertShaderModule;
+ private ShaderModule triangleFragShaderModule;
+
+ private GraphicsPipeline blitPipeline;
+ private ShaderModule blitVertShaderModule;
+ private ShaderModule blitFragShaderModule;
+
+ private Texture rt;
+ private Sampler rtSampler;
+ private Buffer quadVertexBuffer;
+ private Buffer quadIndexBuffer;
+
+ private SampleCount currentSampleCount = SampleCount.Four;
+
+ public MSAAGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
+ {
+ Logger.LogInfo("Press A and D to cycle between sample counts");
+ Logger.LogInfo("Setting sample count to: " + currentSampleCount);
+
+ // Create the MSAA pipelines
+ triangleVertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("RawTriangleVertices.spv"));
+ triangleFragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.spv"));
+
+ GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
+ triangleVertShaderModule,
+ triangleFragShaderModule
+ );
+ for (int i = 0; i < msaaPipelines.Length; i += 1)
+ {
+ pipelineCreateInfo.MultisampleState.MultisampleCount = (SampleCount) i;
+ msaaPipelines[i] = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+ }
+
+ // Create the blit pipeline
+ blitVertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuadVert.spv"));
+ blitFragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuadFrag.spv"));
+
+ pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
+ blitVertShaderModule,
+ blitFragShaderModule
+ );
+ pipelineCreateInfo.VertexInputState = new VertexInputState(
+ VertexBinding.Create(),
+ VertexAttribute.Create("Position", 0),
+ VertexAttribute.Create("TexCoord", 1)
+ );
+ pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
+ blitPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ // Create the MSAA render texture and sampler
+ rt = Texture.CreateTexture2D(
+ GraphicsDevice,
+ MainWindow.Width,
+ MainWindow.Height,
+ TextureFormat.R8G8B8A8,
+ TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler
+ );
+ rtSampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
+
+ // Create and populate the vertex and index buffers
+ quadVertexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Vertex, 4);
+ quadIndexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Index, 6);
+
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ cmdbuf.SetBufferData(
+ quadVertexBuffer,
+ new PositionTextureVertex[]
+ {
+ new PositionTextureVertex(new Vector3(-1, -1, 0), new Vector2(0, 0)),
+ new PositionTextureVertex(new Vector3(1, -1, 0), new Vector2(1, 0)),
+ new PositionTextureVertex(new Vector3(1, 1, 0), new Vector2(1, 1)),
+ new PositionTextureVertex(new Vector3(-1, 1, 0), new Vector2(0, 1)),
+ }
+ );
+ cmdbuf.SetBufferData(
+ quadIndexBuffer,
+ new ushort[]
+ {
+ 0, 1, 2,
+ 0, 2, 3,
+ }
+ );
+ GraphicsDevice.Submit(cmdbuf);
+ GraphicsDevice.Wait();
+ }
+
+ protected override void Update(System.TimeSpan delta)
+ {
+ SampleCount prevSampleCount = currentSampleCount;
+
+ if (Inputs.Keyboard.IsPressed(Input.KeyCode.A))
+ {
+ currentSampleCount -= 1;
+ if (currentSampleCount < 0)
+ {
+ currentSampleCount = SampleCount.Eight;
+ }
+ }
+ if (Inputs.Keyboard.IsPressed(Input.KeyCode.D))
+ {
+ currentSampleCount += 1;
+ if (currentSampleCount > SampleCount.Eight)
+ {
+ currentSampleCount = SampleCount.One;
+ }
+ }
+
+ if (prevSampleCount != currentSampleCount)
+ {
+ Logger.LogInfo("Setting sample count to: " + currentSampleCount);
+ }
+ }
+
+ protected override void Draw(double alpha)
+ {
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
+ if (backbuffer != null)
+ {
+ cmdbuf.BeginRenderPass(
+ new ColorAttachmentInfo(
+ rt,
+ Color.Black,
+ currentSampleCount,
+ StoreOp.DontCare
+ )
+ );
+ cmdbuf.BindGraphicsPipeline(msaaPipelines[(int) currentSampleCount]);
+ cmdbuf.DrawPrimitives(0, 1, 0, 0);
+ cmdbuf.EndRenderPass();
+
+ cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, LoadOp.DontCare));
+ cmdbuf.BindGraphicsPipeline(blitPipeline);
+ cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(rt, rtSampler));
+ cmdbuf.BindVertexBuffers(quadVertexBuffer);
+ cmdbuf.BindIndexBuffer(quadIndexBuffer, IndexElementSize.Sixteen);
+ cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, 0);
+ cmdbuf.EndRenderPass();
+ }
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ public static void Main(string[] args)
+ {
+ MSAAGame game = new MSAAGame();
+ game.Run();
+ }
+ }
+}
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/PositionColorVert.spv b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/PositionColorVert.spv
new file mode 100644
index 0000000..0852ff8
Binary files /dev/null and b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/PositionColorVert.spv differ
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/RawTriangleVertices.spv b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/RawTriangleVertices.spv
new file mode 100644
index 0000000..917342f
Binary files /dev/null and b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/RawTriangleVertices.spv differ
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/SolidColor.spv b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/SolidColor.spv
new file mode 100644
index 0000000..211b356
Binary files /dev/null and b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/SolidColor.spv differ
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadAnimatedFrag.spv b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadAnimatedFrag.spv
new file mode 100644
index 0000000..fa849a9
Binary files /dev/null and b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadAnimatedFrag.spv differ
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadAnimatedVert.spv b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadAnimatedVert.spv
new file mode 100644
index 0000000..e43dee2
Binary files /dev/null and b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadAnimatedVert.spv differ
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadFrag.spv b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadFrag.spv
new file mode 100644
index 0000000..d19ad27
Binary files /dev/null and b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadFrag.spv differ
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadVert.spv b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadVert.spv
new file mode 100644
index 0000000..c565481
Binary files /dev/null and b/tests/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadVert.spv differ
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Source/PositionColorVert.vert b/tests/MoonWorks.Test.Common/Content/Shaders/Source/PositionColorVert.vert
new file mode 100644
index 0000000..99d5237
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/Content/Shaders/Source/PositionColorVert.vert
@@ -0,0 +1,12 @@
+#version 450
+
+layout (location = 0) in vec3 Position;
+layout (location = 1) in vec4 Color;
+
+layout (location = 0) out vec4 outColor;
+
+void main()
+{
+ outColor = Color;
+ gl_Position = vec4(Position, 1);
+}
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Source/RawTriangleVertices.vert b/tests/MoonWorks.Test.Common/Content/Shaders/Source/RawTriangleVertices.vert
new file mode 100644
index 0000000..fba105d
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/Content/Shaders/Source/RawTriangleVertices.vert
@@ -0,0 +1,26 @@
+#version 450
+
+layout (location = 0) out vec4 outColor;
+
+void main()
+{
+ vec2 pos;
+
+ if (gl_VertexIndex == 0)
+ {
+ pos = vec2(-1, 1);
+ outColor = vec4(1, 0, 0, 1);
+ }
+ else if (gl_VertexIndex == 1)
+ {
+ pos = vec2(1, 1);
+ outColor = vec4(0, 1, 0, 1);
+ }
+ else if (gl_VertexIndex == 2)
+ {
+ pos = vec2(0, -1);
+ outColor = vec4(0, 0, 1, 1);
+ }
+
+ gl_Position = vec4(pos, 0, 1);
+}
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Source/SolidColor.frag b/tests/MoonWorks.Test.Common/Content/Shaders/Source/SolidColor.frag
new file mode 100644
index 0000000..ec2d430
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/Content/Shaders/Source/SolidColor.frag
@@ -0,0 +1,10 @@
+#version 450
+
+layout (location = 0) in vec4 Color;
+
+layout (location = 0) out vec4 FragColor;
+
+void main()
+{
+ FragColor = Color;
+}
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadAnimatedFrag.frag b/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadAnimatedFrag.frag
new file mode 100644
index 0000000..5e0db2e
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadAnimatedFrag.frag
@@ -0,0 +1,17 @@
+#version 450
+
+layout (location = 0) in vec2 TexCoord;
+
+layout (location = 0) out vec4 FragColor;
+
+layout(binding = 0, set = 1) uniform sampler2D Sampler;
+
+layout (binding = 0, set = 3) uniform UniformBlock
+{
+ vec4 MultiplyColor;
+};
+
+void main()
+{
+ FragColor = MultiplyColor * texture(Sampler, TexCoord);
+}
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadAnimatedVert.vert b/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadAnimatedVert.vert
new file mode 100644
index 0000000..080dfb5
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadAnimatedVert.vert
@@ -0,0 +1,17 @@
+#version 450
+
+layout (location = 0) in vec3 Position;
+layout (location = 1) in vec2 TexCoord;
+
+layout (location = 0) out vec2 outTexCoord;
+
+layout (binding = 0, set = 2) uniform UniformBlock
+{
+ mat4x4 MatrixTransform;
+};
+
+void main()
+{
+ outTexCoord = TexCoord;
+ gl_Position = MatrixTransform * vec4(Position, 1);
+}
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadFrag.frag b/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadFrag.frag
new file mode 100644
index 0000000..c4237bd
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadFrag.frag
@@ -0,0 +1,12 @@
+#version 450
+
+layout (location = 0) in vec2 TexCoord;
+
+layout (location = 0) out vec4 FragColor;
+
+layout(binding = 0, set = 1) uniform sampler2D Sampler;
+
+void main()
+{
+ FragColor = texture(Sampler, TexCoord);
+}
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadVert.vert b/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadVert.vert
new file mode 100644
index 0000000..ff0d240
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadVert.vert
@@ -0,0 +1,12 @@
+#version 450
+
+layout (location = 0) in vec3 Position;
+layout (location = 1) in vec2 TexCoord;
+
+layout (location = 0) out vec2 outTexCoord;
+
+void main()
+{
+ outTexCoord = TexCoord;
+ gl_Position = vec4(Position, 1);
+}
diff --git a/tests/MoonWorks.Test.Common/Content/Shaders/compileShaders.ps1 b/tests/MoonWorks.Test.Common/Content/Shaders/compileShaders.ps1
new file mode 100644
index 0000000..aa16bf5
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/Content/Shaders/compileShaders.ps1
@@ -0,0 +1,5 @@
+Get-ChildItem "Source" |
+Foreach-Object {
+ $filename = $_.Basename
+ glslc $_.FullName -o Compiled/$filename.spv
+}
diff --git a/tests/MoonWorks.Test.Common/Content/Textures/ravioli.png b/tests/MoonWorks.Test.Common/Content/Textures/ravioli.png
new file mode 100644
index 0000000..f202cb2
Binary files /dev/null and b/tests/MoonWorks.Test.Common/Content/Textures/ravioli.png differ
diff --git a/tests/MoonWorks.Test.Common/CopyMoonlibs.targets b/tests/MoonWorks.Test.Common/CopyMoonlibs.targets
new file mode 100644
index 0000000..c1b4245
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/CopyMoonlibs.targets
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+ %(RecursiveDir)%(Filename)%(Extension)
+ PreserveNewest
+
+
+ %(RecursiveDir)%(Filename)%(Extension)
+ PreserveNewest
+
+
+ %(RecursiveDir)%(Filename)%(Extension)
+ PreserveNewest
+
+
+
+
+ %(RecursiveDir)%(Filename)%(Extension)
+ PreserveNewest
+
+
+ %(RecursiveDir)%(Filename)%(Extension)
+ PreserveNewest
+
+
+ %(RecursiveDir)%(Filename)%(Extension)
+ PreserveNewest
+
+
+
+
+ %(RecursiveDir)%(Filename)%(Extension)
+ PreserveNewest
+
+
+
+
diff --git a/tests/MoonWorks.Test.Common/MoonWorks.Test.Common.csproj b/tests/MoonWorks.Test.Common/MoonWorks.Test.Common.csproj
new file mode 100644
index 0000000..5c33609
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/MoonWorks.Test.Common.csproj
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ library
+ net6.0
+ enable
+ x64
+
+
+
+
+
diff --git a/tests/MoonWorks.Test.Common/TestUtils.cs b/tests/MoonWorks.Test.Common/TestUtils.cs
new file mode 100644
index 0000000..801b467
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/TestUtils.cs
@@ -0,0 +1,53 @@
+using MoonWorks.Graphics;
+
+namespace MoonWorks.Test
+{
+ public static class TestUtils
+ {
+ public static WindowCreateInfo GetStandardWindowCreateInfo()
+ {
+ return new WindowCreateInfo(
+ "Main Window",
+ 640,
+ 480,
+ ScreenMode.Windowed,
+ PresentMode.FIFO
+ );
+ }
+
+ public static FrameLimiterSettings GetStandardFrameLimiterSettings()
+ {
+ return new FrameLimiterSettings(
+ FrameLimiterMode.Capped,
+ 60
+ );
+ }
+
+ public static GraphicsPipelineCreateInfo GetStandardGraphicsPipelineCreateInfo(
+ ShaderModule vertShaderModule,
+ ShaderModule fragShaderModule
+ ) {
+ return new GraphicsPipelineCreateInfo
+ {
+ AttachmentInfo = new GraphicsPipelineAttachmentInfo(
+ new ColorAttachmentDescription(
+ TextureFormat.R8G8B8A8,
+ ColorAttachmentBlendState.Opaque
+ )
+ ),
+ DepthStencilState = DepthStencilState.Disable,
+ MultisampleState = MultisampleState.None,
+ PrimitiveType = PrimitiveType.TriangleList,
+ RasterizerState = RasterizerState.CW_CullNone,
+ VertexInputState = VertexInputState.Empty,
+ VertexShaderInfo = GraphicsShaderInfo.Create(vertShaderModule, "main", 0),
+ FragmentShaderInfo = GraphicsShaderInfo.Create(fragShaderModule, "main", 0)
+ };
+ }
+
+ public static string GetShaderPath(string shaderName)
+ {
+ return SDL2.SDL.SDL_GetBasePath() + "Content/Shaders/Compiled/" + shaderName;
+ }
+ }
+}
diff --git a/tests/MoonWorks.Test.Common/VertexTypes.cs b/tests/MoonWorks.Test.Common/VertexTypes.cs
new file mode 100644
index 0000000..fe7c1c9
--- /dev/null
+++ b/tests/MoonWorks.Test.Common/VertexTypes.cs
@@ -0,0 +1,32 @@
+using System.Runtime.InteropServices;
+using MoonWorks.Graphics;
+using MoonWorks.Math.Float;
+
+namespace MoonWorks.Test
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct PositionColorVertex
+ {
+ public Vector3 Position;
+ public Color Color;
+
+ public PositionColorVertex(Vector3 position, Color color)
+ {
+ Position = position;
+ Color = color;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct PositionTextureVertex
+ {
+ public Vector3 Position;
+ public Vector2 TexCoord;
+
+ public PositionTextureVertex(Vector3 position, Vector2 texCoord)
+ {
+ Position = position;
+ TexCoord = texCoord;
+ }
+ }
+}
diff --git a/tests/TexturedAnimatedQuad/TexturedAnimatedQuad.csproj b/tests/TexturedAnimatedQuad/TexturedAnimatedQuad.csproj
new file mode 100644
index 0000000..e0a93fd
--- /dev/null
+++ b/tests/TexturedAnimatedQuad/TexturedAnimatedQuad.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+ Exe
+ net6.0
+ enable
+ x64
+
+
+
+
+ Content\%(RecursiveDir)%(Filename)%(Extension)
+ Always
+
+
+
+
diff --git a/tests/TexturedAnimatedQuad/TexturedAnimatedQuadGame.cs b/tests/TexturedAnimatedQuad/TexturedAnimatedQuadGame.cs
new file mode 100644
index 0000000..e1ee4d9
--- /dev/null
+++ b/tests/TexturedAnimatedQuad/TexturedAnimatedQuadGame.cs
@@ -0,0 +1,121 @@
+using System.Runtime.InteropServices;
+using MoonWorks;
+using MoonWorks.Graphics;
+using MoonWorks.Math.Float;
+
+namespace MoonWorks.Test
+{
+ class TexturedAnimatedQuadGame : Game
+ {
+ private GraphicsPipeline pipeline;
+ private ShaderModule vertShaderModule;
+ private ShaderModule fragShaderModule;
+ private Buffer vertexBuffer;
+ private Buffer indexBuffer;
+ private Texture texture;
+ private Sampler sampler;
+
+ private float t;
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct VertexUniforms
+ {
+ public Matrix4x4 TransformMatrix;
+
+ public VertexUniforms(Matrix4x4 transformMatrix)
+ {
+ TransformMatrix = transformMatrix;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct FragmentUniforms
+ {
+ public Vector4 MultiplyColor;
+
+ public FragmentUniforms(Vector4 multiplyColor)
+ {
+ MultiplyColor = multiplyColor;
+ }
+ }
+
+ public TexturedAnimatedQuadGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
+ {
+ // Load the shaders
+ vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuadAnimatedVert.spv"));
+ fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuadAnimatedFrag.spv"));
+
+ // Create the graphics pipeline
+ GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(vertShaderModule, fragShaderModule);
+ pipelineCreateInfo.VertexInputState = new VertexInputState(
+ VertexBinding.Create(),
+ VertexAttribute.Create("Position", 0),
+ VertexAttribute.Create("TexCoord", 1)
+ );
+ pipelineCreateInfo.VertexShaderInfo = GraphicsShaderInfo.Create(vertShaderModule, "main", 0);
+ pipelineCreateInfo.FragmentShaderInfo = GraphicsShaderInfo.Create(fragShaderModule, "main", 1);
+ pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ // Create and populate the GPU resources
+ vertexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Vertex, 4);
+ indexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Index, 6);
+ sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
+
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ cmdbuf.SetBufferData(
+ vertexBuffer,
+ new PositionTextureVertex[]
+ {
+ new PositionTextureVertex(new Vector3(-1, -1, 0), new Vector2(0, 0)),
+ new PositionTextureVertex(new Vector3(1, -1, 0), new Vector2(1, 0)),
+ new PositionTextureVertex(new Vector3(1, 1, 0), new Vector2(1, 1)),
+ new PositionTextureVertex(new Vector3(-1, 1, 0), new Vector2(0, 1)),
+ }
+ );
+ cmdbuf.SetBufferData(
+ indexBuffer,
+ new ushort[]
+ {
+ 0, 1, 2,
+ 0, 2, 3,
+ }
+ );
+ texture = Texture.LoadPNG(GraphicsDevice, cmdbuf, "Content/Textures/ravioli.png");
+ GraphicsDevice.Submit(cmdbuf);
+ GraphicsDevice.Wait();
+ }
+
+ protected override void Update(System.TimeSpan delta)
+ {
+ t += (float) delta.TotalSeconds;
+ }
+
+ protected override void Draw(double alpha)
+ {
+ VertexUniforms vertUniforms = new VertexUniforms(Matrix4x4.CreateRotationZ(t));
+ FragmentUniforms fragUniforms = new FragmentUniforms(new Vector4(1f, 0.5f + System.MathF.Sin(t) * 0.5f, 1f, 1f));
+
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
+ if (backbuffer != null)
+ {
+ cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black));
+ cmdbuf.BindGraphicsPipeline(pipeline);
+ cmdbuf.BindVertexBuffers(vertexBuffer);
+ cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.Sixteen);
+ cmdbuf.PushVertexShaderUniforms(vertUniforms);
+ cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(texture, sampler));
+ cmdbuf.PushFragmentShaderUniforms(fragUniforms);
+ cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, 0);
+ cmdbuf.EndRenderPass();
+ }
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ public static void Main(string[] args)
+ {
+ TexturedAnimatedQuadGame game = new TexturedAnimatedQuadGame();
+ game.Run();
+ }
+ }
+}
diff --git a/tests/TexturedQuad/TexturedQuad.csproj b/tests/TexturedQuad/TexturedQuad.csproj
new file mode 100644
index 0000000..9538ed1
--- /dev/null
+++ b/tests/TexturedQuad/TexturedQuad.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+ Exe
+ net6.0
+ enable
+ x64
+
+
+
+
+ Content\%(RecursiveDir)%(Filename)%(Extension)
+ Always
+
+
+
+
diff --git a/tests/TexturedQuad/TexturedQuadGame.cs b/tests/TexturedQuad/TexturedQuadGame.cs
new file mode 100644
index 0000000..e2e3086
--- /dev/null
+++ b/tests/TexturedQuad/TexturedQuadGame.cs
@@ -0,0 +1,134 @@
+using MoonWorks;
+using MoonWorks.Graphics;
+using MoonWorks.Math.Float;
+
+namespace MoonWorks.Test
+{
+ class TexturedQuadGame : Game
+ {
+ private GraphicsPipeline pipeline;
+ private ShaderModule vertShaderModule;
+ private ShaderModule fragShaderModule;
+ private Buffer vertexBuffer;
+ private Buffer indexBuffer;
+ private Texture texture;
+ private Sampler[] samplers = new Sampler[6];
+ private string[] samplerNames = new string[]
+ {
+ "PointClamp",
+ "PointWrap",
+ "LinearClamp",
+ "LinearWrap",
+ "AnisotropicClamp",
+ "AnisotropicWrap"
+ };
+
+ private int currentSamplerIndex;
+
+ public TexturedQuadGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
+ {
+ Logger.LogInfo("Press A and D to cycle between sampler states");
+ Logger.LogInfo("Setting sampler state to: " + samplerNames[0]);
+
+ // Load the shaders
+ vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuadVert.spv"));
+ fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuadFrag.spv"));
+
+ // Create the graphics pipeline
+ GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(vertShaderModule, fragShaderModule);
+ pipelineCreateInfo.VertexInputState = new VertexInputState(
+ VertexBinding.Create(),
+ VertexAttribute.Create("Position", 0),
+ VertexAttribute.Create("TexCoord", 1)
+ );
+ pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
+ pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ // Create samplers
+ samplers[0] = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
+ samplers[1] = new Sampler(GraphicsDevice, SamplerCreateInfo.PointWrap);
+ samplers[2] = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearClamp);
+ samplers[3] = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearWrap);
+ samplers[4] = new Sampler(GraphicsDevice, SamplerCreateInfo.AnisotropicClamp);
+ samplers[5] = new Sampler(GraphicsDevice, SamplerCreateInfo.AnisotropicWrap);
+
+ // Create and populate the GPU resources
+ vertexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Vertex, 4);
+ indexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Index, 6);
+
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ cmdbuf.SetBufferData(
+ vertexBuffer,
+ new PositionTextureVertex[]
+ {
+ new PositionTextureVertex(new Vector3(-1, -1, 0), new Vector2(0, 0)),
+ new PositionTextureVertex(new Vector3(1, -1, 0), new Vector2(4, 0)),
+ new PositionTextureVertex(new Vector3(1, 1, 0), new Vector2(4, 4)),
+ new PositionTextureVertex(new Vector3(-1, 1, 0), new Vector2(0, 4)),
+ }
+ );
+ cmdbuf.SetBufferData(
+ indexBuffer,
+ new ushort[]
+ {
+ 0, 1, 2,
+ 0, 2, 3,
+ }
+ );
+ texture = Texture.LoadPNG(GraphicsDevice, cmdbuf, "Content/Textures/ravioli.png");
+ GraphicsDevice.Submit(cmdbuf);
+ GraphicsDevice.Wait();
+ }
+
+ protected override void Update(System.TimeSpan delta)
+ {
+ int prevSamplerIndex = currentSamplerIndex;
+
+ if (Inputs.Keyboard.IsPressed(Input.KeyCode.A))
+ {
+ currentSamplerIndex -= 1;
+ if (currentSamplerIndex < 0)
+ {
+ currentSamplerIndex = samplers.Length - 1;
+ }
+ }
+
+ if (Inputs.Keyboard.IsPressed(Input.KeyCode.D))
+ {
+ currentSamplerIndex += 1;
+ if (currentSamplerIndex >= samplers.Length)
+ {
+ currentSamplerIndex = 0;
+ }
+ }
+
+ if (prevSamplerIndex != currentSamplerIndex)
+ {
+ Logger.LogInfo("Setting sampler state to: " + samplerNames[currentSamplerIndex]);
+ }
+ }
+
+ protected override void Draw(double alpha)
+ {
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
+ if (backbuffer != null)
+ {
+ cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black));
+ cmdbuf.BindGraphicsPipeline(pipeline);
+ cmdbuf.BindVertexBuffers(vertexBuffer);
+ cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.Sixteen);
+ cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(texture, samplers[currentSamplerIndex]));
+ cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, 0);
+ cmdbuf.EndRenderPass();
+ }
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ public static void Main(string[] args)
+ {
+ TexturedQuadGame game = new TexturedQuadGame();
+ game.Run();
+ }
+ }
+}
diff --git a/tests/TriangleVertexBuffer/TriangleVertexBuffer.csproj b/tests/TriangleVertexBuffer/TriangleVertexBuffer.csproj
new file mode 100644
index 0000000..9538ed1
--- /dev/null
+++ b/tests/TriangleVertexBuffer/TriangleVertexBuffer.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+ Exe
+ net6.0
+ enable
+ x64
+
+
+
+
+ Content\%(RecursiveDir)%(Filename)%(Extension)
+ Always
+
+
+
+
diff --git a/tests/TriangleVertexBuffer/TriangleVertexBufferGame.cs b/tests/TriangleVertexBuffer/TriangleVertexBufferGame.cs
new file mode 100644
index 0000000..8e7eab0
--- /dev/null
+++ b/tests/TriangleVertexBuffer/TriangleVertexBufferGame.cs
@@ -0,0 +1,69 @@
+using MoonWorks;
+using MoonWorks.Graphics;
+using MoonWorks.Math.Float;
+
+namespace MoonWorks.Test
+{
+ class TriangleVertexBufferGame : Game
+ {
+ private GraphicsPipeline pipeline;
+ private ShaderModule vertShaderModule;
+ private ShaderModule fragShaderModule;
+ private Buffer vertexBuffer;
+
+ public TriangleVertexBufferGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
+ {
+ // Load the shaders
+ vertShaderModule = new ShaderModule(GraphicsDevice, "Content/Shaders/Compiled/PositionColorVert.spv");
+ fragShaderModule = new ShaderModule(GraphicsDevice, "Content/Shaders/Compiled/SolidColor.spv");
+
+ // Create the graphics pipeline
+ GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(vertShaderModule, fragShaderModule);
+ pipelineCreateInfo.VertexInputState = new VertexInputState(
+ VertexBinding.Create(),
+ VertexAttribute.Create("Position", 0),
+ VertexAttribute.Create("Color", 1)
+ );
+ pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ // Create and populate the vertex buffer
+ vertexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Vertex, 3);
+
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ cmdbuf.SetBufferData(
+ vertexBuffer,
+ new PositionColorVertex[]
+ {
+ new PositionColorVertex(new Vector3(-1, 1, 0), Color.Red),
+ new PositionColorVertex(new Vector3(1, 1, 0), Color.Lime),
+ new PositionColorVertex(new Vector3(0, -1, 0), Color.Blue),
+ }
+ );
+ GraphicsDevice.Submit(cmdbuf);
+ GraphicsDevice.Wait();
+ }
+
+ protected override void Update(System.TimeSpan delta) { }
+
+ protected override void Draw(double alpha)
+ {
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
+ if (backbuffer != null)
+ {
+ cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black));
+ cmdbuf.BindGraphicsPipeline(pipeline);
+ cmdbuf.BindVertexBuffers(vertexBuffer);
+ cmdbuf.DrawPrimitives(0, 1, 0, 0);
+ cmdbuf.EndRenderPass();
+ }
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ public static void Main(string[] args)
+ {
+ TriangleVertexBufferGame p = new TriangleVertexBufferGame();
+ p.Run();
+ }
+ }
+}