diff --git a/Cube/Cube.csproj b/Cube/Cube.csproj
new file mode 100644
index 0000000..a8d5981
--- /dev/null
+++ b/Cube/Cube.csproj
@@ -0,0 +1,15 @@
+
+
+  
+    
+    
+  
+
+  
+    Exe
+    net6.0
+    enable
+    x64
+  
+
+
diff --git a/Cube/CubeGame.cs b/Cube/CubeGame.cs
new file mode 100644
index 0000000..e1ac5b5
--- /dev/null
+++ b/Cube/CubeGame.cs
@@ -0,0 +1,358 @@
+using MoonWorks;
+using MoonWorks.Graphics;
+using MoonWorks.Math;
+using MoonWorks.Math.Float;
+using System.Threading.Tasks;
+
+namespace MoonWorks.Test
+{
+    class CubeGame : Game
+    {
+        private GraphicsPipeline cubePipeline;
+        private GraphicsPipeline skyboxPipeline;
+        private Texture depthTexture;
+        private Buffer cubeVertexBuffer;
+        private Buffer skyboxVertexBuffer;
+        private Buffer indexBuffer;
+        private Texture skyboxTexture;
+        private Sampler skyboxSampler;
+        private bool finishedLoading;
+
+        private float cubeTimer = 0f;
+        private Quaternion cubeRotation = Quaternion.Identity;
+        private Quaternion previousCubeRotation = Quaternion.Identity;
+
+        struct Uniforms
+        {
+            public Matrix4x4 ViewProjection;
+
+            public Uniforms(Matrix4x4 viewProjection)
+            {
+                ViewProjection = viewProjection;
+            }
+        }
+
+        void LoadCubemap(CommandBuffer cmdbuf, string[] imagePaths)
+        {
+            System.IntPtr textureData;
+            int w, h, numChannels;
+
+            for (uint i = 0; i < imagePaths.Length; i++)
+            {
+                textureData = RefreshCS.Refresh.Refresh_Image_Load(
+                    imagePaths[i],
+                    out w,
+                    out h,
+                    out numChannels
+                );
+                cmdbuf.SetTextureData(
+                    new TextureSlice(
+                        skyboxTexture,
+                        new Rect(0, 0, w, h),
+                        0,
+                        i
+                    ),
+                    textureData,
+                    (uint) (w * h * 4) // w * h * numChannels does not work
+                );
+                RefreshCS.Refresh.Refresh_Image_Free(textureData);
+            }
+        }
+
+        public CubeGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
+        {
+            ShaderModule cubeVertShaderModule = new ShaderModule(
+                GraphicsDevice,
+                TestUtils.GetShaderPath("PositionColorVertWithMatrix.spv")
+            );
+            ShaderModule cubeFragShaderModule = new ShaderModule(
+                GraphicsDevice,
+                TestUtils.GetShaderPath("SolidColor.spv")
+            );
+
+            ShaderModule skyboxVertShaderModule = new ShaderModule(
+                GraphicsDevice,
+                TestUtils.GetShaderPath("SkyboxVert.spv")
+            );
+            ShaderModule skyboxFragShaderModule = new ShaderModule(
+                GraphicsDevice,
+                TestUtils.GetShaderPath("SkyboxFrag.spv")
+            );
+
+            depthTexture = Texture.CreateTexture2D(
+                GraphicsDevice,
+                MainWindow.Width,
+                MainWindow.Height,
+                TextureFormat.D16,
+                TextureUsageFlags.DepthStencilTarget
+            );
+
+            skyboxTexture = Texture.CreateTextureCube(
+                GraphicsDevice,
+                2048,
+                TextureFormat.R8G8B8A8,
+                TextureUsageFlags.Sampler
+            );
+            skyboxSampler = new Sampler(GraphicsDevice, new SamplerCreateInfo());
+
+            cubeVertexBuffer = Buffer.Create(
+                GraphicsDevice,
+                BufferUsageFlags.Vertex,
+                24
+            );
+            skyboxVertexBuffer = Buffer.Create(
+                GraphicsDevice,
+                BufferUsageFlags.Vertex,
+                24
+            );
+            indexBuffer = Buffer.Create(
+                GraphicsDevice,
+                BufferUsageFlags.Index,
+                36
+            ); // Using uint here just to test IndexElementSize=32
+
+            Task loadingTask = Task.Run(() => UploadGPUAssets());
+
+            cubePipeline = new GraphicsPipeline(
+                GraphicsDevice,
+                new GraphicsPipelineCreateInfo
+                {
+                    AttachmentInfo = new GraphicsPipelineAttachmentInfo(
+                        TextureFormat.D16,
+                        new ColorAttachmentDescription(
+                            MainWindow.SwapchainFormat,
+                            ColorAttachmentBlendState.Opaque
+                        )
+                    ),
+                    DepthStencilState = DepthStencilState.DepthReadWrite,
+                    VertexShaderInfo = GraphicsShaderInfo.Create(cubeVertShaderModule, "main", 0),
+                    VertexInputState = new VertexInputState(
+                        VertexBinding.Create(),
+                        VertexAttribute.Create("Position", 0),
+                        VertexAttribute.Create("Color", 1)
+                    ),
+                    PrimitiveType = PrimitiveType.TriangleList,
+                    FragmentShaderInfo = GraphicsShaderInfo.Create(cubeFragShaderModule, "main", 0),
+                    RasterizerState = RasterizerState.CW_CullBack,
+                    MultisampleState = MultisampleState.None
+                }
+            );
+
+            skyboxPipeline = new GraphicsPipeline(
+                GraphicsDevice,
+                new GraphicsPipelineCreateInfo
+                {
+                    AttachmentInfo = new GraphicsPipelineAttachmentInfo(
+					    TextureFormat.D16,
+					    new ColorAttachmentDescription(
+						    MainWindow.SwapchainFormat,
+						    ColorAttachmentBlendState.Opaque
+					    )
+				    ),
+				    DepthStencilState = DepthStencilState.DepthReadWrite,
+				    VertexShaderInfo = GraphicsShaderInfo.Create(skyboxVertShaderModule, "main", 0),
+				    VertexInputState = new VertexInputState(
+					    VertexBinding.Create(),
+					    VertexAttribute.Create("Position", 0)
+				    ),
+				    PrimitiveType = PrimitiveType.TriangleList,
+				    FragmentShaderInfo = GraphicsShaderInfo.Create(skyboxFragShaderModule, "main", 1),
+				    RasterizerState = RasterizerState.CW_CullNone,
+				    MultisampleState = MultisampleState.None,
+                }
+            );
+        }
+
+        private void UploadGPUAssets()
+        {
+            Logger.LogInfo("Loading...");
+
+            CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+
+            cmdbuf.SetBufferData(
+                cubeVertexBuffer,
+                new PositionColorVertex[]
+                {
+                    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))
+                }
+            );
+
+            cmdbuf.SetBufferData(
+			    skyboxVertexBuffer,
+			    new PositionVertex[]
+			    {
+				    new PositionVertex(new Vector3(-10, -10, -10)),
+				    new PositionVertex(new Vector3(10, -10, -10)),
+				    new PositionVertex(new Vector3(10, 10, -10)),
+				    new PositionVertex(new Vector3(-10, 10, -10)),
+
+				    new PositionVertex(new Vector3(-10, -10, 10)),
+				    new PositionVertex(new Vector3(10, -10, 10)),
+				    new PositionVertex(new Vector3(10, 10, 10)),
+				    new PositionVertex(new Vector3(-10, 10, 10)),
+
+				    new PositionVertex(new Vector3(-10, -10, -10)),
+				    new PositionVertex(new Vector3(-10, 10, -10)),
+				    new PositionVertex(new Vector3(-10, 10, 10)),
+				    new PositionVertex(new Vector3(-10, -10, 10)),
+
+				    new PositionVertex(new Vector3(10, -10, -10)),
+				    new PositionVertex(new Vector3(10, 10, -10)),
+				    new PositionVertex(new Vector3(10, 10, 10)),
+				    new PositionVertex(new Vector3(10, -10, 10)),
+
+				    new PositionVertex(new Vector3(-10, -10, -10)),
+				    new PositionVertex(new Vector3(-10, -10, 10)),
+				    new PositionVertex(new Vector3(10, -10, 10)),
+				    new PositionVertex(new Vector3(10, -10, -10)),
+
+				    new PositionVertex(new Vector3(-10, 10, -10)),
+				    new PositionVertex(new Vector3(-10, 10, 10)),
+				    new PositionVertex(new Vector3(10, 10, 10)),
+				    new PositionVertex(new Vector3(10, 10, -10))
+			    }
+		    );
+
+            cmdbuf.SetBufferData(
+                indexBuffer,
+                new uint[]
+                {
+                    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
+                }
+            );
+
+            LoadCubemap(cmdbuf, new string[]
+		    {
+			    TestUtils.GetTexturePath("right.png"),
+			    TestUtils.GetTexturePath("left.png"),
+			    TestUtils.GetTexturePath("top.png"),
+			    TestUtils.GetTexturePath("bottom.png"),
+			    TestUtils.GetTexturePath("front.png"),
+			    TestUtils.GetTexturePath("back.png")
+		    });
+
+            GraphicsDevice.Submit(cmdbuf);
+
+            finishedLoading = true;
+            Logger.LogInfo("Finished loading!");
+        }
+
+        protected override void Update(System.TimeSpan delta)
+        {
+            cubeTimer += (float) delta.TotalSeconds;
+
+            previousCubeRotation = cubeRotation;
+
+            cubeRotation = Quaternion.CreateFromYawPitchRoll(
+                cubeTimer * 2f,
+                0,
+                cubeTimer * 2f
+            );
+        }
+
+        protected override void Draw(double alpha)
+        {
+            Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView(
+                MathHelper.ToRadians(75f),
+                (float) MainWindow.Width / MainWindow.Height,
+                0.01f,
+                100f
+            );
+            Matrix4x4 view = Matrix4x4.CreateLookAt(
+                new Vector3(0, 1.5f, 4f),
+                Vector3.Zero,
+                Vector3.Up
+            );
+            Uniforms skyboxUniforms = new Uniforms(view * proj);
+
+            Matrix4x4 model = Matrix4x4.CreateFromQuaternion(
+                Quaternion.Slerp(
+                    previousCubeRotation,
+                    cubeRotation,
+                    (float) alpha
+                )
+            );
+            Uniforms cubeUniforms = new Uniforms(model * view * proj);
+
+            CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+            Texture? swapchainTexture = cmdbuf.AcquireSwapchainTexture(MainWindow);
+            if (swapchainTexture != null)
+            {
+                if (!finishedLoading)
+                {
+                    float sine = System.MathF.Abs(System.MathF.Sin(cubeTimer));
+                    Color clearColor = new Color(sine, sine, sine);
+
+                    // Just show a clear screen.
+                    cmdbuf.BeginRenderPass(new ColorAttachmentInfo(swapchainTexture, clearColor));
+                    cmdbuf.EndRenderPass();
+                }
+                else
+                {
+                    cmdbuf.BeginRenderPass(
+                        new DepthStencilAttachmentInfo(depthTexture, new DepthStencilValue(1f, 0)),
+                        new ColorAttachmentInfo(swapchainTexture, Color.CornflowerBlue)
+                    );
+
+                    // Draw cube
+                    cmdbuf.BindGraphicsPipeline(cubePipeline);
+                    cmdbuf.BindVertexBuffers(cubeVertexBuffer);
+                    cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.ThirtyTwo);
+                    uint vertexParamOffset = cmdbuf.PushVertexShaderUniforms(cubeUniforms);
+                    cmdbuf.DrawIndexedPrimitives(0, 0, 12, vertexParamOffset, 0);
+
+                    // Draw skybox
+                    cmdbuf.BindGraphicsPipeline(skyboxPipeline);
+                    cmdbuf.BindVertexBuffers(skyboxVertexBuffer);
+                    cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.ThirtyTwo);
+                    cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(skyboxTexture, skyboxSampler));
+                    vertexParamOffset = cmdbuf.PushVertexShaderUniforms(skyboxUniforms);
+                    cmdbuf.DrawIndexedPrimitives(0, 0, 12, vertexParamOffset, 0);
+
+                    cmdbuf.EndRenderPass();
+                }
+            }
+
+            GraphicsDevice.Submit(cmdbuf);
+        }
+
+        public static void Main(string[] args)
+        {
+            CubeGame game = new CubeGame();
+            game.Run();
+        }
+    }
+}
diff --git a/CullFace/CullFaceGame.cs b/CullFace/CullFaceGame.cs
index d4226c4..8ce915e 100644
--- a/CullFace/CullFaceGame.cs
+++ b/CullFace/CullFaceGame.cs
@@ -4,7 +4,7 @@ using MoonWorks.Math.Float;
 
 namespace MoonWorks.Test
 {
-	internal class CullFaceGame : Game
+	class CullFaceGame : Game
 	{
 		private GraphicsPipeline CW_CullNonePipeline;
 		private GraphicsPipeline CW_CullFrontPipeline;
diff --git a/GetBufferData/GetBufferDataGame.cs b/GetBufferData/GetBufferDataGame.cs
index f95ee03..7eb7197 100644
--- a/GetBufferData/GetBufferDataGame.cs
+++ b/GetBufferData/GetBufferDataGame.cs
@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
 
 namespace MoonWorks.Test
 {
-    internal class GetBufferDataGame : Game
+    class GetBufferDataGame : Game
     {
         public GetBufferDataGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
         {
diff --git a/MoonWorks.Test.Common/Content/Shaders/Compiled/PositionColorVertWithMatrix.spv b/MoonWorks.Test.Common/Content/Shaders/Compiled/PositionColorVertWithMatrix.spv
new file mode 100644
index 0000000..033f897
Binary files /dev/null and b/MoonWorks.Test.Common/Content/Shaders/Compiled/PositionColorVertWithMatrix.spv differ
diff --git a/MoonWorks.Test.Common/Content/Shaders/Compiled/SkyboxFrag.spv b/MoonWorks.Test.Common/Content/Shaders/Compiled/SkyboxFrag.spv
new file mode 100644
index 0000000..b7b8249
Binary files /dev/null and b/MoonWorks.Test.Common/Content/Shaders/Compiled/SkyboxFrag.spv differ
diff --git a/MoonWorks.Test.Common/Content/Shaders/Compiled/SkyboxVert.spv b/MoonWorks.Test.Common/Content/Shaders/Compiled/SkyboxVert.spv
new file mode 100644
index 0000000..4c4a358
Binary files /dev/null and b/MoonWorks.Test.Common/Content/Shaders/Compiled/SkyboxVert.spv differ
diff --git a/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadAnimatedFrag.spv b/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadFragWithMultiplyColor.spv
similarity index 100%
rename from MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadAnimatedFrag.spv
rename to MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadFragWithMultiplyColor.spv
diff --git a/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadAnimatedVert.spv b/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadVertWithMatrix.spv
similarity index 100%
rename from MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadAnimatedVert.spv
rename to MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedQuadVertWithMatrix.spv
diff --git a/MoonWorks.Test.Common/Content/Shaders/Source/PositionColorVertWithMatrix.vert b/MoonWorks.Test.Common/Content/Shaders/Source/PositionColorVertWithMatrix.vert
new file mode 100644
index 0000000..899c06a
--- /dev/null
+++ b/MoonWorks.Test.Common/Content/Shaders/Source/PositionColorVertWithMatrix.vert
@@ -0,0 +1,17 @@
+#version 450
+
+layout (location = 0) in vec3 Position;
+layout (location = 1) in vec4 Color;
+
+layout (location = 0) out vec4 outColor;
+
+layout (binding = 0, set = 2) uniform UniformBlock
+{
+	mat4x4 MatrixTransform;
+};
+
+void main()
+{
+	outColor = Color;
+	gl_Position = MatrixTransform * vec4(Position, 1);
+}
diff --git a/MoonWorks.Test.Common/Content/Shaders/Source/SkyboxFrag.frag b/MoonWorks.Test.Common/Content/Shaders/Source/SkyboxFrag.frag
new file mode 100644
index 0000000..905b196
--- /dev/null
+++ b/MoonWorks.Test.Common/Content/Shaders/Source/SkyboxFrag.frag
@@ -0,0 +1,11 @@
+#version 450
+
+layout(location = 0) in vec3 TexCoord;
+layout(location = 0) out vec4 FragColor;
+
+layout(binding = 0, set = 1) uniform samplerCube SkyboxSampler;
+
+void main()
+{
+    FragColor = texture(SkyboxSampler, TexCoord);
+}
diff --git a/MoonWorks.Test.Common/Content/Shaders/Source/SkyboxVert.vert b/MoonWorks.Test.Common/Content/Shaders/Source/SkyboxVert.vert
new file mode 100644
index 0000000..9cd3885
--- /dev/null
+++ b/MoonWorks.Test.Common/Content/Shaders/Source/SkyboxVert.vert
@@ -0,0 +1,15 @@
+#version 450
+
+layout(location = 0) in vec3 inPos;
+layout(location = 0) out vec3 vPos;
+
+layout(set = 2, binding = 0) uniform UBO
+{
+	mat4 ViewProjection;
+} ubo;
+
+void main()
+{
+    vPos = inPos;
+    gl_Position = ubo.ViewProjection * vec4(inPos, 1.0);
+}
diff --git a/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadAnimatedFrag.frag b/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadFragWithMultiplyColor.frag
similarity index 100%
rename from MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadAnimatedFrag.frag
rename to MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadFragWithMultiplyColor.frag
diff --git a/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadAnimatedVert.vert b/MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadVertWithMatrix.vert
similarity index 100%
rename from MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadAnimatedVert.vert
rename to MoonWorks.Test.Common/Content/Shaders/Source/TexturedQuadVertWithMatrix.vert
diff --git a/MoonWorks.Test.Common/Content/Textures/back.png b/MoonWorks.Test.Common/Content/Textures/back.png
new file mode 100644
index 0000000..f269d39
Binary files /dev/null and b/MoonWorks.Test.Common/Content/Textures/back.png differ
diff --git a/MoonWorks.Test.Common/Content/Textures/bottom.png b/MoonWorks.Test.Common/Content/Textures/bottom.png
new file mode 100644
index 0000000..2479502
Binary files /dev/null and b/MoonWorks.Test.Common/Content/Textures/bottom.png differ
diff --git a/MoonWorks.Test.Common/Content/Textures/front.png b/MoonWorks.Test.Common/Content/Textures/front.png
new file mode 100644
index 0000000..fc9f4b9
Binary files /dev/null and b/MoonWorks.Test.Common/Content/Textures/front.png differ
diff --git a/MoonWorks.Test.Common/Content/Textures/left.png b/MoonWorks.Test.Common/Content/Textures/left.png
new file mode 100644
index 0000000..1e78960
Binary files /dev/null and b/MoonWorks.Test.Common/Content/Textures/left.png differ
diff --git a/MoonWorks.Test.Common/Content/Textures/right.png b/MoonWorks.Test.Common/Content/Textures/right.png
new file mode 100644
index 0000000..ea5d966
Binary files /dev/null and b/MoonWorks.Test.Common/Content/Textures/right.png differ
diff --git a/MoonWorks.Test.Common/Content/Textures/top.png b/MoonWorks.Test.Common/Content/Textures/top.png
new file mode 100644
index 0000000..57a8b3b
Binary files /dev/null and b/MoonWorks.Test.Common/Content/Textures/top.png differ
diff --git a/MoonWorks.Test.Common/TestUtils.cs b/MoonWorks.Test.Common/TestUtils.cs
index 801b467..bd4dcfa 100644
--- a/MoonWorks.Test.Common/TestUtils.cs
+++ b/MoonWorks.Test.Common/TestUtils.cs
@@ -49,5 +49,10 @@ namespace MoonWorks.Test
 		{
 			return SDL2.SDL.SDL_GetBasePath() + "Content/Shaders/Compiled/" + shaderName;
 		}
+
+		public static string GetTexturePath(string textureName)
+		{
+			return SDL2.SDL.SDL_GetBasePath() + "Content/Textures/" + textureName;
+		}
 	}
 }
diff --git a/MoonWorks.Test.Common/VertexTypes.cs b/MoonWorks.Test.Common/VertexTypes.cs
index feebea4..b25b520 100644
--- a/MoonWorks.Test.Common/VertexTypes.cs
+++ b/MoonWorks.Test.Common/VertexTypes.cs
@@ -5,6 +5,22 @@ using MoonWorks.Math.Float;
 namespace MoonWorks.Test
 {
 	[StructLayout(LayoutKind.Sequential)]
+	public struct PositionVertex
+	{
+		public Vector3 Position;
+
+		public PositionVertex(Vector3 position)
+		{
+			Position = position;
+		}
+
+		public override string ToString()
+        {
+			return Position.ToString();
+		}
+	}
+
+    [StructLayout(LayoutKind.Sequential)]
 	public struct PositionColorVertex
 	{
 		public Vector3 Position;
diff --git a/MoonWorksGraphicsTests.sln b/MoonWorksGraphicsTests.sln
index bc028bf..32fcc2a 100644
--- a/MoonWorksGraphicsTests.sln
+++ b/MoonWorksGraphicsTests.sln
@@ -25,6 +25,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GetBufferData", "GetBufferD
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MoonWorks", "..\MoonWorks\MoonWorks.csproj", "{1695B1D8-4935-490C-A5EC-E2F2AA94B150}"
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cube", "Cube\Cube.csproj", "{C3808AFD-23DD-4622-BFA7-981A344D0C19}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|x64 = Debug|x64
@@ -75,6 +77,10 @@ Global
 		{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Debug|x64.Build.0 = Debug|x64
 		{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Release|x64.ActiveCfg = Release|x64
 		{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Release|x64.Build.0 = Release|x64
+		{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Debug|x64.ActiveCfg = Debug|x64
+		{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
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/README.md b/README.md
index d378937..ee763b2 100644
--- a/README.md
+++ b/README.md
@@ -35,3 +35,7 @@ Draws several triangles with various culling modes and winding orders.
 **GetBufferData**
 
 Sets buffer data, gets the data back from the GPU, and prints the results to the console.
+
+**Cube**
+
+Renders a cubemap skybox and a spinning cube. Tests depth texture, cube texture, and 32-bit index buffers.
diff --git a/TexturedAnimatedQuad/TexturedAnimatedQuadGame.cs b/TexturedAnimatedQuad/TexturedAnimatedQuadGame.cs
index bbdf66d..2e4ea9a 100644
--- a/TexturedAnimatedQuad/TexturedAnimatedQuadGame.cs
+++ b/TexturedAnimatedQuad/TexturedAnimatedQuadGame.cs
@@ -81,7 +81,7 @@ namespace MoonWorks.Test
 					0, 2, 3,
 				}
 			);
-			texture = Texture.LoadPNG(GraphicsDevice, cmdbuf, "Content/Textures/ravioli.png");
+			texture = Texture.LoadPNG(GraphicsDevice, cmdbuf, TestUtils.GetTexturePath("ravioli.png"));
 			GraphicsDevice.Submit(cmdbuf);
 			GraphicsDevice.Wait();
 		}
@@ -104,10 +104,10 @@ namespace MoonWorks.Test
 				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);
+				uint vertParamOffset = cmdbuf.PushVertexShaderUniforms(vertUniforms);
+				uint fragParamOffset = cmdbuf.PushFragmentShaderUniforms(fragUniforms);
+				cmdbuf.DrawIndexedPrimitives(0, 0, 2, vertParamOffset, fragParamOffset);
 				cmdbuf.EndRenderPass();
 			}
 			GraphicsDevice.Submit(cmdbuf);
diff --git a/TexturedQuad/TexturedQuadGame.cs b/TexturedQuad/TexturedQuadGame.cs
index b0a3b58..ab93b5e 100644
--- a/TexturedQuad/TexturedQuadGame.cs
+++ b/TexturedQuad/TexturedQuadGame.cs
@@ -76,7 +76,7 @@ namespace MoonWorks.Test
 					0, 2, 3,
 				}
 			);
-			texture = Texture.LoadPNG(GraphicsDevice, cmdbuf, "Content/Textures/ravioli.png");
+			texture = Texture.LoadPNG(GraphicsDevice, cmdbuf, TestUtils.GetTexturePath("ravioli.png"));
 			GraphicsDevice.Submit(cmdbuf);
 			GraphicsDevice.Wait();
 		}