You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-15 13:51:40 +00:00
Fix shader crash if passing const values to modf function
This commit is contained in:
@@ -2114,7 +2114,7 @@ const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[]
|
|||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) {
|
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) {
|
||||||
|
|
||||||
ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, false);
|
ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, false);
|
||||||
|
|
||||||
@@ -2185,16 +2185,68 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
|
|||||||
|
|
||||||
if (arg_idx < argcount) {
|
if (arg_idx < argcount) {
|
||||||
|
|
||||||
if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE) {
|
if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) {
|
||||||
_set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable");
|
_set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
StringName var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
|
|
||||||
|
|
||||||
|
if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
|
||||||
|
ArrayNode *mn = static_cast<ArrayNode *>(p_func->arguments[arg_idx + 1]);
|
||||||
|
if (mn->is_const) {
|
||||||
|
fail = true;
|
||||||
|
}
|
||||||
|
} else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
|
||||||
|
MemberNode *mn = static_cast<MemberNode *>(p_func->arguments[arg_idx + 1]);
|
||||||
|
if (mn->basetype_const) {
|
||||||
|
fail = true;
|
||||||
|
}
|
||||||
|
} else { // TYPE_VARIABLE
|
||||||
|
VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg_idx + 1]);
|
||||||
|
if (vn->is_const) {
|
||||||
|
fail = true;
|
||||||
|
} else {
|
||||||
|
StringName varname = vn->name;
|
||||||
|
if (shader->uniforms.has(varname)) {
|
||||||
|
fail = true;
|
||||||
|
} else {
|
||||||
|
if (p_builtin_types.has(varname)) {
|
||||||
|
BuiltInInfo info = p_builtin_types[varname];
|
||||||
|
if (info.constant) {
|
||||||
|
fail = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fail) {
|
||||||
|
_set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringName var_name;
|
||||||
|
if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
|
||||||
|
var_name = static_cast<const ArrayNode *>(p_func->arguments[arg_idx + 1])->name;
|
||||||
|
} else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
|
||||||
|
Node *n = static_cast<const MemberNode *>(p_func->arguments[arg_idx + 1])->owner;
|
||||||
|
while (n->type == Node::TYPE_MEMBER) {
|
||||||
|
n = static_cast<const MemberNode *>(n)->owner;
|
||||||
|
}
|
||||||
|
if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) {
|
||||||
|
_set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (n->type == Node::TYPE_VARIABLE) {
|
||||||
|
var_name = static_cast<const VariableNode *>(n)->name;
|
||||||
|
} else { // TYPE_ARRAY
|
||||||
|
var_name = static_cast<const ArrayNode *>(n)->name;
|
||||||
|
}
|
||||||
|
} else { // TYPE_VARIABLE
|
||||||
|
var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
|
||||||
|
}
|
||||||
const BlockNode *b = p_block;
|
const BlockNode *b = p_block;
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
while (b) {
|
while (b) {
|
||||||
if (b->variables.has(var_name)) {
|
if (b->variables.has(var_name) || p_builtin_types.has(var_name)) {
|
||||||
valid = true;
|
valid = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2210,7 +2262,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
_set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable");
|
_set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3197,7 +3249,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||||||
if (!ok)
|
if (!ok)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!_validate_function_call(p_block, func, &func->return_cache, &func->struct_name)) {
|
if (!_validate_function_call(p_block, p_builtin_types, func, &func->return_cache, &func->struct_name)) {
|
||||||
_set_error("No matching constructor found for: '" + String(funcname->name) + "'");
|
_set_error("No matching constructor found for: '" + String(funcname->name) + "'");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -3461,7 +3513,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||||||
if (!ok)
|
if (!ok)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!_validate_function_call(p_block, func, &func->return_cache, &func->struct_name)) {
|
if (!_validate_function_call(p_block, p_builtin_types, func, &func->return_cache, &func->struct_name)) {
|
||||||
_set_error("No matching function found for: '" + String(funcname->name) + "'");
|
_set_error("No matching function found for: '" + String(funcname->name) + "'");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -859,7 +859,7 @@ private:
|
|||||||
Error _validate_datatype(DataType p_type);
|
Error _validate_datatype(DataType p_type);
|
||||||
bool _compare_datatypes_in_nodes(Node *a, Node *b) const;
|
bool _compare_datatypes_in_nodes(Node *a, Node *b) const;
|
||||||
|
|
||||||
bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str);
|
bool _validate_function_call(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str);
|
||||||
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
|
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
|
||||||
bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat);
|
bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat);
|
||||||
bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin);
|
bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin);
|
||||||
|
|||||||
Reference in New Issue
Block a user