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

First time graphics - bad performance in software rendering

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

Problem

I'm writing an utility audio plugin that specializes in "fullscreen" (the window is freely resizable) visualization of audio, like spectrograms, oscilloscopes and in this instance, a vectorscope. For those who doesn't know, a vectorscope is a coordinate system where each sample in an audiostream maps the coordinates (left is x, while right channel is y). Here's an image of the visualization the program performs:

I am however experiencing troublesome performance, dialogs like 1280x1024 can consume 100% of one core depending on circumstances.

I'm currently hoping my rendering code is simply bad and that the performance can be increased, therefore I'm asking for a review of the following code. This is the first time I'm writing graphics code, so bear with me. So far I've steered clear of most bad premature optimizations (I can also measure most didn't do much), and tried to retain nice modularization of the code.

I've included the relevant parts of the code and I hope it's clear what's going on. Here's the painting function:

```
void CVectorScope::paint(Graphics & g)
{
auto clockStart = cpl::Misc::ClockCounter();

// erase previous content
waveFormGraphics->fillAll(Colours::black);

// .. draw graph here

// render waveform of all audio samples in the buffer, interconnecting each new pair with a line to the previous
renderGeneric(numSamples,
// this is the 'fetch' lambda, that returns a sample from the audio buffer
&
{
return audioData[channel].directAccess(sample);
},
// this is the line-drawing lambda
[](Image::BitmapData & data, int x, int y, int ox, int oy, float sampleFade)
{
bDrawLine(x, y, ox, oy,
// the line drawing lambda uses following lambda to color pixels
[&](int xx,

Solution

Here are some suggestions:

Double Buffering

Draw into one buffer (bitmap, etc) while the graphics processor is processing the other. When the graphics processor is finished, switch buffers. Use more buffers as necessary to accommodate speed differences.

Use threads

You could use 3 threads. Thread 1 reads the data and stores into a data buffer. Thread 2 processes data from the data buffer and writes into an image buffer. Thread 3 gives the image buffer to the graphics processor.

Don't Paint Often
Painting is an expensive operation. Consider some of the operations such as clipping that need to be performed. Instead, draw many times into a buffer, then paint to the buffer. For example, perform 4 draw operations into a buffer then paint the buffer. You've just saved 3 expensive paint operations.

Use a library

Use a graphics library that will detect your graphics hardware and exploit as much hardware functionality. Some GPUs have the ability to BitBlit, which is to copy rectangular regions in memory to the display without using the CPU. (Taking time away from the CPU).

Context

StackExchange Code Review Q#55802, answer score: 4

Revisions (0)

No revisions yet.