diff options
-rw-r--r-- | doc/classes/RenderingServer.xml | 8 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 59 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 122 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 1 | ||||
-rw-r--r-- | drivers/gles3/storage/light_storage.cpp | 100 | ||||
-rw-r--r-- | drivers/gles3/storage/mesh_storage.cpp | 46 | ||||
-rw-r--r-- | drivers/gles3/storage/particles_storage.cpp | 44 | ||||
-rw-r--r-- | drivers/gles3/storage/texture_storage.cpp | 76 | ||||
-rw-r--r-- | drivers/gles3/storage/texture_storage.h | 4 | ||||
-rw-r--r-- | drivers/gles3/storage/utilities.cpp | 38 | ||||
-rw-r--r-- | drivers/gles3/storage/utilities.h | 64 | ||||
-rw-r--r-- | editor/plugins/node_3d_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp | 4 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp | 4 | ||||
-rw-r--r-- | servers/rendering/renderer_viewport.cpp | 2 | ||||
-rw-r--r-- | servers/rendering/renderer_viewport.h | 2 | ||||
-rw-r--r-- | servers/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 6b65302a7d..0f2a6d649f 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -4575,7 +4575,7 @@ Number of objects drawn in a single frame. </constant> <constant name="VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME" value="1" enum="ViewportRenderInfo"> - Number of vertices drawn in a single frame. + Number of points, lines, or triangles drawn in a single frame. </constant> <constant name="VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME" value="2" enum="ViewportRenderInfo"> 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. </constant> <constant name="RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME" value="1" enum="RenderingInfo"> - 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. </constant> <constant name="RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME" value="2" enum="RenderingInfo"> 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). </constant> <constant name="RENDERING_INFO_BUFFER_MEM_USED" value="4" enum="RenderingInfo"> - Buffer memory used (in bytes). + Buffer memory used (in bytes). This includes vertex data, uniform buffers, and many miscellaneous buffer types used internally. </constant> <constant name="RENDERING_INFO_VIDEO_MEM_USED" value="5" enum="RenderingInfo"> - 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]. </constant> <constant name="FEATURE_SHADERS" value="0" enum="Features"> 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 59a65b4538..86405fa3f0 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 3d8f7924a7..6ed5b3b2f8 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<RenderSceneBuffers> &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<GLES3::LightInstance>, 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<GLES3::LightInstance>, 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 b4e787ad85..9709d6be2a 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 8da5e657cd..5aab91e8ae 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<Vector2> &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<float> geometry; - PoolVector<uint16_t> indices; - int lc = p_lines.size(); - - geometry.resize(lc * 6); - indices.resize(lc * 3); - - PoolVector<float>::Write vw = geometry.write(); - PoolVector<uint16_t>::Write iw = indices.write(); - - PoolVector<Vector2>::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 585ed5ff96..8a027aad1c 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 4b64e2aec1..dbd86451d2 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<ParticleProcessMaterialData *>(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 c4fef89cfd..05b4443963 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<Image> &p_im texture.type = Texture::TYPE_2D; texture.target = GL_TEXTURE_2D; _get_gl_image_and_format(Ref<Image>(), 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<R texture.target = p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D_ARRAY; texture.layers = p_layers.size(); _get_gl_image_and_format(Ref<Image>(), 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<Image> &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<Image> &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<Image> 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<Image> &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<Image> &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 2b939aa7fa..7aa69d48be 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<Image> &p_image, int p_layer = 0); - void texture_set_data_partial(RID p_texture, const Ref<Image> &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<Image> 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 5f21d8f70a..3e6e72edad 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<GLuint, ResourceAllocation> &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<GLuint, ResourceAllocation> &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<uint8_t> 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 92131aff8c..243342014b 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<GLuint, ResourceAllocation> buffer_allocs_cache; + HashMap<GLuint, ResourceAllocation> 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<uint8_t> 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 c3e011b812..7fad4061b1 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 eea891792a..4f47a80c13 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 0b4157c5d6..77dd39b8d9 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 8813c2e651..71f6a28671 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 2f9537a47c..c004d05b23 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 5f14245307..65bdb94c9f 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(); } |