From 1333ea2a2d70d45a295702c2d941e7bfb00bfe94 Mon Sep 17 00:00:00 2001 From: Chaosus Date: Mon, 29 Jul 2019 17:08:25 +0300 Subject: [PATCH] Implement shader array support for varyings --- drivers/gles2/shader_compiler_gles2.cpp | 5 ++++ drivers/gles3/shader_compiler_gles3.cpp | 5 ++++ servers/visual/shader_language.cpp | 40 ++++++++++++++++++++++--- servers/visual/shader_language.h | 4 ++- 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 640d45ae65..92bf0e29e2 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/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 += " "; 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"; String final_code = varying_code.as_string(); diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 0121d88f4d..3f21be8dd3 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/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 += _typestr(E->get().type); vcode += " " + _mkid(E->key()); + if (E->get().array_size > 0) { + vcode += "["; + vcode += itos(E->get().array_size); + vcode += "]"; + } vcode += ";\n"; r_gen_code.vertex_global += interp_mode + "out " + vcode; r_gen_code.fragment_global += interp_mode + "in " + vcode; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 4bc65a8f4f..1b9c3e2eff 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -924,6 +924,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Mapvaryings[p_identifier].type; } + if (r_array_size) { + *r_array_size = shader->varyings[p_identifier].array_size; + } if (r_type) { *r_type = IDENTIFIER_VARYING; } @@ -2759,6 +2762,12 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Mapvaryings.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; } @@ -4695,7 +4704,7 @@ Error ShaderLanguage::_parse_shader(const Map &p_funct } 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; } @@ -4877,13 +4886,36 @@ Error ShaderLanguage::_parse_shader(const Map &p_funct varying.type = type; varying.precision = precision; varying.interpolation = interpolation; - shader->varyings[name] = varying; 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; } + + 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; diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 6753456323..3a5630ef42 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -519,11 +519,13 @@ public: DataType type; DataInterpolation interpolation; DataPrecision precision; + int array_size; Varying() : type(TYPE_VOID), interpolation(INTERPOLATION_FLAT), - precision(PRECISION_DEFAULT) {} + precision(PRECISION_DEFAULT), + array_size(0) {} }; struct Uniform {