Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement geompropvalue as GLSL varying parameters #1046

Merged

Conversation

JGamache-autodesk
Copy link
Collaborator

@JGamache-autodesk JGamache-autodesk commented Dec 2, 2020

The geompropvalue node in GLSL must be coded as varying parameter since there is no OpenGL API that allows a shader to request a named stream from the geometry.

So the GLSL codegen for these nodes was changed to pass varying input streams.
This will not work for boolean and string geompropvalues so the GLSL codegen correctly leaves them as unimplemented.
Fixes #1042

registerImplementation("IM_geompropvalue_integer_" + GlslShaderGenerator::LANGUAGE, GeomPropValueNodeGlsl::create);
registerImplementation("IM_geompropvalue_boolean_" + GlslShaderGenerator::LANGUAGE, GeomPropValueNodeGlsl::create);
registerImplementation("IM_geompropvalue_string_" + GlslShaderGenerator::LANGUAGE, GeomPropValueNodeGlsl::create);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will throw an exception when generating code for a document that contains these unimplementable nodes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should let these through and support them as uniforms for now so we don't lose any functionality. I think for the code generation we can test for these cases. As discussed with Niklas, later on we can add in some way to specify this in MaterialX. Then we can support the general concept of "primvars" which may be uniform or varying.

Copy link

@niklasharrysson niklasharrysson Dec 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes for longer term we should start using the geompropdef element. This is already in the spec and should be used to define new geometric stream/properties like this.

So before you can call the geompropvalue node to get the value from a geomprop this geomprop has to be defined first using a geompropdef element. If/when we start using this we could introduce a "uniform" attribute on these definitions to tag the geomprops as being uniform or varying. Boolean and string would naturally always be "uniform".

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JGamache-autodesk , @niklasharrysson : For the current implementation to avoid a regression I'd like to leave the uniform support for boolean and string so graphs that used to work don't fail now. Is that agreeable?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I then recommend splitting the nodedef into varyinggeompropvalue and uniformgeompropvalue in some future update? Otherwise some of the downstream code (like xmlSetProperty in OgsXmlGenerator.cpp) will require some creativity to find out if the value is uniform or varying.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @JGamache-autodesk, Yes, let's do a follow-up to see what works best e.g. two new types as you mention or one type with a reference with an attribute indicating variation.

const ShaderOutput* output = node.getOutput();
if (output->getType() == Type::BOOLEAN || output->getType() == Type::STRING) {
throw ExceptionShaderGenError("GLSL: unsupported type for geompropvalue node '" + node.getName() + "', can not generate code.");
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copied from TexCoordNodeGlsl.cpp, but with geomprop instead of index appended.

mx::ShaderPtr getShader() const
{
return _glslShader;
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Helped with debugging.

@@ -85,6 +83,13 @@ namespace
{ "u_time", "Time" }
};

static const vector<std::pair<string, const pugi::char_t*> > OGS_SEMANTICS_PREFIX_MAP =
{
{ "texcoord_", "mayaUvCoordSemantic" },
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to handle texcoord_1 and color_2 as well.

@@ -1508,7 +1508,7 @@ void ShaderGraph::calculateScopes()
{
newScopeInfo.adjustAtConditionalInput(node, int(inputIndex), 0x12);
}
else if (isSwitch)
else if (isSwitch && inputIndex != node->numInputs() - 1)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not mine. Possibly broke when the which "parameter" became an "input" with 1.38.

if (output)
{
outputNode = output->getConnectedNode();
// Handle connected upstream material nodes later on.
if (outputNode->getType() != mx::MATERIAL_TYPE_STRING)
{
nodeDef = outputNode->getNodeDef();

// We sometimes have complex graph where the node we want to skip is upstream:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The geompropvalue graphs have an extra test node downstream when the final value is not GLSL compatible. We need to traverse to find the unimplementable nodes.

@@ -25,6 +25,7 @@ void bindPyOgsFragment(py::module& mod)
.def_property_readonly("document", &my::OgsFragment::getDocument)
.def_property_readonly("fragmentSource", &my::OgsFragment::getFragmentSource)
.def_property_readonly("fragmentName", &my::OgsFragment::getFragmentName)
.def_property_readonly("shader", &my::OgsFragment::getShader)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely helped with debugging.

Copy link

@niklasharrysson niklasharrysson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thanks Jerry

@@ -8,7 +8,7 @@
<input name="in3" type="vector4" value="0.5000, 0.5000, 0.5000, 0.5000" />
<input name="in4" type="vector4" value="0.7000, 0.7000, 0.7000, 0.7000" />
<input name="in5" type="vector4" value="1.0000, 1.0000, 1.0000, 1.0000" />
<parameter name="which" type="integer" nodnname="geompropvalue_integer" />
<parameter name="which" type="integer" nodename="geompropvalue_integer" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made the result visually more interesting when used with a varying input stream.

registerImplementation("IM_geompropvalue_integer_" + GlslShaderGenerator::LANGUAGE, GeomPropValueNodeGlsl::create);
registerImplementation("IM_geompropvalue_boolean_" + GlslShaderGenerator::LANGUAGE, GeomPropValueNodeGlsl::create);
registerImplementation("IM_geompropvalue_string_" + GlslShaderGenerator::LANGUAGE, GeomPropValueNodeGlsl::create);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should let these through and support them as uniforms for now so we don't lose any functionality. I think for the code generation we can test for these cases. As discussed with Niklas, later on we can add in some way to specify this in MaterialX. Then we can support the general concept of "primvars" which may be uniform or varying.

@@ -23,24 +23,48 @@ void GeomPropValueNodeGlsl::createVariables(const ShaderNode& node, GenContext&,
throw ExceptionShaderGenError("No 'geomprop' parameter found on geompropvalue node '" + node.getName() + "', don't know what property to bind");
}
const string geomProp = geomPropInput->getValue()->getValueString();
const ShaderOutput* output = node.getOutput();
if (output->getType() == Type::BOOLEAN || output->getType() == Type::STRING) {
throw ExceptionShaderGenError("GLSL: unsupported type for geompropvalue node '" + node.getName() + "', can not generate code.");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above. Maybe we should just default back to uniform generation to not lose functionality.

const ShaderInput* geomPropInput = node.getInput(GEOMPROP);
if (!geomPropInput)
{
throw ExceptionShaderGenError("No 'geomprop' parameter found on geompropvalue node '" + node.getName() + "', don't know what property to bind");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick. Should probably be ". Don't" vs "don't" to start a new sentence.

The naming of geompropvalue inputs will now reflect the uniform vs varying nature.
@@ -8,7 +8,7 @@
<input name="in3" type="vector4" value="0.5000, 0.5000, 0.5000, 0.5000" />
<input name="in4" type="vector4" value="0.7000, 0.7000, 0.7000, 0.7000" />
<input name="in5" type="vector4" value="1.0000, 1.0000, 1.0000, 1.0000" />
<parameter name="which" type="integer" nodnname="geompropvalue_integer" />
<parameter name="which" type="integer" nodename="geompropvalue_integer" />
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made the result visually more interesting when used with a varying input stream.

ShaderStage& ps = shader.getStage(Stage::PIXEL);

addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_GEOMPROP + "_" + geomProp, vs);
addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_IN_GEOMPROP + "_" + geomProp, vs, ps);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Systematic use of T_IN_GEOMPROP insures the parameter ends up being named i_geomprop_* when varying and u_geomprop_* when uniform.

{
{ "texcoord_", "mayaUvCoordSemantic" },
{ "color_", "colorset" },
{ "i_geomprop_", "mayaUvCoordSemantic" }
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now looking for explicit varying input using i_geomprop_

@@ -210,12 +209,107 @@ void addAdditionalTestStreams(mx::MeshPtr mesh)
mesh->addStream(colorStream2);
}

const std::string GEOM_INT_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_integer");
int32_t* geomIntData = nullptr;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added tests for all known varying geompropvalue input types.

Copy link

@bernardkwok bernardkwok left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for preserving the uniform support capability. LGTM.

@JGamache-autodesk JGamache-autodesk merged commit a70027b into adsk_contrib/dev Dec 7, 2020
@JGamache-autodesk JGamache-autodesk deleted the t_gamaj/glsl_varying_geompropvalue branch December 7, 2020 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix geomPropValue for GLSL to output varying vs unifom
3 participants