HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Line rendering optimization

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
optimizationrenderingline

Problem

I spent the past hour trying to optimize a block of code I wrote that renders a simple coloured line directly to a backbuffer.

I've compared it with one of the DrawLine method implementations of the WriteableBitmapEx project, and found that my algorithm isn't quite as fast (unless I use Parallel).

public static unsafe void DrawLineVector(this IntPtr target, Line2D line, int colour, int width, int height)
{
    var buf = (int*) target;
    var start = line.Start;
    var lineVector = line.Stop - start;
    var steps = (int)lineVector.Magnitude();
    var uX = lineVector.X / steps;
    var uY = lineVector.Y / steps;
    var col = colour;
    Parallel.For(0, steps, i =>
    //for (var i = 0; i != steps; ++i)
    {
        var x = start.X + uX * i;
        var y = start.Y + uY * i;
        if (x > -1 && y > -1 && x < width && y < height)
            buf[(int)y * width + (int)x] = col;
        //x += uX;
        //y += uY;
    }
    );
}


Note, the Line2D object is basically just a container for two VectorD objects (which are my own implementation of vectors).

Running this as it is currently, will get me, on my machine, roughly 300MPixels per second, while the "default" DrawLine method from WriteableBitmapEx gets me around 170MPixels per second. If I use the 'serial' version of this (i.e. not use Parallel), I get around 100MPixels per second.

Is there any way I can optimize this further?

Solution

Because you're comparing your performance with that of the WriteableBitmapEx project, you might like to compare your algorithm with theirs, which is here on github: WriteableBitmapShapeExtensions.cs

You say your performance isn't much slower than theirs (100 versus 170 MPixels/second).

A difference between yours and there's might be that yours is using float or double arithmetic, whereas theirs is using int arithmetic.

Their code is much longer (more lines of code) than yours, but their inner loop is something like this:

for (int x = x1; x > PRECISION_SHIFT;
           if (y != previousY)
           {
              previousY = y;
              index += k;
           }
           else
           {
              ++index;
           }
        }


Note:

  • Only int (not double)



  • Few branches



  • Every write is to a significant pixels (in your algorithm if you write a line at 45 degrees then you do 1.414 writes per pixels).

Code Snippets

for (int x = x1; x <= x2; ++x)
        {
           pixels[index] = color;
           ys += incy;
           y = ys >> PRECISION_SHIFT;
           if (y != previousY)
           {
              previousY = y;
              index += k;
           }
           else
           {
              ++index;
           }
        }

Context

StackExchange Code Review Q#44474, answer score: 5

Revisions (0)

No revisions yet.