diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h index 3b9084a04ce..78d13d91ffc 100644 --- a/drivers/gles3/storage/mesh_storage.h +++ b/drivers/gles3/storage/mesh_storage.h @@ -320,6 +320,7 @@ public: virtual void mesh_clear(RID p_mesh) override; virtual void mesh_surface_remove(RID p_mesh, int p_surface) override; + virtual void mesh_debug_usage(List *r_info) override {} _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); diff --git a/servers/debugger/servers_debugger.cpp b/servers/debugger/servers_debugger.cpp index d4c728d8bdf..6b4807e2367 100644 --- a/servers/debugger/servers_debugger.cpp +++ b/servers/debugger/servers_debugger.cpp @@ -454,6 +454,22 @@ void ServersDebugger::_send_resource_usage() { usage.infos.push_back(info); } + List mesh_info; + RS::get_singleton()->mesh_debug_usage(&mesh_info); + + for (const RS::MeshInfo &E : mesh_info) { + ServersDebugger::ResourceInfo info; + info.path = E.path; + // we use 64bit integers to avoid overflow, if for whatever reason, the sum is bigger than 4GB + uint64_t vram = E.vertex_buffer_size + E.attribute_buffer_size + E.skin_buffer_size + E.index_buffer_size + E.blend_shape_buffer_size + E.lod_index_buffers_size; + // but can info.vram even hold that, and why is it an int instead of an uint? + info.vram = vram; + info.id = E.mesh; + info.type = "Mesh"; + info.format = itos(E.vertex_count) + " Vertices"; + usage.infos.push_back(info); + } + EngineDebugger::get_singleton()->send_message("servers:memory_usage", usage.serialize()); } diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h index 4d43927eee5..e259554665c 100644 --- a/servers/rendering/dummy/storage/mesh_storage.h +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -133,6 +133,7 @@ public: virtual void mesh_surface_remove(RID p_mesh, int p_surface) override; virtual void mesh_clear(RID p_mesh) override; + virtual void mesh_debug_usage(List *r_info) override {} /* MESH INSTANCE */ diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index abc525512a2..9ac0168437f 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -395,6 +395,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) if (new_surface.attribute_data.size()) { s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(new_surface.attribute_data.size(), new_surface.attribute_data); + s->attribute_buffer_size = new_surface.attribute_data.size(); } if (new_surface.skin_data.size()) { s->skin_buffer = RD::get_singleton()->vertex_buffer_create(new_surface.skin_data.size(), new_surface.skin_data, as_storage_flag); @@ -411,6 +412,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) bool is_index_16 = new_surface.vertex_count <= 65536 && new_surface.vertex_count > 0; s->index_buffer = RD::get_singleton()->index_buffer_create(new_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, new_surface.index_data, false); + s->index_buffer_size = new_surface.index_data.size(); s->index_count = new_surface.index_count; s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count); if (new_surface.lods.size()) { @@ -420,6 +422,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) for (int i = 0; i < new_surface.lods.size(); i++) { uint32_t indices = new_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4); s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, new_surface.lods[i].index_data); + s->lods[i].index_buffer_size = new_surface.lods[i].index_data.size(); s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices); s->lods[i].edge_length = new_surface.lods[i].edge_length; s->lods[i].index_count = indices; @@ -437,6 +440,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) if (mesh->blend_shape_count > 0) { s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(new_surface.blend_shape_data.size(), new_surface.blend_shape_data); + s->blend_shape_buffer_size = new_surface.blend_shape_data.size(); } if (use_as_storage) { @@ -917,6 +921,38 @@ void MeshStorage::mesh_surface_remove(RID p_mesh, int p_surface) { } } +void MeshStorage::mesh_debug_usage(List *r_info) { + List meshes; + mesh_owner.get_owned_list(&meshes); + + for (List::Element *E = meshes.front(); E; E = E->next()) { + Mesh *mesh = mesh_owner.get_or_null(E->get()); + if (!mesh) { + continue; + } + RS::MeshInfo mesh_info; + mesh_info.mesh = E->get(); + mesh_info.path = mesh->path; + + for (uint32_t surface_index = 0; surface_index < mesh->surface_count; surface_index++) { + MeshStorage::Mesh::Surface *surface = mesh->surfaces[surface_index]; + + mesh_info.vertex_buffer_size += surface->vertex_buffer_size; + mesh_info.attribute_buffer_size += surface->attribute_buffer_size; + mesh_info.skin_buffer_size += surface->skin_buffer_size; + mesh_info.index_buffer_size += surface->index_buffer_size; + mesh_info.blend_shape_buffer_size += surface->blend_shape_buffer_size; + mesh_info.vertex_count += surface->vertex_count; + + for (uint32_t lod_index = 0; lod_index < surface->lod_count; lod_index++) { + mesh_info.lod_index_buffers_size += surface->lods[lod_index].index_buffer_size; + } + } + + r_info->push_back(mesh_info); + } +} + bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); ERR_FAIL_NULL_V(mesh, false); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 5b8ed343857..2ccc9f521d0 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -79,11 +79,14 @@ private: RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS; uint64_t format = 0; - RID vertex_buffer; - RID attribute_buffer; - RID skin_buffer; uint32_t vertex_count = 0; + RID vertex_buffer; uint32_t vertex_buffer_size = 0; + + RID attribute_buffer; + uint32_t attribute_buffer_size = 0; + + RID skin_buffer; uint32_t skin_buffer_size = 0; // A different pipeline needs to be allocated @@ -107,6 +110,7 @@ private: uint32_t version_count = 0; RID index_buffer; + uint32_t index_buffer_size = 0; RID index_array; uint32_t index_count = 0; @@ -114,6 +118,7 @@ private: float edge_length = 0.0; uint32_t index_count = 0; RID index_buffer; + uint32_t index_buffer_size = 0; RID index_array; }; @@ -131,6 +136,7 @@ private: Vector4 uv_scale; RID blend_shape_buffer; + uint32_t blend_shape_buffer_size = 0; RID material; @@ -398,6 +404,8 @@ public: virtual void mesh_clear(RID p_mesh) override; virtual void mesh_surface_remove(RID p_mesh, int p_surface) override; + virtual void mesh_debug_usage(List *r_info) override; + virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override; _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) { diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index ffbc5c70950..032428c105b 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -378,6 +378,8 @@ public: FUNC2(mesh_surface_remove, RID, int) FUNC1(mesh_clear, RID) + FUNC1(mesh_debug_usage, List *) + /* MULTIMESH API */ FUNCRIDSPLIT(multimesh) diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h index 7e190c39739..990183b59fa 100644 --- a/servers/rendering/storage/mesh_storage.h +++ b/servers/rendering/storage/mesh_storage.h @@ -77,6 +77,8 @@ public: virtual void mesh_surface_remove(RID p_mesh, int p_surface) = 0; virtual void mesh_clear(RID p_mesh) = 0; + virtual void mesh_debug_usage(List *r_info) = 0; + virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0; /* MESH INSTANCE */ diff --git a/servers/rendering_server.h b/servers/rendering_server.h index f889cce0482..d9b2b6ea6ae 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -443,6 +443,20 @@ public: virtual void mesh_surface_remove(RID p_mesh, int p_surface) = 0; virtual void mesh_clear(RID p_mesh) = 0; + struct MeshInfo { + RID mesh; + String path; + uint32_t vertex_buffer_size = 0; + uint32_t attribute_buffer_size = 0; + uint32_t skin_buffer_size = 0; + uint32_t index_buffer_size = 0; + uint32_t blend_shape_buffer_size = 0; + uint32_t lod_index_buffers_size = 0; + uint64_t vertex_count = 0; + }; + + virtual void mesh_debug_usage(List *r_info) = 0; + /* MULTIMESH API */ virtual RID multimesh_create() = 0;