]> O.S.I.I.S - jp/vke.net.git/commitdiff
stroker first tests
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sun, 9 Oct 2022 16:34:18 +0000 (18:34 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sun, 9 Oct 2022 16:34:33 +0000 (18:34 +0200)
samples/compute/compute.csproj
samples/compute/shaders/stroker.comp [new file with mode: 0644]
samples/compute/shaders/stroker.frag [new file with mode: 0644]
samples/compute/shaders/stroker.vert [new file with mode: 0644]
samples/compute/stroker.cs [new file with mode: 0644]

index 30c6b43802093ed306910073c97e70639f416e09..245ffe566c7d68e691f598a8ab9c77d22da317c7 100644 (file)
@@ -4,6 +4,6 @@
   </PropertyGroup>
               
   <ItemGroup>    
-    <Compile Include="main.cs" /> 
+    <Compile Include="stroker.cs" /> 
   </ItemGroup>     
 </Project>
\ No newline at end of file
diff --git a/samples/compute/shaders/stroker.comp b/samples/compute/shaders/stroker.comp
new file mode 100644 (file)
index 0000000..d7a570a
--- /dev/null
@@ -0,0 +1,50 @@
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_EXT_shader_16bit_storage : require
+
+layout(binding = 0) buffer readonly path {
+    vec2 pointsIn[];
+};
+layout(binding = 1) buffer writeonly vertices {
+    vec2 vbo[];
+};
+layout(binding = 2) buffer writeonly indices {
+    uint16_t ibo[];
+};
+
+layout(push_constant) uniform PushConsts {
+    float halfWidth;
+};
+
+
+layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+
+
+void main()
+{
+
+    if (gl_GlobalInvocationID.x > 0) {
+        vec2 p0 = pointsIn[gl_GlobalInvocationID.x - 1];
+        vec2 p1 = pointsIn[gl_GlobalInvocationID.x];
+        vec2 n = normalize(p1 - p0);
+        vec2 v = halfWidth * vec2(-n.y, n.x);
+        
+        uint pV = (gl_GlobalInvocationID.x - 1) * 4;
+        uint pI = (gl_GlobalInvocationID.x - 1) * 6;
+        
+        vbo[pV] = p0 + v;
+        vbo[pV+1] = p0 - v;
+        vbo[pV+2] = p1 + v;
+        vbo[pV+3] = p1 - v;
+
+        ibo[pI] = uint16_t(pV);
+        ibo[pI+1] = uint16_t(pV+2);
+        ibo[pI+2] = uint16_t(pV+1);
+        ibo[pI+3] = uint16_t(pV+2);
+        ibo[pI+4] = uint16_t(pV+3);
+        ibo[pI+5] = uint16_t(pV+1);
+    }
+
+}
diff --git a/samples/compute/shaders/stroker.frag b/samples/compute/shaders/stroker.frag
new file mode 100644 (file)
index 0000000..82b78a4
--- /dev/null
@@ -0,0 +1,11 @@
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out vec4 outFragColor;
+
+void main() 
+{
+  outFragColor = vec4(1.0, 0.5, 0.0, 1.0);
+}
\ No newline at end of file
diff --git a/samples/compute/shaders/stroker.vert b/samples/compute/shaders/stroker.vert
new file mode 100644 (file)
index 0000000..993dee4
--- /dev/null
@@ -0,0 +1,21 @@
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec2 inPos;
+
+layout(push_constant) uniform PushConsts {
+    vec2 size;
+};
+
+out gl_PerVertex 
+{
+    vec4 gl_Position;   
+};
+
+
+void main() 
+{      
+    gl_Position = vec4(inPos.xy * vec2(2) / size - vec2(1), 0.0, 1.0);
+}
diff --git a/samples/compute/stroker.cs b/samples/compute/stroker.cs
new file mode 100644 (file)
index 0000000..2533a5f
--- /dev/null
@@ -0,0 +1,288 @@
+using System;
+using Glfw;
+using Vulkan;
+using vke;
+using Image = vke.Image;
+
+using System.Numerics;
+using System.Runtime.InteropServices;
+
+namespace delaunay {
+       class Program : VkWindow {
+#if DEBUG
+               public override string[] EnabledLayers  =>
+                       new string[] {
+                               "VK_LAYER_KHRONOS_validation"
+                               ,"VK_LAYER_RENDERDOC_Capture"
+                       };
+
+#endif
+               public override string[] EnabledInstanceExtensions => new string[] {
+                       Ext.I.VK_EXT_debug_utils,
+               };
+               public override string[] EnabledDeviceExtensions => new string[] {
+                       Ext.D.VK_KHR_swapchain,
+                       Ext.D.VK_AMD_shader_info
+               };
+               Program() : base ("Stroker", 800, 600, false) {
+
+               }
+               static void Main (string[] args) {
+                       using (Program vke = new Program ()) {
+                               vke.Run ();
+                       }
+               }
+
+               FrameBuffers frameBuffers;
+               GraphicPipeline grPipeline;
+               ComputePipeline plStroke;
+               Queue computeQ, transferQ;
+
+               HostBuffer<Vector2> pathBuff; 
+               Vector2[] path;
+               GPUBuffer vbo, ibo;
+               DescriptorPool dsPool;
+               DescriptorSetLayout dslStroke;
+               DescriptorSet dsetStroke;
+
+
+               uint zoom = 2;
+               int invocationCount = 8;
+
+               uint pointCount = 0;
+               uint maxPointCount = 256;
+               int curPoint = - 1, hoverPoint = -1;
+               float lineWidth = 10f;
+
+               const int primitiveSize = 2;
+
+               void addPoint(float x, float y) {
+                       if (pointCount < maxPointCount) {
+                               path[pointCount++] = new Vector2(x,y);
+                       }
+               }
+               void addPoint(Vector2 p) {
+                       if (pointCount < maxPointCount) {
+                               path[pointCount++] = p;
+                       }
+               }
+
+               protected override void initVulkan () {
+                       base.initVulkan ();
+
+                       path = new Vector2[maxPointCount];
+                       
+                       addPoint(50,50);
+                       addPoint(100,150);
+                       addPoint(150,60);
+                       /*addPoint(200,100);
+                       addPoint(300,200);*/
+
+                       pathBuff = new HostBuffer<Vector2>(dev, VkBufferUsageFlags.StorageBuffer, path, true);
+
+                       vbo = new GPUBuffer<Vector2> (dev, VkBufferUsageFlags.StorageBuffer | VkBufferUsageFlags.VertexBuffer, (int)(maxPointCount - 1) * 4);
+                       ibo = new GPUBuffer<UInt16> (dev, VkBufferUsageFlags.StorageBuffer | VkBufferUsageFlags.IndexBuffer, (int)(maxPointCount - 1) * 6);
+                       pathBuff.SetName("path");
+                       vbo.SetName("vbo");
+                       ibo.SetName("ibo");
+
+                       dsPool = new DescriptorPool (dev, 1,
+                               new VkDescriptorPoolSize (VkDescriptorType.StorageBuffer, 3));
+                       dslStroke = new DescriptorSetLayout (dev,
+                               new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Compute, VkDescriptorType.StorageBuffer),
+                               new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Compute, VkDescriptorType.StorageBuffer),
+                               new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Compute, VkDescriptorType.StorageBuffer)
+                       );
+
+                       using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount8, false)) {
+                               cfg.Layout = new PipelineLayout (dev, new VkPushConstantRange (VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf<Vector2>()));
+                               cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, VkSampleCountFlags.SampleCount8);
+                               cfg.RenderPass.ClearValues[0] = new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.1f) };
+
+                               cfg.AddVertexBinding<Vector2> (0);
+                               cfg.AddVertexAttributes (0, VkFormat.R32g32Sfloat);//2d position
+
+                               cfg.AddShaders (
+                                       new ShaderInfo (dev, VkShaderStageFlags.Vertex, "#shaders.stroker.vert.spv"),
+                                       new ShaderInfo (dev, VkShaderStageFlags.Fragment, "#shaders.stroker.frag.spv")
+                               );
+
+                               grPipeline = new GraphicPipeline (cfg);
+                       }
+
+                       plStroke = new ComputePipeline (
+                               new PipelineLayout (dev, new VkPushConstantRange (VkShaderStageFlags.Compute, sizeof (float)), dslStroke),
+                               "#shaders.stroker.comp.spv");
+
+                       dsetStroke = dsPool.Allocate (dslStroke);
+
+                       DescriptorSetWrites dsUpdate = new DescriptorSetWrites (dsetStroke, dslStroke);
+                       dsUpdate.Write (dev, pathBuff.Descriptor, vbo.Descriptor, ibo.Descriptor);
+
+                       UpdateFrequency = 1;
+
+                       cmds = cmdPool.AllocateCommandBuffer (swapChain.ImageCount);
+               }
+
+               protected override void createQueues () {
+                       computeQ = new Queue (dev, VkQueueFlags.Compute);
+                       transferQ = new Queue (dev, VkQueueFlags.Transfer);
+
+                       base.createQueues ();
+               }
+               bool rebuildBuffers = false;
+
+               void buildCommandBuffers() {
+                       cmdPool.Reset (VkCommandPoolResetFlags.ReleaseResources);
+
+                       for (int i = 0; i < swapChain.ImageCount; ++i) {
+                               FrameBuffer fb = frameBuffers[i];
+                               cmds[i].Start ();
+
+                               grPipeline.RenderPass.Begin (cmds[i], fb);
+
+                               cmds[i].SetViewport (swapChain.Width, swapChain.Height);
+                               cmds[i].SetScissor (swapChain.Width, swapChain.Height);
+
+                               cmds[i].BindPipeline (grPipeline);
+                               cmds[i].PushConstant (grPipeline.Layout, VkShaderStageFlags.Vertex, new Vector2(swapChain.Width, swapChain.Height));
+
+                               cmds[i].BindVertexBuffer (vbo);
+                               cmds[i].BindIndexBuffer (ibo, VkIndexType.Uint16);
+                               cmds[i].DrawIndexed ((uint)(pointCount - 1) * 6);
+
+                               grPipeline.RenderPass.End (cmds[i]);
+
+                               cmds[i].End ();
+                       }
+               }
+
+               public override void Update () {
+
+                       using (CommandPool cmdPoolCompute = new CommandPool (dev, computeQ.qFamIndex)) {
+
+                               PrimaryCommandBuffer cmd = cmdPoolCompute.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);
+
+                               plStroke.Bind (cmd);
+                               plStroke.BindDescriptorSet (cmd, dsetStroke);
+                               cmd.PushConstant (plStroke.Layout, VkShaderStageFlags.Compute, lineWidth * 0.5f);
+                               cmd.Dispatch (pointCount);
+                               cmd.End ();
+                               computeQ.Submit (cmd);
+                               dev.WaitIdle();
+                       }
+                       if (rebuildBuffers) { 
+                               buildCommandBuffers();
+                               rebuildBuffers = false;
+                       }
+               }
+               protected override void OnResize () {
+                       base.OnResize ();
+
+                       dev.WaitIdle();
+
+                       frameBuffers?.Dispose();
+                       frameBuffers = grPipeline.RenderPass.CreateFrameBuffers(swapChain);
+
+                       buildCommandBuffers ();
+               }
+               protected override void Dispose (bool disposing) {
+                       if (disposing) {
+                               if (!isDisposed) {
+                                       dev.WaitIdle ();
+
+                                       for (int i = 0; i < swapChain.ImageCount; ++i)
+                                               frameBuffers[i]?.Dispose ();
+
+                                       grPipeline.Dispose ();
+                                       plStroke.Dispose ();
+
+                                       dslStroke.Dispose ();
+                                       dsPool.Dispose ();
+
+                                       pathBuff.Dispose ();
+                                       vbo.Dispose ();
+                                       ibo.Dispose ();
+                               }
+                       }
+
+                       base.Dispose (disposing);
+               }
+
+               protected override void onKeyDown(Key key, int scanCode, Modifier modifiers)
+               {
+                       switch(key) {
+                               case Key.F3:
+                                       if (phy.GetDeviceExtensionSupported (Ext.D.VK_AMD_shader_info))
+                                               printAMDStats();
+                                       break;
+                               case Key.KeypadAdd:
+                                       lineWidth *= 2.0f;
+                                       rebuildBuffers = true;
+                                       break;                          
+                               case Key.KeypadSubtract:
+                                       lineWidth /= 2.0f;
+                                       rebuildBuffers = true;
+                                       break;                          
+                               default:
+                                       base.onKeyDown(key, scanCode, modifiers);
+                                       break;
+                       }
+               }
+               Vector2 curMousePos;
+               const float pointSizeSquared = 10;
+               protected override async void onMouseMove(double xPos, double yPos)
+               {
+                       base.onMouseMove(xPos, yPos);
+
+                       curMousePos = new Vector2((float)xPos, (float)yPos);
+
+                       if (curPoint < 0) {
+                               for (int i = 0; i < pointCount; i++)
+                               {
+                                       if (Vector2.DistanceSquared(curMousePos, path[i]) < pointSizeSquared) {
+                                               hoverPoint = i;
+                                               return;
+                                       }
+                               }
+                               hoverPoint = -1;
+                       } else {
+                               path[curPoint] = curMousePos;
+                               pathBuff.Update((uint)curPoint, path[curPoint]);
+                       }
+               }
+               protected override void onMouseButtonDown(MouseButton button, Modifier mods)
+               {
+                       if (hoverPoint < 0) {
+                               addPoint(curMousePos);
+                               pathBuff.Update(pointCount - 1, path[pointCount - 1]);
+                               rebuildBuffers = true;
+                       } else {
+                               curPoint = hoverPoint;
+                       }
+               }
+               protected override void onMouseButtonUp(MouseButton button, Modifier mods)
+               {
+                       curPoint = -1;
+               }
+               void printAMDStats() {
+                       VkShaderStatisticsInfoAMD stats = new VkShaderStatisticsInfoAMD();
+                       
+                       Vk.vkGetShaderInfoAMD(dev.Handle, plStroke.Handle, VkShaderStageFlags.Compute, VkShaderInfoTypeAMD.StatisticsAMD, 
+                               out UIntPtr statSize, IntPtr.Zero);
+
+                       IntPtr statSize2 = (IntPtr)Marshal.SizeOf<VkShaderStatisticsInfoAMD>();
+
+                       Vk.vkGetShaderInfoAMD(dev.Handle, plStroke.Handle, VkShaderStageFlags.Compute, VkShaderInfoTypeAMD.StatisticsAMD, 
+                               (IntPtr)(statSize.ToUInt64()), stats.Pin());
+
+                       stats.Unpin();
+
+                       Console.WriteLine ($"AMD Statistics");
+                       Console.WriteLine ($"==============");
+                       Console.WriteLine ($"Sgprs: {stats.resourceUsage.numUsedSgprs} / Avail:{stats.numAvailableSgprs} Phy:{stats.numPhysicalSgprs}");
+                       Console.WriteLine ($"Vgprs: {stats.resourceUsage.numUsedVgprs} / Avail:{stats.numAvailableVgprs} Phy:{stats.numPhysicalVgprs}");
+                       Console.WriteLine ($"_________________________________________________________________");
+               }
+       }
+}