Backport latest varying fixes to 3.x (2)
This commit is contained in:
parent
8ecb5d2047
commit
0a99613e53
2 changed files with 58 additions and 24 deletions
|
@ -879,6 +879,8 @@ void ShaderLanguage::clear() {
|
|||
completion_class = SubClassTag::TAG_GLOBAL;
|
||||
completion_struct = StringName();
|
||||
|
||||
unknown_varying_usages.clear();
|
||||
|
||||
error_line = 0;
|
||||
tk_line = 1;
|
||||
char_idx = 0;
|
||||
|
@ -2447,6 +2449,20 @@ bool ShaderLanguage::is_token_operator(TokenType p_type) {
|
|||
p_type == TK_COLON);
|
||||
}
|
||||
|
||||
bool ShaderLanguage::is_token_operator_assign(TokenType p_type) {
|
||||
return (p_type == TK_OP_ASSIGN ||
|
||||
p_type == TK_OP_ASSIGN_ADD ||
|
||||
p_type == TK_OP_ASSIGN_SUB ||
|
||||
p_type == TK_OP_ASSIGN_MUL ||
|
||||
p_type == TK_OP_ASSIGN_DIV ||
|
||||
p_type == TK_OP_ASSIGN_MOD ||
|
||||
p_type == TK_OP_ASSIGN_SHIFT_LEFT ||
|
||||
p_type == TK_OP_ASSIGN_SHIFT_RIGHT ||
|
||||
p_type == TK_OP_ASSIGN_BIT_AND ||
|
||||
p_type == TK_OP_ASSIGN_BIT_OR ||
|
||||
p_type == TK_OP_ASSIGN_BIT_XOR);
|
||||
}
|
||||
|
||||
bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value) {
|
||||
if (p_constant->datatype == p_to_type) {
|
||||
if (p_value) {
|
||||
|
@ -2793,8 +2809,7 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St
|
|||
p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT;
|
||||
}
|
||||
break;
|
||||
case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT:
|
||||
case ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT:
|
||||
case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT:
|
||||
case ShaderNode::Varying::STAGE_VERTEX:
|
||||
if (current_function == String("fragment")) {
|
||||
*r_message = RTR("Varyings which assigned in 'vertex' function may not be reassigned in 'fragment' or 'light'.");
|
||||
|
@ -2817,13 +2832,14 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St
|
|||
bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, String *r_message) {
|
||||
switch (p_varying.stage) {
|
||||
case ShaderNode::Varying::STAGE_UNKNOWN:
|
||||
*r_message = RTR("Varying must be assigned before using!");
|
||||
VaryingUsage usage;
|
||||
usage.var = &p_varying;
|
||||
usage.line = tk_line;
|
||||
unknown_varying_usages.push_back(usage);
|
||||
return false;
|
||||
case ShaderNode::Varying::STAGE_VERTEX:
|
||||
if (current_function == String("fragment")) {
|
||||
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT;
|
||||
} else if (current_function == String("light")) {
|
||||
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT;
|
||||
if (current_function == String("fragment") || current_function == String("light")) {
|
||||
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT;
|
||||
}
|
||||
break;
|
||||
case ShaderNode::Varying::STAGE_FRAGMENT:
|
||||
|
@ -2831,24 +2847,25 @@ bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, Str
|
|||
p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
|
||||
}
|
||||
break;
|
||||
case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT:
|
||||
if (current_function == String("light")) {
|
||||
*r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT:
|
||||
if (current_function == String("fragment")) {
|
||||
*r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderLanguage::_check_varying_usages(int *r_error_line, String *r_error_message) const {
|
||||
for (const List<ShaderLanguage::VaryingUsage>::Element *E = unknown_varying_usages.front(); E; E = E->next()) {
|
||||
ShaderNode::Varying::Stage stage = E->get().var->stage;
|
||||
if (stage != ShaderNode::Varying::STAGE_UNKNOWN && stage != ShaderNode::Varying::STAGE_VERTEX && stage != ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT) {
|
||||
*r_error_line = E->get().line;
|
||||
*r_error_message = RTR("Fragment-stage varying could not been accessed in custom function!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message) {
|
||||
if (p_node->type == Node::TYPE_OPERATOR) {
|
||||
OperatorNode *op = static_cast<OperatorNode *>(p_node);
|
||||
|
@ -3502,7 +3519,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||
Token next_token = _get_token();
|
||||
_set_tkpos(prev_pos);
|
||||
String error;
|
||||
if (next_token.type == TK_OP_ASSIGN) {
|
||||
|
||||
if (is_token_operator_assign(next_token.type)) {
|
||||
if (!_validate_varying_assign(shader->varyings[identifier], &error)) {
|
||||
_set_error(error);
|
||||
return nullptr;
|
||||
|
@ -6347,6 +6365,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
|||
tk = _get_token();
|
||||
}
|
||||
|
||||
int error_line;
|
||||
String error_message;
|
||||
if (!_check_varying_usages(&error_line, &error_message)) {
|
||||
_set_tkpos({ 0, error_line });
|
||||
_set_error(error_message);
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -587,10 +587,9 @@ public:
|
|||
struct Varying {
|
||||
enum Stage {
|
||||
STAGE_UNKNOWN,
|
||||
STAGE_VERTEX, // transition stage to STAGE_VERTEX_TO_FRAGMENT or STAGE_VERTEX_TO_LIGHT, emits error if they are not used
|
||||
STAGE_FRAGMENT, // transition stage to STAGE_FRAGMENT_TO_LIGHT, emits error if it's not used
|
||||
STAGE_VERTEX_TO_FRAGMENT,
|
||||
STAGE_VERTEX_TO_LIGHT,
|
||||
STAGE_VERTEX, // transition stage to STAGE_VERTEX_TO_FRAGMENT_LIGHT, emits warning if it's not used
|
||||
STAGE_FRAGMENT, // transition stage to STAGE_FRAGMENT_TO_LIGHT, emits warning if it's not used
|
||||
STAGE_VERTEX_TO_FRAGMENT_LIGHT,
|
||||
STAGE_FRAGMENT_TO_LIGHT,
|
||||
};
|
||||
|
||||
|
@ -702,6 +701,7 @@ public:
|
|||
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);
|
||||
static bool is_token_operator_assign(TokenType p_type);
|
||||
|
||||
static bool convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value = nullptr);
|
||||
static DataType get_scalar_type(DataType p_type);
|
||||
|
@ -752,6 +752,14 @@ private:
|
|||
StringName current_function;
|
||||
bool last_const = false;
|
||||
|
||||
struct VaryingUsage {
|
||||
ShaderNode::Varying *var;
|
||||
int line;
|
||||
};
|
||||
List<VaryingUsage> unknown_varying_usages;
|
||||
|
||||
bool _check_varying_usages(int *r_error_line, String *r_error_message) const;
|
||||
|
||||
TkPos _get_tkpos() {
|
||||
TkPos tkp;
|
||||
tkp.char_idx = char_idx;
|
||||
|
|
Loading…
Reference in a new issue