diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml index 2d941405005..6ce847cd6ed 100644 --- a/doc/classes/VisualServer.xml +++ b/doc/classes/VisualServer.xml @@ -3719,28 +3719,34 @@ The amount of shader rebinds in the frame. - + + The peak amount of shaders that have been under compilation in the frame. + This is useful to know when asynchronous shader compilation has finished for the current shaders on screen. + [b]Note:[/b] For complete certainty, only assume there are no outstanding compilations when this value is zero for at least two frames in a row. + Unimplemented in the GLES2 rendering backend, always returns 0. + + The amount of surface changes in the frame. - + The amount of draw calls in frame. - + The amount of 2d items in the frame. - + The amount of 2d draw calls in frame. - + Unimplemented in the GLES2 and GLES3 rendering backends, always returns 0. - + The amount of video memory used, i.e. texture and vertex memory combined. - + The amount of texture memory used. - + The amount of vertex memory used. diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index bc4c3dde1fd..1d34c085f76 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -207,13 +207,13 @@ void RasterizerGLES3::begin_frame(double frame_step) { storage->frame.time[2] = Math::fmod(time_total, 900); storage->frame.time[3] = Math::fmod(time_total, 60); storage->frame.count++; - storage->frame.shader_compiles_started = 0; storage->frame.delta = frame_step; storage->update_dirty_resources(); storage->info.render_final = storage->info.render; storage->info.render.reset(); + storage->info.render.shader_compiles_in_progress_count = ShaderGLES3::active_compiles_count; ShaderGLES3::current_frame = storage->frame.count; @@ -493,7 +493,8 @@ RasterizerGLES3::RasterizerGLES3() { time_total = 0; time_scale = 1; - ShaderGLES3::compiles_started_this_frame = &storage->frame.shader_compiles_started; + ShaderGLES3::compiles_started_this_frame = &storage->info.render.shader_compiles_started_count; + ShaderGLES3::max_frame_compiles_in_progress = &storage->info.render.shader_compiles_in_progress_count; } RasterizerGLES3::~RasterizerGLES3() { diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 151e56f420b..8d36927f78f 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -7950,6 +7950,8 @@ void RasterizerStorageGLES3::render_info_end_capture() { 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.shader_compiles_started_count = info.render.shader_compiles_started_count - info.snap.shader_compiles_started_count; + info.snap.shader_compiles_in_progress_count = info.render.shader_compiles_in_progress_count - info.snap.shader_compiles_in_progress_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; @@ -7969,6 +7971,9 @@ int RasterizerStorageGLES3::get_captured_render_info(VS::RenderInfo p_info) { case VS::INFO_SHADER_CHANGES_IN_FRAME: { return info.snap.shader_rebind_count; } break; + case VS::INFO_SHADER_COMPILES_IN_FRAME: { + return info.snap.shader_compiles_in_progress_count; + } break; case VS::INFO_SURFACE_CHANGES_IN_FRAME: { return info.snap.surface_switch_count; } break; @@ -7997,6 +8002,8 @@ uint64_t RasterizerStorageGLES3::get_render_info(VS::RenderInfo p_info) { return info.render_final.material_switch_count; case VS::INFO_SHADER_CHANGES_IN_FRAME: return info.render_final.shader_rebind_count; + case VS::INFO_SHADER_COMPILES_IN_FRAME: + return info.render.shader_compiles_in_progress_count; case VS::INFO_SURFACE_CHANGES_IN_FRAME: return info.render_final.surface_switch_count; case VS::INFO_DRAW_CALLS_IN_FRAME: diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 5c28b5de750..a1c5e4774ae 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -164,6 +164,8 @@ public: uint32_t material_switch_count; uint32_t surface_switch_count; uint32_t shader_rebind_count; + uint32_t shader_compiles_started_count; + uint32_t shader_compiles_in_progress_count; uint32_t vertices_count; uint32_t _2d_item_count; uint32_t _2d_draw_call_count; @@ -174,6 +176,8 @@ public: material_switch_count = 0; surface_switch_count = 0; shader_rebind_count = 0; + shader_compiles_started_count = 0; + shader_compiles_in_progress_count = 0; vertices_count = 0; _2d_item_count = 0; _2d_draw_call_count = 0; @@ -1487,7 +1491,6 @@ public: float time[4]; float delta; uint64_t count; - int shader_compiles_started; } frame; diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index aa07e0e6454..d781f3dd031 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -64,13 +64,14 @@ ThreadedCallableQueue *ShaderGLES3::compile_queue; bool ShaderGLES3::parallel_compile_supported; bool ShaderGLES3::async_hidden_forbidden; -int *ShaderGLES3::compiles_started_this_frame; -int ShaderGLES3::max_simultaneous_compiles; +uint32_t *ShaderGLES3::compiles_started_this_frame; +uint32_t *ShaderGLES3::max_frame_compiles_in_progress; +uint32_t ShaderGLES3::max_simultaneous_compiles; +uint32_t ShaderGLES3::active_compiles_count; #ifdef DEBUG_ENABLED bool ShaderGLES3::log_active_async_compiles_count; #endif -int ShaderGLES3::active_compiles_count; uint64_t ShaderGLES3::current_frame; //#define DEBUG_SHADER @@ -210,7 +211,6 @@ void ShaderGLES3::advance_async_shaders_compilation() { void ShaderGLES3::_log_active_compiles() { #ifdef DEBUG_ENABLED if (log_active_async_compiles_count) { - ERR_FAIL_COND(active_compiles_count < 0); if (parallel_compile_supported) { print_line("Async. shader compiles: " + itos(active_compiles_count)); } else if (compile_queue) { @@ -240,9 +240,9 @@ bool ShaderGLES3::_process_program_state(Version *p_version, bool p_async_forbid // These lead to nowhere unless other piece of code starts the compile process } break; case Version::COMPILE_STATUS_SOURCE_PROVIDED: { - int start_compiles_count = p_async_forbidden ? 2 : 0; + uint32_t start_compiles_count = p_async_forbidden ? 2 : 0; if (!start_compiles_count) { - int free_async_slots = MAX(0, MIN(max_simultaneous_compiles - active_compiles_count, max_simultaneous_compiles - *compiles_started_this_frame)); + uint32_t free_async_slots = MAX(0, MIN(max_simultaneous_compiles - active_compiles_count, max_simultaneous_compiles - *compiles_started_this_frame)); start_compiles_count = MIN(2, free_async_slots); } if (start_compiles_count >= 1) { @@ -257,6 +257,7 @@ bool ShaderGLES3::_process_program_state(Version *p_version, bool p_async_forbid versions_compiling.add_last(&p_version->compiling_list); // Vertex and fragment shaders take independent compile slots active_compiles_count += start_compiles_count; + *max_frame_compiles_in_progress = MAX(*max_frame_compiles_in_progress, active_compiles_count); _log_active_compiles(); } (*compiles_started_this_frame) += start_compiles_count; @@ -274,6 +275,7 @@ bool ShaderGLES3::_process_program_state(Version *p_version, bool p_async_forbid glCompileShader(p_version->ids.frag); if (p_version->compiling_list.in_list()) { active_compiles_count++; + *max_frame_compiles_in_progress = MAX(*max_frame_compiles_in_progress, active_compiles_count); _log_active_compiles(); } p_version->compile_status = Version::COMPILE_STATUS_COMPILING_VERTEX_AND_FRAGMENT; @@ -299,6 +301,10 @@ bool ShaderGLES3::_process_program_state(Version *p_version, bool p_async_forbid glGetShaderiv(p_version->ids.vert, _EXT_COMPLETION_STATUS, &vertex_completed); if (p_version->compiling_list.in_list()) { active_compiles_count--; +#ifdef DEV_ENABLED + CRASH_COND(active_compiles_count == UINT32_MAX); +#endif + *max_frame_compiles_in_progress = MAX(*max_frame_compiles_in_progress, active_compiles_count); _log_active_compiles(); } p_version->compile_status = Version::COMPILE_STATUS_COMPILING_FRAGMENT; @@ -322,6 +328,9 @@ bool ShaderGLES3::_process_program_state(Version *p_version, bool p_async_forbid if (p_version->compiling_list.in_list()) { p_version->compiling_list.remove_from_list(); active_compiles_count--; +#ifdef DEV_ENABLED + CRASH_COND(active_compiles_count == UINT32_MAX); +#endif _log_active_compiles(); } } @@ -334,6 +343,9 @@ bool ShaderGLES3::_process_program_state(Version *p_version, bool p_async_forbid p_version->compile_status = Version::COMPILE_STATUS_ERROR; p_version->compiling_list.remove_from_list(); active_compiles_count--; +#ifdef DEV_ENABLED + CRASH_COND(active_compiles_count == UINT32_MAX); +#endif _log_active_compiles(); } break; case 0: { // In progress @@ -361,6 +373,7 @@ bool ShaderGLES3::_process_program_state(Version *p_version, bool p_async_forbid if (!p_async_forbidden) { versions_compiling.add_last(&p_version->compiling_list); active_compiles_count++; + *max_frame_compiles_in_progress = MAX(*max_frame_compiles_in_progress, active_compiles_count); _log_active_compiles(); (*compiles_started_this_frame)++; } @@ -425,6 +438,9 @@ bool ShaderGLES3::_process_program_state(Version *p_version, bool p_async_forbid if (p_version->compiling_list.in_list()) { p_version->compiling_list.remove_from_list(); active_compiles_count--; +#ifdef DEV_ENABLED + CRASH_COND(active_compiles_count == UINT32_MAX); +#endif _log_active_compiles(); } } @@ -818,6 +834,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version(bool &r_async_forbidden) v.compile_status = Version::COMPILE_STATUS_PROCESSING_AT_QUEUE; versions_compiling.add_last(&v.compiling_list); active_compiles_count++; + *max_frame_compiles_in_progress = MAX(*max_frame_compiles_in_progress, active_compiles_count); _log_active_compiles(); (*compiles_started_this_frame)++; @@ -1065,13 +1082,18 @@ void ShaderGLES3::_dispose_program(Version *p_version) { if (p_version->compiling_list.in_list()) { p_version->compiling_list.remove_from_list(); active_compiles_count--; +#ifdef DEV_ENABLED + CRASH_COND(active_compiles_count == UINT32_MAX); +#endif if (p_version->compile_status == Version::COMPILE_STATUS_COMPILING_VERTEX_AND_FRAGMENT) { active_compiles_count--; +#ifdef DEV_ENABLED + CRASH_COND(active_compiles_count == UINT32_MAX); +#endif } _log_active_compiles(); } p_version->compile_status = Version::COMPILE_STATUS_ERROR; - ERR_FAIL_COND(active_compiles_count < 0); } GLint ShaderGLES3::get_uniform_location(const String &p_name) const { diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 6b77b4ce488..490a95c9621 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -132,8 +132,10 @@ public: static bool parallel_compile_supported; // True if using natively supported asyncrhonous compilation static bool async_hidden_forbidden; - static int *compiles_started_this_frame; - static int max_simultaneous_compiles; + static uint32_t *compiles_started_this_frame; + static uint32_t *max_frame_compiles_in_progress; + static uint32_t max_simultaneous_compiles; + static uint32_t active_compiles_count; #ifdef DEBUG_ENABLED static bool log_active_async_compiles_count; #endif @@ -142,8 +144,6 @@ public: static void advance_async_shaders_compilation(); private: - static int active_compiles_count; - union VersionKey { static const uint32_t UBERSHADER_FLAG = ((uint32_t)1) << 31; struct { diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index affb6152111..dfbc7aae49b 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -2465,6 +2465,7 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(INFO_VERTICES_IN_FRAME); BIND_ENUM_CONSTANT(INFO_MATERIAL_CHANGES_IN_FRAME); BIND_ENUM_CONSTANT(INFO_SHADER_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_SHADER_COMPILES_IN_FRAME); BIND_ENUM_CONSTANT(INFO_SURFACE_CHANGES_IN_FRAME); BIND_ENUM_CONSTANT(INFO_DRAW_CALLS_IN_FRAME); BIND_ENUM_CONSTANT(INFO_2D_ITEMS_IN_FRAME); diff --git a/servers/visual_server.h b/servers/visual_server.h index 832bae02006..1a5d009d62d 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -1147,6 +1147,7 @@ public: INFO_VERTICES_IN_FRAME, INFO_MATERIAL_CHANGES_IN_FRAME, INFO_SHADER_CHANGES_IN_FRAME, + INFO_SHADER_COMPILES_IN_FRAME, INFO_SURFACE_CHANGES_IN_FRAME, INFO_DRAW_CALLS_IN_FRAME, INFO_2D_ITEMS_IN_FRAME,