Skip to content

Commit a7bb85d

Browse files
committed
Fix shader crash when using varyings with non-flat integer type
1 parent aa8d9b8 commit a7bb85d

File tree

3 files changed

+21
-43
lines changed

3 files changed

+21
-43
lines changed

servers/rendering/shader_compiler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
674674
const StringName &varying_name = varying_names[k];
675675
const SL::ShaderNode::Varying &varying = pnode->varyings[varying_name];
676676

677-
if (varying.stage == SL::ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT || varying.stage == SL::ShaderNode::Varying::STAGE_FRAGMENT) {
677+
if (varying.stage == SL::ShaderNode::Varying::STAGE_FRAGMENT) {
678678
var_frag_to_light.push_back(Pair<StringName, SL::ShaderNode::Varying>(varying_name, varying));
679679
fragment_varyings.insert(varying_name);
680680
continue;

servers/rendering/shader_language.cpp

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5062,25 +5062,23 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St
50625062
case ShaderNode::Varying::STAGE_UNKNOWN: // first assign
50635063
if (current_function == varying_function_names.vertex) {
50645064
if (p_varying.type < TYPE_INT) {
5065-
*r_message = vformat(RTR("Varying with '%s' data type may only be assigned in the 'fragment' function."), get_datatype_name(p_varying.type));
5065+
*r_message = vformat(RTR("Varying with '%s' data type may only be assigned in the '%s' function."), get_datatype_name(p_varying.type), "fragment");
50665066
return false;
50675067
}
50685068
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX;
50695069
} else if (current_function == varying_function_names.fragment) {
50705070
p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT;
50715071
}
50725072
break;
5073-
case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT:
50745073
case ShaderNode::Varying::STAGE_VERTEX:
50755074
if (current_function == varying_function_names.fragment) {
5076-
*r_message = RTR("Varyings which assigned in 'vertex' function may not be reassigned in 'fragment' or 'light'.");
5075+
*r_message = vformat(RTR("Varyings which assigned in '%s' function may not be reassigned in '%s' or '%s'."), "vertex", "fragment", "light");
50775076
return false;
50785077
}
50795078
break;
5080-
case ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT:
50815079
case ShaderNode::Varying::STAGE_FRAGMENT:
50825080
if (current_function == varying_function_names.vertex) {
5083-
*r_message = RTR("Varyings which assigned in 'fragment' function may not be reassigned in 'vertex' or 'light'.");
5081+
*r_message = vformat(RTR("Varyings which assigned in '%s' function may not be reassigned in '%s' or '%s'."), "fragment", "vertex", "light");
50845082
return false;
50855083
}
50865084
break;
@@ -6038,15 +6036,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
60386036
error = true;
60396037
}
60406038
break;
6041-
case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT:
6042-
[[fallthrough]];
60436039
case ShaderNode::Varying::STAGE_VERTEX:
60446040
if (is_out_arg && current_function != varying_function_names.vertex) { // inout/out
60456041
error = true;
60466042
}
60476043
break;
6048-
case ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT:
6049-
[[fallthrough]];
60506044
case ShaderNode::Varying::STAGE_FRAGMENT:
60516045
if (!is_out_arg) {
60526046
if (current_function != varying_function_names.fragment && current_function != varying_function_names.light) {
@@ -6246,37 +6240,15 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
62466240
return nullptr;
62476241
}
62486242
} else {
6249-
switch (var.stage) {
6250-
case ShaderNode::Varying::STAGE_UNKNOWN: {
6251-
if (var.type < TYPE_INT) {
6252-
if (current_function == varying_function_names.vertex) {
6253-
_set_error(vformat(RTR("Varying with '%s' data type may only be used in the 'fragment' function."), get_datatype_name(var.type)));
6254-
} else {
6255-
_set_error(vformat(RTR("Varying '%s' must be assigned in the 'fragment' function first."), identifier));
6256-
}
6257-
return nullptr;
6258-
}
6259-
} break;
6260-
case ShaderNode::Varying::STAGE_VERTEX:
6261-
if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
6262-
var.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT;
6263-
}
6264-
break;
6265-
case ShaderNode::Varying::STAGE_FRAGMENT:
6266-
if (current_function == varying_function_names.light) {
6267-
var.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
6268-
}
6269-
break;
6270-
default:
6271-
break;
6243+
if (var.stage == ShaderNode::Varying::STAGE_UNKNOWN && var.type < TYPE_INT) {
6244+
if (current_function == varying_function_names.vertex) {
6245+
_set_error(vformat(RTR("Varying with '%s' data type may only be used in the '%s' function."), get_datatype_name(var.type), "fragment"));
6246+
} else {
6247+
_set_error(vformat(RTR("Varying '%s' must be assigned in the '%s' function first."), identifier, "fragment"));
6248+
}
6249+
return nullptr;
62726250
}
62736251
}
6274-
6275-
if ((var.stage != ShaderNode::Varying::STAGE_FRAGMENT && var.stage != ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT) && var.type < TYPE_FLOAT && var.interpolation != INTERPOLATION_FLAT) {
6276-
_set_tkpos(var.tkpos);
6277-
_set_error(RTR("Varying with integer data type must be declared with `flat` interpolation qualifier."));
6278-
return nullptr;
6279-
}
62806252
}
62816253

62826254
if (ident_type == IDENTIFIER_FUNCTION) {
@@ -10697,6 +10669,14 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
1069710669
tk = _get_token();
1069810670
}
1069910671

10672+
for (const KeyValue<StringName, ShaderNode::Varying> &kv : shader->varyings) {
10673+
if (kv.value.stage != ShaderNode::Varying::STAGE_FRAGMENT && (kv.value.type > TYPE_BVEC4 && kv.value.type < TYPE_FLOAT) && kv.value.interpolation != INTERPOLATION_FLAT) {
10674+
_set_tkpos(kv.value.tkpos);
10675+
_set_error(vformat(RTR("Varying with integer data type must be declared with `%s` interpolation qualifier."), "flat"));
10676+
return ERR_PARSE_ERROR;
10677+
}
10678+
}
10679+
1070010680
#ifdef DEBUG_ENABLED
1070110681
if (check_device_limit_warnings && uniform_buffer_exceeded_line != -1) {
1070210682
_add_warning(ShaderWarning::DEVICE_LIMIT_EXCEEDED, uniform_buffer_exceeded_line, RTR("uniform buffer"), { uniform_buffer_size, max_uniform_buffer_size });

servers/rendering/shader_language.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -620,10 +620,8 @@ class ShaderLanguage {
620620
struct Varying {
621621
enum Stage {
622622
STAGE_UNKNOWN,
623-
STAGE_VERTEX, // transition stage to STAGE_VERTEX_TO_FRAGMENT_LIGHT, emits warning if it's not used
624-
STAGE_FRAGMENT, // transition stage to STAGE_FRAGMENT_TO_LIGHT, emits warning if it's not used
625-
STAGE_VERTEX_TO_FRAGMENT_LIGHT,
626-
STAGE_FRAGMENT_TO_LIGHT,
623+
STAGE_VERTEX,
624+
STAGE_FRAGMENT,
627625
};
628626

629627
Stage stage = STAGE_UNKNOWN;

0 commit comments

Comments
 (0)