Compare commits
2 Commits
1bdead0750
...
1d64749e76
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d64749e76 | ||
|
|
0ef4ad1c4a |
@@ -1,4 +1,6 @@
|
|||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAccelerator_002EAllocations_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fa3e5a0b5353a4a59d3be7bb386db3c46069739eacca1fc6b7323dca1ee7fd_003FAccelerator_002EAllocations_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEntryPointDescription_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F32b5380d8ca1aa7219c1622702a3e927b2bb32c9a53b43e12bb5a4af9a2862d_003FEntryPointDescription_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AImage_007BTPixel_007D_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F98f0ece83ba33754ab932bd7b5c712d12f3a59029f9f14067f553a3a318c8f_003FImage_007BTPixel_007D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AImage_007BTPixel_007D_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F98f0ece83ba33754ab932bd7b5c712d12f3a59029f9f14067f553a3a318c8f_003FImage_007BTPixel_007D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APixelTypeInfo_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fc3cfdca1fb93eb6df5e51a81da5df646adfab8b862fd1a07ee5d247b49c5179_003FPixelTypeInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APixelTypeInfo_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fc3cfdca1fb93eb6df5e51a81da5df646adfab8b862fd1a07ee5d247b49c5179_003FPixelTypeInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F2c8e7ca976f350cba9836d5565dac56b11e0b56656fa786460eb1395857a6fa_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F2c8e7ca976f350cba9836d5565dac56b11e0b56656fa786460eb1395857a6fa_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class Program {
|
|||||||
static List<TransitionMaskData> TransitionMasks = new();
|
static List<TransitionMaskData> TransitionMasks = new();
|
||||||
static List<SDFData> SDFs = new();
|
static List<SDFData> SDFs = new();
|
||||||
static List<Vector3[,]> Gradients = new();
|
static List<Vector3[,]> Gradients = new();
|
||||||
|
static readonly SdfKernels kernels = new();
|
||||||
static void ConsoleUpdateLine(string s) => Console.Write("\r" + s);
|
static void ConsoleUpdateLine(string s) => Console.Write("\r" + s);
|
||||||
|
|
||||||
public static void Main(string[] args) {
|
public static void Main(string[] args) {
|
||||||
@@ -48,12 +48,9 @@ public class Program {
|
|||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1; i < Images.Count; i++)
|
for (int i = 1; i < Images.Count; i++) {
|
||||||
{
|
for (int x = 0; x < Images[i].Width; x++) {
|
||||||
for (int x = 0; x < Images[i].Width; x++)
|
for (int y = 0; y < Images[i].Height; y++) {
|
||||||
{
|
|
||||||
for (int y = 0; y < Images[i].Height; y++)
|
|
||||||
{
|
|
||||||
Images[i].Pixels[x, y].X = MathF.Min(Images[i - 1].Pixels[x, y].X + Images[i].Pixels[x, y].X, MAX);
|
Images[i].Pixels[x, y].X = MathF.Min(Images[i - 1].Pixels[x, y].X + Images[i].Pixels[x, y].X, MAX);
|
||||||
Images[i].Pixels[x, y].Y = MathF.Min(Images[i - 1].Pixels[x, y].Y + Images[i].Pixels[x, y].X, MAX);
|
Images[i].Pixels[x, y].Y = MathF.Min(Images[i - 1].Pixels[x, y].Y + Images[i].Pixels[x, y].X, MAX);
|
||||||
Images[i].Pixels[x, y].Z = MathF.Min(Images[i - 1].Pixels[x, y].Z + Images[i].Pixels[x, y].X, MAX);
|
Images[i].Pixels[x, y].Z = MathF.Min(Images[i - 1].Pixels[x, y].Z + Images[i].Pixels[x, y].X, MAX);
|
||||||
@@ -116,7 +113,8 @@ public class Program {
|
|||||||
for (var x = 0; x < mask.Mask.GetLength(0); x++) {
|
for (var x = 0; x < mask.Mask.GetLength(0); x++) {
|
||||||
for (var y = 0; y < mask.Mask.GetLength(1); y++) {
|
for (var y = 0; y < mask.Mask.GetLength(1); y++) {
|
||||||
if (gradient[x, y].X == 0) continue;
|
if (gradient[x, y].X == 0) continue;
|
||||||
var pixel = new Vector3(Remap(gradient[x, y].X, MIN, MAX, 1.0f-currStep, 1.0f-(currStep + stepIncrement)));
|
var pixel = new Vector3(Remap(gradient[x, y].X, MIN, MAX, 1.0f - currStep,
|
||||||
|
1.0f - (currStep + stepIncrement)));
|
||||||
if (pixel.X > finalImage[x, y].X) finalImage[x, y] = pixel;
|
if (pixel.X > finalImage[x, y].X) finalImage[x, y] = pixel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,26 +127,15 @@ public class Program {
|
|||||||
private static void EdgeDetect(MaskData maskData) {
|
private static void EdgeDetect(MaskData maskData) {
|
||||||
uint width = (uint)maskData.Image.Width;
|
uint width = (uint)maskData.Image.Width;
|
||||||
uint height = (uint)maskData.Image.Height;
|
uint height = (uint)maskData.Image.Height;
|
||||||
int iterCount = 0;
|
|
||||||
var sw = new Stopwatch();
|
var sw = new Stopwatch();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
Console.WriteLine("Running edge detection...");
|
Console.WriteLine("Running edge detection...");
|
||||||
Parallel.For(0, width * height, parallelOptions, (i) =>
|
kernels.EdgeDetect(maskData.Mask, out var temp);
|
||||||
{
|
maskData.Mask = temp;
|
||||||
int x = (int)(i % width);
|
Parallel.For(0, width * height, parallelOptions, (i) => {
|
||||||
int y = (int)(i / width);
|
if(maskData.Mask[i % width, i / width].Y != 0) lock (maskData.Edges) maskData.Edges.Add(new(i % width, i / width));
|
||||||
|
|
||||||
if (!EdgeKernel(maskData.Mask, x, y, width, height)) return;
|
|
||||||
var color = maskData.Mask[x, y];
|
|
||||||
color.Y = MAX;
|
|
||||||
maskData.Mask[x, y] = color;
|
|
||||||
lock (maskData.Edges) maskData.Edges.Add(new(x, y));
|
|
||||||
iterCount++;
|
|
||||||
if (iterCount % (width * height / 100) == 0) {
|
|
||||||
ConsoleUpdateLine(
|
|
||||||
$"Progress: {iterCount / (float)(width * height):P} | {iterCount / (sw.Elapsed.TotalSeconds):N0} pixels/s");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
Console.WriteLine(
|
Console.WriteLine(
|
||||||
$"\nEdge pixels: {maskData.Edges.Count} | {maskData.Edges.Count / (sw.ElapsedMilliseconds + 1)} pixels/s\n Time: {sw.Elapsed.TotalSeconds:F4}s");
|
$"\nEdge pixels: {maskData.Edges.Count} | {maskData.Edges.Count / (sw.ElapsedMilliseconds + 1)} pixels/s\n Time: {sw.Elapsed.TotalSeconds:F4}s");
|
||||||
@@ -247,55 +234,16 @@ public class Program {
|
|||||||
private static float EuclideanDistance(Vector2 a, Vector2 b) =>
|
private static float EuclideanDistance(Vector2 a, Vector2 b) =>
|
||||||
MathF.Sqrt(MathF.Pow(a.X - b.X, 2) + MathF.Pow(a.Y - b.Y, 2));
|
MathF.Sqrt(MathF.Pow(a.X - b.X, 2) + MathF.Pow(a.Y - b.Y, 2));
|
||||||
|
|
||||||
|
|
||||||
static Vector3[,] GetABMask(Vector3[,] A, Vector3[,] B, uint resX, uint resY) {
|
static Vector3[,] GetABMask(Vector3[,] A, Vector3[,] B, uint resX, uint resY) {
|
||||||
var temp = new Vector3[resX, resY];
|
kernels.ABMask(A, B, out var temp);
|
||||||
Parallel.For(0, resX * resY, parallelOptions, (i) =>
|
|
||||||
{
|
|
||||||
uint x = (uint)(i % resX);
|
|
||||||
uint y = (uint)(i / resX);
|
|
||||||
var pixelA = A[x, y];
|
|
||||||
var pixelB = B[x, y];
|
|
||||||
float lumaA = (pixelA.X + pixelA.Y + pixelA.Z) / 3;
|
|
||||||
float lumaB = (pixelB.X + pixelB.Y + pixelB.Z) / 3;
|
|
||||||
float resultPixel = lumaB > lumaA ? MAX : MIN;
|
|
||||||
temp[x, y] = new(resultPixel, 0, 0);
|
|
||||||
});
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector3[,] SelfMask(Vector3[,] A, uint resX, uint resY) {
|
static Vector3[,] SelfMask(Vector3[,] A, uint resX, uint resY) {
|
||||||
var temp = new Vector3[resX, resY];
|
kernels.SelfMask(A, out var temp);
|
||||||
Parallel.For(0, resX * resY, parallelOptions, (i) =>
|
|
||||||
{
|
|
||||||
uint x = (uint)(i % resX);
|
|
||||||
uint y = (uint)(i / resX);
|
|
||||||
var pixelA = A[x, y];
|
|
||||||
float lumaA = (pixelA.X + pixelA.Y + pixelA.Z) / 3;
|
|
||||||
float resultPixel = lumaA > 0.99 ? MAX : MIN;
|
|
||||||
temp[x, y] = new(resultPixel, 0, 0);
|
|
||||||
});
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool EdgeKernel(Vector3[,] mask, int x, int y, uint width, uint height) {
|
|
||||||
//if we are already empty, return false
|
|
||||||
if (mask[x, y].X == 0) return false;
|
|
||||||
//if we are on the edge of the image, return false
|
|
||||||
if (x == 0 || y == 0 || x == width - 1 || y == height - 1) return false;
|
|
||||||
//check the 3x3 kernel
|
|
||||||
for (int xi = x - 1; xi <= x + 1; xi++) {
|
|
||||||
for (int yi = y - 1; yi <= y + 1; yi++) {
|
|
||||||
if (xi < 0 || xi >= width || yi < 0 || yi >= height)
|
|
||||||
continue; //skip out of bounds pixels
|
|
||||||
if (mask[xi, yi].X == 0)
|
|
||||||
return true; //if we find a black pixel, return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//if we didn't find any black pixels, return false
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static T Lerp<T>(T a, T b, float t)
|
static T Lerp<T>(T a, T b, float t)
|
||||||
where T : INumber<T>, IMultiplyOperators<T, float, T>, IAdditionOperators<T, T, T>
|
where T : INumber<T>, IMultiplyOperators<T, float, T>, IAdditionOperators<T, T, T>
|
||||||
=> a * (1 - t) + b * t;
|
=> a * (1 - t) + b * t;
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ using System.Numerics;
|
|||||||
namespace SDFMapCreator;
|
namespace SDFMapCreator;
|
||||||
|
|
||||||
public record Image(Vector3[,] Pixels, int Width, int Height);
|
public record Image(Vector3[,] Pixels, int Width, int Height);
|
||||||
public record MaskData(Vector3[,] Mask, Image Image, List<Vector2> Edges);
|
public record MaskData(Vector3[,] Mask, Image Image, List<Vector2> Edges) {
|
||||||
|
public Vector3[,] Mask { get; set; } = Mask;
|
||||||
|
public List<Vector2> Edges { get; set; } = Edges;
|
||||||
|
}
|
||||||
|
|
||||||
public record SDFData(Vector3[,] SDF);
|
public record SDFData(Vector3[,] SDF);
|
||||||
public record TransitionMaskData(Vector3[,] Mask, Image ImageA, Image ImageB);
|
public record TransitionMaskData(Vector3[,] Mask, Image ImageA, Image ImageB);
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="ILGPU" Version="1.5.2" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
|
||||||
<PackageReference Include="System.Numerics.Vectors" Version="4.6.1" />
|
<PackageReference Include="System.Numerics.Vectors" Version="4.6.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
52
SDFMapCreator/SdfKernels.Kernels.cs
Normal file
52
SDFMapCreator/SdfKernels.Kernels.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using ILGPU;
|
||||||
|
using ILGPU.Runtime;
|
||||||
|
|
||||||
|
namespace SDFMapCreator;
|
||||||
|
|
||||||
|
public partial class SdfKernels {
|
||||||
|
private static void SelfMaskKernel(Index2D index, ArrayView2D<Vector3, Stride2D.DenseX> input, ArrayView2D<Vector3, Stride2D.DenseX> mask) {
|
||||||
|
int x = index.X;
|
||||||
|
int y = index.Y;
|
||||||
|
Vector3 value = input[x, y];
|
||||||
|
float lumaA = (value.X + value.Y + value.Z)/3f;
|
||||||
|
float r = lumaA > 0.99f ? 1f : 0f;
|
||||||
|
mask[x,y] = new (r, 0f, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ABMaskKernel(Index2D index,
|
||||||
|
ArrayView2D<Vector3, Stride2D.DenseX> A,
|
||||||
|
ArrayView2D<Vector3, Stride2D.DenseX> B,
|
||||||
|
ArrayView2D<Vector3, Stride2D.DenseX> mask
|
||||||
|
) {
|
||||||
|
int x = index.X;
|
||||||
|
int y = index.Y;
|
||||||
|
Vector3 valueA = A[x, y];
|
||||||
|
Vector3 valueB = B[x, y];
|
||||||
|
float lumaA = (valueA.X + valueA.Y + valueA.Z) / 3f;
|
||||||
|
float lumaB = (valueB.X + valueB.Y + valueB.Z) / 3f;
|
||||||
|
float r = lumaA > 0.99f && lumaB > 0.99f ? 1f : 0f;
|
||||||
|
mask[x, y] = new (r, 0f, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EdgeKernel(Index2D index,
|
||||||
|
ArrayView2D<Vector3, Stride2D.DenseX> mask,
|
||||||
|
uint width, uint height
|
||||||
|
) { // early exit if not on mask
|
||||||
|
if (mask[index].X == 0f) return;
|
||||||
|
int x = index.X;
|
||||||
|
int y = index.Y;
|
||||||
|
//if we are on the edge of the image, return false
|
||||||
|
if (x == 0 || y == 0 || x == width - 1 || y == height - 1) return;
|
||||||
|
|
||||||
|
//check the 3x3 kernel
|
||||||
|
for (int xi = x - 1; xi <= x + 1; xi++) {
|
||||||
|
for (int yi = y - 1; yi <= y + 1; yi++) {
|
||||||
|
if (xi < 0 || xi >= width || yi < 0 || yi >= height)
|
||||||
|
continue; //skip out of bounds pixels
|
||||||
|
if (mask[xi, yi].X == 0f)
|
||||||
|
mask[index].Y = 1f; //if we find a black pixel, return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
115
SDFMapCreator/SdfKernels.cs
Normal file
115
SDFMapCreator/SdfKernels.cs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
|
using ILGPU;
|
||||||
|
using ILGPU.Runtime;
|
||||||
|
using ILGPU.Runtime.CPU;
|
||||||
|
using ILGPU.Runtime.Cuda;
|
||||||
|
using ILGPU.Runtime.OpenCL;
|
||||||
|
|
||||||
|
namespace SDFMapCreator;
|
||||||
|
|
||||||
|
public partial class SdfKernels {
|
||||||
|
private Context gpuContext;
|
||||||
|
|
||||||
|
public SdfKernels() {
|
||||||
|
// Initialize the GPU context
|
||||||
|
gpuContext = Context.Create(builder => builder
|
||||||
|
.OpenCL()
|
||||||
|
.Cuda()
|
||||||
|
.CPU()
|
||||||
|
);
|
||||||
|
|
||||||
|
Console.WriteLine("Reading available accelerators (CUDA only)...");
|
||||||
|
foreach (var device in gpuContext.GetCudaDevices()) {
|
||||||
|
using Accelerator accelerator = device.CreateAccelerator(gpuContext);
|
||||||
|
Console.WriteLine($"{GetInfoString(accelerator)}");
|
||||||
|
}
|
||||||
|
Console.WriteLine("Reading available accelerators (OpenCL only)...");
|
||||||
|
foreach (var device in gpuContext.GetCLDevices()) {
|
||||||
|
using Accelerator accelerator = device.CreateAccelerator(gpuContext);
|
||||||
|
Console.WriteLine($"{GetInfoString(accelerator)}");
|
||||||
|
}
|
||||||
|
Console.WriteLine("Reading available accelerators (CPU only)...");
|
||||||
|
foreach (var device in gpuContext.GetCPUDevices()) {
|
||||||
|
using Accelerator accelerator = device.CreateAccelerator(gpuContext);
|
||||||
|
Console.WriteLine($"{GetInfoString(accelerator)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelfMask(Vector3[,] input, out Vector3[,] mask) {
|
||||||
|
var dev = gpuContext.GetPreferredDevice(preferCPU:false);
|
||||||
|
int width = input.GetLength(0);
|
||||||
|
int height = input.GetLength(1);
|
||||||
|
mask = new Vector3[width, height];
|
||||||
|
using Accelerator accelerator = dev.CreateAccelerator(gpuContext);
|
||||||
|
|
||||||
|
using var buffer = accelerator.Allocate2DDenseX<Vector3>(new (width, height));
|
||||||
|
buffer.CopyFromCPU(input);
|
||||||
|
|
||||||
|
using var maskBuffer = accelerator.Allocate2DDenseX<Vector3>(new (width, height));
|
||||||
|
|
||||||
|
var selfMaskKernel = accelerator.LoadAutoGroupedStreamKernel<Index2D, ArrayView2D<Vector3, Stride2D.DenseX>,
|
||||||
|
ArrayView2D<Vector3, Stride2D.DenseX>>(SelfMaskKernel);
|
||||||
|
|
||||||
|
selfMaskKernel(new (width, height), buffer.View, maskBuffer.View);
|
||||||
|
|
||||||
|
accelerator.Synchronize();
|
||||||
|
|
||||||
|
mask = maskBuffer.GetAsArray2D();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ABMask(Vector3[,] A, Vector3[,] B, out Vector3[,] mask) {
|
||||||
|
var dev = gpuContext.GetPreferredDevice(preferCPU:false);
|
||||||
|
int width = A.GetLength(0);
|
||||||
|
int height = A.GetLength(1);
|
||||||
|
mask = new Vector3[width, height];
|
||||||
|
using Accelerator accelerator = dev.CreateAccelerator(gpuContext);
|
||||||
|
|
||||||
|
using var bufferA = accelerator.Allocate2DDenseX<Vector3>(new (width, height));
|
||||||
|
bufferA.CopyFromCPU(A);
|
||||||
|
|
||||||
|
using var bufferB = accelerator.Allocate2DDenseX<Vector3>(new (width, height));
|
||||||
|
bufferB.CopyFromCPU(B);
|
||||||
|
|
||||||
|
using var maskBuffer = accelerator.Allocate2DDenseX<Vector3>(new (width, height));
|
||||||
|
|
||||||
|
var abMaskKernel = accelerator.LoadAutoGroupedStreamKernel<Index2D,
|
||||||
|
ArrayView2D<Vector3, Stride2D.DenseX>,
|
||||||
|
ArrayView2D<Vector3, Stride2D.DenseX>,
|
||||||
|
ArrayView2D<Vector3, Stride2D.DenseX>>(ABMaskKernel);
|
||||||
|
|
||||||
|
abMaskKernel(new (width, height), bufferA.View, bufferB.View, maskBuffer.View);
|
||||||
|
|
||||||
|
accelerator.Synchronize();
|
||||||
|
|
||||||
|
mask = maskBuffer.GetAsArray2D();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EdgeDetect(Vector3[,] mask, out Vector3[,] edge) {
|
||||||
|
var dev = gpuContext.GetPreferredDevice(preferCPU:false);
|
||||||
|
int width = mask.GetLength(0);
|
||||||
|
int height = mask.GetLength(1);
|
||||||
|
edge = new Vector3[width, height];
|
||||||
|
using Accelerator accelerator = dev.CreateAccelerator(gpuContext);
|
||||||
|
|
||||||
|
using var buffer = accelerator.Allocate2DDenseX<Vector3>(new (width, height));
|
||||||
|
buffer.CopyFromCPU(mask);
|
||||||
|
|
||||||
|
var edgeKernel = accelerator.LoadAutoGroupedStreamKernel<Index2D,
|
||||||
|
ArrayView2D<Vector3, Stride2D.DenseX>, uint, uint>(EdgeKernel);
|
||||||
|
|
||||||
|
edgeKernel(new (width, height), buffer.View, (uint)width, (uint)height);
|
||||||
|
|
||||||
|
accelerator.Synchronize();
|
||||||
|
|
||||||
|
edge = buffer.GetAsArray2D();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetInfoString(Accelerator a)
|
||||||
|
{
|
||||||
|
StringWriter infoString = new StringWriter();
|
||||||
|
a.PrintInformation(infoString);
|
||||||
|
return infoString.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user