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.cpp63
1 files changed, 52 insertions, 11 deletions
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 49f9e161fa..bc59acead5 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -3,7 +3,7 @@
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
-/* http://www.godotengine.org */
+/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
@@ -165,6 +165,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"CF_BREAK",
"CF_CONTINUE",
"CF_RETURN",
+ "CF_DISCARD",
"BRACKET_OPEN",
"BRACKET_CLOSE",
"CURLY_BRACKET_OPEN",
@@ -1041,6 +1042,12 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
}
} break;
case OP_ASSIGN: {
+
+ if (p_op->arguments[0]->type != Node::TYPE_MEMBER && p_op->arguments[0]->type != Node::TYPE_VARIABLE) {
+ valid = false;
+ break;
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
valid = na == nb;
@@ -1563,9 +1570,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
{ "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
- { "facefordward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
- { "facefordward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "facefordward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
+ { "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
+ { "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
+ { "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
{ "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID } },
{ "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID } },
@@ -1931,7 +1938,8 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
}
if (!fail) {
- p_func->return_cache = pfunc->return_type;
+ if (r_ret_type)
+ *r_ret_type = pfunc->return_type;
return true;
}
}
@@ -3150,6 +3158,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
assign->op = OP_ASSIGN;
p_block->statements.push_back(assign);
tk = _get_token();
+
+ if (!_validate_operator(assign)) {
+ _set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(type) + "'");
+ return ERR_PARSE_ERROR;
+ }
}
if (tk.type == TK_COMMA) {
@@ -3285,6 +3298,34 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
}
p_block->statements.push_back(flow);
+ } else if (tk.type == TK_CF_DISCARD) {
+
+ //check return type
+ BlockNode *b = p_block;
+ while (b && !b->parent_function) {
+ b = b->parent_block;
+ }
+ if (!b) {
+ _set_error("Bug");
+ return ERR_BUG;
+ }
+
+ if (!b->parent_function->can_discard) {
+ _set_error("Use of 'discard' is not allowed here.");
+ return ERR_PARSE_ERROR;
+ }
+
+ ControlFlowNode *flow = alloc_node<ControlFlowNode>();
+ flow->flow_op = FLOW_OP_DISCARD;
+
+ pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ //all is good
+ _set_error("Expected ';' after discard");
+ }
+
+ p_block->statements.push_back(flow);
} else {
@@ -3309,7 +3350,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
return OK;
}
-Error ShaderLanguage::_parse_shader(const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) {
+Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) {
Token tk = _get_token();
@@ -3646,7 +3687,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, Map<StringName, DataTy
Map<StringName, DataType> builtin_types;
if (p_functions.has(name)) {
- builtin_types = p_functions[name];
+ builtin_types = p_functions[name].built_ins;
}
ShaderNode::Function function;
@@ -3810,7 +3851,7 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
return String();
}
-Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) {
+Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) {
clear();
@@ -3827,7 +3868,7 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Map<St
return OK;
}
-Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint) {
+Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint) {
clear();
@@ -3854,7 +3895,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Map<S
} break;
case COMPLETION_MAIN_FUNCTION: {
- for (const Map<StringName, Map<StringName, DataType> >::Element *E = p_functions.front(); E; E = E->next()) {
+ for (const Map<StringName, FunctionInfo>::Element *E = p_functions.front(); E; E = E->next()) {
r_options->push_back(E->key());
}
@@ -3895,7 +3936,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Map<S
if (comp_ident && skip_function != StringName() && p_functions.has(skip_function)) {
- for (Map<StringName, DataType>::Element *E = p_functions[skip_function].front(); E; E = E->next()) {
+ for (Map<StringName, DataType>::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) {
matches.insert(E->key());
}
}