diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 0e6c0e4bf66..0c40fd4e9fa 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -303,8 +303,8 @@ String ShaderCompiler::_get_sampler_name(ShaderLanguage::TextureFilter p_filter, void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const HashMap &p_func_code, String &r_to_add, HashSet &added) { int fidx = -1; - for (int i = 0; i < p_node->functions.size(); i++) { - if (p_node->functions[i].name == p_for_func) { + for (int i = 0; i < p_node->vfunctions.size(); i++) { + if (p_node->vfunctions[i].name == p_for_func) { fidx = i; break; } @@ -314,7 +314,7 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str Vector uses_functions; - for (const StringName &E : p_node->functions[fidx].uses_function) { + for (const StringName &E : p_node->vfunctions[fidx].uses_function) { uses_functions.push_back(E); } uses_functions.sort_custom(); //ensure order is deterministic so the same shader is always produced @@ -328,9 +328,9 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str SL::FunctionNode *fnode = nullptr; - for (int i = 0; i < p_node->functions.size(); i++) { - if (p_node->functions[i].name == uses_functions[k]) { - fnode = p_node->functions[i].function; + for (int i = 0; i < p_node->vfunctions.size(); i++) { + if (p_node->vfunctions[i].name == uses_functions[k]) { + fnode = p_node->vfunctions[i].function; break; } } @@ -765,8 +765,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene HashMap function_code; //code for functions - for (int i = 0; i < pnode->functions.size(); i++) { - SL::FunctionNode *fnode = pnode->functions[i].function; + for (int i = 0; i < pnode->vfunctions.size(); i++) { + SL::FunctionNode *fnode = pnode->vfunctions[i].function; function = fnode; current_func_name = fnode->name; function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); @@ -777,8 +777,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene HashSet added_funcs_per_stage[STAGE_MAX]; - for (int i = 0; i < pnode->functions.size(); i++) { - SL::FunctionNode *fnode = pnode->functions[i].function; + for (int i = 0; i < pnode->vfunctions.size(); i++) { + SL::FunctionNode *fnode = pnode->vfunctions[i].function; function = fnode; @@ -1150,9 +1150,9 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene const bool is_internal_func = internal_functions.has(vnode->name); if (!is_internal_func) { - for (int i = 0; i < shader->functions.size(); i++) { - if (shader->functions[i].name == vnode->name) { - func = shader->functions[i].function; + for (int i = 0; i < shader->vfunctions.size(); i++) { + if (shader->vfunctions[i].name == vnode->name) { + func = shader->vfunctions[i].function; break; } } diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 1460a918260..f86e1900fbe 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -1433,17 +1433,17 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea return true; } - for (int i = 0; i < shader->functions.size(); i++) { - if (!shader->functions[i].callable) { + for (int i = 0; i < shader->vfunctions.size(); i++) { + if (!shader->vfunctions[i].callable) { continue; } - if (shader->functions[i].name == p_identifier) { + if (shader->vfunctions[i].name == p_identifier) { if (r_data_type) { - *r_data_type = shader->functions[i].function->return_type; + *r_data_type = shader->vfunctions[i].function->return_type; } if (r_array_size) { - *r_array_size = shader->functions[i].function->return_array_size; + *r_array_size = shader->vfunctions[i].function->return_array_size; } if (r_type) { *r_type = IDENTIFIER_FUNCTION; @@ -3391,18 +3391,18 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI bool exists = false; String arg_list = ""; - for (int i = 0; i < shader->functions.size(); i++) { - if (name != shader->functions[i].name) { + for (int i = 0; i < shader->vfunctions.size(); i++) { + if (name != shader->vfunctions[i].name) { continue; } exists = true; - if (!shader->functions[i].callable) { + if (!shader->vfunctions[i].callable) { _set_error(vformat(RTR("Function '%s' can't be called from source code."), String(name))); return false; } - FunctionNode *pfunc = shader->functions[i].function; + FunctionNode *pfunc = shader->vfunctions[i].function; if (arg_list.is_empty()) { for (int j = 0; j < pfunc->arguments.size(); j++) { if (j > 0) { @@ -4640,10 +4640,10 @@ 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; 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]; + for (int i = 0; i < shader->vfunctions.size(); i++) { + if (shader->vfunctions[i].name == p_name) { + ERR_FAIL_INDEX_V(p_argument, shader->vfunctions[i].function->arguments.size(), false); + FunctionNode::Argument *arg = &shader->vfunctions[i].function->arguments.write[p_argument]; if (arg->tex_builtin_check) { _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."), p_argument, String(p_name))); return false; @@ -4674,10 +4674,10 @@ 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; 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]; + for (int i = 0; i < shader->vfunctions.size(); i++) { + if (shader->vfunctions[i].name == p_name) { + ERR_FAIL_INDEX_V(p_argument, shader->vfunctions[i].function->arguments.size(), false); + FunctionNode::Argument *arg = &shader->vfunctions[i].function->arguments.write[p_argument]; if (arg->tex_argument_check) { _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."), p_argument, String(p_name))); return false; @@ -5207,11 +5207,13 @@ 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) { + + // Non-builtin function call is forbidden for constant declaration. + if (is_const_decl) { + if (shader->functions.has(identifier)) { _set_error(RTR("Expected constant expression.")); + return nullptr; } - return nullptr; } const StringName &name = identifier; @@ -5238,12 +5240,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons //test if function was parsed first int function_index = -1; - for (int i = 0; i < shader->functions.size(); i++) { - if (shader->functions[i].name == name) { + for (int i = 0; i < shader->vfunctions.size(); i++) { + if (shader->vfunctions[i].name == name) { //add to current function as dependency - for (int j = 0; j < shader->functions.size(); j++) { - if (shader->functions[j].name == current_function) { - shader->functions.write[j].uses_function.insert(name); + for (int j = 0; j < shader->vfunctions.size(); j++) { + if (shader->vfunctions[j].name == current_function) { + shader->vfunctions.write[j].uses_function.insert(name); break; } } @@ -5276,7 +5278,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons //connect texture arguments, so we can cache in the //argument what type of filter and repeat to use - FunctionNode *call_function = shader->functions[function_index].function; + FunctionNode *call_function = shader->vfunctions[function_index].function; if (call_function) { func->return_cache = call_function->get_datatype(); func->struct_name = call_function->get_datatype_name(); @@ -9454,8 +9456,8 @@ Error ShaderLanguage::_parse_shader(const HashMap &p_f } } - for (int i = 0; i < shader->functions.size(); i++) { - if (!shader->functions[i].callable && shader->functions[i].name == name) { + for (int i = 0; i < shader->vfunctions.size(); i++) { + if (!shader->vfunctions[i].callable && shader->vfunctions[i].name == name) { _set_redefinition_error(String(name)); return ERR_PARSE_ERROR; } @@ -9470,7 +9472,8 @@ Error ShaderLanguage::_parse_shader(const HashMap &p_f function.function = func_node; - shader->functions.push_back(function); + shader->functions.insert(name, function); + shader->vfunctions.push_back(function); func_node->name = name; func_node->return_type = type; @@ -10114,8 +10117,8 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ continue; } bool found = false; - for (int i = 0; i < shader->functions.size(); i++) { - if (shader->functions[i].name == E.key) { + for (int i = 0; i < shader->vfunctions.size(); i++) { + if (shader->vfunctions[i].name == E.key) { found = true; break; } @@ -10235,11 +10238,11 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } } - for (int i = 0; i < shader->functions.size(); i++) { - if (!shader->functions[i].callable || shader->functions[i].name == skip_function) { + for (int i = 0; i < shader->vfunctions.size(); i++) { + if (!shader->vfunctions[i].callable || shader->vfunctions[i].name == skip_function) { continue; } - matches.insert(String(shader->functions[i].name), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); + matches.insert(String(shader->vfunctions[i].name), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); } int idx = 0; @@ -10297,26 +10300,26 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ block = block->parent_block; } - for (int i = 0; i < shader->functions.size(); i++) { - if (!shader->functions[i].callable) { + for (int i = 0; i < shader->vfunctions.size(); i++) { + if (!shader->vfunctions[i].callable) { continue; } - if (shader->functions[i].name == completion_function) { + if (shader->vfunctions[i].name == completion_function) { String calltip; - calltip += get_datatype_name(shader->functions[i].function->return_type); + calltip += get_datatype_name(shader->vfunctions[i].function->return_type); - if (shader->functions[i].function->return_array_size > 0) { + if (shader->vfunctions[i].function->return_array_size > 0) { calltip += "["; - calltip += itos(shader->functions[i].function->return_array_size); + calltip += itos(shader->vfunctions[i].function->return_array_size); calltip += "]"; } calltip += " "; - calltip += shader->functions[i].name; + calltip += shader->vfunctions[i].name; calltip += "("; - for (int j = 0; j < shader->functions[i].function->arguments.size(); j++) { + for (int j = 0; j < shader->vfunctions[i].function->arguments.size(); j++) { if (j > 0) { calltip += ", "; } else { @@ -10327,25 +10330,25 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ calltip += char32_t(0xFFFF); } - if (shader->functions[i].function->arguments[j].is_const) { + if (shader->vfunctions[i].function->arguments[j].is_const) { calltip += "const "; } - if (shader->functions[i].function->arguments[j].qualifier != ArgumentQualifier::ARGUMENT_QUALIFIER_IN) { - if (shader->functions[i].function->arguments[j].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT) { + if (shader->vfunctions[i].function->arguments[j].qualifier != ArgumentQualifier::ARGUMENT_QUALIFIER_IN) { + if (shader->vfunctions[i].function->arguments[j].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT) { calltip += "out "; } else { // ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT calltip += "inout "; } } - calltip += get_datatype_name(shader->functions[i].function->arguments[j].type); + calltip += get_datatype_name(shader->vfunctions[i].function->arguments[j].type); calltip += " "; - calltip += shader->functions[i].function->arguments[j].name; + calltip += shader->vfunctions[i].function->arguments[j].name; - if (shader->functions[i].function->arguments[j].array_size > 0) { + if (shader->vfunctions[i].function->arguments[j].array_size > 0) { calltip += "["; - calltip += itos(shader->functions[i].function->arguments[j].array_size); + calltip += itos(shader->vfunctions[i].function->arguments[j].array_size); calltip += "]"; } @@ -10354,7 +10357,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } } - if (shader->functions[i].function->arguments.size()) { + if (shader->vfunctions[i].function->arguments.size()) { calltip += " "; } calltip += ")"; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 0ddd27f0289..9893ba9a3cc 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -711,9 +711,10 @@ public: HashMap varyings; HashMap uniforms; HashMap structs; + HashMap functions; Vector render_modes; - Vector functions; + Vector vfunctions; Vector vconstants; Vector vstructs;