Merge pull request #39820 from Chaosus/shader_fix_const_crash_3.2

[3.2] Fix shader crash if pass const argument to 'out/inout' parameter
This commit is contained in:
Rémi Verschelde 2020-06-25 11:36:37 +02:00 committed by GitHub
commit 5079bea660
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 1 deletions

View File

@ -883,6 +883,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<String
if (r_data_type) { if (r_data_type) {
*r_data_type = p_builtin_types[p_identifier].type; *r_data_type = p_builtin_types[p_identifier].type;
} }
if (r_is_const) {
*r_is_const = p_builtin_types[p_identifier].constant;
}
if (r_type) { if (r_type) {
*r_type = IDENTIFIER_BUILTIN_VAR; *r_type = IDENTIFIER_BUILTIN_VAR;
} }
@ -2962,7 +2965,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} }
bnode = bnode->parent_block; bnode = bnode->parent_block;
} }
int function_index = -1;
//test if function was parsed first //test if function was parsed first
for (int i = 0; i < shader->functions.size(); i++) { for (int i = 0; i < shader->functions.size(); i++) {
if (shader->functions[i].name == name) { if (shader->functions[i].name == name) {
@ -2973,6 +2976,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
break; break;
} }
} }
function_index = i;
break; break;
} }
} }
@ -2994,6 +2998,54 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} }
completion_class = TAG_GLOBAL; // reset sub-class completion_class = TAG_GLOBAL; // reset sub-class
if (function_index >= 0) {
FunctionNode *call_function = shader->functions[function_index].function;
if (call_function) {
for (int i = 0; i < call_function->arguments.size(); i++) {
int argidx = i + 1;
if (argidx < func->arguments.size()) {
if (call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT) {
bool error = false;
Node *n = func->arguments[argidx];
if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) {
error = true;
} else if (n->type == Node::TYPE_ARRAY) {
ArrayNode *an = static_cast<ArrayNode *>(n);
if (an->call_expression != nullptr || an->is_const) {
error = true;
}
} else if (n->type == Node::TYPE_VARIABLE) {
VariableNode *vn = static_cast<VariableNode *>(n);
if (vn->is_const) {
error = true;
} else {
StringName varname = vn->name;
if (shader->constants.has(varname)) {
error = true;
} else if (shader->uniforms.has(varname)) {
error = true;
} else {
if (p_builtin_types.has(varname)) {
BuiltInInfo info = p_builtin_types[varname];
if (info.constant) {
error = true;
}
}
}
}
}
if (error) {
_set_error(vformat("Constant value cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier)));
return nullptr;
}
}
} else {
break;
}
}
}
}
expr = func; expr = func;
} else { } else {
@ -4729,6 +4781,18 @@ String ShaderLanguage::_get_shader_type_list(const Set<String> &p_shader_types)
return valid_types; return valid_types;
} }
String ShaderLanguage::_get_qualifier_str(ArgumentQualifier p_qualifier) const {
switch (p_qualifier) {
case ArgumentQualifier::ARGUMENT_QUALIFIER_IN:
return "in";
case ArgumentQualifier::ARGUMENT_QUALIFIER_OUT:
return "out";
case ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT:
return "inout";
}
return "";
}
Error ShaderLanguage::_validate_datatype(DataType p_type) { Error ShaderLanguage::_validate_datatype(DataType p_type) {
if (VisualServer::get_singleton()->is_low_end()) { if (VisualServer::get_singleton()->is_low_end()) {
bool invalid_type = false; bool invalid_type = false;

View File

@ -761,6 +761,7 @@ private:
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);
Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false);
String _get_shader_type_list(const Set<String> &p_shader_types) const; String _get_shader_type_list(const Set<String> &p_shader_types) const;
String _get_qualifier_str(ArgumentQualifier p_qualifier) const;
Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types); Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);