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.cpp318
1 files changed, 211 insertions, 107 deletions
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 9c38bf7606..ca911d995a 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -88,7 +88,8 @@ String ShaderLanguage::get_operator_text(Operator p_op) {
"--",
"()",
"construct",
- "index" };
+ "index",
+ "empty" };
return op_names[p_op];
}
@@ -474,6 +475,10 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
case ':':
return _make_token(TK_COLON);
case '^':
+ if (GETCHAR(0) == '=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_BIT_XOR);
+ }
return _make_token(TK_OP_BIT_XOR);
case '~':
return _make_token(TK_OP_BIT_INVERT);
@@ -909,8 +914,10 @@ void ShaderLanguage::clear() {
completion_type = COMPLETION_NONE;
completion_block = nullptr;
completion_function = StringName();
- completion_class = SubClassTag::TAG_GLOBAL;
+ completion_class = TAG_GLOBAL;
completion_struct = StringName();
+ completion_base = TYPE_VOID;
+ completion_base_array = false;
unknown_varying_usages.clear();
@@ -2763,6 +2770,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
bool is_const = false;
ConstantNode::Value value;
+ value.sint = -1;
_find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, &is_const, nullptr, nullptr, &value);
if (!is_const || value.sint < min || value.sint > max) {
@@ -2993,7 +3001,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
FunctionNode *pfunc = shader->functions[i].function;
- if (arg_list == "") {
+ if (arg_list.is_empty()) {
for (int j = 0; j < pfunc->arguments.size(); j++) {
if (j > 0) {
arg_list += ", ";
@@ -3229,6 +3237,10 @@ bool ShaderLanguage::is_token_operator_assign(TokenType p_type) {
p_type == TK_OP_ASSIGN_BIT_XOR);
}
+bool ShaderLanguage::is_token_hint(TokenType p_type) {
+ return int(p_type) > int(TK_RENDER_MODE) && int(p_type) < int(TK_SHADER_TYPE);
+}
+
bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value) {
if (p_constant->datatype == p_to_type) {
if (p_value) {
@@ -3295,16 +3307,16 @@ bool ShaderLanguage::is_float_type(DataType p_type) {
}
bool ShaderLanguage::is_sampler_type(DataType p_type) {
return p_type == TYPE_SAMPLER2D ||
- p_type == TYPE_ISAMPLER2D ||
- p_type == TYPE_USAMPLER2D ||
- p_type == TYPE_SAMPLER2DARRAY ||
- p_type == TYPE_ISAMPLER2DARRAY ||
- p_type == TYPE_USAMPLER2DARRAY ||
- p_type == TYPE_SAMPLER3D ||
- p_type == TYPE_ISAMPLER3D ||
- p_type == TYPE_USAMPLER3D ||
- p_type == TYPE_SAMPLERCUBE ||
- p_type == TYPE_SAMPLERCUBEARRAY;
+ p_type == TYPE_ISAMPLER2D ||
+ p_type == TYPE_USAMPLER2D ||
+ p_type == TYPE_SAMPLER2DARRAY ||
+ p_type == TYPE_ISAMPLER2DARRAY ||
+ p_type == TYPE_USAMPLER2DARRAY ||
+ p_type == TYPE_SAMPLER3D ||
+ p_type == TYPE_ISAMPLER3D ||
+ p_type == TYPE_USAMPLER3D ||
+ p_type == TYPE_SAMPLERCUBE ||
+ p_type == TYPE_SAMPLERCUBEARRAY;
}
Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, int p_array_size, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
@@ -3872,16 +3884,16 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
bool ShaderLanguage::is_control_flow_keyword(String p_keyword) {
return p_keyword == "break" ||
- p_keyword == "case" ||
- p_keyword == "continue" ||
- p_keyword == "default" ||
- p_keyword == "do" ||
- p_keyword == "else" ||
- p_keyword == "for" ||
- p_keyword == "if" ||
- p_keyword == "return" ||
- p_keyword == "switch" ||
- p_keyword == "while";
+ p_keyword == "case" ||
+ p_keyword == "continue" ||
+ p_keyword == "default" ||
+ p_keyword == "do" ||
+ p_keyword == "else" ||
+ p_keyword == "for" ||
+ p_keyword == "if" ||
+ p_keyword == "return" ||
+ p_keyword == "switch" ||
+ p_keyword == "while";
}
void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) {
@@ -4292,7 +4304,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, cons
return n;
}
-Error ShaderLanguage::_parse_global_array_size(int &r_array_size) {
+Error ShaderLanguage::_parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info) {
if (r_array_size > 0) {
_set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
@@ -4304,7 +4316,7 @@ Error ShaderLanguage::_parse_global_array_size(int &r_array_size) {
if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
_set_tkpos(pos);
- Node *n = _parse_array_size(nullptr, FunctionInfo(), array_size);
+ Node *n = _parse_array_size(nullptr, p_function_info, array_size);
if (!n) {
return ERR_PARSE_ERROR;
}
@@ -4919,7 +4931,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
bool error = false;
Node *n = func->arguments[argidx];
if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) {
- error = true;
+ if (!call_function->arguments[i].is_const) {
+ error = true;
+ }
} else if (n->type == Node::TYPE_ARRAY) {
ArrayNode *an = static_cast<ArrayNode *>(n);
if (an->call_expression != nullptr || an->is_const) {
@@ -5205,9 +5219,21 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.push_back(e);
continue;
} else {
- _set_error("Expected expression, found: " + get_token_text(tk));
- return nullptr;
- //nothing
+ if (tk.type != TK_SEMICOLON) {
+ _set_error("Expected expression, found: " + get_token_text(tk));
+ return nullptr;
+ } else {
+#if DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) {
+ _add_line_warning(ShaderWarning::FORMATTING_ERROR, "Empty statement. Remove ';' to fix this warning.");
+ }
+#endif // DEBUG_ENABLED
+ _set_tkpos(prepos);
+
+ OperatorNode *func = alloc_node<OperatorNode>();
+ func->op = OP_EMPTY;
+ expr = func;
+ }
}
ERR_FAIL_COND_V(!expr, nullptr);
@@ -6070,7 +6096,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at);
return nullptr;
}
- expression.remove(i + 1);
+ expression.remove_at(i + 1);
}
} else if (is_ternary) {
@@ -6110,7 +6136,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
for (int i = 0; i < 4; i++) {
- expression.remove(next_op);
+ expression.remove_at(next_op);
}
} else {
@@ -6171,8 +6197,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
- expression.remove(next_op);
- expression.remove(next_op);
+ expression.remove_at(next_op);
+ expression.remove_at(next_op);
}
}
@@ -6383,7 +6409,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ArrayDeclarationNode::Declaration adecl;
if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
- _set_error("Expected identifier or '[' after type.");
+ _set_error("Expected identifier or '[' after datatype.");
return ERR_PARSE_ERROR;
}
@@ -7187,11 +7213,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
//check return type
BlockNode *b = p_block;
- if (b && b->parent_function && p_function_info.main_function) {
- _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;
}
@@ -7201,6 +7222,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_BUG;
}
+ if (b && b->parent_function && p_function_info.main_function) {
+ _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name));
+ return ERR_PARSE_ERROR;
+ }
+
String return_struct_name = String(b->parent_function->return_struct_name);
String array_size_string;
@@ -7216,7 +7242,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type == TK_SEMICOLON) {
//all is good
if (b->parent_function->return_type != TYPE_VOID) {
- _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
+ _set_error("Expected return with an expression of type '" + (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
return ERR_PARSE_ERROR;
}
} else {
@@ -7228,7 +7254,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
if (b->parent_function->return_type != expr->get_datatype() || b->parent_function->return_array_size != expr->get_array_size() || return_struct_name != expr->get_datatype_name()) {
- _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
+ _set_error("Expected return with an expression of type '" + (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
return ERR_PARSE_ERROR;
}
@@ -7350,7 +7376,7 @@ String ShaderLanguage::_get_shader_type_list(const Set<String> &p_shader_types)
// Return a list of shader types as an human-readable string
String valid_types;
for (const Set<String>::Element *E = p_shader_types.front(); E; E = E->next()) {
- if (valid_types != String()) {
+ if (!valid_types.is_empty()) {
valid_types += ", ";
}
@@ -7443,6 +7469,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
stages = &p_functions;
+ const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo();
while (tk.type != TK_EOF) {
switch (tk.type) {
@@ -7486,7 +7513,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_IDENTIFIER) {
st.name = tk.text;
- if (shader->structs.has(st.name)) {
+ if (shader->constants.has(st.name) || shader->structs.has(st.name)) {
_set_error("Redefinition of '" + String(st.name) + "'");
return ERR_PARSE_ERROR;
}
@@ -7558,7 +7585,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int array_size = 0;
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(array_size);
+ Error error = _parse_global_array_size(array_size, constants);
if (error != OK) {
return error;
}
@@ -7585,7 +7612,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(member->array_size);
+ Error error = _parse_global_array_size(member->array_size, constants);
if (error != OK) {
return error;
}
@@ -7644,7 +7671,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
bool uniform = tk.type == TK_UNIFORM;
if (!uniform) {
- if (shader_type_identifier == "particles" || shader_type_identifier == "sky") {
+ if (shader_type_identifier == "particles" || shader_type_identifier == "sky" || shader_type_identifier == "fog") {
_set_error(vformat("Varyings cannot be used in '%s' shaders!", shader_type_identifier));
return ERR_PARSE_ERROR;
}
@@ -7712,7 +7739,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(array_size);
+ Error error = _parse_global_array_size(array_size, constants);
if (error != OK) {
return error;
}
@@ -7727,7 +7754,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
prev_pos = _get_tkpos();
name = tk.text;
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
+ if (_find_identifier(nullptr, false, constants, name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -7760,7 +7787,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(uniform2.array_size);
+ Error error = _parse_global_array_size(uniform2.array_size, constants);
if (error != OK) {
return error;
}
@@ -7808,9 +7835,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int custom_instance_index = -1;
if (tk.type == TK_COLON) {
+ completion_type = COMPLETION_HINT;
+ completion_base = type;
+ completion_base_array = uniform2.array_size > 0;
+
//hint
do {
tk = _get_token();
+ completion_line = tk.line;
+
+ if (!is_token_hint(tk.type)) {
+ _set_error("Expected valid type hint after ':'.");
+ return ERR_PARSE_ERROR;
+ }
if (uniform2.array_size > 0) {
if (tk.type != TK_HINT_COLOR) {
@@ -7980,8 +8017,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
uniform2.repeat = REPEAT_DISABLE;
} else if (tk.type == TK_REPEAT_ENABLE) {
uniform2.repeat = REPEAT_ENABLE;
- } else {
- _set_error("Expected valid type hint after ':'.");
}
if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) {
@@ -8014,7 +8049,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *expr = _parse_and_reduce_expression(nullptr, constants);
if (!expr) {
return ERR_PARSE_ERROR;
}
@@ -8048,6 +8083,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Expected ';'");
return ERR_PARSE_ERROR;
}
+
+ completion_type = COMPLETION_NONE;
} else { // varying
ShaderNode::Varying varying;
varying.type = type;
@@ -8110,7 +8147,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
DataPrecision precision = PRECISION_DEFAULT;
DataType type;
StringName name;
- int return_array_size = 0;
+ int array_size = 0;
if (tk.type == TK_CONST) {
is_constant = true;
@@ -8149,13 +8186,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
prev_pos = _get_tkpos();
tk = _get_token();
+ bool unknown_size = false;
+
if (tk.type == TK_BRACKET_OPEN) {
+ if (is_constant && RenderingServer::get_singleton()->is_low_end()) {
+ _set_error("Global const arrays are only supported on high-end platform!");
+ return ERR_PARSE_ERROR;
+ }
bool error = false;
tk = _get_token();
if (tk.type == TK_INT_CONSTANT) {
- return_array_size = (int)tk.constant;
- if (return_array_size > 0) {
+ array_size = (int)tk.constant;
+ if (array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
@@ -8164,11 +8207,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else {
error = true;
}
+ } else if (tk.type == TK_BRACKET_CLOSE) {
+ unknown_size = true;
} else {
error = true;
}
if (error) {
- _set_error("Expected integer constant > 0");
+ _set_error("Expected integer constant > 0 or ']'");
return ERR_PARSE_ERROR;
}
@@ -8180,16 +8225,15 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_get_completable_identifier(nullptr, COMPLETION_MAIN_FUNCTION, name);
if (name == StringName()) {
- _set_error("Expected function name after datatype");
- return ERR_PARSE_ERROR;
- }
-
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
- _set_error("Redefinition of '" + String(name) + "'");
+ if (is_constant) {
+ _set_error("Expected identifier or '[' after datatype.");
+ } else {
+ _set_error("Expected function name after datatype.");
+ }
return ERR_PARSE_ERROR;
}
- if (has_builtin(p_functions, name)) {
+ if (shader->structs.has(name) || _find_identifier(nullptr, false, constants, name) || has_builtin(p_functions, name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -8202,7 +8246,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
//variable
-
+ bool first = true;
while (true) {
ShaderNode::Constant constant;
constant.name = name;
@@ -8210,16 +8254,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.type_str = struct_name;
constant.precision = precision;
constant.initializer = nullptr;
- constant.array_size = 0;
-
- bool unknown_size = false;
+ constant.array_size = (first ? array_size : 0);
+ first = false;
if (tk.type == TK_BRACKET_OPEN) {
if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error("Global const arrays are supported only on high-end platform!");
+ _set_error("Global const arrays are only supported on high-end platform!");
+ return ERR_PARSE_ERROR;
+ }
+ if (constant.array_size > 0 || unknown_size) {
+ _set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
}
-
tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
unknown_size = true;
@@ -8297,7 +8343,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else {
_set_tkpos(prev_pos);
- Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *n = _parse_and_reduce_expression(nullptr, constants);
if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
@@ -8378,7 +8424,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
while (true) {
- Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *n = _parse_and_reduce_expression(nullptr, constants);
if (!n) {
return ERR_PARSE_ERROR;
}
@@ -8433,7 +8479,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
} else {
//variable created with assignment! must parse an expression
- Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *expr = _parse_and_reduce_expression(nullptr, constants);
if (!expr) {
return ERR_PARSE_ERROR;
}
@@ -8449,7 +8495,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
- if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), 0)) {
+ if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), expr->get_array_size())) {
return ERR_PARSE_ERROR;
}
}
@@ -8480,7 +8526,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
name = tk.text;
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
+ if (_find_identifier(nullptr, false, constants, name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -8514,6 +8560,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
}
+ if (p_functions.has("constants")) { // Adds global constants: 'PI', 'TAU', 'E'
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["constants"].built_ins) {
+ builtins.built_ins.insert(E.key, E.value);
+ }
+ }
+
ShaderNode::Function function;
function.callable = !p_functions.has(name);
@@ -8529,7 +8581,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
func_node->return_type = type;
func_node->return_struct_name = struct_name;
func_node->return_precision = precision;
- func_node->return_array_size = return_array_size;
+ func_node->return_array_size = array_size;
if (p_functions.has(name)) {
func_node->can_discard = p_functions[name].can_discard;
@@ -8583,7 +8635,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
StringName param_struct_name;
DataPrecision pprecision = PRECISION_DEFAULT;
bool use_precision = false;
- int array_size = 0;
+ int arg_array_size = 0;
if (is_token_precision(tk.type)) {
pprecision = get_token_precision(tk.type);
@@ -8634,9 +8686,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_INT_CONSTANT) {
- array_size = (int)tk.constant;
+ arg_array_size = (int)tk.constant;
- if (array_size > 0) {
+ if (arg_array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
@@ -8688,7 +8740,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- if (array_size > 0) {
+ if (arg_array_size > 0) {
_set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
}
@@ -8696,9 +8748,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_INT_CONSTANT) {
- array_size = (int)tk.constant;
+ arg_array_size = (int)tk.constant;
- if (array_size > 0) {
+ if (arg_array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
@@ -8718,7 +8770,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- arg.array_size = array_size;
+ arg.array_size = arg_array_size;
func_node->arguments.push_back(arg);
if (tk.type == TK_COMMA) {
@@ -8897,7 +8949,7 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
break;
} else if (p_code[i] <= 32) {
- if (cur_identifier != String()) {
+ if (!cur_identifier.is_empty()) {
if (!reading_type) {
if (cur_identifier != "shader_type") {
return String();
@@ -8957,17 +9009,17 @@ uint32_t ShaderLanguage::get_warning_flags() const {
}
#endif // DEBUG_ENABLED
-Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func) {
+Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_info) {
clear();
code = p_code;
- global_var_get_type_func = p_global_variable_type_func;
- varying_function_names = p_varying_function_names;
+ global_var_get_type_func = p_info.global_variable_type_func;
+ varying_function_names = p_info.varying_function_names;
nodes = nullptr;
shader = alloc_node<ShaderNode>();
- Error err = _parse_shader(p_functions, p_render_modes, p_shader_types);
+ Error err = _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
#ifdef DEBUG_ENABLED
if (check_warnings) {
@@ -8981,17 +9033,17 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi
return OK;
}
-Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
+Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
clear();
code = p_code;
- varying_function_names = p_varying_function_names;
+ varying_function_names = p_info.varying_function_names;
nodes = nullptr;
- global_var_get_type_func = p_global_variable_type_func;
+ global_var_get_type_func = p_info.global_variable_type_func;
shader = alloc_node<ShaderNode>();
- _parse_shader(p_functions, p_render_modes, p_shader_types);
+ _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
switch (completion_type) {
case COMPLETION_NONE: {
@@ -8999,8 +9051,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
return OK;
} break;
case COMPLETION_RENDER_MODE: {
- for (int i = 0; i < p_render_modes.size(); i++) {
- ScriptCodeCompletionOption option(p_render_modes[i], ScriptCodeCompletionOption::KIND_ENUM);
+ for (int i = 0; i < p_info.render_modes.size(); i++) {
+ ScriptCodeCompletionOption option(p_info.render_modes[i], ScriptCodeCompletionOption::KIND_ENUM);
r_options->push_back(option);
}
@@ -9018,7 +9070,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
return OK;
} break;
case COMPLETION_MAIN_FUNCTION: {
- for (const KeyValue<StringName, FunctionInfo> &E : p_functions) {
+ for (const KeyValue<StringName, FunctionInfo> &E : p_info.functions) {
ScriptCodeCompletionOption option(E.key, ScriptCodeCompletionOption::KIND_FUNCTION);
r_options->push_back(option);
}
@@ -9054,8 +9106,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
if (comp_ident) {
- if (p_functions.has("global")) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["global"].built_ins) {
+ if (p_info.functions.has("global")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
if (E.value.constant) {
kind = ScriptCodeCompletionOption::KIND_CONSTANT;
@@ -9064,8 +9116,18 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
}
- if (skip_function != StringName() && p_functions.has(skip_function)) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_functions[skip_function].built_ins) {
+ if (p_info.functions.has("constants")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
+ ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptCodeCompletionOption::KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+
+ if (skip_function != StringName() && p_info.functions.has(skip_function)) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
if (E.value.constant) {
kind = ScriptCodeCompletionOption::KIND_CONSTANT;
@@ -9369,15 +9431,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
limit = 4;
} break;
- case TYPE_MAT2:
- limit = 2;
- break;
- case TYPE_MAT3:
- limit = 3;
- break;
- case TYPE_MAT4:
- limit = 4;
- break;
default: {
}
}
@@ -9389,6 +9442,57 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
} break;
+ case COMPLETION_HINT: {
+ if (completion_base == DataType::TYPE_VEC4) {
+ ScriptCodeCompletionOption option("hint_color", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ } else if ((completion_base == DataType::TYPE_INT || completion_base == DataType::TYPE_FLOAT) && !completion_base_array) {
+ ScriptCodeCompletionOption option("hint_range", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+
+ if (completion_base == DataType::TYPE_INT) {
+ option.insert_text = "hint_range(0, 100, 1)";
+ } else {
+ option.insert_text = "hint_range(0.0, 1.0, 0.1)";
+ }
+
+ r_options->push_back(option);
+ } else if ((int(completion_base) > int(TYPE_MAT4) && int(completion_base) < int(TYPE_STRUCT)) && !completion_base_array) {
+ static Vector<String> options;
+
+ if (options.is_empty()) {
+ options.push_back("filter_linear");
+ options.push_back("filter_linear_mipmap");
+ options.push_back("filter_linear_mipmap_aniso");
+ options.push_back("filter_nearest");
+ options.push_back("filter_nearest_mipmap");
+ options.push_back("filter_nearest_mipmap_aniso");
+ options.push_back("hint_albedo");
+ options.push_back("hint_aniso");
+ options.push_back("hint_black");
+ options.push_back("hint_black_albedo");
+ options.push_back("hint_normal");
+ options.push_back("hint_roughness_a");
+ options.push_back("hint_roughness_b");
+ options.push_back("hint_roughness_g");
+ options.push_back("hint_roughness_gray");
+ options.push_back("hint_roughness_normal");
+ options.push_back("hint_roughness_r");
+ options.push_back("hint_white");
+ options.push_back("repeat_enable");
+ options.push_back("repeat_disable");
+ }
+
+ for (int i = 0; i < options.size(); i++) {
+ ScriptCodeCompletionOption option(options[i], ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ if (!completion_base_array) {
+ ScriptCodeCompletionOption option("instance_index", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ option.insert_text = "instance_index(0)";
+ r_options->push_back(option);
+ }
+ } break;
}
return ERR_PARSE_ERROR;