DaVinci Resolve DCTL and OFX Plugins

My set-up is specifically suited for compiling plugins for Resolve, hence the CUDA 8.0.90 driver. Otherwise I would probably use the most up to date versions (provided they work). The throttling issue is something worth approaching either Apple or Blackmagic Design about.

Hey everyone and Paul!

I’ve been trying to work with ACES inside Resolve’s YRGB mode using DCTLs instead of your ACES OFX plugin, as you recommend.

At first, I tried exporting DCTLs with the proper transforms from the Plugin, but couldn’t due to a permissions issue (even to the default folder). So I’m using your ACES_Sample as a reference, so I could create DCTLs for the transform.

For the IDT/ACES_to_ACEScct, it worked well, just like the OFX.
For the ACEScct_to_ACES/RRT/ODT (rec 709), it didn’t. I can’t figure out what I’m doing wrong.

#include “ACES_LIB/ACES_IDT.h”
#include “ACES_LIB/ACES_LMT.h”
#include “ACES_LIB/ACES_RRT.h”
#include “ACES_LIB/ACES_ODT.h”
DEVICE float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B)
float3 aces = make_float3(p_R, p_G, p_B);
aces = IDT_Alexa_v3_logC_EI800(aces);
aces = ACES_to_ACEScct(aces);
return aces;

#include “ACES_LIB/ACES_IDT.h”
#include “ACES_LIB/ACES_LMT.h”
#include “ACES_LIB/ACES_RRT.h”
#include “ACES_LIB/ACES_ODT.h”
DEVICE float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B)
float3 aces = make_float3(p_R, p_G, p_B);
aces = ACEScct_to_ACES(aces)
aces = RRT(aces)
aces = ODT_Rec709_100nits_dim(aces);
return aces;

Can anyone help me figure out what I’m doing wrong?

What does it say in the davinci log files? The source of the error can be traced there. Also, list your operating system, version of Resolve, and the exact location of the dctls.

Is that missing ACES_Conversion.h in the includes?

Dear Paul,

Thankyou for this OFX plugin. Its a great timesaver.
Just wondering if support for Sony Raw is available? Currently if i put it as bypass it still works on OFX but for sake having already some Sony transforms there already would be benificial.

The other thing is the plugin currently works on my 2009 Mac Pro. which has Nvidea cards.
Unfortunatly Trashcan mac Pros only have AMD cards which make the plugin unworkable.

Pedro (on the thread above) has suggested to build the DCTL using the sample file.
Coming from a total noob it looks alittle menacing if i change the values.

But am I right in removing the // tags to activate certain aspects of the OFX options?

I know youre only doing support for Cuda based setup but for those who are later Macs which are AMD based, what would you suggest to do?

Thankyou nonetheless.
Why doesnt BMD implement this brilliant workaround i dont understand. Giving big props and share of money you’ve given to the community.

1 Like

@Paul_Dore. Just updated to R15.1.1 and now considering using the DCTLs actively…

I have a question for you and @sdyer: The highlight fix LMT used to be applied directly on the clip in Resolve. Could we fit it somewhere else in this DCTL workflow? I tried adding it as the first and last nodes, after and before the RRT and after the IDT. This is not producing the same result as adding it directly to the clip (which I think might be problematic since the clip is technically not in ACES at that particular position).

So I guess my question would be: where do we put this RRT in the workflow?


I haven’t done any testing recently but would be happy to look into this.

To be clear what we’re talking about here,

1)What version of the highlight fix LMT are you using?
Are you using a DCTL version (like this one https://www.dropbox.com/s/itmg7pvrwr67nz9/LMT.Academy.FixHighlights.dctl?dl=0)
or are you using Resolve’s CLF implementation?

It sounds like you’re using DCTL. Have you tried using Resolve’s provided sample CLF?

2)What is your “Process Node LUTs in” dropdown set to? (in Settings->Color Management->Color Space and Transforms)

The DCTL is supposed to be applied in to ACES values (AP0/linear), so if this option is set to ACEScc AP1 Timeline Space, that could be causing the differences you’re seeing.

It absolutely shouldn’t go after the RRT. The artefacts happen in the RRT (or at least begin in the RRT and are hit home by the ODT). It really needs to be applied up front, to fix the image data before you do anything else to it.

If you are using @Paul_Dore’s DCTL, you could put it as the first node in the node tree, as long as it is sandwiched between transforms from the working space to ACES2065-1 and back. Something like the following (untested) code:

#include "ACES_LIB/ACES_LMT.h"
#include "ACES_LIB/ACES_CSC/ACES_Conversion.h"

__DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B)

float3 aces = make_float3(p_R, p_G, p_B);

aces = ACEScct_to_ACES(aces);
aces = LMT_FixHighlightImageArtifacts(aces);
aces = ACES_to_ACEScct(aces);

return aces;


Or you could bundle the IDT and LMT fix into a single DCTL which goes camera log −> ACES2065-1 −> LMT fix −> ACEScct.

Thanks @nick! Always very helpful!

Could I consider doing the following:

Node 1: IDT
Node 2: MT_FixHighlightImageArtifacts
Node 3: ACES_to_ACESccct
Subsequent nodes: color work

Then: ACEScct_to_ACES, RRT, ODT

What do you think!


Indeed you could. But there is no need for so many nodes. Using @Paul_Dore’s DCTL, you can combine multiple transforms into a single DCTL, as per my example above. Just replace the first aces = ACEScct_to_ACES(aces); line with the relevant IDT (and add ACES_IDT.h to the imports). I don’t know how Resolve optimises multiple sequential DCTL nodes, but you might find you get better performance with a single combined DCTL too. You could do the same for the output set as well.

You’re absolutely right! It was just for me to understand the workflow properly. ;o)

I did some tidying up over at my GitHub page. Here are some of the updated links:


ACES 1.1 OFX Plugin

ACES 1.1 OFX Source Files

I’ve merged the three different operating system specific files into a single plugin, so the same one will work on macOS, Win10, and Linux. Still CUDA only though.

ACES OFX Plugin can now run on CPU if CUDA is unavailable. A CPU only version should also work in other applications that can run OFX plugins.

The option of exporting a 3D LUT has also been added, with choice of cube size ranging from 3 to 129. The exported LUT is Resolve compatible, but other varieties of LUT can be included in future updates if requested.

Nice work @Paul_Dore! Does that include exporting Resolve LUTs with a shaper for situations where the input is linear?

The current version exports just a standard 3D LUT with an input range of 0.0 to 1.0, but a 1D shaper LUT could be included, and the option of modifying the input ranges could also be added. Defining when exactly to do this, and how it might affect the pipeline of transforms if implemented, is another consideration.

I added a shaper LUT option, as well as modifiable input values (for the 3D LUT), but I’m unsure about the initial 1D input range values (I used 0.0000019180 and 15.7761012587 from the LMT ACES v0.1.1.cube in Resolve), and how best to approach that. For now the shaper options are just Linear to ACEScc and Linear to ACEScct.

Here’s a link to a macOS compatible version of the OFX Plugin that includes the new features:

ACES OFX Plugin shaper

That seems a reasonable range. The SDR ODTs hit peak white 6.5 stops above mid grey, i.e. 0.18 * 2^6.5 = 16.2917, so 0 - 16.3 would also be a reasonable range if you want round numbers.

Finding an optimum shaper LUT is non-trivial. This may not produce a truly optimised result, but one approach I have used with success in the past is using a 1D LUT derived from the transform along the neutral axis as the shaper, and then using a 3D cube for what remains. In pseudocode, a LUT to apply out = f(in) would be constructed as follows:

shaper = f(linear_ramp_f3(min, max))

cube = f(inv_shaper(identity cube))

As per Nick’s suggestions, I’ve added more options to the Plugin.

I added a dynamic link between the min and max output values of the shaper and the input values of the 3D LUT (the values were preset in the earlier version), as well and an option to modify the size of the shaper (8bit to 14bit). Both shaper and 3D LUT have 10 decimal point deep values. Although the plugin UI rounds values up to 3 decimal points, the actual full values are preserved in the computation and printing of the LUT.

As it stands, only the Linear to ACEScc and Linear to ACEScct shapers are included (which are probably only of actual use when dealing with ACEScg data), but the entire ACES library is available to call as I converted it to C and included it in the .cpp file (this is separate to the DCTL and CUDA versions already translated).

At full capacity, the LUT is around 85MB with 16,384 rows for the shaper and 2,146,689 rows for the 3D LUT, but runs realtime on a modest system.

I’ve attached an example LUT (Linear to ACEScct shaper + unity 3D LUT). The previous link to the OFX Plugin has been updated for the new version.

Combined LUT

1 Like

ACES OFX Plugin and source files have been updated in the main repositories. I also added a separate version that works in Natron (and limited functionality in Nuke).

ACES 1.1 OFX Plugin

ACES 1.1 OFX Source Files

ACES 1.1 OFX Plugin Natron

Hi to all!

Is the plugin now efficient enough to be used on it’s own?