summaryrefslogtreecommitdiff
path: root/servers/visual/shader_language.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual/shader_language.cpp')
-rw-r--r--servers/visual/shader_language.cpp139
1 files changed, 91 insertions, 48 deletions
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 1acec7ccaf..6efd05593e 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -525,7 +525,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
bool exponent_found = false;
bool hexa_found = false;
bool sign_found = false;
- bool minus_exponent_found = false;
bool float_suffix_found = false;
String str;
@@ -557,8 +556,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
if (sign_found)
return _make_token(TK_ERROR, "Invalid numeric constant");
sign_found = true;
- if (GETCHAR(i) == '-')
- minus_exponent_found = true;
} else
break;
@@ -571,7 +568,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
if (hexa_found) {
//hex integers eg."0xFF" or "0x12AB", etc - NOT supported yet
return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant - Not supported");
- } else if (period_found || float_suffix_found) {
+ } else if (period_found || exponent_found || float_suffix_found) {
//floats
if (period_found) {
if (float_suffix_found) {
@@ -614,12 +611,12 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
char_idx += str.length();
Token tk;
- if (period_found || minus_exponent_found || float_suffix_found)
+ if (period_found || exponent_found || float_suffix_found)
tk.type = TK_REAL_CONSTANT;
else
tk.type = TK_INT_CONSTANT;
- tk.constant = str.to_double(); //wont work with hex
+ tk.constant = str.to_double(); //won't work with hex
tk.line = tk_line;
return tk;
@@ -2078,7 +2075,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
for (int i = 0; i < argcount; i++) {
if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) {
- //all good
+ //all good, but needs implicit conversion later
} else if (args[i] != builtin_func_defs[idx].args[i]) {
fail = true;
break;
@@ -2124,6 +2121,24 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
outarg_idx++;
}
+ //implicitly convert values if possible
+ for (int i = 0; i < argcount; i++) {
+
+ if (get_scalar_type(args[i]) != args[i] || args[i] == builtin_func_defs[idx].args[i] || p_func->arguments[i + 1]->type != Node::TYPE_CONSTANT) {
+ //can't do implicit conversion here
+ continue;
+ }
+
+ //this is an implicit conversion
+ ConstantNode *constant = static_cast<ConstantNode *>(p_func->arguments[i + 1]);
+ ConstantNode *conversion = alloc_node<ConstantNode>();
+
+ conversion->datatype = builtin_func_defs[idx].args[i];
+ conversion->values.resize(1);
+
+ convert_constant(constant, builtin_func_defs[idx].args[i], conversion->values.ptrw());
+ p_func->arguments.write[i + 1] = conversion;
+ }
if (r_ret_type)
*r_ret_type = builtin_func_defs[idx].rettype;
@@ -2187,17 +2202,37 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
bool fail = false;
- for (int i = 0; i < args.size(); i++) {
+ for (int j = 0; j < args.size(); j++) {
- if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), pfunc->arguments[i].type)) {
- //all good
- } else if (args[i] != pfunc->arguments[i].type) {
+ if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) {
+ //all good, but it needs implicit conversion later
+ } else if (args[j] != pfunc->arguments[j].type) {
fail = true;
break;
}
}
if (!fail) {
+
+ //implicitly convert values if possible
+ for (int k = 0; k < args.size(); k++) {
+
+ if (get_scalar_type(args[k]) != args[k] || args[k] == pfunc->arguments[k].type || p_func->arguments[k + 1]->type != Node::TYPE_CONSTANT) {
+ //can't do implicit conversion here
+ continue;
+ }
+
+ //this is an implicit conversion
+ ConstantNode *constant = static_cast<ConstantNode *>(p_func->arguments[k + 1]);
+ ConstantNode *conversion = alloc_node<ConstantNode>();
+
+ conversion->datatype = pfunc->arguments[k].type;
+ conversion->values.resize(1);
+
+ convert_constant(constant, pfunc->arguments[k].type, conversion->values.ptrw());
+ p_func->arguments.write[k + 1] = conversion;
+ }
+
if (r_ret_type)
*r_ret_type = pfunc->return_type;
return true;
@@ -2900,7 +2935,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
/* OK now see what's NEXT to the operator.. */
while (true) {
- TkPos pos = _get_tkpos();
+ TkPos pos2 = _get_tkpos();
tk = _get_token();
if (tk.type == TK_CURSOR) {
@@ -2933,6 +2968,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
member_type = DataType(dt - 1);
} else if (l == 2) {
member_type = dt;
+ } else if (l == 3) {
+ member_type = DataType(dt + 1);
+ } else if (l == 4) {
+ member_type = DataType(dt + 2);
} else {
ok = false;
break;
@@ -2966,6 +3005,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
member_type = DataType(dt - 1);
} else if (l == 3) {
member_type = dt;
+ } else if (l == 4) {
+ member_type = DataType(dt + 1);
} else {
ok = false;
break;
@@ -3184,7 +3225,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = op;
} else {
- _set_tkpos(pos);
+ _set_tkpos(pos2);
break;
}
}
@@ -3377,10 +3418,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!_validate_operator(op, &op->return_cache)) {
String at;
- for (int i = 0; i < op->arguments.size(); i++) {
- if (i > 0)
+ for (int j = 0; j < op->arguments.size(); j++) {
+ if (j > 0)
at += " and ";
- at += get_datatype_name(op->arguments[i]->get_datatype());
+ at += get_datatype_name(op->arguments[j]->get_datatype());
}
_set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at);
return NULL;
@@ -3585,7 +3626,8 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
case TYPE_FLOAT: {
nv.real = -cn->values[i].real;
} break;
- default: {}
+ default: {
+ }
}
values.push_back(nv);
@@ -4106,17 +4148,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (uniform) {
- ShaderNode::Uniform uniform;
+ ShaderNode::Uniform uniform2;
if (is_sampler_type(type)) {
- uniform.texture_order = texture_uniforms++;
- uniform.order = -1;
+ uniform2.texture_order = texture_uniforms++;
+ uniform2.order = -1;
} else {
- uniform.texture_order = -1;
- uniform.order = uniforms++;
+ uniform2.texture_order = -1;
+ uniform2.order = uniforms++;
}
- uniform.type = type;
- uniform.precission = precision;
+ uniform2.type = type;
+ uniform2.precision = precision;
//todo parse default value
@@ -4127,26 +4169,26 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_HINT_WHITE_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_WHITE;
+ uniform2.hint = ShaderNode::Uniform::HINT_WHITE;
} else if (tk.type == TK_HINT_BLACK_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_BLACK;
+ uniform2.hint = ShaderNode::Uniform::HINT_BLACK;
} else if (tk.type == TK_HINT_NORMAL_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_NORMAL;
+ uniform2.hint = ShaderNode::Uniform::HINT_NORMAL;
} else if (tk.type == TK_HINT_ANISO_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_ANISO;
+ uniform2.hint = ShaderNode::Uniform::HINT_ANISO;
} else if (tk.type == TK_HINT_ALBEDO_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_ALBEDO;
+ uniform2.hint = ShaderNode::Uniform::HINT_ALBEDO;
} else if (tk.type == TK_HINT_BLACK_ALBEDO_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO;
+ uniform2.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO;
} else if (tk.type == TK_HINT_COLOR) {
if (type != TYPE_VEC4) {
_set_error("Color hint is for vec4 only");
return ERR_PARSE_ERROR;
}
- uniform.hint = ShaderNode::Uniform::HINT_COLOR;
+ uniform2.hint = ShaderNode::Uniform::HINT_COLOR;
} else if (tk.type == TK_HINT_RANGE) {
- uniform.hint = ShaderNode::Uniform::HINT_RANGE;
+ uniform2.hint = ShaderNode::Uniform::HINT_RANGE;
if (type != TYPE_FLOAT && type != TYPE_INT) {
_set_error("Range hint is for float and int only");
return ERR_PARSE_ERROR;
@@ -4172,8 +4214,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- uniform.hint_range[0] = tk.constant;
- uniform.hint_range[0] *= sign;
+ uniform2.hint_range[0] = tk.constant;
+ uniform2.hint_range[0] *= sign;
tk = _get_token();
@@ -4196,8 +4238,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- uniform.hint_range[1] = tk.constant;
- uniform.hint_range[1] *= sign;
+ uniform2.hint_range[1] = tk.constant;
+ uniform2.hint_range[1] *= sign;
tk = _get_token();
@@ -4209,13 +4251,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- uniform.hint_range[2] = tk.constant;
+ uniform2.hint_range[2] = tk.constant;
tk = _get_token();
} else {
if (type == TYPE_INT) {
- uniform.hint_range[2] = 1;
+ uniform2.hint_range[2] = 1;
} else {
- uniform.hint_range[2] = 0.001;
+ uniform2.hint_range[2] = 0.001;
}
}
@@ -4228,7 +4270,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Expected valid type hint after ':'.");
}
- if (uniform.hint != ShaderNode::Uniform::HINT_RANGE && uniform.hint != ShaderNode::Uniform::HINT_NONE && uniform.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) {
+ if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) {
_set_error("This hint is only for sampler types");
return ERR_PARSE_ERROR;
}
@@ -4248,16 +4290,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
ConstantNode *cn = static_cast<ConstantNode *>(expr);
- uniform.default_value.resize(cn->values.size());
+ uniform2.default_value.resize(cn->values.size());
- if (!convert_constant(cn, uniform.type, uniform.default_value.ptrw())) {
- _set_error("Can't convert constant to " + get_datatype_name(uniform.type));
+ if (!convert_constant(cn, uniform2.type, uniform2.default_value.ptrw())) {
+ _set_error("Can't convert constant to " + get_datatype_name(uniform2.type));
return ERR_PARSE_ERROR;
}
tk = _get_token();
}
- shader->uniforms[name] = uniform;
+ shader->uniforms[name] = uniform2;
if (tk.type != TK_SEMICOLON) {
_set_error("Expected ';'");
@@ -4267,7 +4309,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
ShaderNode::Varying varying;
varying.type = type;
- varying.precission = precision;
+ varying.precision = precision;
varying.interpolation = interpolation;
shader->varyings[name] = varying;
@@ -4787,7 +4829,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
case TYPE_MAT2: limit = 2; break;
case TYPE_MAT3: limit = 3; break;
case TYPE_MAT4: limit = 4; break;
- default: {}
+ default: {
+ }
}
for (int i = 0; i < limit; i++) {