Rough Seas with Triton at duskLooking to squeeze a few more frames per second out of the Triton Ocean SDK? Here are a few tips on maximizing performance when using Triton.

Enable Uniform Buffer Objects

If you’re using OpenGL, Triton may be configured to use uniform buffer objects (UBO’s) to pass data to its shaders more efficiently. This isn’t on by default, because some drivers seem to have trouble with it – but if you’re targeting known hardware or modern hardware, this should be safe to enable.

To do so, open up the file Resources/Triton.config in a text editor, and look for this line:

use-uniform-buffer-objects = no

Change the “no” to “yes”, and that’s it.

Make sure GPGPU acceleration is working

Triton spends most of its time updating its physical simulation of tens of thousands of waves every frame, and it’s important that you’re using the GPU to accelerate these computations.

Again, open up Resources/Triton.config, and change the setting enable-debug-messages to yes temporarily. When you run your Triton-based application next, you should see some lines that start with TRITON: in your debugger output.

Make sure these lines indicate that CUDA, OpenCL, or compute shaders are being used successfully. If it says that IPP or FFTCPU is being used, then you may have a configuration problem. NVidia systems should be using CUDA or compute shaders, and AMD systems should be using OpenCL or compute shaders. If not, make sure your drivers are up to date – and if you are building Triton from source (ie, on Linux,) make sure you have the CUDA Toolkit or AMD APP SDK properly installed on your development system before building Triton. Another common problem under Linux is the dynamic linking of CUDA shared objects; make sure the TritonCUDA.so and CUDA runtime shared objects are showing up when using ldd. Follow the instructions carefully when installing the CUDA Toolkit on Linux; you may need to modify your LD_LIBRARY_PATH for example.

Avoid thread deadlocks

Most of Triton’s public API’s are protected by a mutex object. If your application is multi-threaded, you might be calling Ocean::UpdateSimulation() from your update thread. However, doing so can cause deadlocks with the Ocean::Draw() method in your drawing thread. In general, that is only worth doing if you have multiple windows – for a single view, don’t call Ocean::UpdateSimulation() at all, and just let Ocean::Draw() call it when it needs to automatically.

If your application is single-threaded, then those mutex objects aren’t doing you any good anyhow. You can disable them using the thread-safe setting in the resources/triton.config file.

Optimize multi-view applications

If your application has more than one window or view, make sure you’re not computing the ocean waves more than once per frame. If your engine has an update thread or callback that is called once per frame, call Triton::Ocean::UpdateSimulation() from it to ensure waves are only updated once per frame, and not once per view.

Optimize height map transfers

If you are passing height maps to Triton at runtime via Triton::Environment::SetHeightMap(), you can prevent this from stalling the graphics pipeline. In Resources/Triton.config, look for this line:

height-map-copy-use-pbo = no

And change the “no” to “yes”. Under OpenGL, this will use pixel buffer objects to transfer the height map to system memory asynchronously. We’ll probably enable this by default at some point in the future, but for now it’s a little too new for us to be 100% confident in driver compatibility.

Disable features you don’t need

Triton::Ocean::Create has a couple of important parameters: enableHeightReads, and enableBreakingWaves. If you don’t need to do real-time wave height queries with Triton, passing false to enableHeightReads can make a big difference. If you’re not using the breaking waves at shorelines feature, disabling that will simplify Triton’s shaders and make them more efficient as well.

Triton’s particle-based spray effects can also be expensive. Ocean::EnableSpray(false) may be used to turn off spray on wave crests, and the WakeGeneratorParameters have a spray parameter as well if you don’t need spray from ship wakes. Better still, set fft-enable-spray to “no” in Triton.config if you’re sure you’ll never need it.

If you won’t be calling Triton from multiple threads, disabling the “thread-safe” setting in Triton.config will spare you the cost of several mutex calls each frame.

Most of the complexity of Triton’s shaders come from ship wakes, so if you don’t need ship wakes, disabling them can help a lot too. Look for the wake-kelvin-wakes and wake-propeller-backwash settings in Triton.config, and set them to “no” if you don’t need them.

Even more

If you explore the other settings in Triton.config, you’ll find there are many other ways to choose your own balance between quality and performance. If you need additional guidance, feel free to contact us at support@sundog-soft.com for more tuning help!