Skip to content

Commit

Permalink
Exposed option to allow/disallow 1D texture GPU resources for 1D LUTs. (
Browse files Browse the repository at this point in the history
#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]>
  • Loading branch information
3 people authored Aug 26, 2023
1 parent 9221ffa commit 929d536
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 67 deletions.
20 changes: 17 additions & 3 deletions include/OpenColorIO/OpenColorIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -3156,6 +3156,10 @@ class OCIOEXPORT GpuShaderCreator
virtual void setTextureMaxWidth(unsigned maxWidth) = 0;
virtual unsigned getTextureMaxWidth() const noexcept = 0;

/// Allow 1D GPU resource type, otherwise always using 2D resources for 1D LUTs.
virtual void setAllowTexture1D(bool allowed) = 0;
virtual bool getAllowTexture1D() const = 0;

/**
* To avoid global texture sampler and uniform name clashes always append an increasing index
* to the resource name.
Expand Down Expand Up @@ -3213,16 +3217,25 @@ class OCIOEXPORT GpuShaderCreator
};

/**
* Add a 2D texture (1D texture if height equals 1).
*
* \note
* Dimension enum used to differentiate between 1D and 2D object/resource types.
*/
enum TextureDimensions : uint8_t {
TEXTURE_1D = 1,
TEXTURE_2D = 2,
};

/**
* Add a 1D or 2D texture
*
* \note
* The 'values' parameter contains the LUT data which must be used as-is as the dimensions and
* origin are hard-coded in the fragment shader program. So, it means one GPU texture per entry.
**/
virtual void addTexture(const char * textureName,
const char * samplerName,
unsigned width, unsigned height,
TextureType channel,
TextureDimensions dimensions,
Interpolation interpolation,
const float * values) = 0;

Expand Down Expand Up @@ -3474,6 +3487,7 @@ class OCIOEXPORT GpuShaderDesc : public GpuShaderCreator
unsigned & width,
unsigned & height,
TextureType & channel,
TextureDimensions & dimensions,
Interpolation & interpolation) const = 0;
virtual void getTextureValues(unsigned index, const float *& values) const = 0;

Expand Down
52 changes: 41 additions & 11 deletions src/OpenColorIO/GpuShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class PrivateImpl
const char * samplerName,
unsigned w, unsigned h, unsigned d,
GpuShaderDesc::TextureType channel,
unsigned dimensions,
Interpolation interpolation,
const float * v)
: m_textureName(textureName)
Expand All @@ -57,6 +58,7 @@ class PrivateImpl
, m_height(h)
, m_depth(d)
, m_type(channel)
, m_dimensions(dimensions)
, m_interp(interpolation)
{
if (!textureName || !*textureName)
Expand Down Expand Up @@ -90,6 +92,7 @@ class PrivateImpl
unsigned m_height;
unsigned m_depth;
GpuShaderDesc::TextureType m_type;
unsigned m_dimensions;
Interpolation m_interp;

std::vector<float> m_values;
Expand Down Expand Up @@ -158,21 +161,25 @@ class PrivateImpl
typedef std::vector<Uniform> Uniforms;

public:
PrivateImpl() : m_max1DLUTWidth(4 * 1024) {}
PrivateImpl() : m_max1DLUTWidth(4 * 1024), m_allowTexture1D(true) {}
PrivateImpl(const PrivateImpl & rhs) = delete;
PrivateImpl& operator= (const PrivateImpl & rhs) = delete;

virtual ~PrivateImpl() {}

inline unsigned get3dLutMaxDimension() const { return Lut3DOpData::maxSupportedLength; }
inline unsigned get3dLutMaxLength() const { return Lut3DOpData::maxSupportedLength; }

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

inline bool getAllowTexture1D() const { return m_allowTexture1D; }
inline void setAllowTexture1D(bool allowed) { m_allowTexture1D = allowed; }

void addTexture(const char * textureName,
const char * samplerName,
unsigned width, unsigned height,
GpuShaderDesc::TextureType channel,
GpuShaderDesc::TextureDimensions dimensions,
Interpolation interpolation,
const float * values)
{
Expand All @@ -184,7 +191,8 @@ class PrivateImpl
throw Exception(ss.str().c_str());
}

Texture t(textureName, samplerName, width, height, 1, channel, interpolation, values);
unsigned numDimensions = static_cast<unsigned>(dimensions);
Texture t(textureName, samplerName, width, height, 1, channel, numDimensions, interpolation, values);
m_textures.push_back(t);
}

Expand All @@ -193,6 +201,7 @@ class PrivateImpl
const char *& samplerName,
unsigned & width, unsigned & height,
GpuShaderDesc::TextureType & channel,
GpuShaderDesc::TextureDimensions& dimensions,
Interpolation & interpolation) const
{
if(index >= m_textures.size())
Expand All @@ -209,6 +218,14 @@ class PrivateImpl
width = t.m_width;
height = t.m_height;
channel = t.m_type;
if (t.m_dimensions > 2)
{
std::stringstream ss;
ss << "1D LUT cannot have more than two dimensions: "
<< t.m_dimensions << " > 2";
throw Exception(ss.str().c_str());
}
dimensions = static_cast<GpuShaderDesc::TextureDimensions>(t.m_dimensions);
interpolation = t.m_interp;
}

Expand All @@ -228,20 +245,20 @@ class PrivateImpl

void add3DTexture(const char * textureName,
const char * samplerName,
unsigned dimension,
unsigned edgelen,
Interpolation interpolation,
const float * values)
{
if(dimension > get3dLutMaxDimension())
if(edgelen > get3dLutMaxLength())
{
std::stringstream ss;
ss << "3D LUT dimension exceeds the maximum: "
<< dimension << " > " << get3dLutMaxDimension();
ss << "3D LUT edge length exceeds the maximum: "
<< edgelen << " > " << get3dLutMaxLength();
throw Exception(ss.str().c_str());
}

Texture t(textureName, samplerName, dimension, dimension, dimension,
GpuShaderDesc::TEXTURE_RGB_CHANNEL,
Texture t(textureName, samplerName, edgelen, edgelen, edgelen,
GpuShaderDesc::TEXTURE_RGB_CHANNEL, 3,
interpolation, values);
m_textures3D.push_back(t);
}
Expand Down Expand Up @@ -374,6 +391,7 @@ class PrivateImpl
return false;
}
unsigned m_max1DLUTWidth;
bool m_allowTexture1D;
};

} // namespace GPUShaderImpl
Expand Down Expand Up @@ -452,6 +470,16 @@ void GenericGpuShaderDesc::setTextureMaxWidth(unsigned maxWidth)
getImplGeneric()->set1dLutMaxWidth(maxWidth);
}

bool GenericGpuShaderDesc::getAllowTexture1D() const noexcept
{
return getImplGeneric()->getAllowTexture1D();
}

void GenericGpuShaderDesc::setAllowTexture1D(bool allowed)
{
getImplGeneric()->setAllowTexture1D(allowed);
}

unsigned GenericGpuShaderDesc::getNumTextures() const noexcept
{
return unsigned(getImplGeneric()->m_textures.size());
Expand All @@ -461,20 +489,22 @@ void GenericGpuShaderDesc::addTexture(const char * textureName,
const char * samplerName,
unsigned width, unsigned height,
TextureType channel,
TextureDimensions dimensions,
Interpolation interpolation,
const float * values)
{
getImplGeneric()->addTexture(textureName, samplerName, width, height, channel, interpolation, values);
getImplGeneric()->addTexture(textureName, samplerName, width, height, channel, dimensions, interpolation, values);
}

void GenericGpuShaderDesc::getTexture(unsigned index,
const char *& textureName,
const char *& samplerName,
unsigned & width, unsigned & height,
TextureType & channel,
TextureDimensions & dimensions,
Interpolation & interpolation) const
{
getImplGeneric()->getTexture(index, textureName, samplerName, width, height, channel, interpolation);
getImplGeneric()->getTexture(index, textureName, samplerName, width, height, channel, dimensions, interpolation);
}

void GenericGpuShaderDesc::getTextureValues(unsigned index, const float *& values) const
Expand Down
7 changes: 6 additions & 1 deletion src/OpenColorIO/GpuShader.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class GenericGpuShaderDesc : public GpuShaderDesc
unsigned getTextureMaxWidth() const noexcept override;
void setTextureMaxWidth(unsigned maxWidth) override;

bool getAllowTexture1D() const noexcept override;
void setAllowTexture1D(bool allowed) override;

// Accessors to the uniforms
//
unsigned getNumUniforms() const noexcept override;
Expand All @@ -47,16 +50,18 @@ class GenericGpuShaderDesc : public GpuShaderDesc
//
unsigned getNumTextures() const noexcept override;
void addTexture(const char * textureName,
const char * samplerNName,
const char * samplerName,
unsigned width, unsigned height,
TextureType channel,
TextureDimensions dimensions,
Interpolation interpolation,
const float * values) override;
void getTexture(unsigned index,
const char *& textureName,
const char *& samplerName,
unsigned & width, unsigned & height,
TextureType & channel,
TextureDimensions & dimensions,
Interpolation & interpolation) const override;
void getTextureValues(unsigned index, const float *& values) const override;

Expand Down
47 changes: 26 additions & 21 deletions src/OpenColorIO/ops/lut1d/Lut1DOpGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,21 +189,29 @@ void GetLut1DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator,
std::string name(resName.str());
StringUtils::ReplaceInPlace(name, "__", "_");

GpuShaderDesc::TextureDimensions dimensions = GpuShaderDesc::TEXTURE_1D;
if (height > 1 || lutData->isInputHalfDomain()
|| shaderCreator->getLanguage() == GPU_LANGUAGE_GLSL_ES_1_0
|| shaderCreator->getLanguage() == GPU_LANGUAGE_GLSL_ES_3_0
|| !shaderCreator->getAllowTexture1D())
{
dimensions = GpuShaderDesc::TEXTURE_2D;
}

// (Using CacheID here to potentially allow reuse of existing textures.)
shaderCreator->addTexture(name.c_str(),
GpuShaderText::getSamplerName(name).c_str(),
width,
height,
singleChannel ? GpuShaderCreator::TEXTURE_RED_CHANNEL
: GpuShaderCreator::TEXTURE_RGB_CHANNEL,
dimensions,
lutData->getConcreteInterpolation(),
&values[0]);

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

if (height > 1 || lutData->isInputHalfDomain()
|| shaderCreator->getLanguage() == GPU_LANGUAGE_GLSL_ES_1_0
|| shaderCreator->getLanguage() == GPU_LANGUAGE_GLSL_ES_3_0)
if (dimensions == GpuShaderDesc::TEXTURE_2D)
{
// In case the 1D LUT length exceeds the 1D texture maximum length,
// or the language doesn't support 1D textures,
Expand Down Expand Up @@ -261,29 +269,28 @@ void GetLut1DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator,
// At this point 'dep' contains the raw half
// Note: Raw halfs for NaN floats cannot be computed using
// floating-point operations.
ss.newLine() << ss.float2Decl("retVal") << ";";
ss.newLine() << "retVal.y = floor(dep / " << float(width - 1) << ");"; // floor( dep / (width-1) ))
ss.newLine() << "retVal.x = dep - retVal.y * " << float(width - 1) << ";"; // dep - retVal.y * (width-1)

ss.newLine() << "retVal.x = (retVal.x + 0.5) / " << float(width) << ";"; // (retVal.x + 0.5) / width;
ss.newLine() << "retVal.y = (retVal.y + 0.5) / " << float(height) << ";"; // (retVal.x + 0.5) / height;
}
else
{
// Need clamp() to protect against f outside [0,1] causing a bogus x value.
// clamp( f, 0., 1.) * (dim - 1)
ss.newLine() << "float dep = clamp(f, 0.0, 1.0) * " << float(length - 1) << ";";
}

ss.newLine() << ss.float2Decl("retVal") << ";";

ss.newLine() << ss.float2Decl("retVal") << ";";
// float(int( dep / (width-1) ))
ss.newLine() << "retVal.y = float(int(dep / " << float(width - 1) << "));";
// dep - retVal.y * (width-1)
ss.newLine() << "retVal.x = dep - retVal.y * " << float(width - 1) << ";";
if (height > 1)
{
ss.newLine() << "retVal.y = floor(dep / " << float(width - 1) << ");"; // floor( dep / (width-1) ))
ss.newLine() << "retVal.x = dep - retVal.y * " << float(width - 1) << ";"; // dep - retVal.y * (width-1)

// (retVal.x + 0.5) / width;
ss.newLine() << "retVal.x = (retVal.x + 0.5) / " << float(width) << ";";
// (retVal.x + 0.5) / height;
ss.newLine() << "retVal.y = (retVal.y + 0.5) / " << float(height) << ";";
ss.newLine() << "retVal.x = (retVal.x + 0.5) / " << float(width) << ";"; // (retVal.x + 0.5) / width;
ss.newLine() << "retVal.y = (retVal.y + 0.5) / " << float(height) << ";"; // (retVal.x + 0.5) / height;
}
else
{
ss.newLine() << "retVal.x = (dep + 0.5) / " << float(width) << ";"; // (dep + 0.5) / width;
ss.newLine() << "retVal.y = 0.5;";
}

ss.newLine() << "return retVal;";
Expand Down Expand Up @@ -324,9 +331,7 @@ void GetLut1DGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator,
ss.newLine() << "";
}

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

Expand Down
2 changes: 1 addition & 1 deletion src/apps/pyociodisplay/pyociodisplay.py
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ def _allocate_ocio_tex(self):
tex = GL.glGenTextures(1)
GL.glActiveTexture(GL.GL_TEXTURE0 + tex_index)

if tex_info.height > 1:
if tex_info.dimensions == self._ocio_shader_desc.TEXTURE_2D:
tex_type = GL.GL_TEXTURE_2D
GL.glBindTexture(tex_type, tex)
self._set_ocio_tex_params(tex_type, tex_info.interpolation)
Expand Down
18 changes: 16 additions & 2 deletions src/bindings/python/PyGpuShaderCreator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ void bindPyGpuShaderCreator(py::module & m)
clsGpuShaderCreator, "TextureType",
DOC(GpuShaderCreator, TextureType));

auto enumTextureDimensions =
py::enum_<GpuShaderCreator::TextureDimensions>(
clsGpuShaderCreator, "TextureDimensions",
DOC(GpuShaderCreator, TextureDimensions));

auto clsDynamicPropertyIterator =
py::class_<DynamicPropertyIterator>(
clsGpuShaderCreator, "DynamicPropertyIterator");
Expand Down Expand Up @@ -67,8 +72,12 @@ void bindPyGpuShaderCreator(py::module & m)
DOC(GpuShaderCreator, getTextureMaxWidth))
.def("setTextureMaxWidth", &GpuShaderCreator::setTextureMaxWidth, "maxWidth"_a,
DOC(GpuShaderCreator, setTextureMaxWidth))
.def("getNextResourceIndex", &GpuShaderCreator::getNextResourceIndex,
DOC(GpuShaderCreator, getNextResourceIndex))
.def("setAllowTexture1D", &GpuShaderCreator::setAllowTexture1D, "allowed"_a,
DOC(GpuShaderCreator, setAllowTexture1D))
.def("getAllowTexture1D", &GpuShaderCreator::getAllowTexture1D,
DOC(GpuShaderCreator, getAllowTexture1D))
.def("getNextResourceIndex", &GpuShaderCreator::getNextResourceIndex,
DOC(GpuShaderCreator, getNextResourceIndex))

// Dynamic properties.
.def("hasDynamicProperty", &GpuShaderCreator::hasDynamicProperty, "type"_a,
Expand Down Expand Up @@ -111,6 +120,11 @@ void bindPyGpuShaderCreator(py::module & m)
.value("TEXTURE_RGB_CHANNEL", GpuShaderCreator::TEXTURE_RGB_CHANNEL)
.export_values();

enumTextureDimensions
.value("TEXTURE_1D", GpuShaderCreator::TEXTURE_1D)
.value("TEXTURE_2D", GpuShaderCreator::TEXTURE_2D)
.export_values();

clsDynamicPropertyIterator
.def("__len__", [](DynamicPropertyIterator & it)
{
Expand Down
Loading

0 comments on commit 929d536

Please sign in to comment.