From 36a005fafcad7be0c22f6402b6475d7bd7024703 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Fri, 26 May 2023 18:09:39 -0700 Subject: [PATCH] Add RENDERING_INFO parameters to GL Compatibility renderer This also fixes RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME for the RD renderers as it was incorrectly reporting vertex/index count at times This also adds memory tracking to textures and buffers to catch memory leaks. This also cleans up some memory leaks that the new system caught. --- doc/classes/RenderingServer.xml | 8 +- drivers/gles3/rasterizer_canvas_gles3.cpp | 59 ++++++--- drivers/gles3/rasterizer_scene_gles3.cpp | 122 +++++++++++++----- drivers/gles3/rasterizer_scene_gles3.h | 1 + drivers/gles3/storage/light_storage.cpp | 100 -------------- drivers/gles3/storage/mesh_storage.cpp | 46 +++---- drivers/gles3/storage/particles_storage.cpp | 44 ++++--- drivers/gles3/storage/texture_storage.cpp | 76 ++++++----- drivers/gles3/storage/texture_storage.h | 4 - drivers/gles3/storage/utilities.cpp | 38 ++++++ drivers/gles3/storage/utilities.h | 64 +++++++++ editor/plugins/node_3d_editor_plugin.cpp | 2 +- .../render_forward_clustered.cpp | 4 +- .../forward_mobile/render_forward_mobile.cpp | 4 +- servers/rendering/renderer_viewport.cpp | 2 +- servers/rendering/renderer_viewport.h | 2 +- .../rendering/rendering_server_default.cpp | 2 +- 17 files changed, 336 insertions(+), 242 deletions(-) diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 6b65302a7dd..0f2a6d649f4 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -4575,7 +4575,7 @@ Number of objects drawn in a single frame. - Number of vertices drawn in a single frame. + Number of points, lines, or triangles drawn in a single frame. Number of draw calls during this frame. @@ -5201,7 +5201,7 @@ Number of objects rendered in the current 3D scene. This varies depending on camera position and rotation. - Number of vertices/indices rendered in the current 3D scene. This varies depending on camera position and rotation. + Number of points, lines, or triangles rendered in the current 3D scene. This varies depending on camera position and rotation. Number of draw calls performed to render in the current 3D scene. This varies depending on camera position and rotation. @@ -5210,10 +5210,10 @@ Texture memory used (in bytes). - Buffer memory used (in bytes). + Buffer memory used (in bytes). This includes vertex data, uniform buffers, and many miscellaneous buffer types used internally. - Video memory used (in bytes). This is always greater than the sum of [constant RENDERING_INFO_TEXTURE_MEM_USED] and [constant RENDERING_INFO_BUFFER_MEM_USED], since there is miscellaneous data not accounted for by those two metrics. + Video memory used (in bytes). When using the Forward+ or mobile rendering backends, this is always greater than the sum of [constant RENDERING_INFO_TEXTURE_MEM_USED] and [constant RENDERING_INFO_BUFFER_MEM_USED], since there is miscellaneous data not accounted for by those two metrics. When using the GL Compatibility backend, this is equal to the sum of [constant RENDERING_INFO_TEXTURE_MEM_USED] and [constant RENDERING_INFO_BUFFER_MEM_USED]. Hardware supports shaders. This enum is currently unused in Godot 3.x. diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 59a65b4538a..86405fa3f04 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -1790,6 +1790,7 @@ void RasterizerCanvasGLES3::_update_shadow_atlas() { state.shadow_depth_buffer = 0; WARN_PRINT("Could not create CanvasItem shadow atlas, status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status)); } + GLES3::Utilities::get_singleton()->texture_allocated_data(state.shadow_texture, state.shadow_texture_size * data.max_lights_per_render * 2 * 4, "2D shadow atlas texture"); glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); } } @@ -1894,8 +1895,8 @@ void RasterizerCanvasGLES3::occluder_polygon_set_shape(RID p_occluder, const Vec if (oc->line_point_count != lines.size() && oc->vertex_array != 0) { glDeleteVertexArrays(1, &oc->vertex_array); - glDeleteBuffers(1, &oc->vertex_buffer); - glDeleteBuffers(1, &oc->index_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(oc->vertex_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(oc->index_buffer); oc->vertex_array = 0; oc->vertex_buffer = 0; @@ -1954,13 +1955,15 @@ void RasterizerCanvasGLES3::occluder_polygon_set_shape(RID p_occluder, const Vec glGenBuffers(1, &oc->vertex_buffer); glBindBuffer(GL_ARRAY_BUFFER, oc->vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(float), geometry.ptr(), GL_STATIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, oc->vertex_buffer, lc * 6 * sizeof(float), geometry.ptr(), GL_STATIC_DRAW, "Occluder polygon vertex buffer"); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); glVertexAttribPointer(RS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr); glGenBuffers(1, &oc->index_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, oc->index_buffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * lc * sizeof(uint16_t), indices.ptr(), GL_STATIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, oc->index_buffer, 3 * lc * sizeof(uint16_t), indices.ptr(), GL_STATIC_DRAW, "Occluder polygon index buffer"); + glBindVertexArray(0); } else { glBindBuffer(GL_ARRAY_BUFFER, oc->vertex_buffer); @@ -1995,8 +1998,8 @@ void RasterizerCanvasGLES3::occluder_polygon_set_shape(RID p_occluder, const Vec if (oc->sdf_index_count != sdf_indices.size() && oc->sdf_point_count != p_points.size() && oc->sdf_vertex_array != 0) { glDeleteVertexArrays(1, &oc->sdf_vertex_array); - glDeleteBuffers(1, &oc->sdf_vertex_buffer); - glDeleteBuffers(1, &oc->sdf_index_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(oc->sdf_vertex_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(oc->sdf_index_buffer); oc->sdf_vertex_array = 0; oc->sdf_vertex_buffer = 0; @@ -2015,13 +2018,15 @@ void RasterizerCanvasGLES3::occluder_polygon_set_shape(RID p_occluder, const Vec glGenBuffers(1, &oc->sdf_vertex_buffer); glBindBuffer(GL_ARRAY_BUFFER, oc->sdf_vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, p_points.size() * 2 * sizeof(float), p_points.to_byte_array().ptr(), GL_STATIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, oc->sdf_vertex_buffer, oc->sdf_point_count * 2 * sizeof(float), p_points.to_byte_array().ptr(), GL_STATIC_DRAW, "Occluder polygon SDF vertex buffer"); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr); glGenBuffers(1, &oc->sdf_index_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, oc->sdf_index_buffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sdf_indices.size() * sizeof(uint32_t), sdf_indices.to_byte_array().ptr(), GL_STATIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, oc->sdf_index_buffer, oc->sdf_index_count * sizeof(uint32_t), sdf_indices.to_byte_array().ptr(), GL_STATIC_DRAW, "Occluder polygon SDF index buffer"); + glBindVertexArray(0); } else { glBindBuffer(GL_ARRAY_BUFFER, oc->sdf_vertex_buffer); @@ -2410,7 +2415,7 @@ RendererCanvasRender::PolygonID RasterizerCanvasGLES3::request_polygon(const Vec } ERR_FAIL_COND_V(base_offset != stride, 0); - glBufferData(GL_ARRAY_BUFFER, vertex_count * stride * sizeof(float), polygon_buffer.ptr(), GL_STATIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, pb.vertex_buffer, vertex_count * stride * sizeof(float), polygon_buffer.ptr(), GL_STATIC_DRAW, "Polygon 2D vertex buffer"); } if (p_indices.size()) { @@ -2423,7 +2428,7 @@ RendererCanvasRender::PolygonID RasterizerCanvasGLES3::request_polygon(const Vec } glGenBuffers(1, &pb.index_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pb.index_buffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, p_indices.size() * 4, index_buffer.ptr(), GL_STATIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, pb.index_buffer, p_indices.size() * 4, index_buffer.ptr(), GL_STATIC_DRAW, "Polygon 2D index buffer"); pb.count = p_indices.size(); } @@ -2444,11 +2449,11 @@ void RasterizerCanvasGLES3::free_polygon(PolygonID p_polygon) { PolygonBuffers &pb = *pb_ptr; if (pb.index_buffer != 0) { - glDeleteBuffers(1, &pb.index_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(pb.index_buffer); } glDeleteVertexArrays(1, &pb.vertex_array); - glDeleteBuffers(1, &pb.vertex_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(pb.vertex_buffer); polygon_buffers.polygons.erase(p_polygon); } @@ -2462,13 +2467,13 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() { glGenBuffers(3, new_buffers); // Batch UBO. glBindBuffer(GL_ARRAY_BUFFER, new_buffers[0]); - glBufferData(GL_ARRAY_BUFFER, data.max_instance_buffer_size, nullptr, GL_STREAM_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, new_buffers[0], data.max_instance_buffer_size, nullptr, GL_STREAM_DRAW, "2D Batch UBO[" + itos(state.current_data_buffer_index) + "][0]"); // Light uniform buffer. glBindBuffer(GL_UNIFORM_BUFFER, new_buffers[1]); - glBufferData(GL_UNIFORM_BUFFER, sizeof(LightUniform) * data.max_lights_per_render, nullptr, GL_STREAM_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, new_buffers[1], sizeof(LightUniform) * data.max_lights_per_render, nullptr, GL_STREAM_DRAW, "2D Lights UBO[" + itos(state.current_data_buffer_index) + "]"); // State buffer. glBindBuffer(GL_UNIFORM_BUFFER, new_buffers[2]); - glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), nullptr, GL_STREAM_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, new_buffers[2], sizeof(StateBuffer), nullptr, GL_STREAM_DRAW, "2D State UBO[" + itos(state.current_data_buffer_index) + "]"); state.current_data_buffer_index = (state.current_data_buffer_index + 1); DataBuffer db; @@ -2493,7 +2498,7 @@ void RasterizerCanvasGLES3::_allocate_instance_buffer() { glGenBuffers(1, &new_buffer); glBindBuffer(GL_ARRAY_BUFFER, new_buffer); - glBufferData(GL_ARRAY_BUFFER, data.max_instance_buffer_size, nullptr, GL_STREAM_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, new_buffer, data.max_instance_buffer_size, nullptr, GL_STREAM_DRAW, "Batch UBO[" + itos(state.current_data_buffer_index) + "][" + itos(state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers.size()) + "]"); state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers.push_back(new_buffer); @@ -2656,13 +2661,13 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() { glGenBuffers(3, new_buffers); // Batch UBO. glBindBuffer(GL_ARRAY_BUFFER, new_buffers[0]); - glBufferData(GL_ARRAY_BUFFER, data.max_instance_buffer_size, nullptr, GL_STREAM_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, new_buffers[0], data.max_instance_buffer_size, nullptr, GL_STREAM_DRAW, "Batch UBO[0][0]"); // Light uniform buffer. glBindBuffer(GL_UNIFORM_BUFFER, new_buffers[1]); - glBufferData(GL_UNIFORM_BUFFER, sizeof(LightUniform) * data.max_lights_per_render, nullptr, GL_STREAM_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, new_buffers[1], sizeof(LightUniform) * data.max_lights_per_render, nullptr, GL_STREAM_DRAW, "2D lights UBO[0]"); // State buffer. glBindBuffer(GL_UNIFORM_BUFFER, new_buffers[2]); - glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), nullptr, GL_STREAM_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, new_buffers[2], sizeof(StateBuffer), nullptr, GL_STREAM_DRAW, "2D state UBO[0]"); DataBuffer db; db.instance_buffers.push_back(new_buffers[0]); db.light_ubo = new_buffers[1]; @@ -2779,12 +2784,26 @@ RasterizerCanvasGLES3::~RasterizerCanvasGLES3() { if (state.shadow_fb != 0) { glDeleteFramebuffers(1, &state.shadow_fb); - glDeleteTextures(1, &state.shadow_texture); + GLES3::Utilities::get_singleton()->texture_free_data(state.shadow_texture); glDeleteRenderbuffers(1, &state.shadow_depth_buffer); state.shadow_fb = 0; state.shadow_texture = 0; state.shadow_depth_buffer = 0; } + + for (uint32_t i = 0; i < state.canvas_instance_data_buffers.size(); i++) { + for (int j = 0; j < state.canvas_instance_data_buffers[i].instance_buffers.size(); j++) { + if (state.canvas_instance_data_buffers[i].instance_buffers[j]) { + GLES3::Utilities::get_singleton()->buffer_free_data(state.canvas_instance_data_buffers[i].instance_buffers[j]); + } + } + if (state.canvas_instance_data_buffers[i].light_ubo) { + GLES3::Utilities::get_singleton()->buffer_free_data(state.canvas_instance_data_buffers[i].light_ubo); + } + if (state.canvas_instance_data_buffers[i].state_ubo) { + GLES3::Utilities::get_singleton()->buffer_free_data(state.canvas_instance_data_buffers[i].state_ubo); + } + } } #endif // GLES3_ENABLED diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 3d8f7924a78..6ed5b3b2f80 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -443,8 +443,10 @@ void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_g void RasterizerSceneGLES3::_free_sky_data(Sky *p_sky) { if (p_sky->radiance != 0) { - glDeleteTextures(1, &p_sky->radiance); + GLES3::Utilities::get_singleton()->texture_free_data(p_sky->radiance); p_sky->radiance = 0; + GLES3::Utilities::get_singleton()->texture_free_data(p_sky->raw_radiance); + p_sky->raw_radiance = 0; glDeleteFramebuffers(1, &p_sky->radiance_framebuffer); p_sky->radiance_framebuffer = 0; } @@ -546,6 +548,8 @@ void RasterizerSceneGLES3::_update_dirty_skys() { glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count - 1); + GLES3::Utilities::get_singleton()->texture_allocated_data(sky->radiance, Image::get_image_data_size(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBA8, true), "Sky radiance map"); + glGenTextures(1, &sky->raw_radiance); glBindTexture(GL_TEXTURE_CUBE_MAP, sky->raw_radiance); @@ -568,6 +572,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() { glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count - 1); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + GLES3::Utilities::get_singleton()->texture_allocated_data(sky->raw_radiance, Image::get_image_data_size(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBA8, true), "Sky raw radiance map"); } sky->reflection_dirty = true; @@ -1154,6 +1159,11 @@ void RasterizerSceneGLES3::voxel_gi_update(RID p_probe, bool p_update_light_inst void RasterizerSceneGLES3::voxel_gi_set_quality(RS::VoxelGIQuality) { } +_FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primitive, uint32_t p_indices) { + static const uint32_t divisor[RS::PRIMITIVE_MAX] = { 1, 2, 1, 3, 1 }; + static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 }; + return (p_indices - subtractor[p_primitive]) / divisor[p_primitive]; +} void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append) { GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton(); @@ -1258,7 +1268,8 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const uint32_t indices = 0; surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, indices); - /* + surf->index_count = indices; + if (p_render_data->render_info) { indices = _indices_to_primitives(surf->primitive, indices); if (p_render_list == RENDER_LIST_OPAQUE) { //opaque @@ -1267,21 +1278,20 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += indices; } } - */ + } else { surf->lod_index = 0; - /* + if (p_render_data->render_info) { uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); to_draw = _indices_to_primitives(surf->primitive, to_draw); - to_draw *= inst->instance_count; + to_draw *= inst->instance_count > 0 ? inst->instance_count : 1; if (p_render_list == RENDER_LIST_OPAQUE) { //opaque - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += to_draw; } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += to_draw; } } - */ } // ADD Element @@ -1451,17 +1461,26 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da if (scene_state.ubo_buffer == 0) { glGenBuffers(1, &scene_state.ubo_buffer); + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_DATA_UNIFORM_LOCATION, scene_state.ubo_buffer); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, scene_state.ubo_buffer, sizeof(SceneState::UBO), &scene_state.ubo, GL_STREAM_DRAW, "Scene state UBO"); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } else { + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_DATA_UNIFORM_LOCATION, scene_state.ubo_buffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneState::UBO), &scene_state.ubo, GL_STREAM_DRAW); } - glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_DATA_UNIFORM_LOCATION, scene_state.ubo_buffer); - glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneState::UBO), &scene_state.ubo, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); if (p_render_data->view_count > 1) { if (scene_state.multiview_buffer == 0) { glGenBuffers(1, &scene_state.multiview_buffer); + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_MULTIVIEW_UNIFORM_LOCATION, scene_state.multiview_buffer); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, scene_state.multiview_buffer, sizeof(SceneState::MultiviewUBO), &scene_state.multiview_ubo, GL_STREAM_DRAW, "Multiview UBO"); + } else { + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_MULTIVIEW_UNIFORM_LOCATION, scene_state.multiview_buffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneState::MultiviewUBO), &scene_state.multiview_ubo, GL_STREAM_DRAW); } - glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_MULTIVIEW_UNIFORM_LOCATION, scene_state.multiview_buffer); - glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneState::MultiviewUBO), &scene_state.multiview_ubo, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); } } @@ -1792,9 +1811,14 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ if (scene_state.tonemap_buffer == 0) { // Only create if using 3D glGenBuffers(1, &scene_state.tonemap_buffer); + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_TONEMAP_UNIFORM_LOCATION, scene_state.tonemap_buffer); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, scene_state.tonemap_buffer, sizeof(SceneState::TonemapUBO), &tonemap_ubo, GL_STREAM_DRAW, "Tonemap UBO"); + } else { + glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_TONEMAP_UNIFORM_LOCATION, scene_state.tonemap_buffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneState::TonemapUBO), &tonemap_ubo, GL_STREAM_DRAW); } - glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_TONEMAP_UNIFORM_LOCATION, scene_state.tonemap_buffer); - glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneState::TonemapUBO), &tonemap_ubo, GL_STREAM_DRAW); + + glBindBuffer(GL_UNIFORM_BUFFER, 0); scene_state.ubo.emissive_exposure_normalization = -1.0; // Use default exposure normalization. @@ -2086,6 +2110,12 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, } bool should_request_redraw = false; + if constexpr (p_pass_mode != PASS_MODE_DEPTH) { + // Don't count elements during depth pre-pass to match the RD renderers. + if (p_render_data->render_info) { + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] += p_to_element - p_from_element; + } + } for (uint32_t i = p_from_element; i < p_to_element; i++) { const GeometryInstanceSurface *surf = p_params->elements[i]; @@ -2326,6 +2356,21 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, } material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, instance_variant, spec_constants); + + // Can be index count or vertex count + uint32_t count = 0; + if (surf->lod_index > 0) { + count = surf->index_count; + } else { + count = mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface); + } + if constexpr (p_pass_mode != PASS_MODE_DEPTH) { + // Don't count draw calls during depth pre-pass to match the RD renderers. + if (p_render_data->render_info) { + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME]++; + } + } + if (inst->instance_count > 0) { // Using MultiMesh or Particles. // Bind instance buffers. @@ -2366,16 +2411,16 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, glVertexAttribDivisor(15, 1); } if (use_index_buffer) { - glDrawElementsInstanced(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), mesh_storage->mesh_surface_get_index_type(mesh_surface), 0, inst->instance_count); + glDrawElementsInstanced(primitive_gl, count, mesh_storage->mesh_surface_get_index_type(mesh_surface), 0, inst->instance_count); } else { - glDrawArraysInstanced(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), inst->instance_count); + glDrawArraysInstanced(primitive_gl, 0, count, inst->instance_count); } } else { // Using regular Mesh. if (use_index_buffer) { - glDrawElements(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), mesh_storage->mesh_surface_get_index_type(mesh_surface), 0); + glDrawElements(primitive_gl, count, mesh_storage->mesh_surface_get_index_type(mesh_surface), 0); } else { - glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface)); + glDrawArrays(primitive_gl, 0, count); } } if (inst->instance_count > 0) { @@ -2579,19 +2624,20 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() { scene_state.omni_light_sort = memnew_arr(InstanceSort, config->max_renderable_lights); glGenBuffers(1, &scene_state.omni_light_buffer); glBindBuffer(GL_UNIFORM_BUFFER, scene_state.omni_light_buffer); - glBufferData(GL_UNIFORM_BUFFER, light_buffer_size, nullptr, GL_STREAM_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, scene_state.omni_light_buffer, light_buffer_size, nullptr, GL_STREAM_DRAW, "OmniLight UBO"); scene_state.spot_lights = memnew_arr(LightData, config->max_renderable_lights); scene_state.spot_light_sort = memnew_arr(InstanceSort, config->max_renderable_lights); glGenBuffers(1, &scene_state.spot_light_buffer); glBindBuffer(GL_UNIFORM_BUFFER, scene_state.spot_light_buffer); - glBufferData(GL_UNIFORM_BUFFER, light_buffer_size, nullptr, GL_STREAM_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, scene_state.spot_light_buffer, light_buffer_size, nullptr, GL_STREAM_DRAW, "SpotLight UBO"); uint32_t directional_light_buffer_size = MAX_DIRECTIONAL_LIGHTS * sizeof(DirectionalLightData); scene_state.directional_lights = memnew_arr(DirectionalLightData, MAX_DIRECTIONAL_LIGHTS); glGenBuffers(1, &scene_state.directional_light_buffer); glBindBuffer(GL_UNIFORM_BUFFER, scene_state.directional_light_buffer); - glBufferData(GL_UNIFORM_BUFFER, directional_light_buffer_size, nullptr, GL_STREAM_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, scene_state.directional_light_buffer, directional_light_buffer_size, nullptr, GL_STREAM_DRAW, "DirectionalLight UBO"); + glBindBuffer(GL_UNIFORM_BUFFER, 0); } @@ -2603,7 +2649,8 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() { sky_globals.last_frame_directional_light_count = sky_globals.max_directional_lights + 1; glGenBuffers(1, &sky_globals.directional_light_buffer); glBindBuffer(GL_UNIFORM_BUFFER, sky_globals.directional_light_buffer); - glBufferData(GL_UNIFORM_BUFFER, directional_light_buffer_size, nullptr, GL_STREAM_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, sky_globals.directional_light_buffer, directional_light_buffer_size, nullptr, GL_STREAM_DRAW, "Sky DirectionalLight UBO"); + glBindBuffer(GL_UNIFORM_BUFFER, 0); } @@ -2702,6 +2749,8 @@ void sky() { } { + glGenVertexArrays(1, &sky_globals.screen_triangle_array); + glBindVertexArray(sky_globals.screen_triangle_array); glGenBuffers(1, &sky_globals.screen_triangle); glBindBuffer(GL_ARRAY_BUFFER, sky_globals.screen_triangle); @@ -2714,12 +2763,8 @@ void sky() { 3.0f, }; - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, qv, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, sky_globals.screen_triangle, sizeof(float) * 6, qv, GL_STATIC_DRAW, "Screen triangle vertex buffer"); - glGenVertexArrays(1, &sky_globals.screen_triangle_array); - glBindVertexArray(sky_globals.screen_triangle_array); - glBindBuffer(GL_ARRAY_BUFFER, sky_globals.screen_triangle); glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, nullptr); glEnableVertexAttribArray(RS::ARRAY_VERTEX); glBindVertexArray(0); @@ -2735,9 +2780,9 @@ void sky() { } RasterizerSceneGLES3::~RasterizerSceneGLES3() { - glDeleteBuffers(1, &scene_state.directional_light_buffer); - glDeleteBuffers(1, &scene_state.omni_light_buffer); - glDeleteBuffers(1, &scene_state.spot_light_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(scene_state.directional_light_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(scene_state.omni_light_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(scene_state.spot_light_buffer); memdelete_arr(scene_state.directional_lights); memdelete_arr(scene_state.omni_lights); memdelete_arr(scene_state.spot_lights); @@ -2756,13 +2801,26 @@ RasterizerSceneGLES3::~RasterizerSceneGLES3() { RSG::material_storage->shader_free(sky_globals.default_shader); RSG::material_storage->material_free(sky_globals.fog_material); RSG::material_storage->shader_free(sky_globals.fog_shader); - glDeleteBuffers(1, &sky_globals.screen_triangle); + GLES3::Utilities::get_singleton()->buffer_free_data(sky_globals.screen_triangle); glDeleteVertexArrays(1, &sky_globals.screen_triangle_array); glDeleteTextures(1, &sky_globals.radical_inverse_vdc_cache_tex); - glDeleteBuffers(1, &sky_globals.directional_light_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(sky_globals.directional_light_buffer); memdelete_arr(sky_globals.directional_lights); memdelete_arr(sky_globals.last_frame_directional_lights); + // UBOs + if (scene_state.ubo_buffer != 0) { + GLES3::Utilities::get_singleton()->buffer_free_data(scene_state.ubo_buffer); + } + + if (scene_state.multiview_buffer != 0) { + GLES3::Utilities::get_singleton()->buffer_free_data(scene_state.multiview_buffer); + } + + if (scene_state.tonemap_buffer != 0) { + GLES3::Utilities::get_singleton()->buffer_free_data(scene_state.tonemap_buffer); + } + singleton = nullptr; } diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index b4e787ad857..9709d6be2a1 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -220,6 +220,7 @@ private: uint32_t flags = 0; uint32_t surface_index = 0; uint32_t lod_index = 0; + uint32_t index_count = 0; void *surface = nullptr; GLES3::SceneShaderData *shader = nullptr; diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp index 8da5e657cd2..5aab91e8ae0 100644 --- a/drivers/gles3/storage/light_storage.cpp +++ b/drivers/gles3/storage/light_storage.cpp @@ -595,106 +595,6 @@ void LightStorage::lightmap_instance_free(RID p_lightmap) { void LightStorage::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) { } -/* LIGHT SHADOW MAPPING */ -/* - -RID LightStorage::canvas_light_occluder_create() { - CanvasOccluder *co = memnew(CanvasOccluder); - co->index_id = 0; - co->vertex_id = 0; - co->len = 0; - - return canvas_occluder_owner.make_rid(co); -} - -void LightStorage::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector &p_lines) { - CanvasOccluder *co = canvas_occluder_owner.get(p_occluder); - ERR_FAIL_COND(!co); - - co->lines = p_lines; - - if (p_lines.size() != co->len) { - if (co->index_id) { - glDeleteBuffers(1, &co->index_id); - } if (co->vertex_id) { - glDeleteBuffers(1, &co->vertex_id); - } - - co->index_id = 0; - co->vertex_id = 0; - co->len = 0; - } - - if (p_lines.size()) { - PoolVector geometry; - PoolVector indices; - int lc = p_lines.size(); - - geometry.resize(lc * 6); - indices.resize(lc * 3); - - PoolVector::Write vw = geometry.write(); - PoolVector::Write iw = indices.write(); - - PoolVector::Read lr = p_lines.read(); - - const int POLY_HEIGHT = 16384; - - for (int i = 0; i < lc / 2; i++) { - vw[i * 12 + 0] = lr[i * 2 + 0].x; - vw[i * 12 + 1] = lr[i * 2 + 0].y; - vw[i * 12 + 2] = POLY_HEIGHT; - - vw[i * 12 + 3] = lr[i * 2 + 1].x; - vw[i * 12 + 4] = lr[i * 2 + 1].y; - vw[i * 12 + 5] = POLY_HEIGHT; - - vw[i * 12 + 6] = lr[i * 2 + 1].x; - vw[i * 12 + 7] = lr[i * 2 + 1].y; - vw[i * 12 + 8] = -POLY_HEIGHT; - - vw[i * 12 + 9] = lr[i * 2 + 0].x; - vw[i * 12 + 10] = lr[i * 2 + 0].y; - vw[i * 12 + 11] = -POLY_HEIGHT; - - iw[i * 6 + 0] = i * 4 + 0; - iw[i * 6 + 1] = i * 4 + 1; - iw[i * 6 + 2] = i * 4 + 2; - - iw[i * 6 + 3] = i * 4 + 2; - iw[i * 6 + 4] = i * 4 + 3; - iw[i * 6 + 5] = i * 4 + 0; - } - - //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush - - if (!co->vertex_id) { - glGenBuffers(1, &co->vertex_id); - glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); - glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_STATIC_DRAW); - } else { - glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); - glBufferSubData(GL_ARRAY_BUFFER, 0, lc * 6 * sizeof(real_t), vw.ptr()); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - - if (!co->index_id) { - glGenBuffers(1, &co->index_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, lc * 3 * sizeof(uint16_t), iw.ptr(), GL_DYNAMIC_DRAW); - } else { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, lc * 3 * sizeof(uint16_t), iw.ptr()); - } - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind - - co->len = lc; - } -} -*/ - /* SHADOW ATLAS API */ RID LightStorage::shadow_atlas_create() { diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index 585ed5ff96c..8a027aad1cc 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -193,26 +193,26 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) if (p_surface.vertex_data.size()) { glGenBuffers(1, &s->vertex_buffer); glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, p_surface.vertex_data.size(), p_surface.vertex_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->vertex_buffer, p_surface.vertex_data.size(), p_surface.vertex_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh vertex buffer"); s->vertex_buffer_size = p_surface.vertex_data.size(); } if (p_surface.attribute_data.size()) { glGenBuffers(1, &s->attribute_buffer); glBindBuffer(GL_ARRAY_BUFFER, s->attribute_buffer); - glBufferData(GL_ARRAY_BUFFER, p_surface.attribute_data.size(), p_surface.attribute_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->attribute_buffer, p_surface.attribute_data.size(), p_surface.attribute_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh attribute buffer"); s->attribute_buffer_size = p_surface.attribute_data.size(); } + if (p_surface.skin_data.size()) { glGenBuffers(1, &s->skin_buffer); glBindBuffer(GL_ARRAY_BUFFER, s->skin_buffer); - glBufferData(GL_ARRAY_BUFFER, p_surface.skin_data.size(), p_surface.skin_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->skin_buffer, p_surface.skin_data.size(), p_surface.skin_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh skin buffer"); s->skin_buffer_size = p_surface.skin_data.size(); } + glBindBuffer(GL_ARRAY_BUFFER, 0); + s->vertex_count = p_surface.vertex_count; if (p_surface.format & RS::ARRAY_FORMAT_BONES) { @@ -223,7 +223,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0; glGenBuffers(1, &s->index_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_buffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, p_surface.index_data.size(), p_surface.index_data.ptr(), GL_STATIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->index_buffer, p_surface.index_data.size(), p_surface.index_data.ptr(), GL_STATIC_DRAW, "Mesh index buffer"); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind s->index_count = p_surface.index_count; s->index_buffer_size = p_surface.index_data.size(); @@ -235,7 +235,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) for (int i = 0; i < p_surface.lods.size(); i++) { glGenBuffers(1, &s->lods[i].index_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->lods[i].index_buffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, p_surface.lods[i].index_data.size(), p_surface.lods[i].index_data.ptr(), GL_STATIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->lods[i].index_buffer, p_surface.lods[i].index_data.size(), p_surface.lods[i].index_data.ptr(), GL_STATIC_DRAW, "Mesh index buffer LOD[" + itos(i) + "]"); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind s->lods[i].edge_length = p_surface.lods[i].edge_length; s->lods[i].index_count = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4); @@ -282,7 +282,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) glBindVertexArray(s->blend_shapes[i].vertex_array); glGenBuffers(1, &s->blend_shapes[i].vertex_buffer); glBindBuffer(GL_ARRAY_BUFFER, s->blend_shapes[i].vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, size, p_surface.blend_shape_data.ptr() + i * size, (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s->blend_shapes[i].vertex_buffer, size, p_surface.blend_shape_data.ptr() + i * size, (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, "Mesh blend shape buffer"); if ((p_surface.format & (1 << RS::ARRAY_VERTEX))) { glEnableVertexAttribArray(RS::ARRAY_VERTEX + 3); @@ -637,7 +637,7 @@ void MeshStorage::mesh_clear(RID p_mesh) { Mesh::Surface &s = *mesh->surfaces[i]; if (s.vertex_buffer != 0) { - glDeleteBuffers(1, &s.vertex_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(s.vertex_buffer); s.vertex_buffer = 0; } @@ -649,17 +649,17 @@ void MeshStorage::mesh_clear(RID p_mesh) { } if (s.attribute_buffer != 0) { - glDeleteBuffers(1, &s.attribute_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(s.attribute_buffer); s.attribute_buffer = 0; } if (s.skin_buffer != 0) { - glDeleteBuffers(1, &s.skin_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(s.skin_buffer); s.skin_buffer = 0; } if (s.index_buffer != 0) { - glDeleteBuffers(1, &s.index_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(s.index_buffer); s.index_buffer = 0; } @@ -670,7 +670,7 @@ void MeshStorage::mesh_clear(RID p_mesh) { if (s.lod_count) { for (uint32_t j = 0; j < s.lod_count; j++) { if (s.lods[j].index_buffer != 0) { - glDeleteBuffers(1, &s.lods[j].index_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(s.lods[j].index_buffer); s.lods[j].index_buffer = 0; } } @@ -680,7 +680,7 @@ void MeshStorage::mesh_clear(RID p_mesh) { if (mesh->blend_shape_count) { for (uint32_t j = 0; j < mesh->blend_shape_count; j++) { if (s.blend_shapes[j].vertex_buffer != 0) { - glDeleteBuffers(1, &s.blend_shapes[j].vertex_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(s.blend_shapes[j].vertex_buffer); s.blend_shapes[j].vertex_buffer = 0; } if (s.blend_shapes[j].vertex_array != 0) { @@ -916,13 +916,14 @@ void MeshStorage::_mesh_instance_clear(MeshInstance *mi) { } if (mi->surfaces[i].vertex_buffers[0] != 0) { - glDeleteBuffers(2, mi->surfaces[i].vertex_buffers); + GLES3::Utilities::get_singleton()->buffer_free_data(mi->surfaces[i].vertex_buffers[0]); + GLES3::Utilities::get_singleton()->buffer_free_data(mi->surfaces[i].vertex_buffers[1]); mi->surfaces[i].vertex_buffers[0] = 0; mi->surfaces[i].vertex_buffers[1] = 0; } if (mi->surfaces[i].vertex_buffer != 0) { - glDeleteBuffers(1, &mi->surfaces[i].vertex_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(mi->surfaces[i].vertex_buffer); mi->surfaces[i].vertex_buffer = 0; } } @@ -963,13 +964,13 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3 // Buffer to be used for rendering. Final output of skeleton and blend shapes. glGenBuffers(1, &s.vertex_buffer); glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count, nullptr, GL_DYNAMIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s.vertex_buffer, s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count, nullptr, GL_DYNAMIC_DRAW, "MeshInstance vertex buffer"); if (mesh->blend_shape_count > 0) { // Ping-Pong buffers for processing blendshapes. glGenBuffers(2, s.vertex_buffers); for (uint32_t i = 0; i < 2; i++) { glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffers[i]); - glBufferData(GL_ARRAY_BUFFER, s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count, nullptr, GL_DYNAMIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, s.vertex_buffers[i], s.vertex_stride_cache * mesh->surfaces[p_surface]->vertex_count, nullptr, GL_DYNAMIC_DRAW, "MeshInstance process buffer[" + itos(i) + "]"); } } glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind @@ -1271,7 +1272,7 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS:: } if (multimesh->buffer) { - glDeleteBuffers(1, &multimesh->buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(multimesh->buffer); multimesh->buffer = 0; } @@ -1298,7 +1299,7 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS:: if (multimesh->instances) { glGenBuffers(1, &multimesh->buffer); glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer); - glBufferData(GL_ARRAY_BUFFER, multimesh->instances * multimesh->stride_cache * sizeof(float), nullptr, GL_STATIC_DRAW); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float), nullptr, GL_STATIC_DRAW, "MultiMesh buffer"); glBindBuffer(GL_ARRAY_BUFFER, 0); } @@ -1958,7 +1959,7 @@ void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_ } if (skeleton->transforms_texture != 0) { - glDeleteTextures(1, &skeleton->transforms_texture); + GLES3::Utilities::get_singleton()->texture_free_data(skeleton->transforms_texture); skeleton->transforms_texture = 0; skeleton->data.clear(); } @@ -1973,6 +1974,7 @@ void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); + GLES3::Utilities::get_singleton()->texture_allocated_data(skeleton->transforms_texture, skeleton->data.size() * sizeof(float), "Skeleton transforms texture"); memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float)); diff --git a/drivers/gles3/storage/particles_storage.cpp b/drivers/gles3/storage/particles_storage.cpp index 4b64e2aec13..dbd86451d2c 100644 --- a/drivers/gles3/storage/particles_storage.cpp +++ b/drivers/gles3/storage/particles_storage.cpp @@ -141,23 +141,23 @@ void ParticlesStorage::_particles_free_data(Particles *particles) { if (particles->front_process_buffer != 0) { glDeleteVertexArrays(1, &particles->front_vertex_array); - glDeleteBuffers(1, &particles->front_process_buffer); - glDeleteBuffers(1, &particles->front_instance_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(particles->front_process_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(particles->front_instance_buffer); particles->front_vertex_array = 0; particles->front_process_buffer = 0; particles->front_instance_buffer = 0; glDeleteVertexArrays(1, &particles->back_vertex_array); - glDeleteBuffers(1, &particles->back_process_buffer); - glDeleteBuffers(1, &particles->back_instance_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(particles->back_process_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(particles->back_instance_buffer); particles->back_vertex_array = 0; particles->back_process_buffer = 0; particles->back_instance_buffer = 0; } if (particles->sort_buffer != 0) { - glDeleteBuffers(1, &particles->last_frame_buffer); - glDeleteBuffers(1, &particles->sort_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(particles->last_frame_buffer); + GLES3::Utilities::get_singleton()->buffer_free_data(particles->sort_buffer); particles->last_frame_buffer = 0; particles->sort_buffer = 0; particles->sort_buffer_filled = false; @@ -165,7 +165,7 @@ void ParticlesStorage::_particles_free_data(Particles *particles) { } if (particles->frame_params_ubo != 0) { - glDeleteBuffers(1, &particles->frame_params_ubo); + GLES3::Utilities::get_singleton()->buffer_free_data(particles->frame_params_ubo); particles->frame_params_ubo = 0; } } @@ -680,10 +680,13 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta if (p_particles->frame_params_ubo == 0) { glGenBuffers(1, &p_particles->frame_params_ubo); + glBindBufferBase(GL_UNIFORM_BUFFER, PARTICLES_FRAME_UNIFORM_LOCATION, p_particles->frame_params_ubo); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_UNIFORM_BUFFER, p_particles->frame_params_ubo, sizeof(ParticlesFrameParams), &frame_params, GL_STREAM_DRAW, "Particle Frame UBO"); + } else { + // Update per-frame UBO. + glBindBufferBase(GL_UNIFORM_BUFFER, PARTICLES_FRAME_UNIFORM_LOCATION, p_particles->frame_params_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(ParticlesFrameParams), &frame_params, GL_STREAM_DRAW); } - // Update per-frame UBO. - glBindBufferBase(GL_UNIFORM_BUFFER, PARTICLES_FRAME_UNIFORM_LOCATION, p_particles->frame_params_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(ParticlesFrameParams), &frame_params, GL_STREAM_DRAW); // Get shader and set shader uniforms; ParticleProcessMaterialData *m = static_cast(material_storage->material_get_data(p_particles->process_material, RS::SHADER_PARTICLES)); @@ -831,7 +834,7 @@ void ParticlesStorage::_particles_update_buffers(Particles *particles) { glGenBuffers(1, &particles->front_instance_buffer); glBindBuffer(GL_ARRAY_BUFFER, particles->front_process_buffer); - glBufferData(GL_ARRAY_BUFFER, particles->process_buffer_stride_cache * total_amount, data, GL_DYNAMIC_COPY); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, particles->front_process_buffer, particles->process_buffer_stride_cache * total_amount, data, GL_DYNAMIC_COPY, "Particles front process buffer"); for (uint32_t j = 0; j < particles->num_attrib_arrays_cache; j++) { glEnableVertexAttribArray(j); @@ -840,7 +843,7 @@ void ParticlesStorage::_particles_update_buffers(Particles *particles) { glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, particles->front_instance_buffer); - glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_COPY); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, particles->front_instance_buffer, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_COPY, "Particles front instance buffer"); } { @@ -850,7 +853,7 @@ void ParticlesStorage::_particles_update_buffers(Particles *particles) { glGenBuffers(1, &particles->back_instance_buffer); glBindBuffer(GL_ARRAY_BUFFER, particles->back_process_buffer); - glBufferData(GL_ARRAY_BUFFER, particles->process_buffer_stride_cache * total_amount, data, GL_DYNAMIC_COPY); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, particles->back_process_buffer, particles->process_buffer_stride_cache * total_amount, data, GL_DYNAMIC_COPY, "Particles back process buffer"); for (uint32_t j = 0; j < particles->num_attrib_arrays_cache; j++) { glEnableVertexAttribArray(j); @@ -859,7 +862,7 @@ void ParticlesStorage::_particles_update_buffers(Particles *particles) { glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, particles->back_instance_buffer); - glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_COPY); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, particles->back_instance_buffer, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_COPY, "Particles back instance buffer"); } glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -871,11 +874,12 @@ void ParticlesStorage::_particles_allocate_history_buffers(Particles *particles) if (particles->sort_buffer == 0) { glGenBuffers(1, &particles->last_frame_buffer); glBindBuffer(GL_ARRAY_BUFFER, particles->last_frame_buffer); - glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_READ); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, particles->last_frame_buffer, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_READ, "Particles last frame buffer"); glGenBuffers(1, &particles->sort_buffer); glBindBuffer(GL_ARRAY_BUFFER, particles->sort_buffer); - glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_READ); + GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ARRAY_BUFFER, particles->sort_buffer, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_READ, "Particles sort buffer"); + particles->sort_buffer_filled = false; particles->last_frame_buffer_filled = false; glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -1179,7 +1183,7 @@ void ParticlesStorage::particles_collision_free(RID p_rid) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_rid); if (particles_collision->heightfield_texture != 0) { - glDeleteTextures(1, &particles_collision->heightfield_texture); + GLES3::Utilities::get_singleton()->texture_free_data(particles_collision->heightfield_texture); particles_collision->heightfield_texture = 0; glDeleteFramebuffers(1, &particles_collision->heightfield_fb); particles_collision->heightfield_fb = 0; @@ -1226,6 +1230,8 @@ GLuint ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_p WARN_PRINT("Could create heightmap texture status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status)); } #endif + GLES3::Utilities::get_singleton()->texture_allocated_data(particles_collision->heightfield_texture, size.x * size.y * 4, "Particles collision heightfield texture"); + particles_collision->heightfield_fb_size = size; glBindTexture(GL_TEXTURE_2D, 0); @@ -1244,7 +1250,7 @@ void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_co } if (particles_collision->heightfield_texture != 0) { - glDeleteTextures(1, &particles_collision->heightfield_texture); + GLES3::Utilities::get_singleton()->texture_free_data(particles_collision->heightfield_texture); particles_collision->heightfield_texture = 0; glDeleteFramebuffers(1, &particles_collision->heightfield_fb); particles_collision->heightfield_fb = 0; @@ -1319,7 +1325,7 @@ void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_par particles_collision->heightfield_resolution = p_resolution; if (particles_collision->heightfield_texture != 0) { - glDeleteTextures(1, &particles_collision->heightfield_texture); + GLES3::Utilities::get_singleton()->texture_free_data(particles_collision->heightfield_texture); particles_collision->heightfield_texture = 0; glDeleteFramebuffers(1, &particles_collision->heightfield_fb); particles_collision->heightfield_fb = 0; diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index c4fef89cfd2..05b44439632 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -33,6 +33,7 @@ #include "texture_storage.h" #include "config.h" #include "drivers/gles3/effects/copy_effects.h" +#include "utilities.h" #ifdef ANDROID_ENABLED #define glFramebufferTextureMultiviewOVR GLES3::Config::get_singleton()->eglFramebufferTextureMultiviewOVR @@ -164,6 +165,7 @@ TextureStorage::TextureStorage() { glBindTexture(GL_TEXTURE_2D, texture.tex_id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 4, 4, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixel_data); + GLES3::Utilities::get_singleton()->texture_allocated_data(texture.tex_id, 4 * 4 * 4, "Default uint texture"); texture.gl_set_filter(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST); } { @@ -185,6 +187,7 @@ TextureStorage::TextureStorage() { glBindTexture(GL_TEXTURE_2D, texture.tex_id); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 4, 4, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, pixel_data); + GLES3::Utilities::get_singleton()->texture_allocated_data(texture.tex_id, 4 * 4 * 2, "Default depth texture"); texture.gl_set_filter(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST); } } @@ -203,6 +206,7 @@ TextureStorage::TextureStorage() { glGenTextures(1, &texture_atlas.texture); glBindTexture(GL_TEXTURE_2D, texture_atlas.texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel_data); + GLES3::Utilities::get_singleton()->texture_allocated_data(texture_atlas.texture, 4 * 4 * 4, "Texture atlas (Default)"); } glBindTexture(GL_TEXTURE_2D, 0); @@ -222,8 +226,9 @@ TextureStorage::~TextureStorage() { for (int i = 0; i < DEFAULT_GL_TEXTURE_MAX; i++) { texture_free(default_gl_textures[i]); } - - glDeleteTextures(1, &texture_atlas.texture); + if (texture_atlas.texture != 0) { + GLES3::Utilities::get_singleton()->texture_free_data(texture_atlas.texture); + } texture_atlas.texture = 0; glDeleteFramebuffers(1, &texture_atlas.framebuffer); texture_atlas.framebuffer = 0; @@ -706,7 +711,7 @@ void TextureStorage::texture_free(RID p_texture) { if (t->tex_id != 0) { if (!t->is_external) { - glDeleteTextures(1, &t->tex_id); + GLES3::Utilities::get_singleton()->texture_free_data(t->tex_id); } t->tex_id = 0; } @@ -743,9 +748,10 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref &p_im texture.type = Texture::TYPE_2D; texture.target = GL_TEXTURE_2D; _get_gl_image_and_format(Ref(), texture.format, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false); - //texture.total_data_size = p_image->get_image_data_size(); // verify that this returns size in bytes + texture.total_data_size = p_image->get_image_data_size(texture.width, texture.height, texture.format, texture.mipmaps); texture.active = true; glGenTextures(1, &texture.tex_id); + GLES3::Utilities::get_singleton()->texture_allocated_data(texture.tex_id, texture.total_data_size, "Texture 2D"); texture_owner.initialize_rid(p_texture, texture); texture_set_data(p_texture, p_image); } @@ -792,8 +798,10 @@ void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector(), texture.format, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false); + texture.total_data_size = p_layers[0]->get_image_data_size(texture.width, texture.height, texture.format, texture.mipmaps) * texture.layers; texture.active = true; glGenTextures(1, &texture.tex_id); + GLES3::Utilities::get_singleton()->texture_allocated_data(texture.tex_id, texture.total_data_size, "Texture Layered"); texture_owner.initialize_rid(p_texture, texture); for (int i = 0; i < p_layers.size(); i++) { _texture_set_data(p_texture, p_layers[i], i, i == 0); @@ -850,10 +858,12 @@ RID TextureStorage::texture_create_external(Texture::Type p_type, Image::Format void TextureStorage::texture_2d_update(RID p_texture, const Ref &p_image, int p_layer) { texture_set_data(p_texture, p_image, p_layer); -#ifdef TOOLS_ENABLED + Texture *tex = texture_owner.get_or_null(p_texture); ERR_FAIL_COND(!tex); + GLES3::Utilities::get_singleton()->texture_resize_data(tex->tex_id, tex->total_data_size); +#ifdef TOOLS_ENABLED tex->image_cache_2d.unref(); #endif } @@ -1063,7 +1073,7 @@ void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) { } if (tex_to->tex_id) { - glDeleteTextures(1, &tex_to->tex_id); + GLES3::Utilities::get_singleton()->texture_free_data(tex_to->tex_id); tex_to->tex_id = 0; } @@ -1213,15 +1223,11 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref &p_image, ERR_FAIL_COND(!p_image->get_width()); ERR_FAIL_COND(!p_image->get_height()); - // ERR_FAIL_COND(texture->type == RS::TEXTURE_TYPE_EXTERNAL); - GLenum type; GLenum format; GLenum internal_format; bool compressed = false; - // print_line("texture_set_data width " + itos (p_image->get_width()) + " height " + itos(p_image->get_height())); - Image::Format real_format; Ref img = _get_gl_image_and_format(p_image, p_image->get_format(), real_format, format, internal_format, type, compressed, texture->resize_to_po2); ERR_FAIL_COND(img.is_null()); @@ -1322,21 +1328,13 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref &p_image, h = MAX(1, h >> 1); } - // info.texture_mem -= texture->total_data_size; // TODO make this work again!! texture->total_data_size = tsize; - // info.texture_mem += texture->total_data_size; // TODO make this work again!! - - // printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem); texture->stored_cube_sides |= (1 << p_layer); texture->mipmaps = mipmaps; } -void TextureStorage::texture_set_data_partial(RID p_texture, const Ref &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) { - ERR_PRINT("Not implemented yet, sorry :("); -} - Image::Format TextureStorage::texture_get_format(RID p_texture) const { Texture *texture = texture_owner.get_or_null(p_texture); @@ -1386,10 +1384,6 @@ void TextureStorage::texture_bind(RID p_texture, uint32_t p_texture_no) { glBindTexture(texture->target, texture->tex_id); } -RID TextureStorage::texture_create_radiance_cubemap(RID p_source, int p_resolution) const { - return RID(); -} - /* TEXTURE ATLAS API */ void TextureStorage::texture_add_to_texture_atlas(RID p_texture) { @@ -1442,7 +1436,7 @@ void TextureStorage::update_texture_atlas() { texture_atlas.dirty = false; if (texture_atlas.texture != 0) { - glDeleteTextures(1, &texture_atlas.texture); + GLES3::Utilities::get_singleton()->texture_free_data(texture_atlas.texture); texture_atlas.texture = 0; glDeleteFramebuffers(1, &texture_atlas.framebuffer); texture_atlas.framebuffer = 0; @@ -1559,6 +1553,7 @@ void TextureStorage::update_texture_atlas() { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture_atlas.texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture_atlas.size.width, texture_atlas.size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + GLES3::Utilities::get_singleton()->texture_allocated_data(texture_atlas.texture, texture_atlas.size.width * texture_atlas.size.height * 4, "Texture atlas"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -1576,7 +1571,7 @@ void TextureStorage::update_texture_atlas() { if (status != GL_FRAMEBUFFER_COMPLETE) { glDeleteFramebuffers(1, &texture_atlas.framebuffer); texture_atlas.framebuffer = 0; - glDeleteTextures(1, &texture_atlas.texture); + GLES3::Utilities::get_singleton()->texture_free_data(texture_atlas.texture); texture_atlas.texture = 0; WARN_PRINT("Could not create texture atlas, status: " + get_framebuffer_error(status)); return; @@ -1702,6 +1697,8 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + GLES3::Utilities::get_singleton()->texture_allocated_data(rt->color, rt->size.x * rt->size.y * rt->view_count * 4, "Render target color texture"); } #ifndef IOS_ENABLED if (use_multiview) { @@ -1733,6 +1730,8 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + GLES3::Utilities::get_singleton()->texture_allocated_data(rt->depth, rt->size.x * rt->size.y * rt->view_count * 3, "Render target depth texture"); } #ifndef IOS_ENABLED if (use_multiview) { @@ -1747,7 +1746,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { glDeleteFramebuffers(1, &rt->fbo); - glDeleteTextures(1, &rt->color); + GLES3::Utilities::get_singleton()->texture_free_data(rt->color); rt->fbo = 0; rt->size.x = 0; rt->size.y = 0; @@ -1805,8 +1804,10 @@ void TextureStorage::_create_render_target_backbuffer(RenderTarget *rt) { glGenTextures(1, &rt->backbuffer); glBindTexture(GL_TEXTURE_2D, rt->backbuffer); + uint32_t texture_size_bytes = 0; for (int l = 0; l < count; l++) { + texture_size_bytes += width * height * 4; glTexImage2D(GL_TEXTURE_2D, l, rt->color_internal_format, width, height, 0, rt->color_format, rt->color_type, nullptr); width = MAX(1, (width / 2)); height = MAX(1, (height / 2)); @@ -1826,6 +1827,7 @@ void TextureStorage::_create_render_target_backbuffer(RenderTarget *rt) { glBindFramebuffer(GL_FRAMEBUFFER, system_fbo); return; } + GLES3::Utilities::get_singleton()->texture_allocated_data(rt->backbuffer, texture_size_bytes, "Render target backbuffer color texture"); // Initialize all levels to opaque Magenta. for (int j = 0; j < count; j++) { @@ -1862,7 +1864,7 @@ void GLES3::TextureStorage::copy_scene_to_backbuffer(RenderTarget *rt, const boo } else { glTexImage2D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr); } - + GLES3::Utilities::get_singleton()->texture_allocated_data(rt->backbuffer, rt->size.x * rt->size.y * rt->view_count * 4, "Render target backbuffer color texture (3D)"); glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -1885,6 +1887,8 @@ void GLES3::TextureStorage::copy_scene_to_backbuffer(RenderTarget *rt, const boo } else { glTexImage2D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); } + GLES3::Utilities::get_singleton()->texture_allocated_data(rt->backbuffer_depth, rt->size.x * rt->size.y * rt->view_count * 3, "Render target backbuffer depth texture"); + glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -1941,7 +1945,7 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { if (rt->overridden.color.is_valid()) { rt->overridden.color = RID(); } else if (rt->color) { - glDeleteTextures(1, &rt->color); + GLES3::Utilities::get_singleton()->texture_free_data(rt->color); if (rt->texture.is_valid()) { Texture *tex = get_texture(rt->texture); tex->tex_id = 0; @@ -1952,7 +1956,7 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { if (rt->overridden.depth.is_valid()) { rt->overridden.depth = RID(); } else if (rt->depth) { - glDeleteTextures(1, &rt->depth); + GLES3::Utilities::get_singleton()->texture_free_data(rt->depth); } rt->depth = 0; @@ -1961,12 +1965,12 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { if (rt->backbuffer_fbo != 0) { glDeleteFramebuffers(1, &rt->backbuffer_fbo); - glDeleteTextures(1, &rt->backbuffer); + GLES3::Utilities::get_singleton()->texture_free_data(rt->backbuffer); rt->backbuffer = 0; rt->backbuffer_fbo = 0; } if (rt->backbuffer_depth != 0) { - glDeleteTextures(1, &rt->backbuffer_depth); + GLES3::Utilities::get_singleton()->texture_free_data(rt->backbuffer_depth); rt->backbuffer_depth = 0; } _render_target_clear_sdf(rt); @@ -2331,6 +2335,7 @@ void TextureStorage::_render_target_allocate_sdf(RenderTarget *rt) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, rt->sdf_texture_write); glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, size.width, size.height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr); + GLES3::Utilities::get_singleton()->texture_allocated_data(rt->sdf_texture_write, size.width * size.height, "SDF texture"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); @@ -2371,6 +2376,7 @@ void TextureStorage::_render_target_allocate_sdf(RenderTarget *rt) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + GLES3::Utilities::get_singleton()->texture_allocated_data(rt->sdf_texture_process[0], rt->process_size.width * rt->process_size.height * 4, "SDF process texture[0]"); glBindTexture(GL_TEXTURE_2D, rt->sdf_texture_process[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16I, rt->process_size.width, rt->process_size.height, 0, GL_RG_INTEGER, GL_SHORT, nullptr); @@ -2380,6 +2386,7 @@ void TextureStorage::_render_target_allocate_sdf(RenderTarget *rt) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + GLES3::Utilities::get_singleton()->texture_allocated_data(rt->sdf_texture_process[1], rt->process_size.width * rt->process_size.height * 4, "SDF process texture[1]"); glGenTextures(1, &rt->sdf_texture_read); glBindTexture(GL_TEXTURE_2D, rt->sdf_texture_read); @@ -2390,13 +2397,16 @@ void TextureStorage::_render_target_allocate_sdf(RenderTarget *rt) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + GLES3::Utilities::get_singleton()->texture_allocated_data(rt->sdf_texture_read, rt->process_size.width * rt->process_size.height * 4, "SDF texture (read)"); } void TextureStorage::_render_target_clear_sdf(RenderTarget *rt) { if (rt->sdf_texture_write_fb != 0) { - glDeleteTextures(1, &rt->sdf_texture_read); - glDeleteTextures(1, &rt->sdf_texture_write); - glDeleteTextures(2, rt->sdf_texture_process); + GLES3::Utilities::get_singleton()->texture_free_data(rt->sdf_texture_read); + GLES3::Utilities::get_singleton()->texture_free_data(rt->sdf_texture_write); + GLES3::Utilities::get_singleton()->texture_free_data(rt->sdf_texture_process[0]); + GLES3::Utilities::get_singleton()->texture_free_data(rt->sdf_texture_process[1]); + glDeleteFramebuffers(1, &rt->sdf_texture_write_fb); rt->sdf_texture_read = 0; rt->sdf_texture_write = 0; diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index 2b939aa7fa5..7aa69d48bef 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -542,16 +542,12 @@ public: virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const override; void texture_set_data(RID p_texture, const Ref &p_image, int p_layer = 0); - void texture_set_data_partial(RID p_texture, const Ref &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0); - //Ref texture_get_data(RID p_texture, int p_layer = 0) const; - void texture_set_sampler(RID p_texture, RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat); Image::Format texture_get_format(RID p_texture) const; uint32_t texture_get_texid(RID p_texture) const; uint32_t texture_get_width(RID p_texture) const; uint32_t texture_get_height(RID p_texture) const; uint32_t texture_get_depth(RID p_texture) const; void texture_bind(RID p_texture, uint32_t p_texture_no); - RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const; /* TEXTURE ATLAS API */ diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp index 5f21d8f70a1..3e6e72edadb 100644 --- a/drivers/gles3/storage/utilities.cpp +++ b/drivers/gles3/storage/utilities.cpp @@ -67,6 +67,37 @@ Utilities::~Utilities() { for (int i = 0; i < FRAME_COUNT; i++) { glDeleteQueries(max_timestamp_query_elements, frames[i].queries); } + + if (texture_mem_cache) { + uint32_t leaked_data_size = 0; + for (const KeyValue &E : texture_allocs_cache) { +#ifdef DEV_ENABLED + ERR_PRINT(E.value.name + ": leaked " + itos(E.value.size) + " bytes."); +#else + ERR_PRINT("Texture with GL ID of " + itos(E.key) + ": leaked " + itos(E.value.size) + " bytes."); +#endif + leaked_data_size += E.value.size; + } + if (leaked_data_size < texture_mem_cache) { + ERR_PRINT("Texture cache is not empty. There may be an additional texture leak of " + itos(texture_mem_cache - leaked_data_size) + " bytes."); + } + } + + if (buffer_mem_cache) { + uint32_t leaked_data_size = 0; + + for (const KeyValue &E : buffer_allocs_cache) { +#ifdef DEV_ENABLED + ERR_PRINT(E.value.name + ": leaked " + itos(E.value.size) + " bytes."); +#else + ERR_PRINT("Buffer with GL ID of " + itos(E.key) + ": leaked " + itos(E.value.size) + " bytes."); +#endif + leaked_data_size += E.value.size; + } + if (leaked_data_size < buffer_mem_cache) { + ERR_PRINT("Buffer cache is not empty. There may be an additional buffer leak of " + itos(buffer_mem_cache - leaked_data_size) + " bytes."); + } + } } Vector Utilities::buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size) { @@ -324,6 +355,13 @@ void Utilities::update_memory_info() { } uint64_t Utilities::get_rendering_info(RS::RenderingInfo p_info) { + if (p_info == RS::RENDERING_INFO_TEXTURE_MEM_USED) { + return texture_mem_cache; + } else if (p_info == RS::RENDERING_INFO_BUFFER_MEM_USED) { + return buffer_mem_cache; + } else if (p_info == RS::RENDERING_INFO_VIDEO_MEM_USED) { + return texture_mem_cache + buffer_mem_cache; + } return 0; } diff --git a/drivers/gles3/storage/utilities.h b/drivers/gles3/storage/utilities.h index 92131aff8ca..243342014b1 100644 --- a/drivers/gles3/storage/utilities.h +++ b/drivers/gles3/storage/utilities.h @@ -48,6 +48,18 @@ class Utilities : public RendererUtilities { private: static Utilities *singleton; + struct ResourceAllocation { +#ifdef DEV_ENABLED + String name; +#endif + uint32_t size = 0; + }; + HashMap buffer_allocs_cache; + HashMap texture_allocs_cache; + + uint64_t buffer_mem_cache = 0; + uint64_t texture_mem_cache = 0; + public: static Utilities *get_singleton() { return singleton; } @@ -57,6 +69,58 @@ public: // Buffer size is specified in bytes static Vector buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size); + // Allocate memory with glBufferData. Does not handle resizing. + _FORCE_INLINE_ void buffer_allocate_data(GLenum p_target, GLuint p_id, uint32_t p_size, const void *p_data, GLenum p_usage, String p_name = "") { + glBufferData(p_target, p_size, p_data, p_usage); + buffer_mem_cache += p_size; + +#ifdef DEV_ENABLED + ERR_FAIL_COND_MSG(buffer_allocs_cache.has(p_id), "trying to allocate buffer with name " + p_name + " but ID already used by " + buffer_allocs_cache[p_id].name); +#endif + + ResourceAllocation resource_allocation; + resource_allocation.size = p_size; +#ifdef DEV_ENABLED + resource_allocation.name = p_name + ": " + itos((uint64_t)p_id); +#endif + buffer_allocs_cache[p_id] = resource_allocation; + } + + _FORCE_INLINE_ void buffer_free_data(GLuint p_id) { + ERR_FAIL_COND(!buffer_allocs_cache.has(p_id)); + glDeleteBuffers(1, &p_id); + buffer_mem_cache -= buffer_allocs_cache[p_id].size; + buffer_allocs_cache.erase(p_id); + } + + // Records that data was allocated for state tracking purposes. + _FORCE_INLINE_ void texture_allocated_data(GLuint p_id, uint32_t p_size, String p_name = "") { + texture_mem_cache += p_size; +#ifdef DEV_ENABLED + ERR_FAIL_COND_MSG(texture_allocs_cache.has(p_id), "trying to allocate texture with name " + p_name + " but ID already used by " + texture_allocs_cache[p_id].name); +#endif + ResourceAllocation resource_allocation; + resource_allocation.size = p_size; +#ifdef DEV_ENABLED + resource_allocation.name = p_name + ": " + itos((uint64_t)p_id); +#endif + texture_allocs_cache[p_id] = resource_allocation; + } + + _FORCE_INLINE_ void texture_free_data(GLuint p_id) { + ERR_FAIL_COND(!texture_allocs_cache.has(p_id)); + glDeleteTextures(1, &p_id); + texture_mem_cache -= texture_allocs_cache[p_id].size; + texture_allocs_cache.erase(p_id); + } + + _FORCE_INLINE_ void texture_resize_data(GLuint p_id, uint32_t p_size) { + ERR_FAIL_COND(!texture_allocs_cache.has(p_id)); + texture_mem_cache -= texture_allocs_cache[p_id].size; + texture_mem_cache += p_size; + texture_allocs_cache[p_id].size = p_size; + } + /* INSTANCES */ virtual RS::InstanceType get_base_type(RID p_rid) const override; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index c3e011b8121..7fad4061b19 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2817,7 +2817,7 @@ void Node3DEditorViewport::_notification(int p_what) { text += "\n"; text += vformat(TTR("Objects: %d\n"), viewport->get_render_info(Viewport::RENDER_INFO_TYPE_VISIBLE, Viewport::RENDER_INFO_OBJECTS_IN_FRAME)); - text += vformat(TTR("Primitive Indices: %d\n"), viewport->get_render_info(Viewport::RENDER_INFO_TYPE_VISIBLE, Viewport::RENDER_INFO_PRIMITIVES_IN_FRAME)); + text += vformat(TTR("Primitives: %d\n"), viewport->get_render_info(Viewport::RENDER_INFO_TYPE_VISIBLE, Viewport::RENDER_INFO_PRIMITIVES_IN_FRAME)); text += vformat(TTR("Draw Calls: %d"), viewport->get_render_info(Viewport::RENDER_INFO_TYPE_VISIBLE, Viewport::RENDER_INFO_DRAW_CALLS_IN_FRAME)); info_label->set_text(text); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index eea891792a0..4f47a80c13d 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -984,9 +984,9 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con to_draw = _indices_to_primitives(surf->primitive, to_draw); to_draw *= inst->instance_count; if (p_render_list == RENDER_LIST_OPAQUE) { //opaque - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += to_draw; } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += to_draw; } } } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 0b4157c5d63..77dd39b8d92 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -1884,9 +1884,9 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const to_draw = _indices_to_primitives(surf->primitive, to_draw); to_draw *= inst->instance_count; if (p_render_list == RENDER_LIST_OPAQUE) { //opaque - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += to_draw; } else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow - p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface); + p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += to_draw; } } } diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 8813c2e651e..71f6a28671f 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -1403,7 +1403,7 @@ void RendererViewport::call_set_vsync_mode(DisplayServer::VSyncMode p_mode, Disp int RendererViewport::get_total_objects_drawn() const { return total_objects_drawn; } -int RendererViewport::get_total_vertices_drawn() const { +int RendererViewport::get_total_primitives_drawn() const { return total_vertices_drawn; } int RendererViewport::get_total_draw_calls_used() const { diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index 2f9537a47c1..c004d05b23c 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -297,7 +297,7 @@ public: bool free(RID p_rid); int get_total_objects_drawn() const; - int get_total_vertices_drawn() const; + int get_total_primitives_drawn() const; int get_total_draw_calls_used() const; // Workaround for setting this on thread. diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 5f142453075..65bdb94c9f6 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -251,7 +251,7 @@ uint64_t RenderingServerDefault::get_rendering_info(RenderingInfo p_info) { if (p_info == RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME) { return RSG::viewport->get_total_objects_drawn(); } else if (p_info == RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME) { - return RSG::viewport->get_total_vertices_drawn(); + return RSG::viewport->get_total_primitives_drawn(); } else if (p_info == RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME) { return RSG::viewport->get_total_draw_calls_used(); }