diff --git a/CMakeLists.txt b/CMakeLists.txt index 54dff0df0e..a1b28d036f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ option(MATERIALX_BUILD_GEN_MSL "Build the MSL shader generator back-end." ON) option(MATERIALX_BUILD_RENDER "Build the MaterialX Render modules." ON) option(MATERIALX_BUILD_OIIO "Build OpenImageIO support for MaterialXRender." OFF) option(MATERIALX_BUILD_TESTS "Build unit tests." OFF) +option(MATERIALX_BUILD_OCIO "Build OpenColorIO support for shader generators." OFF) option(MATERIALX_BUILD_BENCHMARK_TESTS "Build benchmark tests." OFF) option(MATERIALX_BUILD_SHARED_LIBS "Build MaterialX libraries as shared rather than static." OFF) @@ -135,6 +136,7 @@ mark_as_advanced(MATERIALX_BUILD_GEN_MDL) mark_as_advanced(MATERIALX_BUILD_GEN_MSL) mark_as_advanced(MATERIALX_BUILD_RENDER) mark_as_advanced(MATERIALX_BUILD_OIIO) +mark_as_advanced(MATERIALX_BUILD_OCIO) mark_as_advanced(MATERIALX_BUILD_BENCHMARK_TESTS) mark_as_advanced(MATERIALX_BUILD_SHARED_LIBS) mark_as_advanced(MATERIALX_BUILD_MONOLITHIC) diff --git a/libraries/stdlib/genosl/lib/vector4_extra_ops.osl b/libraries/stdlib/genosl/lib/vector4_extra_ops.osl new file mode 100644 index 0000000000..73aa32d6fc --- /dev/null +++ b/libraries/stdlib/genosl/lib/vector4_extra_ops.osl @@ -0,0 +1,45 @@ +// Adds some syntactic sugar allowing mixing vector4 and color4 as +// arguments of some binary operators used by OCIO transform code. + +vector4 __operator__mul__(matrix m, vector4 v) +{ + return vector4(v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2] + v.w * m[0][3], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2] + v.w * m[1][3], + v.x * m[2][0] + v.y * m[2][1] + v.z * m[2][2] + v.w * m[2][3], + v.x * m[3][0] + v.y * m[3][1] + v.z * m[3][2] + v.w * m[3][3]); +} + +vector4 __operator__mul__(color4 c, vector4 v) +{ + return vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a) * v; +} + +vector4 __operator__mul__(vector4 v, color4 c) +{ + return v * vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a); +} + +vector4 __operator__sub__(color4 c, vector4 v) +{ + return vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a) - v; +} + +vector4 __operator__add__(vector4 v, color4 c) +{ + return v + vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a); +} + +vector4 __operator__add__(color4 c, vector4 v) +{ + return vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a) + v; +} + +vector4 pow(color4 c, vector4 v) +{ + return pow(vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a), v); +} + +vector4 max(vector4 v, color4 c) +{ + return max(v, vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a)); +} diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp index c648441c7e..c176d3dc5e 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp @@ -776,8 +776,12 @@ ShaderNodeImplPtr GlslShaderGenerator::getImplementation(const NodeDef& nodedef, } else if (implElement->isA()) { - // Try creating a new in the factory. - impl = _implFactory.create(name); + if (getColorManagementSystem() && getColorManagementSystem()->hasImplementation(name)) { + impl = getColorManagementSystem()->createImplementation(name); + } else { + // Try creating a new in the factory. + impl = _implFactory.create(name); + } if (!impl) { // Fall back to source code implementation. diff --git a/source/MaterialXGenMdl/MdlShaderGenerator.cpp b/source/MaterialXGenMdl/MdlShaderGenerator.cpp index 76cd7587fd..ec0431e15e 100644 --- a/source/MaterialXGenMdl/MdlShaderGenerator.cpp +++ b/source/MaterialXGenMdl/MdlShaderGenerator.cpp @@ -307,8 +307,12 @@ ShaderNodeImplPtr MdlShaderGenerator::getImplementation(const NodeDef& nodedef, } else if (implElement->isA()) { - // Try creating a new in the factory. - impl = _implFactory.create(name); + if (getColorManagementSystem() && getColorManagementSystem()->hasImplementation(name)) { + impl = getColorManagementSystem()->createImplementation(name); + } else { + // Try creating a new in the factory. + impl = _implFactory.create(name); + } if (!impl) { // Fall back to source code implementation. diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp index 8db763d7e1..6e269e0e05 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.cpp +++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp @@ -1269,8 +1269,12 @@ ShaderNodeImplPtr MslShaderGenerator::getImplementation(const NodeDef& nodedef, } else if (implElement->isA()) { - // Try creating a new in the factory. - impl = _implFactory.create(name); + if (getColorManagementSystem() && getColorManagementSystem()->hasImplementation(name)) { + impl = getColorManagementSystem()->createImplementation(name); + } else { + // Try creating a new in the factory. + impl = _implFactory.create(name); + } if (!impl) { // Fall back to source code implementation. diff --git a/source/MaterialXGenShader/CMakeLists.txt b/source/MaterialXGenShader/CMakeLists.txt index ebdf814234..b2f48e7e3e 100644 --- a/source/MaterialXGenShader/CMakeLists.txt +++ b/source/MaterialXGenShader/CMakeLists.txt @@ -11,3 +11,9 @@ mx_add_library(MaterialXGenShader MaterialXCore EXPORT_DEFINE MATERIALX_GENSHADER_EXPORTS) + +if(MATERIALX_BUILD_OCIO) + find_package(OpenColorIO REQUIRED) + target_link_libraries(${TARGET_NAME} PUBLIC OpenColorIO::OpenColorIO) + target_compile_definitions(${TARGET_NAME} PUBLIC MATERIALX_BUILD_OCIO) +endif() \ No newline at end of file diff --git a/source/MaterialXGenShader/ColorManagementSystem.h b/source/MaterialXGenShader/ColorManagementSystem.h index 5eb37b0a97..c6661d0e06 100644 --- a/source/MaterialXGenShader/ColorManagementSystem.h +++ b/source/MaterialXGenShader/ColorManagementSystem.h @@ -64,6 +64,12 @@ class MX_GENSHADER_API ColorManagementSystem ShaderNodePtr createNode(const ShaderGraph* parent, const ColorSpaceTransform& transform, const string& name, GenContext& context) const; + /// Returns true if the CMS can create a shader node implementation for a locally managed CMS transform + virtual bool hasImplementation(const string& /*implName*/) const { return false; } + + /// Create an CMS node implementation for a locally managed transform + virtual ShaderNodeImplPtr createImplementation(const string& /*implName*/) const { return {}; } + protected: /// Protected constructor ColorManagementSystem(); diff --git a/source/MaterialXGenShader/Nodes/OpenColorIONode.cpp b/source/MaterialXGenShader/Nodes/OpenColorIONode.cpp new file mode 100644 index 0000000000..3610e43d52 --- /dev/null +++ b/source/MaterialXGenShader/Nodes/OpenColorIONode.cpp @@ -0,0 +1,209 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifdef MATERIALX_BUILD_OCIO + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +MATERIALX_NAMESPACE_BEGIN + +namespace +{ +// Internal OCIO strings: +constexpr const char OCIO_COLOR3[] = "color3"; +constexpr const char COLOR4_SUFFIX[] = "_color4_temp"; + +// Lengths where needed: +constexpr auto OCIO_COLOR3_LEN = sizeof(OCIO_COLOR3) / sizeof(OCIO_COLOR3[0]); + +} // namespace + +ShaderNodeImplPtr OpenColorIONode::create() +{ + return std::make_shared(); +} + +void OpenColorIONode::initialize(const InterfaceElement& element, GenContext& context) +{ + ShaderNodeImpl::initialize(element, context); + + // Single function shared between color3 and color4 nodes, use a custom hash with only the function name. + _hash = std::hash{}(getFunctionName()); +} + +void OpenColorIONode::emitFunctionDefinition( + const ShaderNode& /*node*/, + GenContext& context, + ShaderStage& stage) const +{ + if (stage.getName() == Stage::PIXEL) + { + auto ocioManager = std::dynamic_pointer_cast(context.getShaderGenerator().getColorManagementSystem()); + + auto gpuProcessor = ocioManager->getGpuProcessor(getName()); + OCIO::GpuShaderDescRcPtr shaderDesc = OCIO::GpuShaderDesc::CreateShaderDesc(); + + // TODO: Extend to essl and MDL and possibly SLang. + bool isOSL = false; + if (context.getShaderGenerator().getTarget() == "genglsl") + { + shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_4_0); + } + else if (context.getShaderGenerator().getTarget() == "genmsl") + { + shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_MSL_2_0); + } + else if (context.getShaderGenerator().getTarget() == "genosl") + { + shaderDesc->setLanguage(OCIO::LANGUAGE_OSL_1); + isOSL = true; + } + + auto functionName = getFunctionName(); + + shaderDesc->setFunctionName(functionName.c_str()); + + gpuProcessor->extractGpuShaderInfo(shaderDesc); + + string shaderText = shaderDesc->getShaderText(); + + // For OSL, we need to extract the function from the shader OCIO creates. + if (isOSL) + { + const ShaderGenerator& shadergen = context.getShaderGenerator(); + shadergen.emitLibraryInclude("stdlib/genosl/lib/vector4_extra_ops.osl", context, stage); + shadergen.emitLineBreak(stage); + auto startpos = shaderText.find(string{"color4 "} + shaderDesc->getFunctionName()); + if (startpos != string::npos) + { + auto endpos = shaderText.find(string{"outColor = "} + shaderDesc->getFunctionName(), startpos); + if (endpos != string::npos) + { + shaderText = shaderText.substr(startpos, endpos - startpos); + } + } + } + + stage.addString(shaderText); + stage.endLine(false); + } +} + +void OpenColorIONode::emitFunctionCall( + const ShaderNode& node, + GenContext& context, + ShaderStage& stage) const +{ + if (stage.getName() == Stage::PIXEL) + { + auto functionName = getFunctionName(); + + // TODO: Adjust syntax for other languages. + // TODO: Handle LUT samplers. + const bool isColor3 = getName().back() == '3'; + + const auto& shadergen = context.getShaderGenerator(); + shadergen.emitLineBegin(stage); + + const auto* output = node.getOutput(); + const auto* colorInput = node.getInput(0); + + if (context.getShaderGenerator().getTarget() == "genosl") + { + // For OSL, since swizzling the output of a function is not allowed, we need: + // Function call for color4: color4 res = func(in); + // Function call for color3: + // color4 res_color4 = func(color4(in, 1.0)); + // color res = res_color4.rgb; + if (isColor3) + { + shadergen.emitString("color4 " + output->getVariable() + COLOR4_SUFFIX + " = ", stage); + shadergen.emitString(functionName + "(color4(", stage); + shadergen.emitInput(colorInput, context, stage); + shadergen.emitString(", 1.0))", stage); + shadergen.emitLineEnd(stage); + shadergen.emitLineBegin(stage); + shadergen.emitOutput(output, true, false, context, stage); + shadergen.emitString(" = " + output->getVariable() + COLOR4_SUFFIX + ".rgb", stage); + shadergen.emitLineEnd(stage); + } + else + { + shadergen.emitOutput(output, true, false, context, stage); + shadergen.emitString(" = ", stage); + shadergen.emitString(functionName + "(", stage); + shadergen.emitInput(colorInput, context, stage); + shadergen.emitString(")", stage); + shadergen.emitLineEnd(stage); + } + } + else + { + // The OCIO function uses a vec4 parameter, so: + // Function call for color4: vec4 res = func(in); + // Function call for color3: vec3 res = func(vec4(in, 1.0)).rgb; + shadergen.emitOutput(output, true, false, context, stage); + shadergen.emitString(" = ", stage); + + shadergen.emitString(functionName + "(", stage); + if (isColor3) + { + if (context.getShaderGenerator().getTarget() == "genglsl") + { + shadergen.emitString("vec4(", stage); + } + else if (context.getShaderGenerator().getTarget() == "genmsl") + { + shadergen.emitString("float4(", stage); + } + } + shadergen.emitInput(colorInput, context, stage); + if (isColor3) + { + shadergen.emitString(", 1.0)", stage); + } + + shadergen.emitString(")", stage); + + if (isColor3) + { + shadergen.emitString(".rgb", stage); + } + shadergen.emitLineEnd(stage); + } + } +} + +string OpenColorIONode::getFunctionName() const +{ + auto name = getName(); + + // Strip _color3 and _color4 suffixes and impl prefix: + size_t startPos = OpenColorIOManagementSystem::IMPL_PREFIX.size(); + size_t length = name.size() - OCIO_COLOR3_LEN - 1 - startPos; + + return name.substr(startPos, length); +} + +MATERIALX_NAMESPACE_END + +#endif diff --git a/source/MaterialXGenShader/Nodes/OpenColorIONode.h b/source/MaterialXGenShader/Nodes/OpenColorIONode.h new file mode 100644 index 0000000000..92dae7552d --- /dev/null +++ b/source/MaterialXGenShader/Nodes/OpenColorIONode.h @@ -0,0 +1,44 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_OCIO_NODE_H +#define MATERIALX_OCIO_NODE_H + +#ifdef MATERIALX_BUILD_OCIO +/// @file +/// OCIO node implementation + +#include +#include +#include +#include +#include +#include + +MATERIALX_NAMESPACE_BEGIN + +/// OCIO node implementation. Takes an OCIO GpuProcessor and +/// uses it to inject shadergen code. +class OpenColorIONode : public ShaderNodeImpl +{ + public: + static ShaderNodeImplPtr create(); + + void initialize(const InterfaceElement& element, GenContext& context) override; + + void emitFunctionDefinition(const ShaderNode& node, GenContext& context, ShaderStage& stage) + const override; + + void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) + const override; + + private: + string getFunctionName() const; +}; + +MATERIALX_NAMESPACE_END + +#endif +#endif diff --git a/source/MaterialXGenShader/OpenColorIOManagementSystem.cpp b/source/MaterialXGenShader/OpenColorIOManagementSystem.cpp new file mode 100644 index 0000000000..d2852a6e91 --- /dev/null +++ b/source/MaterialXGenShader/OpenColorIOManagementSystem.cpp @@ -0,0 +1,198 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifdef MATERIALX_BUILD_OCIO + +#include "MaterialXCore/Library.h" + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +MATERIALX_NAMESPACE_BEGIN + +const string OpenColorIOManagementSystem::IMPL_PREFIX = "IMPL_MXOCIO_"; +const string OpenColorIOManagementSystem::ND_PREFIX = "ND_MXOCIO_"; + +namespace +{ + +const string CMS_NAME = "OpenColorIO"; + +// Remap from legacy color space names to their ACES 1.3 equivalents. +const std::map COLOR_SPACE_REMAP = { + { "gamma18", "Gamma 1.8 Rec.709 - Texture" }, + { "gamma22", "Gamma 2.2 Rec.709 - Texture" }, + { "gamma24", "Gamma 2.4 Rec.709 - Texture" }, + // TODO: Add support for adobergb and lin_adobergb +}; + +} // anonymous namespace + +// +// OpenColorIOManagementSystem methods +// + +OpenColorIOManagementSystemPtr OpenColorIOManagementSystem::create(const OCIO::ConstConfigRcPtr& config, const string& target) +{ + if (target != "genglsl" && target != "genmsl" && target != "genosl") + { + throw std::runtime_error("OCIO does not support this target"); + } + + return OpenColorIOManagementSystemPtr(new OpenColorIOManagementSystem(config, target)); +} + +OpenColorIOManagementSystem::OpenColorIOManagementSystem(const OCIO::ConstConfigRcPtr& config, const string& target) : + DefaultColorManagementSystem(target), + _target(target), + _config(std::move(config)) +{ +} + +const string& OpenColorIOManagementSystem::getName() const +{ + return CMS_NAME; +} + +const char* OpenColorIOManagementSystem::getSupportedColorSpaceName(const char* colorSpace) const +{ + if (_config->getColorSpace(colorSpace)) + { + return colorSpace; + } + + auto remap = COLOR_SPACE_REMAP.find(colorSpace); + if (remap != COLOR_SPACE_REMAP.end()) + { + return getSupportedColorSpaceName(remap->second.c_str()); + } + + auto cgConfig = OCIO::Config::CreateFromBuiltinConfig("ocio://studio-config-latest"); + try + { + // Throws on failure. Try at least two configs: + return OCIO::Config::IdentifyBuiltinColorSpace(_config, cgConfig, colorSpace); + } + catch (const std::exception& /*e*/) + { + return nullptr; + } +} + +NodeDefPtr OpenColorIOManagementSystem::getNodeDef(const ColorSpaceTransform& transform) const +{ + // See if the default color management system already handles this: + if (auto cmNodeDef = DefaultColorManagementSystem::getNodeDef(transform)) { + return cmNodeDef; + } + + OCIO::ConstProcessorRcPtr processor; + // Check if directly supported in the config: + const char* sourceColorSpace = getSupportedColorSpaceName(transform.sourceSpace.c_str()); + const char* targetColorSpace = getSupportedColorSpaceName(transform.targetSpace.c_str()); + if (!sourceColorSpace || !targetColorSpace) + { + return {}; + } + + try + { + processor = _config->getProcessor(sourceColorSpace, targetColorSpace); + } + catch (const std::exception& /*e*/) + { + return {}; + } + + if (!processor) + { + return {}; + } + + auto gpuProcessor = processor->getDefaultGPUProcessor(); + if (!gpuProcessor) + { + return {}; + } + + if (gpuProcessor->isNoOp()) + { + return _document->getNodeDef("ND_dot_" + transform.type.getName()); + } + + // Reject transforms requiring textures (1D and 3D LUTs) + OCIO::GpuShaderDescRcPtr shaderDesc = OCIO::GpuShaderDesc::CreateShaderDesc(); + gpuProcessor->extractGpuShaderInfo(shaderDesc); + if (shaderDesc->getNum3DTextures() || shaderDesc->getNumTextures()) + { + // TODO: Support LUTs + return {}; + } + + static const auto NODE_NAME = string{ "ocio_color_conversion" }; + const auto functionName = NODE_NAME + "_" + processor->getCacheID(); + const auto implName = IMPL_PREFIX + functionName + "_" + transform.type.getName(); + const auto nodeDefName = ND_PREFIX + functionName + "_" + transform.type.getName(); + auto nodeDef = _document->getNodeDef(nodeDefName); + if (!nodeDef) + { + nodeDef = _document->addNodeDef(nodeDefName, "", functionName); + nodeDef->setNodeGroup("colortransform"); + + nodeDef->addInput("in", transform.type.getName()); + nodeDef->addOutput("out", transform.type.getName()); + + auto implementation = _document->addImplementation(implName); + implementation->setTarget(_target); + implementation->setNodeDef(nodeDef); + } + + _implementations.emplace(implName, gpuProcessor); + + return nodeDef; +} + +bool OpenColorIOManagementSystem::hasImplementation(const string& implName) const +{ + if (DefaultColorManagementSystem::hasImplementation(implName)) { + return true; + } + return _implementations.count(implName); +} + +ShaderNodeImplPtr OpenColorIOManagementSystem::createImplementation(const string& implName) const +{ + if (auto impl = DefaultColorManagementSystem::createImplementation(implName)) { + return impl; + } + + if (_implementations.count(implName)) + { + return OpenColorIONode::create(); + } + return {}; +} + +OCIO::ConstGPUProcessorRcPtr OpenColorIOManagementSystem::getGpuProcessor(const string& implName) +{ + auto it = _implementations.find(implName); + + return it != _implementations.end() ? it->second : nullptr; +} + +MATERIALX_NAMESPACE_END +#endif diff --git a/source/MaterialXGenShader/OpenColorIOManagementSystem.h b/source/MaterialXGenShader/OpenColorIOManagementSystem.h new file mode 100644 index 0000000000..f81086ffbc --- /dev/null +++ b/source/MaterialXGenShader/OpenColorIOManagementSystem.h @@ -0,0 +1,81 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_OCIO_COLOR_MANAGEMENT_SYSTEM_H +#define MATERIALX_OCIO_COLOR_MANAGEMENT_SYSTEM_H + +#ifdef MATERIALX_BUILD_OCIO +/// @file +/// OCIO color management system implementation + +#include + +#include +#include +#include + +#include +#include +#include + +namespace OCIO = OCIO_NAMESPACE; + +MATERIALX_NAMESPACE_BEGIN + +/// A shared pointer to a OpenColorIOManagementSystem +using OpenColorIOManagementSystemPtr = std::shared_ptr; + +/// @class OpenColorIOManagementSystem +/// Class for a default color management system. +class MX_GENSHADER_API OpenColorIOManagementSystem : public DefaultColorManagementSystem +{ + public: + virtual ~OpenColorIOManagementSystem() { } + + /// Create a new OpenColorIOManagementSystem + static OpenColorIOManagementSystemPtr create(const OCIO::ConstConfigRcPtr& config, const string& target); + + /// Return the OpenColorIOManagementSystem name + const string& getName() const override; + + /// Can the CMS create a shader node implementation for one of its registered CMS transforms + bool hasImplementation(const string& implName) const override; + + /// Create an OCIO node + ShaderNodeImplPtr createImplementation(const string& implName) const override; + + /// Returns a cached GPU processor registered for an implementation + OCIO::ConstGPUProcessorRcPtr getGpuProcessor(const string& implName); + + /// Prefix common to all implementation names + static const string IMPL_PREFIX; + + /// Prefix common to all node definition names + static const string ND_PREFIX; + + /// Prefix common to all node graph names + static const string NG_PREFIX; + + protected: + /// Returns a nodedef for a given transform + NodeDefPtr getNodeDef(const ColorSpaceTransform& transform) const override; + + /// Looks for a valid color space name, either in the current config, or using built-in + /// color spaces to find an equivalent one. + const char* getSupportedColorSpaceName(const char* colorSpace) const; + + /// Protected constructor + OpenColorIOManagementSystem(const OCIO::ConstConfigRcPtr& config, const string& target); + + private: + string _target; + OCIO::ConstConfigRcPtr _config; + mutable std::map _implementations; +}; + +MATERIALX_NAMESPACE_END + +#endif +#endif diff --git a/source/MaterialXGenShader/ShaderGenerator.cpp b/source/MaterialXGenShader/ShaderGenerator.cpp index 6c23382f81..e50a423088 100644 --- a/source/MaterialXGenShader/ShaderGenerator.cpp +++ b/source/MaterialXGenShader/ShaderGenerator.cpp @@ -316,8 +316,12 @@ ShaderNodeImplPtr ShaderGenerator::getImplementation(const NodeDef& nodedef, Gen } else if (implElement->isA()) { - // Try creating a new in the factory. - impl = _implFactory.create(name); + if (getColorManagementSystem() && getColorManagementSystem()->hasImplementation(name)) { + impl = getColorManagementSystem()->createImplementation(name); + } else { + // Try creating a new in the factory. + impl = _implFactory.create(name); + } if (!impl) { // Fall back to source code implementation. diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp index 848348066c..436bf0b7ce 100644 --- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp +++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp @@ -16,6 +16,10 @@ #include #include +#ifdef MATERIALX_BUILD_OCIO +#include +#endif + #include namespace mx = MaterialX; @@ -324,8 +328,23 @@ void shaderGenPerformanceTest(mx::GenContext& context) context.registerSourceCodeSearchPath(libSearchPath); // Enable Color Management - mx::ColorManagementSystemPtr colorManagementSystem = + mx::ColorManagementSystemPtr colorManagementSystem; +#ifdef MATERIALX_BUILD_OCIO + try + { + auto config = OCIO::Config::CreateFromBuiltinConfig("ocio://studio-config-latest"); + colorManagementSystem = + mx::OpenColorIOManagementSystem::create(config, context.getShaderGenerator().getTarget()); + } + catch (const std::exception& /*e*/) + { + colorManagementSystem = + mx::DefaultColorManagementSystem::create(context.getShaderGenerator().getTarget()); + } +#else + colorManagementSystem = mx::DefaultColorManagementSystem::create(context.getShaderGenerator().getTarget()); +#endif REQUIRE(colorManagementSystem); if (colorManagementSystem) diff --git a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp index d8265a4050..bb1ce59ff9 100644 --- a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp +++ b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp @@ -8,6 +8,10 @@ #include +#ifdef MATERIALX_BUILD_OCIO +#include +#endif + namespace mx = MaterialX; namespace RenderUtil @@ -142,7 +146,20 @@ bool ShaderRenderTester::validate(const mx::FilePath optionsFilePath) createRenderer(log); - mx::ColorManagementSystemPtr colorManagementSystem = mx::DefaultColorManagementSystem::create(_shaderGenerator->getTarget()); + mx::ColorManagementSystemPtr colorManagementSystem; +#ifdef MATERIALX_BUILD_OCIO + try + { + auto config = OCIO::Config::CreateFromBuiltinConfig("ocio://studio-config-latest"); + colorManagementSystem = mx::OpenColorIOManagementSystem::create(config, _shaderGenerator->getTarget()); + } + catch (const std::exception& /*e*/) + { + colorManagementSystem = mx::DefaultColorManagementSystem::create(_shaderGenerator->getTarget()); + } +#else + colorManagementSystem = mx::DefaultColorManagementSystem::create(_shaderGenerator->getTarget()); +#endif colorManagementSystem->loadLibrary(dependLib); _shaderGenerator->setColorManagementSystem(colorManagementSystem);