Merge pull request #30596 from Chaosus/shader_array_init

Added local shader array initializer
This commit is contained in:
Yuri Roubinsky 2019-07-16 07:54:49 +03:00 committed by GitHub
commit 8202ba2212
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 217 additions and 16 deletions

View file

@ -531,6 +531,22 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
declaration += "[";
declaration += itos(var_dec_node->declarations[i].size);
declaration += "]";
int sz = var_dec_node->declarations[i].initializer.size();
if (sz > 0) {
declaration += "=";
declaration += _typestr(var_dec_node->datatype);
declaration += "[";
declaration += itos(sz);
declaration += "]";
declaration += "(";
for (int j = 0; j < sz; j++) {
declaration += _dump_node_code(var_dec_node->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
if (j != sz - 1) {
declaration += ", ";
}
}
declaration += ")";
}
}
code += declaration.as_string();

View file

@ -622,6 +622,22 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
declaration += "[";
declaration += itos(vdnode->declarations[i].size);
declaration += "]";
int sz = vdnode->declarations[i].initializer.size();
if (sz > 0) {
declaration += "=";
declaration += _typestr(vdnode->datatype);
declaration += "[";
declaration += itos(sz);
declaration += "]";
declaration += "(";
for (int j = 0; j < sz; j++) {
declaration += _dump_node_code(vdnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
if (j != sz - 1) {
declaration += ", ";
}
}
declaration += ")";
}
}
code += declaration;

View file

@ -785,6 +785,17 @@ ShaderLanguage::DataPrecision ShaderLanguage::get_token_precision(TokenType p_ty
return PRECISION_MEDIUMP;
}
String ShaderLanguage::get_precision_name(DataPrecision p_type) {
switch (p_type) {
case PRECISION_LOWP: return "lowp";
case PRECISION_MEDIUMP: return "mediump";
case PRECISION_HIGHP: return "highp";
default:
break;
}
return "";
}
String ShaderLanguage::get_datatype_name(DataType p_type) {
switch (p_type) {
@ -3803,6 +3814,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
bool unknown_size = false;
ArrayDeclarationNode *node = alloc_node<ArrayDeclarationNode>();
node->datatype = type;
@ -3815,22 +3827,181 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
tk = _get_token();
if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
_set_error("Expected integer constant > 0");
return ERR_PARSE_ERROR;
if (tk.type == TK_BRACKET_CLOSE) {
unknown_size = true;
} else {
if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
_set_error("Expected integer constant > 0 or ']'");
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
return ERR_PARSE_ERROR;
}
decl.size = ((uint32_t)tk.constant);
var.array_size = decl.size;
}
tk = _get_token();
bool full_def = false;
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
return ERR_PARSE_ERROR;
tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
tk = _get_token();
if (tk.type != TK_CURLY_BRACKET_OPEN) {
if (unknown_size) {
_set_error("Expected '{'");
return ERR_PARSE_ERROR;
}
full_def = true;
DataPrecision precision2 = PRECISION_DEFAULT;
if (is_token_precision(tk.type)) {
precision2 = get_token_precision(tk.type);
tk = _get_token();
if (!is_token_nonvoid_datatype(tk.type)) {
_set_error("Expected datatype after precision");
return ERR_PARSE_ERROR;
}
}
if (!is_token_variable_datatype(tk.type)) {
_set_error("Invalid data type for array");
return ERR_PARSE_ERROR;
}
DataType type2 = get_token_datatype(tk.type);
int array_size2 = 0;
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
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 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 {
_set_error("Expected '[");
return ERR_PARSE_ERROR;
}
if (precision != precision2 || type != type2 || var.array_size != array_size2) {
String error_str = "Cannot convert from '";
if (precision2 != PRECISION_DEFAULT) {
error_str += get_precision_name(precision2);
error_str += " ";
}
error_str += get_datatype_name(type2);
error_str += "[";
error_str += itos(array_size2);
error_str += "]'";
error_str += " to '";
if (precision != PRECISION_DEFAULT) {
error_str += get_precision_name(precision);
error_str += " ";
}
error_str += get_datatype_name(type);
error_str += "[";
error_str += itos(var.array_size);
error_str += "]'";
_set_error(error_str);
return ERR_PARSE_ERROR;
}
}
bool curly = tk.type == TK_CURLY_BRACKET_OPEN;
if (unknown_size) {
if (!curly) {
_set_error("Expected '{'");
return ERR_PARSE_ERROR;
}
} else {
if (full_def) {
if (curly) {
_set_error("Expected '('");
return ERR_PARSE_ERROR;
}
}
}
if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
while (true) {
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!n) {
return ERR_PARSE_ERROR;
}
if (n->type != Node::TYPE_CONSTANT) {
_set_error("Expected constant expression in the array declaration");
return ERR_PARSE_ERROR;
}
if (var.type != n->get_datatype()) {
_set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(var.type) + "'");
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type == TK_COMMA) {
decl.initializer.push_back(n);
continue;
} else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) {
decl.initializer.push_back(n);
break;
} else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) {
decl.initializer.push_back(n);
break;
} else {
if (curly)
_set_error("Expected '}' or ','");
else
_set_error("Expected ')' or ','");
return ERR_PARSE_ERROR;
}
}
if (unknown_size) {
decl.size = decl.initializer.size();
var.array_size = decl.initializer.size();
} else if (decl.initializer.size() != var.array_size) {
_set_error("Array size mismatch");
return ERR_PARSE_ERROR;
}
tk = _get_token();
}
} else {
if (unknown_size) {
_set_error("Expected array initialization");
return ERR_PARSE_ERROR;
}
}
decl.size = ((uint32_t)tk.constant);
var.array_size = decl.size;
tk = _get_token();
node->declarations.push_back(decl);
} else if (tk.type == TK_OP_ASSIGN) {
@ -3878,11 +4049,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
} else if (tk.type == TK_SEMICOLON) {
break;
} else {
if (var.array_size != 0U) {
_set_error("Expected ',' or ';' or '[' after variable");
} else {
_set_error("Expected ',' or ';' after variable");
}
_set_error("Expected ',' or ';' after variable");
return ERR_PARSE_ERROR;
}
}

View file

@ -376,6 +376,7 @@ public:
struct Declaration {
StringName name;
uint32_t size;
Vector<Node *> initializer;
};
Vector<Declaration> declarations;
@ -588,6 +589,7 @@ public:
static DataInterpolation get_token_interpolation(TokenType p_type);
static bool is_token_precision(TokenType p_type);
static DataPrecision get_token_precision(TokenType p_type);
static String get_precision_name(DataPrecision p_type);
static String get_datatype_name(DataType p_type);
static bool is_token_nonvoid_datatype(TokenType p_type);
static bool is_token_operator(TokenType p_type);