summaryrefslogtreecommitdiff
path: root/servers/rendering/shader_language.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/shader_language.cpp')
-rw-r--r--servers/rendering/shader_language.cpp324
1 files changed, 235 insertions, 89 deletions
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index a92292209f..11a9303f11 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* shader_language.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* shader_language.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "shader_language.h"
@@ -90,8 +90,9 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"IDENTIFIER",
"TRUE",
"FALSE",
- "REAL_CONSTANT",
+ "FLOAT_CONSTANT",
"INT_CONSTANT",
+ "UINT_CONSTANT",
"TYPE_VOID",
"TYPE_BOOL",
"TYPE_BVEC2",
@@ -126,6 +127,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"INTERPOLATION_FLAT",
"INTERPOLATION_SMOOTH",
"CONST",
+ "STRUCT",
"PRECISION_LOW",
"PRECISION_MID",
"PRECISION_HIGH",
@@ -169,6 +171,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"CF_DO",
"CF_SWITCH",
"CF_CASE",
+ "CF_DEFAULT",
"CF_BREAK",
"CF_CONTINUE",
"CF_RETURN",
@@ -185,19 +188,26 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"SEMICOLON",
"PERIOD",
"UNIFORM",
+ "UNIFORM_GROUP",
"INSTANCE",
"GLOBAL",
"VARYING",
- "IN",
- "OUT",
- "INOUT",
+ "ARG_IN",
+ "ARG_OUT",
+ "ARG_INOUT",
"RENDER_MODE",
- "SOURCE_COLOR",
"HINT_DEFAULT_WHITE_TEXTURE",
"HINT_DEFAULT_BLACK_TEXTURE",
"HINT_DEFAULT_TRANSPARENT_TEXTURE",
"HINT_NORMAL_TEXTURE",
+ "HINT_ROUGHNESS_NORMAL_TEXTURE",
+ "HINT_ROUGHNESS_R",
+ "HINT_ROUGHNESS_G",
+ "HINT_ROUGHNESS_B",
+ "HINT_ROUGHNESS_A",
+ "HINT_ROUGHNESS_GRAY",
"HINT_ANISOTROPY_TEXTURE",
+ "HINT_SOURCE_COLOR",
"HINT_RANGE",
"HINT_INSTANCE_INDEX",
"HINT_SCREEN_TEXTURE",
@@ -612,7 +622,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
char_idx += 2;
include_positions.resize(include_positions.size() - 1); // Pop back.
- tk_line = include_positions[include_positions.size() - 1].line; // Restore line.
+ tk_line = include_positions[include_positions.size() - 1].line - 1; // Restore line.
} else {
return _make_token(TK_ERROR, "Invalid include enter/exit hint token (@@> and @@<)");
@@ -989,6 +999,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:
@@ -1251,7 +1273,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;
}
@@ -2815,6 +2837,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
{ "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ // dFdxCoarse
+
+ { "dFdxCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
+ // dFdxFine
+
+ { "dFdxFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
// dFdy
{ "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
@@ -2822,6 +2858,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
{ "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ // dFdyCoarse
+
+ { "dFdyCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
+ // dFdyFine
+
+ { "dFdyFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
// fwidth
{ "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
@@ -2829,6 +2879,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
{ "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ // fwidthCoarse
+
+ { "fwidthCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
+ // fwidthFine
+
+ { "fwidthFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
// Sub-functions.
// array
@@ -3645,7 +3709,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);
}
@@ -3658,7 +3722,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);
}
@@ -3671,7 +3735,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);
}
@@ -3684,7 +3748,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);
}
@@ -3695,7 +3759,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);
}
@@ -3708,7 +3772,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);
}
@@ -3721,7 +3785,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);
}
@@ -3734,7 +3798,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);
}
@@ -3745,7 +3809,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);
}
@@ -3758,7 +3822,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);
}
@@ -3771,7 +3835,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);
}
@@ -3784,7 +3848,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);
}
@@ -3795,7 +3859,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);
}
@@ -3808,7 +3872,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));
}
@@ -3822,13 +3886,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));
}
@@ -3847,13 +3911,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);
@@ -3874,7 +3938,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);
@@ -3890,7 +3954,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);
@@ -3916,7 +3980,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);
@@ -4110,43 +4174,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.
@@ -4309,8 +4371,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];
}
@@ -4340,8 +4412,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];
}
@@ -4399,13 +4481,17 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
}
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;
@@ -5205,7 +5291,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:
@@ -5365,6 +5451,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
} else {
if (!_find_identifier(p_block, false, p_function_info, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) {
+ if (identifier == "SCREEN_TEXTURE" || identifier == "DEPTH_TEXTURE" || identifier == "NORMAL_ROUGHNESS_TEXTURE") {
+ String name = String(identifier);
+ String name_lower = name.to_lower();
+ _set_error(vformat(RTR("%s has been removed in favor of using hint_%s with a uniform.\nTo continue with minimal code changes add 'uniform sampler2D %s : hint_%s, filter_linear_mipmap;' near the top of your shader."), name, name_lower, name, name_lower));
+ return nullptr;
+ }
_set_error(vformat(RTR("Unknown identifier in expression: '%s'."), String(identifier)));
return nullptr;
}
@@ -5389,6 +5481,16 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
} else {
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;
@@ -7570,7 +7672,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;
}
@@ -8170,21 +8272,31 @@ 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 (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
+ _set_error(RTR("Uniform instances are not supported in gl_compatibility shaders."));
+ return ERR_PARSE_ERROR;
+ }
+ 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]];
@@ -8201,7 +8313,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;
@@ -8310,6 +8422,11 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
return ERR_PARSE_ERROR;
}
+ 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;
@@ -8635,12 +8752,22 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
} break;
case TK_HINT_SCREEN_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_SCREEN_TEXTURE;
+ --texture_uniforms;
+ --texture_binding;
} break;
case TK_HINT_NORMAL_ROUGHNESS_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE;
+ --texture_uniforms;
+ --texture_binding;
+ if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
+ _set_error(RTR("'hint_normal_roughness_texture is not supported in gl_compatibility shaders."));
+ return ERR_PARSE_ERROR;
+ }
} break;
case TK_HINT_DEPTH_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE;
+ --texture_uniforms;
+ --texture_binding;
} break;
case TK_FILTER_NEAREST: {
new_filter = FILTER_NEAREST;
@@ -8851,7 +8978,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
_set_error(RTR("Expected an uniform group identifier or `;`."));
}
return ERR_PARSE_ERROR;
- } else if (tk.type == TK_SEMICOLON && current_uniform_group_name.is_empty()) {
+ } else if (current_uniform_group_name.is_empty()) {
_set_error(RTR("Group needs to be opened before."));
return ERR_PARSE_ERROR;
} else {
@@ -9710,6 +9837,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) {