Skip to content

Commit

Permalink
Merge pull request godotengine#5 from Ansraer/profiling
Browse files Browse the repository at this point in the history
Add profiling information to the renderer
  • Loading branch information
hpvb committed May 9, 2023
2 parents d6eab5d + e352a2b commit 7800b10
Show file tree
Hide file tree
Showing 12 changed files with 600 additions and 81 deletions.
13 changes: 13 additions & 0 deletions drivers/gles2/rasterizer_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,19 @@ void RasterizerGLES2::initialize() {
print_line("OpenGL debugging not supported!");
}
}
if (GLAD_GL_KHR_debug) {
push_label_func = glPushDebugGroup;
pop_label_func = glPopDebugGroup;
khr_debug_enabled = true;
}
if (GLAD_GL_ARB_timer_query) {
gen_queries_func = glGenQueries;
del_queries_func = glGenQueries;
query_counter_func = glQueryCounter;
get_query_func = glGetQueryObjectui64v;
enable_frame_timings();
}
#else
#endif // GLAD_ENABLED

// For debugging
Expand Down
14 changes: 13 additions & 1 deletion drivers/gles2/rasterizer_scene_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3542,13 +3542,19 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
}

// render opaque things first
SECTION_START("OPAQUE");
TIMESTAMP("opaque");
render_list.sort_by_key(false);
_render_render_list(render_list.elements, render_list.element_count, cam_transform, p_cam_projection, p_eye, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, false, false);
SECTION_END();

// then draw the sky after
if (env && env->bg_mode == VS::ENV_BG_SKY && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) {
if (sky && sky->panorama.is_valid()) {
SECTION_START("SKY");
TIMESTAMP("sky");
_draw_sky(sky, p_cam_projection, cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation);
SECTION_END();
}
}

Expand Down Expand Up @@ -3596,16 +3602,22 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const

render_list.sort_by_reverse_depth_and_priority(true);

SECTION_START("ALPHA");
TIMESTAMP("alpha");
_render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, cam_transform, p_cam_projection, p_eye, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, true, false);
SECTION_END();

if (p_reflection_probe.is_valid()) {
// Rendering to a probe so no need for post_processing
return;
}

//post process
SECTION_START("POST PROCESS");
TIMESTAMP("post_process");
_post_process(env, p_cam_projection);

SECTION_END();
TIMESTAMP_END();
//#define GLES2_SHADOW_ATLAS_DEBUG_VIEW

#ifdef GLES2_SHADOW_ATLAS_DEBUG_VIEW
Expand Down
50 changes: 49 additions & 1 deletion drivers/gles3/rasterizer_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
#include "core/os/os.h"
#include "core/project_settings.h"

#ifdef ANDROID_ENABLED
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif

RasterizerStorage *RasterizerGLES3::get_storage() {
return storage;
}
Expand Down Expand Up @@ -168,7 +173,50 @@ void RasterizerGLES3::initialize() {
print_line("OpenGL debugging not supported!");
}
}
#endif // GLAD_ENABLED
if (GLAD_GL_KHR_debug) {
push_label_func = glPushDebugGroup;
pop_label_func = glPopDebugGroup;
khr_debug_enabled = true;
}
if (GLAD_GL_ARB_timer_query) {
gen_queries_func = glGenQueries;
del_queries_func = glGenQueries;
query_counter_func = glQueryCounter;
get_query_func = glGetQueryObjectui64v;
enable_frame_timings();
}
#else // GLAD_ENABLED

// While we use GLAD for the desktop platforms we have to do this manually for mobile.
#ifdef ANDROID_ENABLED

GLint extension_count = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &extension_count);

bool found_arb_timer_query = false;

for (int i = 0; i < extension_count; ++i) {
if (strcmp((const char *)glGetStringi(GL_EXTENSIONS, i), "GL_KHR_debug") == 0) {
khr_debug_enabled = true;
} else if (strcmp((const char *)glGetStringi(GL_EXTENSIONS, i), "GL_ARB_timer_query") == 0) {
found_arb_timer_query = true;
}
}
if (khr_debug_enabled) {
//These might need a KHR suffix, see https://registry.khronos.org/OpenGL/extensions/KHR/KHR_debug.txt
push_label_func = (void (*)(unsigned int, unsigned int, int, const char *))eglGetProcAddress("glPushDebugGroup");
pop_label_func = eglGetProcAddress("glPopDebugGroup");
}
if (found_arb_timer_query) {
gen_queries_func = (void (*)(int, unsigned int *))eglGetProcAddress("glGenQueries");
del_queries_func = (void (*)(int, unsigned int *))eglGetProcAddress("glDeleteQueries");
query_counter_func = (void (*)(unsigned int, unsigned int))eglGetProcAddress("glQueryCounter");
get_query_func = (void (*)(unsigned int, unsigned int, uint64_t *))eglGetProcAddress("glGetQueryObjectui64v");
enable_frame_timings();
}

#endif
#endif // not GLAD_ENABLED

/* // For debugging
if (GLAD_GL_ARB_debug_output) {
Expand Down
17 changes: 17 additions & 0 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4188,6 +4188,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const

if (use_depth_prepass) {
//pre z pass
SECTION_START("DEPTH PREPASS");
TIMESTAMP("depth_prepass");

glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
Expand Down Expand Up @@ -4216,6 +4218,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
_bind_depth_texture();
}

SECTION_END();
fb_cleared = true;
render_pass++;
state.used_depth_prepass = true;
Expand Down Expand Up @@ -4483,6 +4486,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const

render_list.sort_by_key(false);

SECTION_START("OPAQUE");
TIMESTAMP("opaque");
if (state.directional_light_count == 0) {
directional_light = nullptr;
_render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, false, use_shadows);
Expand All @@ -4496,6 +4501,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
_render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, i > 0, use_shadows);
}
}
SECTION_END();

state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, false);

Expand All @@ -4511,7 +4517,10 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
*/

if (sky && sky->panorama.is_valid()) {
SECTION_START("SKY");
TIMESTAMP("sky");
_draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation);
SECTION_END();
}
}

Expand Down Expand Up @@ -4568,6 +4577,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const

render_list.sort_by_reverse_depth_and_priority(true);

SECTION_START("ALPHA");
TIMESTAMP("alpha");
if (state.directional_light_count <= 1) {
if (state.directional_light_count == 1) {
directional_light = directional_lights[0];
Expand Down Expand Up @@ -4614,6 +4625,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
}
}
}
SECTION_END();

if (probe) {
//rendering a probe, do no more!
Expand All @@ -4623,7 +4635,12 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
if (env && (env->dof_blur_far_enabled || env->dof_blur_near_enabled) && storage->frame.current_rt && storage->frame.current_rt->buffers.active) {
_prepare_depth_texture();
}
SECTION_START("POST PROCESS");
TIMESTAMP("post_process");
_post_process(env, p_cam_projection);
SECTION_END();
TIMESTAMP_END();

// Needed only for debugging
/* if (shadow_atlas && storage->frame.current_rt) {
Expand Down
113 changes: 113 additions & 0 deletions servers/visual/rasterizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,123 @@

Rasterizer *(*Rasterizer::_create_func)() = nullptr;

bool Rasterizer::khr_debug_enabled = false;
void (*Rasterizer::push_label_func)(unsigned int source, unsigned int id, int length, const char *message) = nullptr;
void (*Rasterizer::pop_label_func)() = nullptr;

void (*Rasterizer::gen_queries_func)(int n, unsigned int *ids) = nullptr;
void (*Rasterizer::del_queries_func)(int n, unsigned int *ids) = nullptr;
void (*Rasterizer::query_counter_func)(unsigned int id, unsigned int target) = nullptr;
void (*Rasterizer::get_query_func)(unsigned int id, unsigned int pname, uint64_t *params) = nullptr;

Rasterizer *Rasterizer::create() {
return _create_func();
}

void Rasterizer::push_label(String p_label) {
if (khr_debug_enabled) {
push_label_func(0x824A, 1, p_label.length(), p_label.utf8().get_data());
}
}

void Rasterizer::pop_label() {
if (khr_debug_enabled) {
pop_label_func();
}
}

bool Rasterizer::frame_timing_enabled = false;

void Rasterizer::enable_frame_timings() {
if (!frame_timing_enabled) {
// Setup the frame timing querys
for (int i = 0; i < FRAME_TIMING_COUNT; i++) {
frame_timings[i].query_count = 0;
gen_queries_func(MAX_QUERIES, frame_timings[i].queries);
frame_timings[i].query_names.resize(MAX_QUERIES);
frame_timings[i].query_results.resize(MAX_QUERIES);
}
frame_timing_enabled = true;
}
}

void Rasterizer::begin_frame_timings() {
if (!frame_timing_enabled)
return;

frame = (frame + 1) % FRAME_TIMING_COUNT;
if (frame_timings[frame].query_count) {
//We have written to this struct before, by now the results should be ready
frame_timings[frame].result_count = frame_timings[frame].query_count;

uint64_t prev_time = 0;
uint64_t cur_time = 0;
for (uint32_t i = 0; i < frame_timings[frame].query_count; i++) {
//get_query_func(frame_timings[frame].queries[i], GL_QUERY_RESULT, &frame_timings[frame].query_results[i]);
get_query_func(frame_timings[frame].queries[i], GL_QUERY_RESULT, &cur_time);
//frame_timings[frame].query_results[i] = result;
if (i > 0) {
//turn the timestamps into durations
frame_timings[frame].query_results[i - 1] = cur_time - prev_time;
}

prev_time = cur_time;
}

//Send the data to the profiler
#ifdef DEBUG_ENABLED
if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_profiling()) {
Array values;

// sum results based on name (since parts of the render pipeline may run more than once due to viewports)
for (uint32_t i = 0; i < frame_timings[frame].query_count - 1; i++) {
String name = frame_timings[frame].query_names[i];
if (name == "END_TIMESTAMP")
continue;

uint64_t time = frame_timings[frame].query_results[i];

if (time != 0) {
for (uint32_t j = i + 1; j < frame_timings[frame].query_count - 1; j++) {
if (frame_timings[frame].query_names[j] == name) {
time += frame_timings[frame].query_results[j];
frame_timings[frame].query_results[j] = 0;
}
}
float time_ms = USEC_TO_SEC(time / 1000);
values.push_back(name);
values.push_back(time_ms);
}
}

ScriptDebugger::get_singleton()->add_profiling_frame_data("rendering", values);
}
#endif
}
frame_timings[frame].query_count = 0;
}

void Rasterizer::timestamp(const String &p_name) {
if (!frame_timing_enabled)
return;

int query_index = frame_timings[frame].query_count;

ERR_FAIL_COND_MSG(query_index >= MAX_QUERIES, "Attempting to take too many rendering timestamp: increase MAX_QUERIES");

query_counter_func(frame_timings[frame].queries[query_index], GL_TIMESTAMP);
frame_timings[frame].query_names[query_index] = p_name;
frame_timings[frame].query_count++;
}

Rasterizer::~Rasterizer() {
if (frame_timing_enabled) {
for (int i = 0; i < FRAME_TIMING_COUNT; i++) {
del_queries_func(MAX_QUERIES, frame_timings[i].queries);
}
}
}

RasterizerStorage *RasterizerStorage::base_singleton = nullptr;

RasterizerStorage::RasterizerStorage() {
Expand Down
Loading

0 comments on commit 7800b10

Please sign in to comment.