Skip to content

Commit

Permalink
Add a ShaderGen option to select the target MDL version (#1417)
Browse files Browse the repository at this point in the history
This allows to generate MDL code for older applications while adding new features in the future.

It also to helps structuring changes and features depending on the MDL version.
  • Loading branch information
krohmerNV authored Feb 5, 2024
1 parent d64e044 commit de5c2b6
Show file tree
Hide file tree
Showing 22 changed files with 7,111 additions and 6,371 deletions.
2 changes: 1 addition & 1 deletion libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
<!-- ======================================================================== -->

<!-- <viewdirection> -->
<implementation name="IM_viewdirection_vector3_genmdl" nodedef="ND_viewdirection_vector3" sourcecode="mx::stdlib::mx_viewdirection_vector3()" target="genmdl" />
<implementation name="IM_viewdirection_vector3_genmdl" nodedef="ND_viewdirection_vector3" sourcecode="materialx::stdlib_{{MDL_VERSION_SUFFIX}}::mx_viewdirection_vector3()" target="genmdl" />

</materialx>
72 changes: 36 additions & 36 deletions libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx

Large diffs are not rendered by default.

418 changes: 209 additions & 209 deletions libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx

Large diffs are not rendered by default.

86 changes: 76 additions & 10 deletions source/MaterialXGenMdl/MdlShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ MATERIALX_NAMESPACE_BEGIN
namespace
{

const string MDL_VERSION = "1.6";

const vector<string> DEFAULT_IMPORTS =
{
"import ::df::*",
Expand All @@ -42,16 +40,30 @@ const vector<string> DEFAULT_IMPORTS =
"import ::state::*",
"import ::anno::*",
"import ::tex::*",
"import ::mx::swizzle::*",
"using ::mx::core import *",
"using ::mx::stdlib import *",
"using ::mx::pbrlib import *",
"using ::mx::sampling import *",
"import ::materialx::swizzle::*",
"using ::materialx::core import *",
"using ::materialx::sampling import *",
};

const vector<string> DEFAULT_VERSIONED_IMPORTS = {
"using ::materialx::stdlib_",
"using ::materialx::pbrlib_",
};

const string IMPORT_ALL = " import *";


const string MDL_VERSION_1_6 = "1.6";
const string MDL_VERSION_1_7 = "1.7";
const string MDL_VERSION_1_8 = "1.8";
const string MDL_VERSION_SUFFIX_1_6 = "1_6";
const string MDL_VERSION_SUFFIX_1_7 = "1_7";
const string MDL_VERSION_SUFFIX_1_8 = "1_8";

} // anonymous namespace

const string MdlShaderGenerator::TARGET = "genmdl";
const string GenMdlOptions::GEN_CONTEXT_USER_DATA_KEY = "genmdloptions";

const std::unordered_map<string, string> MdlShaderGenerator::GEOMPROP_DEFINITIONS =
{
Expand Down Expand Up @@ -214,16 +226,21 @@ ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, G
ShaderStage& stage = shader->getStage(Stage::PIXEL);

// Emit version
emitLine("mdl " + MDL_VERSION, stage);
emitMdlVersionNumber(context, stage);
emitLineBreak(stage);

emitLine("using mx = materialx", stage);

// Emit module imports
for (const string& module : DEFAULT_IMPORTS)
{
emitLine(module, stage);
}
for (const string& module : DEFAULT_VERSIONED_IMPORTS)
{
emitString(module, stage);
emitMdlVersionFilenameSuffix(context, stage);
emitString(IMPORT_ALL, stage);
emitLineEnd(stage, true);
}

// Add global constants and type definitions
emitTypeDefinitions(context, stage);
Expand Down Expand Up @@ -697,6 +714,55 @@ void MdlShaderGenerator::emitShaderInputs(const VariableBlock& inputs, ShaderSta
}
}


void MdlShaderGenerator::emitMdlVersionNumber(GenContext& context, ShaderStage& stage) const
{
GenMdlOptionsPtr options = context.getUserData<GenMdlOptions>(GenMdlOptions::GEN_CONTEXT_USER_DATA_KEY);
GenMdlOptions::MdlVersion version = options ? options->targetVersion : GenMdlOptions::MdlVersion::MDL_LATEST;

emitLineBegin(stage);
emitString("mdl ", stage);
switch (version)
{
case GenMdlOptions::MdlVersion::MDL_1_6:
emitString(MDL_VERSION_1_6, stage);
break;
case GenMdlOptions::MdlVersion::MDL_1_7:
emitString(MDL_VERSION_1_7, stage);
break;
default:
// GenMdlOptions::MdlVersion::MDL_1_8
// GenMdlOptions::MdlVersion::MDL_LATEST
emitString(MDL_VERSION_1_8, stage);
break;
}
emitLineEnd(stage, true);
}

const string& MdlShaderGenerator::getMdlVersionFilenameSuffix(GenContext& context) const
{
GenMdlOptionsPtr options = context.getUserData<GenMdlOptions>(GenMdlOptions::GEN_CONTEXT_USER_DATA_KEY);
GenMdlOptions::MdlVersion version = options ? options->targetVersion : GenMdlOptions::MdlVersion::MDL_LATEST;

switch (version)
{
case GenMdlOptions::MdlVersion::MDL_1_6:
return MDL_VERSION_SUFFIX_1_6;
case GenMdlOptions::MdlVersion::MDL_1_7:
return MDL_VERSION_SUFFIX_1_7;
default:
// GenMdlOptions::MdlVersion::MDL_1_8
// GenMdlOptions::MdlVersion::MDL_LATEST
return MDL_VERSION_SUFFIX_1_8;
}
}


void MdlShaderGenerator::emitMdlVersionFilenameSuffix(GenContext& context, ShaderStage& stage) const
{
emitString(getMdlVersionFilenameSuffix(context), stage);
}

namespace MDL
{
// Identifiers for MDL variable blocks
Expand Down
38 changes: 38 additions & 0 deletions source/MaterialXGenMdl/MdlShaderGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,35 @@

MATERIALX_NAMESPACE_BEGIN

/// Generator context data class to pass strings.
class MX_GENMDL_API GenMdlOptions : public GenUserData
{
public:
/// MDL Versions supported by the Code Generator
enum class MdlVersion
{
MDL_1_6,
MDL_1_7,
MDL_1_8,
MDL_LATEST = MDL_1_8
};

/// Create MDL code generator options with default values.
GenMdlOptions() :
targetVersion(MdlVersion::MDL_LATEST) { }

/// Unique identifier for the MDL options on the GenContext object.
static const string GEN_CONTEXT_USER_DATA_KEY;

/// The MDL version number the generated module will have.
/// Allows to generate MDL for older applications by limiting support according
/// to the corresponding specification. By default this option is MDL_LATEST.
MdlVersion targetVersion;
};

/// Shared pointer to GenMdlOptions
using GenMdlOptionsPtr = shared_ptr<class GenMdlOptions>;

/// Shared pointer to an MdlShaderGenerator
using MdlShaderGeneratorPtr = shared_ptr<class MdlShaderGenerator>;

Expand Down Expand Up @@ -47,6 +76,15 @@ class MX_GENMDL_API MdlShaderGenerator : public ShaderGenerator
/// Map of code snippets for geomprops in MDL.
static const std::unordered_map<string, string> GEOMPROP_DEFINITIONS;

/// Add the MDL file header containing the version number of the generated module..
void emitMdlVersionNumber(GenContext& context, ShaderStage& stage) const;

/// Add the version number suffix appended to MDL modules that use versions.
void emitMdlVersionFilenameSuffix(GenContext& context, ShaderStage& stage) const;

/// Get the version number suffix appended to MDL modules that use versions.
const string& getMdlVersionFilenameSuffix(GenContext& context) const;

protected:
// Create and initialize a new MDL shader for shader generation.
ShaderPtr createShader(const string& name, ElementPtr element, GenContext& context) const;
Expand Down
6 changes: 5 additions & 1 deletion source/MaterialXGenMdl/Nodes/MaterialNodeMdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//

#include <MaterialXGenMdl/Nodes/MaterialNodeMdl.h>
#include <MaterialXGenMdl/MdlShaderGenerator.h>
#include <MaterialXGenShader/ShaderGenerator.h>
#include <MaterialXGenShader/Shader.h>
#include <MaterialXGenShader/GenContext.h>
Expand All @@ -30,6 +31,7 @@ void MaterialNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& cont
}

const ShaderGenerator& shadergen = context.getShaderGenerator();
const MdlShaderGenerator& shadergenMdl = static_cast<const MdlShaderGenerator&>(shadergen);

// Emit the function call for upstream surface shader.
const ShaderNode* surfaceshaderNode = surfaceshaderInput->getConnection()->getNode();
Expand All @@ -39,7 +41,9 @@ void MaterialNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& cont

// Emit the output and funtion name.
shadergen.emitOutput(node.getOutput(), true, false, context, stage);
shadergen.emitString(" = mx::stdlib::mx_surfacematerial(", stage);
shadergen.emitString(" = materialx::stdlib_", stage);
shadergenMdl.emitMdlVersionFilenameSuffix(context, stage);
shadergen.emitString("::mx_surfacematerial(", stage);

// Emit all inputs on the node.
string delim = "";
Expand Down
98 changes: 68 additions & 30 deletions source/MaterialXGenMdl/Nodes/SourceCodeNodeMdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,52 @@
//

#include <MaterialXGenMdl/Nodes/SourceCodeNodeMdl.h>
#include <MaterialXGenMdl/MdlSyntax.h>
#include <MaterialXGenMdl/MdlShaderGenerator.h>

#include <MaterialXGenShader/GenContext.h>
#include <MaterialXGenShader/ShaderGenerator.h>
#include <MaterialXGenShader/ShaderNode.h>
#include <MaterialXGenShader/ShaderStage.h>
#include <MaterialXGenShader/Util.h>

#include <numeric>

MATERIALX_NAMESPACE_BEGIN

namespace // anonymous
{
const string MARKER_MDL_VERSION_SUFFIX = "MDL_VERSION_SUFFIX";

StringVec replaceSourceCodeMarkers(const string& nodeName, const string& soureCode, std::function<string(const string&)> lambda)
{
// An inline function call
// Replace tokens of the format "{{<var>}}"
static const string prefix("{{");
static const string postfix("}}");

size_t pos = 0;
size_t i = soureCode.find_first_of(prefix);
StringVec code;
while (i != string::npos)
{
code.push_back(soureCode.substr(pos, i - pos));
size_t j = soureCode.find_first_of(postfix, i + 2);
if (j == string::npos)
{
throw ExceptionShaderGenError("Malformed inline expression in implementation for node " + nodeName);
}
const string marker = soureCode.substr(i + 2, j - i - 2);
code.push_back(lambda(marker));
pos = j + 2;
i = soureCode.find_first_of(prefix, pos);
}
code.push_back(soureCode.substr(pos));
return code;
}

} // anonymous namespace

ShaderNodeImplPtr SourceCodeNodeMdl::create()
{
return std::make_shared<SourceCodeNodeMdl>();
Expand All @@ -36,6 +73,15 @@ void SourceCodeNodeMdl::initialize(const InterfaceElement& element, GenContext&
{
size_t pos = _functionSource.find_first_of('(');
string functionName = _functionSource.substr(0, pos);

const ShaderGenerator& shadergen = context.getShaderGenerator();
const MdlShaderGenerator& shadergenMdl = static_cast<const MdlShaderGenerator&>(shadergen);
const string versionSuffix = shadergenMdl.getMdlVersionFilenameSuffix(context);
StringVec code = replaceSourceCodeMarkers(getName(), functionName, [&versionSuffix](const string& marker)
{
return marker == MARKER_MDL_VERSION_SUFFIX ? versionSuffix : EMPTY_STRING;
});
functionName = std::accumulate(code.begin(), code.end(), EMPTY_STRING);
_returnStruct = functionName + "__result";
}
else
Expand All @@ -54,39 +100,31 @@ void SourceCodeNodeMdl::emitFunctionCall(const ShaderNode& node, GenContext& con
DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
{
const ShaderGenerator& shadergen = context.getShaderGenerator();
const MdlShaderGenerator& shadergenMdl = static_cast<const MdlShaderGenerator&>(shadergen);
if (_inlined)
{
// An inline function call

static const string prefix("{{");
static const string postfix("}}");

size_t pos = 0;
size_t i = _functionSource.find_first_of(prefix);
StringVec code;
while (i != string::npos)
{
code.push_back(_functionSource.substr(pos, i - pos));
size_t j = _functionSource.find_first_of(postfix, i + 2);
if (j == string::npos)
const string versionSuffix = shadergenMdl.getMdlVersionFilenameSuffix(context);
StringVec code = replaceSourceCodeMarkers(node.getName(), _functionSource,
[&shadergenMdl, &context, &node, &versionSuffix](const string& marker)
{
throw ExceptionShaderGenError("Malformed inline expression in implementation for node " + node.getName());
}

const string variable = _functionSource.substr(i + 2, j - i - 2);
const ShaderInput* input = node.getInput(variable);
if (!input)
{
throw ExceptionShaderGenError("Could not find an input named '" + variable +
"' on node '" + node.getName() + "'");
}

code.push_back(shadergen.getUpstreamResult(input, context));

pos = j + 2;
i = _functionSource.find_first_of(prefix, pos);
}
code.push_back(_functionSource.substr(pos));
// Special handling for the version suffix of MDL source code modules.
if (marker == MARKER_MDL_VERSION_SUFFIX)
{
return versionSuffix;
}
// Insert inputs based on parameter names.
else
{
const ShaderInput* input = node.getInput(marker);
if (!input)
{
throw ExceptionShaderGenError("Could not find an input named '" + marker +
"' on node '" + node.getName() + "'");
}

return shadergenMdl.getUpstreamResult(input, context);
}
});

if (!_returnStruct.empty())
{
Expand Down
4 changes: 3 additions & 1 deletion source/MaterialXGenMdl/Nodes/SurfaceNodeMdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ void SurfaceNodeMdl::emitFunctionCall(const ShaderNode& node, GenContext& contex

// Emit the output and funtion name.
shadergen.emitOutput(node.getOutput(), true, false, context, stage);
shadergen.emitString(" = mx::pbrlib::mx_surface(", stage);
shadergen.emitString(" = materialx::pbrlib_", stage);
shadergen.emitMdlVersionFilenameSuffix(context, stage);
shadergen.emitString("::mx_surface(", stage);

// Emit all inputs on the node.
string delim = "";
Expand Down
4 changes: 2 additions & 2 deletions source/MaterialXGenMdl/mdl/materialx/core.mdl
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
// Document version 1.7.2, January 17, 2022
// www.nvidia.com/mdl

mdl 1.7;
mdl 1.6;

import ::math::*;
import ::tex::*;
import ::state::*;
import ::tex::*;

// Epsilon value used in float calculations.
export const float FLOAT_EPS = 0.000001;
Expand Down
4 changes: 2 additions & 2 deletions source/MaterialXGenMdl/mdl/materialx/hsv.mdl
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@

// Support functions for HSV <--> RGB color conversions

mdl 1.0;
mdl 1.6;

import ::math::*;
import ::limits::*;
import ::math::*;

// Convert from the HSV color model to the RGB color model
export float3 mx_hsvtorgb(float3 hsv) {
Expand Down
7 changes: 4 additions & 3 deletions source/MaterialXGenMdl/mdl/materialx/noise.mdl
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

mdl 1.6;

using core import *;
import swizzle::*;
import ::anno::*;
import ::math::*;
import ::state::*;
import ::anno::*;

import .::core::*;
import .::swizzle::*;

float mx_bilerp_float(float v0, float v1, float v2, float v3, float s, float t)
{
Expand Down
Loading

0 comments on commit de5c2b6

Please sign in to comment.