diff --git a/BasicCompute/BasicCompute.csproj b/BasicCompute/BasicCompute.csproj
new file mode 100644
index 0000000..a8d5981
--- /dev/null
+++ b/BasicCompute/BasicCompute.csproj
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+ Exe
+ net6.0
+ enable
+ x64
+
+
+
diff --git a/BasicCompute/BasicComputeGame.cs b/BasicCompute/BasicComputeGame.cs
new file mode 100644
index 0000000..77874cd
--- /dev/null
+++ b/BasicCompute/BasicComputeGame.cs
@@ -0,0 +1,108 @@
+using MoonWorks;
+using MoonWorks.Graphics;
+using MoonWorks.Math.Float;
+
+namespace MoonWorks.Test
+{
+ class BasicComputeGame : Game
+ {
+ private GraphicsPipeline drawPipeline;
+ private Texture texture;
+ private Sampler sampler;
+ private Buffer vertexBuffer;
+
+ public BasicComputeGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
+ {
+ ShaderModule computeShaderModule = new ShaderModule(
+ GraphicsDevice,
+ TestUtils.GetShaderPath("FillTextureCompute.spv")
+ );
+
+ ComputePipeline computePipeline = new ComputePipeline(
+ GraphicsDevice,
+ ComputeShaderInfo.Create(computeShaderModule, "main", 0, 1)
+ );
+
+ ShaderModule vertShaderModule = new ShaderModule(
+ GraphicsDevice,
+ TestUtils.GetShaderPath("TexturedQuadVert.spv")
+ );
+
+ ShaderModule fragShaderModule = new ShaderModule(
+ GraphicsDevice,
+ TestUtils.GetShaderPath("TexturedQuadFrag.spv")
+ );
+
+ GraphicsPipelineCreateInfo drawPipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
+ vertShaderModule,
+ fragShaderModule
+ );
+ drawPipelineCreateInfo.VertexInputState = new VertexInputState(
+ VertexBinding.Create(),
+ VertexAttribute.Create("Position", 0),
+ VertexAttribute.Create("TexCoord", 1)
+ );
+ drawPipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
+
+ drawPipeline = new GraphicsPipeline(
+ GraphicsDevice,
+ drawPipelineCreateInfo
+ );
+
+ vertexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Vertex, 6);
+
+ // Create the texture that will be filled in by the compute pipeline
+ texture = Texture.CreateTexture2D(
+ GraphicsDevice,
+ MainWindow.Width,
+ MainWindow.Height,
+ TextureFormat.R8G8B8A8,
+ TextureUsageFlags.Compute | TextureUsageFlags.Sampler
+ );
+ sampler = new Sampler(GraphicsDevice, new SamplerCreateInfo());
+
+ // Populate the vertex buffer and run the compute shader to generate the texture data
+ 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, 0)),
+ new PositionTextureVertex(new Vector3(1, 1, 0), new Vector2(1, 1)),
+ new PositionTextureVertex(new Vector3(-1, 1, 0), new Vector2(0, 1)),
+ });
+
+ cmdbuf.BindComputePipeline(computePipeline);
+ cmdbuf.BindComputeTextures(texture);
+ cmdbuf.DispatchCompute(MainWindow.Width / 8, MainWindow.Height / 8, 1, 0);
+
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ 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.BindGraphicsPipeline(drawPipeline);
+ cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(texture, sampler));
+ cmdbuf.BindVertexBuffers(vertexBuffer);
+ cmdbuf.DrawPrimitives(0, 2, 0, 0);
+ cmdbuf.EndRenderPass();
+ }
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ public static void Main(string[] args)
+ {
+ BasicComputeGame game = new BasicComputeGame();
+ game.Run();
+ }
+ }
+}
diff --git a/MoonWorks.Test.Common/Content/Shaders/Compiled/FillTextureCompute.spv b/MoonWorks.Test.Common/Content/Shaders/Compiled/FillTextureCompute.spv
new file mode 100644
index 0000000..07b7b82
Binary files /dev/null and b/MoonWorks.Test.Common/Content/Shaders/Compiled/FillTextureCompute.spv differ
diff --git a/MoonWorks.Test.Common/Content/Shaders/Source/FillTextureCompute.comp b/MoonWorks.Test.Common/Content/Shaders/Source/FillTextureCompute.comp
new file mode 100644
index 0000000..8828003
--- /dev/null
+++ b/MoonWorks.Test.Common/Content/Shaders/Source/FillTextureCompute.comp
@@ -0,0 +1,17 @@
+#version 450
+
+layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+layout (set = 1, binding = 0, rgba8) uniform writeonly image2D outImage;
+
+void main()
+{
+ ivec2 coord = ivec2(gl_GlobalInvocationID.xy);
+ vec3 totalWorkgroupSize = gl_NumWorkGroups * gl_WorkGroupSize;
+ vec4 col = vec4(
+ float(coord.x) / totalWorkgroupSize.x,
+ float(coord.y) / totalWorkgroupSize.y,
+ 1.0,
+ 1.0
+ );
+ imageStore(outImage, coord, col);
+}
diff --git a/MoonWorksGraphicsTests.sln b/MoonWorksGraphicsTests.sln
index 32fcc2a..eb87a27 100644
--- a/MoonWorksGraphicsTests.sln
+++ b/MoonWorksGraphicsTests.sln
@@ -27,6 +27,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MoonWorks", "..\MoonWorks\M
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cube", "Cube\Cube.csproj", "{C3808AFD-23DD-4622-BFA7-981A344D0C19}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicCompute", "BasicCompute\BasicCompute.csproj", "{68D47057-BBCB-4F86-9C0A-D6D730B18D9E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -81,6 +83,10 @@ Global
{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Debug|x64.Build.0 = Debug|x64
{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Release|x64.ActiveCfg = Release|Any CPU
{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Release|x64.Build.0 = Release|Any CPU
+ {68D47057-BBCB-4F86-9C0A-D6D730B18D9E}.Debug|x64.ActiveCfg = Debug|x64
+ {68D47057-BBCB-4F86-9C0A-D6D730B18D9E}.Debug|x64.Build.0 = Debug|x64
+ {68D47057-BBCB-4F86-9C0A-D6D730B18D9E}.Release|x64.ActiveCfg = Release|Any CPU
+ {68D47057-BBCB-4F86-9C0A-D6D730B18D9E}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/README.md b/README.md
index 3f0706b..199bfbc 100644
--- a/README.md
+++ b/README.md
@@ -39,3 +39,7 @@ Sets buffer data, gets the data back from the GPU, and prints the results to the
**Cube**
Renders a cubemap skybox and a spinning cube. Tests depth textures, sampling from depth textures, depth-only render passes, cube textures, and 32-bit index buffers.
+
+**BasicCompute**
+
+Uses a compute pipeline to fill a texture with data, then displays it to the screen. Tests compute pipeline creation and compute dispatching.