diff options
Diffstat (limited to 'servers/rendering/shader_language.cpp')
-rw-r--r-- | servers/rendering/shader_language.cpp | 125 |
1 files changed, 108 insertions, 17 deletions
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 59a2ff66f3..940363a7e8 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -90,8 +90,9 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "IDENTIFIER", "TRUE", "FALSE", - "REAL_CONSTANT", + "FLOAT_CONSTANT", "INT_CONSTANT", + "UINT_CONSTANT", "TYPE_VOID", "TYPE_BOOL", "TYPE_BVEC2", @@ -126,6 +127,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "INTERPOLATION_FLAT", "INTERPOLATION_SMOOTH", "CONST", + "STRUCT", "PRECISION_LOW", "PRECISION_MID", "PRECISION_HIGH", @@ -169,6 +171,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "CF_DO", "CF_SWITCH", "CF_CASE", + "CF_DEFAULT", "CF_BREAK", "CF_CONTINUE", "CF_RETURN", @@ -185,19 +188,26 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "SEMICOLON", "PERIOD", "UNIFORM", + "UNIFORM_GROUP", "INSTANCE", "GLOBAL", "VARYING", - "IN", - "OUT", - "INOUT", + "ARG_IN", + "ARG_OUT", + "ARG_INOUT", "RENDER_MODE", - "SOURCE_COLOR", "HINT_DEFAULT_WHITE_TEXTURE", "HINT_DEFAULT_BLACK_TEXTURE", "HINT_DEFAULT_TRANSPARENT_TEXTURE", "HINT_NORMAL_TEXTURE", + "HINT_ROUGHNESS_NORMAL_TEXTURE", + "HINT_ROUGHNESS_R", + "HINT_ROUGHNESS_G", + "HINT_ROUGHNESS_B", + "HINT_ROUGHNESS_A", + "HINT_ROUGHNESS_GRAY", "HINT_ANISOTROPY_TEXTURE", + "HINT_SOURCE_COLOR", "HINT_RANGE", "HINT_INSTANCE_INDEX", "HINT_SCREEN_TEXTURE", @@ -612,7 +622,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { char_idx += 2; include_positions.resize(include_positions.size() - 1); // Pop back. - tk_line = include_positions[include_positions.size() - 1].line; // Restore line. + tk_line = include_positions[include_positions.size() - 1].line - 1; // Restore line. } else { return _make_token(TK_ERROR, "Invalid include enter/exit hint token (@@> and @@<)"); @@ -1215,7 +1225,7 @@ void ShaderLanguage::clear() { char_idx = 0; error_set = false; error_str = ""; - last_const = false; + is_const_decl = false; while (nodes) { Node *n = nodes; nodes = nodes->next; @@ -2827,6 +2837,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, + // dFdxCoarse + + { "dFdxCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + + // dFdxFine + + { "dFdxFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + // dFdy { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, @@ -2834,6 +2858,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, + // dFdyCoarse + + { "dFdyCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + + // dFdyFine + + { "dFdyFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + // fwidth { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, @@ -2841,6 +2879,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, + // fwidthCoarse + + { "fwidthCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + + // fwidthFine + + { "fwidthFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + // Sub-functions. // array @@ -2849,10 +2901,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { // 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 }, + { "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, // Packing/Unpacking functions. @@ -3509,6 +3561,14 @@ bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Functio return false; } + if (is_const_decl && arg->type == Node::TYPE_VARIABLE) { + const VariableNode *var = static_cast<const VariableNode *>(arg); + if (!var->is_const) { + _set_error(RTR("Expected constant expression.")); + return false; + } + } + p_func->arguments.push_back(arg); tk = _get_token(); @@ -4478,14 +4538,14 @@ bool ShaderLanguage::_check_node_constness(const Node *p_node) const { case Node::TYPE_CONSTANT: break; case Node::TYPE_VARIABLE: { - const VariableNode *varn = static_cast<const VariableNode *>(p_node); - if (!varn->is_const) { + const VariableNode *var_node = static_cast<const VariableNode *>(p_node); + if (!var_node->is_const) { return false; } } break; case Node::TYPE_ARRAY: { - const ArrayNode *arrn = static_cast<const ArrayNode *>(p_node); - if (!arrn->is_const) { + const ArrayNode *arr_node = static_cast<const ArrayNode *>(p_node); + if (!arr_node->is_const) { return false; } } break; @@ -5132,6 +5192,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expr = func; } else { //a function call + if (p_block == nullptr) { // Non-constructor function call in global space is forbidden. + if (is_const_decl) { + _set_error(RTR("Expected constant expression.")); + } + return nullptr; + } const StringName &name = identifier; @@ -5399,9 +5465,19 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } } else { if (!_find_identifier(p_block, false, p_function_info, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) { + if (identifier == "SCREEN_TEXTURE" || identifier == "DEPTH_TEXTURE" || identifier == "NORMAL_ROUGHNESS_TEXTURE") { + String name = String(identifier); + String name_lower = name.to_lower(); + _set_error(vformat(RTR("%s has been removed in favor of using hint_%s with a uniform.\nTo continue with minimal code changes add 'uniform sampler2D %s : hint_%s, filter_linear_mipmap;' near the top of your shader."), name, name_lower, name, name_lower)); + return nullptr; + } _set_error(vformat(RTR("Unknown identifier in expression: '%s'."), String(identifier))); return nullptr; } + if (is_const_decl && !is_const) { + _set_error(RTR("Expected constant expression.")); + return nullptr; + } if (ident_type == IDENTIFIER_VARYING) { TkPos prev_pos = _get_tkpos(); Token next_token = _get_token(); @@ -6477,7 +6553,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons OperatorNode *op = alloc_node<OperatorNode>(); op->op = expression[i].op; if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_function_info)) { - _set_error(RTR("Can't use increment/decrement operator in a constant expression.")); + _set_error(RTR("Invalid use of increment/decrement operator in a constant expression.")); return nullptr; } op->arguments.push_back(expression[i + 1].node); @@ -6919,6 +6995,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } } #endif // DEBUG_ENABLED + is_const_decl = is_const; BlockNode::Variable var; var.type = type; @@ -7175,6 +7252,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun vdnode->declarations.push_back(decl); p_block->variables[name] = var; + is_const_decl = false; if (!fixed_array_size) { array_size = 0; @@ -8227,6 +8305,10 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f _set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier)); return ERR_PARSE_ERROR; } + if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { + _set_error(RTR("Uniform instances are not supported in gl_compatibility shaders.")); + return ERR_PARSE_ERROR; + } if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) { tk = _get_token(); if (tk.type != TK_UNIFORM) { @@ -8339,7 +8421,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f _set_error(vformat(RTR("The '%s' data type is not supported for uniforms."), "struct")); return ERR_PARSE_ERROR; } else { - _set_error(vformat(RTR("The '%s' data type not allowed here."), "struct")); + _set_error(vformat(RTR("The '%s' data type is not allowed here."), "struct")); return ERR_PARSE_ERROR; } } @@ -8691,14 +8773,21 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f case TK_HINT_SCREEN_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_SCREEN_TEXTURE; --texture_uniforms; + --texture_binding; } break; case TK_HINT_NORMAL_ROUGHNESS_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE; --texture_uniforms; + --texture_binding; + if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { + _set_error(RTR("'hint_normal_roughness_texture' is not supported in gl_compatibility shaders.")); + return ERR_PARSE_ERROR; + } } break; case TK_HINT_DEPTH_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE; --texture_uniforms; + --texture_binding; } break; case TK_FILTER_NEAREST: { new_filter = FILTER_NEAREST; @@ -9032,6 +9121,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f constant.precision = precision; constant.initializer = nullptr; constant.array_size = array_size; + is_const_decl = true; if (tk.type == TK_BRACKET_OPEN) { Error error = _parse_array_size(nullptr, constants, false, nullptr, &constant.array_size, &unknown_size); @@ -9291,6 +9381,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f unknown_size = false; } else if (tk.type == TK_SEMICOLON) { + is_const_decl = false; break; } else { _set_expected_error(",", ";"); |