Trying to optimize NanoVG

The Rack uses NanoVG to render all graphics

And we all know that the Rack needs a dedicated gaming graphics card to work fine on high frame rates.

Lately I found this article about optimizing NanoVG

No I’m trying to optimize NanoVG as described above, at least for my personal needs, because AFAIK it is impossible to replace the graphics rendering code in a similar way the module-browser was replaced by Stoermelder’s MB module in Rack v1.1.6

Has anyone tried to do similar things so far?

I’ve never done OpenGL coding, but however, I’m going to post my struggling and forthcoming here in this thread :sunglasses:

3 Likes

That’s a fascinating article. Although I think I disagree with the statement that anti-aliasing is not necessary for rectangular fill.

That statement assumes that rectangles are always rendered to exact pixel boundaries, which is not the case in VCV.

1 Like

I saw that article a few months ago and tried some of the shader optimisations within Rack, but the results were disappointing.

Don’t let that put you off though - I didn’t spend a lot of time on it, and I suspect they’ll make a big difference on some graphics cards and little on others.

The first thing I’d do in your position is simply remove some big chunks of the code altogether and see what difference that makes. It’s possible that most of your rendering disappears but the frame rate doesn’t improve by much. If that happens, you’ll be disappointed but at least you’ll know that the plan wasn’t going to work, at least on your hardware.

Keep us posted - I’ll be very interested to hear what you discover!

2 Likes

What I did so far: In nanovg_gl.h I replaced

	"	if (type == 0) {			// Gradient\n"
	"		// Calculate gradient color using box gradient\n"
	"		vec2 pt = (paintMat * vec3(fpos,1.0)).xy;\n"
	"		float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);\n"
	"		vec4 color = mix(innerCol,outerCol,d);\n"
	"		// Combine alpha\n"
	"		color *= strokeAlpha * scissor;\n"
	"		result = color;\n"

by

	"	if (type == 0) {			// Gradient\n"
	"		result = innerCol;\n"

Now the Rack has no antialiasing at all.

Following the article this should improve performance by more than 20 times.

I’m on Windows using an NVIDIA GeForce GT 710 graphics card, it brings around 10% performance improvement.

That’s disappointing but I think it was worth giving it a try :thinking:

10% is a good start! I don’t think I saw that on my hardware (or maybe I just mucked it up somehow :slight_smile: )

I’m not sure how they’re measuring the difference - when they say “can improve performance by more than 20 times” they might mean just the shader performance, which is only part of the overall frame rate picture.

If the other optimisations bring similar improvements then they’ll add up to something very successful!

I think there’s more performance optimization possible in Rack itself. I found out that by simply disabling the module’s shadows I can get up to 15% performance improvement when zoom is set to 400%. This performance improvement decreases down to 5% on zoom = 100% and I didn’t see any noticeable improvements when zoomimg out.

Don’t forget that the impetus of the article was improving performance on an android device, which is likely to have a very limited GPU capability to start with, and may well lack good hardware for some of the shader’s requirements.

Isn’t one of the goals of vcv 3 to move away from nanovg entirely?

from the dev-log

Consider switching from nanovg to Skia or vkvg or Intel fastuidraw or something else. A nanovg API wrapper will be needed.

I don’t expect that to happen in 2022 :santa:

I’m going back to building Rack instead of the SDK so I can try out a few things. Can you outline how you did the above? Thanks.

I disabled all the lines inside the if (layer == -1) block in ModuleWidget::drawLayer().

The performance improvement takes place on GPU, not on CPU.

1 Like