You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-15 13:51:40 +00:00
Backport bc0e8e7 "Fix using post-init shader array constructors" to 3.4
This commit is contained in:
@@ -779,12 +779,13 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
|||||||
if (anode->call_expression != nullptr) {
|
if (anode->call_expression != nullptr) {
|
||||||
code += ".";
|
code += ".";
|
||||||
code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false);
|
code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false);
|
||||||
}
|
} else if (anode->index_expression != nullptr) {
|
||||||
|
|
||||||
if (anode->index_expression != nullptr) {
|
|
||||||
code += "[";
|
code += "[";
|
||||||
code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
||||||
code += "]";
|
code += "]";
|
||||||
|
} else if (anode->assign_expression != NULL) {
|
||||||
|
code += "=";
|
||||||
|
code += _dump_node_code(anode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (anode->name == time_name) {
|
if (anode->name == time_name) {
|
||||||
@@ -952,8 +953,10 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
|||||||
code += "[";
|
code += "[";
|
||||||
code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
||||||
code += "]";
|
code += "]";
|
||||||
|
} else if (mnode->assign_expression != nullptr) {
|
||||||
|
code += "=";
|
||||||
|
code += _dump_node_code(mnode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -884,6 +884,7 @@ void ShaderLanguage::clear() {
|
|||||||
char_idx = 0;
|
char_idx = 0;
|
||||||
error_set = false;
|
error_set = false;
|
||||||
error_str = "";
|
error_str = "";
|
||||||
|
last_const = false;
|
||||||
while (nodes) {
|
while (nodes) {
|
||||||
Node *n = nodes;
|
Node *n = nodes;
|
||||||
nodes = nodes->next;
|
nodes = nodes->next;
|
||||||
@@ -2835,6 +2836,137 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, DataType p_type, const StringName &p_struct_name, int p_array_size) {
|
||||||
|
DataType type = TYPE_VOID;
|
||||||
|
String struct_name = "";
|
||||||
|
int array_size = 0;
|
||||||
|
bool auto_size = false;
|
||||||
|
Token tk = _get_token();
|
||||||
|
|
||||||
|
if (tk.type == TK_CURLY_BRACKET_OPEN) {
|
||||||
|
auto_size = true;
|
||||||
|
} else {
|
||||||
|
if (shader->structs.has(tk.text)) {
|
||||||
|
type = TYPE_STRUCT;
|
||||||
|
struct_name = tk.text;
|
||||||
|
} else {
|
||||||
|
if (!is_token_variable_datatype(tk.type)) {
|
||||||
|
_set_error("Invalid data type for array");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
type = get_token_datatype(tk.type);
|
||||||
|
}
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type == TK_BRACKET_OPEN) {
|
||||||
|
TkPos pos = _get_tkpos();
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type == TK_BRACKET_CLOSE) {
|
||||||
|
array_size = p_array_size;
|
||||||
|
tk = _get_token();
|
||||||
|
} else {
|
||||||
|
_set_tkpos(pos);
|
||||||
|
|
||||||
|
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
|
||||||
|
if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
|
||||||
|
_set_error("Expected single integer constant > 0");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantNode *cnode = (ConstantNode *)n;
|
||||||
|
if (cnode->values.size() == 1) {
|
||||||
|
array_size = cnode->values[0].sint;
|
||||||
|
if (array_size <= 0) {
|
||||||
|
_set_error("Expected single integer constant > 0");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_set_error("Expected single integer constant > 0");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type != TK_BRACKET_CLOSE) {
|
||||||
|
_set_error("Expected ']'");
|
||||||
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
tk = _get_token();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_set_error("Expected '['");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != p_type || struct_name != p_struct_name || array_size != p_array_size) {
|
||||||
|
String error_str = "Cannot convert from '";
|
||||||
|
if (type == TYPE_STRUCT) {
|
||||||
|
error_str += struct_name;
|
||||||
|
} else {
|
||||||
|
error_str += get_datatype_name(type);
|
||||||
|
}
|
||||||
|
error_str += "[";
|
||||||
|
error_str += itos(array_size);
|
||||||
|
error_str += "]'";
|
||||||
|
error_str += " to '";
|
||||||
|
if (type == TYPE_STRUCT) {
|
||||||
|
error_str += p_struct_name;
|
||||||
|
} else {
|
||||||
|
error_str += get_datatype_name(p_type);
|
||||||
|
}
|
||||||
|
error_str += "[";
|
||||||
|
error_str += itos(p_array_size);
|
||||||
|
error_str += "]'";
|
||||||
|
_set_error(error_str);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayConstructNode *an = alloc_node<ArrayConstructNode>();
|
||||||
|
an->datatype = p_type;
|
||||||
|
an->struct_name = p_struct_name;
|
||||||
|
|
||||||
|
if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization
|
||||||
|
while (true) {
|
||||||
|
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
|
||||||
|
if (!n) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_type != n->get_datatype() || p_struct_name != n->get_datatype_name()) {
|
||||||
|
_set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type == TK_COMMA) {
|
||||||
|
an->initializer.push_back(n);
|
||||||
|
} else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) {
|
||||||
|
an->initializer.push_back(n);
|
||||||
|
break;
|
||||||
|
} else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) {
|
||||||
|
an->initializer.push_back(n);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (auto_size) {
|
||||||
|
_set_error("Expected '}' or ','");
|
||||||
|
} else {
|
||||||
|
_set_error("Expected ')' or ','");
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (an->initializer.size() != p_array_size) {
|
||||||
|
_set_error("Array size mismatch");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_set_error("Expected array initialization!");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return an;
|
||||||
|
}
|
||||||
|
|
||||||
ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) {
|
ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) {
|
||||||
Vector<Expression> expression;
|
Vector<Expression> expression;
|
||||||
|
|
||||||
@@ -2976,6 +3108,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||||||
Node *nexpr;
|
Node *nexpr;
|
||||||
|
|
||||||
if (pstruct->members[i]->array_size != 0) {
|
if (pstruct->members[i]->array_size != 0) {
|
||||||
|
nexpr = _parse_array_constructor(p_block, p_builtin_types, pstruct->members[i]->get_datatype(), pstruct->members[i]->struct_name, pstruct->members[i]->array_size);
|
||||||
|
if (!nexpr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
DataType type = pstruct->members[i]->get_datatype();
|
DataType type = pstruct->members[i]->get_datatype();
|
||||||
String struct_name = pstruct->members[i]->struct_name;
|
String struct_name = pstruct->members[i]->struct_name;
|
||||||
@@ -3111,8 +3247,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||||||
_set_error("Expected array initialization!");
|
_set_error("Expected array initialization!");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nexpr = an;
|
|
||||||
} else {
|
} else {
|
||||||
nexpr = _parse_and_reduce_expression(p_block, p_builtin_types);
|
nexpr = _parse_and_reduce_expression(p_block, p_builtin_types);
|
||||||
if (!nexpr) {
|
if (!nexpr) {
|
||||||
@@ -3255,6 +3389,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||||||
} else {
|
} else {
|
||||||
//an identifier
|
//an identifier
|
||||||
|
|
||||||
|
last_const = false;
|
||||||
_set_tkpos(pos);
|
_set_tkpos(pos);
|
||||||
|
|
||||||
DataType data_type;
|
DataType data_type;
|
||||||
@@ -3283,6 +3418,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||||||
_set_error("Unknown identifier in expression: " + String(identifier));
|
_set_error("Unknown identifier in expression: " + String(identifier));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
last_const = is_const;
|
||||||
|
|
||||||
if (ident_type == IDENTIFIER_FUNCTION) {
|
if (ident_type == IDENTIFIER_FUNCTION) {
|
||||||
_set_error("Can't use function as identifier: " + String(identifier));
|
_set_error("Can't use function as identifier: " + String(identifier));
|
||||||
@@ -3292,16 +3428,30 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||||||
|
|
||||||
Node *index_expression = nullptr;
|
Node *index_expression = nullptr;
|
||||||
Node *call_expression = nullptr;
|
Node *call_expression = nullptr;
|
||||||
|
Node *assign_expression = nullptr;
|
||||||
|
|
||||||
if (array_size > 0) {
|
if (array_size > 0) {
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
|
|
||||||
if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD) {
|
if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD && tk.type != TK_OP_ASSIGN) {
|
||||||
_set_error("Expected '[' or '.'");
|
_set_error("Expected '[','.' or '='");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tk.type == TK_PERIOD) {
|
if (tk.type == TK_OP_ASSIGN) {
|
||||||
|
if (is_const) {
|
||||||
|
_set_error("Constants cannot be modified.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (shader->varyings.has(identifier) && current_function != String("vertex")) {
|
||||||
|
_set_error("Varyings can only be assigned in vertex function.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
assign_expression = _parse_array_constructor(p_block, p_builtin_types, data_type, struct_name, array_size);
|
||||||
|
if (!assign_expression) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} else if (tk.type == TK_PERIOD) {
|
||||||
completion_class = TAG_ARRAY;
|
completion_class = TAG_ARRAY;
|
||||||
p_block->block_tag = SubClassTag::TAG_ARRAY;
|
p_block->block_tag = SubClassTag::TAG_ARRAY;
|
||||||
call_expression = _parse_and_reduce_expression(p_block, p_builtin_types);
|
call_expression = _parse_and_reduce_expression(p_block, p_builtin_types);
|
||||||
@@ -3348,6 +3498,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||||||
arrname->struct_name = struct_name;
|
arrname->struct_name = struct_name;
|
||||||
arrname->index_expression = index_expression;
|
arrname->index_expression = index_expression;
|
||||||
arrname->call_expression = call_expression;
|
arrname->call_expression = call_expression;
|
||||||
|
arrname->assign_expression = assign_expression;
|
||||||
arrname->is_const = is_const;
|
arrname->is_const = is_const;
|
||||||
expr = arrname;
|
expr = arrname;
|
||||||
|
|
||||||
@@ -3575,7 +3726,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||||||
mn->owner = expr;
|
mn->owner = expr;
|
||||||
if (array_size > 0) {
|
if (array_size > 0) {
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
if (tk.type == TK_PERIOD) {
|
if (tk.type == TK_OP_ASSIGN) {
|
||||||
|
if (last_const) {
|
||||||
|
last_const = false;
|
||||||
|
_set_error("Constants cannot be modified.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
Node *assign_expression = _parse_array_constructor(p_block, p_builtin_types, member_type, member_struct_name, array_size);
|
||||||
|
if (!assign_expression) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
mn->assign_expression = assign_expression;
|
||||||
|
} else if (tk.type == TK_PERIOD) {
|
||||||
_set_error("Nested array length() is not yet implemented");
|
_set_error("Nested array length() is not yet implemented");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else if (tk.type == TK_BRACKET_OPEN) {
|
} else if (tk.type == TK_BRACKET_OPEN) {
|
||||||
@@ -3609,7 +3771,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||||||
mn->index_expression = index_expression;
|
mn->index_expression = index_expression;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_set_error("Expected '[' or '.'");
|
_set_error("Expected '[','.' or '='");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -386,6 +386,7 @@ public:
|
|||||||
StringName name;
|
StringName name;
|
||||||
Node *index_expression;
|
Node *index_expression;
|
||||||
Node *call_expression;
|
Node *call_expression;
|
||||||
|
Node *assign_expression;
|
||||||
bool is_const;
|
bool is_const;
|
||||||
|
|
||||||
virtual DataType get_datatype() const { return datatype_cache; }
|
virtual DataType get_datatype() const { return datatype_cache; }
|
||||||
@@ -396,6 +397,7 @@ public:
|
|||||||
datatype_cache(TYPE_VOID),
|
datatype_cache(TYPE_VOID),
|
||||||
index_expression(nullptr),
|
index_expression(nullptr),
|
||||||
call_expression(nullptr),
|
call_expression(nullptr),
|
||||||
|
assign_expression(nullptr),
|
||||||
is_const(false) {}
|
is_const(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -508,6 +510,8 @@ public:
|
|||||||
StringName name;
|
StringName name;
|
||||||
Node *owner;
|
Node *owner;
|
||||||
Node *index_expression;
|
Node *index_expression;
|
||||||
|
Node *assign_expression;
|
||||||
|
bool has_swizzling_duplicates;
|
||||||
|
|
||||||
virtual DataType get_datatype() const { return datatype; }
|
virtual DataType get_datatype() const { return datatype; }
|
||||||
virtual String get_datatype_name() const { return String(struct_name); }
|
virtual String get_datatype_name() const { return String(struct_name); }
|
||||||
@@ -518,7 +522,9 @@ public:
|
|||||||
datatype(TYPE_VOID),
|
datatype(TYPE_VOID),
|
||||||
array_size(0),
|
array_size(0),
|
||||||
owner(nullptr),
|
owner(nullptr),
|
||||||
index_expression(nullptr) {}
|
index_expression(nullptr),
|
||||||
|
assign_expression(nullptr),
|
||||||
|
has_swizzling_duplicates(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StructNode : public Node {
|
struct StructNode : public Node {
|
||||||
@@ -726,6 +732,7 @@ private:
|
|||||||
int tk_line;
|
int tk_line;
|
||||||
|
|
||||||
StringName current_function;
|
StringName current_function;
|
||||||
|
bool last_const = false;
|
||||||
|
|
||||||
struct TkPos {
|
struct TkPos {
|
||||||
int char_idx;
|
int char_idx;
|
||||||
@@ -810,6 +817,7 @@ private:
|
|||||||
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = nullptr);
|
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = nullptr);
|
||||||
|
|
||||||
Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
|
Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
|
||||||
|
Node *_parse_array_constructor(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, DataType p_type, const StringName &p_struct_name, int p_array_size);
|
||||||
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);
|
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);
|
||||||
|
|
||||||
Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
|
Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
|
||||||
|
|||||||
Reference in New Issue
Block a user