Browse Source

Implement shader array support for varyings (#30925)

Implement shader array support for varyings
Yuri Roubinsky 6 years ago
parent
commit
2861fd9552

+ 5 - 0
drivers/gles2/shader_compiler_gles2.cpp

@@ -353,6 +353,11 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
 				varying_code += _typestr(E->get().type);
 				varying_code += _typestr(E->get().type);
 				varying_code += " ";
 				varying_code += " ";
 				varying_code += _mkid(E->key());
 				varying_code += _mkid(E->key());
+				if (E->get().array_size > 0) {
+					varying_code += "[";
+					varying_code += itos(E->get().array_size);
+					varying_code += "]";
+				}
 				varying_code += ";\n";
 				varying_code += ";\n";
 
 
 				String final_code = varying_code.as_string();
 				String final_code = varying_code.as_string();

+ 5 - 0
drivers/gles3/shader_compiler_gles3.cpp

@@ -467,6 +467,11 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
 				vcode += _prestr(E->get().precision);
 				vcode += _prestr(E->get().precision);
 				vcode += _typestr(E->get().type);
 				vcode += _typestr(E->get().type);
 				vcode += " " + _mkid(E->key());
 				vcode += " " + _mkid(E->key());
+				if (E->get().array_size > 0) {
+					vcode += "[";
+					vcode += itos(E->get().array_size);
+					vcode += "]";
+				}
 				vcode += ";\n";
 				vcode += ";\n";
 				r_gen_code.vertex_global += interp_mode + "out " + vcode;
 				r_gen_code.vertex_global += interp_mode + "out " + vcode;
 				r_gen_code.fragment_global += interp_mode + "in " + vcode;
 				r_gen_code.fragment_global += interp_mode + "in " + vcode;

+ 36 - 4
servers/visual/shader_language.cpp

@@ -924,6 +924,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<String
 		if (r_data_type) {
 		if (r_data_type) {
 			*r_data_type = shader->varyings[p_identifier].type;
 			*r_data_type = shader->varyings[p_identifier].type;
 		}
 		}
+		if (r_array_size) {
+			*r_array_size = shader->varyings[p_identifier].array_size;
+		}
 		if (r_type) {
 		if (r_type) {
 			*r_type = IDENTIFIER_VARYING;
 			*r_type = IDENTIFIER_VARYING;
 		}
 		}
@@ -2759,6 +2762,12 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
 			return false;
 			return false;
 		}
 		}
 
 
+		if (shader->varyings.has(arr->name) && current_function != String("vertex")) {
+			if (r_message)
+				*r_message = RTR("Varyings can only be assigned in vertex function.");
+			return false;
+		}
+
 		return true;
 		return true;
 	}
 	}
 
 
@@ -4695,7 +4704,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
 				}
 				}
 
 
 				if (!uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) {
 				if (!uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) {
-					_set_error("Invalid type for varying, only float,vec2,vec3,vec4,mat2,mat3,mat4 allowed.");
+					_set_error("Invalid type for varying, only float,vec2,vec3,vec4,mat2,mat3,mat4 or array of these types allowed.");
 					return ERR_PARSE_ERROR;
 					return ERR_PARSE_ERROR;
 				}
 				}
 
 
@@ -4877,13 +4886,36 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
 					varying.type = type;
 					varying.type = type;
 					varying.precision = precision;
 					varying.precision = precision;
 					varying.interpolation = interpolation;
 					varying.interpolation = interpolation;
-					shader->varyings[name] = varying;
 
 
 					tk = _get_token();
 					tk = _get_token();
-					if (tk.type != TK_SEMICOLON) {
-						_set_error("Expected ';'");
+					if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
+						_set_error("Expected ';' or '['");
 						return ERR_PARSE_ERROR;
 						return ERR_PARSE_ERROR;
 					}
 					}
+
+					if (tk.type == TK_BRACKET_OPEN) {
+						tk = _get_token();
+						if (tk.type == TK_INT_CONSTANT && tk.constant > 0) {
+							varying.array_size = (int)tk.constant;
+
+							tk = _get_token();
+							if (tk.type == TK_BRACKET_CLOSE) {
+								tk = _get_token();
+								if (tk.type != TK_SEMICOLON) {
+									_set_error("Expected ';'");
+									return ERR_PARSE_ERROR;
+								}
+							} else {
+								_set_error("Expected ']'");
+								return ERR_PARSE_ERROR;
+							}
+						} else {
+							_set_error("Expected single integer constant > 0");
+							return ERR_PARSE_ERROR;
+						}
+					}
+
+					shader->varyings[name] = varying;
 				}
 				}
 
 
 			} break;
 			} break;

+ 3 - 1
servers/visual/shader_language.h

@@ -519,11 +519,13 @@ public:
 			DataType type;
 			DataType type;
 			DataInterpolation interpolation;
 			DataInterpolation interpolation;
 			DataPrecision precision;
 			DataPrecision precision;
+			int array_size;
 
 
 			Varying() :
 			Varying() :
 					type(TYPE_VOID),
 					type(TYPE_VOID),
 					interpolation(INTERPOLATION_FLAT),
 					interpolation(INTERPOLATION_FLAT),
-					precision(PRECISION_DEFAULT) {}
+					precision(PRECISION_DEFAULT),
+					array_size(0) {}
 		};
 		};
 
 
 		struct Uniform {
 		struct Uniform {