public unsafe void ComputeMandelbrotSet( uint[,] iterations, int width, int height, double offsetX, double offsetY, double zoom, uint maxIterations, bool doublePrecision, ref bool cancel) { Resize(width, height); // Precompute the pixels coordinates. double startX = -(width / (height * zoom)) + offsetX; double startY = -1.0 / zoom + offsetY; double scale = 2 / (height * zoom); if (doublePrecision) { _doubleKernel(new Index2(width, height), _deviceMemory.View, width, height, startX, startY, scale, maxIterations); } else { _singleKernel(new Index2(width, height), _deviceMemory.View, width, height, (float)startX, (float)startY, (float)scale, maxIterations); } fixed(uint *ptr = iterations) { using var viewArrayWrapper = ViewPointerWrapper.Create(new IntPtr(ptr)); var arrayView = new ArrayView <uint>(viewArrayWrapper, 0, iterations.Length); _deviceMemory.CopyTo(arrayView, 0); _gpu.Synchronize(); } }
public unsafe void ComputeMandelbrotSet( uint[,] iterations, int width, int height, double offsetX, double offsetY, double zoom, uint maxIterations, bool doublePrecision, ref bool cancel) { Resize(width, height); var doubleOverhead = doublePrecision ? 32 : 1; var cores = _gpu.NumMultiprocessors * 128; // TODO ILGPU proper number of CUDA cores per multi processor. var maxPixelPerBatch = 200L * _gpu.ClockRate * cores / (doubleOverhead * maxIterations); var blockSizeX = 16; var blockSizeY = 8; var gridX = DivUp(width, blockSizeX); var gridY = DivUp(height, blockSizeY); var maxBlocks = DivUp(checked ((int)maxPixelPerBatch), blockSizeX * blockSizeY); var maxBlocksY = DivUp(maxBlocks, gridX); // Precompute the pixels coordinates. double startX = -(width / (height * zoom)) + offsetX; double startY = -1.0 / zoom + offsetY; double scale = 2 / (height * zoom); // Batch the mandelbrot computation into sets of block so that we avoid hitting the Windows watchdog timer for CUDA (5 seconds on Windows 10). for (int blockOffsetY = 0; blockOffsetY < gridY; blockOffsetY += maxBlocksY) { if (cancel) { break; } var lp = ((gridX, Math.Min(gridY, maxBlocksY)), (blockSizeX, blockSizeY)); if (doublePrecision) { _gpu.Launch(DoubleKernel, lp, _deviceMemory.View, width, height, blockOffsetY * blockSizeY, startX, startY, scale, maxIterations); } else { _gpu.Launch(SingleKernel, lp, _deviceMemory.View, width, height, blockOffsetY * blockSizeY, startX, startY, scale, maxIterations); } } fixed(uint *ptr = iterations) { using var viewArrayWrapper = ViewPointerWrapper.Create(new IntPtr(ptr)); var arrayView = new ArrayView <uint>(viewArrayWrapper, 0, iterations.Length); _deviceMemory.CopyTo(arrayView, 0); } }