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.cpp135
1 files changed, 110 insertions, 25 deletions
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 742ad8a7bf..3b73f6a8d6 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -920,7 +920,7 @@ void ShaderLanguage::clear() {
}
}
-bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name) {
+bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name, ConstantNode::Value *r_constant_value) {
if (p_function_info.built_ins.has(p_identifier)) {
if (r_data_type) {
*r_data_type = p_function_info.built_ins[p_identifier].type;
@@ -968,6 +968,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_struct_name) {
*r_struct_name = p_block->variables[p_identifier].struct_name;
}
+ if (r_constant_value) {
+ *r_constant_value = p_block->variables[p_identifier].value;
+ }
return true;
}
@@ -1028,6 +1031,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
}
if (shader->constants.has(p_identifier)) {
+ if (r_is_const) {
+ *r_is_const = true;
+ }
if (r_data_type) {
*r_data_type = shader->constants[p_identifier].type;
}
@@ -1040,6 +1046,11 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_struct_name) {
*r_struct_name = shader->constants[p_identifier].type_str;
}
+ if (r_constant_value) {
+ if (shader->constants[p_identifier].initializer && shader->constants[p_identifier].initializer->values.size() == 1) {
+ *r_constant_value = shader->constants[p_identifier].initializer->values[0];
+ }
+ }
return true;
}
@@ -5010,17 +5021,53 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
decl.name = name;
decl.size = 0U;
+ pos = _get_tkpos();
tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
unknown_size = true;
} else {
if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
+ _set_tkpos(pos);
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (n) {
+ if (n->type == Node::TYPE_VARIABLE) {
+ VariableNode *vn = static_cast<VariableNode *>(n);
+ if (vn) {
+ ConstantNode::Value v;
+ DataType data_type;
+
+ _find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, &is_const, nullptr, nullptr, &v);
+
+ if (is_const) {
+ if (data_type == TYPE_INT) {
+ int32_t value = v.sint;
+ if (value > 0) {
+ node->size_expression = n;
+ decl.size = (uint32_t)value;
+ }
+ } else if (data_type == TYPE_UINT) {
+ uint32_t value = v.uint;
+ if (value > 0U) {
+ node->size_expression = n;
+ decl.size = value;
+ }
+ }
+ }
+ }
+ } else if (n->type == Node::TYPE_OPERATOR) {
+ _set_error("Array size expressions are not yet implemented.");
+ return ERR_PARSE_ERROR;
+ }
+ }
+ } else if (((int)tk.constant) > 0) {
+ decl.size = (uint32_t)tk.constant;
+ }
+
+ if (decl.size == 0U) {
_set_error("Expected integer constant > 0 or ']'");
return ERR_PARSE_ERROR;
}
-
- decl.size = ((uint32_t)tk.constant);
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
@@ -5218,7 +5265,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
_set_error("Expected array initialization");
return ERR_PARSE_ERROR;
}
- if (is_const) {
+ if (node->is_const) {
_set_error("Expected initialization of constant");
return ERR_PARSE_ERROR;
}
@@ -5252,6 +5299,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
decl.initializer = n;
+ if (n->type == Node::TYPE_CONSTANT) {
+ ConstantNode *const_node = static_cast<ConstantNode *>(n);
+ if (const_node && const_node->values.size() == 1) {
+ var.value = const_node->values[0];
+ }
+ }
+
if (var.type == TYPE_STRUCT ? (var.struct_name != n->get_datatype_name()) : (var.type != n->get_datatype())) {
_set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? String(var.struct_name) : get_datatype_name(var.type)) + "'");
return ERR_PARSE_ERROR;
@@ -5420,18 +5474,29 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i];
if (flow) {
if (flow->flow_op == FLOW_OP_CASE) {
- ConstantNode *n2 = static_cast<ConstantNode *>(flow->expressions[0]);
- if (!n2) {
- return ERR_PARSE_ERROR;
- }
- if (n2->values.empty()) {
- return ERR_PARSE_ERROR;
- }
- if (constants.has(n2->values[0].sint)) {
- _set_error("Duplicated case label: '" + itos(n2->values[0].sint) + "'");
- return ERR_PARSE_ERROR;
+ if (flow->expressions[0]->type == Node::TYPE_CONSTANT) {
+ ConstantNode *cn = static_cast<ConstantNode *>(flow->expressions[0]);
+ if (!cn || cn->values.empty()) {
+ return ERR_PARSE_ERROR;
+ }
+ if (constants.has(cn->values[0].sint)) {
+ _set_error("Duplicated case label: '" + itos(cn->values[0].sint) + "'");
+ return ERR_PARSE_ERROR;
+ }
+ constants.insert(cn->values[0].sint);
+ } else if (flow->expressions[0]->type == Node::TYPE_VARIABLE) {
+ VariableNode *vn = static_cast<VariableNode *>(flow->expressions[0]);
+ if (!vn) {
+ return ERR_PARSE_ERROR;
+ }
+ ConstantNode::Value v;
+ _find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, nullptr, nullptr, nullptr, &v);
+ if (constants.has(v.sint)) {
+ _set_error("Duplicated case label: '" + itos(v.sint) + "'");
+ return ERR_PARSE_ERROR;
+ }
+ constants.insert(v.sint);
}
- constants.insert(n2->values[0].sint);
} else if (flow->flow_op == FLOW_OP_DEFAULT) {
continue;
} else {
@@ -5467,12 +5532,38 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
}
+ Node *n = nullptr;
+
if (tk.type != TK_INT_CONSTANT) {
- _set_error("Expected integer constant");
- return ERR_PARSE_ERROR;
- }
+ bool correct_constant_expression = false;
+ DataType data_type;
- int constant = (int)tk.constant * sign;
+ if (tk.type == TK_IDENTIFIER) {
+ bool is_const;
+ _find_identifier(p_block, false, p_function_info, tk.text, &data_type, nullptr, &is_const);
+ if (is_const) {
+ if (data_type == TYPE_INT) {
+ correct_constant_expression = true;
+ }
+ }
+ }
+ if (!correct_constant_expression) {
+ _set_error("Expected integer constant");
+ return ERR_PARSE_ERROR;
+ }
+
+ VariableNode *vn = alloc_node<VariableNode>();
+ vn->name = tk.text;
+ n = vn;
+ } else {
+ ConstantNode::Value v;
+ v.sint = (int)tk.constant * sign;
+
+ ConstantNode *cn = alloc_node<ConstantNode>();
+ cn->values.push_back(v);
+ cn->datatype = TYPE_INT;
+ n = cn;
+ }
tk = _get_token();
@@ -5484,12 +5575,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ControlFlowNode *cf = alloc_node<ControlFlowNode>();
cf->flow_op = FLOW_OP_CASE;
- ConstantNode *n = alloc_node<ConstantNode>();
- ConstantNode::Value v;
- v.sint = constant;
- n->values.push_back(v);
- n->datatype = TYPE_INT;
-
BlockNode *case_block = alloc_node<BlockNode>();
case_block->block_type = BlockNode::BLOCK_TYPE_CASE;
case_block->parent_block = p_block;