private void btnCompare_Click(object sender, EventArgs e) { if (!(Selection1.HasValue && (Selection2.Count > 0 || cbSelfShadow.Checked))) { return; } Console.Write(@"Comparing ... "); var target = GetPatch(Selection1.Value); target.InitializeHorizons(); target.Matrices = null; // Ensure these are generated fresh btnGpuCalculate_Click(sender, e); _gpu = new TerrainPatch(); _gpu.Horizons = target.Horizons; target.InitializeHorizons(); target.Matrices = null; // Ensure these are generated fresh (different from matrices for gpu) btnShadow2To1_Click(sender, e); _cpu = new TerrainPatch(); _cpu.Horizons = target.Horizons; _delta = new TerrainPatch(); _delta.InitializeHorizons(); // Subtract for (var i = 0; i < _cpu.Horizons.Length; i++) { for (var j = 0; j < _cpu.Horizons.Length; j++) { var g = _gpu.Horizons[i][j].Buffer; var d = _delta.Horizons[i][j].Buffer; var c = _cpu.Horizons[i][j].Buffer; for (var k = 0; k < d.Length; k++) { d[k] = c[k] - g[k]; } } } Console.WriteLine(@"Done"); Console.WriteLine($"delta[0,0]={_delta.Horizons[0][0].Buffer[0]}"); }
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]; } } } } } } }