diff options
Diffstat (limited to 'servers/visual/shader_language.cpp')
-rw-r--r-- | servers/visual/shader_language.cpp | 380 |
1 files changed, 319 insertions, 61 deletions
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index ba8d134b5c..8705033326 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -123,6 +123,12 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "TYPE_SAMPLER2D", "TYPE_ISAMPLER2D", "TYPE_USAMPLER2D", + "TYPE_SAMPLER2DARRAY", + "TYPE_ISAMPLER2DARRAY", + "TYPE_USAMPLER2DARRAY", + "TYPE_SAMPLER3D", + "TYPE_ISAMPLER3D", + "TYPE_USAMPLER3D", "TYPE_SAMPLERCUBE", "INTERPOLATION_FLAT", "INTERPOLATION_NO_PERSPECTIVE", @@ -257,6 +263,12 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_TYPE_SAMPLER2D, "sampler2D" }, { TK_TYPE_ISAMPLER2D, "isampler2D" }, { TK_TYPE_USAMPLER2D, "usampler2D" }, + { TK_TYPE_SAMPLER2DARRAY, "sampler2DArray" }, + { TK_TYPE_ISAMPLER2DARRAY, "isampler2DArray" }, + { TK_TYPE_USAMPLER2DARRAY, "usampler2DArray" }, + { TK_TYPE_SAMPLER3D, "sampler3D" }, + { TK_TYPE_ISAMPLER3D, "isampler3D" }, + { TK_TYPE_USAMPLER3D, "usampler3D" }, { TK_TYPE_SAMPLERCUBE, "samplerCube" }, { TK_INTERPOLATION_FLAT, "flat" }, { TK_INTERPOLATION_NO_PERSPECTIVE, "noperspective" }, @@ -516,13 +528,14 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { bool hexa_found = false; bool sign_found = false; bool minus_exponent_found = false; + bool float_suffix_found = false; String str; int i = 0; while (true) { if (GETCHAR(i) == '.') { - if (period_found || exponent_found) + if (period_found || exponent_found || hexa_found || float_suffix_found) return _make_token(TK_ERROR, "Invalid numeric constant"); period_found = true; } else if (GETCHAR(i) == 'x') { @@ -530,11 +543,16 @@ 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) + if (hexa_found || 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) + return _make_token(TK_ERROR, "Invalid numeric constant"); + float_suffix_found = true; } else if (_is_number(GETCHAR(i))) { - //all ok + if (float_suffix_found) + return _make_token(TK_ERROR, "Invalid numeric constant"); } else if (hexa_found && _is_hex(GETCHAR(i))) { } else if ((GETCHAR(i) == '-' || GETCHAR(i) == '+') && exponent_found) { @@ -550,21 +568,60 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { i++; } - if (!_is_number(str[str.length() - 1])) - return _make_token(TK_ERROR, "Invalid numeric constant"); + CharType last_char = str[str.length() - 1]; + + if (hexa_found) { + //hex integers eg."0xFF" or "0x12AB", etc - NOT supported yet + return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant - Not supported"); + } else if (period_found || float_suffix_found) { + //floats + if (period_found) { + if (float_suffix_found) { + //checks for eg "1.f" or "1.99f" notations + if (last_char != 'f') { + return _make_token(TK_ERROR, "Invalid (float) numeric constant"); + } + } else { + //checks for eg. "1." or "1.99" notations + if (last_char != '.' && !_is_number(last_char)) { + return _make_token(TK_ERROR, "Invalid (float) numeric constant"); + } + } + } else if (float_suffix_found) { + // if no period found the float suffix must be the last character, like in "2f" for "2.0" + if (last_char != 'f') { + return _make_token(TK_ERROR, "Invalid (float) numeric constant"); + } + } + + if (float_suffix_found) { + //strip the suffix + str = str.left(str.length() - 1); + //compensate reading cursor position + char_idx += 1; + } + + if (!str.is_valid_float()) { + return _make_token(TK_ERROR, "Invalid (float) numeric constant"); + } + } else { + //integers + if (!_is_number(last_char)) { + return _make_token(TK_ERROR, "Invalid (integer) numeric constant"); + } + if (!str.is_valid_integer()) { + return _make_token(TK_ERROR, "Invalid numeric constant"); + } + } char_idx += str.length(); Token tk; - if (period_found || minus_exponent_found) + if (period_found || minus_exponent_found || float_suffix_found) tk.type = TK_REAL_CONSTANT; else tk.type = TK_INT_CONSTANT; - if (!str.is_valid_float()) { - return _make_token(TK_ERROR, "Invalid numeric constant"); - } - - tk.constant = str.to_double(); + tk.constant = str.to_double(); //wont work with hex tk.line = tk_line; return tk; @@ -612,6 +669,8 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { } ERR_PRINT("BUG"); return Token(); + +#undef GETCHAR } String ShaderLanguage::token_debug(const String &p_code) { @@ -658,6 +717,12 @@ bool ShaderLanguage::is_token_datatype(TokenType p_type) { p_type == TK_TYPE_SAMPLER2D || p_type == TK_TYPE_ISAMPLER2D || p_type == TK_TYPE_USAMPLER2D || + p_type == TK_TYPE_SAMPLER2DARRAY || + p_type == TK_TYPE_ISAMPLER2DARRAY || + p_type == TK_TYPE_USAMPLER2DARRAY || + p_type == TK_TYPE_SAMPLER3D || + p_type == TK_TYPE_ISAMPLER3D || + p_type == TK_TYPE_USAMPLER3D || p_type == TK_TYPE_SAMPLERCUBE); } @@ -729,6 +794,12 @@ String ShaderLanguage::get_datatype_name(DataType p_type) { case TYPE_SAMPLER2D: return "sampler2D"; case TYPE_ISAMPLER2D: return "isampler2D"; case TYPE_USAMPLER2D: return "usampler2D"; + case TYPE_SAMPLER2DARRAY: return "sampler2DArray"; + case TYPE_ISAMPLER2DARRAY: return "isampler2DArray"; + case TYPE_USAMPLER2DARRAY: return "usampler2DArray"; + case TYPE_SAMPLER3D: return "sampler3D"; + case TYPE_ISAMPLER3D: return "isampler3D"; + case TYPE_USAMPLER3D: return "usampler3D"; case TYPE_SAMPLERCUBE: return "samplerCube"; } @@ -1376,6 +1447,15 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID } }, { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID } }, + //conversion between matrixes + + { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID } }, + { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID } }, + { "mat3", TYPE_MAT3, { TYPE_MAT2, TYPE_VOID } }, + { "mat3", TYPE_MAT3, { TYPE_MAT4, TYPE_VOID } }, + { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID } }, + { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID } }, + //builtins - trigonometry { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, @@ -1625,14 +1705,14 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID } }, { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID } }, - { "isnan", TYPE_BOOL, { TYPE_VEC2, TYPE_VOID } }, - { "isnan", TYPE_BOOL, { TYPE_VEC3, TYPE_VOID } }, - { "isnan", TYPE_BOOL, { TYPE_VEC4, TYPE_VOID } }, + { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID } }, + { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID } }, + { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID } }, { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID } }, - { "isinf", TYPE_BOOL, { TYPE_VEC2, TYPE_VOID } }, - { "isinf", TYPE_BOOL, { TYPE_VEC3, TYPE_VOID } }, - { "isinf", TYPE_BOOL, { TYPE_VEC4, TYPE_VOID } }, + { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID } }, + { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID } }, + { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID } }, { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID } }, { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID } }, @@ -1791,6 +1871,12 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID } }, { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID } }, { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID } }, { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID } }, { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID } }, @@ -1802,6 +1888,24 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID } }, { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + + { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + + { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + + { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID } }, { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, @@ -1820,15 +1924,38 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID } }, + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, + + { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID } }, + { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, + + { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID } }, + { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } }, { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } }, { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } }, + { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + + { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, @@ -1841,6 +1968,12 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, + { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, + { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, + { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, + { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } }, + { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } }, + { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } }, { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } }, { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, @@ -2128,7 +2261,16 @@ bool ShaderLanguage::is_scalar_type(DataType p_type) { bool ShaderLanguage::is_sampler_type(DataType p_type) { - return p_type == TYPE_SAMPLER2D || p_type == TYPE_ISAMPLER2D || p_type == TYPE_USAMPLER2D || p_type == TYPE_SAMPLERCUBE; + 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; } void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { @@ -2207,6 +2349,37 @@ ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) { return scalar_types[p_type]; } +int ShaderLanguage::get_cardinality(DataType p_type) { + static const int cardinality_table[] = { + 0, + 1, + 2, + 3, + 4, + 1, + 2, + 3, + 4, + 1, + 2, + 3, + 4, + 1, + 2, + 3, + 4, + 2, + 3, + 4, + 1, + 1, + 1, + 1, + }; + + return cardinality_table[p_type]; +} + bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier) { identifier = StringName(); @@ -2264,24 +2437,54 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const { return false; } -bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types) { +bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message) { if (p_node->type == Node::TYPE_OPERATOR) { OperatorNode *op = static_cast<OperatorNode *>(p_node); - if (op->type == OP_INDEX) { - return _validate_assign(op->arguments[0], p_builtin_types); + + if (op->op == OP_INDEX) { + return _validate_assign(op->arguments[0], p_builtin_types, r_message); + + } else if (_is_operator_assign(op->op)) { + //chained assignment + return _validate_assign(op->arguments[1], p_builtin_types, r_message); + + } else if (op->op == OP_CALL) { + if (r_message) + *r_message = RTR("Assignment to function."); + return false; } - } - if (p_node->type == Node::TYPE_VARIABLE) { + } else if (p_node->type == Node::TYPE_MEMBER) { + + MemberNode *member = static_cast<MemberNode *>(p_node); + return _validate_assign(member->owner, p_builtin_types, r_message); + + } else if (p_node->type == Node::TYPE_VARIABLE) { VariableNode *var = static_cast<VariableNode *>(p_node); - if (p_builtin_types.has(var->name) && p_builtin_types[var->name].constant) { - return false; //ops not valid + + if (shader->uniforms.has(var->name)) { + if (r_message) + *r_message = RTR("Assignment to uniform."); + 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 (!(p_builtin_types.has(var->name) && p_builtin_types[var->name].constant)) { + return true; } } - return true; + + if (r_message) + *r_message = "Assignment to constant expression."; + return false; } ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) { @@ -2429,7 +2632,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons //add to current function as dependency for (int j = 0; j < shader->functions.size(); j++) { if (shader->functions[j].name == current_function) { - shader->functions[j].uses_function.insert(name); + shader->functions.write[j].uses_function.insert(name); break; } } @@ -2514,7 +2717,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons TkPos pos = _get_tkpos(); tk = _get_token(); - if (tk.type == TK_PERIOD) { + if (tk.type == TK_CURSOR) { + //do nothing + } else if (tk.type == TK_PERIOD) { StringName identifier; if (_get_completable_identifier(p_block, COMPLETION_INDEX, identifier)) { @@ -2677,7 +2882,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return NULL; } - bool index_valid = false; DataType member_type = TYPE_VOID; switch (expr->get_datatype()) { @@ -2696,7 +2900,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Only integer constants are allowed as index at the moment"); return NULL; } - index_valid = true; + switch (expr->get_datatype()) { case TYPE_BVEC2: member_type = TYPE_BOOL; break; case TYPE_VEC2: member_type = TYPE_FLOAT; break; @@ -2721,7 +2925,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Only integer constants are allowed as index at the moment"); return NULL; } - index_valid = true; + switch (expr->get_datatype()) { case TYPE_BVEC3: member_type = TYPE_BOOL; break; case TYPE_VEC3: member_type = TYPE_FLOAT; break; @@ -2745,7 +2949,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Only integer constants are allowed as index at the moment"); return NULL; } - index_valid = true; + switch (expr->get_datatype()) { case TYPE_BVEC4: member_type = TYPE_BOOL; break; case TYPE_VEC4: member_type = TYPE_FLOAT; break; @@ -2760,11 +2964,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } } - if (!index_valid) { - _set_error("Invalid index"); - return NULL; - } - OperatorNode *op = alloc_node<OperatorNode>(); op->op = OP_INDEX; op->return_cache = member_type; @@ -2983,8 +3182,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } op->arguments.push_back(expression[i + 1].node); - expression[i].is_op = false; - expression[i].node = op; + expression.write[i].is_op = false; + expression.write[i].node = op; if (!_validate_operator(op, &op->return_cache)) { @@ -3018,8 +3217,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons op->arguments.push_back(expression[next_op + 1].node); op->arguments.push_back(expression[next_op + 3].node); - expression[next_op - 1].is_op = false; - expression[next_op - 1].node = op; + expression.write[next_op - 1].is_op = false; + expression.write[next_op - 1].node = op; if (!_validate_operator(op, &op->return_cache)) { String at; @@ -3052,10 +3251,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons ERR_FAIL_V(NULL); } - if (_is_operator_assign(op->op) && !_validate_assign(expression[next_op - 1].node, p_builtin_types)) { + if (_is_operator_assign(op->op)) { - _set_error("Assignment to constant expression."); - return NULL; + String assign_message; + if (!_validate_assign(expression[next_op - 1].node, p_builtin_types, &assign_message)) { + + _set_error(assign_message); + return NULL; + } } if (expression[next_op + 1].is_op) { @@ -3069,7 +3272,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons op->arguments.push_back(expression[next_op - 1].node); //expression goes as left op->arguments.push_back(expression[next_op + 1].node); //next expression goes as right - expression[next_op - 1].node = op; + expression.write[next_op - 1].node = op; //replace all 3 nodes by this operator and make it an expression @@ -3111,15 +3314,24 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha for (int i = 1; i < op->arguments.size(); i++) { - op->arguments[i] = _reduce_expression(p_block, op->arguments[i]); + op->arguments.write[i] = _reduce_expression(p_block, op->arguments[i]); if (op->arguments[i]->type == Node::TYPE_CONSTANT) { ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[i]); if (get_scalar_type(cn->datatype) == base) { - for (int j = 0; j < cn->values.size(); j++) { - values.push_back(cn->values[j]); - } + int cardinality = get_cardinality(op->arguments[i]->get_datatype()); + if (cn->values.size() == cardinality) { + + for (int j = 0; j < cn->values.size(); j++) { + values.push_back(cn->values[j]); + } + } else if (cn->values.size() == 1) { + + for (int j = 0; j < cardinality; j++) { + values.push_back(cn->values[0]); + } + } // else: should be filtered by the parser as it's an invalid constructor } else if (get_scalar_type(cn->datatype) == cn->datatype) { ConstantNode::Value v; @@ -3142,7 +3354,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha return cn; } else if (op->op == OP_NEGATE) { - op->arguments[0] = _reduce_expression(p_block, op->arguments[0]); + op->arguments.write[0] = _reduce_expression(p_block, op->arguments[0]); if (op->arguments[0]->type == Node::TYPE_CONSTANT) { ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[0]); @@ -3549,7 +3761,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui return OK; } -Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) { +Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) { Token tk = _get_token(); @@ -3608,7 +3820,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - if (!p_render_modes.has(mode)) { + if (p_render_modes.find(mode) == -1) { _set_error("Invalid render mode: '" + String(mode) + "'"); return ERR_PARSE_ERROR; } @@ -3662,8 +3874,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct _set_error("void datatype not allowed here"); return ERR_PARSE_ERROR; } - if (!uniform && type < TYPE_FLOAT && type > TYPE_VEC4) { // FIXME: always false! should it be || instead? - _set_error("Invalid type for varying, only float,vec2,vec3,vec4 allowed."); + + if (!uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) { + _set_error("Invalid type for varying, only float,vec2,vec3,vec4,mat2,mat3,mat4 allowed."); return ERR_PARSE_ERROR; } @@ -4027,13 +4240,58 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return OK; } +// skips over whitespace and /* */ and // comments +static int _get_first_ident_pos(const String &p_code) { + + int idx = 0; + +#define GETCHAR(m_idx) (((idx + m_idx) < p_code.length()) ? p_code[idx + m_idx] : CharType(0)) + + while (true) { + if (GETCHAR(0) == '/' && GETCHAR(1) == '/') { + idx += 2; + while (true) { + if (GETCHAR(0) == 0) return 0; + if (GETCHAR(0) == '\n') { + idx++; + break; // loop + } + idx++; + } + } else if (GETCHAR(0) == '/' && GETCHAR(1) == '*') { + idx += 2; + while (true) { + if (GETCHAR(0) == 0) return 0; + if (GETCHAR(0) == '*' && GETCHAR(1) == '/') { + idx += 2; + break; // loop + } + idx++; + } + } else { + switch (GETCHAR(0)) { + case ' ': + case '\t': + case '\r': + case '\n': { + idx++; + } break; // switch + default: + return idx; + } + } + } + +#undef GETCHAR +} + String ShaderLanguage::get_shader_type(const String &p_code) { bool reading_type = false; String cur_identifier; - for (int i = 0; i < p_code.length(); i++) { + for (int i = _get_first_ident_pos(p_code); i < p_code.length(); i++) { if (p_code[i] == ';') { break; @@ -4062,7 +4320,7 @@ 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 Set<String> &p_render_modes, const Set<String> &p_shader_types) { +Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) { clear(); @@ -4079,7 +4337,7 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi return OK; } -Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint) { +Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint) { clear(); @@ -4095,13 +4353,13 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct switch (completion_type) { case COMPLETION_NONE: { - //do none - return ERR_PARSE_ERROR; + //do nothing + return OK; } break; case COMPLETION_RENDER_MODE: { - for (const Set<String>::Element *E = p_render_modes.front(); E; E = E->next()) { + for (int i = 0; i < p_render_modes.size(); i++) { - r_options->push_back(E->get()); + r_options->push_back(p_render_modes[i]); } return OK; |