Browse Source

Merge pull request #63424 from Chaosus/shader_preprocessor_inc_fix

Rémi Verschelde 3 years ago
parent
commit
49b0aa93e3

+ 26 - 4
editor/plugins/shader_editor_plugin.cpp

@@ -208,7 +208,30 @@ void ShaderTextEditor::_load_theme_settings() {
 	// to distinguish from keywords at a quick glance.
 
 	List<String> built_ins;
-	if (shader.is_valid()) {
+
+	if (shader_inc.is_valid()) {
+		for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+			for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i))) {
+				for (const KeyValue<StringName, ShaderLanguage::BuiltInInfo> &F : E.value.built_ins) {
+					built_ins.push_back(F.key);
+				}
+			}
+
+			const Vector<ShaderLanguage::ModeInfo> &modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
+
+			for (int j = 0; j < modes.size(); j++) {
+				const ShaderLanguage::ModeInfo &info = modes[j];
+
+				if (!info.options.is_empty()) {
+					for (int k = 0; k < info.options.size(); k++) {
+						built_ins.push_back(String(info.name) + "_" + String(info.options[k]));
+					}
+				} else {
+					built_ins.push_back(String(info.name));
+				}
+			}
+		}
+	} else if (shader.is_valid()) {
 		for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode()))) {
 			for (const KeyValue<StringName, ShaderLanguage::BuiltInInfo> &F : E.value.built_ins) {
 				built_ins.push_back(F.key);
@@ -337,11 +360,10 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptLa
 	ShaderLanguage::ShaderCompileInfo info;
 	info.global_variable_type_func = _get_global_variable_type;
 
-	Ref<ShaderInclude> inc = shader_inc;
 	if (shader.is_null()) {
 		info.is_include = true;
 
-		sl.complete(p_code, info, r_options, calltip);
+		sl.complete(code, info, r_options, calltip);
 		get_text_editor()->set_code_hint(calltip);
 		return;
 	}
@@ -350,7 +372,7 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptLa
 	info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode()));
 	info.shader_types = ShaderTypes::get_singleton()->get_types();
 
-	sl.complete(p_code, info, r_options, calltip);
+	sl.complete(code, info, r_options, calltip);
 	get_text_editor()->set_code_hint(calltip);
 }
 

+ 184 - 63
servers/rendering/shader_language.cpp

@@ -34,6 +34,7 @@
 #include "core/string/print_string.h"
 #include "core/templates/local_vector.h"
 #include "servers/rendering_server.h"
+#include "shader_types.h"
 
 #define HAS_WARNING(flag) (warning_flags & flag)
 
@@ -1218,17 +1219,36 @@ void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, Iden
 #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;
-		}
-		if (r_is_const) {
-			*r_is_const = p_function_info.built_ins[p_identifier].constant;
+	if (is_shader_inc) {
+		for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+			for (const KeyValue<StringName, FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i))) {
+				if ((current_function == E.key || E.key == "global") && E.value.built_ins.has(p_identifier)) {
+					if (r_data_type) {
+						*r_data_type = E.value.built_ins[p_identifier].type;
+					}
+					if (r_is_const) {
+						*r_is_const = E.value.built_ins[p_identifier].constant;
+					}
+					if (r_type) {
+						*r_type = IDENTIFIER_BUILTIN_VAR;
+					}
+					return true;
+				}
+			}
 		}
-		if (r_type) {
-			*r_type = IDENTIFIER_BUILTIN_VAR;
+	} else {
+		if (p_function_info.built_ins.has(p_identifier)) {
+			if (r_data_type) {
+				*r_data_type = p_function_info.built_ins[p_identifier].type;
+			}
+			if (r_is_const) {
+				*r_is_const = p_function_info.built_ins[p_identifier].constant;
+			}
+			if (r_type) {
+				*r_type = IDENTIFIER_BUILTIN_VAR;
+			}
+			return true;
 		}
-		return true;
 	}
 
 	if (p_function_info.stage_functions.has(p_identifier)) {
@@ -7728,12 +7748,12 @@ Error ShaderLanguage::_validate_precision(DataType p_type, DataPrecision p_preci
 	return OK;
 }
 
-Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types, bool p_is_include) {
+Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types) {
 	Token tk;
 	TkPos prev_pos;
 	Token next;
 
-	if (!p_is_include) {
+	if (!is_shader_inc) {
 		tk = _get_token();
 
 		if (tk.type != TK_SHADER_TYPE) {
@@ -7815,25 +7835,54 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
 
 					bool found = false;
 
-					for (int i = 0; i < p_render_modes.size(); i++) {
-						const ModeInfo &info = p_render_modes[i];
-						const String name = String(info.name);
+					if (is_shader_inc) {
+						for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+							const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
 
-						if (smode.begins_with(name)) {
-							if (!info.options.is_empty()) {
-								if (info.options.has(smode.substr(name.length() + 1))) {
-									found = true;
+							for (int j = 0; j < modes.size(); j++) {
+								const ModeInfo &info = modes[j];
+								const String name = String(info.name);
 
-									if (defined_modes.has(name)) {
-										_set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
-										return ERR_PARSE_ERROR;
+								if (smode.begins_with(name)) {
+									if (!info.options.is_empty()) {
+										if (info.options.has(smode.substr(name.length() + 1))) {
+											found = true;
+
+											if (defined_modes.has(name)) {
+												_set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
+												return ERR_PARSE_ERROR;
+											}
+											defined_modes.insert(name, smode);
+											break;
+										}
+									} else {
+										found = true;
+										break;
+									}
+								}
+							}
+						}
+					} else {
+						for (int i = 0; i < p_render_modes.size(); i++) {
+							const ModeInfo &info = p_render_modes[i];
+							const String name = String(info.name);
+
+							if (smode.begins_with(name)) {
+								if (!info.options.is_empty()) {
+									if (info.options.has(smode.substr(name.length() + 1))) {
+										found = true;
+
+										if (defined_modes.has(name)) {
+											_set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
+											return ERR_PARSE_ERROR;
+										}
+										defined_modes.insert(name, smode);
+										break;
 									}
-									defined_modes.insert(name, smode);
+								} else {
+									found = true;
 									break;
 								}
-							} else {
-								found = true;
-								break;
 							}
 						}
 					}
@@ -9563,6 +9612,7 @@ uint32_t ShaderLanguage::get_warning_flags() const {
 
 Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_info) {
 	clear();
+	is_shader_inc = p_info.is_include;
 
 	code = p_code;
 	global_var_get_type_func = p_info.global_variable_type_func;
@@ -9572,7 +9622,7 @@ Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_i
 	nodes = nullptr;
 
 	shader = alloc_node<ShaderNode>();
-	Error err = _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types, p_info.is_include);
+	Error err = _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
 
 #ifdef DEBUG_ENABLED
 	if (check_warnings) {
@@ -9588,6 +9638,7 @@ Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_i
 
 Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint) {
 	clear();
+	is_shader_inc = p_info.is_include;
 
 	code = p_code;
 	varying_function_names = p_info.varying_function_names;
@@ -9596,7 +9647,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
 	global_var_get_type_func = p_info.global_variable_type_func;
 
 	shader = alloc_node<ShaderNode>();
-	_parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types, p_info.is_include);
+	_parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
 
 #ifdef DEBUG_ENABLED
 	// Adds context keywords.
@@ -9633,30 +9684,64 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
 			return OK;
 		} break;
 		case COMPLETION_RENDER_MODE: {
-			for (int i = 0; i < p_info.render_modes.size(); i++) {
-				const ModeInfo &info = p_info.render_modes[i];
+			if (is_shader_inc) {
+				for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+					const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
 
-				if (!info.options.is_empty()) {
-					bool found = false;
+					for (int j = 0; j < modes.size(); j++) {
+						const ModeInfo &info = modes[j];
 
-					for (int j = 0; j < info.options.size(); j++) {
-						if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) {
-							found = true;
+						if (!info.options.is_empty()) {
+							bool found = false;
+
+							for (int k = 0; k < info.options.size(); k++) {
+								if (shader->render_modes.has(String(info.name) + "_" + String(info.options[k]))) {
+									found = true;
+								}
+							}
+
+							if (!found) {
+								for (int k = 0; k < info.options.size(); k++) {
+									ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[k]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+									r_options->push_back(option);
+								}
+							}
+						} else {
+							const String name = String(info.name);
+
+							if (!shader->render_modes.has(name)) {
+								ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+								r_options->push_back(option);
+							}
 						}
 					}
+				}
+			} else {
+				for (int i = 0; i < p_info.render_modes.size(); i++) {
+					const ModeInfo &info = p_info.render_modes[i];
+
+					if (!info.options.is_empty()) {
+						bool found = false;
 
-					if (!found) {
 						for (int j = 0; j < info.options.size(); j++) {
-							ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
-							r_options->push_back(option);
+							if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) {
+								found = true;
+							}
 						}
-					}
-				} else {
-					const String name = String(info.name);
 
-					if (!shader->render_modes.has(name)) {
-						ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
-						r_options->push_back(option);
+						if (!found) {
+							for (int j = 0; j < info.options.size(); j++) {
+								ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+								r_options->push_back(option);
+							}
+						}
+					} else {
+						const String name = String(info.name);
+
+						if (!shader->render_modes.has(name)) {
+							ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+							r_options->push_back(option);
+						}
 					}
 				}
 			}
@@ -9724,33 +9809,69 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
 				}
 
 				if (comp_ident) {
-					if (p_info.functions.has("global")) {
-						for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
-							ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
-							if (E.value.constant) {
-								kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+					if (is_shader_inc) {
+						for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+							const HashMap<StringName, ShaderLanguage::FunctionInfo> info = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i));
+
+							if (info.has("global")) {
+								for (const KeyValue<StringName, BuiltInInfo> &E : info["global"].built_ins) {
+									ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+									if (E.value.constant) {
+										kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+									}
+									matches.insert(E.key, kind);
+								}
+							}
+
+							if (info.has("constants")) {
+								for (const KeyValue<StringName, BuiltInInfo> &E : info["constants"].built_ins) {
+									ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+									if (E.value.constant) {
+										kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+									}
+									matches.insert(E.key, kind);
+								}
+							}
+
+							if (skip_function != StringName() && info.has(skip_function)) {
+								for (const KeyValue<StringName, BuiltInInfo> &E : info[skip_function].built_ins) {
+									ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+									if (E.value.constant) {
+										kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+									}
+									matches.insert(E.key, kind);
+								}
+							}
+						}
+					} else {
+						if (p_info.functions.has("global")) {
+							for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
+								ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+								if (E.value.constant) {
+									kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+								}
+								matches.insert(E.key, kind);
 							}
-							matches.insert(E.key, kind);
 						}
-					}
 
-					if (p_info.functions.has("constants")) {
-						for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
-							ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
-							if (E.value.constant) {
-								kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+						if (p_info.functions.has("constants")) {
+							for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
+								ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+								if (E.value.constant) {
+									kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+								}
+								matches.insert(E.key, kind);
 							}
-							matches.insert(E.key, kind);
 						}
-					}
 
-					if (skip_function != StringName() && p_info.functions.has(skip_function)) {
-						for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
-							ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
-							if (E.value.constant) {
-								kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+						if (skip_function != StringName() && p_info.functions.has(skip_function)) {
+							for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
+								ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+								if (E.value.constant) {
+									kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+								}
+								matches.insert(E.key, kind);
 							}
-							matches.insert(E.key, kind);
 						}
 					}
 

+ 2 - 1
servers/rendering/shader_language.h

@@ -936,6 +936,7 @@ private:
 	StringName current_function;
 	bool last_const = false;
 	StringName last_name;
+	bool is_shader_inc = false;
 
 	VaryingFunctionNames varying_function_names;
 
@@ -1079,7 +1080,7 @@ private:
 	String _get_shader_type_list(const HashSet<String> &p_shader_types) const;
 	String _get_qualifier_str(ArgumentQualifier p_qualifier) const;
 
-	Error _parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types, bool p_is_include);
+	Error _parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types);
 
 	Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);
 	Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op);