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

Added 'fma' function to shader language #36225

Merged
merged 1 commit into from
Jul 10, 2020
Merged
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
29 changes: 29 additions & 0 deletions doc/classes/VisualShaderNodeMultiplyAdd.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeMultiplyAdd" inherits="VisualShaderNode" version="4.0">
<brief_description>
Performs a fused multiply-add operation within the visual shader graph.
</brief_description>
<description>
Uses three operands to compute [code](a * b + c)[/code] expression.
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
<member name="type" type="int" setter="set_type" getter="get_type" enum="VisualShaderNodeMultiplyAdd.Type" default="0">
A type of operands and returned value.
</member>
</members>
<constants>
<constant name="TYPE_SCALAR" value="0" enum="Type">
A scalar type.
</constant>
<constant name="TYPE_VECTOR" value="1" enum="Type">
A vector type.
</constant>
<constant name="TYPE_MAX" value="2" enum="Type">
Represents the size of the [enum Type] enum.
</constant>
</constants>
</class>
2 changes: 2 additions & 0 deletions drivers/gles2/shader_compiler_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[RS::SHADER_CANVAS_ITEM].usage_defines["isinf"] = "#define IS_INF_USED\n";
actions[RS::SHADER_CANVAS_ITEM].usage_defines["isnan"] = "#define IS_NAN_USED\n";
actions[RS::SHADER_CANVAS_ITEM].usage_defines["trunc"] = "#define TRUNC_USED\n";
actions[RS::SHADER_CANVAS_ITEM].usage_defines["fma"] = "#define FMA_USED\n";

/** SPATIAL SHADER **/

Expand Down Expand Up @@ -1126,6 +1127,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[RS::SHADER_SPATIAL].usage_defines["isinf"] = "#define IS_INF_USED\n";
actions[RS::SHADER_SPATIAL].usage_defines["isnan"] = "#define IS_NAN_USED\n";
actions[RS::SHADER_SPATIAL].usage_defines["trunc"] = "#define TRUNC_USED\n";
actions[RS::SHADER_SPATIAL].usage_defines["fma"] = "#define FMA_USED\n";

actions[RS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions[RS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
Expand Down
20 changes: 20 additions & 0 deletions drivers/gles2/shaders/stdlib.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -417,4 +417,24 @@ highp mat4 outerProduct(highp vec4 c, highp vec4 r) {

#endif

#if defined(FMA_USED)

highp float fma(highp float a, highp float b, highp float c) {
return a * b + c;
}

highp vec2 fma(highp vec2 a, highp vec2 b, highp vec2 c) {
return a * b + c;
}

highp vec3 fma(highp vec3 a, highp vec3 b, highp vec3 c) {
return a * b + c;
}

highp vec4 fma(highp vec4 a, highp vec4 b, highp vec4 c) {
return a * b + c;
}

#endif

#endif
8 changes: 8 additions & 0 deletions editor/plugins/visual_shader_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1392,6 +1392,12 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
if (vderFunc) {
vderFunc->set_function((VisualShaderNodeVectorDerivativeFunc::Function)p_op_idx);
}

VisualShaderNodeMultiplyAdd *fmaFunc = Object::cast_to<VisualShaderNodeMultiplyAdd>(vsn);

if (fmaFunc) {
fmaFunc->set_type((VisualShaderNodeMultiplyAdd::Type)p_op_idx);
}
}

vsnode = Ref<VisualShaderNode>(vsn);
Expand Down Expand Up @@ -2711,6 +2717,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Max", "Scalar", "Functions", "VisualShaderNodeFloatOp", TTR("Returns the greater of two values."), VisualShaderNodeFloatOp::OP_MAX, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("Min", "Scalar", "Functions", "VisualShaderNodeFloatOp", TTR("Returns the lesser of two values."), VisualShaderNodeFloatOp::OP_MIN, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("Mix", "Scalar", "Functions", "VisualShaderNodeScalarInterp", TTR("Linear interpolation between two scalars."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("MultiplyAdd", "Scalar", "Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on scalars."), VisualShaderNodeMultiplyAdd::TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("Negate", "Scalar", "Functions", "VisualShaderNodeFloatFunc", TTR("Returns the opposite value of the parameter."), VisualShaderNodeFloatFunc::FUNC_NEGATE, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("Negate", "Scalar", "Functions", "VisualShaderNodeIntFunc", TTR("Returns the opposite value of the parameter."), VisualShaderNodeIntFunc::FUNC_NEGATE, VisualShaderNode::PORT_TYPE_SCALAR_INT));
add_options.push_back(AddOption("OneMinus", "Scalar", "Functions", "VisualShaderNodeFloatFunc", TTR("1.0 - scalar"), VisualShaderNodeFloatFunc::FUNC_ONEMINUS, VisualShaderNode::PORT_TYPE_SCALAR));
Expand Down Expand Up @@ -2813,6 +2820,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Min", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), VisualShaderNodeVectorOp::OP_MIN, VisualShaderNode::PORT_TYPE_VECTOR));
add_options.push_back(AddOption("Mix", "Vector", "Functions", "VisualShaderNodeVectorInterp", TTR("Linear interpolation between two vectors."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
add_options.push_back(AddOption("MixS", "Vector", "Functions", "VisualShaderNodeVectorScalarMix", TTR("Linear interpolation between two vectors using scalar."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
add_options.push_back(AddOption("MultiplyAdd", "Vector", "Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on vectors."), VisualShaderNodeMultiplyAdd::TYPE_VECTOR, VisualShaderNode::PORT_TYPE_VECTOR));
add_options.push_back(AddOption("Negate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNode::PORT_TYPE_VECTOR));
add_options.push_back(AddOption("Normalize", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNode::PORT_TYPE_VECTOR));
add_options.push_back(AddOption("OneMinus", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), VisualShaderNodeVectorFunc::FUNC_ONEMINUS, VisualShaderNode::PORT_TYPE_VECTOR));
Expand Down
1 change: 1 addition & 0 deletions scene/register_scene_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,7 @@ void register_scene_types() {
ClassDB::register_class<VisualShaderNodeGlobalExpression>();
ClassDB::register_class<VisualShaderNodeIs>();
ClassDB::register_class<VisualShaderNodeCompare>();
ClassDB::register_class<VisualShaderNodeMultiplyAdd>();

ClassDB::register_class<ShaderMaterial>();
ClassDB::register_virtual_class<CanvasItem>();
Expand Down
93 changes: 93 additions & 0 deletions scene/resources/visual_shader_nodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4794,3 +4794,96 @@ VisualShaderNodeCompare::VisualShaderNodeCompare() {
set_input_port_default_value(1, 0.0);
set_input_port_default_value(2, CMP_EPSILON);
}

////////////// Fma

String VisualShaderNodeMultiplyAdd::get_caption() const {
return "MultiplyAdd";
}

int VisualShaderNodeMultiplyAdd::get_input_port_count() const {
return 3;
}

VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_input_port_type(int p_port) const {
if (type == TYPE_SCALAR) {
return PORT_TYPE_SCALAR;
}
return PORT_TYPE_VECTOR;
}

String VisualShaderNodeMultiplyAdd::get_input_port_name(int p_port) const {
if (p_port == 0) {
return "a";
} else if (p_port == 1) {
return "b(*)";
} else if (p_port == 2) {
return "c(+)";
}
return "";
}

int VisualShaderNodeMultiplyAdd::get_output_port_count() const {
return 1;
}

VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_output_port_type(int p_port) const {
if (type == TYPE_SCALAR) {
return PORT_TYPE_SCALAR;
} else {
return PORT_TYPE_VECTOR;
}
}

String VisualShaderNodeMultiplyAdd::get_output_port_name(int p_port) const {
return "";
}

String VisualShaderNodeMultiplyAdd::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
return "\t" + p_output_vars[0] + " = fma(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
}

void VisualShaderNodeMultiplyAdd::set_type(Type p_type) {
ERR_FAIL_INDEX((int)p_type, TYPE_MAX);
if (p_type != type) {
if (p_type == TYPE_SCALAR) {
set_input_port_default_value(0, 0.0);
set_input_port_default_value(1, 0.0);
set_input_port_default_value(2, 0.0);
} else {
set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0));
set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0));
set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0));
}
}
type = p_type;
emit_changed();
}

VisualShaderNodeMultiplyAdd::Type VisualShaderNodeMultiplyAdd::get_type() const {
return type;
}

Vector<StringName> VisualShaderNodeMultiplyAdd::get_editable_properties() const {
Vector<StringName> props;
props.push_back("type");
return props;
}

void VisualShaderNodeMultiplyAdd::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_type", "type"), &VisualShaderNodeMultiplyAdd::set_type);
ClassDB::bind_method(D_METHOD("get_type"), &VisualShaderNodeMultiplyAdd::get_type);

ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Scalar,Vector"), "set_type", "get_type");

BIND_ENUM_CONSTANT(TYPE_SCALAR);
BIND_ENUM_CONSTANT(TYPE_VECTOR);
BIND_ENUM_CONSTANT(TYPE_MAX);
}

VisualShaderNodeMultiplyAdd::VisualShaderNodeMultiplyAdd() {
type = TYPE_SCALAR;
set_input_port_default_value(0, 0.0);
set_input_port_default_value(1, 0.0);
set_input_port_default_value(2, 0.0);
}
39 changes: 39 additions & 0 deletions scene/resources/visual_shader_nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1995,4 +1995,43 @@ VARIANT_ENUM_CAST(VisualShaderNodeCompare::ComparisonType)
VARIANT_ENUM_CAST(VisualShaderNodeCompare::Function)
VARIANT_ENUM_CAST(VisualShaderNodeCompare::Condition)

class VisualShaderNodeMultiplyAdd : public VisualShaderNode {
GDCLASS(VisualShaderNodeMultiplyAdd, VisualShaderNode);

public:
enum Type {
TYPE_SCALAR,
TYPE_VECTOR,
TYPE_MAX,
};
Chaosus marked this conversation as resolved.
Show resolved Hide resolved

protected:
Type type;

protected:
static void _bind_methods();

public:
virtual String get_caption() const;

virtual int get_input_port_count() const;
virtual PortType get_input_port_type(int p_port) const;
virtual String get_input_port_name(int p_port) const;

virtual int get_output_port_count() const;
virtual PortType get_output_port_type(int p_port) const;
virtual String get_output_port_name(int p_port) const;

virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty

void set_type(Type p_type);
Type get_type() const;

virtual Vector<StringName> get_editable_properties() const;

VisualShaderNodeMultiplyAdd();
};

VARIANT_ENUM_CAST(VisualShaderNodeMultiplyAdd::Type)

#endif // VISUAL_SHADER_NODES_H
7 changes: 7 additions & 0 deletions servers/rendering/shader_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2135,6 +2135,13 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
//array
{ "length", TYPE_INT, { TYPE_VOID }, TAG_ARRAY, true },

// modern functions

{ "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
{ "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },

{ nullptr, TYPE_VOID, { TYPE_VOID }, TAG_GLOBAL, false }

};
Expand Down