1
0
Fork 0

Merge pull request #67032 from clayjohn/GLES3-gpu-profiling

Add OpenGL timer queries to OpenGL3 backend
This commit is contained in:
Rémi Verschelde 2022-10-31 10:43:13 +01:00
commit 5a00568afb
No known key found for this signature in database
GPG Key ID: C3336907360768E1
3 changed files with 112 additions and 132 deletions

View File

@ -101,8 +101,7 @@ void RasterizerGLES3::begin_frame(double frame_step) {
scene->set_time(time_total, frame_step); scene->set_time(time_total, frame_step);
GLES3::Utilities *utils = GLES3::Utilities::get_singleton(); GLES3::Utilities *utils = GLES3::Utilities::get_singleton();
utils->info.render_final = utils->info.render; utils->_capture_timestamps_begin();
utils->info.render.reset();
//scene->iteration(); //scene->iteration();
} }
@ -272,6 +271,13 @@ RasterizerGLES3::~RasterizerGLES3() {
} }
void RasterizerGLES3::prepare_for_blitting_render_targets() { void RasterizerGLES3::prepare_for_blitting_render_targets() {
// This is a hack, but this function is called one time after all viewports have been updated.
// So it marks the end of the frame for all viewports
// In the OpenGL renderer we have to call end_frame for each viewport so we can swap the
// buffers for each window before proceeding to the next.
// This allows us to only increment the frame after all viewports are done.
GLES3::Utilities *utils = GLES3::Utilities::get_singleton();
utils->capture_timestamps_end();
} }
void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect, uint32_t p_layer) { void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect, uint32_t p_layer) {

View File

@ -38,16 +38,35 @@
#include "particles_storage.h" #include "particles_storage.h"
#include "texture_storage.h" #include "texture_storage.h"
#include "servers/rendering/rendering_server_globals.h"
using namespace GLES3; using namespace GLES3;
Utilities *Utilities::singleton = nullptr; Utilities *Utilities::singleton = nullptr;
Utilities::Utilities() { Utilities::Utilities() {
singleton = this; singleton = this;
frame = 0;
for (int i = 0; i < FRAME_COUNT; i++) {
frames[i].index = 0;
glGenQueries(max_timestamp_query_elements, frames[i].queries);
frames[i].timestamp_names.resize(max_timestamp_query_elements);
frames[i].timestamp_cpu_values.resize(max_timestamp_query_elements);
frames[i].timestamp_count = 0;
frames[i].timestamp_result_names.resize(max_timestamp_query_elements);
frames[i].timestamp_cpu_result_values.resize(max_timestamp_query_elements);
frames[i].timestamp_result_values.resize(max_timestamp_query_elements);
frames[i].timestamp_result_count = 0;
}
} }
Utilities::~Utilities() { Utilities::~Utilities() {
singleton = nullptr; singleton = nullptr;
for (int i = 0; i < FRAME_COUNT; i++) {
glDeleteQueries(max_timestamp_query_elements, frames[i].queries);
}
} }
Vector<uint8_t> Utilities::buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size) { Vector<uint8_t> Utilities::buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size) {
@ -213,87 +232,69 @@ void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_de
/* TIMING */ /* TIMING */
//void Utilities::render_info_begin_capture() { void Utilities::capture_timestamps_begin() {
// info.snap = info.render; capture_timestamp("Frame Begin");
//} }
//void Utilities::render_info_end_capture() { void Utilities::capture_timestamp(const String &p_name) {
// info.snap.object_count = info.render.object_count - info.snap.object_count; ERR_FAIL_COND(frames[frame].timestamp_count >= max_timestamp_query_elements);
// info.snap.draw_call_count = info.render.draw_call_count - info.snap.draw_call_count;
// info.snap.material_switch_count = info.render.material_switch_count - info.snap.material_switch_count;
// info.snap.surface_switch_count = info.render.surface_switch_count - info.snap.surface_switch_count;
// info.snap.shader_rebind_count = info.render.shader_rebind_count - info.snap.shader_rebind_count;
// info.snap.vertices_count = info.render.vertices_count - info.snap.vertices_count;
// info.snap._2d_item_count = info.render._2d_item_count - info.snap._2d_item_count;
// info.snap._2d_draw_call_count = info.render._2d_draw_call_count - info.snap._2d_draw_call_count;
//}
//int Utilities::get_captured_render_info(RS::RenderInfo p_info) { #ifdef GLES_OVER_GL
// switch (p_info) { glQueryCounter(frames[frame].queries[frames[frame].timestamp_count], GL_TIMESTAMP);
// case RS::INFO_OBJECTS_IN_FRAME: { #endif
// return info.snap.object_count;
// } break;
// case RS::INFO_VERTICES_IN_FRAME: {
// return info.snap.vertices_count;
// } break;
// case RS::INFO_MATERIAL_CHANGES_IN_FRAME: {
// return info.snap.material_switch_count;
// } break;
// case RS::INFO_SHADER_CHANGES_IN_FRAME: {
// return info.snap.shader_rebind_count;
// } break;
// case RS::INFO_SURFACE_CHANGES_IN_FRAME: {
// return info.snap.surface_switch_count;
// } break;
// case RS::INFO_DRAW_CALLS_IN_FRAME: {
// return info.snap.draw_call_count;
// } break;
// /*
// case RS::INFO_2D_ITEMS_IN_FRAME: {
// return info.snap._2d_item_count;
// } break;
// case RS::INFO_2D_DRAW_CALLS_IN_FRAME: {
// return info.snap._2d_draw_call_count;
// } break;
// */
// default: {
// return get_render_info(p_info);
// }
// }
//}
//int Utilities::get_render_info(RS::RenderInfo p_info) { frames[frame].timestamp_names[frames[frame].timestamp_count] = p_name;
// switch (p_info) { frames[frame].timestamp_cpu_values[frames[frame].timestamp_count] = OS::get_singleton()->get_ticks_usec();
// case RS::INFO_OBJECTS_IN_FRAME: frames[frame].timestamp_count++;
// return info.render_final.object_count; }
// case RS::INFO_VERTICES_IN_FRAME:
// return info.render_final.vertices_count; void Utilities::_capture_timestamps_begin() {
// case RS::INFO_MATERIAL_CHANGES_IN_FRAME: // frame is incremented at the end of the frame so this gives us the queries for frame - 2. By then they should be ready.
// return info.render_final.material_switch_count; if (frames[frame].timestamp_count) {
// case RS::INFO_SHADER_CHANGES_IN_FRAME: #ifdef GLES_OVER_GL
// return info.render_final.shader_rebind_count; for (uint32_t i = 0; i < frames[frame].timestamp_count; i++) {
// case RS::INFO_SURFACE_CHANGES_IN_FRAME: uint64_t temp = 0;
// return info.render_final.surface_switch_count; glGetQueryObjectui64v(frames[frame].queries[i], GL_QUERY_RESULT, &temp);
// case RS::INFO_DRAW_CALLS_IN_FRAME: frames[frame].timestamp_result_values[i] = temp;
// return info.render_final.draw_call_count; }
// /* #endif
// case RS::INFO_2D_ITEMS_IN_FRAME: SWAP(frames[frame].timestamp_names, frames[frame].timestamp_result_names);
// return info.render_final._2d_item_count; SWAP(frames[frame].timestamp_cpu_values, frames[frame].timestamp_cpu_result_values);
// case RS::INFO_2D_DRAW_CALLS_IN_FRAME: }
// return info.render_final._2d_draw_call_count;
//*/ frames[frame].timestamp_result_count = frames[frame].timestamp_count;
// case RS::INFO_USAGE_VIDEO_MEM_TOTAL: frames[frame].timestamp_count = 0;
// return 0; //no idea frames[frame].index = Engine::get_singleton()->get_frames_drawn();
// case RS::INFO_VIDEO_MEM_USED: capture_timestamp("Internal Begin");
// return info.vertex_mem + info.texture_mem; }
// case RS::INFO_TEXTURE_MEM_USED:
// return info.texture_mem; void Utilities::capture_timestamps_end() {
// case RS::INFO_VERTEX_MEM_USED: capture_timestamp("Internal End");
// return info.vertex_mem; frame = (frame + 1) % FRAME_COUNT;
// default: }
// return 0; //no idea either
// } uint32_t Utilities::get_captured_timestamps_count() const {
//} return frames[frame].timestamp_result_count;
}
uint64_t Utilities::get_captured_timestamps_frame() const {
return frames[frame].index;
}
uint64_t Utilities::get_captured_timestamp_gpu_time(uint32_t p_index) const {
ERR_FAIL_UNSIGNED_INDEX_V(p_index, frames[frame].timestamp_result_count, 0);
return frames[frame].timestamp_result_values[p_index];
}
uint64_t Utilities::get_captured_timestamp_cpu_time(uint32_t p_index) const {
ERR_FAIL_UNSIGNED_INDEX_V(p_index, frames[frame].timestamp_result_count, 0);
return frames[frame].timestamp_cpu_result_values[p_index];
}
String Utilities::get_captured_timestamp_name(uint32_t p_index) const {
ERR_FAIL_UNSIGNED_INDEX_V(p_index, frames[frame].timestamp_result_count, String());
return frames[frame].timestamp_result_names[p_index];
}
/* MISC */ /* MISC */

View File

@ -79,62 +79,35 @@ public:
/* TIMING */ /* TIMING */
struct Info { #define MAX_QUERIES 256
uint64_t texture_mem = 0; #define FRAME_COUNT 3
uint64_t vertex_mem = 0;
struct Render { struct Frame {
uint32_t object_count; GLuint queries[MAX_QUERIES];
uint32_t draw_call_count; TightLocalVector<String> timestamp_names;
uint32_t material_switch_count; TightLocalVector<uint64_t> timestamp_cpu_values;
uint32_t surface_switch_count; uint32_t timestamp_count = 0;
uint32_t shader_rebind_count; TightLocalVector<String> timestamp_result_names;
uint32_t vertices_count; TightLocalVector<uint64_t> timestamp_cpu_result_values;
uint32_t _2d_item_count; TightLocalVector<uint64_t> timestamp_result_values;
uint32_t _2d_draw_call_count; uint32_t timestamp_result_count = 0;
uint64_t index = 0;
};
void reset() { const uint32_t max_timestamp_query_elements = MAX_QUERIES;
object_count = 0;
draw_call_count = 0;
material_switch_count = 0;
surface_switch_count = 0;
shader_rebind_count = 0;
vertices_count = 0;
_2d_item_count = 0;
_2d_draw_call_count = 0;
}
} render, render_final, snap;
Info() { Frame frames[FRAME_COUNT]; // Frames for capturing timestamps. We use 3 so we don't need to wait for commands to complete
render.reset(); uint32_t frame = 0;
render_final.reset();
}
} info; virtual void capture_timestamps_begin() override;
virtual void capture_timestamp(const String &p_name) override;
virtual void capture_timestamps_begin() override {} virtual uint32_t get_captured_timestamps_count() const override;
virtual void capture_timestamp(const String &p_name) override {} virtual uint64_t get_captured_timestamps_frame() const override;
virtual uint32_t get_captured_timestamps_count() const override { virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override;
return 0; virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override;
} virtual String get_captured_timestamp_name(uint32_t p_index) const override;
virtual uint64_t get_captured_timestamps_frame() const override { void _capture_timestamps_begin();
return 0; void capture_timestamps_end();
}
virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override {
return 0;
}
virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override {
return 0;
}
virtual String get_captured_timestamp_name(uint32_t p_index) const override {
return String();
}
// void render_info_begin_capture() override;
// void render_info_end_capture() override;
// int get_captured_render_info(RS::RenderInfo p_info) override;
// int get_render_info(RS::RenderInfo p_info) override;
/* MISC */ /* MISC */