From: Jean-Philippe Bruyère Date: Tue, 28 Mar 2023 09:31:27 +0000 (+0200) Subject: test compute rasterization X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=a78be85e8826bc252afbd2a9833d70766d68b7ef;p=jp%2Fvke.net.git test compute rasterization --- diff --git a/.vscode/launch.json b/.vscode/launch.json index f0d49ed..4a31790 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -43,6 +43,28 @@ "stopAtEntry": false, "console": "internalConsole" }, + { + "name": ".NET Core Launch (FillTests)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build FillTests", + "program": "${workspaceFolder}/build/Debug/netcoreapp3.1/FillTests", + "args": [], + "cwd": "${workspaceFolder}/build/Debug/netcoreapp3.1/", + "stopAtEntry": false, + "console": "internalConsole" + }, + { + "name": ".NET Core Launch (DynamicRendering)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build DynamicRendering", + "program": "${workspaceFolder}/build/Debug/netcoreapp3.1/DynamicRendering", + "args": [], + "cwd": "${workspaceFolder}/build/Debug/netcoreapp3.1/", + "stopAtEntry": false, + "console": "internalConsole" + }, { "name": ".NET Core Launch (MeshShader)", "type": "coreclr", @@ -68,7 +90,12 @@ "args": [], "cwd": "${workspaceFolder}/build/Debug/netcoreapp3.1/", "stopAtEntry": false, - "console": "internalConsole" + "console": "internalConsole", + "env": { + "VK_ICD_FILENAMES": "/opt/share/vulkan/icd.d/radeon_icd.x86_64.json", + "RADV_PERFTEST": "rt,ext_ms", + "LD_LIBARY_PATH": "/opt/lib/x86_64-linux-gnu/" + } }, { "name": ".NET Core Launch (ExternalMemmories)", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index e1657dd..d7522d2 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -57,6 +57,34 @@ ], "problemMatcher": "$msCompile" }, + { + "label": "build FillTests", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/samples/FillTests/FillTests.csproj", + "/property:GenerateFullPaths=true", + "/property:SolutionDir=${workspaceFolder}/", + "/property:Configuration=Debug", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "build DynamicRendering", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/samples/DynamicRendering/DynamicRendering.csproj", + "/property:GenerateFullPaths=true", + "/property:SolutionDir=${workspaceFolder}/", + "/property:Configuration=Debug", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, { "label": "build MeshShader", "command": "dotnet", diff --git a/samples/DynamicRendering/DynamicRendering.csproj b/samples/DynamicRendering/DynamicRendering.csproj new file mode 100644 index 0000000..672fb5a --- /dev/null +++ b/samples/DynamicRendering/DynamicRendering.csproj @@ -0,0 +1,5 @@ + + + false + + diff --git a/samples/DynamicRendering/main.cs b/samples/DynamicRendering/main.cs new file mode 100644 index 0000000..beb4bc5 --- /dev/null +++ b/samples/DynamicRendering/main.cs @@ -0,0 +1,161 @@ +// Copyright (c) 2023 Jean-Philippe Bruyère +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) +using System; +using System.Numerics; +using System.Runtime.InteropServices; +using vke; +using Vulkan; +using Glfw; + +//the traditional triangle sample with dynamic rendeging aithout framebuffers +namespace FillTests { + class Program : SampleBase { + static void Main (string[] args) { +#if DEBUG + Instance.VALIDATION = true; +#endif + using (Program vke = new Program ()) { + vke.Run (); + } + } + public override string[] EnabledInstanceExtensions => new string[] + { + Ext.I.VK_KHR_get_physical_device_properties2 + }; + public override string[] EnabledDeviceExtensions => new string[] + { + Ext.D.VK_KHR_swapchain, + Ext.D.VK_KHR_dynamic_rendering, + Ext.D.VK_KHR_depth_stencil_resolve, + }; + + const float rotSpeed = 0.01f, zoomSpeed = 0.01f; + float rotX, rotY, zoom = 1f; + + //vertex structure + [StructLayout(LayoutKind.Sequential)] + struct Vertex { + Vector3 position; + Vector3 color; + + public Vertex (float x, float y, float z, float r, float g, float b) { + position = new Vector3 (x, y, z); + color = new Vector3 (r, g, b); + } + } + + HostBuffer ibo; //a host mappable buffer to hold the indices. + HostBuffer vbo; //a host mappable buffer to hold vertices. + HostBuffer uboMVPmatrix; //a host mappable buffer for mvp matrice. + + DescriptorPool descriptorPool; + DescriptorSet descriptorSet;//descriptor set for the mvp matrice. + GraphicPipeline pipeline; //the triangle rendering pipeline + + //triangle vertices (position + color per vertex) and indices. + Vertex[] vertices = { + new Vertex (-1.0f, -1.0f, 0.0f , 1.0f, 0.0f, 0.0f), + new Vertex ( 1.0f, -1.0f, 0.0f , 0.0f, 1.0f, 0.0f), + new Vertex ( 0.0f, 1.0f, 0.0f , 0.0f, 0.0f, 1.0f), + }; + ushort[] indices = new ushort[] { 0, 1, 2 }; + + protected override void initVulkan () { + base.initVulkan (); + + vbo = new HostBuffer (dev, VkBufferUsageFlags.VertexBuffer, vertices); + ibo = new HostBuffer (dev, VkBufferUsageFlags.IndexBuffer, indices); + uboMVPmatrix = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, 1, true); + + descriptorPool = new DescriptorPool (dev, 1, new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer)); + + using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false)) { + cfg.Layout = new PipelineLayout (dev, + new DescriptorSetLayout (dev, new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex, VkDescriptorType.UniformBuffer))); + cfg.AddVertexBinding (0); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat);//position + color + + cfg.AddShaders ( + new ShaderInfo (dev, VkShaderStageFlags.Vertex, "#shaders.main.vert.spv"), + new ShaderInfo (dev, VkShaderStageFlags.Fragment, "#shaders.main.frag.spv") + ); + + pipeline = new GraphicPipeline (dev, cfg); + } + + descriptorSet = descriptorPool.Allocate (pipeline.Layout.DescriptorSetLayouts[0]); + + DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descriptorSet, pipeline.Layout.DescriptorSetLayouts[0]); + uboUpdate.Write (dev, uboMVPmatrix.Descriptor); + + cmds = cmdPool.AllocateCommandBuffer (swapChain.ImageCount); + } + + //view update override, see base method for more informations. + public override void UpdateView () { + uboMVPmatrix.AsSpan()[0] = + Matrix4x4.CreateFromAxisAngle (Vector3.UnitY, rotY) * + Matrix4x4.CreateFromAxisAngle (Vector3.UnitX, rotX) * + Matrix4x4.CreateTranslation (0, 0, -3f * zoom) * + Helpers.CreatePerspectiveFieldOfView (Helpers.DegreesToRadians (45f), (float)swapChain.Width / (float)swapChain.Height, 0.1f, 256.0f); + + base.UpdateView (); + } + protected override void onMouseMove (double xPos, double yPos) { + double diffX = lastMouseX - xPos; + double diffY = lastMouseY - yPos; + if (GetButton (MouseButton.Left) == InputAction.Press) { + rotY -= rotSpeed * (float)diffX; + rotX += rotSpeed * (float)diffY; + updateViewRequested = true; + } else if (GetButton (MouseButton.Right) == InputAction.Press) { + zoom += zoomSpeed * (float)diffY; + updateViewRequested = true; + } + } + + void buildCommandBuffers(PrimaryCommandBuffer cmd) { + cmd.Start (); + + cmd.SetViewport (swapChain.Width, swapChain.Height); + cmd.SetScissor (swapChain.Width, swapChain.Height); + + cmd.BindDescriptorSet (pipeline.Layout, descriptorSet); + + cmd.BindPipeline (pipeline); + + cmd.BindVertexBuffer (vbo); + cmd.BindIndexBuffer (ibo, VkIndexType.Uint16); + cmd.DrawIndexed ((uint)indices.Length); + + cmd.End (); + } + + protected override void OnResize () { + base.OnResize (); + + updateViewRequested = true; + + cmdPool.Reset (VkCommandPoolResetFlags.ReleaseResources); + + for (int i = 0; i < swapChain.ImageCount; ++i) + buildCommandBuffers (cmds[i]); + } + //clean up + protected override void Dispose (bool disposing) { + dev.WaitIdle (); + if (disposing) { + if (!isDisposed) { + pipeline.Dispose (); + descriptorPool.Dispose (); + vbo.Dispose (); + ibo.Dispose (); + uboMVPmatrix.Dispose (); + } + } + + base.Dispose (disposing); + } + } +} diff --git a/samples/DynamicRendering/shaders/main.frag b/samples/DynamicRendering/shaders/main.frag new file mode 100644 index 0000000..85aeb08 --- /dev/null +++ b/samples/DynamicRendering/shaders/main.frag @@ -0,0 +1,12 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec3 inColor; +layout (location = 0) out vec4 outFragColor; + +void main() +{ + outFragColor = vec4(inColor, 1.0); +} \ No newline at end of file diff --git a/samples/DynamicRendering/shaders/main.vert b/samples/DynamicRendering/shaders/main.vert new file mode 100644 index 0000000..40a3796 --- /dev/null +++ b/samples/DynamicRendering/shaders/main.vert @@ -0,0 +1,26 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec3 inColor; + +layout (binding = 0) uniform UBO +{ + mat4 mvp; +}; + +layout (location = 0) out vec3 outColor; + +out gl_PerVertex +{ + vec4 gl_Position; +}; + + +void main() +{ + outColor = inColor; + gl_Position = mvp * vec4(inPos.xyz, 1.0); +} diff --git a/samples/FillTests/FillTests.csproj b/samples/FillTests/FillTests.csproj new file mode 100644 index 0000000..672fb5a --- /dev/null +++ b/samples/FillTests/FillTests.csproj @@ -0,0 +1,5 @@ + + + false + + diff --git a/samples/FillTests/main.cs b/samples/FillTests/main.cs new file mode 100644 index 0000000..4c8abf6 --- /dev/null +++ b/samples/FillTests/main.cs @@ -0,0 +1,261 @@ +// Copyright (c) 2023 Jean-Philippe Bruyère +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) +using System; +using System.Numerics; +using System.Runtime.InteropServices; +using vke; +using Vulkan; +using Glfw; + +namespace FillTests { + + class Program : SampleBase { + static void Main (string[] args) { +#if DEBUG + Instance.VALIDATION = true; + Instance.RENDER_DOC_CAPTURE = true; +#endif + using (Program vke = new Program ()) { + vke.Run (); + } + } + + + FrameBuffers frameBuffers; //the frame buffer collection coupled to the swapchain images + FrameBuffer fbContour; + + [StructLayout(LayoutKind.Sequential)] + struct Vertex { + Vector2 position; + UInt32 contourID; + public Vertex (float x, float y, UInt32 _contourID) { + position = new Vector2 (x, y); + contourID = _contourID; + } + } + //triangle vertices (position + color per vertex) and indices. + /*Vertex[] vertices = { + new Vertex (10.0f, 210.0f, 1), + new Vertex (100.0f, 220.0f, 1), + new Vertex (50.0f, 270.0f, 1), + new Vertex (10.0f, 210.0f, 1), + };*/ + /*Vertex[] vertices = { + new Vertex (100.0f, 210.0f, 1), + new Vertex (200.0f, 120.0f, 1), + new Vertex (350.0f, 270.0f, 1), + new Vertex (150.0f, 310.0f, 1), + new Vertex (100.0f, 210.0f, 1) + };*/ + Vertex[] vertices = { + new Vertex (100.0f, 100.0f, 1), + new Vertex (500.0f, 400.0f, 1), + new Vertex (450.0f, 150.0f, 1), + new Vertex (120.0f, 420.0f, 1), + new Vertex (100.0f, 100.0f, 1) + }; + HostBuffer vbo; + GraphicPipeline plContours; + GraphicPipeline plFSQ; + ComputePipeline plComp; + DescriptorPool descriptorPool; + DescriptorSet dsComp, dsFSQ;//descriptor set for the mvp matrice. + vke.Image imgContour, imgColor; + + VkFormat rastFormat = VkFormat.B8g8r8a8Uint; + const VkSampleCountFlags contourSamplesCount = VkSampleCountFlags.SampleCount1; + + + protected override void initVulkan () { + base.initVulkan (); + + UpdateFrequency = 1; + + vbo = new HostBuffer (dev, VkBufferUsageFlags.VertexBuffer, vertices); + vbo.SetName("vbo"); + + using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.LineStrip, contourSamplesCount, false)) { + cfg.Layout = new PipelineLayout (dev, + new VkPushConstantRange (VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf())); + cfg.RenderPass = new RenderPass (dev, contourSamplesCount); + cfg.RenderPass.AddAttachment(rastFormat, VkImageLayout.General, contourSamplesCount, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.Store, VkImageLayout.General); + cfg.RenderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + cfg.RenderPass.AddSubpass(new SubPass (VkImageLayout.ColorAttachmentOptimal)); + cfg.RenderPass.AddDependency (Vk.SubpassExternal, 0, + VkPipelineStageFlags.ComputeShader, VkPipelineStageFlags.ColorAttachmentOutput, + VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentWrite); + cfg.RenderPass.AddDependency (0, Vk.SubpassExternal, + VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.ComputeShader, + VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryWrite); + + + cfg.AddVertexBinding (0); + cfg.AddVertexAttributes (0, VkFormat.R32g32Sfloat, VkFormat.R32Uint);//position + color + cfg.AddShaders ( + new ShaderInfo (dev, VkShaderStageFlags.Vertex, "#shaders.contour.vert.spv"), + new ShaderInfo (dev, VkShaderStageFlags.Fragment, "#shaders.contour.frag.spv") + ); + plContours = new GraphicPipeline (cfg); + } + + //uboMVPmatrix = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, 1, true); + + descriptorPool = new DescriptorPool (dev, 2, + new VkDescriptorPoolSize (VkDescriptorType.StorageImage, 2), + new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 1) + ); + + + using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, contourSamplesCount, false)) { + cfg.Layout = new PipelineLayout (dev, new DescriptorSetLayout(dev, + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler))); + cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, VkSampleCountFlags.SampleCount1); + cfg.RenderPass.ClearValues[0] = new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }; + cfg.AddVertexBinding (0); + cfg.AddVertexAttributes (0, VkFormat.R32g32Sfloat, VkFormat.R32g32b32Sfloat);//position + color + cfg.AddShaders ( + new ShaderInfo (dev, VkShaderStageFlags.Vertex, "#vke.FullScreenQuad.vert.spv"), + new ShaderInfo (dev, VkShaderStageFlags.Fragment, "#shaders.simpletexture.frag.spv") + ); + plFSQ = new GraphicPipeline (cfg); + } + + + plComp = new ComputePipeline ( + new PipelineLayout (dev, + new VkPushConstantRange (VkShaderStageFlags.Compute, sizeof (float)), + new DescriptorSetLayout(dev, + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Compute, VkDescriptorType.StorageImage), + new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Compute, VkDescriptorType.StorageImage))), + "#shaders.test.comp.spv"); + + dsComp = descriptorPool.Allocate (plComp.Layout.DescriptorSetLayouts[0]); + dsFSQ = descriptorPool.Allocate (plFSQ.Layout.DescriptorSetLayouts[0]); + + cmds = cmdPool.AllocateCommandBuffer (swapChain.ImageCount); + } + + //view update override, see base method for more informations. + public override void UpdateView () { + + base.UpdateView (); + } + protected override void onMouseMove (double xPos, double yPos) { + + } + + void stroke() { + PrimaryCommandBuffer cmd = cmdPool.AllocateAndStart(VkCommandBufferUsageFlags.OneTimeSubmit); + + imgContour.SetLayout(cmd, VkImageAspectFlags.Color, VkImageLayout.ColorAttachmentOptimal); + + plContours.RenderPass.Begin (cmd, fbContour); + + cmd.SetViewport (swapChain.Width, swapChain.Height); + cmd.SetScissor (swapChain.Width, swapChain.Height); + //cmd.BindDescriptorSet (pipeline.Layout, descriptorSet); + + cmd.BindPipeline (plContours); + cmd.PushConstant (plContours.Layout, VkShaderStageFlags.Vertex, new Vector2(swapChain.Width, swapChain.Height)); + + cmd.BindVertexBuffer (vbo); + cmd.Draw ((uint)vertices.Length); + + plContours.RenderPass.End (cmd); + + imgContour.SetLayout(cmd, VkImageAspectFlags.Color,VkImageLayout.ColorAttachmentOptimal, VkImageLayout.General); + imgColor.SetLayout(cmd, VkImageAspectFlags.Color, VkImageLayout.General); + + cmd.BindPipeline(plComp, VkPipelineBindPoint.Compute); + plComp.BindDescriptorSet(cmd,dsComp); + + cmd.Dispatch(swapChain.Height); + + this.presentQueue.EndSubmitAndWait(cmd, true); + } + void buildCommandBuffer(PrimaryCommandBuffer cmd, FrameBuffer fb) { + cmd.Start (); + + imgColor.SetLayout(cmd, VkImageAspectFlags.Color, VkImageLayout.ColorAttachmentOptimal); + + plFSQ.RenderPass.Begin (cmd, fb); + + cmd.BindPipeline (plFSQ); + cmd.SetViewport (swapChain.Width, swapChain.Height); + cmd.SetScissor (swapChain.Width, swapChain.Height); + cmd.BindDescriptorSet (plFSQ.Layout, dsFSQ); + + cmd.Draw (3); + + plFSQ.RenderPass.End (cmd); + + cmd.End (); + } + void buildCommandBuffers() { + cmdPool.Reset (VkCommandPoolResetFlags.ReleaseResources); + + stroke(); + + for (int i = 0; i < swapChain.ImageCount; ++i) { + buildCommandBuffer(cmds[i], frameBuffers[i]); + } + } + public override void Update() + { + dev.WaitIdle(); + stroke(); + } + protected override void OnResize () { + base.OnResize (); + + updateViewRequested = true; + + frameBuffers?.Dispose(); + frameBuffers = plFSQ.RenderPass.CreateFrameBuffers(swapChain); + + imgContour?.Dispose(); + imgContour = new vke.Image (dev, rastFormat, VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.Storage, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, contourSamplesCount); + imgContour.CreateView(); + + fbContour = new FrameBuffer(plContours.RenderPass, swapChain.Width, swapChain.Height, 1, imgContour); + + imgColor?.Dispose(); + imgColor = new vke.Image (dev, VkFormat.R8g8b8a8Unorm, VkImageUsageFlags.Sampled | VkImageUsageFlags.Storage, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, contourSamplesCount); + imgColor.CreateSampler(); + imgColor.CreateView(); + + + DescriptorSetWrites compUpdate = new DescriptorSetWrites (dsComp, plComp.Layout.DescriptorSetLayouts[0]); + imgColor.Descriptor.imageLayout = VkImageLayout.General; + imgContour.Descriptor.imageLayout = VkImageLayout.General; + compUpdate.Write (dev, imgContour.Descriptor, imgColor.Descriptor); + + DescriptorSetWrites fsqUpdate = new DescriptorSetWrites (dsFSQ, plFSQ.Layout.DescriptorSetLayouts[0]); + imgColor.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + fsqUpdate.Write (dev, imgColor.Descriptor); + + buildCommandBuffers (); + + } + //clean up + protected override void Dispose (bool disposing) { + dev.WaitIdle (); + if (disposing) { + if (!isDisposed) { + plContours.Dispose(); + plComp.Dispose (); + plFSQ.Dispose(); + imgContour?.Dispose(); + imgColor?.Dispose(); + frameBuffers?.Dispose(); + fbContour.Dispose(); + descriptorPool.Dispose (); + vbo.Dispose (); + } + } + + base.Dispose (disposing); + } + } +} diff --git a/samples/FillTests/shaders/contour.frag b/samples/FillTests/shaders/contour.frag new file mode 100644 index 0000000..631e45a --- /dev/null +++ b/samples/FillTests/shaders/contour.frag @@ -0,0 +1,12 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in flat uint inContourID; +layout (location = 0) out uvec4 outFragColor; + +void main() +{ + outFragColor = uvec4(1u << gl_PrimitiveID, inContourID, 0, 1); +} \ No newline at end of file diff --git a/samples/FillTests/shaders/contour.vert b/samples/FillTests/shaders/contour.vert new file mode 100644 index 0000000..e38ef7b --- /dev/null +++ b/samples/FillTests/shaders/contour.vert @@ -0,0 +1,23 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec2 inPos; +layout (location = 1) in uint inContourID; + +layout(push_constant) uniform PushConsts { + vec2 size; +}; + +out gl_PerVertex +{ + vec4 gl_Position; +}; + +layout (location = 0) out flat uint outContourID; + +void main() +{ + gl_Position = vec4(inPos.xy * vec2(2) / size - vec2(1), 0.0, 1.0); +} diff --git a/samples/FillTests/shaders/main.frag b/samples/FillTests/shaders/main.frag new file mode 100644 index 0000000..85aeb08 --- /dev/null +++ b/samples/FillTests/shaders/main.frag @@ -0,0 +1,12 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec3 inColor; +layout (location = 0) out vec4 outFragColor; + +void main() +{ + outFragColor = vec4(inColor, 1.0); +} \ No newline at end of file diff --git a/samples/FillTests/shaders/main.vert b/samples/FillTests/shaders/main.vert new file mode 100644 index 0000000..40a3796 --- /dev/null +++ b/samples/FillTests/shaders/main.vert @@ -0,0 +1,26 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec3 inColor; + +layout (binding = 0) uniform UBO +{ + mat4 mvp; +}; + +layout (location = 0) out vec3 outColor; + +out gl_PerVertex +{ + vec4 gl_Position; +}; + + +void main() +{ + outColor = inColor; + gl_Position = mvp * vec4(inPos.xyz, 1.0); +} diff --git a/samples/FillTests/shaders/simpletexture.frag b/samples/FillTests/shaders/simpletexture.frag new file mode 100644 index 0000000..a081876 --- /dev/null +++ b/samples/FillTests/shaders/simpletexture.frag @@ -0,0 +1,15 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (set = 0, binding = 0) uniform sampler2D samplerColor; + +layout (location = 0) in vec2 inUV; + +layout (location = 0) out vec4 outFragColor; + +void main() +{ + outFragColor = texture(samplerColor, inUV); +} diff --git a/samples/FillTests/shaders/test.comp b/samples/FillTests/shaders/test.comp new file mode 100644 index 0000000..c68fc0d --- /dev/null +++ b/samples/FillTests/shaders/test.comp @@ -0,0 +1,65 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (set = 0, binding = 0, rgba8ui) readonly uniform uimage2D inputImage; +layout (set = 0, binding = 1, rgba8) writeonly uniform image2D outputImage; + +layout(push_constant) uniform PushConsts { + float halfWidth; +}; + + +layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +void main() +{ + int count=0; + ivec2 is = imageSize(inputImage); + int c = 0; + uint[64] contourStates; + for(int i=0; i 0) { + imageStore(outputImage, uv, vec4(1.f,0.f,0.f,1.f)); + + uint lastState = contourStates[contourID]; + contourStates[contourID] = contourStates[contourID] | primID; + + if (contourStates[contourID] != lastState) { + uint bc = bitCount(contourStates[contourID]); + if ((bc % 2) != 0) { + if (start >= 0) { + for(int j=start; j= 0) { + for(int j=start; j new string[] { Ext.I.VK_KHR_get_physical_device_properties2, - Ext.I.VK_EXT_debug_utils, + //Ext.I.VK_EXT_debug_utils, }; public override string[] EnabledDeviceExtensions => new string[] { Ext.D.VK_KHR_swapchain, @@ -74,7 +74,7 @@ namespace MeshShader { uboMVPmatrix = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, 1, true); descriptorPool = new DescriptorPool (dev, 1, new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer)); - using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false)) { + using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount8, false)) { cfg.Layout = new PipelineLayout (dev, new DescriptorSetLayout (dev, new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.MeshEXT, VkDescriptorType.UniformBuffer))); cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, cfg.Samples); diff --git a/samples/Triangle/main.cs b/samples/Triangle/main.cs index aabed92..c52f292 100644 --- a/samples/Triangle/main.cs +++ b/samples/Triangle/main.cs @@ -9,11 +9,11 @@ using Vulkan; using Glfw; //the traditional triangle sample -namespace Triangle { +namespace FillTests { class Program : SampleBase { static void Main (string[] args) { #if DEBUG - Instance.VALIDATION = true; + //Instance.VALIDATION = true; #endif using (Program vke = new Program ()) { vke.Run (); diff --git a/samples/common/SampleBase.cs b/samples/common/SampleBase.cs index d6a3a64..3564d29 100644 --- a/samples/common/SampleBase.cs +++ b/samples/common/SampleBase.cs @@ -10,11 +10,11 @@ namespace vke { base.initVulkan(); #if DEBUG - foreach (VkPhysicalDeviceToolProperties toolProp in phy.GetToolProperties()) { + /*foreach (VkPhysicalDeviceToolProperties toolProp in phy.GetToolProperties()) { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine ($"Enabled Tool: {toolProp.name}({toolProp.version})"); Console.ResetColor (); - } + }*/ #endif } } diff --git a/samples/compute/main.cs b/samples/compute/main.cs index 29b244d..bb317f3 100644 --- a/samples/compute/main.cs +++ b/samples/compute/main.cs @@ -6,6 +6,7 @@ using System.Runtime.InteropServices; using System.Linq; using Vulkan; using vke; +using System.Threading; //very simple compute example that just do an addition on every items of a random list of numbers. namespace SimpleCompute { @@ -18,12 +19,9 @@ namespace SimpleCompute { Instance instance; PhysicalDevice phy; Device dev; + DescriptorSetLayout dsLayout; Queue computeQ; - HostBuffer inBuff, outBuff; - DescriptorPool dsPool; - DescriptorSetLayout dsLayout; - DescriptorSet dset; ComputePipeline plCompute; @@ -49,10 +47,7 @@ namespace SimpleCompute { createRandomDatas (); - inBuff = new HostBuffer (dev, VkBufferUsageFlags.StorageBuffer, datas); - outBuff = new HostBuffer (dev, VkBufferUsageFlags.StorageBuffer, data_size); - dsPool = new DescriptorPool (dev, 1, new VkDescriptorPoolSize (VkDescriptorType.StorageBuffer, 2)); dsLayout = new DescriptorSetLayout (dev, new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Compute, VkDescriptorType.StorageBuffer), new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Compute, VkDescriptorType.StorageBuffer) @@ -60,27 +55,58 @@ namespace SimpleCompute { plCompute = new ComputePipeline (new PipelineLayout (dev, dsLayout), "#shaders.compute.comp.spv" ); + } + const int threadCount = 64; + object printMutex = new object(); + void computeThread() { + HostBuffer inBuff, outBuff; + DescriptorPool dsPool; + DescriptorSet dset; + + inBuff = new HostBuffer (dev, VkBufferUsageFlags.StorageBuffer, datas); + outBuff = new HostBuffer (dev, VkBufferUsageFlags.StorageBuffer, data_size); + + dsPool = new DescriptorPool (dev, 1, new VkDescriptorPoolSize (VkDescriptorType.StorageBuffer, 2)); dset = dsPool.Allocate (dsLayout); DescriptorSetWrites dsUpdate = new DescriptorSetWrites (dset, dsLayout); dsUpdate.Write (dev, inBuff.Descriptor, outBuff.Descriptor); - } - public void Run () { using (CommandPool cmdPool = new CommandPool (dev, computeQ.qFamIndex)) { PrimaryCommandBuffer cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit); plCompute.Bind (cmd); plCompute.BindDescriptorSet (cmd, dset); cmd.Dispatch (data_size * sizeof (int)); cmd.End (); - - computeQ.Submit (cmd); + lock(computeQ) + computeQ.Submit (cmd); computeQ.WaitIdle (); } + lock(printMutex) + printResults (outBuff); - printResults (); + dsPool.Dispose (); + inBuff.Dispose (); + outBuff.Dispose (); + finishedThread++; + } + volatile int finishedThread = 0; + void createThreads () { + //Console.WriteLine ($"count down reset"); + for (int i = 0; i < threadCount; i++) { + Thread t = new Thread (computeThread); + t.IsBackground = true; + t.Start (); + } } - void printResults () { + public void Run () { + createThreads(); + while (finishedThread < threadCount) + Thread.Sleep(1); + dev.WaitIdle(); + } + + void printResults (HostBuffer outBuff) { int[] results = new int[data_size]; outBuff.Map (); @@ -105,10 +131,6 @@ namespace SimpleCompute { plCompute.Dispose (); dsLayout.Dispose (); - dsPool.Dispose (); - - inBuff.Dispose (); - outBuff.Dispose (); dev.Dispose (); instance.Dispose (); diff --git a/samples/compute/stroker.cs b/samples/compute/stroker.cs index 1a6e0a9..9a80a9a 100644 --- a/samples/compute/stroker.cs +++ b/samples/compute/stroker.cs @@ -147,7 +147,7 @@ namespace delaunay { bool rebuildBuffers = false; void buildCommandBuffers() { - cmdPool.Reset (VkCommandPoolResetFlags.ReleaseResources); + cmdPool.Reset (); for (int i = 0; i < swapChain.ImageCount; ++i) { FrameBuffer fb = frameBuffers[i]; diff --git a/samples/compute/test.cs b/samples/compute/test.cs index 80e66d4..5d1dbc6 100644 --- a/samples/compute/test.cs +++ b/samples/compute/test.cs @@ -1,7 +1,9 @@ using System; +using System.Numerics; using System.Runtime.InteropServices; -using CVKL; -using VK; +using Glfw; +using Vulkan; +using vke; using System.Linq; namespace test { @@ -53,7 +55,8 @@ namespace test { phy = instance.GetAvailablePhysicalDevice ().FirstOrDefault (); dev = new Device (phy); computeQ = new Queue (dev, VkQueueFlags.Compute); - dev.Activate (enabledFeatures, enabledExtensions); + + dev.Activate (IntPtr.Zero, enabledFeatures, enabledExtensions); datas = new float[data_size]; Random rnd = new Random (); @@ -72,7 +75,7 @@ namespace test { plCompute = new ComputePipeline ( new PipelineLayout (dev, new VkPushConstantRange (VkShaderStageFlags.Compute, sizeof (int)), dsLayoutCompute), - "#compute.computeTest.comp.spv" ); + "#shaders.computeTest.comp.spv" ); dsetPing = dsPool.Allocate (dsLayoutCompute); dsetPong = dsPool.Allocate (dsLayoutCompute); @@ -87,7 +90,7 @@ namespace test { public void Run () { using (CommandPool cmdPool = new CommandPool (dev, computeQ.qFamIndex)) { - CommandBuffer cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit); + PrimaryCommandBuffer cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit); bool pong = false; diff --git a/vke.net.sln b/vke.net.sln index a366bba..0219e5f 100644 --- a/vke.net.sln +++ b/vke.net.sln @@ -50,6 +50,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VulkanContext", "samples\Vu EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MeshShader", "samples\MeshShader\MeshShader.csproj", "{5787D082-7E4E-4B18-9C69-529CBC4F105E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamicRendering", "samples\DynamicRendering\DynamicRendering.csproj", "{3A0E5765-911E-4451-9715-ED55095D6C39}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FillTests", "samples\FillTests\FillTests.csproj", "{273C88AE-D095-4CF9-8D6F-D7ABE3E9C8D3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution BuildPackages|Any CPU = BuildPackages|Any CPU @@ -134,6 +138,22 @@ Global {5787D082-7E4E-4B18-9C69-529CBC4F105E}.Debug|Any CPU.Build.0 = Debug|Any CPU {5787D082-7E4E-4B18-9C69-529CBC4F105E}.Release|Any CPU.ActiveCfg = Release|Any CPU {5787D082-7E4E-4B18-9C69-529CBC4F105E}.Release|Any CPU.Build.0 = Release|Any CPU + {3A0E5765-911E-4451-9715-ED55095D6C39}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU + {3A0E5765-911E-4451-9715-ED55095D6C39}.BuildPackages|Any CPU.Build.0 = Debug|Any CPU + {3A0E5765-911E-4451-9715-ED55095D6C39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A0E5765-911E-4451-9715-ED55095D6C39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A0E5765-911E-4451-9715-ED55095D6C39}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A0E5765-911E-4451-9715-ED55095D6C39}.Release|Any CPU.Build.0 = Release|Any CPU + {3A0E5765-911E-4451-9715-ED55095D6C39}.ReleaseSpirVTasks|Any CPU.ActiveCfg = Debug|Any CPU + {3A0E5765-911E-4451-9715-ED55095D6C39}.ReleaseSpirVTasks|Any CPU.Build.0 = Debug|Any CPU + {273C88AE-D095-4CF9-8D6F-D7ABE3E9C8D3}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU + {273C88AE-D095-4CF9-8D6F-D7ABE3E9C8D3}.BuildPackages|Any CPU.Build.0 = Debug|Any CPU + {273C88AE-D095-4CF9-8D6F-D7ABE3E9C8D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {273C88AE-D095-4CF9-8D6F-D7ABE3E9C8D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {273C88AE-D095-4CF9-8D6F-D7ABE3E9C8D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {273C88AE-D095-4CF9-8D6F-D7ABE3E9C8D3}.Release|Any CPU.Build.0 = Release|Any CPU + {273C88AE-D095-4CF9-8D6F-D7ABE3E9C8D3}.ReleaseSpirVTasks|Any CPU.ActiveCfg = Debug|Any CPU + {273C88AE-D095-4CF9-8D6F-D7ABE3E9C8D3}.ReleaseSpirVTasks|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -153,6 +173,8 @@ Global {85CD9813-E182-4ED1-8D2C-38467657BEF3} = {16439374-B8DB-4643-8116-EB3358B49A12} {CF8755E1-9E8B-4AD2-A7D1-D66D797004AD} = {16439374-B8DB-4643-8116-EB3358B49A12} {5787D082-7E4E-4B18-9C69-529CBC4F105E} = {16439374-B8DB-4643-8116-EB3358B49A12} + {3A0E5765-911E-4451-9715-ED55095D6C39} = {16439374-B8DB-4643-8116-EB3358B49A12} + {273C88AE-D095-4CF9-8D6F-D7ABE3E9C8D3} = {16439374-B8DB-4643-8116-EB3358B49A12} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1360F94D-CF3C-4121-A8D7-E227F41668F1} diff --git a/vke/src/base/GraphicPipeline.cs b/vke/src/base/GraphicPipeline.cs index c20cd1f..4e70340 100644 --- a/vke/src/base/GraphicPipeline.cs +++ b/vke/src/base/GraphicPipeline.cs @@ -21,7 +21,8 @@ namespace vke { /// a managed Render pass that will be activated (if not already) during the pipeline creation. /// an optional pipeline cache to speed up pipeline creation. /// an optionnal name that will be used by the debug utils extension if enabled. - protected GraphicPipeline (RenderPass renderPass, PipelineCache cache = null, string name = "graphic pipeline") : base (renderPass.Dev, cache, name) { + protected GraphicPipeline (RenderPass renderPass, PipelineCache cache = null, string name = "graphic pipeline") : + base (renderPass?.Dev, cache, name) { RenderPass = renderPass; } /// @@ -29,18 +30,23 @@ namespace vke { /// public GraphicPipeline (GraphicPipelineConfig cfg, string name = "graphic pipeline") : this (cfg.RenderPass, cfg.Cache, name) { layout = cfg.Layout; - init (cfg); } - + /// + /// Create a new Graphic Pipeline with Dynamic rendering (without RenderPass) + /// + public GraphicPipeline (Device dev, GraphicPipelineConfig cfg, string name = "graphic pipeline") : base (dev, cfg.Cache, name) { + layout = cfg.Layout; + init (cfg); + } #endregion public override void Activate () => throw new NotSupportedException ("Please initialize graphic pipeline through the init method"); protected void init (GraphicPipelineConfig cfg) { if (state != ActivableState.Activated) { - Layout.Activate (); - RenderPass.Activate (); + Layout?.Activate (); + RenderPass?.Activate (); Cache?.Activate (); bool enableTesselation = false; @@ -79,8 +85,8 @@ namespace vke { viewportState.scissorCount = 1; VkGraphicsPipelineCreateInfo info = default; - info.renderPass = RenderPass.handle; - info.layout = Layout.handle; + info.renderPass = RenderPass == null ? 0 : RenderPass.handle; + info.layout = layout == null ? 0 : Layout.handle; info.pVertexInputState = vertInputInfo; info.pInputAssemblyState = cfg.inputAssemblyState; info.pRasterizationState = cfg.rasterizationState; @@ -120,7 +126,7 @@ namespace vke { protected override void Dispose (bool disposing) { if (disposing) { if (state == ActivableState.Activated) - RenderPass.Dispose (); + RenderPass?.Dispose (); } else System.Diagnostics.Debug.WriteLine ("GraphicPipeline disposed by finalizer"); diff --git a/vke/src/base/RenderPass.cs b/vke/src/base/RenderPass.cs index b5a977d..91a56ef 100644 --- a/vke/src/base/RenderPass.cs +++ b/vke/src/base/RenderPass.cs @@ -36,20 +36,19 @@ namespace vke { /// Create renderpass with a single color attachment and a resolve one if needed /// public RenderPass (Device device, VkFormat colorFormat, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1, VkAttachmentLoadOp loadOp = VkAttachmentLoadOp.Clear) - : this (device) { - Samples = samples; - - AddAttachment (colorFormat, (samples == VkSampleCountFlags.SampleCount1) ? VkImageLayout.PresentSrcKHR : VkImageLayout.ColorAttachmentOptimal, samples, - loadOp, VkAttachmentStoreOp.Store); + : this (device, samples) { ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); SubPass subpass0 = new SubPass (); subpass0.AddColorReference (0, VkImageLayout.ColorAttachmentOptimal); if (samples != VkSampleCountFlags.SampleCount1) { + AddAttachment (colorFormat, VkImageLayout.ColorAttachmentOptimal, samples, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare); AddAttachment (colorFormat, VkImageLayout.PresentSrcKHR, VkSampleCountFlags.SampleCount1); ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); subpass0.AddResolveReference (1, VkImageLayout.ColorAttachmentOptimal); + } else { + AddAttachment (colorFormat, VkImageLayout.PresentSrcKHR, samples, loadOp, VkAttachmentStoreOp.Store); } AddSubpass (subpass0);