From 482d9313a2626950356c8ad8e12d7cbbb4c081c3 Mon Sep 17 00:00:00 2001 From: Skyth <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Mon, 2 Feb 2026 14:39:46 +0300 Subject: [PATCH] Fix accidental write-combined memory reads in canvas renderer. --- servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp | 4 +++- servers/rendering/renderer_rd/renderer_canvas_render_rd.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index abc20b44d5..25a588ed8a 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -3231,7 +3231,8 @@ RendererCanvasRenderRD::InstanceData *RendererCanvasRenderRD::new_instance_data( // instance_count must be > 0 to indicate the batch has been used when calling _new_batch, so we set a flag. p_current_batch.instance_count = PUSH_DATA_INSTANCE_COUNT; } else { - instance_data = &state.instance_data[state.instance_data_index]; + // Return the intermediary instance data to prevent the caller from accidentally reading write-combined memory pages, which has huge performance implications. + instance_data = &state.intermediary_instance_data; } memcpy(instance_data, &template_instance, sizeof(InstanceData)); @@ -3287,6 +3288,7 @@ void RendererCanvasRenderRD::_add_to_batch(bool &r_batch_broken, Batch *&r_curre r_current_batch->command_type == Item::Command::TYPE_NINEPATCH || r_current_batch->command_type == Item::Command::TYPE_PRIMITIVE); r_current_batch->instance_count++; + memcpy(&state.instance_data[state.instance_data_index], &state.intermediary_instance_data, sizeof(InstanceData)); state.instance_data_index++; if (state.instance_data_index >= state.max_instances_per_buffer) { RD::get_singleton()->buffer_flush(r_current_batch->instance_buffer); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 9a47856c4d..12b2b395e6 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -615,6 +615,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { InstanceData *prev_instance_data = nullptr; uint32_t prev_instance_data_index = 0; + InstanceData intermediary_instance_data; + uint32_t max_instances_per_buffer = 16384; uint32_t max_instance_buffer_size = 16384 * sizeof(InstanceData);