diff options
Diffstat (limited to 'servers/rendering/shader_language.cpp')
-rw-r--r-- | servers/rendering/shader_language.cpp | 422 |
1 files changed, 323 insertions, 99 deletions
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index cfabddded3..8c732b3d5a 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -195,10 +195,14 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "SOURCE_COLOR", "HINT_DEFAULT_WHITE_TEXTURE", "HINT_DEFAULT_BLACK_TEXTURE", + "HINT_DEFAULT_TRANSPARENT_TEXTURE", "HINT_NORMAL_TEXTURE", "HINT_ANISOTROPY_TEXTURE", "HINT_RANGE", "HINT_INSTANCE_INDEX", + "HINT_SCREEN_TEXTURE", + "HINT_NORMAL_ROUGHNESS_TEXTURE", + "HINT_DEPTH_TEXTURE", "FILTER_NEAREST", "FILTER_LINEAR", "FILTER_NEAREST_MIPMAP", @@ -253,6 +257,7 @@ enum ContextFlag : uint32_t { CF_UNIFORM_KEYWORD = 2048U, // "uniform" CF_CONST_KEYWORD = 4096U, // "const" CF_UNIFORM_QUALIFIER = 8192U, // "<x> uniform float t;" + CF_SHADER_TYPE = 16384U, // "shader_type" }; const uint32_t KCF_DATATYPE = CF_BLOCK | CF_GLOBAL_SPACE | CF_DATATYPE | CF_FUNC_DECL_PARAM_TYPE | CF_UNIFORM_TYPE; @@ -310,10 +315,11 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { // global space keywords { TK_UNIFORM, "uniform", CF_GLOBAL_SPACE | CF_UNIFORM_KEYWORD, {}, {} }, + { TK_UNIFORM_GROUP, "group_uniforms", CF_GLOBAL_SPACE, {}, {} }, { TK_VARYING, "varying", CF_GLOBAL_SPACE, { "particles", "sky", "fog" }, {} }, { TK_CONST, "const", CF_BLOCK | CF_GLOBAL_SPACE | CF_CONST_KEYWORD, {}, {} }, { TK_STRUCT, "struct", CF_GLOBAL_SPACE, {}, {} }, - { TK_SHADER_TYPE, "shader_type", CF_GLOBAL_SPACE, {}, {} }, + { TK_SHADER_TYPE, "shader_type", CF_SHADER_TYPE, {}, {} }, { TK_RENDER_MODE, "render_mode", CF_GLOBAL_SPACE, {}, {} }, // uniform qualifiers @@ -353,6 +359,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_HINT_NORMAL_TEXTURE, "hint_normal", CF_UNSPECIFIED, {}, {} }, { TK_HINT_DEFAULT_WHITE_TEXTURE, "hint_default_white", CF_UNSPECIFIED, {}, {} }, { TK_HINT_DEFAULT_BLACK_TEXTURE, "hint_default_black", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_DEFAULT_TRANSPARENT_TEXTURE, "hint_default_transparent", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ANISOTROPY_TEXTURE, "hint_anisotropy", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_R, "hint_roughness_r", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_G, "hint_roughness_g", CF_UNSPECIFIED, {}, {} }, @@ -360,6 +367,10 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_HINT_ROUGHNESS_A, "hint_roughness_a", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_SCREEN_TEXTURE, "hint_screen_texture", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_NORMAL_ROUGHNESS_TEXTURE, "hint_normal_roughness_texture", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_DEPTH_TEXTURE, "hint_depth_texture", CF_UNSPECIFIED, {}, {} }, + { TK_FILTER_NEAREST, "filter_nearest", CF_UNSPECIFIED, {}, {} }, { TK_FILTER_LINEAR, "filter_linear", CF_UNSPECIFIED, {}, {} }, { TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap", CF_UNSPECIFIED, {}, {} }, @@ -978,6 +989,18 @@ String ShaderLanguage::get_precision_name(DataPrecision p_type) { return ""; } +String ShaderLanguage::get_interpolation_name(DataInterpolation p_interpolation) { + switch (p_interpolation) { + case INTERPOLATION_FLAT: + return "flat"; + case INTERPOLATION_SMOOTH: + return "smooth"; + default: + break; + } + return ""; +} + String ShaderLanguage::get_datatype_name(DataType p_type) { switch (p_type) { case TYPE_VOID: @@ -1058,7 +1081,7 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) { result = "hint_range"; } break; case ShaderNode::Uniform::HINT_SOURCE_COLOR: { - result = "hint_color"; + result = "source_color"; } break; case ShaderNode::Uniform::HINT_NORMAL: { result = "hint_normal"; @@ -1087,9 +1110,21 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) { case ShaderNode::Uniform::HINT_DEFAULT_WHITE: { result = "hint_default_white"; } break; + case ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: { + result = "hint_default_transparent"; + } break; case ShaderNode::Uniform::HINT_ANISOTROPY: { result = "hint_anisotropy"; } break; + case ShaderNode::Uniform::HINT_SCREEN_TEXTURE: { + result = "hint_screen_texture"; + } break; + case ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE: { + result = "hint_normal_roughness_texture"; + } break; + case ShaderNode::Uniform::HINT_DEPTH_TEXTURE: { + result = "hint_depth_texture"; + } break; default: break; } @@ -1146,6 +1181,12 @@ void ShaderLanguage::clear() { current_function = StringName(); last_name = StringName(); last_type = IDENTIFIER_MAX; + current_uniform_group_name = ""; + current_uniform_subgroup_name = ""; + current_uniform_hint = ShaderNode::Uniform::HINT_NONE; + current_uniform_filter = FILTER_DEFAULT; + current_uniform_repeat = REPEAT_DEFAULT; + current_uniform_instance_index_defined = false; completion_type = COMPLETION_NONE; completion_block = nullptr; @@ -1159,7 +1200,7 @@ void ShaderLanguage::clear() { include_positions.push_back(FilePosition()); #ifdef DEBUG_ENABLED - keyword_completion_context = CF_GLOBAL_SPACE; + keyword_completion_context = CF_UNSPECIFIED; used_constants.clear(); used_varyings.clear(); used_uniforms.clear(); @@ -1222,7 +1263,7 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea 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 ((current_function == E.key || E.key == "global" || E.key == "constants") && E.value.built_ins.has(p_identifier)) { if (r_data_type) { *r_data_type = E.value.built_ins[p_identifier].type; } @@ -2455,11 +2496,15 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { // reflect + { "reflect", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false }, { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false }, + { "reflect", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false }, // refract + { "refract", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false }, { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false }, + { "refract", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false }, // faceforward @@ -2720,6 +2765,18 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false }, { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false }, + // textureProjGrad + + { "textureProjGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false }, + { "textureProjGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false }, + { "textureProjGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false }, + { "textureProjGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false }, + { "textureProjGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false }, + { "textureProjGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false }, + { "textureProjGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false }, + { "textureProjGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false }, + { "textureProjGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false }, + // textureGather { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false }, @@ -2737,6 +2794,32 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false }, { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false }, + // textureQueryLod + + { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLER2D, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureQueryLod", TYPE_VEC2, { TYPE_ISAMPLER2D, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureQueryLod", TYPE_VEC2, { TYPE_USAMPLER2D, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLER2DARRAY, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureQueryLod", TYPE_VEC2, { TYPE_ISAMPLER2DARRAY, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureQueryLod", TYPE_VEC2, { TYPE_USAMPLER2DARRAY, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLER3D, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureQueryLod", TYPE_VEC2, { TYPE_ISAMPLER3D, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureQueryLod", TYPE_VEC2, { TYPE_USAMPLER3D, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true }, + { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLERCUBE, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true }, + + // textureQueryLevels + + { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLER2D }, { "sampler" }, TAG_GLOBAL, true }, + { "textureQueryLevels", TYPE_INT, { TYPE_ISAMPLER2D }, { "sampler" }, TAG_GLOBAL, true }, + { "textureQueryLevels", TYPE_INT, { TYPE_USAMPLER2D }, { "sampler" }, TAG_GLOBAL, true }, + { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLER2DARRAY }, { "sampler" }, TAG_GLOBAL, true }, + { "textureQueryLevels", TYPE_INT, { TYPE_ISAMPLER2DARRAY }, { "sampler" }, TAG_GLOBAL, true }, + { "textureQueryLevels", TYPE_INT, { TYPE_USAMPLER2DARRAY }, { "sampler" }, TAG_GLOBAL, true }, + { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLER3D }, { "sampler" }, TAG_GLOBAL, true }, + { "textureQueryLevels", TYPE_INT, { TYPE_ISAMPLER3D }, { "sampler" }, TAG_GLOBAL, true }, + { "textureQueryLevels", TYPE_INT, { TYPE_USAMPLER3D }, { "sampler" }, TAG_GLOBAL, true }, + { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLERCUBE }, { "sampler" }, TAG_GLOBAL, true }, + // dFdx { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, @@ -3574,7 +3657,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C switch (p_type) { case ShaderLanguage::TYPE_BOOL: if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].boolean); } @@ -3587,7 +3670,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C array_size *= 2; if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].boolean); } @@ -3600,7 +3683,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C array_size *= 3; if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].boolean); } @@ -3613,7 +3696,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C array_size *= 4; if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].boolean); } @@ -3624,7 +3707,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C break; case ShaderLanguage::TYPE_INT: if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].sint); } @@ -3637,7 +3720,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 2; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].sint); } @@ -3650,7 +3733,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 3; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].sint); } @@ -3663,7 +3746,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 4; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].sint); } @@ -3674,7 +3757,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C break; case ShaderLanguage::TYPE_UINT: if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].uint); } @@ -3687,7 +3770,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 2; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].uint); } @@ -3700,7 +3783,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 3; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].uint); } @@ -3713,7 +3796,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 4; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].uint); } @@ -3724,7 +3807,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C break; case ShaderLanguage::TYPE_FLOAT: if (array_size > 0) { - PackedFloat32Array array = PackedFloat32Array(); + PackedFloat32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].real); } @@ -3737,7 +3820,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 2; - PackedVector2Array array = PackedVector2Array(); + PackedVector2Array array; for (int i = 0; i < array_size; i += 2) { array.push_back(Vector2(p_value[i].real, p_value[i + 1].real)); } @@ -3751,13 +3834,13 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C array_size *= 3; if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) { - PackedColorArray array = PackedColorArray(); + PackedColorArray array; for (int i = 0; i < array_size; i += 3) { array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real)); } value = Variant(array); } else { - PackedVector3Array array = PackedVector3Array(); + PackedVector3Array array; for (int i = 0; i < array_size; i += 3) { array.push_back(Vector3(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real)); } @@ -3776,13 +3859,13 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C array_size *= 4; if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) { - PackedColorArray array = PackedColorArray(); + PackedColorArray array; for (int i = 0; i < array_size; i += 4) { array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real, p_value[i + 3].real)); } value = Variant(array); } else { - PackedFloat32Array array = PackedFloat32Array(); + PackedFloat32Array array; for (int i = 0; i < array_size; i += 4) { array.push_back(p_value[i].real); array.push_back(p_value[i + 1].real); @@ -3803,7 +3886,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 4; - PackedFloat32Array array = PackedFloat32Array(); + PackedFloat32Array array; for (int i = 0; i < array_size; i += 4) { array.push_back(p_value[i].real); array.push_back(p_value[i + 1].real); @@ -3819,7 +3902,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 9; - PackedFloat32Array array = PackedFloat32Array(); + PackedFloat32Array array; for (int i = 0; i < array_size; i += 9) { for (int j = 0; j < 9; j++) { array.push_back(p_value[i + j].real); @@ -3845,7 +3928,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 16; - PackedFloat32Array array = PackedFloat32Array(); + PackedFloat32Array array; for (int i = 0; i < array_size; i += 16) { for (int j = 0; j < 16; j++) { array.push_back(p_value[i + j].real); @@ -3853,18 +3936,11 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C } value = Variant(array); } else { - Basis p; - p[0][0] = p_value[0].real; - p[0][1] = p_value[1].real; - p[0][2] = p_value[2].real; - p[1][0] = p_value[4].real; - p[1][1] = p_value[5].real; - p[1][2] = p_value[6].real; - p[2][0] = p_value[8].real; - p[2][1] = p_value[9].real; - p[2][2] = p_value[10].real; - Transform3D t = Transform3D(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real)); - value = Variant(t); + Projection p = Projection(Vector4(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real), + Vector4(p_value[4].real, p_value[5].real, p_value[6].real, p_value[7].real), + Vector4(p_value[8].real, p_value[9].real, p_value[10].real, p_value[11].real), + Vector4(p_value[12].real, p_value[13].real, p_value[14].real, p_value[15].real)); + value = Variant(p); } break; } @@ -4046,43 +4122,41 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform case ShaderLanguage::TYPE_USAMPLER2D: { if (p_uniform.array_size > 0) { pi.type = Variant::ARRAY; + pi.hint = PROPERTY_HINT_ARRAY_TYPE; + pi.hint_string = MAKE_RESOURCE_TYPE_HINT("Texture2D"); } else { pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "Texture2D"; } - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "Texture2D"; } break; case ShaderLanguage::TYPE_SAMPLER2DARRAY: case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: { + case ShaderLanguage::TYPE_USAMPLER2DARRAY: + case ShaderLanguage::TYPE_SAMPLERCUBE: + case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { if (p_uniform.array_size > 0) { pi.type = Variant::ARRAY; + pi.hint = PROPERTY_HINT_ARRAY_TYPE; + pi.hint_string = MAKE_RESOURCE_TYPE_HINT("TextureLayered"); } else { pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "TextureLayered"; } - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "TextureLayered"; } break; case ShaderLanguage::TYPE_SAMPLER3D: case ShaderLanguage::TYPE_ISAMPLER3D: case ShaderLanguage::TYPE_USAMPLER3D: { if (p_uniform.array_size > 0) { pi.type = Variant::ARRAY; + pi.hint = PROPERTY_HINT_ARRAY_TYPE; + pi.hint_string = MAKE_RESOURCE_TYPE_HINT("Texture3D"); } else { pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "Texture3D"; } - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "Texture3D"; - } break; - case ShaderLanguage::TYPE_SAMPLERCUBE: - case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { - if (p_uniform.array_size > 0) { - pi.type = Variant::ARRAY; - } else { - pi.type = Variant::OBJECT; - } - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "TextureLayered"; } break; case ShaderLanguage::TYPE_STRUCT: { // FIXME: Implement this. @@ -4245,8 +4319,18 @@ ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) { TYPE_INT, TYPE_UINT, TYPE_FLOAT, + TYPE_INT, + TYPE_UINT, + TYPE_FLOAT, + TYPE_INT, + TYPE_UINT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_VOID, }; + static_assert(sizeof(scalar_types) / sizeof(*scalar_types) == TYPE_MAX); + return scalar_types[p_type]; } @@ -4276,8 +4360,18 @@ int ShaderLanguage::get_cardinality(DataType p_type) { 1, 1, 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, }; + static_assert(sizeof(cardinality_table) / sizeof(*cardinality_table) == TYPE_MAX); + return cardinality_table[p_type]; } @@ -4332,18 +4426,20 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const { default: return false; } - - return false; } bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message) { - if (current_function != String("vertex") && current_function != String("fragment")) { + if (current_function != "vertex" && current_function != "fragment") { *r_message = vformat(RTR("Varying may not be assigned in the '%s' function."), current_function); return false; } switch (p_varying.stage) { case ShaderNode::Varying::STAGE_UNKNOWN: // first assign if (current_function == varying_function_names.vertex) { + if (p_varying.type < TYPE_INT) { + *r_message = vformat(RTR("Varying with '%s' data type may only be assigned in the 'fragment' function."), get_datatype_name(p_varying.type)); + return false; + } p_varying.stage = ShaderNode::Varying::STAGE_VERTEX; } else if (current_function == varying_function_names.fragment) { p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT; @@ -5143,7 +5239,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (shader->varyings.has(varname)) { switch (shader->varyings[varname].stage) { case ShaderNode::Varying::STAGE_UNKNOWN: { - _set_error(vformat(RTR("Varying '%s' must be assigned in the vertex or fragment function first."), varname)); + _set_error(vformat(RTR("Varying '%s' must be assigned in the 'vertex' or 'fragment' function first."), varname)); return nullptr; } case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT: @@ -5280,8 +5376,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons last_type = IDENTIFIER_MAX; _set_tkpos(pos); - DataType data_type; - IdentifierType ident_type; + DataType data_type = TYPE_MAX; + IdentifierType ident_type = IDENTIFIER_MAX; int array_size = 0; StringName struct_name; bool is_local = false; @@ -5318,6 +5414,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } _set_tkpos(prev_pos); + ShaderNode::Varying &var = shader->varyings[identifier]; String error; if (is_token_operator_assign(next_token.type)) { if (!_validate_varying_assign(shader->varyings[identifier], &error)) { @@ -5325,9 +5422,17 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return nullptr; } } else { - ShaderNode::Varying &var = shader->varyings[identifier]; - switch (var.stage) { + case ShaderNode::Varying::STAGE_UNKNOWN: { + if (var.type < TYPE_INT) { + if (current_function == varying_function_names.vertex) { + _set_error(vformat(RTR("Varying with '%s' data type may only be used in the 'fragment' function."), get_datatype_name(var.type))); + } else { + _set_error(vformat(RTR("Varying '%s' must be assigned in the 'fragment' function first."), identifier)); + } + return nullptr; + } + } break; case ShaderNode::Varying::STAGE_VERTEX: if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) { var.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT; @@ -5342,6 +5447,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons break; } } + + if ((var.stage != ShaderNode::Varying::STAGE_FRAGMENT && var.stage != ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT) && var.type < TYPE_FLOAT && var.interpolation != INTERPOLATION_FLAT) { + _set_tkpos(var.tkpos); + _set_error(RTR("Varying with integer data type must be declared with `flat` interpolation qualifier.")); + return nullptr; + } } if (ident_type == IDENTIFIER_FUNCTION) { @@ -7157,9 +7268,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (!n) { return ERR_PARSE_ERROR; } - if (n->get_datatype() != TYPE_INT) { - _set_error(RTR("Expected an integer expression.")); - return ERR_PARSE_ERROR; + { + const ShaderLanguage::DataType switch_type = n->get_datatype(); + if (switch_type != TYPE_INT && switch_type != TYPE_UINT) { + _set_error(RTR("Expected an integer expression.")); + return ERR_PARSE_ERROR; + } } tk = _get_token(); if (tk.type != TK_PARENTHESIS_CLOSE) { @@ -7500,7 +7614,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_BUG; } - if (b && b->parent_function && p_function_info.main_function) { + if (b->parent_function && p_function_info.main_function) { _set_error(vformat(RTR("Using '%s' in the '%s' processor function is incorrect."), "return", b->parent_function->name)); return ERR_PARSE_ERROR; } @@ -7754,6 +7868,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f Token next; if (!is_shader_inc) { +#ifdef DEBUG_ENABLED + keyword_completion_context = CF_SHADER_TYPE; +#endif // DEBUG_ENABLED tk = _get_token(); if (tk.type != TK_SHADER_TYPE) { @@ -8097,21 +8214,27 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f }; [[fallthrough]]; case TK_INSTANCE: { + if (tk.type == TK_INSTANCE) { #ifdef DEBUG_ENABLED - keyword_completion_context = CF_UNIFORM_KEYWORD; - if (_lookup_next(next)) { - if (next.type == TK_UNIFORM) { - keyword_completion_context ^= CF_UNIFORM_KEYWORD; + keyword_completion_context = CF_UNIFORM_KEYWORD; + if (_lookup_next(next)) { + if (next.type == TK_UNIFORM) { + keyword_completion_context ^= CF_UNIFORM_KEYWORD; + } } - } #endif // DEBUG_ENABLED - if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) { - tk = _get_token(); - if (tk.type != TK_UNIFORM) { - _set_expected_after_error("uniform", "instance"); + if (String(shader_type_identifier) != "spatial") { + _set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier)); return ERR_PARSE_ERROR; } - uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE; + if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) { + tk = _get_token(); + if (tk.type != TK_UNIFORM) { + _set_expected_after_error("uniform", "instance"); + return ERR_PARSE_ERROR; + } + uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE; + } } }; [[fallthrough]]; @@ -8128,7 +8251,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f } } DataPrecision precision = PRECISION_DEFAULT; - DataInterpolation interpolation = INTERPOLATION_SMOOTH; + DataInterpolation interpolation = INTERPOLATION_DEFAULT; DataType type; StringName name; int array_size = 0; @@ -8237,8 +8360,13 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } - if (!is_uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) { - _set_error(RTR("Invalid type for varying, only 'float', 'vec2', 'vec3', 'vec4', 'mat2', 'mat3', 'mat4', or arrays of these types are allowed.")); + if (!is_uniform && interpolation != INTERPOLATION_DEFAULT && type < TYPE_INT) { + _set_error(vformat(RTR("Interpolation modifier '%s' cannot be used with boolean types."), get_interpolation_name(interpolation))); + return ERR_PARSE_ERROR; + } + + if (!is_uniform && type > TYPE_MAT4) { + _set_error(RTR("Invalid data type for varying.")); return ERR_PARSE_ERROR; } @@ -8281,7 +8409,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f if (is_uniform) { if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL && Engine::get_singleton()->is_editor_hint()) { // Type checking for global uniforms is not allowed outside the editor. //validate global uniform - DataType gvtype = global_var_get_type_func(name); + DataType gvtype = global_shader_uniform_get_type_func(name); if (gvtype == TYPE_MAX) { _set_error(vformat(RTR("Global uniform '%s' does not exist. Create it in Project Settings."), String(name))); return ERR_PARSE_ERROR; @@ -8298,6 +8426,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f uniform.scope = uniform_scope; uniform.precision = precision; uniform.array_size = array_size; + uniform.group = current_uniform_group_name; + uniform.subgroup = current_uniform_subgroup_name; tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { @@ -8412,6 +8542,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f case TK_HINT_DEFAULT_WHITE_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_DEFAULT_WHITE; } break; + case TK_HINT_DEFAULT_TRANSPARENT_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT; + } break; case TK_HINT_NORMAL_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_NORMAL; } break; @@ -8541,6 +8674,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f } custom_instance_index = tk.constant; + current_uniform_instance_index_defined = true; if (custom_instance_index >= MAX_INSTANCE_UNIFORM_INDICES) { _set_error(vformat(RTR("Allowed instance uniform indices must be within [0..%d] range."), MAX_INSTANCE_UNIFORM_INDICES - 1)); @@ -8554,6 +8688,18 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } } break; + case TK_HINT_SCREEN_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_SCREEN_TEXTURE; + --texture_uniforms; + } break; + case TK_HINT_NORMAL_ROUGHNESS_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE; + --texture_uniforms; + } break; + case TK_HINT_DEPTH_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE; + --texture_uniforms; + } break; case TK_FILTER_NEAREST: { new_filter = FILTER_NEAREST; } break; @@ -8578,6 +8724,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f case TK_REPEAT_ENABLE: { new_repeat = REPEAT_ENABLE; } break; + default: break; } @@ -8596,32 +8743,35 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } else { uniform.hint = new_hint; + current_uniform_hint = new_hint; } } if (new_filter != FILTER_DEFAULT) { if (uniform.filter != FILTER_DEFAULT) { if (uniform.filter == new_filter) { - _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_filter_name(new_filter))); + _set_error(vformat(RTR("Duplicated filter mode: '%s'."), get_texture_filter_name(new_filter))); } else { - _set_error(vformat(RTR("Redefinition of hint: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter))); + _set_error(vformat(RTR("Redefinition of filter mode: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter))); } return ERR_PARSE_ERROR; } else { uniform.filter = new_filter; + current_uniform_filter = new_filter; } } if (new_repeat != REPEAT_DEFAULT) { if (uniform.repeat != REPEAT_DEFAULT) { if (uniform.repeat == new_repeat) { - _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_repeat_name(new_repeat))); + _set_error(vformat(RTR("Duplicated repeat mode: '%s'."), get_texture_repeat_name(new_repeat))); } else { - _set_error(vformat(RTR("Redefinition of hint: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat))); + _set_error(vformat(RTR("Redefinition of repeat mode: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat))); } return ERR_PARSE_ERROR; } else { uniform.repeat = new_repeat; + current_uniform_repeat = new_repeat; } } @@ -8689,6 +8839,11 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f keyword_completion_context = CF_GLOBAL_SPACE; #endif // DEBUG_ENABLED completion_type = COMPLETION_NONE; + + current_uniform_hint = ShaderNode::Uniform::HINT_NONE; + current_uniform_filter = FILTER_DEFAULT; + current_uniform_repeat = REPEAT_DEFAULT; + current_uniform_instance_index_defined = false; } else { // varying ShaderNode::Varying varying; varying.type = type; @@ -8724,6 +8879,45 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f } } break; + case TK_UNIFORM_GROUP: { + tk = _get_token(); + if (tk.type == TK_IDENTIFIER) { + current_uniform_group_name = tk.text; + tk = _get_token(); + if (tk.type == TK_PERIOD) { + tk = _get_token(); + if (tk.type == TK_IDENTIFIER) { + current_uniform_subgroup_name = tk.text; + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_expected_error(";"); + return ERR_PARSE_ERROR; + } + } else { + _set_error(RTR("Expected an uniform subgroup identifier.")); + return ERR_PARSE_ERROR; + } + } else if (tk.type != TK_SEMICOLON) { + _set_expected_error(";", "."); + return ERR_PARSE_ERROR; + } + } else { + if (tk.type != TK_SEMICOLON) { + if (current_uniform_group_name.is_empty()) { + _set_error(RTR("Expected an uniform group identifier.")); + } else { + _set_error(RTR("Expected an uniform group identifier or `;`.")); + } + return ERR_PARSE_ERROR; + } else if (current_uniform_group_name.is_empty()) { + _set_error(RTR("Group needs to be opened before.")); + return ERR_PARSE_ERROR; + } else { + current_uniform_group_name = ""; + current_uniform_subgroup_name = ""; + } + } + } break; case TK_SHADER_TYPE: { _set_error(RTR("Shader type is already defined.")); return ERR_PARSE_ERROR; @@ -9574,6 +9768,25 @@ String ShaderLanguage::get_shader_type(const String &p_code) { return String(); } +bool ShaderLanguage::is_builtin_func_out_parameter(const String &p_name, int p_param) { + int i = 0; + while (builtin_func_out_args[i].name) { + if (p_name == builtin_func_out_args[i].name) { + for (int j = 0; j < BuiltinFuncOutArgs::MAX_ARGS; j++) { + int arg = builtin_func_out_args[i].arguments[j]; + if (arg == p_param) { + return true; + } + if (arg < 0) { + return false; + } + } + } + i++; + } + return false; +} + #ifdef DEBUG_ENABLED void ShaderLanguage::_check_warning_accums() { for (const KeyValue<ShaderWarning::Code, HashMap<StringName, HashMap<StringName, Usage>> *> &E : warnings_check_map2) { @@ -9615,7 +9828,7 @@ Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_i is_shader_inc = p_info.is_include; code = p_code; - global_var_get_type_func = p_info.global_variable_type_func; + global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func; varying_function_names = p_info.varying_function_names; @@ -9644,7 +9857,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ varying_function_names = p_info.varying_function_names; nodes = nullptr; - global_var_get_type_func = p_info.global_variable_type_func; + global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func; shader = alloc_node<ShaderNode>(); _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types); @@ -10186,31 +10399,37 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } break; case COMPLETION_HINT: { if (completion_base == DataType::TYPE_VEC3 || completion_base == DataType::TYPE_VEC4) { - ScriptLanguage::CodeCompletionOption option("source_color", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); - r_options->push_back(option); + if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) { + ScriptLanguage::CodeCompletionOption option("source_color", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + r_options->push_back(option); + } } else if ((completion_base == DataType::TYPE_INT || completion_base == DataType::TYPE_FLOAT) && !completion_base_array) { - ScriptLanguage::CodeCompletionOption option("hint_range", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) { + ScriptLanguage::CodeCompletionOption option("hint_range", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); - if (completion_base == DataType::TYPE_INT) { - option.insert_text = "hint_range(0, 100, 1)"; - } else { - option.insert_text = "hint_range(0.0, 1.0, 0.1)"; - } + if (completion_base == DataType::TYPE_INT) { + option.insert_text = "hint_range(0, 100, 1)"; + } else { + option.insert_text = "hint_range(0.0, 1.0, 0.1)"; + } - r_options->push_back(option); + r_options->push_back(option); + } } else if ((int(completion_base) > int(TYPE_MAT4) && int(completion_base) < int(TYPE_STRUCT)) && !completion_base_array) { - static Vector<String> options; - - if (options.is_empty()) { + Vector<String> options; + if (current_uniform_filter == FILTER_DEFAULT) { options.push_back("filter_linear"); options.push_back("filter_linear_mipmap"); options.push_back("filter_linear_mipmap_anisotropic"); options.push_back("filter_nearest"); options.push_back("filter_nearest_mipmap"); options.push_back("filter_nearest_mipmap_anisotropic"); + } + if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) { options.push_back("hint_anisotropy"); options.push_back("hint_default_black"); options.push_back("hint_default_white"); + options.push_back("hint_default_transparent"); options.push_back("hint_normal"); options.push_back("hint_roughness_a"); options.push_back("hint_roughness_b"); @@ -10218,7 +10437,12 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ options.push_back("hint_roughness_gray"); options.push_back("hint_roughness_normal"); options.push_back("hint_roughness_r"); + options.push_back("hint_screen_texture"); + options.push_back("hint_normal_roughness_texture"); + options.push_back("hint_depth_texture"); options.push_back("source_color"); + } + if (current_uniform_repeat == REPEAT_DEFAULT) { options.push_back("repeat_enable"); options.push_back("repeat_disable"); } @@ -10228,7 +10452,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ r_options->push_back(option); } } - if (!completion_base_array) { + if (!completion_base_array && !current_uniform_instance_index_defined) { ScriptLanguage::CodeCompletionOption option("instance_index", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); option.insert_text = "instance_index(0)"; r_options->push_back(option); |