Skip to content

Commit e696b9a

Browse files
committed
Disable GPU threaded optimizations option
We can disable indirectly by enabling verbose GL debug output.
1 parent 2f4336b commit e696b9a

File tree

6 files changed

+85
-0
lines changed

6 files changed

+85
-0
lines changed

core/os/os.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ class OS {
159159

160160
HasServerFeatureCallback has_server_feature_callback;
161161
RenderThreadMode _render_thread_mode;
162+
bool _disable_gpu_threaded_optimizations = false;
163+
bool _allow_gpu_threaded_optimizations = false;
162164

163165
// functions used by main to initialize/deinitialize the OS
164166
void add_logger(Logger *p_logger);
@@ -678,6 +680,12 @@ class OS {
678680
virtual void benchmark_end_measure(const String &p_what);
679681
virtual void benchmark_dump();
680682

683+
// Internal.
684+
// Disabling takes action to prevent GPU driver threaded optimizations to help prevent jitter.
685+
// Allow overrides "disable" and can be specified via the command line.
686+
bool _is_gpu_threaded_optimization_disabled() const { return _disable_gpu_threaded_optimizations; }
687+
void _set_gpu_threaded_optimization_allowed(bool p_allow) { _allow_gpu_threaded_optimizations = p_allow; }
688+
681689
virtual void process_and_drop_events() {}
682690
OS();
683691
virtual ~OS();

doc/classes/ProjectSettings.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,6 +1637,11 @@
16371637
<member name="rendering/limits/time/time_rollover_secs" type="float" setter="" getter="" default="3600">
16381638
Shaders have a time variable that constantly increases. At some point, it needs to be rolled back to zero to avoid precision errors on shader animations. This setting specifies when (in seconds).
16391639
</member>
1640+
<member name="rendering/misc/compatibility/driver_disable_threaded_optimizations" type="bool" setter="" getter="" default="true">
1641+
If [code]true[/code], attempts to disable the threaded optimization feature from the NVIDIA drivers, which are known to cause stuttering in most OpenGL applications.
1642+
This is done by enabling minimal OpenGL debug logging, and ignoring the output, which can force the driver to disable threaded optimization.
1643+
[b]Note:[/b] This setting only works on Windows, as threaded optimization is disabled by default on other platforms.
1644+
</member>
16401645
<member name="rendering/misc/lossless_compression/force_png" type="bool" setter="" getter="" default="false">
16411646
If [code]true[/code], the texture importer will import lossless textures using the PNG format. Otherwise, it will default to using WebP.
16421647
</member>

drivers/gles2/rasterizer_gles2.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@
8585
#endif
8686

8787
#ifdef CAN_DEBUG
88+
89+
// We offer the option to disable GPU threaded optimizations indirectly by forcing debug output.
90+
// We aren't actually interested in the strings in this case so we try and make the call as cheap as possible.
91+
static void GLAPIENTRY _gl_debug_print_dummy(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
92+
}
93+
8894
static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
8995
if (type == _EXT_DEBUG_TYPE_OTHER_ARB) {
9096
return;
@@ -216,6 +222,17 @@ Error RasterizerGLES2::is_viable() {
216222
void RasterizerGLES2::initialize() {
217223
print_verbose("Using GLES2 video driver");
218224

225+
// Use dummy OpenGL logging to indirectly disable threaded optimization if desired.
226+
bool disable_threaded_optimization = OS::get_singleton()->_is_gpu_threaded_optimization_disabled();
227+
if (disable_threaded_optimization) {
228+
String video_adapter = VisualServer::get_singleton()->get_video_adapter_name().to_lower();
229+
230+
// Only disable for nvidia currently.
231+
if (video_adapter.find("nvidia") == -1) {
232+
disable_threaded_optimization = false;
233+
}
234+
}
235+
219236
#ifdef GLAD_ENABLED
220237
if (OS::get_singleton()->is_stdout_verbose()) {
221238
if (GLAD_GL_ARB_debug_output) {
@@ -225,6 +242,14 @@ void RasterizerGLES2::initialize() {
225242
} else {
226243
print_line("OpenGL debugging not supported!");
227244
}
245+
} else if (disable_threaded_optimization) {
246+
if (GLAD_GL_ARB_debug_output) {
247+
glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
248+
glDebugMessageCallbackARB(_gl_debug_print_dummy, nullptr);
249+
glEnable(_EXT_DEBUG_OUTPUT);
250+
} else {
251+
print_line("Disabling GPU threaded optimization via OpenGL debugging not supported by this driver.");
252+
}
228253
}
229254
#endif // GLAD_ENABLED
230255

@@ -243,6 +268,9 @@ void RasterizerGLES2::initialize() {
243268
GL_DEBUG_TYPE_OTHER_ARB, 1,
244269
GL_DEBUG_SEVERITY_HIGH_ARB, 5, "hello");
245270
*/
271+
} else if (disable_threaded_optimization && GLAD_GL_ARB_debug_output) {
272+
// Try to enable the minimum debug output to disable threaded optimization.
273+
glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_ERROR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, nullptr, GL_TRUE);
246274
}
247275
#else
248276
if (OS::get_singleton()->is_stdout_verbose()) {
@@ -257,6 +285,18 @@ void RasterizerGLES2::initialize() {
257285
callback(_gl_debug_print, NULL);
258286
glEnable(_EXT_DEBUG_OUTPUT);
259287
}
288+
} else if (disable_threaded_optimization) {
289+
DebugMessageCallbackARB callback = (DebugMessageCallbackARB)eglGetProcAddress("glDebugMessageCallback");
290+
if (!callback) {
291+
callback = (DebugMessageCallbackARB)eglGetProcAddress("glDebugMessageCallbackKHR");
292+
}
293+
294+
if (callback) {
295+
print_line("godot: ENABLING GL DEBUG dummy output");
296+
glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
297+
callback(_gl_debug_print_dummy, NULL);
298+
glEnable(_EXT_DEBUG_OUTPUT);
299+
}
260300
}
261301
#endif // GLES_OVER_GL
262302
#endif // CAN_DEBUG

drivers/gles3/rasterizer_gles3.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ RasterizerScene *RasterizerGLES3::get_scene() {
7474
#endif
7575

7676
#ifdef GLAD_ENABLED
77+
// We offer the option to disable GPU threaded optimizations indirectly by forcing debug output.
78+
// We aren't actually interested in the strings in this case so we try and make the call as cheap as possible.
79+
static void GLAPIENTRY _gl_debug_print_dummy(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
80+
}
81+
7782
// Restricting to GLAD as only used in initialize() with GLAD_GL_ARB_debug_output
7883
static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
7984
if (type == _EXT_DEBUG_TYPE_OTHER_ARB) {
@@ -158,6 +163,17 @@ Error RasterizerGLES3::is_viable() {
158163
void RasterizerGLES3::initialize() {
159164
print_verbose("Using GLES3 video driver");
160165

166+
// Use dummy OpenGL logging to indirectly disable threaded optimization if desired.
167+
bool disable_threaded_optimization = OS::get_singleton()->_is_gpu_threaded_optimization_disabled();
168+
if (disable_threaded_optimization) {
169+
String video_adapter = VisualServer::get_singleton()->get_video_adapter_name().to_lower();
170+
171+
// Only disable for nvidia currently.
172+
if (video_adapter.find("nvidia") == -1) {
173+
disable_threaded_optimization = false;
174+
}
175+
}
176+
161177
#ifdef GLAD_ENABLED
162178
if (OS::get_singleton()->is_stdout_verbose()) {
163179
if (GLAD_GL_ARB_debug_output) {
@@ -167,6 +183,14 @@ void RasterizerGLES3::initialize() {
167183
} else {
168184
print_line("OpenGL debugging not supported!");
169185
}
186+
} else if (disable_threaded_optimization) {
187+
if (GLAD_GL_ARB_debug_output) {
188+
glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
189+
glDebugMessageCallbackARB(_gl_debug_print_dummy, nullptr);
190+
glEnable(_EXT_DEBUG_OUTPUT);
191+
} else {
192+
print_line("Disabling GPU threaded optimization via OpenGL debugging not supported by this driver.");
193+
}
170194
}
171195
#endif // GLAD_ENABLED
172196

main/main.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ void Main::print_help(const char *p_binary) {
332332
OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
333333
OS::get_singleton()->print(" --enable-delta-smoothing When vsync is enabled, enabled frame delta smoothing.\n");
334334
OS::get_singleton()->print(" --disable-delta-smoothing Disable frame delta smoothing.\n");
335+
OS::get_singleton()->print(" --allow-gpu-threaded Override the 'driver_disable_threaded_optimizations' project setting.\n");
335336
OS::get_singleton()->print(" --tablet-driver Tablet input driver (");
336337
for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
337338
if (i != 0) {
@@ -935,6 +936,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
935936
OS::get_singleton()->print("Missing editor PID argument, aborting.\n");
936937
goto error;
937938
}
939+
} else if (I->get() == "--allow-gpu-multithread") {
940+
OS::get_singleton()->_set_gpu_threaded_optimization_allowed(true);
938941
} else if (I->get() == "--disable-render-loop") {
939942
disable_render_loop = true;
940943
} else if (I->get() == "--fixed-fps") {
@@ -1246,6 +1249,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
12461249
rtm = GLOBAL_DEF("rendering/threads/thread_model", OS::RENDER_THREAD_SAFE);
12471250
}
12481251
GLOBAL_DEF("rendering/threads/thread_safe_bvh", false);
1252+
GLOBAL_DEF_RST("rendering/misc/compatibility/driver_disable_threaded_optimizations", true);
12491253

12501254
if (rtm >= 0 && rtm < 3) {
12511255
#ifdef NO_THREADS

platform/windows/os_windows.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,10 @@ int OS_Windows::get_current_video_driver() const {
13511351
}
13521352

13531353
Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
1354+
if (!Engine::get_singleton()->is_editor_hint()) {
1355+
_disable_gpu_threaded_optimizations = _allow_gpu_threaded_optimizations ? false : GLOBAL_GET("rendering/misc/compatibility/driver_disable_threaded_optimizations");
1356+
}
1357+
13541358
main_loop = NULL;
13551359
outside = true;
13561360
window_has_focus = true;

0 commit comments

Comments
 (0)