Skip to content

[3.x] Disable GPU threaded optimizations option #106556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: 3.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions core/os/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,10 @@ class OS {
virtual void benchmark_end_measure(const String &p_what);
virtual void benchmark_dump();

// Allow overrides "disable" and can be specified via the command line.
virtual bool _is_gdriver_threaded_optimization_allowed() const { return false; }
virtual void _set_gdriver_threaded_optimization_allowed(bool p_allow) {}

virtual void process_and_drop_events() {}
OS();
virtual ~OS();
Expand Down
5 changes: 5 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1637,6 +1637,11 @@
<member name="rendering/limits/time/time_rollover_secs" type="float" setter="" getter="" default="3600">
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).
</member>
<member name="rendering/misc/compatibility/driver_disable_threaded_optimizations" type="bool" setter="" getter="" default="true">
If [code]true[/code], attempts to disable the threaded optimization feature in NVIDIA drivers, which is known to cause stuttering in most OpenGL applications.
This is done by enabling minimal OpenGL debug logging, and ignoring the output, which can force the driver to disable threaded optimization.
[b]Note:[/b] This setting only works on Windows, as threaded optimization is disabled by default on other platforms.
</member>
<member name="rendering/misc/lossless_compression/force_png" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import lossless textures using the PNG format. Otherwise, it will default to using WebP.
</member>
Expand Down
49 changes: 49 additions & 0 deletions drivers/gles2/rasterizer_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@
#endif

#ifdef CAN_DEBUG

// We offer the option to disable GPU threaded optimizations indirectly by forcing debug output.
// We aren't actually interested in the strings in this case so we try and make the call as cheap as possible.
static void GLAPIENTRY _gl_debug_print_dummy(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
}

static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
if (type == _EXT_DEBUG_TYPE_OTHER_ARB) {
return;
Expand Down Expand Up @@ -216,6 +222,26 @@ Error RasterizerGLES2::is_viable() {
void RasterizerGLES2::initialize() {
print_verbose("Using GLES2 video driver");

// Use dummy OpenGL logging to indirectly disable threaded optimization if desired.
bool disable_threaded_optimization = false;

if (!OS::get_singleton()->is_stdout_verbose() && !Engine::get_singleton()->is_editor_hint() && OS::get_singleton()->get_name() == "Windows") {
disable_threaded_optimization = (bool)GLOBAL_GET("rendering/misc/compatibility/driver_disable_threaded_optimizations") && !OS::get_singleton()->_is_gdriver_threaded_optimization_allowed();

// Only disable for nvidia currently.
if (disable_threaded_optimization) {
String video_adapter = VisualServer::get_singleton()->get_video_adapter_name().to_lower();

if (video_adapter.find("nvidia") == -1) {
disable_threaded_optimization = false;
}

if (disable_threaded_optimization) {
print_line("Attempting to disable GPU Driver threaded optimization via OpenGL debugging : " + VisualServer::get_singleton()->get_video_adapter_name());
}
}
}

#ifdef GLAD_ENABLED
if (OS::get_singleton()->is_stdout_verbose()) {
if (GLAD_GL_ARB_debug_output) {
Expand All @@ -225,6 +251,14 @@ void RasterizerGLES2::initialize() {
} else {
print_line("OpenGL debugging not supported!");
}
} else if (disable_threaded_optimization) {
if (GLAD_GL_ARB_debug_output) {
glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
glDebugMessageCallbackARB(_gl_debug_print_dummy, nullptr);
glEnable(_EXT_DEBUG_OUTPUT);
} else {
print_line("Disabling GPU threaded optimization via OpenGL debugging not supported by this driver.");
}
}
#endif // GLAD_ENABLED

Expand All @@ -243,6 +277,9 @@ void RasterizerGLES2::initialize() {
GL_DEBUG_TYPE_OTHER_ARB, 1,
GL_DEBUG_SEVERITY_HIGH_ARB, 5, "hello");
*/
} else if (disable_threaded_optimization && GLAD_GL_ARB_debug_output) {
// Try to enable the minimum debug output to disable threaded optimization.
glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_ERROR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, nullptr, GL_TRUE);
}
#else
if (OS::get_singleton()->is_stdout_verbose()) {
Expand All @@ -257,6 +294,18 @@ void RasterizerGLES2::initialize() {
callback(_gl_debug_print, NULL);
glEnable(_EXT_DEBUG_OUTPUT);
}
} else if (disable_threaded_optimization) {
DebugMessageCallbackARB callback = (DebugMessageCallbackARB)eglGetProcAddress("glDebugMessageCallback");
if (!callback) {
callback = (DebugMessageCallbackARB)eglGetProcAddress("glDebugMessageCallbackKHR");
}

if (callback) {
print_line("godot: ENABLING GL DEBUG dummy output");
glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
callback(_gl_debug_print_dummy, NULL);
glEnable(_EXT_DEBUG_OUTPUT);
}
}
#endif // GLES_OVER_GL
#endif // CAN_DEBUG
Expand Down
33 changes: 33 additions & 0 deletions drivers/gles3/rasterizer_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ RasterizerScene *RasterizerGLES3::get_scene() {
#endif

#ifdef GLAD_ENABLED
// We offer the option to disable GPU threaded optimizations indirectly by forcing debug output.
// We aren't actually interested in the strings in this case so we try and make the call as cheap as possible.
static void GLAPIENTRY _gl_debug_print_dummy(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
}

// Restricting to GLAD as only used in initialize() with GLAD_GL_ARB_debug_output
static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) {
if (type == _EXT_DEBUG_TYPE_OTHER_ARB) {
Expand Down Expand Up @@ -158,6 +163,26 @@ Error RasterizerGLES3::is_viable() {
void RasterizerGLES3::initialize() {
print_verbose("Using GLES3 video driver");

// Use dummy OpenGL logging to indirectly disable threaded optimization if desired.
bool disable_threaded_optimization = false;

if (!OS::get_singleton()->is_stdout_verbose() && !Engine::get_singleton()->is_editor_hint() && OS::get_singleton()->get_name() == "Windows") {
disable_threaded_optimization = (bool)GLOBAL_GET("rendering/misc/compatibility/driver_disable_threaded_optimizations") && !OS::get_singleton()->_is_gdriver_threaded_optimization_allowed();

// Only disable for nvidia currently.
if (disable_threaded_optimization) {
String video_adapter = VisualServer::get_singleton()->get_video_adapter_name().to_lower();

if (video_adapter.find("nvidia") == -1) {
disable_threaded_optimization = false;
}
}

if (disable_threaded_optimization) {
print_line("Attempting to disable GPU Driver threaded optimization via OpenGL debugging : " + VisualServer::get_singleton()->get_video_adapter_name());
}
}

#ifdef GLAD_ENABLED
if (OS::get_singleton()->is_stdout_verbose()) {
if (GLAD_GL_ARB_debug_output) {
Expand All @@ -167,6 +192,14 @@ void RasterizerGLES3::initialize() {
} else {
print_line("OpenGL debugging not supported!");
}
} else if (disable_threaded_optimization) {
if (GLAD_GL_ARB_debug_output) {
glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
glDebugMessageCallbackARB(_gl_debug_print_dummy, nullptr);
glEnable(_EXT_DEBUG_OUTPUT);
} else {
print_line("Disabling GPU threaded optimization via OpenGL debugging not supported by this driver.");
}
}
#endif // GLAD_ENABLED

Expand Down
4 changes: 4 additions & 0 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
OS::get_singleton()->print(" --enable-delta-smoothing When vsync is enabled, enabled frame delta smoothing.\n");
OS::get_singleton()->print(" --disable-delta-smoothing Disable frame delta smoothing.\n");
OS::get_singleton()->print(" --allow-gpu-threaded Override the 'driver_disable_threaded_optimizations' project setting.\n");
OS::get_singleton()->print(" --tablet-driver Tablet input driver (");
for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
if (i != 0) {
Expand Down Expand Up @@ -935,6 +936,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->print("Missing editor PID argument, aborting.\n");
goto error;
}
} else if (I->get() == "--allow-gpu-threaded") {
OS::get_singleton()->_set_gdriver_threaded_optimization_allowed(true);
} else if (I->get() == "--disable-render-loop") {
disable_render_loop = true;
} else if (I->get() == "--fixed-fps") {
Expand Down Expand Up @@ -1246,6 +1249,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
rtm = GLOBAL_DEF("rendering/threads/thread_model", OS::RENDER_THREAD_SAFE);
}
GLOBAL_DEF("rendering/threads/thread_safe_bvh", false);
GLOBAL_DEF_RST("rendering/misc/compatibility/driver_disable_threaded_optimizations", true);

if (rtm >= 0 && rtm < 3) {
#ifdef NO_THREADS
Expand Down
5 changes: 5 additions & 0 deletions platform/windows/os_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,8 @@ class OS_Windows : public OS {

CrashHandler crash_handler;

bool _allow_gdriver_threaded_optimizations = false;

void _drag_event(float p_x, float p_y, int idx);
void _touch_event(bool p_pressed, float p_x, float p_y, int idx);

Expand Down Expand Up @@ -610,6 +612,9 @@ class OS_Windows : public OS {

virtual void process_and_drop_events();

virtual bool _is_gdriver_threaded_optimization_allowed() const { return _allow_gdriver_threaded_optimizations; }
virtual void _set_gdriver_threaded_optimization_allowed(bool p_allow) override { _allow_gdriver_threaded_optimizations = p_allow; }

OS_Windows(HINSTANCE _hInstance);
~OS_Windows();
};
Expand Down