diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 2262580d9ad..53df7e9c3d9 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -212,11 +212,8 @@ void RasterizerGLES3::begin_frame() { storage->update_dirty_resources(); - storage->info.render_object_count = 0; - storage->info.render_material_switch_count = 0; - storage->info.render_surface_switch_count = 0; - storage->info.render_shader_rebind_count = 0; - storage->info.render_vertices_count = 0; + storage->info.render_final = storage->info.render; + storage->info.render.reset(); scene->iteration(); } diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 8d8c5e556b0..08f15a9b846 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1451,20 +1451,20 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { glDrawElements(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0); - storage->info.render_vertices_count += s->index_array_len; + storage->info.render.vertices_count += s->index_array_len; } else #endif if (s->index_array_len > 0) { glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); - storage->info.render_vertices_count += s->index_array_len; + storage->info.render.vertices_count += s->index_array_len; } else { glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); - storage->info.render_vertices_count += s->array_len; + storage->info.render.vertices_count += s->array_len; } } break; @@ -1480,20 +1480,20 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount); - storage->info.render_vertices_count += s->index_array_len * amount; + storage->info.render.vertices_count += s->index_array_len * amount; } else #endif if (s->index_array_len > 0) { glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); - storage->info.render_vertices_count += s->index_array_len * amount; + storage->info.render.vertices_count += s->index_array_len * amount; } else { glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); - storage->info.render_vertices_count += s->array_len * amount; + storage->info.render.vertices_count += s->array_len * amount; } } break; @@ -1519,7 +1519,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { int vertices = c.vertices.size(); uint32_t buf_ofs = 0; - storage->info.render_vertices_count += vertices; + storage->info.render.vertices_count += vertices; if (c.texture.is_valid() && storage->texture_owner.owns(c.texture)) { @@ -1646,20 +1646,20 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount - split); - storage->info.render_vertices_count += s->index_array_len * (amount - split); + storage->info.render.vertices_count += s->index_array_len * (amount - split); } else #endif if (s->index_array_len > 0) { glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount - split); - storage->info.render_vertices_count += s->index_array_len * (amount - split); + storage->info.render.vertices_count += s->index_array_len * (amount - split); } else { glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount - split); - storage->info.render_vertices_count += s->array_len * (amount - split); + storage->info.render.vertices_count += s->array_len * (amount - split); } } @@ -1684,20 +1684,20 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, split); - storage->info.render_vertices_count += s->index_array_len * split; + storage->info.render.vertices_count += s->index_array_len * split; } else #endif if (s->index_array_len > 0) { glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, split); - storage->info.render_vertices_count += s->index_array_len * split; + storage->info.render.vertices_count += s->index_array_len * split; } else { glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, split); - storage->info.render_vertices_count += s->array_len * split; + storage->info.render.vertices_count += s->array_len * split; } } @@ -1708,20 +1708,20 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->array_wireframe_id) { glDrawElementsInstanced(GL_LINES, s->index_wireframe_len, GL_UNSIGNED_INT, 0, amount); - storage->info.render_vertices_count += s->index_array_len * amount; + storage->info.render.vertices_count += s->index_array_len * amount; } else #endif if (s->index_array_len > 0) { glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); - storage->info.render_vertices_count += s->index_array_len * amount; + storage->info.render.vertices_count += s->index_array_len * amount; } else { glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); - storage->info.render_vertices_count += s->array_len * amount; + storage->info.render.vertices_count += s->array_len * amount; } } @@ -1890,7 +1890,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ bool first = true; bool prev_use_instancing = false; - storage->info.render_object_count += p_element_count; + storage->info.render.draw_call_count += p_element_count; for (int i = 0; i < p_element_count; i++) { @@ -2038,12 +2038,12 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ if (material != prev_material || rebind) { - storage->info.render_material_switch_count++; + storage->info.render.material_switch_count++; rebind = _setup_material(material, p_alpha_pass); if (rebind) { - storage->info.render_shader_rebind_count++; + storage->info.render.shader_rebind_count++; } } @@ -2054,7 +2054,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ if (e->owner != prev_owner || prev_base_type != e->instance->base_type || prev_geometry != e->geometry) { _setup_geometry(e, p_view_transform); - storage->info.render_surface_switch_count++; + storage->info.render.surface_switch_count++; } _set_cull(e->sort_key & RenderList::SORT_KEY_MIRROR_FLAG, p_reverse_cull); @@ -3812,6 +3812,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const //fill up ubo + storage->info.render.object_count += p_cull_count; + Environment *env = environment_owner.getornull(p_environment); ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 1250e557489..54e99eb622e 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2658,6 +2658,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: surface->skeleton_bone_used.resize(surface->skeleton_bone_aabb.size()); surface->aabb = p_aabb; surface->max_bone = p_bone_aabbs.size(); + surface->total_data_size += surface->array_byte_size + surface->index_array_byte_size; for (int i = 0; i < surface->skeleton_bone_used.size(); i++) { if (surface->skeleton_bone_aabb[i].size.x < 0 || surface->skeleton_bone_aabb[i].size.y < 0 || surface->skeleton_bone_aabb[i].size.z < 0) { @@ -2845,6 +2846,8 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: PoolVector::Read vr = p_blend_shapes[i].read(); + surface->total_data_size += array_size; + glGenBuffers(1, &mt.vertex_id); glBindBuffer(GL_ARRAY_BUFFER, mt.vertex_id); glBufferData(GL_ARRAY_BUFFER, array_size, vr.ptr(), GL_STATIC_DRAW); @@ -2876,6 +2879,8 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: mesh->surfaces.push_back(surface); mesh->instance_change_notify(); + + info.vertex_mem += surface->total_data_size; } void RasterizerStorageGLES3::mesh_set_blend_shape_count(RID p_mesh, int p_amount) { @@ -3110,6 +3115,8 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface) { glDeleteVertexArrays(1, &surface->instancing_array_wireframe_id); } + info.vertex_mem -= surface->total_data_size; + mesh->instance_material_change_notify(); memdelete(surface); @@ -6462,6 +6469,92 @@ void RasterizerStorageGLES3::set_debug_generate_wireframes(bool p_generate) { config.generate_wireframes = p_generate; } +void RasterizerStorageGLES3::render_info_begin_capture() { + + info.snap = info.render; +} + +void RasterizerStorageGLES3::render_info_end_capture() { + + info.snap.object_count = info.render.object_count - info.snap.object_count; + info.snap.draw_call_count = info.render.draw_call_count - info.snap.draw_call_count; + info.snap.material_switch_count = info.render.material_switch_count - info.snap.material_switch_count; + info.snap.surface_switch_count = info.render.surface_switch_count - info.snap.surface_switch_count; + info.snap.shader_rebind_count = info.render.shader_rebind_count - info.snap.shader_rebind_count; + info.snap.vertices_count = info.render.vertices_count - info.snap.vertices_count; +} + +int RasterizerStorageGLES3::get_captured_render_info(VS::RenderInfo p_info) { + + switch (p_info) { + case VS::INFO_OBJECTS_IN_FRAME: { + + return info.snap.object_count; + } break; + case VS::INFO_VERTICES_IN_FRAME: { + + return info.snap.vertices_count; + } break; + case VS::INFO_MATERIAL_CHANGES_IN_FRAME: { + return info.snap.material_switch_count; + } break; + case VS::INFO_SHADER_CHANGES_IN_FRAME: { + return info.snap.shader_rebind_count; + } break; + case VS::INFO_SURFACE_CHANGES_IN_FRAME: { + return info.snap.surface_switch_count; + } break; + case VS::INFO_DRAW_CALLS_IN_FRAME: { + return info.snap.draw_call_count; + } break; + default: { + return get_render_info(p_info); + } + } +} + +int RasterizerStorageGLES3::get_render_info(VS::RenderInfo p_info) { + + switch (p_info) { + case VS::INFO_OBJECTS_IN_FRAME: { + + return info.render_final.object_count; + } break; + case VS::INFO_VERTICES_IN_FRAME: { + + return info.render_final.vertices_count; + } break; + case VS::INFO_MATERIAL_CHANGES_IN_FRAME: { + return info.render_final.material_switch_count; + } break; + case VS::INFO_SHADER_CHANGES_IN_FRAME: { + return info.render_final.shader_rebind_count; + } break; + case VS::INFO_SURFACE_CHANGES_IN_FRAME: { + return info.render_final.surface_switch_count; + } break; + case VS::INFO_DRAW_CALLS_IN_FRAME: { + return info.render_final.draw_call_count; + } break; + case VS::INFO_USAGE_VIDEO_MEM_TOTAL: { + + return 0; //no idea + } break; + case VS::INFO_VIDEO_MEM_USED: { + + return info.vertex_mem + info.texture_mem; + } break; + case VS::INFO_TEXTURE_MEM_USED: { + + return info.texture_mem; + } break; + case VS::INFO_VERTEX_MEM_USED: { + + return info.vertex_mem; + } break; + } +} + void RasterizerStorageGLES3::initialize() { RasterizerStorageGLES3::system_fbo = 0; diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index d16fa99c2a7..1357206bfa3 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -126,12 +126,33 @@ public: struct Info { uint64_t texture_mem; + uint64_t vertex_mem; - uint32_t render_object_count; - uint32_t render_material_switch_count; - uint32_t render_surface_switch_count; - uint32_t render_shader_rebind_count; - uint32_t render_vertices_count; + struct Render { + uint32_t object_count; + uint32_t draw_call_count; + uint32_t material_switch_count; + uint32_t surface_switch_count; + uint32_t shader_rebind_count; + uint32_t vertices_count; + + void reset() { + object_count = 0; + draw_call_count = 0; + material_switch_count = 0; + surface_switch_count = 0; + shader_rebind_count = 0; + vertices_count = 0; + } + } render, render_final, snap; + + Info() { + + texture_mem = 0; + vertex_mem = 0; + render.reset(); + render_final.reset(); + } } info; @@ -574,6 +595,8 @@ public: mesh->update_multimeshes(); } + int total_data_size; + Surface() { array_byte_size = 0; @@ -589,6 +612,8 @@ public: index_array_len = 0; active = false; + total_data_size = 0; + index_wireframe_id = 0; array_wireframe_id = 0; instancing_array_wireframe_id = 0; @@ -1286,6 +1311,7 @@ public: float delta; uint64_t prev_tick; uint64_t count; + } frame; void initialize(); @@ -1297,6 +1323,12 @@ public: virtual void set_debug_generate_wireframes(bool p_generate); + virtual void render_info_begin_capture(); + virtual void render_info_end_capture(); + virtual int get_captured_render_info(VS::RenderInfo p_info); + + virtual int get_render_info(VS::RenderInfo p_info); + RasterizerStorageGLES3(); }; diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index e7d7ba05d8c..a8d875a7697 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -1724,6 +1724,33 @@ void SpatialEditorViewport::_notification(int p_what) { bool hdr = GlobalConfig::get_singleton()->get("rendering/quality/hdr"); viewport->set_hdr(hdr); + + bool show_info = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION)); + if (show_info != info->is_visible()) { + if (show_info) + info->show(); + else + info->hide(); + } + + if (show_info) { + + String text; + text += TTR("Objects Drawn") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_OBJECTS_IN_FRAME)) + "\n"; + text += TTR("Material Changes") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_MATERIAL_CHANGES_IN_FRAME)) + "\n"; + text += TTR("Shader Changes") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_SHADER_CHANGES_IN_FRAME)) + "\n"; + text += TTR("Surface Changes") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_SURFACE_CHANGES_IN_FRAME)) + "\n"; + text += TTR("Draw Calls") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_DRAW_CALLS_IN_FRAME)) + "\n"; + text += TTR("Vertices") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_VERTICES_IN_FRAME)); + + if (info_label->get_text() != text || surface->get_size() != prev_size) { + info_label->set_text(text); + Size2 ms = info->get_minimum_size(); + info->set_position(surface->get_size() - ms - Vector2(20, 20) * EDSCALE); + } + } + + prev_size = surface->get_size(); } if (p_what == NOTIFICATION_ENTER_TREE) { @@ -1731,6 +1758,7 @@ void SpatialEditorViewport::_notification(int p_what) { surface->connect("draw", this, "_draw"); surface->connect("gui_input", this, "_sinput"); surface->connect("mouse_entered", this, "_smouseenter"); + info->add_style_override("panel", get_stylebox("panel", "Panel")); preview_camera->set_icon(get_icon("Camera", "EditorIcons")); _init_gizmo_instance(index); } @@ -1996,6 +2024,13 @@ void SpatialEditorViewport::_menu_option(int p_option) { camera->set_cull_mask(((1 << 20) - 1) | (1 << (GIZMO_BASE_LAYER + index)) | (1 << GIZMO_GRID_LAYER)); view_menu->get_popup()->set_item_checked(idx, current); + } break; + case VIEW_INFORMATION: { + + int idx = view_menu->get_popup()->get_item_index(VIEW_INFORMATION); + bool current = view_menu->get_popup()->is_item_checked(idx); + view_menu->get_popup()->set_item_checked(idx, !current); + } break; case VIEW_DISPLAY_NORMAL: { @@ -2312,6 +2347,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed surface = memnew(Control); add_child(surface); surface->set_area_as_parent_rect(); + surface->set_clip_contents(true); camera = memnew(Camera); camera->set_disable_gizmo(true); camera->set_cull_mask(((1 << 20) - 1) | (1 << (GIZMO_BASE_LAYER + p_index)) | (1 << GIZMO_EDIT_LAYER) | (1 << GIZMO_GRID_LAYER)); @@ -2367,6 +2403,13 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed preview = NULL; gizmo_scale = 1.0; + info = memnew(PanelContainer); + info->set_self_modulate(Color(1, 1, 1, 0.4)); + surface->add_child(info); + info_label = memnew(Label); + info->add_child(info_label); + info->hide(); + freelook_active = false; selection_menu = memnew(PopupMenu); diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 4a770311ac0..6b05a8b370c 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -121,6 +121,9 @@ private: bool freelook_active; + PanelContainer *info; + Label *info_label; + struct _RayResult { Spatial *item; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 87cf6eed8c7..eb06c64c405 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -501,6 +501,12 @@ public: virtual void set_debug_generate_wireframes(bool p_generate) = 0; + virtual void render_info_begin_capture() = 0; + virtual void render_info_end_capture() = 0; + virtual int get_captured_render_info(VS::RenderInfo p_info) = 0; + + virtual int get_render_info(VS::RenderInfo p_info) = 0; + static RasterizerStorage *base_singleton; RasterizerStorage(); virtual ~RasterizerStorage() {} diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 93c37938198..8d332b3e6c2 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -145,7 +145,7 @@ void VisualServerRaster::finish() { int VisualServerRaster::get_render_info(RenderInfo p_info) { - return 0; + return VSG::storage->get_render_info(p_info); } /* TESTING */ diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 9ab56894e91..a99b8906019 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -274,9 +274,18 @@ void VisualServerViewport::draw_viewports() { VSG::rasterizer->set_current_render_target(vp->render_target); VSG::scene_render->set_debug_draw_mode(vp->debug_draw); + VSG::storage->render_info_begin_capture(); _draw_viewport(vp); + VSG::storage->render_info_end_capture(); + vp->render_info[VS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_OBJECTS_IN_FRAME); + vp->render_info[VS::VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_VERTICES_IN_FRAME); + vp->render_info[VS::VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_MATERIAL_CHANGES_IN_FRAME); + vp->render_info[VS::VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SHADER_CHANGES_IN_FRAME); + vp->render_info[VS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME); + vp->render_info[VS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_DRAW_CALLS_IN_FRAME); + if (vp->viewport_to_screen_rect != Rect2()) { //copy to screen if set as such VSG::rasterizer->set_current_render_target(RID()); @@ -564,8 +573,10 @@ void VisualServerViewport::viewport_set_usage(RID p_viewport, VS::ViewportUsage int VisualServerViewport::viewport_get_render_info(RID p_viewport, VS::ViewportRenderInfo p_info) { ERR_FAIL_INDEX_V(p_info, VS::VIEWPORT_RENDER_INFO_MAX, -1); + Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND_V(!viewport, -1); + if (!viewport) + return 0; //there should be a lock here.. return viewport->render_info[p_info]; } diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index d4f43ac3968..407a4fd32bd 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -372,7 +372,11 @@ public: FUNC2(viewport_set_hdr, RID, bool) FUNC2(viewport_set_usage, RID, ViewportUsage) - FUNC2R(int, viewport_get_render_info, RID, ViewportRenderInfo) + //this passes directly to avoid stalling, but it's pretty dangerous, so dont call after freeing a viewport + virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) { + visual_server->viewport_get_render_info(p_viewport, p_info); + } + FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw) /* ENVIRONMENT API */ @@ -548,7 +552,10 @@ public: /* RENDER INFO */ - FUNC1R(int, get_render_info, RenderInfo) + //this passes directly to avoid stalling + virtual int get_render_info(RenderInfo p_info) { + visual_server->get_render_info(p_info); + } FUNC3(set_boot_image, const Ref &, const Color &, bool) FUNC1(set_default_clear_color, const Color &)