public void Initialize(Context context, AcceleratorId acceleratorId, double[,] independents, double[] dependants) { AcceleratorId = acceleratorId; AcceleratorType acceleratorType = AcceleratorId.AcceleratorType; if (acceleratorType == AcceleratorType.CPU) { Accelerator = Accelerator.Create(context, AcceleratorId); } else if (acceleratorType == AcceleratorType.OpenCL) { Accelerator = CLAccelerator.Create(context, AcceleratorId); } else if (acceleratorType == AcceleratorType.Cuda) { Accelerator = CudaAccelerator.Create(context, AcceleratorId); } EvaluationKernel = Accelerator.LoadAutoGroupedStreamKernel <Index2, ArrayView2D <double>, ArrayView <double>, ArrayView <NodeGPU>, ArrayView <int>, ArrayView2D <double> >(EvaluationKernelFunction); ProcessResultsKernel = Accelerator.LoadAutoGroupedStreamKernel <Index1, ArrayView2D <double>, ArrayView <double> >(ProcessResultsKernelFunction); IndependentsTableSize = new Index2(independents.GetUpperBound(0) + 1, independents.GetUpperBound(1) + 1); Independents = Accelerator.Allocate <double>(IndependentsTableSize); Independents.CopyFrom(independents, new Index2(), new Index2(), IndependentsTableSize); Dependants = Accelerator.Allocate <double>(dependants.Length); Dependants.CopyFrom(dependants, 0, 0, dependants.Length); }
public void GenerateHeightField(TerrainPatch patch) { using (var context = new Context()) { AcceleratorId aid = Accelerator.Accelerators.Where(id => id.AcceleratorType == AcceleratorType.Cuda).FirstOrDefault(); if (aid.AcceleratorType != AcceleratorType.Cuda) { Console.WriteLine(@"There is no CUDA accelerator present. Doing nothing."); return; } using (var accelerator = Accelerator.Create(context, aid)) using (var gpu_dem = accelerator.Allocate <short>(ViperEnvironment.Terrain.Data.Length)) using (var gpu_range = accelerator.Allocate <float>(cpu_range.Length)) using (var gpu_slope = accelerator.Allocate <float>(cpu_slope.Length)) using (var gpu_rise = accelerator.Allocate <short>(TerrainPatch.DefaultSize * TerrainPatch.DefaultSize)) { gpu_dem.CopyFrom(ViperEnvironment.Terrain.Data, 0, 0, ViperEnvironment.Terrain.Data.Length); gpu_range.CopyFrom(cpu_range, 0, 0, cpu_range.Length); var launchDimension = new Index2(TerrainPatch.DefaultSize, TerrainPatch.DefaultSize); var kernel1 = accelerator.LoadStreamKernel <Index2, ArrayView <short>, ArrayView <float>, ArrayView <short>, int, int>(RiseKernel1); } } }
bool GetAccelerator(AcceleratorType t, out AcceleratorId aid) { aid = Accelerator.Accelerators.Where(id => id.AcceleratorType == t).FirstOrDefault(); if (aid.AcceleratorType != t) { Console.WriteLine(@"There is accelerator present of the desired type. Doing nothing."); } return(aid.AcceleratorType == t); }
public Image<Rgba32> AddFilter(IImageFilter filter) { using (var context = new Context()) { AcceleratorId acceleratorId = new AcceleratorId(); if (Accelerator.Accelerators.Where(a => a.AcceleratorType == AcceleratorType.Cuda).Count() != 0) { acceleratorId = Accelerator.Accelerators.Where(a => a.AcceleratorType == AcceleratorType.Cuda) .FirstOrDefault(); } else { acceleratorId = Accelerator.Accelerators.Where(a => a.AcceleratorType == AcceleratorType.CPU).FirstOrDefault(); } using (var accelerator = Accelerator.Create(context, acceleratorId)) { return filter.PerformFilter(accelerator); } } }
static float EncodingToSlope(int encoding) => 4f * encoding / 1000000f; // Haven't looked at the numerics closely to see whether these are exact inverses. Don't care enough yet. /// <summary> /// Generate the near horizon for the patch, overwriting what was there. /// The horizons will be in slope format, not angles /// </summary> /// <param name="target"></param> public void AddNearHorizon(TerrainPatch target) { Debug.Assert(Terrain != null); Debug.Assert(target != null); if (target.Horizons == null) { target.InitializeHorizons(); } using (var context = new Context()) { AcceleratorId aid = Accelerator.Accelerators.Where(id => id.AcceleratorType == AcceleratorType.Cuda).FirstOrDefault(); //AcceleratorId aid = Accelerator.Accelerators.Where(id => id.AcceleratorType == AcceleratorType.CPU).FirstOrDefault(); if (aid.AcceleratorType != AcceleratorType.Cuda) { Console.WriteLine(@"There is no CUDA accelerator present. Doing nothing."); return; } using (var accelerator = Accelerator.Create(context, aid)) { target.Matrices = null; // Be sure!! target.FillPoints(Terrain); target.FillMatricesRelativeToPoint(Terrain, target.Points[0][0]); // Matrices var cpu_matrices_size = target.Height * target.Width * 12; var basePoint = target.Points[0][0]; var cpu_matrices = MakeCPUMatrices(target); // Horizon (load from target) var cpu_horizon_size = target.Height * target.Width * Horizon.HorizonSamples; var cpu_horizon = new float[cpu_horizon_size]; // Initialize to float.MinValue. Maintain horizon as slope for (var i = 0; i < cpu_horizon_size; i++) { cpu_horizon[i] = float.MinValue; } // Caster array const int dem_size = TerrainPatch.DEM_size; const int patch_size = TerrainPatch.DefaultSize; var maxDistance = (float)TerrainPatch.MaximumLocalDistance; var border = 2 + (int)Math.Ceiling(maxDistance); // the 2 is margin for the bilinear interpolation var line_min = Math.Max(0, target.Line - border); var line_max = Math.Min(dem_size - 1, target.Line + patch_size + border); // 1 more than the highest index var line_size = line_max - line_min; var line_offset = target.Line - line_min; var sample_min = Math.Max(0, target.Sample - border); var sample_max = Math.Min(dem_size - 1, target.Sample + patch_size + border); // 1 more than the highest index var sample_size = sample_max - sample_min; var sample_offset = target.Sample - sample_min; var cpu_caster_points_size = line_size * sample_size * 3; var cpu_caster_points = new float[cpu_caster_points_size]; FillNearCasterArray(cpu_caster_points, target.Points[0][0], line_min, line_max, sample_min, sample_max); //DumpNearFieldTestCsv(cpu_caster_points, cpu_matrices); var test_floats_size = Horizon.HorizonSamples * TerrainPatch.NearHorizonOversample; var test_floats = new float[test_floats_size]; using (var gpu_matrices = accelerator.Allocate <float>(cpu_matrices_size)) using (var gpu_horizon = accelerator.Allocate <float>(cpu_horizon_size)) using (var gpu_caster_points = accelerator.Allocate <float>(cpu_caster_points_size)) using (var gpu_test_floats = accelerator.Allocate <float>(test_floats_size)) { gpu_matrices.CopyFrom(cpu_matrices, 0, 0, cpu_matrices_size); gpu_horizon.CopyFrom(cpu_horizon, 0, 0, cpu_horizon_size); gpu_caster_points.CopyFrom(cpu_caster_points, 0, 0, cpu_caster_points_size); gpu_test_floats.CopyFrom(test_floats, 0, 0, test_floats_size); var groupSize = accelerator.MaxNumThreadsPerGroup; Index launchDimension = Horizon.HorizonSamples * TerrainPatch.NearHorizonOversample; const float d_min = 1f; var d_max = (float)TerrainPatch.MaximumLocalDistance; const float d_step = TerrainPatch.LocalStep; var kernel1 = accelerator.LoadAutoGroupedStreamKernel <Index, int, int, int, int, int, int, float, float, float, ArrayView <float>, ArrayView <float>, ArrayView <float>, ArrayView <float> >(NearHorizonKernel1); Console.WriteLine(@"Launching near horizon kernels ... "); if (true) { for (var target_line = 0; target_line < TerrainPatch.DefaultSize; target_line++) { for (var target_sample = 0; target_sample < TerrainPatch.DefaultSize; target_sample++) { kernel1(launchDimension, target_line, target_sample, line_offset, sample_offset, line_size, sample_size, d_min, d_max, d_step, gpu_caster_points, gpu_matrices, gpu_horizon, gpu_test_floats); } } } else { kernel1(launchDimension, 0, 0, line_offset, sample_offset, line_size, sample_size, d_min, d_max, d_step, gpu_caster_points, gpu_matrices, gpu_horizon, gpu_test_floats); } gpu_horizon.CopyTo(cpu_horizon, 0, 0, cpu_horizon_size); gpu_test_floats.CopyTo(test_floats, 0, 0, test_floats_size); // Update the horizons for (var line = 0; line < TerrainPatch.DefaultSize; line++) { for (var sample = 0; sample < TerrainPatch.DefaultSize; sample++) { var offset = (line * TerrainPatch.DefaultSize + sample) * Horizon.HorizonSamples; var buffer = target.Horizons[line][sample].Buffer; for (var i = 0; i < Horizon.HorizonSamples; i++) { buffer[i] = cpu_horizon[i + offset]; } } } } } } }
/// <summary> /// Update the horizons of a patch based on a list of shadow casters. /// The horizons will be in slope, not angle, format /// </summary> /// <param name="target"></param> /// <param name="casters"></param> public void UpdateHorizons(TerrainPatch target, List <TerrainPatch> casters) { Debug.Assert(Terrain != null); if (casters.Count < 1) { return; } using (var context = new Context()) { AcceleratorId aid = Accelerator.Accelerators.Where(id => id.AcceleratorType == AcceleratorType.Cuda).FirstOrDefault(); if (aid.AcceleratorType != AcceleratorType.Cuda) { Console.WriteLine(@"There is no CUDA accelerator present. Doing nothing."); return; } using (var accelerator = Accelerator.Create(context, aid)) { target.FillPoints(Terrain); target.FillMatricesRelativeToPoint(Terrain, target.Points[0][0]); // Matrices var cpu_matrices_size = target.Height * target.Width * 12; var basePoint = target.Points[0][0]; var cpu_matrices = MakeCPUMatrices(target); // Horizon (load from target) var cpu_horizon_size = target.Height * target.Width * Horizon.HorizonSamples; var cpu_horizon = new int[cpu_horizon_size]; for (var line = 0; line < TerrainPatch.DefaultSize; line++) { for (var sample = 0; sample < TerrainPatch.DefaultSize; sample++) { var offset = (line * TerrainPatch.DefaultSize + sample) * Horizon.HorizonSamples; var buffer = target.Horizons[line][sample].Buffer; for (var i = 0; i < Horizon.HorizonSamples; i++) { cpu_horizon[i + offset] = SlopeToEncoding(buffer[i]); } } } // Caster points var cpu_caster_points_size = casters[0].Width * casters[0].Height * 3; var cpu_caster_points = new float[cpu_caster_points_size]; // test array var cpu_test_array = new float[20]; using (var gpu_matrices = accelerator.Allocate <float>(cpu_matrices_size)) using (var gpu_horizon = accelerator.Allocate <int>(cpu_horizon_size)) using (var gpu_caster_points = accelerator.Allocate <float>(cpu_caster_points_size)) using (var gpu_test_array = accelerator.Allocate <float>(cpu_test_array.Length)) { gpu_matrices.CopyFrom(cpu_matrices, 0, 0, cpu_matrices_size); gpu_horizon.CopyFrom(cpu_horizon, 0, 0, cpu_horizon_size); var groupSize = accelerator.MaxNumThreadsPerGroup; var launchDimension = new GroupedIndex2( new Index2(128, 128), // (data.Length + groupSize - 1) / groupSize, // Compute the number of groups (round up) new Index2(1, 128)); var kernel1 = accelerator.LoadSharedMemoryStreamKernel1 <GroupedIndex2, ArrayView <float>, ArrayView <float>, ArrayView <int>, ArrayView <float>, ArrayView <int> >(ShadowKernel1); //var stopwatch = new Stopwatch(); //stopwatch.Start(); foreach (var caster in casters) { caster.FillPoints(Terrain); CopyPointsToCpuArray(caster, basePoint, cpu_caster_points); gpu_caster_points.CopyFrom(cpu_caster_points, 0, 0, cpu_caster_points_size); kernel1(launchDimension, gpu_caster_points, gpu_matrices, gpu_horizon, gpu_test_array); accelerator.Synchronize(); } // Copy out data gpu_horizon.CopyTo(cpu_horizon, 0, 0, cpu_horizon_size); gpu_test_array.CopyTo(cpu_test_array, 0, 0, cpu_test_array.Length); //stopwatch.Stop(); //Console.WriteLine($"kernel time={stopwatch.Elapsed} cpu_horizon.Max()={cpu_horizon.Max()} cpu_horizon[0]={cpu_horizon[0]}"); // Update the horizons for (var line = 0; line < TerrainPatch.DefaultSize; line++) { for (var sample = 0; sample < TerrainPatch.DefaultSize; sample++) { var offset = (line * TerrainPatch.DefaultSize + sample) * Horizon.HorizonSamples; var buffer = target.Horizons[line][sample].Buffer; for (var i = 0; i < Horizon.HorizonSamples; i++) { buffer[i] = EncodingToSlope(cpu_horizon[i + offset]); } } } //Console.WriteLine($" max slope={cpu_horizon.Select(EncodingToSlope).Max()}"); } } } }