From adb7774a615b714d098985c9574fe02a3b462c7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Mon, 15 Dec 2025 23:25:16 +0100 Subject: [PATCH] RenderingDevice: Add null checks when retrieving uniform sets This may mitigate a crash seen in the wild in Rift Riff on Android, most likely trading it for a single-frame rendering bug (which is better than crashing on user devices). It doesn't solve the underlying issue which seems to be a race condition where a uniform set RID gets has been freed while still being reported as owned by the RID_Owner. --- servers/rendering/rendering_device.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 9e9192d6eeb..cbcd18410ee 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -4996,12 +4996,13 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint if (draw_list.state.sets[i].pipeline_expected_format != draw_list.state.sets[i].uniform_set_format) { if (draw_list.state.sets[i].uniform_set_format == 0) { - ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline."); + ERR_FAIL_MSG(vformat("Uniforms were never supplied for set (%d) at the time of drawing, which are required by the pipeline.", i)); } else if (uniform_set_owner.owns(draw_list.state.sets[i].uniform_set)) { UniformSet *us = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set); - ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(draw_list.state.pipeline_shader)); + const String us_info = us ? vformat("(%d):\n%s\n", i, _shader_uniform_debug(us->shader_id, us->shader_set)) : vformat("(%d, which was just freed) ", i); + ERR_FAIL_MSG(vformat("Uniforms supplied for set %sare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", us_info, _shader_uniform_debug(draw_list.state.pipeline_shader))); } else { - ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(draw_list.state.pipeline_shader)); + ERR_FAIL_MSG(vformat("Uniforms supplied for set (%d, which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(draw_list.state.pipeline_shader))); } } } @@ -5053,6 +5054,7 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint } UniformSet *uniform_set = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set); + ERR_FAIL_NULL(uniform_set); _uniform_set_update_shared(uniform_set); _uniform_set_update_clears(uniform_set); @@ -5161,9 +5163,10 @@ void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indi ERR_FAIL_MSG(vformat("Uniforms were never supplied for set (%d) at the time of drawing, which are required by the pipeline.", i)); } else if (uniform_set_owner.owns(draw_list.state.sets[i].uniform_set)) { UniformSet *us = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set); - ERR_FAIL_MSG(vformat("Uniforms supplied for set (%d):\n%s\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(us->shader_id, us->shader_set), _shader_uniform_debug(draw_list.state.pipeline_shader))); + const String us_info = us ? vformat("(%d):\n%s\n", i, _shader_uniform_debug(us->shader_id, us->shader_set)) : vformat("(%d, which was just freed) ", i); + ERR_FAIL_MSG(vformat("Uniforms supplied for set %sare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", us_info, _shader_uniform_debug(draw_list.state.pipeline_shader))); } else { - ERR_FAIL_MSG(vformat("Uniforms supplied for set (%s, which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(draw_list.state.pipeline_shader))); + ERR_FAIL_MSG(vformat("Uniforms supplied for set (%d, which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(draw_list.state.pipeline_shader))); } } } @@ -5191,6 +5194,7 @@ void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indi draw_graph.add_draw_list_bind_uniform_set(draw_list.state.pipeline_shader_driver_id, draw_list.state.sets[i].uniform_set_driver_id, i); UniformSet *uniform_set = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set); + ERR_FAIL_NULL(uniform_set); _uniform_set_update_shared(uniform_set); _uniform_set_update_clears(uniform_set);