Merge pull request #77536 from clayjohn/GLES3-render-info

Add RENDERING_INFO parameters to GL Compatibility renderer
This commit is contained in:
Rémi Verschelde 2023-06-16 10:19:09 +02:00
commit 908610174d
No known key found for this signature in database
GPG key ID: C3336907360768E1
17 changed files with 336 additions and 242 deletions

View file

@ -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.

View file

@ -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

View file

@ -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;
}

View file

@ -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;

View file

@ -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() {

View file

@ -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));

View file

@ -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;

View file

@ -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;

View file

@ -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 */

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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 {

View file

@ -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.

View file

@ -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();
}