Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Debugging OpenGL issues in Minecraft mods using apitrace

Apitrace tutorial

Debugging OpenGL issues in Minecraft mods using apitrace

In the transition of Minecraft version 1.14 to 1.15, Mojang introduced some sweeping changes to the way rendering is performed; while the internal code still relies on GL1-era immediate-mode, block and entity renderer classes now provide their vertices to a specific RenderLayer* which are later rendered in ordered batches.

These changes broke a majority of Minecraft mods; in the process of porting a mod to 1.15, I had to frequently rely on a tool called “apitrace”, and I thought a quick how-to might come in handy for others struggling with similar problems. Apitrace allows capturing every OpenGL call an application makes, and later replaying these calls and inspecting the entire GL state machine at each rendering step.

For this tutorial, I am using the MultiMC launcher.

First step: Install apitrace

Some operating systems already provide binaries for Apitrace, for everyone else the instructions to build Apitrace from source can be found here.


sudo dnf install apitrace apitrace-gui


pacman -S apitrace


For Windows you can get precompiled builds from here. Then add the bin folder from apitrace to the PATH environment variable. The added path should look something like this: C:\...\apitrace-latest-win64\bin

Second step: Load apitrace into Minecraft

Next, we need to define the wrapper command that will start Minecraft with tracing enabled:

apitrace trace --output minecraft.trace --api gl

In MultiMC, edit your instance and click on the Settings tab, then on the Custom Commands tab on the right and tick the check box. Now provide the wrapper command from above, like so:

MultiMC settings

That’s it for setup, now you can launch the instance as usual. For debugging specific issues, I would recommend preparing a world save that you can quickly load to cause the issue, then close Minecraft again. In general you want to leave it running as little as possible, because every rendered frame is recorded.

When you have successfully reproduced the issue and closed Minecraft, open your instance’s .minecraft folder, where you will find a file named minecraft.trace.
Open this file with the apitrace-gui (qapitrace) you installed earlier, and now you can inspect every frame, GL call by GL call:

Inspecting GL state in apitrace GUI (Note that I have hidden all except render calls via Trace➜Options)

I will not include an in-depth tutorial on apitrace itself here, as there are plenty on the web already. If you’re new to this tool, play around a bit: Right click a GL call and select Lookup State to inspect state settings, bound textures/framebuffers etc. right up until after this GL call was executed.

One more tip though: Combing through thousands of GL calls can be confusing, and println() calls will not show up. There is however an analogue to printf-style debugging:

/* imports */
import org.lwjgl.opengl.GREMEDYStringMarker;
/* [...] */
GREMEDYStringMarker.glStringMarkerGREMEDY("ignoring lighting");
/* render code */
GREMEDYStringMarker.glStringMarkerGREMEDY("rendering a quad");
/* more render code */   

String markers in the trace
(Note: If you’re trimming the view to a subset of calls, eg. draw commands, be sure to include |glStringMarkerGREMEDY in the filter list)

I recommend using my utility library/mod TraceUtil, which just by dropping it into your mods folder, will give you some automatic annotations to common Minecraft renderpaths and also allow you to insert custom strings without the GREMEDY entrypoints.

*Classname provided by yarn
Thanks to @march for the Arch and Windows install steps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment