From 793d065f8b3ace90a25dad6441c56388691724f0 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Thu, 19 Dec 2024 09:45:51 -0800 Subject: [PATCH] Avoid allocating instance buffer for PointLight2D shadows when there are no instances. Also avoid the render loop if there are no occluders. We still have to open the render pass to do a clear though. --- .../renderer_rd/renderer_canvas_render_rd.cpp | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 8940c1d110..a0d2897dd3 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1056,7 +1056,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, // Then, upload all the occluder transforms to a shared buffer. // We only do this for the first light so we can avoid uploading the same // Transforms over and over again. - if (p_shadow_index == 0) { + if (p_shadow_index == 0 && occluder_count > 0) { static thread_local LocalVector transforms; transforms.clear(); transforms.resize(occluder_count * 8); @@ -1076,41 +1076,43 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, Rect2i rect(0, p_shadow_index * 2, state.shadow_texture_size, 2); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::DRAW_CLEAR_ALL, cc, 1.0f, 0, rect); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.render_pipelines[SHADOW_RENDER_MODE_POSITIONAL_SHADOW]); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.shadow_ocluder_uniform_set, 0); + if (state.shadow_occluder_buffer.is_valid()) { + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.render_pipelines[SHADOW_RENDER_MODE_POSITIONAL_SHADOW]); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.shadow_ocluder_uniform_set, 0); - for (int i = 0; i < 4; i++) { - Rect2i sub_rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2); - RD::get_singleton()->draw_list_set_viewport(draw_list, sub_rect); + for (int i = 0; i < 4; i++) { + Rect2i sub_rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2); + RD::get_singleton()->draw_list_set_viewport(draw_list, sub_rect); - static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) }; - static const Vector4 rotations[4] = { Vector4(0, -1, 1, 0), Vector4(-1, 0, 0, -1), Vector4(0, 1, -1, 0), Vector4(1, 0, 0, 1) }; + static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) }; + static const Vector4 rotations[4] = { Vector4(0, -1, 1, 0), Vector4(-1, 0, 0, -1), Vector4(0, 1, -1, 0), Vector4(1, 0, 0, 1) }; - PositionalShadowRenderPushConstant push_constant; - _update_transform_2d_to_mat2x4(p_light_xform, push_constant.modelview); - push_constant.direction[0] = directions[i].x; - push_constant.direction[1] = directions[i].y; - push_constant.rotation[0] = rotations[i].x; - push_constant.rotation[1] = rotations[i].y; - push_constant.rotation[2] = rotations[i].z; - push_constant.rotation[3] = rotations[i].w; - push_constant.z_far = p_far; - push_constant.z_near = p_near; + PositionalShadowRenderPushConstant push_constant; + _update_transform_2d_to_mat2x4(p_light_xform, push_constant.modelview); + push_constant.direction[0] = directions[i].x; + push_constant.direction[1] = directions[i].y; + push_constant.rotation[0] = rotations[i].x; + push_constant.rotation[1] = rotations[i].y; + push_constant.rotation[2] = rotations[i].z; + push_constant.rotation[3] = rotations[i].w; + push_constant.z_far = p_far; + push_constant.z_near = p_near; - for (uint32_t j = 0; j < occluders.size(); j++) { - OccluderPolygon *co = occluders[j]; + for (uint32_t j = 0; j < occluders.size(); j++) { + OccluderPolygon *co = occluders[j]; - push_constant.pad = occluder_indices[j]; - push_constant.cull_mode = uint32_t(co->cull_mode); + push_constant.pad = occluder_indices[j]; + push_constant.cull_mode = uint32_t(co->cull_mode); - // The slowest part about this whole function is that we have to draw the occluders one by one, 4 times. - // We can optimize this so that all occluders draw at once if we store vertices and indices in a giant - // SSBO and just save an index into that SSBO for each occluder. - RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->vertex_array); - RD::get_singleton()->draw_list_bind_index_array(draw_list, co->index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(PositionalShadowRenderPushConstant)); + // The slowest part about this whole function is that we have to draw the occluders one by one, 4 times. + // We can optimize this so that all occluders draw at once if we store vertices and indices in a giant + // SSBO and just save an index into that SSBO for each occluder. + RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->vertex_array); + RD::get_singleton()->draw_list_bind_index_array(draw_list, co->index_array); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(PositionalShadowRenderPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_draw(draw_list, true); + } } } RD::get_singleton()->draw_list_end();