Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion source/MaterialXGenMdl/MdlShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,25 @@ void disconnectTransmissionIor(ShaderGraph* g)

} // anonymous namespace

bool MdlShaderGenerator::isInputUsed(const ShaderGraphInputSocket& input) const
{
for (const ShaderInput* connection : input.getConnections())
{
const ShaderNode* node = connection->getNode();
if (node->isAGraph())
{
return true;
}

const ShaderNodeImpl& implementation = node->getImplementation();
if (implementation.isInputUsed(*connection))
{
return true;
}
}
return false;
}

ShaderPtr MdlShaderGenerator::createShader(const string& name, ElementPtr element, GenContext& context) const
{
// Create the root shader graph
Expand Down Expand Up @@ -690,7 +709,7 @@ void emitInputAnnotations(const MdlShaderGenerator& _this, const ShaderPort* var
_this.emitString(_this.getSyntax().getIndentation() + mtlxParameterPathAnno, stage);
const ShaderGraphInputSocket* input = static_cast<const ShaderGraphInputSocket*>(variable);

if (input->getConnections().empty())
if (!_this.isInputUsed(*input))
{
_this.emitString(",", stage);
_this.emitLineEnd(stage, false);
Expand Down
3 changes: 3 additions & 0 deletions source/MaterialXGenMdl/MdlShaderGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ class MX_GENMDL_API MdlShaderGenerator : public ShaderGenerator
/// Emit type definitions for all data types that need them.
void emitTypeDefinitions(GenContext& context, ShaderStage& stage) const override;

/// Return whether a graph input is referenced by generated MDL code.
bool isInputUsed(const ShaderGraphInputSocket& input) const;

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

#include <MaterialXCore/Definition.h>

#include <set>

MATERIALX_NAMESPACE_BEGIN

ShaderNodeImplPtr ClosureCompoundNodeMdl::create()
Expand Down Expand Up @@ -38,7 +40,7 @@ void ClosureCompoundNodeMdl::emitFunctionDefinition(const ShaderNode& node, GenC
if (!_returnStruct.empty() && _unrollReturnStructMembers)
{
// make sure the upstream definitions are known
for (const ShaderGraphOutputSocket* outputSocket : _rootGraph->getOutputSockets())
for (ShaderGraphOutputSocket* outputSocket : _rootGraph->getOutputSockets())
{
if (!outputSocket->getConnection())
continue;
Expand All @@ -65,9 +67,20 @@ void ClosureCompoundNodeMdl::emitFunctionDefinition(const ShaderNode& node, GenC
// Function body.
shadergen.emitScopeBegin(stage);

// Emit all texturing nodes. These are inputs to the
// closure nodes and need to be emitted first.
shadergen.emitFunctionCalls(*_rootGraph, context, stage, ShaderNode::Classification::TEXTURE);
// Emit only texturing nodes upstream of this output field.
std::set<const ShaderNode*> upstreamNodes;
for (ShaderGraphEdge edge : ShaderGraph::traverseUpstream(outputSocket->getConnection()))
{
upstreamNodes.insert(edge.upstream->getNode());
}
for (const ShaderNode* child : _rootGraph->getNodes())
{
if (upstreamNodes.count(child) &&
child->hasClassification(ShaderNode::Classification::TEXTURE))
{
shadergen.emitFunctionCall(*child, context, stage);
}
}

// Emit function calls for internal closures nodes connected to the graph sockets.
// These will in turn emit function calls for any dependent closure nodes upstream.
Expand Down
8 changes: 7 additions & 1 deletion source/MaterialXGenMdl/Nodes/CompoundNodeMdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ void CompoundNodeMdl::emitFunctionCall(const ShaderNode& node, GenContext& conte
continue;

const std::string& fieldName = outputSocket->getName();
const ShaderOutput* nodeOutput = node.getOutput(fieldName);

// Emit the struct field.
const string& outputType = syntax.getTypeName(outputSocket->getType());
Expand All @@ -142,6 +143,10 @@ void CompoundNodeMdl::emitFunctionCall(const ShaderNode& node, GenContext& conte

// End function call
shadergen.emitString(")", stage);
if (!nodeOutput || nodeOutput->getConnections().empty())
{
shadergen.emitString(" [[ anno::unused() ]]", stage);
}
shadergen.emitLineEnd(stage);
}

Expand Down Expand Up @@ -181,6 +186,7 @@ void CompoundNodeMdl::emitFunctionCall(const ShaderNode& node, GenContext& conte
void CompoundNodeMdl::emitFunctionSignature(const ShaderNode&, GenContext& context, ShaderStage& stage) const
{
const ShaderGenerator& shadergen = context.getShaderGenerator();
const MdlShaderGenerator& mdlShadergen = static_cast<const MdlShaderGenerator&>(shadergen);
const MdlSyntax& syntax = static_cast<const MdlSyntax&>(shadergen.getSyntax());

if (!_returnStruct.empty())
Expand Down Expand Up @@ -256,7 +262,7 @@ void CompoundNodeMdl::emitFunctionSignature(const ShaderNode&, GenContext& conte
shadergen.emitLineBegin(stage);
shadergen.emitString(qualifier + type + " " + input->getVariable() + " = " + value, stage);

if (input->getConnections().empty())
if (!mdlShadergen.isInputUsed(*input))
{
shadergen.emitLineEnd(stage, false);
shadergen.emitLine("[[", stage, false);
Expand Down
4 changes: 4 additions & 0 deletions source/MaterialXGenMdl/Nodes/HeightToNormalNodeMdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ ShaderNodeImplPtr HeightToNormalNodeMdl::create()
return std::make_shared<HeightToNormalNodeMdl>();
}

void HeightToNormalNodeMdl::createVariables(const ShaderNode&, GenContext&, Shader&) const
{
}

void HeightToNormalNodeMdl::computeSampleOffsetStrings(const string& sampleSizeName, const string& offsetTypeString,
unsigned int, StringVec& offsetStrings) const
{
Expand Down
3 changes: 3 additions & 0 deletions source/MaterialXGenMdl/Nodes/HeightToNormalNodeMdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class MX_GENMDL_API HeightToNormalNodeMdl : public ConvolutionNode
public:
static ShaderNodeImplPtr create();

/// Height-to-normal uses a fixed Sobel kernel and needs no filter-weight variables.
void createVariables(const ShaderNode&, GenContext&, Shader&) const override;

void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;

protected:
Expand Down
24 changes: 24 additions & 0 deletions source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//

#include <MaterialXGenMdl/Nodes/ImageNodeMdl.h>
#include <MaterialXGenMdl/Nodes/HeightToNormalNodeMdl.h>
#include <MaterialXGenShader/ShaderGenerator.h>
#include <MaterialXGenShader/Shader.h>
#include <MaterialXGenShader/GenContext.h>
Expand Down Expand Up @@ -37,6 +38,29 @@ void ImageNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& context
DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
{
ShaderNode& node = const_cast<ShaderNode&>(_node);

ShaderOutput* output = node.getOutput();
string outputSuffix;
context.getOutputSuffix(output, outputSuffix);
if (outputSuffix.empty() && output && !output->getConnections().empty())
{
bool sampledOnly = true;
for (const ShaderInput* connection : output->getConnections())
{
const ShaderNode* downstreamNode = connection->getNode();
if (downstreamNode->isAGraph() ||
!dynamic_cast<const HeightToNormalNodeMdl*>(&downstreamNode->getImplementation()))
{
sampledOnly = false;
break;
}
}
if (sampledOnly)
{
return;
}
}

ShaderInput* flipUInput = node.getInput(ImageNodeMdl::FLIP_V);
ValuePtr value = TypedValue<bool>::createValue(context.getOptions().fileTextureVerticalFlip);
if (flipUInput)
Expand Down
11 changes: 11 additions & 0 deletions source/MaterialXGenMdl/Nodes/SourceCodeNodeMdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ ShaderNodeImplPtr SourceCodeNodeMdl::create()
return std::make_shared<SourceCodeNodeMdl>();
}

bool SourceCodeNodeMdl::isInputUsed(const ShaderInput& input) const
{
if (!_inlined)
{
return true;
}

const string marker = "{{" + input.getName() + "}}";
return _functionSource.find(marker) != string::npos;
}

void SourceCodeNodeMdl::resolveSourceCode(const InterfaceElement& /*element*/, GenContext& /*context*/)
{
// Initialize without fetching the source code from file.
Expand Down
3 changes: 3 additions & 0 deletions source/MaterialXGenMdl/Nodes/SourceCodeNodeMdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ class MX_GENMDL_API SourceCodeNodeMdl : public SourceCodeNode
void emitFunctionDefinition(const ShaderNode&, GenContext&, ShaderStage&) const override;
void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;

/// Return whether an input is referenced by the inline source expression.
bool isInputUsed(const ShaderInput& input) const override;

protected:
void resolveSourceCode(const InterfaceElement& element, GenContext& context) override;
string _returnStruct;
Expand Down
6 changes: 6 additions & 0 deletions source/MaterialXGenShader/ShaderNodeImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ class MX_GENSHADER_API ShaderNodeImpl
/// or returns nullptr otherwise.
virtual ShaderGraph* getGraph() const;

/// Return whether an input is referenced by the generated source code.
virtual bool isInputUsed(const ShaderInput& /*input*/) const
{
return true;
}

/// Returns true if an input is editable by users.
/// Editable inputs are allowed to be published as shader uniforms
/// and hence must be presentable in a user interface.
Expand Down