summaryrefslogtreecommitdiff
path: root/servers/rendering/shader_language.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/shader_language.cpp')
-rw-r--r--servers/rendering/shader_language.cpp58
1 files changed, 49 insertions, 9 deletions
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 14a28554f9..a282f10402 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -643,9 +643,9 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
}
if (hexa_found) {
- tk.constant = (double)str.hex_to_int64(true);
+ tk.constant = (double)str.hex_to_int(true);
} else {
- tk.constant = str.to_double();
+ tk.constant = str.to_float();
}
tk.line = tk_line;
@@ -982,6 +982,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_struct_name) {
*r_struct_name = function->arguments[i].type_str;
}
+ if (r_is_const) {
+ *r_is_const = function->arguments[i].is_const;
+ }
return true;
}
}
@@ -1134,13 +1137,13 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} else if (na == TYPE_FLOAT && nb == TYPE_VEC4) {
valid = true;
ret_type = TYPE_VEC4;
- } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT2) {
+ } else if (na == TYPE_FLOAT && nb == TYPE_MAT2) {
valid = true;
ret_type = TYPE_MAT2;
- } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT3) {
+ } else if (na == TYPE_FLOAT && nb == TYPE_MAT3) {
valid = true;
ret_type = TYPE_MAT3;
- } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT4) {
+ } else if (na == TYPE_FLOAT && nb == TYPE_MAT4) {
valid = true;
ret_type = TYPE_MAT4;
} else if (p_op->op == OP_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) {
@@ -1310,13 +1313,13 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} else if (na == TYPE_VEC4 && nb == TYPE_FLOAT) {
valid = true;
ret_type = TYPE_VEC4;
- } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT2 && nb == TYPE_VEC2) {
+ } else if (na == TYPE_MAT2 && nb == TYPE_FLOAT) {
valid = true;
ret_type = TYPE_MAT2;
- } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT3 && nb == TYPE_VEC3) {
+ } else if (na == TYPE_MAT3 && nb == TYPE_FLOAT) {
valid = true;
ret_type = TYPE_MAT3;
- } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT4 && nb == TYPE_VEC4) {
+ } else if (na == TYPE_MAT4 && nb == TYPE_FLOAT) {
valid = true;
ret_type = TYPE_MAT4;
} else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) {
@@ -2132,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, false },
+ { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
+ { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
+ { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
+
{ nullptr, TYPE_VOID, { TYPE_VOID }, TAG_GLOBAL, false }
};
@@ -3553,7 +3563,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
for (int i = 0; i < call_function->arguments.size(); i++) {
int argidx = i + 1;
if (argidx < func->arguments.size()) {
- if (call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT) {
+ if (call_function->arguments[i].is_const || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT) {
bool error = false;
Node *n = func->arguments[argidx];
if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) {
@@ -5585,6 +5595,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
} else if (tk.type == TK_CF_RETURN) {
//check return type
BlockNode *b = p_block;
+
+ if (b && b->parent_function && (b->parent_function->name == "vertex" || b->parent_function->name == "fragment" || b->parent_function->name == "light")) {
+ _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name));
+ return ERR_PARSE_ERROR;
+ }
+
while (b && !b->parent_function) {
b = b->parent_block;
}
@@ -6774,15 +6790,29 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
break;
}
+ bool is_const = false;
+ if (tk.type == TK_CONST) {
+ is_const = true;
+ tk = _get_token();
+ }
+
ArgumentQualifier qualifier = ARGUMENT_QUALIFIER_IN;
if (tk.type == TK_ARG_IN) {
qualifier = ARGUMENT_QUALIFIER_IN;
tk = _get_token();
} else if (tk.type == TK_ARG_OUT) {
+ if (is_const) {
+ _set_error("'out' qualifier cannot be used within a function parameter declared with 'const'.");
+ return ERR_PARSE_ERROR;
+ }
qualifier = ARGUMENT_QUALIFIER_OUT;
tk = _get_token();
} else if (tk.type == TK_ARG_INOUT) {
+ if (is_const) {
+ _set_error("'inout' qualifier cannot be used within a function parameter declared with 'const'.");
+ return ERR_PARSE_ERROR;
+ }
qualifier = ARGUMENT_QUALIFIER_INOUT;
tk = _get_token();
}
@@ -6871,6 +6901,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
arg.tex_builtin_check = false;
arg.tex_argument_filter = FILTER_DEFAULT;
arg.tex_argument_repeat = REPEAT_DEFAULT;
+ arg.is_const = is_const;
func_node->arguments.push_back(arg);
@@ -6948,6 +6979,11 @@ bool ShaderLanguage::has_builtin(const Map<StringName, ShaderLanguage::FunctionI
return true;
}
}
+ if (p_functions.has("compute")) {
+ if (p_functions["compute"].built_ins.has(p_name)) {
+ return true;
+ }
+ }
return false;
}
@@ -7267,6 +7303,10 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += CharType(0xFFFF);
}
+ if (shader->functions[i].function->arguments[j].is_const) {
+ calltip += "const ";
+ }
+
if (shader->functions[i].function->arguments[j].qualifier != ArgumentQualifier::ARGUMENT_QUALIFIER_IN) {
if (shader->functions[i].function->arguments[j].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT) {
calltip += "out ";