summaryrefslogtreecommitdiffstats
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.cpp4958
1 files changed, 3408 insertions, 1550 deletions
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 6c835fcadf..d803d5fcf8 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 */
@@ -30,9 +30,11 @@
#include "shader_language.h"
#include "core/os/os.h"
-#include "core/print_string.h"
+#include "core/string/print_string.h"
#include "servers/rendering_server.h"
+#define HAS_WARNING(flag) (warning_flags & flag)
+
static bool _is_text_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}
@@ -223,7 +225,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
String ShaderLanguage::get_token_text(Token p_token) {
String name = token_names[p_token.type];
- if (p_token.type == TK_INT_CONSTANT || p_token.type == TK_REAL_CONSTANT) {
+ if (p_token.type == TK_INT_CONSTANT || p_token.type == TK_FLOAT_CONSTANT) {
name += "(" + rtos(p_token.constant) + ")";
} else if (p_token.type == TK_IDENTIFIER) {
name += "(" + String(p_token.text) + ")";
@@ -558,13 +560,13 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_ERROR, "Invalid numeric constant");
}
hexa_found = true;
- } else if (GETCHAR(i) == 'e') {
- if (hexa_found || exponent_found || float_suffix_found) {
+ } else if (GETCHAR(i) == 'e' && !hexa_found) {
+ if (exponent_found || float_suffix_found) {
return _make_token(TK_ERROR, "Invalid numeric constant");
}
exponent_found = true;
- } else if (GETCHAR(i) == 'f') {
- if (hexa_found || exponent_found) {
+ } else if (GETCHAR(i) == 'f' && !hexa_found) {
+ if (exponent_found) {
return _make_token(TK_ERROR, "Invalid numeric constant");
}
float_suffix_found = true;
@@ -629,7 +631,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
if (!_is_number(last_char)) {
return _make_token(TK_ERROR, "Invalid (integer) numeric constant");
}
- if (!str.is_valid_integer()) {
+ if (!str.is_valid_int()) {
return _make_token(TK_ERROR, "Invalid numeric constant");
}
}
@@ -637,13 +639,13 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
char_idx += str.length();
Token tk;
if (period_found || exponent_found || float_suffix_found) {
- tk.type = TK_REAL_CONSTANT;
+ tk.type = TK_FLOAT_CONSTANT;
} else {
tk.type = TK_INT_CONSTANT;
}
if (hexa_found) {
- tk.constant = (double)str.hex_to_int(true);
+ tk.constant = (double)str.hex_to_int();
} else {
tk.constant = str.to_float();
}
@@ -901,6 +903,8 @@ bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) {
void ShaderLanguage::clear() {
current_function = StringName();
+ last_name = StringName();
+ last_type = IDENTIFIER_MAX;
completion_type = COMPLETION_NONE;
completion_block = nullptr;
@@ -908,11 +912,24 @@ void ShaderLanguage::clear() {
completion_class = SubClassTag::TAG_GLOBAL;
completion_struct = StringName();
+ unknown_varying_usages.clear();
+
+#ifdef DEBUG_ENABLED
+ used_constants.clear();
+ used_varyings.clear();
+ used_uniforms.clear();
+ used_functions.clear();
+ used_structs.clear();
+ used_local_vars.clear();
+ warnings.clear();
+#endif // DEBUG_ENABLED
+
error_line = 0;
tk_line = 1;
char_idx = 0;
error_set = false;
error_str = "";
+ last_const = false;
while (nodes) {
Node *n = nodes;
nodes = nodes->next;
@@ -920,7 +937,43 @@ void ShaderLanguage::clear() {
}
}
-bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name) {
+#ifdef DEBUG_ENABLED
+void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, IdentifierType p_type, const StringName &p_function) {
+ switch (p_type) {
+ case IdentifierType::IDENTIFIER_CONSTANT:
+ if (HAS_WARNING(ShaderWarning::UNUSED_CONSTANT_FLAG) && used_constants.has(p_identifier)) {
+ used_constants[p_identifier].used = true;
+ }
+ break;
+ case IdentifierType::IDENTIFIER_VARYING:
+ if (HAS_WARNING(ShaderWarning::UNUSED_VARYING_FLAG) && used_varyings.has(p_identifier)) {
+ if (shader->varyings[p_identifier].stage != ShaderNode::Varying::STAGE_VERTEX && shader->varyings[p_identifier].stage != ShaderNode::Varying::STAGE_FRAGMENT) {
+ used_varyings[p_identifier].used = true;
+ }
+ }
+ break;
+ case IdentifierType::IDENTIFIER_UNIFORM:
+ if (HAS_WARNING(ShaderWarning::UNUSED_UNIFORM_FLAG) && used_uniforms.has(p_identifier)) {
+ used_uniforms[p_identifier].used = true;
+ }
+ break;
+ case IdentifierType::IDENTIFIER_FUNCTION:
+ if (HAS_WARNING(ShaderWarning::UNUSED_FUNCTION_FLAG) && used_functions.has(p_identifier)) {
+ used_functions[p_identifier].used = true;
+ }
+ break;
+ case IdentifierType::IDENTIFIER_LOCAL_VAR:
+ if (HAS_WARNING(ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG) && used_local_vars.has(p_function) && used_local_vars[p_function].has(p_identifier)) {
+ used_local_vars[p_function][p_identifier].used = true;
+ }
+ break;
+ default:
+ break;
+ }
+}
+#endif // DEBUG_ENABLED
+
+bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name, ConstantNode::Value *r_constant_value) {
if (p_function_info.built_ins.has(p_identifier)) {
if (r_data_type) {
*r_data_type = p_function_info.built_ins[p_identifier].type;
@@ -931,7 +984,6 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_type) {
*r_type = IDENTIFIER_BUILTIN_VAR;
}
-
return true;
}
@@ -945,7 +997,6 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_type) {
*r_type = IDENTIFIER_FUNCTION;
}
-
return true;
}
@@ -962,13 +1013,15 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_array_size) {
*r_array_size = p_block->variables[p_identifier].array_size;
}
- if (r_type) {
- *r_type = IDENTIFIER_LOCAL_VAR;
- }
if (r_struct_name) {
*r_struct_name = p_block->variables[p_identifier].struct_name;
}
-
+ if (r_constant_value) {
+ *r_constant_value = p_block->variables[p_identifier].value;
+ }
+ if (r_type) {
+ *r_type = IDENTIFIER_LOCAL_VAR;
+ }
return true;
}
@@ -990,15 +1043,18 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_data_type) {
*r_data_type = function->arguments[i].type;
}
- if (r_type) {
- *r_type = IDENTIFIER_FUNCTION_ARGUMENT;
- }
if (r_struct_name) {
*r_struct_name = function->arguments[i].type_str;
}
+ if (r_array_size) {
+ *r_array_size = function->arguments[i].array_size;
+ }
if (r_is_const) {
*r_is_const = function->arguments[i].is_const;
}
+ if (r_type) {
+ *r_type = IDENTIFIER_FUNCTION_ARGUMENT;
+ }
return true;
}
}
@@ -1021,6 +1077,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_data_type) {
*r_data_type = shader->uniforms[p_identifier].type;
}
+ if (r_array_size) {
+ *r_array_size = shader->uniforms[p_identifier].array_size;
+ }
if (r_type) {
*r_type = IDENTIFIER_UNIFORM;
}
@@ -1028,18 +1087,26 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
}
if (shader->constants.has(p_identifier)) {
+ if (r_is_const) {
+ *r_is_const = true;
+ }
if (r_data_type) {
*r_data_type = shader->constants[p_identifier].type;
}
if (r_array_size) {
*r_array_size = shader->constants[p_identifier].array_size;
}
- if (r_type) {
- *r_type = IDENTIFIER_CONSTANT;
- }
if (r_struct_name) {
*r_struct_name = shader->constants[p_identifier].type_str;
}
+ if (r_constant_value) {
+ if (shader->constants[p_identifier].initializer && shader->constants[p_identifier].initializer->values.size() == 1) {
+ *r_constant_value = shader->constants[p_identifier].initializer->values[0];
+ }
+ }
+ if (r_type) {
+ *r_type = IDENTIFIER_CONSTANT;
+ }
return true;
}
@@ -1052,6 +1119,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_data_type) {
*r_data_type = shader->functions[i].function->return_type;
}
+ if (r_array_size) {
+ *r_array_size = shader->functions[i].function->return_array_size;
+ }
if (r_type) {
*r_type = IDENTIFIER_FUNCTION;
}
@@ -1062,13 +1132,18 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
return false;
}
-bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type) {
+bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type, int *r_ret_size) {
bool valid = false;
DataType ret_type = TYPE_VOID;
+ int ret_size = 0;
switch (p_op->op) {
case OP_EQUAL:
case OP_NOT_EQUAL: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
valid = na == nb;
@@ -1078,6 +1153,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_LESS_EQUAL:
case OP_GREATER:
case OP_GREATER_EQUAL: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1087,6 +1166,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} break;
case OP_AND:
case OP_OR: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1095,6 +1178,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} break;
case OP_NOT: {
+ if (!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
valid = na == TYPE_BOOL;
ret_type = TYPE_BOOL;
@@ -1105,6 +1192,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_POST_INCREMENT:
case OP_POST_DECREMENT:
case OP_NEGATE: {
+ if (!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
valid = na > TYPE_BOOL && na < TYPE_MAT2;
ret_type = na;
@@ -1113,6 +1204,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_SUB:
case OP_MUL:
case OP_DIV: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1181,6 +1276,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
* component-wise.
*/
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1233,6 +1332,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_ASSIGN_SHIFT_RIGHT:
case OP_SHIFT_LEFT:
case OP_SHIFT_RIGHT: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1281,6 +1384,18 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
}
} break;
case OP_ASSIGN: {
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[0]->is_indexed()) {
+ sa = p_op->arguments[0]->get_array_size();
+ }
+ if (!p_op->arguments[1]->is_indexed()) {
+ sb = p_op->arguments[1]->get_array_size();
+ }
+ if (sa != sb) {
+ break; // don't accept arrays if their sizes are not equal
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
if (na == TYPE_STRUCT || nb == TYPE_STRUCT) {
@@ -1289,16 +1404,29 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
valid = na == nb;
}
ret_type = na;
+ ret_size = sa;
} break;
case OP_ASSIGN_ADD:
case OP_ASSIGN_SUB:
case OP_ASSIGN_MUL:
case OP_ASSIGN_DIV: {
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[0]->is_indexed()) {
+ sa = p_op->arguments[0]->get_array_size();
+ }
+ if (!p_op->arguments[1]->is_indexed()) {
+ sb = p_op->arguments[1]->get_array_size();
+ }
+ if (sa > 0 || sb > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
if (na == nb) {
- valid = (na > TYPE_BOOL && na < TYPE_MAT2) || (p_op->op == OP_ASSIGN_MUL && na >= TYPE_MAT2 && na <= TYPE_MAT4);
+ valid = (na > TYPE_BOOL && na <= TYPE_MAT4);
ret_type = na;
} else if (na == TYPE_IVEC2 && nb == TYPE_INT) {
valid = true;
@@ -1361,6 +1489,18 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
* must match.
*/
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[0]->is_indexed()) {
+ sa = p_op->arguments[0]->get_array_size();
+ }
+ if (!p_op->arguments[1]->is_indexed()) {
+ sb = p_op->arguments[1]->get_array_size();
+ }
+ if (sa > 0 || sb > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1415,17 +1555,34 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
}
} break;
case OP_BIT_INVERT: { //unaries
+ if (!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
valid = na >= TYPE_INT && na < TYPE_FLOAT;
ret_type = na;
} break;
case OP_SELECT_IF: {
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[1]->is_indexed()) {
+ sa = p_op->arguments[1]->get_array_size();
+ }
+ if (!p_op->arguments[2]->is_indexed()) {
+ sb = p_op->arguments[2]->get_array_size();
+ }
+ if (sa != sb) {
+ break; // don't accept arrays if their sizes are not equal
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
DataType nc = p_op->arguments[2]->get_datatype();
valid = na == TYPE_BOOL && (nb == nc);
ret_type = nb;
+ ret_size = sa;
} break;
default: {
ERR_FAIL_V(false);
@@ -1435,735 +1592,1066 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
if (r_ret_type) {
*r_ret_type = ret_type;
}
+ if (r_ret_size) {
+ *r_ret_size = ret_size;
+ }
return valid;
}
const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
- //constructors
- { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC3, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "mat2", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat3", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat4", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "mat2", TYPE_MAT2, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat3", TYPE_MAT3, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat4", TYPE_MAT4, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- //conversion scalars
-
- { "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "int", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "float", TYPE_FLOAT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "float", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false },
- { "bool", TYPE_BOOL, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- //conversion vectors
-
- { "ivec2", TYPE_IVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec2", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec2", TYPE_IVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec2", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "vec2", TYPE_VEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec2", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "vec2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "bvec2", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec2", TYPE_BVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "bvec2", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "ivec3", TYPE_IVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "ivec3", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "vec3", TYPE_VEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "vec3", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "bvec3", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "bvec3", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "ivec4", TYPE_IVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "ivec4", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "vec4", TYPE_VEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "vec4", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "bvec4", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- //conversion between matrixes
-
- { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat3", TYPE_MAT3, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat3", TYPE_MAT3, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
-
- //builtins - trigonometry
-
- { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "sin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "cos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "cos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "cos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "cos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "tan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "tan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "tan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "tan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "asin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "asin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "asin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "asin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "acos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "acos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "acos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "acos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "sinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "sinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "sinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "sinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "cosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "cosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "cosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "cosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "tanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "tanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- //builtins - exponential
- { "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "pow", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "pow", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "log", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- //builtins - common
- { "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "abs", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "sign", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "sign", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "floor", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "floor", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "floor", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "floor", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "trunc", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "trunc", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "trunc", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "trunc", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "round", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "ceil", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "fract", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "fract", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "fract", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "fract", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "mod", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "min", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "max", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "clamp", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
- { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC2, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "step", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- //builtins - geometric
- { "length", TYPE_FLOAT, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "length", TYPE_FLOAT, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "length", TYPE_FLOAT, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "distance", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "distance", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "distance", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "dot", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "dot", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "dot", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "cross", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "normalize", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "normalize", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "normalize", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
- { "matrixCompMult", TYPE_MAT4, { TYPE_MAT4, TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "outerProduct", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "outerProduct", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "outerProduct", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "transpose", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "transpose", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
- { "transpose", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "determinant", TYPE_FLOAT, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "determinant", TYPE_FLOAT, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
- { "determinant", TYPE_FLOAT, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "inverse", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false },
- { "inverse", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false },
- { "inverse", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "lessThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "lessThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "greaterThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "greaterThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "lessThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "lessThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "equal", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "equal", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "equal", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "notEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "notEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "notEqual", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "any", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "any", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "any", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "all", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "not", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "not", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "not", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false },
-
- //builtins - texture
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
- { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
- { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
-
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
-
- //sub-functions
-
- //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 }
+ // Constructors.
+
+ { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC3, TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+
+ { "mat2", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat3", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat4", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "mat2", TYPE_MAT2, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat3", TYPE_MAT3, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat4", TYPE_MAT4, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ // Conversion scalars.
+
+ { "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "int", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "float", TYPE_FLOAT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "float", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+
+ { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bool", TYPE_BOOL, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ // Conversion vectors.
+
+ { "ivec2", TYPE_IVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec2", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec2", TYPE_IVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec2", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "vec2", TYPE_VEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec2", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+
+ { "bvec2", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec2", TYPE_BVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec2", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "ivec3", TYPE_IVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "ivec3", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "vec3", TYPE_VEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec3", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+
+ { "bvec3", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec3", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "ivec4", TYPE_IVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "ivec4", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "vec4", TYPE_VEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec4", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+
+ { "bvec4", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ // Conversion between matrixes.
+
+ { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat3", TYPE_MAT3, { TYPE_MAT2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat3", TYPE_MAT3, { TYPE_MAT4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+
+ // Built-ins - trigonometric functions.
+ // radians
+
+ { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
+ { "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
+ { "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
+ { "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "degrees" }, TAG_GLOBAL, false },
+
+ // degrees
+
+ { "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
+ { "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
+ { "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
+ { "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "radians" }, TAG_GLOBAL, false },
+
+ // sin
+
+ { "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "sin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+
+ // cos
+
+ { "cos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "cos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "cos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "cos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+
+ // tan
+
+ { "tan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "tan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "tan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+ { "tan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "angle" }, TAG_GLOBAL, false },
+
+ // asin
+
+ { "asin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // acos
+
+ { "acos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // atan
+
+ { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "y_over_x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false },
+ { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "y", "x" }, TAG_GLOBAL, false },
+
+ // sinh
+
+ { "sinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // cosh
+
+ { "cosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "cosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "cosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "cosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // tanh
+
+ { "tanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "tanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // asinh
+
+ { "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // acosh
+
+ { "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // atanh
+
+ { "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // Builtins - exponential functions.
+ // pow
+
+ { "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "pow", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "pow", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+
+ // exp
+
+ { "exp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // log
+
+ { "log", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // exp2
+
+ { "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // log2
+
+ { "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // sqrt
+
+ { "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // inversesqrt
+
+ { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // Built-ins - common functions.
+ // abs
+
+ { "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "abs", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // sign
+
+ { "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ { "sign", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "sign", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // floor
+
+ { "floor", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floor", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floor", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floor", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // trunc
+
+ { "trunc", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "trunc", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "trunc", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "trunc", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // round
+
+ { "round", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // roundEven
+
+ { "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // ceil
+
+ { "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "ceil", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // fract
+
+ { "fract", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "fract", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "fract", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "fract", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // mod
+
+ { "mod", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+ { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "x", "y" }, TAG_GLOBAL, false },
+
+ // modf
+
+ { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+ { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+ { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+ { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+
+ // min
+
+ { "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "min", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ // max
+
+ { "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "max", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ // clamp
+
+ { "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+
+ { "clamp", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+
+ { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+
+ // mix
+
+ { "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+ { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "value" }, TAG_GLOBAL, false },
+
+ // step
+
+ { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC2, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+ { "step", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, { "edge", "x" }, TAG_GLOBAL, false },
+
+ // smoothstep
+
+ { "smoothstep", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+ { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, { "edge0", "edge1", "value" }, TAG_GLOBAL, false },
+
+ // isnan
+
+ { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // isinf
+
+ { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // floatBitsToInt
+
+ { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+
+ // floatBitsToUint
+
+ { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+
+ // intBitsToFloat
+
+ { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+
+ // uintBitsToFloat
+
+ { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+
+ // Built-ins - geometric functions.
+ // length
+
+ { "length", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "length", TYPE_FLOAT, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "length", TYPE_FLOAT, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "length", TYPE_FLOAT, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // distance
+
+ { "distance", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "distance", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "distance", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "distance", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ // dot
+
+ { "dot", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "dot", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "dot", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "dot", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ // cross
+
+ { "cross", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ // normalize
+
+ { "normalize", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "normalize", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "normalize", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "normalize", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+
+ // reflect
+
+ { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
+
+ // refract
+
+ { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
+
+ // faceforward
+
+ { "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false },
+ { "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false },
+ { "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "N", "I", "Nref" }, TAG_GLOBAL, false },
+
+ // matrixCompMult
+
+ { "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "matrixCompMult", TYPE_MAT4, { TYPE_MAT4, TYPE_MAT4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ // outerProduct
+
+ { "outerProduct", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false },
+ { "outerProduct", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false },
+ { "outerProduct", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "c", "r" }, TAG_GLOBAL, false },
+
+ // transpose
+
+ { "transpose", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "transpose", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "transpose", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+
+ // determinant
+
+ { "determinant", TYPE_FLOAT, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "determinant", TYPE_FLOAT, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "determinant", TYPE_FLOAT, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+
+ // inverse
+
+ { "inverse", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "inverse", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+ { "inverse", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, { "m" }, TAG_GLOBAL, false },
+
+ // lessThan
+
+ { "lessThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "lessThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ // greaterThan
+
+ { "greaterThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "greaterThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ // lessThanEqual
+
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ // greaterThanEqual
+
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ // equal
+
+ { "equal", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "equal", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ { "equal", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ // notEqual
+
+ { "notEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "notEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+
+ { "notEqual", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+
+ // any
+
+ { "any", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "any", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "any", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // all
+
+ { "all", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // not
+
+ { "not", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "not", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "not", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+
+ // Built-ins: texture functions.
+ // textureSize
+
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+
+ // texture
+
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+
+ // textureProj
+
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+
+ // textureLod
+
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+
+ // texelFetch
+
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+
+ // textureProjLod
+
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+
+ // textureGrad
+
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+
+ // textureGather
+
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+
+ // dFdx
+
+ { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
+ // dFdy
+
+ { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
+ // fwidth
+
+ { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
+ // Sub-functions.
+ // array
+
+ { "length", TYPE_INT, { TYPE_VOID }, { "" }, TAG_ARRAY, true },
+
+ // Modern functions.
+ // fma
+
+ { "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
+ { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
+ { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
+ { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false },
+
+ // Packing/Unpacking functions.
+
+ { "packHalf2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "packUnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "packSnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "packUnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "packSnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+
+ { "unpackHalf2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "unpackUnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "unpackSnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "unpackUnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "unpackSnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+
+ // bitfieldExtract
+
+ { "bitfieldExtract", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+
+ { "bitfieldExtract", TYPE_UINT, { TYPE_UINT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_UVEC2, { TYPE_UVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_UVEC3, { TYPE_UVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldExtract", TYPE_UVEC4, { TYPE_UVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "value", "offset", "bits" }, TAG_GLOBAL, true },
+
+ // bitfieldInsert
+
+ { "bitfieldInsert", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+
+ { "bitfieldInsert", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+ { "bitfieldInsert", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "base", "insert", "offset", "bits" }, TAG_GLOBAL, true },
+
+ // bitfieldReverse
+
+ { "bitfieldReverse", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ { "bitfieldReverse", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitfieldReverse", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ // bitCount
+
+ { "bitCount", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ { "bitCount", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "bitCount", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ // findLSB
+ { "findLSB", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ { "findLSB", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findLSB", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ // findMSB
+
+ { "findMSB", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ { "findMSB", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ { "findMSB", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+
+ // umulExtended
+
+ { "umulExtended", TYPE_VOID, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "umulExtended", TYPE_VOID, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "umulExtended", TYPE_VOID, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "umulExtended", TYPE_VOID, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+
+ // imulExtended
+
+ { "imulExtended", TYPE_VOID, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "imulExtended", TYPE_VOID, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "imulExtended", TYPE_VOID, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "imulExtended", TYPE_VOID, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+
+ // uaddCarry
+
+ { "uaddCarry", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true },
+ { "uaddCarry", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true },
+ { "uaddCarry", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true },
+ { "uaddCarry", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true },
+
+ // usubBorrow
+
+ { "usubBorrow", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true },
+ { "usubBorrow", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true },
+ { "usubBorrow", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true },
+ { "usubBorrow", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true },
+
+ // ldexp
+
+ { "ldexp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_INT, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "ldexp", TYPE_VEC2, { TYPE_VEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "ldexp", TYPE_VEC3, { TYPE_VEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "ldexp", TYPE_VEC4, { TYPE_VEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+
+ // frexp
+
+ { "frexp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_INT, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "frexp", TYPE_VEC2, { TYPE_VEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "frexp", TYPE_VEC3, { TYPE_VEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "frexp", TYPE_VEC4, { TYPE_VEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+
+ { nullptr, TYPE_VOID, { TYPE_VOID }, { "" }, TAG_GLOBAL, false }
};
const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = {
- //constructors
- { "modf", 1 },
- { nullptr, 0 }
+ { "modf", { 1, -1 } },
+ { "umulExtended", { 2, 3 } },
+ { "imulExtended", { 2, 3 } },
+ { "uaddCarry", { 2, -1 } },
+ { "usubBorrow", { 2, -1 } },
+ { "ldexp", { 1, -1 } },
+ { "frexp", { 1, -1 } },
+ { nullptr, { 0, -1 } }
+};
+
+const ShaderLanguage::BuiltinFuncConstArgs ShaderLanguage::builtin_func_const_args[] = {
+ { "textureGather", 2, 0, 3 },
+ { nullptr, 0, 0, 0 }
};
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) {
@@ -2171,6 +2659,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
Vector<DataType> args;
Vector<StringName> args2;
+ Vector<int> args3;
ERR_FAIL_COND_V(p_func->arguments[0]->type != Node::TYPE_VARIABLE, false);
@@ -2179,6 +2668,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
for (int i = 1; i < p_func->arguments.size(); i++) {
args.push_back(p_func->arguments[i]->get_datatype());
args2.push_back(p_func->arguments[i]->get_datatype_name());
+ args3.push_back(p_func->arguments[i]->get_array_size());
}
int argcount = args.size();
@@ -2225,6 +2715,13 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
failed_builtin = true;
bool fail = false;
for (int i = 0; i < argcount; i++) {
+ if (p_func->arguments[i + 1]->type == Node::TYPE_ARRAY) {
+ const ArrayNode *anode = static_cast<const ArrayNode *>(p_func->arguments[i + 1]);
+ if (anode->call_expression == nullptr && !anode->is_indexed()) {
+ fail = true;
+ break;
+ }
+ }
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, but needs implicit conversion later
} else if (args[i] != builtin_func_defs[idx].args[i]) {
@@ -2248,96 +2745,153 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
if (!fail) {
- //make sure its not an out argument used in the wrong way
- int outarg_idx = 0;
- while (builtin_func_out_args[outarg_idx].name) {
- if (String(name) == builtin_func_out_args[outarg_idx].name) {
- int arg_idx = builtin_func_out_args[outarg_idx].argument;
-
- if (arg_idx < argcount) {
- if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) {
- _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
- return false;
+ {
+ int constarg_idx = 0;
+ while (builtin_func_const_args[constarg_idx].name) {
+ if (String(name) == builtin_func_const_args[constarg_idx].name) {
+ int arg = builtin_func_const_args[constarg_idx].arg + 1;
+ if (p_func->arguments.size() <= arg) {
+ break;
}
- if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
- ArrayNode *mn = static_cast<ArrayNode *>(p_func->arguments[arg_idx + 1]);
- if (mn->is_const) {
- fail = true;
- }
- } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
- MemberNode *mn = static_cast<MemberNode *>(p_func->arguments[arg_idx + 1]);
- if (mn->basetype_const) {
- fail = true;
+ int min = builtin_func_const_args[constarg_idx].min;
+ int max = builtin_func_const_args[constarg_idx].max;
+
+ bool error = false;
+ if (p_func->arguments[arg]->type == Node::TYPE_VARIABLE) {
+ const VariableNode *vn = (VariableNode *)p_func->arguments[arg];
+
+ 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) {
+ error = true;
}
- } else { // TYPE_VARIABLE
- VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg_idx + 1]);
- if (vn->is_const) {
- fail = true;
- } else {
- StringName varname = vn->name;
- if (shader->uniforms.has(varname)) {
- fail = true;
- } else {
- if (p_function_info.built_ins.has(varname)) {
- BuiltInInfo info = p_function_info.built_ins[varname];
- if (info.constant) {
- fail = true;
- }
+ } else {
+ if (p_func->arguments[arg]->type == Node::TYPE_CONSTANT) {
+ ConstantNode *cn = (ConstantNode *)p_func->arguments[arg];
+
+ if (cn->get_datatype() == TYPE_INT && cn->values.size() == 1) {
+ int value = cn->values[0].sint;
+
+ if (value < min || value > max) {
+ error = true;
}
+ } else {
+ error = true;
}
+ } else {
+ error = true;
}
}
- if (fail) {
- _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out"));
+ if (error) {
+ _set_error(vformat("Expected integer constant within %s..%s range.", min, max));
return false;
}
+ }
+ constarg_idx++;
+ }
+ }
- StringName var_name;
- if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
- var_name = static_cast<const ArrayNode *>(p_func->arguments[arg_idx + 1])->name;
- } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
- Node *n = static_cast<const MemberNode *>(p_func->arguments[arg_idx + 1])->owner;
- while (n->type == Node::TYPE_MEMBER) {
- n = static_cast<const MemberNode *>(n)->owner;
- }
- if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) {
+ //make sure its not an out argument used in the wrong way
+ int outarg_idx = 0;
+ while (builtin_func_out_args[outarg_idx].name) {
+ if (String(name) == builtin_func_out_args[outarg_idx].name) {
+ for (int arg = 0; arg < BuiltinFuncOutArgs::MAX_ARGS; arg++) {
+ int arg_idx = builtin_func_out_args[outarg_idx].arguments[arg];
+ if (arg_idx == -1) {
+ break;
+ }
+ if (arg_idx < argcount) {
+ if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) {
_set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
return false;
}
- if (n->type == Node::TYPE_VARIABLE) {
- var_name = static_cast<const VariableNode *>(n)->name;
- } else { // TYPE_ARRAY
- var_name = static_cast<const ArrayNode *>(n)->name;
+
+ if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
+ ArrayNode *mn = static_cast<ArrayNode *>(p_func->arguments[arg_idx + 1]);
+ if (mn->is_const) {
+ fail = true;
+ }
+ } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
+ MemberNode *mn = static_cast<MemberNode *>(p_func->arguments[arg_idx + 1]);
+ if (mn->basetype_const) {
+ fail = true;
+ }
+ } else { // TYPE_VARIABLE
+ VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg_idx + 1]);
+ if (vn->is_const) {
+ fail = true;
+ } else {
+ StringName varname = vn->name;
+ if (shader->uniforms.has(varname)) {
+ fail = true;
+ } else {
+ if (shader->varyings.has(varname)) {
+ _set_error(vformat("Varyings cannot be passed for '%s' parameter!", "out"));
+ return false;
+ }
+ if (p_function_info.built_ins.has(varname)) {
+ BuiltInInfo info = p_function_info.built_ins[varname];
+ if (info.constant) {
+ fail = true;
+ }
+ }
+ }
+ }
}
- } else { // TYPE_VARIABLE
- var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
- }
- const BlockNode *b = p_block;
- bool valid = false;
- while (b) {
- if (b->variables.has(var_name) || p_function_info.built_ins.has(var_name)) {
- valid = true;
- break;
+ if (fail) {
+ _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out"));
+ return false;
}
- if (b->parent_function) {
- for (int i = 0; i < b->parent_function->arguments.size(); i++) {
- if (b->parent_function->arguments[i].name == var_name) {
- valid = true;
- break;
+
+ StringName var_name;
+ if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
+ var_name = static_cast<const ArrayNode *>(p_func->arguments[arg_idx + 1])->name;
+ } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
+ Node *n = static_cast<const MemberNode *>(p_func->arguments[arg_idx + 1])->owner;
+ while (n->type == Node::TYPE_MEMBER) {
+ n = static_cast<const MemberNode *>(n)->owner;
+ }
+ if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
+ return false;
+ }
+ if (n->type == Node::TYPE_VARIABLE) {
+ var_name = static_cast<const VariableNode *>(n)->name;
+ } else { // TYPE_ARRAY
+ var_name = static_cast<const ArrayNode *>(n)->name;
+ }
+ } else { // TYPE_VARIABLE
+ var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
+ }
+ const BlockNode *b = p_block;
+ bool valid = false;
+ while (b) {
+ if (b->variables.has(var_name) || p_function_info.built_ins.has(var_name)) {
+ valid = true;
+ break;
+ }
+ if (b->parent_function) {
+ for (int i = 0; i < b->parent_function->arguments.size(); i++) {
+ if (b->parent_function->arguments[i].name == var_name) {
+ valid = true;
+ break;
+ }
}
}
+ b = b->parent_block;
}
- b = b->parent_block;
- }
- if (!valid) {
- _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member.");
- return false;
+ if (!valid) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member.");
+ return false;
+ }
}
}
}
-
outarg_idx++;
}
//implicitly convert values if possible
@@ -2397,6 +2951,11 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
} else {
arg_name = get_datatype_name(args[i]);
}
+ if (args3[i] > 0) {
+ arg_name += "[";
+ arg_name += itos(args3[i]);
+ arg_name += "]";
+ }
err += arg_name;
}
err += ")";
@@ -2446,6 +3005,11 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
} else {
func_arg_name = get_datatype_name(pfunc->arguments[j].type);
}
+ if (pfunc->arguments[j].array_size > 0) {
+ func_arg_name += "[";
+ func_arg_name += itos(pfunc->arguments[j].array_size);
+ func_arg_name += "]";
+ }
arg_list += func_arg_name;
}
}
@@ -2458,21 +3022,32 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
bool fail = false;
for (int j = 0; j < args.size(); j++) {
- 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)) {
+ if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && args3[j] == 0 && 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 || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str)) {
+ } else if (args[j] != pfunc->arguments[j].type || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str) || args3[j] != pfunc->arguments[j].array_size) {
String func_arg_name;
if (pfunc->arguments[j].type == TYPE_STRUCT) {
func_arg_name = pfunc->arguments[j].type_str;
} else {
func_arg_name = get_datatype_name(pfunc->arguments[j].type);
}
+ if (pfunc->arguments[j].array_size > 0) {
+ func_arg_name += "[";
+ func_arg_name += itos(pfunc->arguments[j].array_size);
+ func_arg_name += "]";
+ }
String arg_name;
if (args[j] == TYPE_STRUCT) {
arg_name = args2[j];
} else {
arg_name = get_datatype_name(args[j]);
}
+ if (args3[j] > 0) {
+ arg_name += "[";
+ arg_name += itos(args3[j]);
+ arg_name += "]";
+ }
+
_set_error(vformat("Invalid argument for \"%s(%s)\" function: argument %s should be %s but is %s.", String(name), arg_list, j + 1, func_arg_name, arg_name));
fail = true;
break;
@@ -2518,16 +3093,45 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
return false;
}
-bool ShaderLanguage::_compare_datatypes_in_nodes(Node *a, Node *b) const {
- if (a->get_datatype() != b->get_datatype()) {
- return false;
+bool ShaderLanguage::_compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b) {
+ bool result = true;
+
+ if (p_datatype_a == TYPE_STRUCT || p_datatype_b == TYPE_STRUCT) {
+ if (p_datatype_name_a != p_datatype_name_b) {
+ result = false;
+ }
+ } else {
+ if (p_datatype_a != p_datatype_b) {
+ result = false;
+ }
}
- if (a->get_datatype() == TYPE_STRUCT || b->get_datatype() == TYPE_STRUCT) {
- if (a->get_datatype_name() != b->get_datatype_name()) {
- return false;
+
+ if (p_array_size_a != p_array_size_b) {
+ result = false;
+ }
+
+ if (!result) {
+ String type_name = p_datatype_a == TYPE_STRUCT ? p_datatype_name_a : get_datatype_name(p_datatype_a);
+ if (p_array_size_a > 0) {
+ type_name += "[";
+ type_name += itos(p_array_size_a);
+ type_name += "]";
+ }
+
+ String type_name2 = p_datatype_b == TYPE_STRUCT ? p_datatype_name_b : get_datatype_name(p_datatype_b);
+ if (p_array_size_b > 0) {
+ type_name2 += "[";
+ type_name2 += itos(p_array_size_b);
+ type_name2 += "]";
}
+
+ _set_error("Invalid assignment of '" + type_name2 + "' to '" + type_name + "'");
}
- return true;
+ return result;
+}
+
+bool ShaderLanguage::_compare_datatypes_in_nodes(Node *a, Node *b) {
+ return _compare_datatypes(a->get_datatype(), a->get_datatype_name(), a->get_array_size(), b->get_datatype(), b->get_datatype_name(), b->get_array_size());
}
bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, int *r_complete_arg) {
@@ -2612,6 +3216,20 @@ bool ShaderLanguage::is_token_operator(TokenType p_type) {
p_type == TK_COLON);
}
+bool ShaderLanguage::is_token_operator_assign(TokenType p_type) {
+ return (p_type == TK_OP_ASSIGN ||
+ p_type == TK_OP_ASSIGN_ADD ||
+ p_type == TK_OP_ASSIGN_SUB ||
+ p_type == TK_OP_ASSIGN_MUL ||
+ p_type == TK_OP_ASSIGN_DIV ||
+ p_type == TK_OP_ASSIGN_MOD ||
+ p_type == TK_OP_ASSIGN_SHIFT_LEFT ||
+ p_type == TK_OP_ASSIGN_SHIFT_RIGHT ||
+ p_type == TK_OP_ASSIGN_BIT_AND ||
+ p_type == TK_OP_ASSIGN_BIT_OR ||
+ p_type == TK_OP_ASSIGN_BIT_XOR);
+}
+
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) {
@@ -2655,100 +3273,329 @@ bool ShaderLanguage::is_scalar_type(DataType p_type) {
return p_type == TYPE_BOOL || p_type == TYPE_INT || p_type == TYPE_UINT || p_type == TYPE_FLOAT;
}
+bool ShaderLanguage::is_float_type(DataType p_type) {
+ switch (p_type) {
+ case TYPE_FLOAT:
+ case TYPE_VEC2:
+ case TYPE_VEC3:
+ case TYPE_VEC4:
+ case TYPE_MAT2:
+ case TYPE_MAT3:
+ case TYPE_MAT4:
+ case TYPE_SAMPLER2D:
+ case TYPE_SAMPLER2DARRAY:
+ case TYPE_SAMPLER3D:
+ case TYPE_SAMPLERCUBE:
+ case TYPE_SAMPLERCUBEARRAY: {
+ return true;
+ }
+ default: {
+ return false;
+ }
+ }
+}
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, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
+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) {
+ int array_size = p_array_size;
+
if (p_value.size() > 0) {
Variant value;
switch (p_type) {
case ShaderLanguage::TYPE_BOOL:
- value = Variant(p_value[0].boolean);
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].boolean);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].boolean);
+ }
break;
case ShaderLanguage::TYPE_BVEC2:
+ array_size *= 2;
+
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].boolean);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].boolean);
+ }
+ break;
case ShaderLanguage::TYPE_BVEC3:
+ array_size *= 3;
+
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].boolean);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].boolean);
+ }
+ break;
case ShaderLanguage::TYPE_BVEC4:
+ array_size *= 4;
+
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].boolean);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].boolean);
+ }
+ break;
case ShaderLanguage::TYPE_INT:
- value = Variant(p_value[0].sint);
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].sint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].sint);
+ }
break;
case ShaderLanguage::TYPE_IVEC2:
- value = Variant(Vector2(p_value[0].sint, p_value[1].sint));
+ if (array_size > 0) {
+ array_size *= 2;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].sint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector2(p_value[0].sint, p_value[1].sint));
+ }
break;
case ShaderLanguage::TYPE_IVEC3:
- value = Variant(Vector3(p_value[0].sint, p_value[1].sint, p_value[2].sint));
+ if (array_size > 0) {
+ array_size *= 3;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].sint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector3(p_value[0].sint, p_value[1].sint, p_value[2].sint));
+ }
break;
case ShaderLanguage::TYPE_IVEC4:
- value = Variant(Plane(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint));
+ if (array_size > 0) {
+ array_size *= 4;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].sint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Plane(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint));
+ }
break;
case ShaderLanguage::TYPE_UINT:
- value = Variant(p_value[0].uint);
+ if (array_size > 0) {
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].uint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].uint);
+ }
break;
case ShaderLanguage::TYPE_UVEC2:
- value = Variant(Vector2(p_value[0].uint, p_value[1].uint));
+ if (array_size > 0) {
+ array_size *= 2;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].uint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector2(p_value[0].uint, p_value[1].uint));
+ }
break;
case ShaderLanguage::TYPE_UVEC3:
- value = Variant(Vector3(p_value[0].uint, p_value[1].uint, p_value[2].uint));
+ if (array_size > 0) {
+ array_size *= 3;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].uint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector3(p_value[0].uint, p_value[1].uint, p_value[2].uint));
+ }
break;
case ShaderLanguage::TYPE_UVEC4:
- value = Variant(Plane(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint));
+ if (array_size > 0) {
+ array_size *= 4;
+
+ PackedInt32Array array = PackedInt32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].uint);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Plane(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint));
+ }
break;
case ShaderLanguage::TYPE_FLOAT:
- value = Variant(p_value[0].real);
+ if (array_size > 0) {
+ PackedFloat32Array array = PackedFloat32Array();
+ for (int i = 0; i < array_size; i++) {
+ array.push_back(p_value[i].real);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(p_value[0].real);
+ }
break;
case ShaderLanguage::TYPE_VEC2:
- value = Variant(Vector2(p_value[0].real, p_value[1].real));
+ if (array_size > 0) {
+ array_size *= 2;
+
+ PackedVector2Array array = PackedVector2Array();
+ for (int i = 0; i < array_size; i += 2) {
+ array.push_back(Vector2(p_value[i].real, p_value[i + 1].real));
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector2(p_value[0].real, p_value[1].real));
+ }
break;
case ShaderLanguage::TYPE_VEC3:
- value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real));
+ if (array_size > 0) {
+ array_size *= 3;
+
+ PackedVector3Array array = PackedVector3Array();
+ for (int i = 0; i < array_size; i += 3) {
+ array.push_back(Vector3(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real));
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real));
+ }
break;
case ShaderLanguage::TYPE_VEC4:
- if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
- value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ if (array_size > 0) {
+ array_size *= 4;
+
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ PackedColorArray array = PackedColorArray();
+ for (int i = 0; i < array_size; i += 4) {
+ array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real, p_value[i + 3].real));
+ }
+ value = Variant(array);
+ } else {
+ PackedFloat32Array array = PackedFloat32Array();
+ for (int i = 0; i < array_size; i += 4) {
+ array.push_back(p_value[i].real);
+ array.push_back(p_value[i + 1].real);
+ array.push_back(p_value[i + 2].real);
+ array.push_back(p_value[i + 3].real);
+ }
+ value = Variant(array);
+ }
} else {
- value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ } else {
+ value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ }
}
break;
case ShaderLanguage::TYPE_MAT2:
- value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0));
+ if (array_size > 0) {
+ array_size *= 4;
+
+ PackedFloat32Array array = PackedFloat32Array();
+ for (int i = 0; i < array_size; i += 4) {
+ array.push_back(p_value[i].real);
+ array.push_back(p_value[i + 1].real);
+ array.push_back(p_value[i + 2].real);
+ array.push_back(p_value[i + 3].real);
+ }
+ value = Variant(array);
+ } else {
+ value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0));
+ }
break;
case ShaderLanguage::TYPE_MAT3: {
- Basis p;
- p[0][0] = p_value[0].real;
- p[0][1] = p_value[1].real;
- p[0][2] = p_value[2].real;
- p[1][0] = p_value[3].real;
- p[1][1] = p_value[4].real;
- p[1][2] = p_value[5].real;
- p[2][0] = p_value[6].real;
- p[2][1] = p_value[7].real;
- p[2][2] = p_value[8].real;
- value = Variant(p);
+ if (array_size > 0) {
+ array_size *= 9;
+
+ PackedFloat32Array array = PackedFloat32Array();
+ for (int i = 0; i < array_size; i += 9) {
+ for (int j = 0; j < 9; j++) {
+ array.push_back(p_value[i + j].real);
+ }
+ }
+ value = Variant(array);
+ } else {
+ Basis p;
+ p[0][0] = p_value[0].real;
+ p[0][1] = p_value[1].real;
+ p[0][2] = p_value[2].real;
+ p[1][0] = p_value[3].real;
+ p[1][1] = p_value[4].real;
+ p[1][2] = p_value[5].real;
+ p[2][0] = p_value[6].real;
+ p[2][1] = p_value[7].real;
+ p[2][2] = p_value[8].real;
+ value = Variant(p);
+ }
break;
}
case ShaderLanguage::TYPE_MAT4: {
- Basis p;
- p[0][0] = p_value[0].real;
- p[0][1] = p_value[1].real;
- p[0][2] = p_value[2].real;
- p[1][0] = p_value[4].real;
- p[1][1] = p_value[5].real;
- p[1][2] = p_value[6].real;
- p[2][0] = p_value[8].real;
- p[2][1] = p_value[9].real;
- p[2][2] = p_value[10].real;
- Transform t = Transform(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real));
- value = Variant(t);
+ if (array_size > 0) {
+ array_size *= 16;
+
+ PackedFloat32Array array = PackedFloat32Array();
+ for (int i = 0; i < array_size; i += 16) {
+ for (int j = 0; j < 16; j++) {
+ array.push_back(p_value[i + j].real);
+ }
+ }
+ value = Variant(array);
+ } else {
+ Basis p;
+ p[0][0] = p_value[0].real;
+ p[0][1] = p_value[1].real;
+ p[0][2] = p_value[2].real;
+ p[1][0] = p_value[4].real;
+ p[1][1] = p_value[5].real;
+ p[1][2] = p_value[6].real;
+ p[2][0] = p_value[8].real;
+ p[2][1] = p_value[9].real;
+ p[2][2] = p_value[10].real;
+ Transform3D t = Transform3D(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real));
+ value = Variant(t);
+ }
break;
}
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
@@ -2784,31 +3631,50 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
pi.type = Variant::NIL;
break;
case ShaderLanguage::TYPE_BOOL:
- pi.type = Variant::BOOL;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::BOOL;
+ }
break;
case ShaderLanguage::TYPE_BVEC2:
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y";
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::INT;
+ pi.hint = PROPERTY_HINT_FLAGS;
+ pi.hint_string = "x,y";
+ }
break;
case ShaderLanguage::TYPE_BVEC3:
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y,z";
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::INT;
+ pi.hint = PROPERTY_HINT_FLAGS;
+ pi.hint_string = "x,y,z";
+ }
break;
case ShaderLanguage::TYPE_BVEC4:
- pi.type = Variant::INT;
- pi.hint = PROPERTY_HINT_FLAGS;
- pi.hint_string = "x,y,z,w";
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::INT;
+ pi.hint = PROPERTY_HINT_FLAGS;
+ pi.hint_string = "x,y,z,w";
+ }
break;
case ShaderLanguage::TYPE_UINT:
case ShaderLanguage::TYPE_INT: {
- pi.type = Variant::INT;
- if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
- pi.hint = PROPERTY_HINT_RANGE;
- pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]);
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::INT;
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
+ pi.hint = PROPERTY_HINT_RANGE;
+ pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]);
+ }
}
-
} break;
case ShaderLanguage::TYPE_IVEC2:
case ShaderLanguage::TYPE_IVEC3:
@@ -2819,59 +3685,106 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
pi.type = Variant::PACKED_INT32_ARRAY;
} break;
case ShaderLanguage::TYPE_FLOAT: {
- pi.type = Variant::FLOAT;
- if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
- pi.hint = PROPERTY_HINT_RANGE;
- pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]);
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_FLOAT32_ARRAY;
+ } else {
+ pi.type = Variant::FLOAT;
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
+ pi.hint = PROPERTY_HINT_RANGE;
+ pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]);
+ }
}
-
} break;
case ShaderLanguage::TYPE_VEC2:
- pi.type = Variant::VECTOR2;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_VECTOR2_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR2;
+ }
break;
case ShaderLanguage::TYPE_VEC3:
- pi.type = Variant::VECTOR3;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_VECTOR3_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR3;
+ }
break;
case ShaderLanguage::TYPE_VEC4: {
- if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
- pi.type = Variant::COLOR;
+ if (p_uniform.array_size > 0) {
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ pi.type = Variant::PACKED_COLOR_ARRAY;
+ } else {
+ pi.type = Variant::PACKED_FLOAT32_ARRAY;
+ }
} else {
- pi.type = Variant::PLANE;
+ if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ pi.type = Variant::COLOR;
+ } else {
+ pi.type = Variant::PLANE;
+ }
}
} break;
case ShaderLanguage::TYPE_MAT2:
- pi.type = Variant::TRANSFORM2D;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_FLOAT32_ARRAY;
+ } else {
+ pi.type = Variant::TRANSFORM2D;
+ }
break;
case ShaderLanguage::TYPE_MAT3:
- pi.type = Variant::BASIS;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_FLOAT32_ARRAY;
+ } else {
+ pi.type = Variant::BASIS;
+ }
break;
case ShaderLanguage::TYPE_MAT4:
- pi.type = Variant::TRANSFORM;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_FLOAT32_ARRAY;
+ } else {
+ pi.type = Variant::TRANSFORM3D;
+ }
break;
case ShaderLanguage::TYPE_SAMPLER2D:
case ShaderLanguage::TYPE_ISAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER2D: {
- pi.type = Variant::OBJECT;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::ARRAY;
+ } else {
+ pi.type = Variant::OBJECT;
+ }
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "Texture2D";
} break;
case ShaderLanguage::TYPE_SAMPLER2DARRAY:
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2DARRAY: {
- pi.type = Variant::OBJECT;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::ARRAY;
+ } else {
+ pi.type = Variant::OBJECT;
+ }
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "TextureLayered";
} break;
case ShaderLanguage::TYPE_SAMPLER3D:
case ShaderLanguage::TYPE_ISAMPLER3D:
case ShaderLanguage::TYPE_USAMPLER3D: {
- pi.type = Variant::OBJECT;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::ARRAY;
+ } else {
+ pi.type = Variant::OBJECT;
+ }
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "Texture3D";
} break;
case ShaderLanguage::TYPE_SAMPLERCUBE:
case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
- pi.type = Variant::OBJECT;
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::ARRAY;
+ } else {
+ pi.type = Variant::OBJECT;
+ }
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "TextureLayered";
} break;
@@ -2958,6 +3871,20 @@ 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";
+}
+
void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) {
Set<String> kws;
@@ -3091,6 +4018,106 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
return false;
}
+bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message) {
+ if (current_function != String("vertex") && current_function != String("fragment")) {
+ *r_message = vformat(RTR("Varying may not be assigned in the '%s' function."), current_function);
+ return false;
+ }
+ switch (p_varying.stage) {
+ case ShaderNode::Varying::STAGE_UNKNOWN: // first assign
+ if (current_function == varying_function_names.vertex) {
+ p_varying.stage = ShaderNode::Varying::STAGE_VERTEX;
+ } else if (current_function == varying_function_names.fragment) {
+ p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT:
+ case ShaderNode::Varying::STAGE_VERTEX:
+ if (current_function == varying_function_names.fragment) {
+ *r_message = RTR("Varyings which assigned in 'vertex' function may not be reassigned in 'fragment' or 'light'.");
+ return false;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT:
+ case ShaderNode::Varying::STAGE_FRAGMENT:
+ if (current_function == varying_function_names.vertex) {
+ *r_message = RTR("Varyings which assigned in 'fragment' function may not be reassigned in 'vertex' or 'light'.");
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, String *r_message) {
+ switch (p_varying.stage) {
+ case ShaderNode::Varying::STAGE_UNKNOWN:
+ VaryingUsage usage;
+ usage.var = &p_varying;
+ usage.line = tk_line;
+ unknown_varying_usages.push_back(usage);
+ break;
+ case ShaderNode::Varying::STAGE_VERTEX:
+ if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
+ p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_FRAGMENT:
+ if (current_function == varying_function_names.light) {
+ p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+bool ShaderLanguage::_check_varying_usages(int *r_error_line, String *r_error_message) const {
+ for (const List<ShaderLanguage::VaryingUsage>::Element *E = unknown_varying_usages.front(); E; E = E->next()) {
+ ShaderNode::Varying::Stage stage = E->get().var->stage;
+ if (stage != ShaderNode::Varying::STAGE_UNKNOWN && stage != ShaderNode::Varying::STAGE_VERTEX && stage != ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT) {
+ *r_error_line = E->get().line;
+ *r_error_message = RTR("Fragment-stage varying could not been accessed in custom function!");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
+ switch (p_node->type) {
+ case Node::TYPE_OPERATOR: {
+ OperatorNode *op_node = (OperatorNode *)p_node;
+ for (int i = int(op_node->op == OP_CALL); i < op_node->arguments.size(); i++) {
+ if (!_check_node_constness(op_node->arguments[i])) {
+ return false;
+ }
+ }
+ } break;
+ case Node::TYPE_CONSTANT:
+ break;
+ case Node::TYPE_VARIABLE: {
+ VariableNode *varn = (VariableNode *)p_node;
+ if (!varn->is_const) {
+ return false;
+ }
+ } break;
+ case Node::TYPE_ARRAY: {
+ ArrayNode *arrn = (ArrayNode *)p_node;
+ if (!arrn->is_const) {
+ return false;
+ }
+ } break;
+ default:
+ return false;
+ }
+ return true;
+}
+
bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message) {
if (p_node->type == Node::TYPE_OPERATOR) {
OperatorNode *op = static_cast<OperatorNode *>(p_node);
@@ -3131,13 +4158,6 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
return false;
}
- if (shader->varyings.has(var->name) && current_function != String("vertex")) {
- if (r_message) {
- *r_message = RTR("Varyings can only be assigned in vertex function.");
- }
- return false;
- }
-
if (shader->constants.has(var->name) || var->is_const) {
if (r_message) {
*r_message = RTR("Constants cannot be modified.");
@@ -3158,13 +4178,6 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
return false;
}
- if (shader->varyings.has(arr->name) && current_function != String("vertex")) {
- if (r_message) {
- *r_message = RTR("Varyings can only be assigned in vertex function.");
- }
- return false;
- }
-
return true;
}
@@ -3175,7 +4188,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
}
bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat) {
- for (int i = 0; shader->functions.size(); i++) {
+ for (int i = 0; i < shader->functions.size(); i++) {
if (shader->functions[i].name == p_name) {
ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false);
FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument];
@@ -3194,9 +4207,9 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam
arg->tex_argument_check = true;
arg->tex_argument_filter = p_filter;
arg->tex_argument_repeat = p_repeat;
- for (Map<StringName, Set<int>>::Element *E = arg->tex_argument_connect.front(); E; E = E->next()) {
- for (Set<int>::Element *F = E->get().front(); F; F = F->next()) {
- if (!_propagate_function_call_sampler_uniform_settings(E->key(), F->get(), p_filter, p_repeat)) {
+ for (KeyValue<StringName, Set<int>> &E : arg->tex_argument_connect) {
+ for (Set<int>::Element *F = E.value.front(); F; F = F->next()) {
+ if (!_propagate_function_call_sampler_uniform_settings(E.key, F->get(), p_filter, p_repeat)) {
return false;
}
}
@@ -3209,7 +4222,7 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam
}
bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin) {
- for (int i = 0; shader->functions.size(); i++) {
+ for (int i = 0; i < shader->functions.size(); i++) {
if (shader->functions[i].name == p_name) {
ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false);
FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument];
@@ -3228,9 +4241,9 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
arg->tex_builtin_check = true;
arg->tex_builtin = p_builtin;
- for (Map<StringName, Set<int>>::Element *E = arg->tex_argument_connect.front(); E; E = E->next()) {
- for (Set<int>::Element *F = E->get().front(); F; F = F->next()) {
- if (!_propagate_function_call_sampler_builtin_reference(E->key(), F->get(), p_builtin)) {
+ for (KeyValue<StringName, Set<int>> &E : arg->tex_argument_connect) {
+ for (Set<int>::Element *F = E.value.front(); F; F = F->next()) {
+ if (!_propagate_function_call_sampler_builtin_reference(E.key, F->get(), p_builtin)) {
return false;
}
}
@@ -3242,6 +4255,376 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
ERR_FAIL_V(false); //bug? function not found
}
+ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size) {
+ int array_size = 0;
+
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (n) {
+ if (n->type == Node::TYPE_VARIABLE) {
+ VariableNode *vn = static_cast<VariableNode *>(n);
+ if (vn) {
+ ConstantNode::Value v;
+ DataType data_type;
+ bool is_const = false;
+
+ _find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, &is_const, nullptr, nullptr, &v);
+
+ if (is_const) {
+ if (data_type == TYPE_INT) {
+ int32_t value = v.sint;
+ if (value > 0) {
+ array_size = value;
+ }
+ } else if (data_type == TYPE_UINT) {
+ uint32_t value = v.uint;
+ if (value > 0U) {
+ array_size = value;
+ }
+ }
+ }
+ }
+ } else if (n->type == Node::TYPE_OPERATOR) {
+ _set_error("Array size expressions are not yet implemented.");
+ return nullptr;
+ }
+ }
+
+ r_array_size = array_size;
+ return n;
+}
+
+Error ShaderLanguage::_parse_global_array_size(int &r_array_size) {
+ if (r_array_size > 0) {
+ _set_error("Array size is already defined!");
+ return ERR_PARSE_ERROR;
+ }
+ TkPos pos = _get_tkpos();
+ Token tk = _get_token();
+
+ int array_size = 0;
+
+ if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
+ _set_tkpos(pos);
+ Node *n = _parse_array_size(nullptr, FunctionInfo(), array_size);
+ if (!n) {
+ return ERR_PARSE_ERROR;
+ }
+ } else if (((int)tk.constant) > 0) {
+ array_size = (uint32_t)tk.constant;
+ }
+
+ if (array_size <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+
+ r_array_size = array_size;
+ return OK;
+}
+
+Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size) {
+ TkPos pos = _get_tkpos();
+ Token tk = _get_token();
+
+ if (tk.type == TK_BRACKET_CLOSE) {
+ r_is_unknown_size = true;
+ } else {
+ if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
+ _set_tkpos(pos);
+ int array_size = 0;
+ Node *n = _parse_array_size(p_block, p_function_info, array_size);
+ if (!n) {
+ return ERR_PARSE_ERROR;
+ }
+ p_decl->size = array_size;
+ p_node->size_expression = n;
+ } else if (((int)tk.constant) > 0) {
+ p_decl->size = (uint32_t)tk.constant;
+ }
+
+ if (p_decl->size <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+
+ r_array_size = p_decl->size;
+ }
+
+ return OK;
+}
+
+ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info) {
+ DataType type = TYPE_VOID;
+ String struct_name = "";
+ int array_size = 0;
+ bool auto_size = false;
+ bool undefined_size = false;
+ Token tk = _get_token();
+
+ if (tk.type == TK_CURLY_BRACKET_OPEN) {
+ auto_size = true;
+ } else {
+ if (shader->structs.has(tk.text)) {
+ type = TYPE_STRUCT;
+ struct_name = tk.text;
+ } else {
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for array");
+ return nullptr;
+ }
+ type = get_token_datatype(tk.type);
+ }
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ TkPos pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_CLOSE) {
+ undefined_size = true;
+ tk = _get_token();
+ } else {
+ _set_tkpos(pos);
+
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+
+ ConstantNode *cnode = (ConstantNode *)n;
+ if (cnode->values.size() == 1) {
+ array_size = cnode->values[0].sint;
+ if (array_size <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+ } else {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return nullptr;
+ } else {
+ tk = _get_token();
+ }
+ }
+ } else {
+ _set_error("Expected '['");
+ return nullptr;
+ }
+ }
+
+ ArrayConstructNode *an = alloc_node<ArrayConstructNode>();
+
+ if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization
+ int idx = 0;
+ while (true) {
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n) {
+ return nullptr;
+ }
+
+ // define type by using the first member
+ if (auto_size && idx == 0) {
+ type = n->get_datatype();
+ if (type == TYPE_STRUCT) {
+ struct_name = n->get_datatype_name();
+ }
+ } else {
+ if (!_compare_datatypes(type, struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
+ return nullptr;
+ }
+ }
+
+ tk = _get_token();
+ if (tk.type == TK_COMMA) {
+ an->initializer.push_back(n);
+ } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) {
+ an->initializer.push_back(n);
+ break;
+ } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) {
+ an->initializer.push_back(n);
+ break;
+ } else {
+ if (auto_size) {
+ _set_error("Expected '}' or ','");
+ } else {
+ _set_error("Expected ')' or ','");
+ }
+ return nullptr;
+ }
+ idx++;
+ }
+ if (!auto_size && !undefined_size && an->initializer.size() != array_size) {
+ _set_error("Array size mismatch");
+ return nullptr;
+ }
+ } else {
+ _set_error("Expected array initialization!");
+ return nullptr;
+ }
+
+ an->datatype = type;
+ an->struct_name = struct_name;
+ return an;
+}
+
+ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size) {
+ DataType type = TYPE_VOID;
+ String struct_name = "";
+ int array_size = 0;
+ bool auto_size = false;
+ TkPos prev_pos = _get_tkpos();
+ Token tk = _get_token();
+
+ if (tk.type == TK_CURLY_BRACKET_OPEN) {
+ auto_size = true;
+ } else {
+ if (shader->structs.has(tk.text)) {
+ type = TYPE_STRUCT;
+ struct_name = tk.text;
+ } else {
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_tkpos(prev_pos);
+
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+
+ if (!n) {
+ _set_error("Invalid data type for array");
+ return nullptr;
+ }
+
+ if (!_compare_datatypes(p_type, p_struct_name, p_array_size, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
+ return nullptr;
+ }
+ return n;
+ }
+ type = get_token_datatype(tk.type);
+ }
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ TkPos pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_CLOSE) {
+ array_size = p_array_size;
+ tk = _get_token();
+ } else {
+ _set_tkpos(pos);
+
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+
+ ConstantNode *cnode = (ConstantNode *)n;
+ if (cnode->values.size() == 1) {
+ array_size = cnode->values[0].sint;
+ if (array_size <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+ } else {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return nullptr;
+ } else {
+ tk = _get_token();
+ }
+ }
+ } else {
+ _set_error("Expected '['");
+ return nullptr;
+ }
+
+ if (type != p_type || struct_name != p_struct_name || array_size != p_array_size) {
+ String error_str = "Cannot convert from '";
+ if (type == TYPE_STRUCT) {
+ error_str += struct_name;
+ } else {
+ error_str += get_datatype_name(type);
+ }
+ error_str += "[";
+ error_str += itos(array_size);
+ error_str += "]'";
+ error_str += " to '";
+ if (type == TYPE_STRUCT) {
+ error_str += p_struct_name;
+ } else {
+ error_str += get_datatype_name(p_type);
+ }
+ error_str += "[";
+ error_str += itos(p_array_size);
+ error_str += "]'";
+ _set_error(error_str);
+ return nullptr;
+ }
+ }
+
+ ArrayConstructNode *an = alloc_node<ArrayConstructNode>();
+ an->datatype = p_type;
+ an->struct_name = p_struct_name;
+
+ if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization
+ while (true) {
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n) {
+ return nullptr;
+ }
+
+ if (!_compare_datatypes(p_type, p_struct_name, 0, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
+ return nullptr;
+ }
+
+ tk = _get_token();
+ if (tk.type == TK_COMMA) {
+ an->initializer.push_back(n);
+ } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) {
+ an->initializer.push_back(n);
+ break;
+ } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) {
+ an->initializer.push_back(n);
+ break;
+ } else {
+ if (auto_size) {
+ _set_error("Expected '}' or ','");
+ } else {
+ _set_error("Expected ')' or ','");
+ }
+ return nullptr;
+ }
+ }
+ if (an->initializer.size() != p_array_size) {
+ _set_error("Array size mismatch");
+ return nullptr;
+ }
+ } else {
+ _set_error("Expected array initialization!");
+ return nullptr;
+ }
+
+ return an;
+}
+
ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info) {
Vector<Expression> expression;
@@ -3270,7 +4653,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
- } else if (tk.type == TK_REAL_CONSTANT) {
+ } else if (tk.type == TK_FLOAT_CONSTANT) {
ConstantNode *constant = alloc_node<ConstantNode>();
ConstantNode::Value v;
v.real = tk.constant;
@@ -3308,50 +4691,73 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
//make sure void is not used in expression
_set_error("Void value not allowed in Expression");
return nullptr;
- } else if (is_token_nonvoid_datatype(tk.type)) {
- //basic type constructor
+ } else if (is_token_nonvoid_datatype(tk.type) || tk.type == TK_CURLY_BRACKET_OPEN) {
+ if (tk.type == TK_CURLY_BRACKET_OPEN) {
+ //array constructor
- OperatorNode *func = alloc_node<OperatorNode>();
- func->op = OP_CONSTRUCT;
+ _set_tkpos(prepos);
+ expr = _parse_array_constructor(p_block, p_function_info);
+ } else {
+ DataType datatype;
+ DataPrecision precision;
+ bool precision_defined = false;
- if (is_token_precision(tk.type)) {
- func->return_precision_cache = get_token_precision(tk.type);
+ if (is_token_precision(tk.type)) {
+ precision = get_token_precision(tk.type);
+ precision_defined = true;
+ tk = _get_token();
+ }
+
+ datatype = get_token_datatype(tk.type);
tk = _get_token();
- }
- VariableNode *funcname = alloc_node<VariableNode>();
- funcname->name = get_datatype_name(get_token_datatype(tk.type));
- func->arguments.push_back(funcname);
+ if (tk.type == TK_BRACKET_OPEN) {
+ //array constructor
- tk = _get_token();
- if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after type name");
- return nullptr;
- }
+ _set_tkpos(prepos);
+ expr = _parse_array_constructor(p_block, p_function_info);
+ } else {
+ if (tk.type != TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after type name");
+ return nullptr;
+ }
+ //basic type constructor
- int carg = -1;
+ OperatorNode *func = alloc_node<OperatorNode>();
+ func->op = OP_CONSTRUCT;
- bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg);
+ if (precision_defined) {
+ func->return_precision_cache = precision;
+ }
- if (carg >= 0) {
- completion_type = COMPLETION_CALL_ARGUMENTS;
- completion_line = tk_line;
- completion_block = p_block;
- completion_function = funcname->name;
- completion_argument = carg;
- }
+ VariableNode *funcname = alloc_node<VariableNode>();
+ funcname->name = get_datatype_name(datatype);
+ func->arguments.push_back(funcname);
- if (!ok) {
- return nullptr;
- }
+ int carg = -1;
- if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) {
- _set_error("No matching constructor found for: '" + String(funcname->name) + "'");
- return nullptr;
- }
+ bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg);
+
+ if (carg >= 0) {
+ completion_type = COMPLETION_CALL_ARGUMENTS;
+ completion_line = tk_line;
+ completion_block = p_block;
+ completion_function = funcname->name;
+ completion_argument = carg;
+ }
+
+ if (!ok) {
+ return nullptr;
+ }
- expr = _reduce_expression(p_block, func);
+ if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) {
+ _set_error("No matching constructor found for: '" + String(funcname->name) + "'");
+ return nullptr;
+ }
+ expr = _reduce_expression(p_block, func);
+ }
+ }
} else if (tk.type == TK_IDENTIFIER) {
_set_tkpos(prepos);
@@ -3364,6 +4770,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (shader->structs.has(identifier)) {
pstruct = shader->structs[identifier].shader_struct;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG) && used_structs.has(identifier)) {
+ used_structs[identifier].used = true;
+ }
+#endif // DEBUG_ENABLED
struct_init = true;
}
@@ -3385,152 +4796,16 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
Node *nexpr;
if (pstruct->members[i]->array_size != 0) {
- DataType type = pstruct->members[i]->get_datatype();
- String struct_name = pstruct->members[i]->struct_name;
- int array_size = pstruct->members[i]->array_size;
-
- DataType type2;
- String struct_name2 = "";
- int array_size2 = 0;
-
- bool auto_size = false;
-
- tk = _get_token();
-
- if (tk.type == TK_CURLY_BRACKET_OPEN) {
- auto_size = true;
- } else {
- if (shader->structs.has(tk.text)) {
- type2 = TYPE_STRUCT;
- struct_name2 = tk.text;
- } else {
- if (!is_token_variable_datatype(tk.type)) {
- _set_error("Invalid data type for array");
- return nullptr;
- }
- type2 = get_token_datatype(tk.type);
- }
-
- tk = _get_token();
- if (tk.type == TK_BRACKET_OPEN) {
- TkPos pos2 = _get_tkpos();
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
- array_size2 = array_size;
- tk = _get_token();
- } else {
- _set_tkpos(pos2);
-
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
-
- ConstantNode *cnode = (ConstantNode *)n;
- if (cnode->values.size() == 1) {
- array_size2 = cnode->values[0].sint;
- if (array_size2 <= 0) {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
- } else {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
-
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return nullptr;
- } else {
- tk = _get_token();
- }
- }
- } else {
- _set_error("Expected '['");
- return nullptr;
- }
-
- if (type != type2 || struct_name != struct_name2 || array_size != array_size2) {
- String error_str = "Cannot convert from '";
- if (type2 == TYPE_STRUCT) {
- error_str += struct_name2;
- } else {
- error_str += get_datatype_name(type2);
- }
- error_str += "[";
- error_str += itos(array_size2);
- error_str += "]'";
- error_str += " to '";
- if (type == TYPE_STRUCT) {
- error_str += struct_name;
- } else {
- error_str += get_datatype_name(type);
- }
- error_str += "[";
- error_str += itos(array_size);
- error_str += "]'";
- _set_error(error_str);
- return nullptr;
- }
- }
-
- ArrayConstructNode *an = alloc_node<ArrayConstructNode>();
- an->datatype = type;
- an->struct_name = struct_name;
-
- if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization
- while (true) {
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n) {
- return nullptr;
- }
-
- if (type != n->get_datatype() || struct_name != n->get_datatype_name()) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'");
- return nullptr;
- }
-
- tk = _get_token();
- if (tk.type == TK_COMMA) {
- an->initializer.push_back(n);
- continue;
- } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) {
- an->initializer.push_back(n);
- break;
- } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) {
- an->initializer.push_back(n);
- break;
- } else {
- if (auto_size) {
- _set_error("Expected '}' or ','");
- } else {
- _set_error("Expected ')' or ','");
- }
- return nullptr;
- }
- }
- if (an->initializer.size() != array_size) {
- _set_error("Array size mismatch");
- return nullptr;
- }
- } else {
- _set_error("Expected array initialization!");
+ nexpr = _parse_array_constructor(p_block, p_function_info, pstruct->members[i]->get_datatype(), pstruct->members[i]->struct_name, pstruct->members[i]->array_size);
+ if (!nexpr) {
return nullptr;
}
-
- nexpr = an;
} else {
nexpr = _parse_and_reduce_expression(p_block, p_function_info);
if (!nexpr) {
return nullptr;
}
- Node *node = pstruct->members[i];
if (!_compare_datatypes_in_nodes(pstruct->members[i], nexpr)) {
- String type_name = nexpr->get_datatype() == TYPE_STRUCT ? nexpr->get_datatype_name() : get_datatype_name(nexpr->get_datatype());
- String type_name2 = node->get_datatype() == TYPE_STRUCT ? node->get_datatype_name() : get_datatype_name(node->get_datatype());
- _set_error("Invalid assignment of '" + type_name + "' to '" + type_name2 + "'");
return nullptr;
}
}
@@ -3552,7 +4827,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = func;
- } else { //a function
+ } else { //a function call
const StringName &name = identifier;
@@ -3617,6 +4892,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
FunctionNode *call_function = shader->functions[function_index].function;
if (call_function) {
+ func->return_cache = call_function->get_datatype();
+ func->struct_name = call_function->get_datatype_name();
+ func->return_array_size = call_function->get_array_size();
+
//get current base function
FunctionNode *base_function = nullptr;
{
@@ -3658,6 +4937,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} else if (shader->uniforms.has(varname)) {
error = true;
} else {
+ if (shader->varyings.has(varname)) {
+ _set_error(vformat("Varyings cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier)));
+ return nullptr;
+ }
if (p_function_info.built_ins.has(varname)) {
BuiltInInfo info = p_function_info.built_ins[varname];
if (info.constant) {
@@ -3719,16 +5002,30 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
}
expr = func;
+#ifdef DEBUG_ENABLED
+ if (check_warnings) {
+ StringName func_name;
+
+ if (p_block && p_block->parent_function) {
+ func_name = p_block->parent_function->name;
+ }
+
+ _parse_used_identifier(name, IdentifierType::IDENTIFIER_FUNCTION, func_name);
+ }
+#endif // DEBUG_ENABLED
}
} else {
//an identifier
+ last_name = identifier;
+ last_type = IDENTIFIER_MAX;
_set_tkpos(pos);
DataType data_type;
IdentifierType ident_type;
int array_size = 0;
StringName struct_name;
+ bool is_local = false;
if (p_block && p_block->block_tag != SubClassTag::TAG_GLOBAL) {
int idx = 0;
@@ -3750,25 +5047,63 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Unknown identifier in expression: " + String(identifier));
return nullptr;
}
+ if (ident_type == IDENTIFIER_VARYING) {
+ TkPos prev_pos = _get_tkpos();
+ Token next_token = _get_token();
+
+ // An array of varyings.
+ if (next_token.type == TK_BRACKET_OPEN) {
+ _get_token(); // Pass constant.
+ _get_token(); // Pass TK_BRACKET_CLOSE.
+ next_token = _get_token();
+ }
+ _set_tkpos(prev_pos);
+
+ String error;
+ if (is_token_operator_assign(next_token.type)) {
+ if (!_validate_varying_assign(shader->varyings[identifier], &error)) {
+ _set_error(error);
+ return nullptr;
+ }
+ } else {
+ if (!_validate_varying_using(shader->varyings[identifier], &error)) {
+ _set_error(error);
+ return nullptr;
+ }
+ }
+ }
if (ident_type == IDENTIFIER_FUNCTION) {
_set_error("Can't use function as identifier: " + String(identifier));
return nullptr;
}
+ if (is_const) {
+ last_type = IDENTIFIER_CONSTANT;
+ } else {
+ last_type = ident_type;
+ }
+
+ is_local = ident_type == IDENTIFIER_LOCAL_VAR || ident_type == IDENTIFIER_FUNCTION_ARGUMENT;
}
Node *index_expression = nullptr;
Node *call_expression = nullptr;
+ Node *assign_expression = nullptr;
if (array_size > 0) {
+ prepos = _get_tkpos();
tk = _get_token();
- if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD) {
- _set_error("Expected '[' or '.'");
- return nullptr;
- }
-
- if (tk.type == TK_PERIOD) {
+ if (tk.type == TK_OP_ASSIGN) {
+ if (is_const) {
+ _set_error("Constants cannot be modified.");
+ return nullptr;
+ }
+ assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size);
+ if (!assign_expression) {
+ return nullptr;
+ }
+ } else if (tk.type == TK_PERIOD) {
completion_class = TAG_ARRAY;
p_block->block_tag = SubClassTag::TAG_ARRAY;
call_expression = _parse_and_reduce_expression(p_block, p_function_info);
@@ -3777,22 +5112,21 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
data_type = call_expression->get_datatype();
- } else { // indexing
-
+ } else if (tk.type == TK_BRACKET_OPEN) { // indexing
index_expression = _parse_and_reduce_expression(p_block, p_function_info);
if (!index_expression) {
return nullptr;
}
- if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) {
- _set_error("Only integer expressions are allowed for indexing");
+ if (index_expression->get_array_size() != 0 || (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT)) {
+ _set_error("Only integer expressions are allowed for indexing.");
return nullptr;
}
if (index_expression->type == Node::TYPE_CONSTANT) {
ConstantNode *cnode = (ConstantNode *)index_expression;
if (cnode) {
- if (!cnode->values.empty()) {
+ if (!cnode->values.is_empty()) {
int value = cnode->values[0].sint;
if (value < 0 || value >= array_size) {
_set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
@@ -3807,6 +5141,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Expected ']'");
return nullptr;
}
+ } else {
+ _set_tkpos(prepos);
}
ArrayNode *arrname = alloc_node<ArrayNode>();
@@ -3815,17 +5151,31 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
arrname->struct_name = struct_name;
arrname->index_expression = index_expression;
arrname->call_expression = call_expression;
+ arrname->assign_expression = assign_expression;
arrname->is_const = is_const;
+ arrname->array_size = array_size;
+ arrname->is_local = is_local;
expr = arrname;
-
} else {
VariableNode *varname = alloc_node<VariableNode>();
varname->name = identifier;
varname->datatype_cache = data_type;
varname->is_const = is_const;
varname->struct_name = struct_name;
+ varname->is_local = is_local;
expr = varname;
}
+#ifdef DEBUG_ENABLED
+ if (check_warnings) {
+ StringName func_name;
+
+ if (p_block && p_block->parent_function) {
+ func_name = p_block->parent_function->name;
+ }
+
+ _parse_used_identifier(identifier, ident_type, func_name);
+ }
+#endif // DEBUG_ENABLED
}
} else if (tk.type == TK_OP_ADD) {
continue; //this one does nothing
@@ -3864,8 +5214,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ERR_FAIL_COND_V(!expr, nullptr);
/* OK now see what's NEXT to the operator.. */
- /* OK now see what's NEXT to the operator.. */
- /* OK now see what's NEXT to the operator.. */
while (true) {
TkPos pos2 = _get_tkpos();
@@ -3878,6 +5226,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
DataType dt = expr->get_datatype();
String st = expr->get_datatype_name();
+ if (!expr->is_indexed() && expr->get_array_size() > 0) {
+ completion_class = TAG_ARRAY;
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (!call_expression) {
+ return nullptr;
+ }
+ expr = call_expression;
+ break;
+ }
+
StringName identifier;
if (_get_completable_identifier(p_block, dt == TYPE_STRUCT ? COMPLETION_STRUCT : COMPLETION_INDEX, identifier)) {
if (dt == TYPE_STRUCT) {
@@ -3911,12 +5271,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
String member_name = String(ident.ptr());
if (shader->structs.has(st)) {
StructNode *n = shader->structs[st].shader_struct;
- for (List<MemberNode *>::Element *E = n->members.front(); E; E = E->next()) {
- if (String(E->get()->name) == member_name) {
- member_type = E->get()->datatype;
- array_size = E->get()->array_size;
+ for (const MemberNode *E : n->members) {
+ if (String(E->name) == member_name) {
+ member_type = E->datatype;
+ array_size = E->array_size;
if (member_type == TYPE_STRUCT) {
- member_struct_name = E->get()->struct_name;
+ member_struct_name = E->struct_name;
}
ok = true;
break;
@@ -4154,25 +5514,43 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
mn->has_swizzling_duplicates = repeated;
if (array_size > 0) {
+ TkPos prev_pos = _get_tkpos();
tk = _get_token();
- if (tk.type == TK_PERIOD) {
- _set_error("Nested array length() is not yet implemented");
- return nullptr;
+ if (tk.type == TK_OP_ASSIGN) {
+ if (last_type == IDENTIFIER_CONSTANT) {
+ _set_error("Constants cannot be modified.");
+ return nullptr;
+ }
+ Node *assign_expression = _parse_array_constructor(p_block, p_function_info, member_type, member_struct_name, array_size);
+ if (!assign_expression) {
+ return nullptr;
+ }
+ mn->assign_expression = assign_expression;
+ } else if (tk.type == TK_PERIOD) {
+ completion_class = TAG_ARRAY;
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (!call_expression) {
+ return nullptr;
+ }
+ mn->datatype = call_expression->get_datatype();
+ mn->call_expression = call_expression;
} else if (tk.type == TK_BRACKET_OPEN) {
Node *index_expression = _parse_and_reduce_expression(p_block, p_function_info);
if (!index_expression) {
return nullptr;
}
- if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) {
- _set_error("Only integer expressions are allowed for indexing");
+ if (index_expression->get_array_size() != 0 || (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT)) {
+ _set_error("Only integer expressions are allowed for indexing.");
return nullptr;
}
if (index_expression->type == Node::TYPE_CONSTANT) {
ConstantNode *cnode = (ConstantNode *)index_expression;
if (cnode) {
- if (!cnode->values.empty()) {
+ if (!cnode->values.is_empty()) {
int value = cnode->values[0].sint;
if (value < 0 || value >= array_size) {
_set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
@@ -4188,13 +5566,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
mn->index_expression = index_expression;
-
} else {
- _set_error("Expected '[' or '.'");
- return nullptr;
+ _set_tkpos(prev_pos);
}
}
-
expr = mn;
//todo
@@ -4213,123 +5588,138 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
- if (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT) {
- _set_error("Only integer datatypes are allowed for indexing");
+ if (index->get_array_size() != 0 || (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT)) {
+ _set_error("Only integer expressions are allowed for indexing.");
return nullptr;
}
DataType member_type = TYPE_VOID;
+ String member_struct_name;
- switch (expr->get_datatype()) {
- case TYPE_BVEC2:
- case TYPE_VEC2:
- case TYPE_IVEC2:
- case TYPE_UVEC2:
- case TYPE_MAT2:
- if (index->type == Node::TYPE_CONSTANT) {
- uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
- if (index_constant >= 2) {
- _set_error("Index out of range (0-1)");
- return nullptr;
- }
+ if (expr->get_array_size() > 0) {
+ if (index->type == Node::TYPE_CONSTANT) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= (uint32_t)expr->get_array_size()) {
+ _set_error(vformat("Index [%s] out of range [%s..%s]", index_constant, 0, expr->get_array_size() - 1));
+ return nullptr;
}
+ }
+ member_type = expr->get_datatype();
+ if (member_type == TYPE_STRUCT) {
+ member_struct_name = expr->get_datatype_name();
+ }
+ } else {
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC2:
+ case TYPE_VEC2:
+ case TYPE_IVEC2:
+ case TYPE_UVEC2:
+ case TYPE_MAT2:
+ if (index->type == Node::TYPE_CONSTANT) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= 2) {
+ _set_error("Index out of range (0-1)");
+ return nullptr;
+ }
+ }
- switch (expr->get_datatype()) {
- case TYPE_BVEC2:
- member_type = TYPE_BOOL;
- break;
- case TYPE_VEC2:
- member_type = TYPE_FLOAT;
- break;
- case TYPE_IVEC2:
- member_type = TYPE_INT;
- break;
- case TYPE_UVEC2:
- member_type = TYPE_UINT;
- break;
- case TYPE_MAT2:
- member_type = TYPE_VEC2;
- break;
- default:
- break;
- }
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC2:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC2:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC2:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC2:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT2:
+ member_type = TYPE_VEC2;
+ break;
+ default:
+ break;
+ }
- break;
- case TYPE_BVEC3:
- case TYPE_VEC3:
- case TYPE_IVEC3:
- case TYPE_UVEC3:
- case TYPE_MAT3:
- if (index->type == Node::TYPE_CONSTANT) {
- uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
- if (index_constant >= 3) {
- _set_error("Index out of range (0-2)");
- return nullptr;
+ break;
+ case TYPE_BVEC3:
+ case TYPE_VEC3:
+ case TYPE_IVEC3:
+ case TYPE_UVEC3:
+ case TYPE_MAT3:
+ if (index->type == Node::TYPE_CONSTANT) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= 3) {
+ _set_error("Index out of range (0-2)");
+ return nullptr;
+ }
}
- }
- switch (expr->get_datatype()) {
- case TYPE_BVEC3:
- member_type = TYPE_BOOL;
- break;
- case TYPE_VEC3:
- member_type = TYPE_FLOAT;
- break;
- case TYPE_IVEC3:
- member_type = TYPE_INT;
- break;
- case TYPE_UVEC3:
- member_type = TYPE_UINT;
- break;
- case TYPE_MAT3:
- member_type = TYPE_VEC3;
- break;
- default:
- break;
- }
- break;
- case TYPE_BVEC4:
- case TYPE_VEC4:
- case TYPE_IVEC4:
- case TYPE_UVEC4:
- case TYPE_MAT4:
- if (index->type == Node::TYPE_CONSTANT) {
- uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
- if (index_constant >= 4) {
- _set_error("Index out of range (0-3)");
- return nullptr;
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC3:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC3:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC3:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC3:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT3:
+ member_type = TYPE_VEC3;
+ break;
+ default:
+ break;
+ }
+ break;
+ case TYPE_BVEC4:
+ case TYPE_VEC4:
+ case TYPE_IVEC4:
+ case TYPE_UVEC4:
+ case TYPE_MAT4:
+ if (index->type == Node::TYPE_CONSTANT) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= 4) {
+ _set_error("Index out of range (0-3)");
+ return nullptr;
+ }
}
- }
- switch (expr->get_datatype()) {
- case TYPE_BVEC4:
- member_type = TYPE_BOOL;
- break;
- case TYPE_VEC4:
- member_type = TYPE_FLOAT;
- break;
- case TYPE_IVEC4:
- member_type = TYPE_INT;
- break;
- case TYPE_UVEC4:
- member_type = TYPE_UINT;
- break;
- case TYPE_MAT4:
- member_type = TYPE_VEC4;
- break;
- default:
- break;
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC4:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC4:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC4:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC4:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT4:
+ member_type = TYPE_VEC4;
+ break;
+ default:
+ break;
+ }
+ break;
+ default: {
+ _set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed");
+ return nullptr;
}
- break;
- default: {
- _set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed");
- return nullptr;
}
}
-
OperatorNode *op = alloc_node<OperatorNode>();
op->op = OP_INDEX;
op->return_cache = member_type;
+ op->struct_name = member_struct_name;
op->arguments.push_back(expr);
op->arguments.push_back(index);
expr = op;
@@ -4345,7 +5735,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
op->op = tk.type == TK_OP_DECREMENT ? OP_POST_DECREMENT : OP_POST_INCREMENT;
op->arguments.push_back(expr);
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
_set_error("Invalid base type for increment/decrement operator");
return nullptr;
}
@@ -4496,9 +5886,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
bool unary = false;
bool ternary = false;
+ Operator op = expression[i].op;
int priority;
- switch (expression[i].op) {
+ switch (op) {
case OP_EQUAL:
priority = 8;
break;
@@ -4619,6 +6010,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ERR_FAIL_V(nullptr); //unexpected operator
}
+#if DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::FLOAT_COMPARISON_FLAG) && (op == OP_EQUAL || op == OP_NOT_EQUAL) &&
+ (!expression[i - 1].is_op && !expression[i + 1].is_op) &&
+ (expression[i - 1].node->get_datatype() == TYPE_FLOAT && expression[i + 1].node->get_datatype() == TYPE_FLOAT)) {
+ _add_line_warning(ShaderWarning::FLOAT_COMPARISON);
+ }
+#endif // DEBUG_ENABLED
+
if (priority < min_priority) {
// < is used for left to right (default)
// <= is used for right to left
@@ -4632,7 +6031,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ERR_FAIL_COND_V(next_op == -1, nullptr);
// OK! create operator..
- // OK! create operator..
if (is_unary) {
int expr_pos = next_op;
while (expression[expr_pos].is_op) {
@@ -4657,13 +6055,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.write[i].is_op = false;
expression.write[i].node = op;
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
String at;
for (int j = 0; j < op->arguments.size(); j++) {
if (j > 0) {
at += " and ";
}
at += get_datatype_name(op->arguments[j]->get_datatype());
+ if (!op->arguments[j]->is_indexed() && op->arguments[j]->get_array_size() > 0) {
+ at += "[";
+ at += itos(op->arguments[j]->get_array_size());
+ at += "]";
+ }
}
_set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at);
return nullptr;
@@ -4690,13 +6093,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.write[next_op - 1].is_op = false;
expression.write[next_op - 1].node = op;
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
String at;
for (int i = 0; i < op->arguments.size(); i++) {
if (i > 0) {
at += " and ";
}
at += get_datatype_name(op->arguments[i]->get_datatype());
+ if (!op->arguments[i]->is_indexed() && op->arguments[i]->get_array_size() > 0) {
+ at += "[";
+ at += itos(op->arguments[i]->get_array_size());
+ at += "]";
+ }
}
_set_error("Invalid argument to ternary ?: operator: " + at);
return nullptr;
@@ -4743,7 +6151,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
//replace all 3 nodes by this operator and make it an expression
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
String at;
for (int i = 0; i < op->arguments.size(); i++) {
if (i > 0) {
@@ -4754,6 +6162,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} else {
at += get_datatype_name(op->arguments[i]->get_datatype());
}
+ if (!op->arguments[i]->is_indexed() && op->arguments[i]->get_array_size() > 0) {
+ at += "[";
+ at += itos(op->arguments[i]->get_array_size());
+ at += "]";
+ }
}
_set_error("Invalid arguments to operator '" + get_operator_text(op->op) + "' :" + at);
return nullptr;
@@ -4964,11 +6377,46 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
Node *vardecl = nullptr;
while (true) {
- if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier after type");
+ bool unknown_size = false;
+ int array_size = 0;
+
+ ArrayDeclarationNode *anode = nullptr;
+ ArrayDeclarationNode::Declaration adecl;
+
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+ _set_error("Expected identifier or '[' after type.");
return ERR_PARSE_ERROR;
}
+ if (tk.type == TK_BRACKET_OPEN) {
+ anode = alloc_node<ArrayDeclarationNode>();
+
+ if (is_struct) {
+ anode->struct_name = struct_name;
+ anode->datatype = TYPE_STRUCT;
+ } else {
+ anode->datatype = type;
+ }
+
+ anode->precision = precision;
+ anode->is_const = is_const;
+ vardecl = (Node *)anode;
+
+ adecl.size = 0U;
+ adecl.single_expression = false;
+
+ Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, array_size, unknown_size);
+ if (error != OK) {
+ return error;
+ }
+ tk = _get_token();
+
+ if (tk.type != TK_IDENTIFIER) {
+ _set_error("Expected identifier!");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
StringName name = tk.text;
ShaderLanguage::IdentifierType itype;
if (_find_identifier(p_block, true, p_function_info, name, (ShaderLanguage::DataType *)nullptr, &itype)) {
@@ -4978,254 +6426,283 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
}
+ adecl.name = name;
+
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG)) {
+ if (p_block && p_block->parent_function) {
+ StringName func_name = p_block->parent_function->name;
+
+ if (!used_local_vars.has(func_name)) {
+ used_local_vars.insert(func_name, Map<StringName, Usage>());
+ }
+
+ used_local_vars[func_name].insert(name, Usage(tk_line));
+ }
+ }
+#endif // DEBUG_ENABLED
+
BlockNode::Variable var;
var.type = type;
var.precision = precision;
var.line = tk_line;
- var.array_size = 0;
+ var.array_size = array_size;
var.is_const = is_const;
var.struct_name = struct_name;
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- bool unknown_size = false;
+ if (var.array_size > 0 || unknown_size) {
+ _set_error("Array size is already defined!");
+ return ERR_PARSE_ERROR;
+ }
if (RenderingServer::get_singleton()->is_low_end() && is_const) {
_set_error("Local const arrays are supported only on high-end platform!");
return ERR_PARSE_ERROR;
}
- ArrayDeclarationNode *node = alloc_node<ArrayDeclarationNode>();
+ anode = alloc_node<ArrayDeclarationNode>();
if (is_struct) {
- node->struct_name = struct_name;
- node->datatype = TYPE_STRUCT;
+ anode->struct_name = struct_name;
+ anode->datatype = TYPE_STRUCT;
} else {
- node->datatype = type;
+ anode->datatype = type;
}
- node->precision = precision;
- node->is_const = is_const;
- vardecl = (Node *)node;
-
- ArrayDeclarationNode::Declaration decl;
- decl.name = name;
- decl.size = 0U;
-
- tk = _get_token();
-
- if (tk.type == TK_BRACKET_CLOSE) {
- unknown_size = true;
- } else {
- if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
- _set_error("Expected integer constant > 0 or ']'");
- return ERR_PARSE_ERROR;
- }
+ anode->precision = precision;
+ anode->is_const = is_const;
+ vardecl = (Node *)anode;
- decl.size = ((uint32_t)tk.constant);
- tk = _get_token();
+ adecl.size = 0U;
+ adecl.single_expression = false;
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
- }
- var.array_size = decl.size;
+ Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, var.array_size, unknown_size);
+ if (error != OK) {
+ return error;
}
+ tk = _get_token();
+ }
+ if (var.array_size > 0 || unknown_size) {
bool full_def = false;
- tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
if (RenderingServer::get_singleton()->is_low_end()) {
_set_error("Array initialization is supported only on high-end platform!");
return ERR_PARSE_ERROR;
}
+ TkPos prev_pos = _get_tkpos();
tk = _get_token();
- if (tk.type != TK_CURLY_BRACKET_OPEN) {
- if (unknown_size) {
- _set_error("Expected '{'");
- return ERR_PARSE_ERROR;
- }
-
- full_def = true;
+ if (tk.type == TK_IDENTIFIER) { // a function call array initialization
+ _set_tkpos(prev_pos);
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- DataPrecision precision2 = PRECISION_DEFAULT;
- if (is_token_precision(tk.type)) {
- precision2 = get_token_precision(tk.type);
- tk = _get_token();
- if (shader->structs.has(tk.text)) {
- _set_error("Precision modifier cannot be used on structs.");
- return ERR_PARSE_ERROR;
+ if (!n) {
+ _set_error("Expected correct array initializer!");
+ return ERR_PARSE_ERROR;
+ } else {
+ if (unknown_size) {
+ adecl.size = n->get_array_size();
+ var.array_size = n->get_array_size();
}
- if (!is_token_nonvoid_datatype(tk.type)) {
- _set_error("Expected datatype after precision");
+
+ if (!_compare_datatypes(var.type, var.struct_name, var.array_size, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
return ERR_PARSE_ERROR;
}
- }
- DataType type2;
- StringName struct_name2 = "";
+ adecl.single_expression = true;
+ adecl.initializer.push_back(n);
+ }
- if (shader->structs.has(tk.text)) {
- type2 = TYPE_STRUCT;
- struct_name2 = tk.text;
- } else {
- if (!is_token_variable_datatype(tk.type)) {
- _set_error("Invalid data type for array");
+ tk = _get_token();
+ } else {
+ if (tk.type != TK_CURLY_BRACKET_OPEN) {
+ if (unknown_size) {
+ _set_error("Expected '{'");
return ERR_PARSE_ERROR;
}
- type2 = get_token_datatype(tk.type);
- }
- int array_size2 = 0;
+ full_def = true;
- tk = _get_token();
- if (tk.type == TK_BRACKET_OPEN) {
- TkPos pos2 = _get_tkpos();
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
- array_size2 = var.array_size;
+ DataPrecision precision2 = PRECISION_DEFAULT;
+ if (is_token_precision(tk.type)) {
+ precision2 = get_token_precision(tk.type);
tk = _get_token();
- } else {
- _set_tkpos(pos2);
-
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
- _set_error("Expected single integer constant > 0");
+ if (shader->structs.has(tk.text)) {
+ _set_error("Precision modifier cannot be used on structs.");
+ return ERR_PARSE_ERROR;
+ }
+ if (!is_token_nonvoid_datatype(tk.type)) {
+ _set_error("Expected datatype after precision");
return ERR_PARSE_ERROR;
}
+ }
- ConstantNode *cnode = (ConstantNode *)n;
- if (cnode->values.size() == 1) {
- array_size2 = cnode->values[0].sint;
- if (array_size2 <= 0) {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected single integer constant > 0");
+ DataType type2;
+ StringName struct_name2 = "";
+
+ if (shader->structs.has(tk.text)) {
+ type2 = TYPE_STRUCT;
+ struct_name2 = tk.text;
+ } else {
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for array");
return ERR_PARSE_ERROR;
}
+ type2 = get_token_datatype(tk.type);
+ }
+
+ int array_size2 = 0;
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ TkPos pos2 = _get_tkpos();
tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
+ if (tk.type == TK_BRACKET_CLOSE) {
+ array_size2 = var.array_size;
+ tk = _get_token();
} else {
+ _set_tkpos(pos2);
+
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ ConstantNode *cnode = (ConstantNode *)n;
+ if (cnode->values.size() == 1) {
+ array_size2 = cnode->values[0].sint;
+ if (array_size2 <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ } else {
+ tk = _get_token();
+ }
}
- }
- } else {
- _set_error("Expected '['");
- return ERR_PARSE_ERROR;
- }
-
- if (precision != precision2 || type != type2 || struct_name != struct_name2 || var.array_size != array_size2) {
- String error_str = "Cannot convert from '";
- if (precision2 != PRECISION_DEFAULT) {
- error_str += get_precision_name(precision2);
- error_str += " ";
- }
- if (type2 == TYPE_STRUCT) {
- error_str += struct_name2;
} else {
- error_str += get_datatype_name(type2);
- }
- error_str += "[";
- error_str += itos(array_size2);
- error_str += "]'";
- error_str += " to '";
- if (precision != PRECISION_DEFAULT) {
- error_str += get_precision_name(precision);
- error_str += " ";
+ _set_error("Expected '['");
+ return ERR_PARSE_ERROR;
}
- if (type == TYPE_STRUCT) {
- error_str += struct_name;
- } else {
- error_str += get_datatype_name(type);
+
+ if (precision != precision2 || type != type2 || struct_name != struct_name2 || var.array_size != array_size2) {
+ String error_str = "Cannot convert from '";
+ if (precision2 != PRECISION_DEFAULT) {
+ error_str += get_precision_name(precision2);
+ error_str += " ";
+ }
+ if (type2 == TYPE_STRUCT) {
+ error_str += struct_name2;
+ } else {
+ error_str += get_datatype_name(type2);
+ }
+ error_str += "[";
+ error_str += itos(array_size2);
+ error_str += "]'";
+ error_str += " to '";
+ if (precision != PRECISION_DEFAULT) {
+ error_str += get_precision_name(precision);
+ error_str += " ";
+ }
+ if (type == TYPE_STRUCT) {
+ error_str += struct_name;
+ } else {
+ error_str += get_datatype_name(type);
+ }
+ error_str += "[";
+ error_str += itos(var.array_size);
+ error_str += "]'";
+ _set_error(error_str);
+ return ERR_PARSE_ERROR;
}
- error_str += "[";
- error_str += itos(var.array_size);
- error_str += "]'";
- _set_error(error_str);
- return ERR_PARSE_ERROR;
}
- }
- bool curly = tk.type == TK_CURLY_BRACKET_OPEN;
+ bool curly = tk.type == TK_CURLY_BRACKET_OPEN;
- if (unknown_size) {
- if (!curly) {
- _set_error("Expected '{'");
- return ERR_PARSE_ERROR;
- }
- } else {
- if (full_def) {
- if (curly) {
- _set_error("Expected '('");
+ if (unknown_size) {
+ if (!curly) {
+ _set_error("Expected '{'");
return ERR_PARSE_ERROR;
}
+ } else {
+ if (full_def) {
+ if (curly) {
+ _set_error("Expected '('");
+ return ERR_PARSE_ERROR;
+ }
+ }
}
- }
- if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
- while (true) {
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n) {
- return ERR_PARSE_ERROR;
- }
+ if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
+ while (true) {
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n) {
+ return ERR_PARSE_ERROR;
+ }
- if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
- _set_error("Expected constant expression");
- return ERR_PARSE_ERROR;
- }
+ if (anode->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ _set_error("Expected constant expression");
+ return ERR_PARSE_ERROR;
+ }
- if (var.type != n->get_datatype() || struct_name != n->get_datatype_name()) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? struct_name : get_datatype_name(var.type)) + "'");
- return ERR_PARSE_ERROR;
- }
+ if (!_compare_datatypes(var.type, struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
+ return ERR_PARSE_ERROR;
+ }
- tk = _get_token();
- if (tk.type == TK_COMMA) {
- decl.initializer.push_back(n);
- continue;
- } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) {
- decl.initializer.push_back(n);
- break;
- } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) {
- decl.initializer.push_back(n);
- break;
- } else {
- if (curly) {
- _set_error("Expected '}' or ','");
+ tk = _get_token();
+ if (tk.type == TK_COMMA) {
+ adecl.initializer.push_back(n);
+ continue;
+ } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) {
+ adecl.initializer.push_back(n);
+ break;
+ } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) {
+ adecl.initializer.push_back(n);
+ break;
} else {
- _set_error("Expected ')' or ','");
+ if (curly) {
+ _set_error("Expected '}' or ','");
+ } else {
+ _set_error("Expected ')' or ','");
+ }
+ return ERR_PARSE_ERROR;
}
+ }
+ if (unknown_size) {
+ adecl.size = adecl.initializer.size();
+ var.array_size = adecl.initializer.size();
+ } else if (adecl.initializer.size() != var.array_size) {
+ _set_error("Array size mismatch");
return ERR_PARSE_ERROR;
}
+ tk = _get_token();
}
- if (unknown_size) {
- decl.size = decl.initializer.size();
- var.array_size = decl.initializer.size();
- } else if (decl.initializer.size() != var.array_size) {
- _set_error("Array size mismatch");
- return ERR_PARSE_ERROR;
- }
- tk = _get_token();
}
} else {
if (unknown_size) {
_set_error("Expected array initialization");
return ERR_PARSE_ERROR;
}
- if (is_const) {
+ if (anode->is_const) {
_set_error("Expected initialization of constant");
return ERR_PARSE_ERROR;
}
}
- node->declarations.push_back(decl);
+ anode->declarations.push_back(adecl);
} else if (tk.type == TK_OP_ASSIGN) {
VariableDeclarationNode *node = alloc_node<VariableDeclarationNode>();
if (is_struct) {
@@ -5248,13 +6725,24 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
- _set_error("Expected constant expression after '='");
- return ERR_PARSE_ERROR;
+ OperatorNode *op = ((OperatorNode *)n);
+ for (int i = 1; i < op->arguments.size(); i++) {
+ if (!_check_node_constness(op->arguments[i])) {
+ _set_error("Expected constant expression for argument '" + itos(i - 1) + "' of function call after '='");
+ return ERR_PARSE_ERROR;
+ }
+ }
}
decl.initializer = n;
- if (var.type == TYPE_STRUCT ? (var.struct_name != n->get_datatype_name()) : (var.type != n->get_datatype())) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? String(var.struct_name) : get_datatype_name(var.type)) + "'");
+ if (n->type == Node::TYPE_CONSTANT) {
+ ConstantNode *const_node = static_cast<ConstantNode *>(n);
+ if (const_node && const_node->values.size() == 1) {
+ var.value = const_node->values[0];
+ }
+ }
+
+ if (!_compare_datatypes(var.type, var.struct_name, var.array_size, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
return ERR_PARSE_ERROR;
}
tk = _get_token();
@@ -5284,7 +6772,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
p_block->statements.push_back(vardecl);
p_block->variables[name] = var;
-
if (tk.type == TK_COMMA) {
if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR) {
_set_error("Multiple declarations in 'for' loop are not implemented yet.");
@@ -5421,18 +6908,29 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i];
if (flow) {
if (flow->flow_op == FLOW_OP_CASE) {
- ConstantNode *n2 = static_cast<ConstantNode *>(flow->expressions[0]);
- if (!n2) {
- return ERR_PARSE_ERROR;
- }
- if (n2->values.empty()) {
- return ERR_PARSE_ERROR;
- }
- if (constants.has(n2->values[0].sint)) {
- _set_error("Duplicated case label: '" + itos(n2->values[0].sint) + "'");
- return ERR_PARSE_ERROR;
+ if (flow->expressions[0]->type == Node::TYPE_CONSTANT) {
+ ConstantNode *cn = static_cast<ConstantNode *>(flow->expressions[0]);
+ if (!cn || cn->values.is_empty()) {
+ return ERR_PARSE_ERROR;
+ }
+ if (constants.has(cn->values[0].sint)) {
+ _set_error("Duplicated case label: '" + itos(cn->values[0].sint) + "'");
+ return ERR_PARSE_ERROR;
+ }
+ constants.insert(cn->values[0].sint);
+ } else if (flow->expressions[0]->type == Node::TYPE_VARIABLE) {
+ VariableNode *vn = static_cast<VariableNode *>(flow->expressions[0]);
+ if (!vn) {
+ return ERR_PARSE_ERROR;
+ }
+ ConstantNode::Value v;
+ _find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, nullptr, nullptr, nullptr, &v);
+ if (constants.has(v.sint)) {
+ _set_error("Duplicated case label: '" + itos(v.sint) + "'");
+ return ERR_PARSE_ERROR;
+ }
+ constants.insert(v.sint);
}
- constants.insert(n2->values[0].sint);
} else if (flow->flow_op == FLOW_OP_DEFAULT) {
continue;
} else {
@@ -5468,12 +6966,38 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
}
+ Node *n = nullptr;
+
if (tk.type != TK_INT_CONSTANT) {
- _set_error("Expected integer constant");
- return ERR_PARSE_ERROR;
- }
+ bool correct_constant_expression = false;
+ DataType data_type;
+
+ if (tk.type == TK_IDENTIFIER) {
+ bool is_const;
+ _find_identifier(p_block, false, p_function_info, tk.text, &data_type, nullptr, &is_const);
+ if (is_const) {
+ if (data_type == TYPE_INT) {
+ correct_constant_expression = true;
+ }
+ }
+ }
+ if (!correct_constant_expression) {
+ _set_error("Expected integer constant");
+ return ERR_PARSE_ERROR;
+ }
- int constant = (int)tk.constant * sign;
+ VariableNode *vn = alloc_node<VariableNode>();
+ vn->name = tk.text;
+ n = vn;
+ } else {
+ ConstantNode::Value v;
+ v.sint = (int)tk.constant * sign;
+
+ ConstantNode *cn = alloc_node<ConstantNode>();
+ cn->values.push_back(v);
+ cn->datatype = TYPE_INT;
+ n = cn;
+ }
tk = _get_token();
@@ -5485,12 +7009,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ControlFlowNode *cf = alloc_node<ControlFlowNode>();
cf->flow_op = FLOW_OP_CASE;
- ConstantNode *n = alloc_node<ConstantNode>();
- ConstantNode::Value v;
- v.sint = constant;
- n->values.push_back(v);
- n->datatype = TYPE_INT;
-
BlockNode *case_block = alloc_node<BlockNode>();
case_block->block_type = BlockNode::BLOCK_TYPE_CASE;
case_block->parent_block = p_block;
@@ -5670,7 +7188,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
//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")) {
+ 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;
}
@@ -5684,6 +7202,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_BUG;
}
+ String return_struct_name = String(b->parent_function->return_struct_name);
+ String array_size_string;
+
+ if (b->parent_function->return_array_size > 0) {
+ array_size_string = "[" + itos(b->parent_function->return_array_size) + "]";
+ }
+
ControlFlowNode *flow = alloc_node<ControlFlowNode>();
flow->flow_op = FLOW_OP_RETURN;
@@ -5692,18 +7217,19 @@ 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 expression of type '" + get_datatype_name(b->parent_function->return_type) + "'");
+ _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 + "'");
return ERR_PARSE_ERROR;
}
} else {
_set_tkpos(pos); //rollback, wants expression
+
Node *expr = _parse_and_reduce_expression(p_block, p_function_info);
if (!expr) {
return ERR_PARSE_ERROR;
}
- if (b->parent_function->return_type != expr->get_datatype()) {
- _set_error("Expected return expression of type '" + get_datatype_name(b->parent_function->return_type) + "'");
+ 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 + "'");
return ERR_PARSE_ERROR;
}
@@ -5747,15 +7273,15 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
pos = _get_tkpos();
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
- //all is good
_set_error("Expected ';' after discard");
+ return ERR_PARSE_ERROR;
}
p_block->statements.push_back(flow);
} else if (tk.type == TK_CF_BREAK) {
if (!p_can_break) {
- //all is good
- _set_error("Breaking is not allowed here");
+ _set_error("'break' is not allowed outside of a loop or 'switch' statement");
+ return ERR_PARSE_ERROR;
}
ControlFlowNode *flow = alloc_node<ControlFlowNode>();
@@ -5764,8 +7290,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
pos = _get_tkpos();
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
- //all is good
_set_error("Expected ';' after break");
+ return ERR_PARSE_ERROR;
}
p_block->statements.push_back(flow);
@@ -5780,8 +7306,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
} else if (tk.type == TK_CF_CONTINUE) {
if (!p_can_continue) {
- //all is good
- _set_error("Continuing is not allowed here");
+ _set_error("'continue' is not allowed outside of a loop");
+ return ERR_PARSE_ERROR;
}
ControlFlowNode *flow = alloc_node<ControlFlowNode>();
@@ -5792,6 +7318,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type != TK_SEMICOLON) {
//all is good
_set_error("Expected ';' after continue");
+ return ERR_PARSE_ERROR;
}
p_block->statements.push_back(flow);
@@ -5877,6 +7404,7 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) {
Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) {
Token tk = _get_token();
+ TkPos prev_pos;
if (tk.type != TK_SHADER_TYPE) {
_set_error("Expected 'shader_type' at the beginning of shader. Valid types are: " + _get_shader_type_list(p_shader_types));
@@ -5898,20 +7426,24 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Invalid shader type. Valid types are: " + _get_shader_type_list(p_shader_types));
return ERR_PARSE_ERROR;
}
-
+ prev_pos = _get_tkpos();
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
+ _set_tkpos(prev_pos);
_set_error("Expected ';' after 'shader_type <type>'.");
+ return ERR_PARSE_ERROR;
}
tk = _get_token();
int texture_uniforms = 0;
- int uniforms = 0;
+ int texture_binding = 0;
int instance_index = 0;
ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
+ stages = &p_functions;
+
while (tk.type != TK_EOF) {
switch (tk.type) {
case TK_RENDER_MODE: {
@@ -5954,6 +7486,10 @@ 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)) {
+ _set_error("Redefinition of '" + String(st.name) + "'");
+ return ERR_PARSE_ERROR;
+ }
tk = _get_token();
if (tk.type != TK_CURLY_BRACKET_OPEN) {
_set_error("Expected '{'");
@@ -6012,8 +7548,23 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("void datatype not allowed here");
return ERR_PARSE_ERROR;
}
-
tk = _get_token();
+
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+ _set_error("Expected identifier or '['.");
+ return ERR_PARSE_ERROR;
+ }
+
+ int array_size = 0;
+
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_global_array_size(array_size);
+ if (error != OK) {
+ return error;
+ }
+ tk = _get_token();
+ }
+
if (tk.type != TK_IDENTIFIER) {
_set_error("Expected identifier!");
return ERR_PARSE_ERROR;
@@ -6024,41 +7575,29 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
member->datatype = type;
member->struct_name = struct_name;
member->name = tk.text;
+ member->array_size = array_size;
if (member_names.has(member->name)) {
_set_error("Redefinition of '" + String(member->name) + "'");
return ERR_PARSE_ERROR;
}
member_names.insert(member->name);
-
tk = _get_token();
- if (tk.type == TK_BRACKET_OPEN) {
- tk = _get_token();
- if (tk.type == TK_INT_CONSTANT && tk.constant > 0) {
- member->array_size = (int)tk.constant;
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
- tk = _get_token();
- if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';'");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_global_array_size(member->array_size);
+ if (error != OK) {
+ return error;
}
+ tk = _get_token();
}
- st_node->members.push_back(member);
if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ']' or ';'");
+ _set_error("Expected ';'");
return ERR_PARSE_ERROR;
}
+
+ st_node->members.push_back(member);
member_count++;
}
}
@@ -6074,7 +7613,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
shader->structs[st.name] = st;
shader->vstructs.push_back(st); // struct's order is important!
-
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG)) {
+ used_structs.insert(st.name, Usage(tk_line));
+ }
+#endif // DEBUG_ENABLED
} break;
case TK_GLOBAL: {
tk = _get_token();
@@ -6101,28 +7644,49 @@ 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;
}
}
+ bool precision_defined = false;
DataPrecision precision = PRECISION_DEFAULT;
DataInterpolation interpolation = INTERPOLATION_SMOOTH;
DataType type;
StringName name;
+ int array_size = 0;
tk = _get_token();
if (is_token_interpolation(tk.type)) {
+ if (uniform) {
+ _set_error("Interpolation qualifiers are not supported for uniforms!");
+ return ERR_PARSE_ERROR;
+ }
interpolation = get_token_interpolation(tk.type);
tk = _get_token();
}
if (is_token_precision(tk.type)) {
precision = get_token_precision(tk.type);
+ precision_defined = true;
tk = _get_token();
}
+ if (shader->structs.has(tk.text)) {
+ if (uniform) {
+ if (precision_defined) {
+ _set_error("Precision modifier cannot be used on structs.");
+ return ERR_PARSE_ERROR;
+ }
+ _set_error("struct datatype is not yet supported for uniforms!");
+ return ERR_PARSE_ERROR;
+ } else {
+ _set_error("struct datatype not allowed here");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
if (!is_token_datatype(tk.type)) {
_set_error("Expected datatype. ");
return ERR_PARSE_ERROR;
@@ -6141,11 +7705,26 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
tk = _get_token();
+
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+ _set_error("Expected identifier or '['.");
+ return ERR_PARSE_ERROR;
+ }
+
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_global_array_size(array_size);
+ if (error != OK) {
+ return error;
+ }
+ tk = _get_token();
+ }
+
if (tk.type != TK_IDENTIFIER) {
_set_error("Expected identifier!");
return ERR_PARSE_ERROR;
}
+ prev_pos = _get_tkpos();
name = tk.text;
if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
@@ -6174,12 +7753,32 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
ShaderNode::Uniform uniform2;
+ uniform2.type = type;
+ uniform2.scope = uniform_scope;
+ uniform2.precision = precision;
+ uniform2.array_size = array_size;
+
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_global_array_size(uniform2.array_size);
+ if (error != OK) {
+ return error;
+ }
+ tk = _get_token();
+ }
+
if (is_sampler_type(type)) {
if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) {
_set_error("Uniforms with 'instance' qualifiers can't be of sampler type.");
return ERR_PARSE_ERROR;
}
uniform2.texture_order = texture_uniforms++;
+ uniform2.texture_binding = texture_binding;
+ if (uniform2.array_size > 0) {
+ texture_binding += uniform2.array_size;
+ } else {
+ ++texture_binding;
+ }
uniform2.order = -1;
if (_validate_datatype(type) != OK) {
return ERR_PARSE_ERROR;
@@ -6189,17 +7788,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Uniforms with 'instance' qualifiers can't be of matrix type.");
return ERR_PARSE_ERROR;
}
-
uniform2.texture_order = -1;
- uniform2.order = uniforms++;
}
- uniform2.type = type;
- uniform2.scope = uniform_scope;
- uniform2.precision = precision;
-
- //todo parse default value
- tk = _get_token();
+ if (uniform2.array_size > 0) {
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL) {
+ _set_error("'SCOPE_GLOBAL' qualifier is not yet supported for uniform array!");
+ return ERR_PARSE_ERROR;
+ }
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) {
+ _set_error("'SCOPE_INSTANCE' qualifier is not yet supported for uniform array!");
+ return ERR_PARSE_ERROR;
+ }
+ }
int custom_instance_index = -1;
@@ -6207,6 +7808,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
//hint
do {
tk = _get_token();
+
+ if (uniform2.array_size > 0) {
+ if (tk.type != TK_HINT_COLOR) {
+ _set_error("This hint is not yet supported for uniform arrays!");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
if (tk.type == TK_HINT_WHITE_TEXTURE) {
uniform2.hint = ShaderNode::Uniform::HINT_WHITE;
} else if (tk.type == TK_HINT_BLACK_TEXTURE) {
@@ -6259,7 +7868,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) {
+ if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) {
_set_error("Expected integer constant");
return ERR_PARSE_ERROR;
}
@@ -6283,7 +7892,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) {
+ if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) {
_set_error("Expected integer constant after ','");
return ERR_PARSE_ERROR;
}
@@ -6296,7 +7905,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_COMMA) {
tk = _get_token();
- if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) {
+ if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) {
_set_error("Expected integer constant after ','");
return ERR_PARSE_ERROR;
}
@@ -6397,6 +8006,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
//reset scope for next uniform
if (tk.type == TK_OP_ASSIGN) {
+ if (uniform2.array_size > 0) {
+ _set_error("Setting default value to a uniform array is not yet supported!");
+ return ERR_PARSE_ERROR;
+ }
+
Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo());
if (!expr) {
return ERR_PARSE_ERROR;
@@ -6418,6 +8032,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
shader->uniforms[name] = uniform2;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_UNIFORM_FLAG)) {
+ used_uniforms.insert(name, Usage(tk_line));
+ }
+#endif // DEBUG_ENABLED
+
//reset scope for next uniform
uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
@@ -6425,19 +8045,29 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Expected ';'");
return ERR_PARSE_ERROR;
}
- } else {
+ } else { // varying
ShaderNode::Varying varying;
varying.type = type;
varying.precision = precision;
varying.interpolation = interpolation;
+ varying.tkpos = prev_pos;
+ varying.array_size = array_size;
tk = _get_token();
if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
- _set_error("Expected ';' or '['");
+ if (array_size == 0) {
+ _set_error("Expected ';' or '['");
+ } else {
+ _set_error("Expected ';'");
+ }
return ERR_PARSE_ERROR;
}
if (tk.type == TK_BRACKET_OPEN) {
+ if (array_size > 0) {
+ _set_error("Array size is already defined!");
+ return ERR_PARSE_ERROR;
+ }
tk = _get_token();
if (tk.type == TK_INT_CONSTANT && tk.constant > 0) {
varying.array_size = (int)tk.constant;
@@ -6454,12 +8084,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
} else {
- _set_error("Expected single integer constant > 0");
+ _set_error("Expected integer constant > 0");
return ERR_PARSE_ERROR;
}
}
shader->varyings[name] = varying;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_VARYING_FLAG)) {
+ used_varyings.insert(name, Usage(tk_line));
+ }
+#endif // DEBUG_ENABLED
}
} break;
@@ -6472,6 +8107,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
DataPrecision precision = PRECISION_DEFAULT;
DataType type;
StringName name;
+ int return_array_size = 0;
if (tk.type == TK_CONST) {
is_constant = true;
@@ -6507,12 +8143,35 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else {
type = get_token_datatype(tk.type);
}
- TkPos prev_pos = _get_tkpos();
+ prev_pos = _get_tkpos();
tk = _get_token();
+
if (tk.type == TK_BRACKET_OPEN) {
- _set_error("Cannot use arrays as return types");
- 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) {
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ error = true;
+ }
+ } else {
+ error = true;
+ }
+ if (error) {
+ _set_error("Expected integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ prev_pos = _get_tkpos();
}
+
_set_tkpos(prev_pos);
_get_completable_identifier(nullptr, COMPLETION_MAIN_FUNCTION, name);
@@ -6627,15 +8286,15 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- TkPos pos2 = _get_tkpos();
+ prev_pos = _get_tkpos();
tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
array_size2 = constant.array_size;
tk = _get_token();
} else {
- _set_tkpos(pos2);
+ _set_tkpos(prev_pos);
- Node *n = _parse_and_reduce_expression(NULL, FunctionInfo());
+ Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo());
if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
@@ -6716,7 +8375,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(NULL, FunctionInfo());
+ Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo());
if (!n) {
return ERR_PARSE_ERROR;
}
@@ -6726,8 +8385,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (constant.type != n->get_datatype() || n->get_datatype_name() != struct_name) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (is_struct ? String(struct_name) : get_datatype_name(constant.type)) + "'");
+ if (!_compare_datatypes(constant.type, struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
return ERR_PARSE_ERROR;
}
@@ -6742,10 +8400,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
decl.initializer.push_back(n);
break;
} else {
- if (curly)
+ if (curly) {
_set_error("Expected '}' or ','");
- else
+ } else {
_set_error("Expected ')' or ','");
+ }
return ERR_PARSE_ERROR;
}
}
@@ -6771,18 +8430,23 @@ 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(NULL, FunctionInfo());
- if (!expr)
+ Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ if (!expr) {
return ERR_PARSE_ERROR;
+ }
if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) {
- _set_error("Expected constant expression after '='");
- return ERR_PARSE_ERROR;
+ OperatorNode *op = ((OperatorNode *)expr);
+ for (int i = 1; i < op->arguments.size(); i++) {
+ if (!_check_node_constness(op->arguments[i])) {
+ _set_error("Expected constant expression for argument '" + itos(i - 1) + "' of function call after '='");
+ return ERR_PARSE_ERROR;
+ }
+ }
}
constant.initializer = static_cast<ConstantNode *>(expr);
- if (type != expr->get_datatype() || expr->get_datatype_name() != struct_name) {
- _set_error("Invalid assignment of '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' to '" + (is_struct ? String(struct_name) : get_datatype_name(type)) + "'");
+ if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), 0)) {
return ERR_PARSE_ERROR;
}
}
@@ -6799,6 +8463,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
shader->constants[name] = constant;
shader->vconstants.push_back(constant);
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_CONSTANT_FLAG)) {
+ used_constants.insert(name, Usage(tk_line));
+ }
+#endif // DEBUG_ENABLED
if (tk.type == TK_COMMA) {
tk = _get_token();
@@ -6837,8 +8506,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (p_functions.has("global")) { // Adds global variables: 'TIME'
- for (Map<StringName, BuiltInInfo>::Element *E = p_functions["global"].built_ins.front(); E; E = E->next()) {
- builtins.built_ins.insert(E->key(), E->value());
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["global"].built_ins) {
+ builtins.built_ins.insert(E.key, E.value);
}
}
@@ -6857,9 +8526,16 @@ 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;
if (p_functions.has(name)) {
func_node->can_discard = p_functions[name].can_discard;
+ } else {
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_FUNCTION_FLAG)) {
+ used_functions.insert(name, Usage(tk_line));
+ }
+#endif // DEBUG_ENABLED
}
func_node->body = alloc_node<BlockNode>();
@@ -6904,6 +8580,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;
if (is_token_precision(tk.type)) {
pprecision = get_token_precision(tk.type);
@@ -6950,8 +8627,29 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- _set_error("Arrays as parameters are not implemented yet");
- return ERR_PARSE_ERROR;
+ bool error = false;
+ tk = _get_token();
+
+ if (tk.type == TK_INT_CONSTANT) {
+ array_size = (int)tk.constant;
+
+ if (array_size > 0) {
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ error = true;
+ }
+ } else {
+ error = true;
+ }
+ if (error) {
+ _set_error("Expected integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ tk = _get_token();
}
if (tk.type != TK_IDENTIFIER) {
_set_error("Expected identifier for argument name");
@@ -6985,14 +8683,41 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
arg.tex_argument_repeat = REPEAT_DEFAULT;
arg.is_const = is_const;
- func_node->arguments.push_back(arg);
-
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- _set_error("Arrays as parameters are not implemented yet");
- return ERR_PARSE_ERROR;
+ if (array_size > 0) {
+ _set_error("Array size is already defined!");
+ return ERR_PARSE_ERROR;
+ }
+ bool error = false;
+ tk = _get_token();
+
+ if (tk.type == TK_INT_CONSTANT) {
+ array_size = (int)tk.constant;
+
+ if (array_size > 0) {
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ error = true;
+ }
+ } else {
+ error = true;
+ }
+
+ if (error) {
+ _set_error("Expected integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ tk = _get_token();
}
+ arg.array_size = array_size;
+ func_node->arguments.push_back(arg);
+
if (tk.type == TK_COMMA) {
tk = _get_token();
//do none and go on
@@ -7042,30 +8767,38 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- return OK;
-}
+ int uniforms = 0;
-bool ShaderLanguage::has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name) {
- if (p_functions.has("vertex")) {
- if (p_functions["vertex"].built_ins.has(p_name)) {
- return true;
+ // Need to push arrays to first place in a uniform buffer in order to correct work.
+ for (Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) {
+ if (E->get().texture_order == -1 && E->get().scope != ShaderNode::Uniform::SCOPE_INSTANCE && E->get().array_size > 0) {
+ E->get().order = uniforms++;
}
}
- if (p_functions.has("fragment")) {
- if (p_functions["fragment"].built_ins.has(p_name)) {
- return true;
+ for (Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) {
+ if (E->get().texture_order == -1 && E->get().scope != ShaderNode::Uniform::SCOPE_INSTANCE && E->get().array_size == 0) {
+ E->get().order = uniforms++;
}
}
- if (p_functions.has("light")) {
- if (p_functions["light"].built_ins.has(p_name)) {
- return true;
- }
+
+ int error_line;
+ String error_message;
+ if (!_check_varying_usages(&error_line, &error_message)) {
+ _set_tkpos({ 0, error_line });
+ _set_error(error_message);
+ return ERR_PARSE_ERROR;
}
- if (p_functions.has("compute")) {
- if (p_functions["compute"].built_ins.has(p_name)) {
+
+ return OK;
+}
+
+bool ShaderLanguage::has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name) {
+ for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : p_functions) {
+ if (E.value.built_ins.has(p_name)) {
return true;
}
}
+
return false;
}
@@ -7199,27 +8932,71 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
return String();
}
-Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func) {
+#ifdef DEBUG_ENABLED
+void ShaderLanguage::_check_warning_accums() {
+ for (const KeyValue<ShaderWarning::Code, Map<StringName, Map<StringName, Usage>> *> &E : warnings_check_map2) {
+ for (Map<StringName, Map<StringName, Usage>>::Element *T = (*E.value).front(); T; T = T->next()) {
+ for (const KeyValue<StringName, Usage> &U : T->get()) {
+ if (!U.value.used) {
+ _add_warning(E.key, U.value.decl_line, U.key);
+ }
+ }
+ }
+ }
+ for (const KeyValue<ShaderWarning::Code, Map<StringName, Usage> *> &E : warnings_check_map) {
+ for (const Map<StringName, Usage>::Element *U = (*E.value).front(); U; U = U->next()) {
+ if (!U->get().used) {
+ _add_warning(E.key, U->get().decl_line, U->key());
+ }
+ }
+ }
+}
+List<ShaderWarning>::Element *ShaderLanguage::get_warnings_ptr() {
+ return warnings.front();
+}
+void ShaderLanguage::enable_warning_checking(bool p_enabled) {
+ check_warnings = p_enabled;
+}
+bool ShaderLanguage::is_warning_checking_enabled() const {
+ return check_warnings;
+}
+void ShaderLanguage::set_warning_flags(uint32_t p_flags) {
+ warning_flags = p_flags;
+}
+uint32_t ShaderLanguage::get_warning_flags() const {
+ return warning_flags;
+}
+#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) {
clear();
code = p_code;
global_var_get_type_func = p_global_variable_type_func;
+ varying_function_names = p_varying_function_names;
nodes = nullptr;
shader = alloc_node<ShaderNode>();
Error err = _parse_shader(p_functions, p_render_modes, p_shader_types);
+#ifdef DEBUG_ENABLED
+ if (check_warnings) {
+ _check_warning_accums();
+ }
+#endif // DEBUG_ENABLED
+
if (err != OK) {
return err;
}
return OK;
}
-Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, 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 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) {
clear();
code = p_code;
+ varying_function_names = p_varying_function_names;
nodes = nullptr;
global_var_get_type_func = p_global_variable_type_func;
@@ -7252,8 +9029,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
return OK;
} break;
case COMPLETION_MAIN_FUNCTION: {
- for (const Map<StringName, FunctionInfo>::Element *E = p_functions.front(); E; E = E->next()) {
- ScriptCodeCompletionOption option(E->key(), ScriptCodeCompletionOption::KIND_FUNCTION);
+ for (const KeyValue<StringName, FunctionInfo> &E : p_functions) {
+ ScriptCodeCompletionOption option(E.key, ScriptCodeCompletionOption::KIND_FUNCTION);
r_options->push_back(option);
}
@@ -7269,9 +9046,9 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
if (completion_class == TAG_GLOBAL) {
while (block) {
if (comp_ident) {
- for (const Map<StringName, BlockNode::Variable>::Element *E = block->variables.front(); E; E = E->next()) {
- if (E->get().line < completion_line) {
- matches.insert(E->key(), ScriptCodeCompletionOption::KIND_VARIABLE);
+ for (const KeyValue<StringName, BlockNode::Variable> &E : block->variables) {
+ if (E.value.line < completion_line) {
+ matches.insert(E.key, ScriptCodeCompletionOption::KIND_VARIABLE);
}
}
}
@@ -7289,30 +9066,30 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
if (comp_ident) {
if (p_functions.has("global")) {
- for (Map<StringName, BuiltInInfo>::Element *E = p_functions["global"].built_ins.front(); E; E = E->next()) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["global"].built_ins) {
ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
- if (E->get().constant) {
+ if (E.value.constant) {
kind = ScriptCodeCompletionOption::KIND_CONSTANT;
}
- matches.insert(E->key(), kind);
+ matches.insert(E.key, kind);
}
}
if (skip_function != StringName() && p_functions.has(skip_function)) {
- for (Map<StringName, BuiltInInfo>::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_functions[skip_function].built_ins) {
ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
- if (E->get().constant) {
+ if (E.value.constant) {
kind = ScriptCodeCompletionOption::KIND_CONSTANT;
}
- matches.insert(E->key(), kind);
+ matches.insert(E.key, kind);
}
}
- for (const Map<StringName, ShaderNode::Varying>::Element *E = shader->varyings.front(); E; E = E->next()) {
- matches.insert(E->key(), ScriptCodeCompletionOption::KIND_VARIABLE);
+ for (const KeyValue<StringName, ShaderNode::Varying> &E : shader->varyings) {
+ matches.insert(E.key, ScriptCodeCompletionOption::KIND_VARIABLE);
}
- for (const Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) {
- matches.insert(E->key(), ScriptCodeCompletionOption::KIND_MEMBER);
+ for (const KeyValue<StringName, ShaderNode::Uniform> &E : shader->uniforms) {
+ matches.insert(E.key, ScriptCodeCompletionOption::KIND_MEMBER);
}
}
@@ -7326,6 +9103,12 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
int idx = 0;
bool low_end = RenderingServer::get_singleton()->is_low_end();
+ if (stages && stages->has(skip_function)) {
+ for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[skip_function].stage_functions) {
+ matches.insert(String(E.key), ScriptCodeCompletionOption::KIND_FUNCTION);
+ }
+ }
+
while (builtin_func_defs[idx].name) {
if (low_end && builtin_func_defs[idx].high_end) {
idx++;
@@ -7351,9 +9134,9 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
}
- for (Map<String, ScriptCodeCompletionOption::Kind>::Element *E = matches.front(); E; E = E->next()) {
- ScriptCodeCompletionOption option(E->key(), E->value());
- if (E->value() == ScriptCodeCompletionOption::KIND_FUNCTION) {
+ for (const KeyValue<String, ScriptCodeCompletionOption::Kind> &E : matches) {
+ ScriptCodeCompletionOption option(E.key, E.value);
+ if (E.value == ScriptCodeCompletionOption::KIND_FUNCTION) {
option.insert_text += "(";
}
r_options->push_back(option);
@@ -7362,6 +9145,16 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
return OK;
} break;
case COMPLETION_CALL_ARGUMENTS: {
+ StringName block_function;
+ BlockNode *block = completion_block;
+
+ while (block) {
+ if (block->parent_function) {
+ block_function = block->parent_function->name;
+ }
+ block = block->parent_block;
+ }
+
for (int i = 0; i < shader->functions.size(); i++) {
if (!shader->functions[i].callable) {
continue;
@@ -7370,6 +9163,13 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
String calltip;
calltip += get_datatype_name(shader->functions[i].function->return_type);
+
+ if (shader->functions[i].function->return_array_size > 0) {
+ calltip += "[";
+ calltip += itos(shader->functions[i].function->return_array_size);
+ calltip += "]";
+ }
+
calltip += " ";
calltip += shader->functions[i].name;
calltip += "(";
@@ -7401,6 +9201,12 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += " ";
calltip += shader->functions[i].function->arguments[j].name;
+ if (shader->functions[i].function->arguments[j].array_size > 0) {
+ calltip += "[";
+ calltip += itos(shader->functions[i].function->arguments[j].array_size);
+ calltip += "]";
+ }
+
if (j == completion_argument) {
calltip += char32_t(0xFFFF);
}
@@ -7421,6 +9227,45 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
String calltip;
bool low_end = RenderingServer::get_singleton()->is_low_end();
+ if (stages && stages->has(block_function)) {
+ for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[block_function].stage_functions) {
+ if (completion_function == E.key) {
+ calltip += get_datatype_name(E.value.return_type);
+ calltip += " ";
+ calltip += E.key;
+ calltip += "(";
+
+ for (int i = 0; i < E.value.arguments.size(); i++) {
+ if (i > 0) {
+ calltip += ", ";
+ } else {
+ calltip += " ";
+ }
+
+ if (i == completion_argument) {
+ calltip += char32_t(0xFFFF);
+ }
+
+ calltip += get_datatype_name(E.value.arguments[i].type);
+ calltip += " ";
+ calltip += E.value.arguments[i].name;
+
+ if (i == completion_argument) {
+ calltip += char32_t(0xFFFF);
+ }
+ }
+
+ if (E.value.arguments.size()) {
+ calltip += " ";
+ }
+ calltip += ")";
+
+ r_call_hint = calltip;
+ return OK;
+ }
+ }
+ }
+
while (builtin_func_defs[idx].name) {
if (low_end && builtin_func_defs[idx].high_end) {
idx++;
@@ -7428,10 +9273,16 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
int idx2 = 0;
- int out_arg = -1;
+ Set<int> out_args;
while (builtin_func_out_args[idx2].name != nullptr) {
if (builtin_func_out_args[idx2].name == builtin_func_defs[idx].name) {
- out_arg = builtin_func_out_args[idx2].argument;
+ for (int i = 0; i < BuiltinFuncOutArgs::MAX_ARGS; i++) {
+ int arg = builtin_func_out_args[idx2].arguments[i];
+ if (arg == -1) {
+ break;
+ }
+ out_args.insert(arg);
+ }
break;
}
idx2++;
@@ -7453,7 +9304,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += "(";
bool found_arg = false;
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < BuiltinFuncDef::MAX_ARGS - 1; i++) {
if (builtin_func_defs[idx].args[i] == TYPE_VOID) {
break;
}
@@ -7468,12 +9319,18 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += char32_t(0xFFFF);
}
- if (out_arg >= 0 && i == out_arg) {
+ if (out_args.has(i)) {
calltip += "out ";
}
calltip += get_datatype_name(builtin_func_defs[idx].args[i]);
+ String arg_name = (String)builtin_func_defs[idx].args_names[i];
+ if (!arg_name.is_empty()) {
+ calltip += " ";
+ calltip += arg_name;
+ }
+
if (i == completion_argument) {
calltip += char32_t(0xFFFF);
}
@@ -7523,15 +9380,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: {
}
}
@@ -7563,6 +9411,16 @@ ShaderLanguage::ShaderNode *ShaderLanguage::get_shader() {
ShaderLanguage::ShaderLanguage() {
nodes = nullptr;
completion_class = TAG_GLOBAL;
+
+#if DEBUG_ENABLED
+ warnings_check_map.insert(ShaderWarning::UNUSED_CONSTANT, &used_constants);
+ warnings_check_map.insert(ShaderWarning::UNUSED_FUNCTION, &used_functions);
+ warnings_check_map.insert(ShaderWarning::UNUSED_STRUCT, &used_structs);
+ warnings_check_map.insert(ShaderWarning::UNUSED_UNIFORM, &used_uniforms);
+ warnings_check_map.insert(ShaderWarning::UNUSED_VARYING, &used_varyings);
+
+ warnings_check_map2.insert(ShaderWarning::UNUSED_LOCAL_VARIABLE, &used_local_vars);
+#endif // DEBUG_ENABLED
}
ShaderLanguage::~ShaderLanguage() {