diff options
Diffstat (limited to 'servers/visual/shader_language.cpp')
-rw-r--r-- | servers/visual/shader_language.cpp | 150 |
1 files changed, 92 insertions, 58 deletions
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index d9f2c949e9..2069e64c43 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -124,6 +124,9 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "TYPE_ISAMPLER2D", "TYPE_USAMPLER2D", "TYPE_SAMPLERCUBE", + "INTERPOLATION_FLAT", + "INTERPOLATION_NO_PERSPECTIVE", + "INTERPOLATION_SMOOTH", "PRECISION_LOW", "PRECISION_MID", "PRECISION_HIGH", @@ -1489,11 +1492,6 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID } }, { "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID } }, - { "abs", TYPE_UINT, { TYPE_UINT, TYPE_VOID } }, - { "abs", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID } }, - { "abs", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID } }, - { "abs", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID } }, - { "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, { "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, { "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, @@ -1608,7 +1606,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } }, { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BOOL, TYPE_VOID } }, - { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC3, TYPE_VOID } }, + { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID } }, { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID } }, { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } }, @@ -1627,24 +1625,24 @@ 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 } }, { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID } }, { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID } }, - { "floatBitsToUInt", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID } }, - { "floatBitsToUInt", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID } }, - { "floatBitsToUInt", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID } }, - { "floatBitsToUInt", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID } }, + { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID } }, + { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID } }, + { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID } }, + { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID } }, { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID } }, { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID } }, @@ -2209,6 +2207,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(); @@ -2271,7 +2300,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI if (p_node->type == Node::TYPE_OPERATOR) { OperatorNode *op = static_cast<OperatorNode *>(p_node); - if (op->type == OP_INDEX) { + if (op->op == OP_INDEX) { return _validate_assign(op->arguments[0], p_builtin_types); } } @@ -2679,7 +2708,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()) { @@ -2698,7 +2726,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; @@ -2723,7 +2751,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; @@ -2747,7 +2775,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; @@ -2762,11 +2790,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; @@ -2968,7 +2991,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expr_pos++; if (expr_pos == expression.size()) { //can happen.. - _set_error("Unexpected end of expression.."); + _set_error("Unexpected end of expression..."); return NULL; } } @@ -3005,12 +3028,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } else if (is_ternary) { if (next_op < 1 || next_op >= (expression.size() - 1)) { - _set_error("Parser bug.."); + _set_error("Parser bug..."); ERR_FAIL_V(NULL); } if (next_op + 2 >= expression.size() || !expression[next_op + 2].is_op || expression[next_op + 2].op != OP_SELECT_ELSE) { - _set_error("Mising matching ':' for select operator"); + _set_error("Missing matching ':' for select operator"); return NULL; } @@ -3041,7 +3064,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } else { if (next_op < 1 || next_op >= (expression.size() - 1)) { - _set_error("Parser bug.."); + _set_error("Parser bug..."); ERR_FAIL_V(NULL); } @@ -3050,7 +3073,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (expression[next_op - 1].is_op) { - _set_error("Parser bug.."); + _set_error("Parser bug..."); ERR_FAIL_V(NULL); } @@ -3066,7 +3089,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons // can be followed by a unary op in a valid combination, // due to how precedence works, unaries will always disappear first - _set_error("Parser bug.."); + _set_error("Parser bug..."); } op->arguments.push_back(expression[next_op - 1].node); //expression goes as left @@ -3119,9 +3142,18 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha 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; @@ -3215,7 +3247,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui precision = get_token_precision(tk.type); tk = _get_token(); if (!is_token_nonvoid_datatype(tk.type)) { - _set_error("Expected datatype after precission"); + _set_error("Expected datatype after precision"); return ERR_PARSE_ERROR; } } @@ -3513,7 +3545,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui if (!p_can_break) { //all is good - _set_error("Contiuning is not allowed here"); + _set_error("Continuing is not allowed here"); } ControlFlowNode *flow = alloc_node<ControlFlowNode>(); @@ -3664,7 +3696,8 @@ 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? + + if (!uniform && (type < TYPE_FLOAT || type > TYPE_VEC4)) { _set_error("Invalid type for varying, only float,vec2,vec3,vec4 allowed."); return ERR_PARSE_ERROR; } @@ -3699,26 +3732,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct //todo parse default value tk = _get_token(); - if (tk.type == TK_OP_ASSIGN) { - - Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>()); - if (!expr) - return ERR_PARSE_ERROR; - if (expr->type != Node::TYPE_CONSTANT) { - _set_error("Expected constant expression after '='"); - return ERR_PARSE_ERROR; - } - - ConstantNode *cn = static_cast<ConstantNode *>(expr); - - uniform.default_value.resize(cn->values.size()); - - if (!convert_constant(cn, uniform.type, uniform.default_value.ptrw())) { - _set_error("Can't convert constant to " + get_datatype_name(uniform.type)); - return ERR_PARSE_ERROR; - } - tk = _get_token(); - } if (tk.type == TK_COLON) { //hint @@ -3834,6 +3847,27 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } + if (tk.type == TK_OP_ASSIGN) { + + Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>()); + if (!expr) + return ERR_PARSE_ERROR; + if (expr->type != Node::TYPE_CONSTANT) { + _set_error("Expected constant expression after '='"); + return ERR_PARSE_ERROR; + } + + ConstantNode *cn = static_cast<ConstantNode *>(expr); + + uniform.default_value.resize(cn->values.size()); + + if (!convert_constant(cn, uniform.type, uniform.default_value.ptrw())) { + _set_error("Can't convert constant to " + get_datatype_name(uniform.type)); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + } + shader->uniforms[name] = uniform; if (tk.type != TK_SEMICOLON) { |