Browse Source

Implementation of 'struct' for shaders

Yuri Roubinsky 5 years ago
parent
commit
6f162395ff

+ 3 - 0
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -1636,6 +1636,9 @@ void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyIn
 		pi.name = E->get();
 
 		switch (u.type) {
+			case ShaderLanguage::TYPE_STRUCT: {
+				pi.type = Variant::ARRAY;
+			} break;
 			case ShaderLanguage::TYPE_VOID: {
 				pi.type = Variant::NIL;
 			} break;

+ 63 - 19
drivers/gles2/shader_compiler_gles2.cpp

@@ -240,21 +240,20 @@ void ShaderCompilerGLES2::_dump_function_deps(SL::ShaderNode *p_node, const Stri
 		r_to_add += "\n";
 
 		StringBuffer<128> header;
-
-		header += _typestr(fnode->return_type);
-		header += " ";
-		header += _mkid(fnode->name);
-		header += "(";
+		if (fnode->return_type == SL::TYPE_STRUCT) {
+			header += _mkid(fnode->return_struct_name) + " " + _mkid(fnode->name) + "(";
+		} else {
+			header += _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "(";
+		}
 
 		for (int i = 0; i < fnode->arguments.size(); i++) {
 			if (i > 0)
 				header += ", ";
-
-			header += _qualstr(fnode->arguments[i].qualifier);
-			header += _prestr(fnode->arguments[i].precision);
-			header += _typestr(fnode->arguments[i].type);
-			header += " ";
-			header += _mkid(fnode->arguments[i].name);
+			if (fnode->arguments[i].type == SL::TYPE_STRUCT) {
+				header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name);
+			} else {
+				header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name);
+			}
 		}
 
 		header += ")\n";
@@ -312,6 +311,36 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
 			StringBuilder vertex_global;
 			StringBuilder fragment_global;
 
+			// structs
+
+			for (int i = 0; i < snode->vstructs.size(); i++) {
+
+				SL::StructNode *st = snode->vstructs[i].shader_struct;
+				String struct_code;
+
+				struct_code += "struct ";
+				struct_code += _mkid(snode->vstructs[i].name);
+				struct_code += " ";
+				struct_code += "{\n";
+				for (int j = 0; j < st->members.size(); j++) {
+					SL::MemberNode *m = st->members[j];
+					if (m->datatype == SL::TYPE_STRUCT) {
+						struct_code += _mkid(m->struct_name);
+					} else {
+						struct_code += _prestr(m->precision);
+						struct_code += _typestr(m->datatype);
+					}
+					struct_code += " ";
+					struct_code += m->name;
+					struct_code += ";\n";
+				}
+				struct_code += "}";
+				struct_code += ";\n";
+
+				vertex_global += struct_code;
+				fragment_global += struct_code;
+			}
+
 			// uniforms
 
 			for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = snode->uniforms.front(); E; E = E->next()) {
@@ -374,7 +403,11 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
 				String gcode;
 				gcode += "const ";
 				gcode += _prestr(E->get().precision);
-				gcode += _typestr(E->get().type);
+				if (E->get().type == SL::TYPE_STRUCT) {
+					gcode += _mkid(E->get().type_str);
+				} else {
+					gcode += _typestr(E->get().type);
+				}
 				gcode += " " + _mkid(E->key());
 				gcode += "=";
 				gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
@@ -420,7 +453,9 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
 			r_gen_code.fragment_global = fragment_global.as_string();
 
 		} break;
+		case SL::Node::TYPE_STRUCT: {
 
+		} break;
 		case SL::Node::TYPE_FUNCTION: {
 
 		} break;
@@ -459,8 +494,12 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
 			if (var_dec_node->is_const) {
 				declaration += "const ";
 			}
-			declaration += _prestr(var_dec_node->precision);
-			declaration += _typestr(var_dec_node->datatype);
+			if (var_dec_node->datatype == SL::TYPE_STRUCT) {
+				declaration += _mkid(var_dec_node->struct_name);
+			} else {
+				declaration += _prestr(var_dec_node->precision);
+				declaration += _typestr(var_dec_node->datatype);
+			}
 
 			for (int i = 0; i < var_dec_node->declarations.size(); i++) {
 
@@ -524,9 +563,12 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
 			SL::ArrayDeclarationNode *arr_dec_node = (SL::ArrayDeclarationNode *)p_node;
 
 			StringBuffer<> declaration;
-			declaration += _prestr(arr_dec_node->precision);
-			declaration += _typestr(arr_dec_node->datatype);
-
+			if (arr_dec_node->datatype == SL::TYPE_STRUCT) {
+				declaration += _mkid(arr_dec_node->struct_name);
+			} else {
+				declaration += _prestr(arr_dec_node->precision);
+				declaration += _typestr(arr_dec_node->datatype);
+			}
 			for (int i = 0; i < arr_dec_node->declarations.size(); i++) {
 
 				if (i > 0) {
@@ -646,12 +688,14 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
 				} break;
 
 				case SL::OP_CALL:
+				case SL::OP_STRUCT:
 				case SL::OP_CONSTRUCT: {
 					ERR_FAIL_COND_V(op_node->arguments[0]->type != SL::Node::TYPE_VARIABLE, String());
 
 					SL::VariableNode *var_node = (SL::VariableNode *)op_node->arguments[0];
-
-					if (op_node->op == SL::OP_CONSTRUCT) {
+					if (op_node->op == SL::OP_STRUCT) {
+						code += _mkid(var_node->name);
+					} else if (op_node->op == SL::OP_CONSTRUCT) {
 						code += var_node->name;
 					} else {
 

+ 3 - 0
main/tests/test_shader_lang.cpp

@@ -162,6 +162,9 @@ static String dump_node_code(SL::Node *p_node, int p_level) {
 			}
 
 			//code+=dump_node_code(pnode->body,p_level);
+		} break;
+		case SL::Node::TYPE_STRUCT: {
+
 		} break;
 		case SL::Node::TYPE_FUNCTION: {
 

+ 77 - 8
servers/visual/rasterizer_rd/shader_compiler_rd.cpp

@@ -90,6 +90,7 @@ static int _get_datatype_size(SL::DataType p_type) {
 		case SL::TYPE_ISAMPLER3D: return 16;
 		case SL::TYPE_USAMPLER3D: return 16;
 		case SL::TYPE_SAMPLERCUBE: return 16;
+		case SL::TYPE_STRUCT: return 0;
 	}
 
 	ERR_FAIL_V(0);
@@ -129,6 +130,7 @@ static int _get_datatype_alignment(SL::DataType p_type) {
 		case SL::TYPE_ISAMPLER3D: return 16;
 		case SL::TYPE_USAMPLER3D: return 16;
 		case SL::TYPE_SAMPLERCUBE: return 16;
+		case SL::TYPE_STRUCT: return 0;
 	}
 
 	ERR_FAIL_V(0);
@@ -315,12 +317,20 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
 		r_to_add += "\n";
 
 		String header;
-		header = _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "(";
+		if (fnode->return_type == SL::TYPE_STRUCT) {
+			header = _mkid(fnode->return_struct_name) + " " + _mkid(fnode->name) + "(";
+		} else {
+			header = _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "(";
+		}
 		for (int i = 0; i < fnode->arguments.size(); i++) {
 
 			if (i > 0)
 				header += ", ";
-			header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name);
+			if (fnode->arguments[i].type == SL::TYPE_STRUCT) {
+				header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name);
+			} else {
+				header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name);
+			}
 		}
 
 		header += ")\n";
@@ -359,6 +369,36 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
 				}
 			}
 
+			// structs
+
+			for (int i = 0; i < pnode->vstructs.size(); i++) {
+
+				SL::StructNode *st = pnode->vstructs[i].shader_struct;
+				String struct_code;
+
+				struct_code += "struct ";
+				struct_code += _mkid(pnode->vstructs[i].name);
+				struct_code += " ";
+				struct_code += "{\n";
+				for (int j = 0; j < st->members.size(); j++) {
+					SL::MemberNode *m = st->members[j];
+					if (m->datatype == SL::TYPE_STRUCT) {
+						struct_code += _mkid(m->struct_name);
+					} else {
+						struct_code += _prestr(m->precision);
+						struct_code += _typestr(m->datatype);
+					}
+					struct_code += " ";
+					struct_code += m->name;
+					struct_code += ";\n";
+				}
+				struct_code += "}";
+				struct_code += ";\n";
+
+				r_gen_code.vertex_global += struct_code;
+				r_gen_code.fragment_global += struct_code;
+			}
+
 			int max_texture_uniforms = 0;
 			int max_uniforms = 0;
 
@@ -506,7 +546,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
 				String gcode;
 				gcode += "const ";
 				gcode += _prestr(E->get().precision);
-				gcode += _typestr(E->get().type);
+				if (E->get().type == SL::TYPE_STRUCT) {
+					gcode += _mkid(E->get().type_str);
+				} else {
+					gcode += _typestr(E->get().type);
+				}
 				gcode += " " + _mkid(E->key());
 				gcode += "=";
 				gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
@@ -560,6 +604,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
 			}
 
 			//code+=dump_node_code(pnode->body,p_level);
+		} break;
+		case SL::Node::TYPE_STRUCT: {
+
 		} break;
 		case SL::Node::TYPE_FUNCTION: {
 
@@ -590,7 +637,15 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
 		case SL::Node::TYPE_VARIABLE_DECLARATION: {
 			SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node;
 
-			String declaration = _prestr(vdnode->precision) + _typestr(vdnode->datatype);
+			String declaration;
+			if (vdnode->is_const) {
+				declaration += "const ";
+			}
+			if (vdnode->datatype == SL::TYPE_STRUCT) {
+				declaration += _mkid(vdnode->struct_name);
+			} else {
+				declaration += _prestr(vdnode->precision) + _typestr(vdnode->datatype);
+			}
 			for (int i = 0; i < vdnode->declarations.size(); i++) {
 				if (i > 0) {
 					declaration += ",";
@@ -649,8 +704,15 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
 		case SL::Node::TYPE_ARRAY_DECLARATION: {
 
 			SL::ArrayDeclarationNode *adnode = (SL::ArrayDeclarationNode *)p_node;
-
-			String declaration = _prestr(adnode->precision) + _typestr(adnode->datatype);
+			String declaration;
+			if (adnode->is_const) {
+				declaration += "const ";
+			}
+			if (adnode->datatype == SL::TYPE_STRUCT) {
+				declaration += _mkid(adnode->struct_name);
+			} else {
+				declaration = _prestr(adnode->precision) + _typestr(adnode->datatype);
+			}
 			for (int i = 0; i < adnode->declarations.size(); i++) {
 				if (i > 0) {
 					declaration += ",";
@@ -664,7 +726,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
 				int sz = adnode->declarations[i].initializer.size();
 				if (sz > 0) {
 					declaration += "=";
-					declaration += _typestr(adnode->datatype);
+					if (adnode->datatype == SL::TYPE_STRUCT) {
+						declaration += _mkid(adnode->struct_name);
+					} else {
+						declaration += _typestr(adnode->datatype);
+					}
 					declaration += "[";
 					declaration += itos(sz);
 					declaration += "]";
@@ -763,6 +829,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
 					code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op);
 					break;
 				case SL::OP_CALL:
+				case SL::OP_STRUCT:
 				case SL::OP_CONSTRUCT: {
 
 					ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::TYPE_VARIABLE, String());
@@ -770,7 +837,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
 					SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0];
 
 					bool is_texture_func = false;
-					if (onode->op == SL::OP_CONSTRUCT) {
+					if (onode->op == SL::OP_STRUCT) {
+						code += _mkid(vnode->name);
+					} else if (onode->op == SL::OP_CONSTRUCT) {
 						code += String(vnode->name);
 					} else {
 

File diff suppressed because it is too large
+ 471 - 148
servers/visual/shader_language.cpp


+ 43 - 3
servers/visual/shader_language.h

@@ -82,6 +82,7 @@ public:
 		TK_INTERPOLATION_FLAT,
 		TK_INTERPOLATION_SMOOTH,
 		TK_CONST,
+		TK_STRUCT,
 		TK_PRECISION_LOW,
 		TK_PRECISION_MID,
 		TK_PRECISION_HIGH,
@@ -214,6 +215,7 @@ public:
 		TYPE_ISAMPLER3D,
 		TYPE_USAMPLER3D,
 		TYPE_SAMPLERCUBE,
+		TYPE_STRUCT,
 	};
 
 	enum DataPrecision {
@@ -269,6 +271,7 @@ public:
 		OP_POST_DECREMENT,
 		OP_CALL,
 		OP_CONSTRUCT,
+		OP_STRUCT,
 		OP_INDEX,
 		OP_MAX
 	};
@@ -329,11 +332,14 @@ public:
 			TYPE_MEMBER,
 			TYPE_ARRAY,
 			TYPE_ARRAY_DECLARATION,
+			TYPE_STRUCT,
 		};
 
 		Type type;
 
 		virtual DataType get_datatype() const { return TYPE_VOID; }
+		virtual String get_datatype_name() const { return ""; }
+
 		Node(Type t) :
 				next(NULL),
 				type(t) {}
@@ -354,20 +360,25 @@ public:
 		DataType return_cache;
 		DataPrecision return_precision_cache;
 		Operator op;
+		StringName struct_name;
 		Vector<Node *> arguments;
 		virtual DataType get_datatype() const { return return_cache; }
+		virtual String get_datatype_name() const { return String(struct_name); }
 
 		OperatorNode() :
 				Node(TYPE_OPERATOR),
 				return_cache(TYPE_VOID),
 				return_precision_cache(PRECISION_DEFAULT),
-				op(OP_EQUAL) {}
+				op(OP_EQUAL),
+				struct_name("") {}
 	};
 
 	struct VariableNode : public Node {
 		DataType datatype_cache;
 		StringName name;
+		StringName struct_name;
 		virtual DataType get_datatype() const { return datatype_cache; }
+		virtual String get_datatype_name() const { return String(struct_name); }
 		bool is_const;
 
 		VariableNode() :
@@ -379,6 +390,7 @@ public:
 	struct VariableDeclarationNode : public Node {
 		DataPrecision precision;
 		DataType datatype;
+		String struct_name;
 		bool is_const;
 
 		struct Declaration {
@@ -398,12 +410,14 @@ public:
 
 	struct ArrayNode : public Node {
 		DataType datatype_cache;
+		StringName struct_name;
 		StringName name;
 		Node *index_expression;
 		Node *call_expression;
 		bool is_const;
 
 		virtual DataType get_datatype() const { return datatype_cache; }
+		virtual String get_datatype_name() const { return String(struct_name); }
 
 		ArrayNode() :
 				Node(TYPE_ARRAY),
@@ -416,6 +430,7 @@ public:
 	struct ArrayDeclarationNode : public Node {
 		DataPrecision precision;
 		DataType datatype;
+		String struct_name;
 		bool is_const;
 
 		struct Declaration {
@@ -470,6 +485,7 @@ public:
 
 		struct Variable {
 			DataType type;
+			StringName struct_name;
 			DataPrecision precision;
 			int line; //for completion
 			int array_size;
@@ -501,11 +517,15 @@ public:
 
 	struct MemberNode : public Node {
 		DataType basetype;
+		StringName base_struct_name;
+		DataPrecision precision;
 		DataType datatype;
+		StringName struct_name;
 		StringName name;
 		Node *owner;
 
 		virtual DataType get_datatype() const { return datatype; }
+		virtual String get_datatype_name() const { return String(struct_name); }
 
 		MemberNode() :
 				Node(TYPE_MEMBER),
@@ -514,12 +534,20 @@ public:
 				owner(NULL) {}
 	};
 
+	struct StructNode : public Node {
+
+		List<MemberNode *> members;
+		StructNode() :
+				Node(TYPE_STRUCT) {}
+	};
+
 	struct FunctionNode : public Node {
 
 		struct Argument {
 			ArgumentQualifier qualifier;
 			StringName name;
 			DataType type;
+			StringName type_str;
 			DataPrecision precision;
 			//for passing textures as arguments
 			bool tex_argument_check;
@@ -533,6 +561,7 @@ public:
 
 		StringName name;
 		DataType return_type;
+		StringName return_struct_name;
 		DataPrecision return_precision;
 		Vector<Argument> arguments;
 		BlockNode *body;
@@ -550,6 +579,7 @@ public:
 
 		struct Constant {
 			DataType type;
+			StringName type_str;
 			DataPrecision precision;
 			ConstantNode *initializer;
 		};
@@ -561,6 +591,11 @@ public:
 			bool callable;
 		};
 
+		struct Struct {
+			StringName name;
+			StructNode *shader_struct;
+		};
+
 		struct Varying {
 			DataType type;
 			DataInterpolation interpolation;
@@ -621,9 +656,11 @@ public:
 		Map<StringName, Constant> constants;
 		Map<StringName, Varying> varyings;
 		Map<StringName, Uniform> uniforms;
+		Map<StringName, Struct> structs;
 		Vector<StringName> render_modes;
 
 		Vector<Function> functions;
+		Vector<Struct> vstructs;
 
 		ShaderNode() :
 				Node(TYPE_SHADER) {}
@@ -650,6 +687,7 @@ public:
 		COMPLETION_FUNCTION_CALL,
 		COMPLETION_CALL_ARGUMENTS,
 		COMPLETION_INDEX,
+		COMPLETION_STRUCT,
 	};
 
 	struct Token {
@@ -766,7 +804,7 @@ private:
 		IDENTIFIER_CONSTANT,
 	};
 
-	bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL, bool *r_is_const = NULL, int *r_array_size = NULL);
+	bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL, bool *r_is_const = NULL, int *r_array_size = NULL, StringName *r_struct_name = NULL);
 	bool _is_operator_assign(Operator p_op) const;
 	bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = NULL);
 	bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL);
@@ -791,6 +829,7 @@ private:
 	DataType completion_base;
 	SubClassTag completion_class;
 	StringName completion_function;
+	StringName completion_struct;
 	int completion_argument;
 
 	bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
@@ -798,8 +837,9 @@ private:
 	static const BuiltinFuncOutArgs builtin_func_out_args[];
 
 	Error _validate_datatype(DataType p_type);
+	bool _compare_datatypes_in_nodes(Node *a, Node *b) const;
 
-	bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
+	bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str);
 	bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
 	bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat);
 	bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin);

Some files were not shown because too many files changed in this diff