From 664c5e02feaf5cf087dc0e30425a107c5b2c34b5 Mon Sep 17 00:00:00 2001 From: Samuele Lorefice Date: Wed, 2 Apr 2025 20:26:28 +0200 Subject: [PATCH] Added SDF kernel --- SDFMapCreator/Program.cs | 12 +++++++----- SDFMapCreator/SdfKernels.Kernels.cs | 20 ++++++++++++++++++++ SDFMapCreator/SdfKernels.cs | 24 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/SDFMapCreator/Program.cs b/SDFMapCreator/Program.cs index d9b6281..0d6d2f1 100644 --- a/SDFMapCreator/Program.cs +++ b/SDFMapCreator/Program.cs @@ -133,7 +133,9 @@ public class Program { kernels.EdgeDetect(maskData.Mask, out var temp); maskData.Mask = temp; Parallel.For(0, width * height, parallelOptions, (i) => { - if(maskData.Mask[i % width, i / width].Y != 0) lock (maskData.Edges) maskData.Edges.Add(new(i % width, i / width)); + if (maskData.Mask[i % width, i / width].Y == 0) return; + // ReSharper disable once PossibleLossOfFraction + lock (maskData.Edges) maskData.Edges.Add(new(i % width, i / width)); }); sw.Stop(); @@ -179,12 +181,11 @@ public class Program { static SDFData SDF(MaskData mask) { var width = (uint)mask.Mask.GetLength(0); var height = (uint)mask.Mask.GetLength(1); - var temp = new Vector3[width, height]; float AbsMax = MIN; int iterCount = 0; var sw = new Stopwatch(); sw.Start(); - Parallel.For(0, width * height, parallelOptions, (i) => + /*Parallel.For(0, width * height, parallelOptions, (i) => { //convert 1D index to 2D index var x = (int)(i % width); @@ -210,8 +211,9 @@ public class Program { ConsoleUpdateLine( $"Progress: {iterCount / (float)(width * height):P}% | {iterCount / (sw.Elapsed.TotalSeconds):N0} pixels/s"); } - }); - + });*/ + kernels.Sdf(mask.Edges.ToArray(), out var temp); + Console.WriteLine( $"\nSDF Generation Time: {sw.Elapsed.TotalSeconds:N4}s ({iterCount / sw.Elapsed.TotalSeconds:N0} pixels/s)"); sw.Restart(); diff --git a/SDFMapCreator/SdfKernels.Kernels.cs b/SDFMapCreator/SdfKernels.Kernels.cs index 0da0cd2..05ccfba 100644 --- a/SDFMapCreator/SdfKernels.Kernels.cs +++ b/SDFMapCreator/SdfKernels.Kernels.cs @@ -49,4 +49,24 @@ public partial class SdfKernels { } } } + + private static void SdfKernel(Index2D index, + ArrayView2D sdf, + ArrayView1D edges, + int width, int height + ) { + Vector2 pos = new((float)index.X / width, (float)index.Y / height); + float minDist = 2f; + int count = edges.IntExtent.X; + + for (int i = 0; i < count; i++) { + Vector2 edgeNrm = new (edges[i].X/width, edges[i].Y/height); + float dist = Vector2.Distance(pos, edgeNrm); + if (dist < minDist) minDist = dist; + } + + if (minDist > 1f) minDist = 1f; + + sdf[index] = new(minDist); + } } \ No newline at end of file diff --git a/SDFMapCreator/SdfKernels.cs b/SDFMapCreator/SdfKernels.cs index a2f2246..4a9c995 100644 --- a/SDFMapCreator/SdfKernels.cs +++ b/SDFMapCreator/SdfKernels.cs @@ -106,6 +106,30 @@ public partial class SdfKernels { edge = buffer.GetAsArray2D(); } + public void Sdf(Vector2[] edges, out Vector3[,] sdf) { + var dev = gpuContext.GetPreferredDevice(preferCPU:false); + int width = edges.Length; + int height = edges.Length; + sdf = new Vector3[width, height]; + using Accelerator accelerator = dev.CreateAccelerator(gpuContext); + + using var buffer = accelerator.Allocate2DDenseX(new (width, height)); + + using var edgeBuffer = accelerator.Allocate1D(edges.Length); + edgeBuffer.CopyFromCPU(edges); + + var sdfKernel = accelerator.LoadAutoGroupedStreamKernel, + ArrayView1D, + int, int>(SdfKernel); + + sdfKernel(new (width, height), buffer.View, edgeBuffer.View, width, height); + + accelerator.Synchronize(); + + sdf = buffer.GetAsArray2D(); + } + private static string GetInfoString(Accelerator a) { StringWriter infoString = new StringWriter();