Skip to content

Commit 2fbaf75

Browse files
committed
Add high-precision GPU trilinear interpolation for 3D LUTs.
This new code path can be enabled by disabling the new default-enabled OPTIMIZATION_NATIVE_GPU_TRILINEAR optimization flag. The existing code path used the GPU's native trilinear texture interpolation function, which, although faster, quantized the lookup coordinates which could cause banding. That's still the default, but full-precision trilinear interpolation can optionally be used instead. Signed-off-by: Nathan Vegdahl <[email protected]>
1 parent 22f5ee0 commit 2fbaf75

File tree

20 files changed

+116
-48
lines changed

20 files changed

+116
-48
lines changed

include/OpenColorIO/OpenColorTypes.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,13 @@ enum OptimizationFlags : unsigned long
619619
*/
620620
OPTIMIZATION_NO_DYNAMIC_PROPERTIES = 0x10000000,
621621

622+
/**
623+
* For GPU processor, use native trilinear interpolation for 3D LUTs. This is faster,
624+
* but on many GPUs also lower precision. With low-resolution LUTs, LUTs with large
625+
* extents, or LUTs applied in a linear color space this can sometimes cause color banding.
626+
*/
627+
OPTIMIZATION_NATIVE_GPU_TRILINEAR = 0x20000000,
628+
622629
/// Apply all possible optimizations.
623630
OPTIMIZATION_ALL = 0xFFFFFFFF,
624631

@@ -645,6 +652,7 @@ enum OptimizationFlags : unsigned long
645652
OPTIMIZATION_COMP_LUT1D |
646653
OPTIMIZATION_LUT_INV_FAST |
647654
OPTIMIZATION_FAST_LOG_EXP_POW |
655+
OPTIMIZATION_NATIVE_GPU_TRILINEAR |
648656
OPTIMIZATION_COMP_SEPARABLE_PREFIX),
649657

650658
OPTIMIZATION_GOOD = OPTIMIZATION_VERY_GOOD | OPTIMIZATION_COMP_LUT3D,

src/OpenColorIO/GPUProcessor.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ void GPUProcessor::Impl::finalize(const OpRcPtrVec & rawOps, OptimizationFlags o
8585
// Is NoOp ?
8686
m_isNoOp = m_ops.isNoOp();
8787

88+
// Store optimization flags for use when generating shader code.
89+
m_oFlags = oFlags;
90+
8891
// Does the color processing introduce crosstalk between the pixel channels?
8992
m_hasChannelCrosstalk = m_ops.hasChannelCrosstalk();
9093

@@ -104,7 +107,7 @@ void GPUProcessor::Impl::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCrea
104107
// Create the shader program information.
105108
for(const auto & op : m_ops)
106109
{
107-
op->extractGpuShaderInfo(shaderCreator);
110+
op->extractGpuShaderInfo(shaderCreator, m_oFlags);
108111
}
109112

110113
WriteShaderHeader(shaderCreator);

src/OpenColorIO/GPUProcessor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class GPUProcessor::Impl
4141
OpRcPtrVec m_ops;
4242
bool m_isNoOp = false;
4343
bool m_hasChannelCrosstalk = true;
44+
OptimizationFlags m_oFlags = OPTIMIZATION_DEFAULT;
4445
std::string m_cacheID;
4546
mutable Mutex m_mutex;
4647
};

src/OpenColorIO/Op.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ class Op
246246
virtual bool supportedByLegacyShader() const { return true; }
247247

248248
// Create & add the gpu shader information needed by the op. Op has to be finalized.
249-
virtual void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const = 0;
249+
virtual void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags oFlags = OPTIMIZATION_DEFAULT) const = 0;
250250

251251
virtual bool isDynamic() const;
252252
virtual bool hasDynamicProperty(DynamicPropertyType type) const;

src/OpenColorIO/ops/cdl/CDLOp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class CDLOp : public Op
5050

5151
ConstOpCPURcPtr getCPUOp(bool fastLogExpPow) const override;
5252

53-
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const override;
53+
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const override;
5454

5555
protected:
5656
ConstCDLOpDataRcPtr cdlData() const { return DynamicPtrCast<const CDLOpData>(data()); }
@@ -133,7 +133,7 @@ ConstOpCPURcPtr CDLOp::getCPUOp(bool fastLogExpPow) const
133133
return GetCDLCPURenderer(data, fastLogExpPow);
134134
}
135135

136-
void CDLOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const
136+
void CDLOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const
137137
{
138138
ConstCDLOpDataRcPtr data = cdlData();
139139
GetCDLGPUShaderProgram(shaderCreator, data);

src/OpenColorIO/ops/exponent/ExponentOp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ class ExponentOp : public Op
150150

151151
ConstOpCPURcPtr getCPUOp(bool fastLogExpPow) const override;
152152

153-
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const override;
153+
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const override;
154154

155155
protected:
156156
ConstExponentOpDataRcPtr expData() const { return DynamicPtrCast<const ExponentOpData>(data()); }
@@ -251,7 +251,7 @@ ConstOpCPURcPtr ExponentOp::getCPUOp(bool /*fastLogExpPow*/) const
251251
return std::make_shared<ExponentOpCPU>(expData());
252252
}
253253

254-
void ExponentOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const
254+
void ExponentOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const
255255
{
256256
GpuShaderText ss(shaderCreator->getLanguage());
257257
ss.indent();

src/OpenColorIO/ops/exposurecontrast/ExposureContrastOp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class ExposureContrastOp : public Op
4949

5050
ConstOpCPURcPtr getCPUOp(bool fastLogExpPow) const override;
5151

52-
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const override;
52+
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const override;
5353

5454
protected:
5555
ConstExposureContrastOpDataRcPtr ecData() const
@@ -135,7 +135,7 @@ ConstOpCPURcPtr ExposureContrastOp::getCPUOp(bool /*fastLogExpPow*/) const
135135
return GetExposureContrastCPURenderer(ecOpData);
136136
}
137137

138-
void ExposureContrastOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const
138+
void ExposureContrastOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const
139139
{
140140
ConstExposureContrastOpDataRcPtr ecOpData = ecData();
141141
GetExposureContrastGPUShaderProgram(shaderCreator, ecOpData);

src/OpenColorIO/ops/fixedfunction/FixedFunctionOp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class FixedFunctionOp : public Op
4545

4646
ConstOpCPURcPtr getCPUOp(bool fastLogExpPow) const override;
4747

48-
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const override;
48+
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const override;
4949

5050
protected:
5151
ConstFixedFunctionOpDataRcPtr fnData() const { return DynamicPtrCast<const FixedFunctionOpData>(data()); }
@@ -125,7 +125,7 @@ ConstOpCPURcPtr FixedFunctionOp::getCPUOp(bool /*fastLogExpPow*/) const
125125
return GetFixedFunctionCPURenderer(data);
126126
}
127127

128-
void FixedFunctionOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const
128+
void FixedFunctionOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const
129129
{
130130
ConstFixedFunctionOpDataRcPtr fnOpData = fnData();
131131
GetFixedFunctionGPUShaderProgram(shaderCreator, fnOpData);

src/OpenColorIO/ops/gamma/GammaOp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class GammaOp : public Op
4444

4545
ConstOpCPURcPtr getCPUOp(bool fastLogExpPow) const override;
4646

47-
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const override;
47+
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const override;
4848

4949
protected:
5050
ConstGammaOpDataRcPtr gammaData() const { return DynamicPtrCast<const GammaOpData>(data()); }
@@ -123,7 +123,7 @@ ConstOpCPURcPtr GammaOp::getCPUOp(bool fastLogExpPow) const
123123
return GetGammaRenderer(data, fastLogExpPow);
124124
}
125125

126-
void GammaOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const
126+
void GammaOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const
127127
{
128128
ConstGammaOpDataRcPtr data = gammaData();
129129
GetGammaGPUShaderProgram(shaderCreator, data);

src/OpenColorIO/ops/gradingprimary/GradingPrimaryOp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class GradingPrimaryOp : public Op
5252

5353
ConstOpCPURcPtr getCPUOp(bool fastLogExpPow) const override;
5454

55-
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const override;
55+
void extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const override;
5656

5757
protected:
5858
ConstGradingPrimaryOpDataRcPtr primaryData() const
@@ -190,7 +190,7 @@ ConstOpCPURcPtr GradingPrimaryOp::getCPUOp(bool /*fastLogExpPow*/) const
190190
return GetGradingPrimaryCPURenderer(data);
191191
}
192192

193-
void GradingPrimaryOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator) const
193+
void GradingPrimaryOp::extractGpuShaderInfo(GpuShaderCreatorRcPtr & shaderCreator, OptimizationFlags /*oFlags*/) const
194194
{
195195
ConstGradingPrimaryOpDataRcPtr data = primaryData();
196196
GetGradingPrimaryGPUShaderProgram(shaderCreator, data);

0 commit comments

Comments
 (0)