Skip to content

Commit 929d536

Browse files
num3ricremiadoug-walker
authored
Exposed option to allow/disallow 1D texture GPU resources for 1D LUTs. (#1762)
* Exposed option to allow/disallow 1D texture GPU resources for 1D LUTs. Signed-off-by: Eric Renaud-Houde <[email protected]> * New API to get or add 1D LUT textures with the specified dimensions. Signed-off-by: Eric Renaud-Houde <[email protected]> * Fix errors relevealed by CIS related to texture dimension API change. Signed-off-by: Eric Renaud-Houde <[email protected]> * Update gpu shader tests away from now deprecated get/add texture functions. Signed-off-by: Eric Renaud-Houde <[email protected]> * Converted deprecated get/add texture functions from pure virtual to virtual. Signed-off-by: Eric Renaud-Houde <[email protected]> * Commenting out unused parameters on deprecated functions to mitigate warnings. Signed-off-by: Eric Renaud-Houde <[email protected]> * Addressing review notes. Signed-off-by: Eric Renaud-Houde <[email protected]> * Updated python addTexture/getTextures test with latest interface. Signed-off-by: Eric Renaud-Houde <[email protected]> * Further update python and metal samples to new texture dimensions API. Signed-off-by: Eric Renaud-Houde <[email protected]> * Improvements: moved default deprecated implementations to base classes, avoided asserts, fixed typo and naming. Signed-off-by: Eric Renaud-Houde <[email protected]> * Follow spacing/formatting convention arguments. Signed-off-by: Eric Renaud-Houde <[email protected]> * Removed the original addTexture and getTexture methods. Signed-off-by: Eric Renaud-Houde <[email protected]> --------- Signed-off-by: Eric Renaud-Houde <[email protected]> Co-authored-by: Rémi Achard <[email protected]> Co-authored-by: Doug Walker <[email protected]>
1 parent 9221ffa commit 929d536

File tree

14 files changed

+177
-67
lines changed

14 files changed

+177
-67
lines changed

include/OpenColorIO/OpenColorIO.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3156,6 +3156,10 @@ class OCIOEXPORT GpuShaderCreator
31563156
virtual void setTextureMaxWidth(unsigned maxWidth) = 0;
31573157
virtual unsigned getTextureMaxWidth() const noexcept = 0;
31583158

3159+
/// Allow 1D GPU resource type, otherwise always using 2D resources for 1D LUTs.
3160+
virtual void setAllowTexture1D(bool allowed) = 0;
3161+
virtual bool getAllowTexture1D() const = 0;
3162+
31593163
/**
31603164
* To avoid global texture sampler and uniform name clashes always append an increasing index
31613165
* to the resource name.
@@ -3213,16 +3217,25 @@ class OCIOEXPORT GpuShaderCreator
32133217
};
32143218

32153219
/**
3216-
* Add a 2D texture (1D texture if height equals 1).
3217-
*
3218-
* \note
3220+
* Dimension enum used to differentiate between 1D and 2D object/resource types.
3221+
*/
3222+
enum TextureDimensions : uint8_t {
3223+
TEXTURE_1D = 1,
3224+
TEXTURE_2D = 2,
3225+
};
3226+
3227+
/**
3228+
* Add a 1D or 2D texture
3229+
*
3230+
* \note
32193231
* The 'values' parameter contains the LUT data which must be used as-is as the dimensions and
32203232
* origin are hard-coded in the fragment shader program. So, it means one GPU texture per entry.
32213233
**/
32223234
virtual void addTexture(const char * textureName,
32233235
const char * samplerName,
32243236
unsigned width, unsigned height,
32253237
TextureType channel,
3238+
TextureDimensions dimensions,
32263239
Interpolation interpolation,
32273240
const float * values) = 0;
32283241

@@ -3474,6 +3487,7 @@ class OCIOEXPORT GpuShaderDesc : public GpuShaderCreator
34743487
unsigned & width,
34753488
unsigned & height,
34763489
TextureType & channel,
3490+
TextureDimensions & dimensions,
34773491
Interpolation & interpolation) const = 0;
34783492
virtual void getTextureValues(unsigned index, const float *& values) const = 0;
34793493

src/OpenColorIO/GpuShader.cpp

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class PrivateImpl
4949
const char * samplerName,
5050
unsigned w, unsigned h, unsigned d,
5151
GpuShaderDesc::TextureType channel,
52+
unsigned dimensions,
5253
Interpolation interpolation,
5354
const float * v)
5455
: m_textureName(textureName)
@@ -57,6 +58,7 @@ class PrivateImpl
5758
, m_height(h)
5859
, m_depth(d)
5960
, m_type(channel)
61+
, m_dimensions(dimensions)
6062
, m_interp(interpolation)
6163
{
6264
if (!textureName || !*textureName)
@@ -90,6 +92,7 @@ class PrivateImpl
9092
unsigned m_height;
9193
unsigned m_depth;
9294
GpuShaderDesc::TextureType m_type;
95+
unsigned m_dimensions;
9396
Interpolation m_interp;
9497

9598
std::vector<float> m_values;
@@ -158,21 +161,25 @@ class PrivateImpl
158161
typedef std::vector<Uniform> Uniforms;
159162

160163
public:
161-
PrivateImpl() : m_max1DLUTWidth(4 * 1024) {}
164+
PrivateImpl() : m_max1DLUTWidth(4 * 1024), m_allowTexture1D(true) {}
162165
PrivateImpl(const PrivateImpl & rhs) = delete;
163166
PrivateImpl& operator= (const PrivateImpl & rhs) = delete;
164167

165168
virtual ~PrivateImpl() {}
166169

167-
inline unsigned get3dLutMaxDimension() const { return Lut3DOpData::maxSupportedLength; }
170+
inline unsigned get3dLutMaxLength() const { return Lut3DOpData::maxSupportedLength; }
168171

169172
inline unsigned get1dLutMaxWidth() const { return m_max1DLUTWidth; }
170173
inline void set1dLutMaxWidth(unsigned maxWidth) { m_max1DLUTWidth = maxWidth; }
171174

175+
inline bool getAllowTexture1D() const { return m_allowTexture1D; }
176+
inline void setAllowTexture1D(bool allowed) { m_allowTexture1D = allowed; }
177+
172178
void addTexture(const char * textureName,
173179
const char * samplerName,
174180
unsigned width, unsigned height,
175181
GpuShaderDesc::TextureType channel,
182+
GpuShaderDesc::TextureDimensions dimensions,
176183
Interpolation interpolation,
177184
const float * values)
178185
{
@@ -184,7 +191,8 @@ class PrivateImpl
184191
throw Exception(ss.str().c_str());
185192
}
186193

187-
Texture t(textureName, samplerName, width, height, 1, channel, interpolation, values);
194+
unsigned numDimensions = static_cast<unsigned>(dimensions);
195+
Texture t(textureName, samplerName, width, height, 1, channel, numDimensions, interpolation, values);
188196
m_textures.push_back(t);
189197
}
190198

@@ -193,6 +201,7 @@ class PrivateImpl
193201
const char *& samplerName,
194202
unsigned & width, unsigned & height,
195203
GpuShaderDesc::TextureType & channel,
204+
GpuShaderDesc::TextureDimensions& dimensions,
196205
Interpolation & interpolation) const
197206
{
198207
if(index >= m_textures.size())
@@ -209,6 +218,14 @@ class PrivateImpl
209218
width = t.m_width;
210219
height = t.m_height;
211220
channel = t.m_type;
221+
if (t.m_dimensions > 2)
222+
{
223+
std::stringstream ss;
224+
ss << "1D LUT cannot have more than two dimensions: "
225+
<< t.m_dimensions << " > 2";
226+
throw Exception(ss.str().c_str());
227+
}
228+
dimensions = static_cast<GpuShaderDesc::TextureDimensions>(t.m_dimensions);
212229
interpolation = t.m_interp;
213230
}
214231

@@ -228,20 +245,20 @@ class PrivateImpl
228245

229246
void add3DTexture(const char * textureName,
230247
const char * samplerName,
231-
unsigned dimension,
248+
unsigned edgelen,
232249
Interpolation interpolation,
233250
const float * values)
234251
{
235-
if(dimension > get3dLutMaxDimension())
252+
if(edgelen > get3dLutMaxLength())
236253
{
237254
std::stringstream ss;
238-
ss << "3D LUT dimension exceeds the maximum: "
239-
<< dimension << " > " << get3dLutMaxDimension();
255+
ss << "3D LUT edge length exceeds the maximum: "
256+
<< edgelen << " > " << get3dLutMaxLength();
240257
throw Exception(ss.str().c_str());
241258
}
242259

243-
Texture t(textureName, samplerName, dimension, dimension, dimension,
244-
GpuShaderDesc::TEXTURE_RGB_CHANNEL,
260+
Texture t(textureName, samplerName, edgelen, edgelen, edgelen,
261+
GpuShaderDesc::TEXTURE_RGB_CHANNEL, 3,
245262
interpolation, values);
246263
m_textures3D.push_back(t);
247264
}
@@ -374,6 +391,7 @@ class PrivateImpl
374391
return false;
375392
}
376393
unsigned m_max1DLUTWidth;
394+
bool m_allowTexture1D;
377395
};
378396

379397
} // namespace GPUShaderImpl
@@ -452,6 +470,16 @@ void GenericGpuShaderDesc::setTextureMaxWidth(unsigned maxWidth)
452470
getImplGeneric()->set1dLutMaxWidth(maxWidth);
453471
}
454472

473+
bool GenericGpuShaderDesc::getAllowTexture1D() const noexcept
474+
{
475+
return getImplGeneric()->getAllowTexture1D();
476+
}
477+
478+
void GenericGpuShaderDesc::setAllowTexture1D(bool allowed)
479+
{
480+
getImplGeneric()->setAllowTexture1D(allowed);
481+
}
482+
455483
unsigned GenericGpuShaderDesc::getNumTextures() const noexcept
456484
{
457485
return unsigned(getImplGeneric()->m_textures.size());
@@ -461,20 +489,22 @@ void GenericGpuShaderDesc::addTexture(const char * textureName,
461489
const char * samplerName,
462490
unsigned width, unsigned height,
463491
TextureType channel,
492+
TextureDimensions dimensions,
464493
Interpolation interpolation,
465494
const float * values)
466495
{
467-
getImplGeneric()->addTexture(textureName, samplerName, width, height, channel, interpolation, values);
496+
getImplGeneric()->addTexture(textureName, samplerName, width, height, channel, dimensions, interpolation, values);
468497
}
469498

470499
void GenericGpuShaderDesc::getTexture(unsigned index,
471500
const char *& textureName,
472501
const char *& samplerName,
473502
unsigned & width, unsigned & height,
474503
TextureType & channel,
504+
TextureDimensions & dimensions,
475505
Interpolation & interpolation) const
476506
{
477-
getImplGeneric()->getTexture(index, textureName, samplerName, width, height, channel, interpolation);
507+
getImplGeneric()->getTexture(index, textureName, samplerName, width, height, channel, dimensions, interpolation);
478508
}
479509

480510
void GenericGpuShaderDesc::getTextureValues(unsigned index, const float *& values) const

src/OpenColorIO/GpuShader.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ class GenericGpuShaderDesc : public GpuShaderDesc
2929
unsigned getTextureMaxWidth() const noexcept override;
3030
void setTextureMaxWidth(unsigned maxWidth) override;
3131

32+
bool getAllowTexture1D() const noexcept override;
33+
void setAllowTexture1D(bool allowed) override;
34+
3235
// Accessors to the uniforms
3336
//
3437
unsigned getNumUniforms() const noexcept override;
@@ -47,16 +50,18 @@ class GenericGpuShaderDesc : public GpuShaderDesc
4750
//
4851
unsigned getNumTextures() const noexcept override;
4952
void addTexture(const char * textureName,
50-
const char * samplerNName,
53+
const char * samplerName,
5154
unsigned width, unsigned height,
5255
TextureType channel,
56+
TextureDimensions dimensions,
5357
Interpolation interpolation,
5458
const float * values) override;
5559
void getTexture(unsigned index,
5660
const char *& textureName,
5761
const char *& samplerName,
5862
unsigned & width, unsigned & height,
5963
TextureType & channel,
64+
TextureDimensions & dimensions,
6065
Interpolation & interpolation) const override;
6166
void getTextureValues(unsigned index, const float *& values) const override;
6267

src/OpenColorIO/ops/lut1d/Lut1DOpGPU.cpp

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -189,21 +189,29 @@ void GetLut1DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator,
189189
std::string name(resName.str());
190190
StringUtils::ReplaceInPlace(name, "__", "_");
191191

192+
GpuShaderDesc::TextureDimensions dimensions = GpuShaderDesc::TEXTURE_1D;
193+
if (height > 1 || lutData->isInputHalfDomain()
194+
|| shaderCreator->getLanguage() == GPU_LANGUAGE_GLSL_ES_1_0
195+
|| shaderCreator->getLanguage() == GPU_LANGUAGE_GLSL_ES_3_0
196+
|| !shaderCreator->getAllowTexture1D())
197+
{
198+
dimensions = GpuShaderDesc::TEXTURE_2D;
199+
}
200+
192201
// (Using CacheID here to potentially allow reuse of existing textures.)
193202
shaderCreator->addTexture(name.c_str(),
194203
GpuShaderText::getSamplerName(name).c_str(),
195204
width,
196205
height,
197206
singleChannel ? GpuShaderCreator::TEXTURE_RED_CHANNEL
198207
: GpuShaderCreator::TEXTURE_RGB_CHANNEL,
208+
dimensions,
199209
lutData->getConcreteInterpolation(),
200210
&values[0]);
201211

202212
// Add the LUT code to the OCIO shader program.
203213

204-
if (height > 1 || lutData->isInputHalfDomain()
205-
|| shaderCreator->getLanguage() == GPU_LANGUAGE_GLSL_ES_1_0
206-
|| shaderCreator->getLanguage() == GPU_LANGUAGE_GLSL_ES_3_0)
214+
if (dimensions == GpuShaderDesc::TEXTURE_2D)
207215
{
208216
// In case the 1D LUT length exceeds the 1D texture maximum length,
209217
// or the language doesn't support 1D textures,
@@ -261,29 +269,28 @@ void GetLut1DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator,
261269
// At this point 'dep' contains the raw half
262270
// Note: Raw halfs for NaN floats cannot be computed using
263271
// floating-point operations.
264-
ss.newLine() << ss.float2Decl("retVal") << ";";
265-
ss.newLine() << "retVal.y = floor(dep / " << float(width - 1) << ");"; // floor( dep / (width-1) ))
266-
ss.newLine() << "retVal.x = dep - retVal.y * " << float(width - 1) << ";"; // dep - retVal.y * (width-1)
267-
268-
ss.newLine() << "retVal.x = (retVal.x + 0.5) / " << float(width) << ";"; // (retVal.x + 0.5) / width;
269-
ss.newLine() << "retVal.y = (retVal.y + 0.5) / " << float(height) << ";"; // (retVal.x + 0.5) / height;
270272
}
271273
else
272274
{
273275
// Need clamp() to protect against f outside [0,1] causing a bogus x value.
274276
// clamp( f, 0., 1.) * (dim - 1)
275277
ss.newLine() << "float dep = clamp(f, 0.0, 1.0) * " << float(length - 1) << ";";
278+
}
279+
280+
ss.newLine() << ss.float2Decl("retVal") << ";";
276281

277-
ss.newLine() << ss.float2Decl("retVal") << ";";
278-
// float(int( dep / (width-1) ))
279-
ss.newLine() << "retVal.y = float(int(dep / " << float(width - 1) << "));";
280-
// dep - retVal.y * (width-1)
281-
ss.newLine() << "retVal.x = dep - retVal.y * " << float(width - 1) << ";";
282+
if (height > 1)
283+
{
284+
ss.newLine() << "retVal.y = floor(dep / " << float(width - 1) << ");"; // floor( dep / (width-1) ))
285+
ss.newLine() << "retVal.x = dep - retVal.y * " << float(width - 1) << ";"; // dep - retVal.y * (width-1)
282286

283-
// (retVal.x + 0.5) / width;
284-
ss.newLine() << "retVal.x = (retVal.x + 0.5) / " << float(width) << ";";
285-
// (retVal.x + 0.5) / height;
286-
ss.newLine() << "retVal.y = (retVal.y + 0.5) / " << float(height) << ";";
287+
ss.newLine() << "retVal.x = (retVal.x + 0.5) / " << float(width) << ";"; // (retVal.x + 0.5) / width;
288+
ss.newLine() << "retVal.y = (retVal.y + 0.5) / " << float(height) << ";"; // (retVal.x + 0.5) / height;
289+
}
290+
else
291+
{
292+
ss.newLine() << "retVal.x = (dep + 0.5) / " << float(width) << ";"; // (dep + 0.5) / width;
293+
ss.newLine() << "retVal.y = 0.5;";
287294
}
288295

289296
ss.newLine() << "return retVal;";
@@ -324,9 +331,7 @@ void GetLut1DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator,
324331
ss.newLine() << "";
325332
}
326333

327-
if (height > 1 || lutData->isInputHalfDomain()
328-
|| shaderCreator->getLanguage() == GPU_LANGUAGE_GLSL_ES_1_0
329-
|| shaderCreator->getLanguage() == GPU_LANGUAGE_GLSL_ES_3_0)
334+
if (dimensions == GpuShaderDesc::TEXTURE_2D)
330335
{
331336
const std::string str = name + "_computePos(" + shaderCreator->getPixelName();
332337

src/apps/pyociodisplay/pyociodisplay.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ def _allocate_ocio_tex(self):
806806
tex = GL.glGenTextures(1)
807807
GL.glActiveTexture(GL.GL_TEXTURE0 + tex_index)
808808

809-
if tex_info.height > 1:
809+
if tex_info.dimensions == self._ocio_shader_desc.TEXTURE_2D:
810810
tex_type = GL.GL_TEXTURE_2D
811811
GL.glBindTexture(tex_type, tex)
812812
self._set_ocio_tex_params(tex_type, tex_info.interpolation)

src/bindings/python/PyGpuShaderCreator.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ void bindPyGpuShaderCreator(py::module & m)
3030
clsGpuShaderCreator, "TextureType",
3131
DOC(GpuShaderCreator, TextureType));
3232

33+
auto enumTextureDimensions =
34+
py::enum_<GpuShaderCreator::TextureDimensions>(
35+
clsGpuShaderCreator, "TextureDimensions",
36+
DOC(GpuShaderCreator, TextureDimensions));
37+
3338
auto clsDynamicPropertyIterator =
3439
py::class_<DynamicPropertyIterator>(
3540
clsGpuShaderCreator, "DynamicPropertyIterator");
@@ -67,8 +72,12 @@ void bindPyGpuShaderCreator(py::module & m)
6772
DOC(GpuShaderCreator, getTextureMaxWidth))
6873
.def("setTextureMaxWidth", &GpuShaderCreator::setTextureMaxWidth, "maxWidth"_a,
6974
DOC(GpuShaderCreator, setTextureMaxWidth))
70-
.def("getNextResourceIndex", &GpuShaderCreator::getNextResourceIndex,
71-
DOC(GpuShaderCreator, getNextResourceIndex))
75+
.def("setAllowTexture1D", &GpuShaderCreator::setAllowTexture1D, "allowed"_a,
76+
DOC(GpuShaderCreator, setAllowTexture1D))
77+
.def("getAllowTexture1D", &GpuShaderCreator::getAllowTexture1D,
78+
DOC(GpuShaderCreator, getAllowTexture1D))
79+
.def("getNextResourceIndex", &GpuShaderCreator::getNextResourceIndex,
80+
DOC(GpuShaderCreator, getNextResourceIndex))
7281

7382
// Dynamic properties.
7483
.def("hasDynamicProperty", &GpuShaderCreator::hasDynamicProperty, "type"_a,
@@ -111,6 +120,11 @@ void bindPyGpuShaderCreator(py::module & m)
111120
.value("TEXTURE_RGB_CHANNEL", GpuShaderCreator::TEXTURE_RGB_CHANNEL)
112121
.export_values();
113122

123+
enumTextureDimensions
124+
.value("TEXTURE_1D", GpuShaderCreator::TEXTURE_1D)
125+
.value("TEXTURE_2D", GpuShaderCreator::TEXTURE_2D)
126+
.export_values();
127+
114128
clsDynamicPropertyIterator
115129
.def("__len__", [](DynamicPropertyIterator & it)
116130
{

0 commit comments

Comments
 (0)