in System.Numerics/SIMD/Mandelbrot/FlyThru.xaml.cs [158:237]
private void DrawMandelbrot(int cw, int ch)
{
// Get the renderer the user selected
var render = FractalRenderer.SelectRender(AddPixel, CheckAbort, UseSIMD, false, UseThreads, false); // always float, always raw
// Create a stopwatch to clock the calculation speed
Stopwatch timer = new Stopwatch();
// Allocate a pair of render buffers that will be swapped per frame
byte[] buffer1 = new byte[cw * ch * 4];
byte[] buffer2 = new byte[cw * ch * 4];
// This is the buffer selector
bool which = false;
// Set the two render properties
width = cw;
height = ch;
// Make sure the toImage buffer is null (no animation starting yet)
toImage = null;
// Start the XX FPS clock tick
Dispatcher.InvokeAsync(renderClock.Start);
// Start the timer
timer.Start();
foreach (var pt in RenderPoints)
{
// Select the buffer
bytes = which ? buffer1 : buffer2;
// Get the frame location & scale
float scale = pt.Item3;
float xc = pt.Item1;
float yc = pt.Item2;
XC = xc;
YC = yc;
Scale = scale;
// Get the min/max/step values and make sure they're all sensible
float xmin = (xc - scale / 2.0f).Clamp(-3.0f, 1f);
float xmax = (xc + scale / 2.0f).Clamp(-3.0f, 1f);
if (xmin > xmax)
{
float t = xmin;
xmin = xmax;
xmax = t;
}
float ymax = (yc + scale / 2.0f).Clamp(-1.5f, 1.5f);
float ymin = (yc - scale / 2.0f).Clamp(-1.5f, 1.5f);
if (ymin > ymax)
{
float t = ymin;
ymin = ymax;
ymax = t;
}
float ystep = (scale / (float)ch).Clamp(0, ymax - ymin);
float xstep = (scale / (float)cw).Clamp(0, xmax - xmin);
float step = Math.Max(ystep, xstep);
xmin = xc - (cw * step / 2);
xmax = xc + (cw * step / 2);
ymin = yc - (ch * step / 2);
ymax = yc + (ch * step / 2);
// Render this frame
render(xmin, xmax, ymin, ymax, step);
// Frame's complete: publish the current buffer for the
// render thread to draw
bytes = Interlocked.Exchange(ref toImage, bytes);
if (bytes == null)
{
// The render thread finished with the previous frame, swap it and keep going
which = !which;
}
else
{
// We've finished a frame before the rendering thread had a change to
// render the previous frame: leave the buffer selection alone, so the
// frame we just calculated gets skipped.
}
// Update the published clock
ElapsedTime = timer.Elapsed;
}
// Stop the timer
timer.Stop();
}