Skip to content

Commit 5a14ab7

Browse files
committed
[Shaders] Allow constants and expressions in hint_range
1 parent 09ea7bc commit 5a14ab7

File tree

3 files changed

+82
-57
lines changed

3 files changed

+82
-57
lines changed

servers/rendering/shader_language.cpp

Lines changed: 58 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
13991399
if (r_is_const) {
14001400
*r_is_const = p_function_info.built_ins[p_identifier].constant;
14011401
}
1402+
if (r_constant_values) {
1403+
*r_constant_values = p_function_info.built_ins[p_identifier].values;
1404+
}
14021405
if (r_type) {
14031406
*r_type = IDENTIFIER_BUILTIN_VAR;
14041407
}
@@ -1551,7 +1554,7 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
15511554
return false;
15521555
}
15531556

1554-
bool ShaderLanguage::_validate_operator(const BlockNode *p_block, OperatorNode *p_op, DataType *r_ret_type, int *r_ret_size) {
1557+
bool ShaderLanguage::_validate_operator(const BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_op, DataType *r_ret_type, int *r_ret_size) {
15551558
bool valid = false;
15561559
DataType ret_type = TYPE_VOID;
15571560
int ret_size = 0;
@@ -2017,18 +2020,18 @@ bool ShaderLanguage::_validate_operator(const BlockNode *p_block, OperatorNode *
20172020

20182021
if (valid && (!p_block || p_block->use_op_eval)) {
20192022
// Need to be placed here and not in the `_reduce_expression` because otherwise expressions like `1 + 2 / 2` will not work correctly.
2020-
valid = _eval_operator(p_block, p_op);
2023+
valid = _eval_operator(p_block, p_function_info, p_op);
20212024
}
20222025

20232026
return valid;
20242027
}
20252028

2026-
Vector<ShaderLanguage::Scalar> ShaderLanguage::_get_node_values(const BlockNode *p_block, Node *p_node) {
2029+
Vector<ShaderLanguage::Scalar> ShaderLanguage::_get_node_values(const BlockNode *p_block, const FunctionInfo &p_function_info, Node *p_node) {
20272030
Vector<Scalar> result;
20282031

20292032
switch (p_node->type) {
20302033
case Node::NODE_TYPE_VARIABLE: {
2031-
_find_identifier(p_block, false, FunctionInfo(), static_cast<VariableNode *>(p_node)->name, nullptr, nullptr, nullptr, nullptr, nullptr, &result);
2034+
_find_identifier(p_block, false, p_function_info, static_cast<VariableNode *>(p_node)->name, nullptr, nullptr, nullptr, nullptr, nullptr, &result);
20322035
} break;
20332036
default: {
20342037
result = p_node->get_values();
@@ -2038,7 +2041,7 @@ Vector<ShaderLanguage::Scalar> ShaderLanguage::_get_node_values(const BlockNode
20382041
return result;
20392042
}
20402043

2041-
bool ShaderLanguage::_eval_operator(const BlockNode *p_block, OperatorNode *p_op) {
2044+
bool ShaderLanguage::_eval_operator(const BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_op) {
20422045
bool is_valid = true;
20432046

20442047
switch (p_op->op) {
@@ -2080,8 +2083,8 @@ bool ShaderLanguage::_eval_operator(const BlockNode *p_block, OperatorNode *p_op
20802083
}
20812084
}
20822085

2083-
Vector<Scalar> va = _get_node_values(p_block, p_op->arguments[0]);
2084-
Vector<Scalar> vb = _get_node_values(p_block, p_op->arguments[1]);
2086+
Vector<Scalar> va = _get_node_values(p_block, p_function_info, p_op->arguments[0]);
2087+
Vector<Scalar> vb = _get_node_values(p_block, p_function_info, p_op->arguments[1]);
20852088

20862089
if (is_op_vec_transform) {
20872090
p_op->values = _eval_vector_transform(va, vb, a, b, p_op->get_datatype());
@@ -2092,7 +2095,7 @@ bool ShaderLanguage::_eval_operator(const BlockNode *p_block, OperatorNode *p_op
20922095
case OP_NOT:
20932096
case OP_NEGATE:
20942097
case OP_BIT_INVERT: {
2095-
p_op->values = _eval_unary_vector(_get_node_values(p_block, p_op->arguments[0]), p_op->get_datatype(), p_op->op);
2098+
p_op->values = _eval_unary_vector(_get_node_values(p_block, p_function_info, p_op->arguments[0]), p_op->get_datatype(), p_op->op);
20962099
} break;
20972100
default: {
20982101
} break;
@@ -3661,7 +3664,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
36613664
int max = builtin_func_const_args[constarg_idx].max;
36623665

36633666
bool error = false;
3664-
Vector<Scalar> values = _get_node_values(p_block, p_func->arguments[arg]);
3667+
Vector<Scalar> values = _get_node_values(p_block, p_function_info, p_func->arguments[arg]);
36653668
if (p_func->arguments[arg]->get_datatype() == TYPE_INT && !values.is_empty()) {
36663669
if (values[0].sint < min || values[0].sint > max) {
36673670
error = true;
@@ -5662,7 +5665,7 @@ Error ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo &
56625665
Node *expr = _parse_and_reduce_expression(p_block, p_function_info);
56635666

56645667
if (expr) {
5665-
Vector<Scalar> values = _get_node_values(p_block, expr);
5668+
Vector<Scalar> values = _get_node_values(p_block, p_function_info, expr);
56665669

56675670
if (!values.is_empty()) {
56685671
switch (expr->get_datatype()) {
@@ -7279,7 +7282,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
72797282
op->op = tk.type == TK_OP_DECREMENT ? OP_POST_DECREMENT : OP_POST_INCREMENT;
72807283
op->arguments.push_back(expr);
72817284

7282-
if (!_validate_operator(p_block, op, &op->return_cache, &op->return_array_size)) {
7285+
if (!_validate_operator(p_block, p_function_info, op, &op->return_cache, &op->return_array_size)) {
72837286
_set_error(RTR("Invalid base type for increment/decrement operator."));
72847287
return nullptr;
72857288
}
@@ -7631,7 +7634,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
76317634
expression.write[i].is_op = false;
76327635
expression.write[i].node = op;
76337636

7634-
if (!_validate_operator(p_block, op, &op->return_cache, &op->return_array_size)) {
7637+
if (!_validate_operator(p_block, p_function_info, op, &op->return_cache, &op->return_array_size)) {
76357638
if (error_set) {
76367639
return nullptr;
76377640
}
@@ -7673,7 +7676,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
76737676

76747677
expression.write[next_op - 1].is_op = false;
76757678
expression.write[next_op - 1].node = op;
7676-
if (!_validate_operator(p_block, op, &op->return_cache, &op->return_array_size)) {
7679+
if (!_validate_operator(p_block, p_function_info, op, &op->return_cache, &op->return_array_size)) {
76777680
if (error_set) {
76787681
return nullptr;
76797682
}
@@ -7740,7 +7743,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
77407743

77417744
//replace all 3 nodes by this operator and make it an expression
77427745

7743-
if (!_validate_operator(p_block, op, &op->return_cache, &op->return_array_size)) {
7746+
if (!_validate_operator(p_block, p_function_info, op, &op->return_cache, &op->return_array_size)) {
77447747
if (error_set) {
77457748
return nullptr;
77467749
}
@@ -9073,6 +9076,40 @@ Error ShaderLanguage::_validate_precision(DataType p_type, DataPrecision p_preci
90739076
return OK;
90749077
}
90759078

9079+
bool ShaderLanguage::_parse_numeric_constant_expression(const FunctionInfo &p_function_info, float &r_constant) {
9080+
ShaderLanguage::Node *expr = _parse_and_reduce_expression(nullptr, p_function_info);
9081+
if (expr == nullptr) {
9082+
return false;
9083+
}
9084+
9085+
Vector<Scalar> values;
9086+
if (expr->type == Node::NODE_TYPE_VARIABLE) {
9087+
_find_identifier(nullptr, false, p_function_info, static_cast<VariableNode *>(expr)->name, nullptr, nullptr, nullptr, nullptr, nullptr, &values);
9088+
} else {
9089+
values = expr->get_values();
9090+
}
9091+
9092+
if (values.is_empty()) {
9093+
return false; // To prevent possible crash.
9094+
}
9095+
9096+
switch (expr->get_datatype()) {
9097+
case TYPE_FLOAT:
9098+
r_constant = values[0].real;
9099+
break;
9100+
case TYPE_INT:
9101+
r_constant = static_cast<float>(values[0].sint);
9102+
break;
9103+
case TYPE_UINT:
9104+
r_constant = static_cast<float>(values[0].uint);
9105+
break;
9106+
default:
9107+
return false;
9108+
}
9109+
9110+
return true;
9111+
}
9112+
90769113
Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types) {
90779114
Token tk;
90789115
TkPos prev_pos;
@@ -9817,58 +9854,30 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
98179854
return ERR_PARSE_ERROR;
98189855
}
98199856

9820-
tk = _get_token();
9821-
9822-
float sign = 1.0;
9823-
9824-
if (tk.type == TK_OP_SUB) {
9825-
sign = -1.0;
9826-
tk = _get_token();
9827-
}
9828-
9829-
if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
9830-
_set_error(RTR("Expected an integer constant."));
9857+
if (!_parse_numeric_constant_expression(constants, uniform.hint_range[0])) {
9858+
_set_error(RTR("Expected a valid numeric expression."));
98319859
return ERR_PARSE_ERROR;
98329860
}
98339861

9834-
uniform.hint_range[0] = tk.constant;
9835-
uniform.hint_range[0] *= sign;
9836-
98379862
tk = _get_token();
98389863

98399864
if (tk.type != TK_COMMA) {
9840-
_set_error(RTR("Expected ',' after integer constant."));
9865+
_set_expected_error(",");
98419866
return ERR_PARSE_ERROR;
98429867
}
98439868

9844-
tk = _get_token();
9845-
9846-
sign = 1.0;
9847-
9848-
if (tk.type == TK_OP_SUB) {
9849-
sign = -1.0;
9850-
tk = _get_token();
9851-
}
9852-
9853-
if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
9854-
_set_error(RTR("Expected an integer constant after ','."));
9869+
if (!_parse_numeric_constant_expression(constants, uniform.hint_range[1])) {
9870+
_set_error(RTR("Expected a valid numeric expression after ','."));
98559871
return ERR_PARSE_ERROR;
98569872
}
98579873

9858-
uniform.hint_range[1] = tk.constant;
9859-
uniform.hint_range[1] *= sign;
9860-
98619874
tk = _get_token();
98629875

98639876
if (tk.type == TK_COMMA) {
9864-
tk = _get_token();
9865-
9866-
if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
9867-
_set_error(RTR("Expected an integer constant after ','."));
9877+
if (!_parse_numeric_constant_expression(constants, uniform.hint_range[2])) {
9878+
_set_error(RTR("Expected a valid numeric expression after ','."));
98689879
return ERR_PARSE_ERROR;
98699880
}
9870-
9871-
uniform.hint_range[2] = tk.constant;
98729881
tk = _get_token();
98739882
} else {
98749883
if (type == TYPE_INT) {

servers/rendering/shader_language.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -862,12 +862,14 @@ class ShaderLanguage {
862862
struct BuiltInInfo {
863863
DataType type = TYPE_VOID;
864864
bool constant = false;
865+
Vector<Scalar> values;
865866

866867
BuiltInInfo() {}
867868

868-
BuiltInInfo(DataType p_type, bool p_constant = false) :
869+
BuiltInInfo(DataType p_type, bool p_constant = false, const Vector<Scalar> &p_values = {}) :
869870
type(p_type),
870-
constant(p_constant) {}
871+
constant(p_constant),
872+
values(p_values) {}
871873
};
872874

873875
struct StageFunctionInfo {
@@ -1119,10 +1121,10 @@ class ShaderLanguage {
11191121
#endif // DEBUG_ENABLED
11201122
bool _is_operator_assign(Operator p_op) const;
11211123
bool _validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message = nullptr);
1122-
bool _validate_operator(const BlockNode *p_block, OperatorNode *p_op, DataType *r_ret_type = nullptr, int *r_ret_size = nullptr);
1124+
bool _validate_operator(const BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_op, DataType *r_ret_type = nullptr, int *r_ret_size = nullptr);
11231125

1124-
Vector<Scalar> _get_node_values(const BlockNode *p_block, Node *p_node);
1125-
bool _eval_operator(const BlockNode *p_block, OperatorNode *p_op);
1126+
Vector<Scalar> _get_node_values(const BlockNode *p_block, const FunctionInfo &p_function_info, Node *p_node);
1127+
bool _eval_operator(const BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_op);
11261128
Scalar _eval_unary_scalar(const Scalar &p_a, Operator p_op, DataType p_ret_type);
11271129
Scalar _eval_scalar(const Scalar &p_a, const Scalar &p_b, Operator p_op, DataType p_ret_type, bool &r_is_valid);
11281130
Vector<Scalar> _eval_unary_vector(const Vector<Scalar> &p_va, DataType p_ret_type, Operator p_op);
@@ -1212,6 +1214,7 @@ class ShaderLanguage {
12121214
String _get_shader_type_list(const HashSet<String> &p_shader_types) const;
12131215
String _get_qualifier_str(ArgumentQualifier p_qualifier) const;
12141216

1217+
bool _parse_numeric_constant_expression(const FunctionInfo &p_function_info, float &r_constant);
12151218
Error _parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types);
12161219

12171220
Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);

servers/rendering/shader_types.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,29 @@ static ShaderLanguage::BuiltInInfo constt(ShaderLanguage::DataType p_type) {
5252
return ShaderLanguage::BuiltInInfo(p_type, true);
5353
}
5454

55+
static ShaderLanguage::BuiltInInfo constvt(ShaderLanguage::DataType p_type, const Vector<ShaderLanguage::Scalar> &p_values) {
56+
return ShaderLanguage::BuiltInInfo(p_type, true, p_values);
57+
}
58+
5559
ShaderTypes::ShaderTypes() {
5660
singleton = this;
5761

5862
/*************** SPATIAL ***********************/
5963

64+
ShaderLanguage::Scalar pi_scalar;
65+
pi_scalar.real = Math::PI;
66+
67+
ShaderLanguage::Scalar tau_scalar;
68+
tau_scalar.real = Math::TAU;
69+
70+
ShaderLanguage::Scalar e_scalar;
71+
e_scalar.real = Math::E;
72+
6073
shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
6174
shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["EXPOSURE"] = constt(ShaderLanguage::TYPE_FLOAT);
62-
shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
63-
shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
64-
shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
75+
shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["PI"] = constvt(ShaderLanguage::TYPE_FLOAT, { pi_scalar });
76+
shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["TAU"] = constvt(ShaderLanguage::TYPE_FLOAT, { tau_scalar });
77+
shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["E"] = constvt(ShaderLanguage::TYPE_FLOAT, { e_scalar });
6578
shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
6679
shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["CLIP_SPACE_FAR"] = constt(ShaderLanguage::TYPE_FLOAT);
6780

0 commit comments

Comments
 (0)