Skip to content

Commit 3dacc5f

Browse files
committed
Merge pull request #95737 from Chaosus/shader_fix_varyings
Fix shader crash when using varyings with non-`flat` integer type
2 parents 66dd289 + a7bb85d commit 3dacc5f

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
@@ -5063,25 +5063,23 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St
50635063
case ShaderNode::Varying::STAGE_UNKNOWN: // first assign
50645064
if (current_function == varying_function_names.vertex) {
50655065
if (p_varying.type < TYPE_INT) {
5066-
*r_message = vformat(RTR("Varying with '%s' data type may only be assigned in the 'fragment' function."), get_datatype_name(p_varying.type));
5066+
*r_message = vformat(RTR("Varying with '%s' data type may only be assigned in the '%s' function."), get_datatype_name(p_varying.type), "fragment");
50675067
return false;
50685068
}
50695069
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX;
50705070
} else if (current_function == varying_function_names.fragment) {
50715071
p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT;
50725072
}
50735073
break;
5074-
case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT:
50755074
case ShaderNode::Varying::STAGE_VERTEX:
50765075
if (current_function == varying_function_names.fragment) {
5077-
*r_message = RTR("Varyings which assigned in 'vertex' function may not be reassigned in 'fragment' or 'light'.");
5076+
*r_message = vformat(RTR("Varyings which assigned in '%s' function may not be reassigned in '%s' or '%s'."), "vertex", "fragment", "light");
50785077
return false;
50795078
}
50805079
break;
5081-
case ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT:
50825080
case ShaderNode::Varying::STAGE_FRAGMENT:
50835081
if (current_function == varying_function_names.vertex) {
5084-
*r_message = RTR("Varyings which assigned in 'fragment' function may not be reassigned in 'vertex' or 'light'.");
5082+
*r_message = vformat(RTR("Varyings which assigned in '%s' function may not be reassigned in '%s' or '%s'."), "fragment", "vertex", "light");
50855083
return false;
50865084
}
50875085
break;
@@ -6039,15 +6037,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
60396037
error = true;
60406038
}
60416039
break;
6042-
case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT:
6043-
[[fallthrough]];
60446040
case ShaderNode::Varying::STAGE_VERTEX:
60456041
if (is_out_arg && current_function != varying_function_names.vertex) { // inout/out
60466042
error = true;
60476043
}
60486044
break;
6049-
case ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT:
6050-
[[fallthrough]];
60516045
case ShaderNode::Varying::STAGE_FRAGMENT:
60526046
if (!is_out_arg) {
60536047
if (current_function != varying_function_names.fragment && current_function != varying_function_names.light) {
@@ -6247,37 +6241,15 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
62476241
return nullptr;
62486242
}
62496243
} else {
6250-
switch (var.stage) {
6251-
case ShaderNode::Varying::STAGE_UNKNOWN: {
6252-
if (var.type < TYPE_INT) {
6253-
if (current_function == varying_function_names.vertex) {
6254-
_set_error(vformat(RTR("Varying with '%s' data type may only be used in the 'fragment' function."), get_datatype_name(var.type)));
6255-
} else {
6256-
_set_error(vformat(RTR("Varying '%s' must be assigned in the 'fragment' function first."), identifier));
6257-
}
6258-
return nullptr;
6259-
}
6260-
} break;
6261-
case ShaderNode::Varying::STAGE_VERTEX:
6262-
if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
6263-
var.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT;
6264-
}
6265-
break;
6266-
case ShaderNode::Varying::STAGE_FRAGMENT:
6267-
if (current_function == varying_function_names.light) {
6268-
var.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
6269-
}
6270-
break;
6271-
default:
6272-
break;
6244+
if (var.stage == ShaderNode::Varying::STAGE_UNKNOWN && var.type < TYPE_INT) {
6245+
if (current_function == varying_function_names.vertex) {
6246+
_set_error(vformat(RTR("Varying with '%s' data type may only be used in the '%s' function."), get_datatype_name(var.type), "fragment"));
6247+
} else {
6248+
_set_error(vformat(RTR("Varying '%s' must be assigned in the '%s' function first."), identifier, "fragment"));
6249+
}
6250+
return nullptr;
62736251
}
62746252
}
6275-
6276-
if ((var.stage != ShaderNode::Varying::STAGE_FRAGMENT && var.stage != ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT) && var.type < TYPE_FLOAT && var.interpolation != INTERPOLATION_FLAT) {
6277-
_set_tkpos(var.tkpos);
6278-
_set_error(RTR("Varying with integer data type must be declared with `flat` interpolation qualifier."));
6279-
return nullptr;
6280-
}
62816253
}
62826254

62836255
if (ident_type == IDENTIFIER_FUNCTION) {
@@ -10698,6 +10670,14 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
1069810670
tk = _get_token();
1069910671
}
1070010672

10673+
for (const KeyValue<StringName, ShaderNode::Varying> &kv : shader->varyings) {
10674+
if (kv.value.stage != ShaderNode::Varying::STAGE_FRAGMENT && (kv.value.type > TYPE_BVEC4 && kv.value.type < TYPE_FLOAT) && kv.value.interpolation != INTERPOLATION_FLAT) {
10675+
_set_tkpos(kv.value.tkpos);
10676+
_set_error(vformat(RTR("Varying with integer data type must be declared with `%s` interpolation qualifier."), "flat"));
10677+
return ERR_PARSE_ERROR;
10678+
}
10679+
}
10680+
1070110681
#ifdef DEBUG_ENABLED
1070210682
if (check_device_limit_warnings && uniform_buffer_exceeded_line != -1) {
1070310683
_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)