1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-09 12:50:35 +00:00

Refactor size expression parsing for arrays in the shaders

This commit is contained in:
Yuri Roubinsky
2022-01-15 12:10:26 +03:00
parent c1e78f749e
commit 08208406ca
2 changed files with 115 additions and 341 deletions

View File

@@ -4309,9 +4309,35 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
ERR_FAIL_V(false); //bug? function not found ERR_FAIL_V(false); //bug? function not found
} }
ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size) { Error ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_forbid_unknown_size, Node **r_size_expression, int *r_array_size, bool *r_unknown_size) {
bool error = false;
if (r_array_size != nullptr && *r_array_size > 0) {
error = true;
}
if (r_unknown_size != nullptr && *r_unknown_size) {
error = true;
}
if (error) {
_set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
}
TkPos pos = _get_tkpos();
Token tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
if (p_forbid_unknown_size) {
_set_error("Unknown array size is forbidden in that context!");
return ERR_PARSE_ERROR;
}
if (r_unknown_size != nullptr) {
*r_unknown_size = true;
}
} else {
int array_size = 0; int array_size = 0;
if (!tk.is_integer_constant() || ((int)tk.constant) <= 0) {
_set_tkpos(pos);
Node *n = _parse_and_reduce_expression(p_block, p_function_info); Node *n = _parse_and_reduce_expression(p_block, p_function_info);
if (n) { if (n) {
if (n->type == Node::TYPE_VARIABLE) { if (n->type == Node::TYPE_VARIABLE) {
@@ -4339,29 +4365,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, cons
} }
} else if (n->type == Node::TYPE_OPERATOR) { } else if (n->type == Node::TYPE_OPERATOR) {
_set_error("Array size expressions are not yet implemented."); _set_error("Array size expressions are not yet implemented.");
return nullptr;
}
}
r_array_size = array_size;
return n;
}
Error ShaderLanguage::_parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info) {
if (r_array_size > 0) {
_set_error("Array size is already defined!");
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
TkPos pos = _get_tkpos(); if (r_size_expression != nullptr) {
Token tk = _get_token(); *r_size_expression = n;
}
int array_size = 0;
if (!tk.is_integer_constant() || ((int)tk.constant) <= 0) {
_set_tkpos(pos);
Node *n = _parse_array_size(nullptr, p_function_info, array_size);
if (!n) {
return ERR_PARSE_ERROR;
} }
} else if (((int)tk.constant) > 0) { } else if (((int)tk.constant) > 0) {
array_size = (uint32_t)tk.constant; array_size = (uint32_t)tk.constant;
@@ -4378,45 +4386,10 @@ Error ShaderLanguage::_parse_global_array_size(int &r_array_size, const Function
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
r_array_size = array_size; if (r_array_size != nullptr) {
return OK; *r_array_size = array_size;
}
Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, Node *&r_size_expression, int &r_array_size, bool &r_is_unknown_size) {
TkPos pos = _get_tkpos();
Token tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
r_is_unknown_size = true;
} else {
int size = 0;
if (!tk.is_integer_constant() || ((int)tk.constant) <= 0) {
_set_tkpos(pos);
int array_size = 0;
Node *n = _parse_array_size(p_block, p_function_info, array_size);
if (!n) {
return ERR_PARSE_ERROR;
} }
size = array_size;
r_size_expression = n;
} else if (((int)tk.constant) > 0) {
size = (uint32_t)tk.constant;
} }
if (size <= 0) {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
return ERR_PARSE_ERROR;
}
r_array_size = size;
}
return OK; return OK;
} }
@@ -4443,40 +4416,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
} }
tk = _get_token(); tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
TkPos pos = _get_tkpos(); Error error = _parse_array_size(p_block, p_function_info, false, nullptr, &array_size, &undefined_size);
tk = _get_token(); if (error != OK) {
if (tk.type == TK_BRACKET_CLOSE) {
undefined_size = true;
tk = _get_token();
} else {
_set_tkpos(pos);
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
_set_error("Expected single integer constant > 0");
return nullptr; 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(); tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
return nullptr;
} else {
tk = _get_token();
}
}
} else { } else {
_set_error("Expected '['"); _set_error("Expected '['");
return nullptr; return nullptr;
@@ -4572,40 +4516,15 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
} }
tk = _get_token(); tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
TkPos pos = _get_tkpos(); bool is_unknown_size = false;
tk = _get_token(); Error error = _parse_array_size(p_block, p_function_info, false, nullptr, &array_size, &is_unknown_size);
if (tk.type == TK_BRACKET_CLOSE) { if (error != OK) {
return nullptr;
}
if (is_unknown_size) {
array_size = p_array_size; array_size = p_array_size;
}
tk = _get_token(); tk = _get_token();
} else {
_set_tkpos(pos);
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
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 { } else {
_set_error("Expected '['"); _set_error("Expected '['");
return nullptr; return nullptr;
@@ -6532,7 +6451,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
} }
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
Error error = _parse_local_array_size(p_block, p_function_info, size_expr, array_size, unknown_size); Error error = _parse_array_size(p_block, p_function_info, false, &size_expr, &array_size, &unknown_size);
if (error != OK) { if (error != OK) {
return error; return error;
} }
@@ -6587,17 +6506,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
bool is_array_decl = var.array_size > 0 || unknown_size; bool is_array_decl = var.array_size > 0 || unknown_size;
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
if (is_array_decl) {
_set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
}
if (RenderingServer::get_singleton()->is_low_end() && is_const) { if (RenderingServer::get_singleton()->is_low_end() && is_const) {
_set_error("Local const arrays are supported only on high-end platform!"); _set_error("Local const arrays are supported only on high-end platform!");
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
Error error = _parse_local_array_size(p_block, p_function_info, size_expr, var.array_size, unknown_size); Error error = _parse_array_size(p_block, p_function_info, false, &size_expr, &var.array_size, &unknown_size);
if (error != OK) { if (error != OK) {
return error; return error;
} }
@@ -6702,40 +6616,15 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token(); tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
TkPos pos2 = _get_tkpos(); bool is_unknown_size = false;
tk = _get_token(); Error error = _parse_array_size(p_block, p_function_info, false, nullptr, &array_size2, &is_unknown_size);
if (tk.type == TK_BRACKET_CLOSE) { if (error != OK) {
return error;
}
if (is_unknown_size) {
array_size2 = var.array_size; array_size2 = var.array_size;
}
tk = _get_token(); tk = _get_token();
} else {
_set_tkpos(pos2);
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
}
ConstantNode *cnode = (ConstantNode *)n;
if (cnode->values.size() == 1) {
array_size2 = cnode->values[0].sint;
if (array_size2 <= 0) {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
}
} else {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
return ERR_PARSE_ERROR;
} else {
tk = _get_token();
}
}
} else { } else {
_set_error("Expected '['"); _set_error("Expected '['");
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
@@ -7764,7 +7653,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} }
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
Error error = _parse_global_array_size(array_size, constants); Error error = _parse_array_size(nullptr, constants, true, nullptr, &array_size, nullptr);
if (error != OK) { if (error != OK) {
return error; return error;
} }
@@ -7793,7 +7682,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token(); tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
Error error = _parse_global_array_size(member->array_size, constants); Error error = _parse_array_size(nullptr, constants, true, nullptr, &member->array_size, nullptr);
if (error != OK) { if (error != OK) {
return error; return error;
} }
@@ -7925,7 +7814,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} }
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
Error error = _parse_global_array_size(array_size, constants); Error error = _parse_array_size(nullptr, constants, true, nullptr, &array_size, nullptr);
if (error != OK) { if (error != OK) {
return error; return error;
} }
@@ -7973,7 +7862,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token(); tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
Error error = _parse_global_array_size(uniform2.array_size, constants); Error error = _parse_array_size(nullptr, constants, true, nullptr, &uniform2.array_size, nullptr);
if (error != OK) { if (error != OK) {
return error; return error;
} }
@@ -8308,29 +8197,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} }
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
if (array_size > 0) { Error error = _parse_array_size(nullptr, constants, true, nullptr, &varying.array_size, nullptr);
_set_error("Array size is already defined!"); if (error != OK) {
return ERR_PARSE_ERROR; return error;
} }
tk = _get_token(); tk = _get_token();
if (tk.is_integer_constant() && tk.constant > 0) {
varying.array_size = (int)tk.constant;
tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
_set_error("Expected ';'");
return ERR_PARSE_ERROR;
}
} else {
_set_error("Expected ']'");
return ERR_PARSE_ERROR;
}
} else {
_set_error("Expected integer constant > 0");
return ERR_PARSE_ERROR;
}
} }
shader->varyings[name] = varying; shader->varyings[name] = varying;
@@ -8395,36 +8266,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token(); tk = _get_token();
bool unknown_size = false; bool unknown_size = false;
bool fixed_array_size = false;
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
if (is_constant && RenderingServer::get_singleton()->is_low_end()) { if (is_constant && RenderingServer::get_singleton()->is_low_end()) {
_set_error("Global const arrays are only supported on high-end platform!"); _set_error("Global const arrays are only supported on high-end platform!");
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
bool error = false; Error error = _parse_array_size(nullptr, constants, !is_constant, nullptr, &array_size, &unknown_size);
tk = _get_token(); if (error != OK) {
return error;
if (tk.is_integer_constant()) {
array_size = (int)tk.constant;
if (array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
return ERR_PARSE_ERROR;
} }
} else { fixed_array_size = true;
error = true;
}
} else if (tk.type == TK_BRACKET_CLOSE) {
unknown_size = true;
} else {
error = true;
}
if (error) {
_set_error("Expected integer constant > 0 or ']'");
return ERR_PARSE_ERROR;
}
prev_pos = _get_tkpos(); prev_pos = _get_tkpos();
} }
@@ -8454,7 +8307,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} }
//variable //variable
bool first = true;
while (true) { while (true) {
ShaderNode::Constant constant; ShaderNode::Constant constant;
constant.name = name; constant.name = name;
@@ -8462,34 +8314,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.type_str = struct_name; constant.type_str = struct_name;
constant.precision = precision; constant.precision = precision;
constant.initializer = nullptr; constant.initializer = nullptr;
constant.array_size = (first ? array_size : 0); constant.array_size = array_size;
first = false;
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
if (RenderingServer::get_singleton()->is_low_end()) { if (RenderingServer::get_singleton()->is_low_end()) {
_set_error("Global const arrays are only supported on high-end platform!"); _set_error("Global const arrays are only supported on high-end platform!");
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
if (constant.array_size > 0 || unknown_size) { Error error = _parse_array_size(nullptr, constants, false, nullptr, &constant.array_size, &unknown_size);
_set_error("Array size is already defined!"); if (error != OK) {
return ERR_PARSE_ERROR; return error;
} }
tk = _get_token(); tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
unknown_size = true;
tk = _get_token();
} else if (tk.is_integer_constant() && ((int)tk.constant) > 0) {
constant.array_size = (int)tk.constant;
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
return ERR_PARSE_ERROR;
}
tk = _get_token();
} else {
_set_error("Expected integer constant > 0 or ']'");
return ERR_PARSE_ERROR;
}
} }
if (tk.type == TK_OP_ASSIGN) { if (tk.type == TK_OP_ASSIGN) {
@@ -8540,43 +8376,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} }
int array_size2 = 0; int array_size2 = 0;
tk = _get_token(); tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
prev_pos = _get_tkpos(); bool is_unknown_size = false;
tk = _get_token(); Error error = _parse_array_size(nullptr, constants, false, nullptr, &array_size2, &is_unknown_size);
if (tk.type == TK_BRACKET_CLOSE) { if (error != OK) {
return error;
}
if (is_unknown_size) {
array_size2 = constant.array_size; array_size2 = constant.array_size;
}
tk = _get_token(); tk = _get_token();
} else {
_set_tkpos(prev_pos);
Node *n = _parse_and_reduce_expression(nullptr, constants);
if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
}
ConstantNode *cnode = (ConstantNode *)n;
if (cnode->values.size() == 1) {
array_size2 = cnode->values[0].sint;
if (array_size2 <= 0) {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
}
} else {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']");
return ERR_PARSE_ERROR;
} else {
tk = _get_token();
}
}
} else { } else {
_set_error("Expected '["); _set_error("Expected '[");
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
@@ -8674,6 +8485,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} }
} }
array_size = constant.array_size;
ConstantNode *expr = memnew(ConstantNode); ConstantNode *expr = memnew(ConstantNode);
expr->datatype = constant.type; expr->datatype = constant.type;
@@ -8746,6 +8559,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token(); tk = _get_token();
if (!fixed_array_size) {
array_size = 0;
}
unknown_size = false;
} else if (tk.type == TK_SEMICOLON) { } else if (tk.type == TK_SEMICOLON) {
break; break;
} else { } else {
@@ -8902,27 +8720,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token(); tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
bool error = false; Error error = _parse_array_size(nullptr, constants, true, nullptr, &arg_array_size, nullptr);
tk = _get_token(); if (error != OK) {
return error;
if (tk.is_integer_constant()) {
arg_array_size = (int)tk.constant;
if (arg_array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
return ERR_PARSE_ERROR;
}
} else {
error = true;
}
} else {
error = true;
}
if (error) {
_set_error("Expected integer constant > 0");
return ERR_PARSE_ERROR;
} }
tk = _get_token(); tk = _get_token();
} }
@@ -8960,32 +8760,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token(); tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) { if (tk.type == TK_BRACKET_OPEN) {
if (arg_array_size > 0) { Error error = _parse_array_size(nullptr, constants, true, nullptr, &arg_array_size, nullptr);
_set_error("Array size is already defined!"); if (error != OK) {
return ERR_PARSE_ERROR; return error;
}
bool error = false;
tk = _get_token();
if (tk.is_integer_constant()) {
arg_array_size = (int)tk.constant;
if (arg_array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
return ERR_PARSE_ERROR;
}
} else {
error = true;
}
} else {
error = true;
}
if (error) {
_set_error("Expected integer constant > 0");
return ERR_PARSE_ERROR;
} }
tk = _get_token(); tk = _get_token();
} }

View File

@@ -1045,11 +1045,8 @@ private:
bool _validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message); bool _validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message);
bool _check_node_constness(const Node *p_node) const; bool _check_node_constness(const Node *p_node) const;
Node *_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size);
Error _parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info);
Error _parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, Node *&r_size_expression, int &r_array_size, bool &r_is_unknown_size);
Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info); Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
Error _parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_forbid_unknown_size, Node **r_size_expression, int *r_array_size, bool *r_unknown_size);
Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info); Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info);
Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size); Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, 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);