From 38683ee221e6fbc364373ca4b76c8bec36af79b7 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 30 Jun 2022 09:49:29 +0200 Subject: [PATCH] Tech ENABLE_OPENGL_DEBUG_OPTION - Add new command line option '--opengl-debug' to allow users to force PrusaSlicer to output to console OpenGL related errors on graphics cards supporting it. --- src/PrusaSlicer.cpp | 17 ++++++- src/libslic3r/PrintConfig.cpp | 8 ++++ src/libslic3r/Technologies.hpp | 2 + src/slic3r/GUI/GUI_App.cpp | 4 ++ src/slic3r/GUI/GUI_Init.hpp | 3 ++ src/slic3r/GUI/OpenGLManager.cpp | 80 +++++++++++++++++++++++++++++++- src/slic3r/GUI/OpenGLManager.hpp | 7 +++ 7 files changed, 118 insertions(+), 3 deletions(-) diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index a2f7b7c62..9cb2cea75 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -122,6 +122,9 @@ int CLI::run(int argc, char **argv) #endif // _WIN32 #if ENABLE_GL_CORE_PROFILE std::pair opengl_version = { 0, 0 }; +#if ENABLE_OPENGL_DEBUG_OPTION + bool opengl_debug = false; +#endif // ENABLE_OPENGL_DEBUG_OPTION #endif // ENABLE_GL_CORE_PROFILE const std::vector &load_configs = m_config.option("load", true)->values; @@ -173,7 +176,7 @@ int CLI::run(int argc, char **argv) it = std::find(m_actions.begin(), m_actions.end(), "opengl-core"); if (it != m_actions.end()) { std::string opengl_version_str = m_config.opt_string("opengl-core"); - const std::vector valid_versions = { "3.3", "4.0", "4.1", "4.2", "4.3", "4.4", "4.5", "4.6" }; + const std::vector valid_versions = { "3.2", "3.3", "4.0", "4.1", "4.2", "4.3", "4.4", "4.5", "4.6" }; if (std::find(valid_versions.begin(), valid_versions.end(), opengl_version_str) == valid_versions.end()) { boost::nowide::cerr << "Found invalid OpenGL version: " << opengl_version_str << std::endl; opengl_version_str.clear(); @@ -188,6 +191,15 @@ int CLI::run(int argc, char **argv) start_gui = true; m_actions.erase(it); } + +#if ENABLE_OPENGL_DEBUG_OPTION + it = std::find(m_actions.begin(), m_actions.end(), "opengl-debug"); + if (it != m_actions.end()) { + start_gui = true; + opengl_debug = true; + m_actions.erase(it); + } +#endif // ENABLE_OPENGL_DEBUG_OPTION #else // are we starting as gcodeviewer ? for (auto it = m_actions.begin(); it != m_actions.end(); ++it) { @@ -650,6 +662,9 @@ int CLI::run(int argc, char **argv) params.start_as_gcodeviewer = start_as_gcodeviewer; #if ENABLE_GL_CORE_PROFILE params.opengl_version = opengl_version; +#if ENABLE_OPENGL_DEBUG_OPTION + params.opengl_debug = opengl_debug; +#endif // ENABLE_OPENGL_DEBUG_OPTION #endif // ENABLE_GL_CORE_PROFILE return Slic3r::GUI::GUI_Run(params); #else // SLIC3R_GUI diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 96786ccde..038f99a37 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -4310,6 +4310,14 @@ CLIActionsConfigDef::CLIActionsConfigDef() def->tooltip = L("Select the specified OpenGL version supporting core profile"); def->cli = "opengl-core"; def->set_default_value(new ConfigOptionString()); + +#if ENABLE_OPENGL_DEBUG_OPTION + def = this->add("opengl-debug", coBool); + def->label = L("OpenGL debug output"); + def->tooltip = L("Activate OpenGL debug output on graphic cards which support it"); + def->cli = "opengl-debug"; + def->set_default_value(new ConfigOptionBool(false)); +#endif // ENABLE_OPENGL_DEBUG_OPTION #endif // ENABLE_GL_CORE_PROFILE def = this->add("slice", coBool); diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 71d679f98..01b3bb2eb 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -57,6 +57,8 @@ #define ENABLE_LEGACY_OPENGL_REMOVAL (1 && ENABLE_2_5_0_ALPHA1) // Enable OpenGL core profile context (tested against Mesa 20.1.8 on Windows) #define ENABLE_GL_CORE_PROFILE (1 && ENABLE_LEGACY_OPENGL_REMOVAL) +// Enable OpenGL debug messages using debug context +#define ENABLE_OPENGL_DEBUG_OPTION (1 && ENABLE_GL_CORE_PROFILE) // Shows an imgui dialog with GLModel statistics data #define ENABLE_GLMODEL_STATISTICS (0 && ENABLE_LEGACY_OPENGL_REMOVAL) // Enable show non-manifold edges diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 7d55e5b14..53aae38bb 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -848,7 +848,11 @@ std::string GUI_App::get_gl_info(bool for_github) wxGLContext* GUI_App::init_glcontext(wxGLCanvas& canvas) { #if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_DEBUG_OPTION + return m_opengl_mgr.init_glcontext(canvas, init_params != nullptr ? init_params->opengl_version : std::make_pair(0, 0), init_params->opengl_debug); +#else return m_opengl_mgr.init_glcontext(canvas, init_params != nullptr ? init_params->opengl_version : std::make_pair(0, 0)); +#endif // ENABLE_OPENGL_DEBUG_OPTION #else return m_opengl_mgr.init_glcontext(canvas); #endif // ENABLE_GL_CORE_PROFILE diff --git a/src/slic3r/GUI/GUI_Init.hpp b/src/slic3r/GUI/GUI_Init.hpp index 44bcd00c8..d3ababe24 100644 --- a/src/slic3r/GUI/GUI_Init.hpp +++ b/src/slic3r/GUI/GUI_Init.hpp @@ -23,6 +23,9 @@ struct GUI_InitParams bool start_as_gcodeviewer; #if ENABLE_GL_CORE_PROFILE std::pair opengl_version; +#if ENABLE_OPENGL_DEBUG_OPTION + bool opengl_debug; +#endif // ENABLE_OPENGL_DEBUG_OPTION #endif // ENABLE_GL_CORE_PROFILE }; diff --git a/src/slic3r/GUI/OpenGLManager.cpp b/src/slic3r/GUI/OpenGLManager.cpp index b4729335a..41a11eda4 100644 --- a/src/slic3r/GUI/OpenGLManager.cpp +++ b/src/slic3r/GUI/OpenGLManager.cpp @@ -273,6 +273,48 @@ OpenGLManager::~OpenGLManager() #endif //__APPLE__ } +#if ENABLE_OPENGL_DEBUG_OPTION +static void APIENTRY CustomGLDebugOutput(GLenum source, GLenum type, unsigned int id, GLenum severity, GLsizei length, const char* message, const void* userParam) +{ + if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) + return; + + std::string out = "OpenGL DEBUG message ["; + switch (type) + { + case GL_DEBUG_TYPE_ERROR: out += "Error"; break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: out += "Deprecated Behaviour"; break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: out += "Undefined Behaviour"; break; + case GL_DEBUG_TYPE_PORTABILITY: out += "Portability"; break; + case GL_DEBUG_TYPE_PERFORMANCE: out += "Performance"; break; + case GL_DEBUG_TYPE_MARKER: out += "Marker"; break; + case GL_DEBUG_TYPE_PUSH_GROUP: out += "Push Group"; break; + case GL_DEBUG_TYPE_POP_GROUP: out += "Pop Group"; break; + case GL_DEBUG_TYPE_OTHER: out += "Other"; break; + } + out += "/"; + switch (source) + { + case GL_DEBUG_SOURCE_API: out += "API"; break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: out += "Window System"; break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: out += "Shader Compiler"; break; + case GL_DEBUG_SOURCE_THIRD_PARTY: out += "Third Party"; break; + case GL_DEBUG_SOURCE_APPLICATION: out += "Application"; break; + case GL_DEBUG_SOURCE_OTHER: out += "Other"; break; + } + out += "/"; + switch (severity) + { + case GL_DEBUG_SEVERITY_HIGH: out += "high"; break; + case GL_DEBUG_SEVERITY_MEDIUM: out += "medium"; break; + case GL_DEBUG_SEVERITY_LOW: out += "low"; break; + case GL_DEBUG_SEVERITY_NOTIFICATION: out += "notification"; break; + } + out += "]:\n"; + std::cout << out << "(" << id << "): " << message << "\n\n"; +} +#endif // ENABLE_OPENGL_DEBUG_OPTION + bool OpenGLManager::init_gl() { if (!m_gl_initialized) { @@ -313,7 +355,7 @@ bool OpenGLManager::init_gl() s_framebuffers_type = EFramebufferType::Unknown; #if ENABLE_GL_CORE_PROFILE - bool valid_version = s_gl_info.is_core_profile() ? s_gl_info.is_version_greater_or_equal_to(3, 3) : s_gl_info.is_version_greater_or_equal_to(2, 0); + bool valid_version = s_gl_info.is_core_profile() ? s_gl_info.is_version_greater_or_equal_to(3, 2) : s_gl_info.is_version_greater_or_equal_to(2, 0); #else bool valid_version = s_gl_info.is_version_greater_or_equal_to(2, 0); #endif // ENABLE_GL_CORE_PROFILE @@ -344,6 +386,14 @@ bool OpenGLManager::init_gl() _utf8(L("Unable to load the following shaders:\n%s"))) % error).str()); wxMessageBox(message, wxString("PrusaSlicer - ") + _L("Error loading shaders"), wxOK | wxICON_ERROR); } +#if ENABLE_OPENGL_DEBUG_OPTION + if (m_debug_enabled) { + ::glEnable(GL_DEBUG_OUTPUT); + ::glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + ::glDebugMessageCallback(CustomGLDebugOutput, nullptr); + ::glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE); + } +#endif // ENABLE_OPENGL_DEBUG_OPTION } } @@ -351,22 +401,37 @@ bool OpenGLManager::init_gl() } #if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_DEBUG_OPTION +wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas, const std::pair& required_opengl_version, bool enable_debug) +#else wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas, const std::pair& required_opengl_version) +#endif // ENABLE_OPENGL_DEBUG_OPTION #else wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas) #endif // ENABLE_GL_CORE_PROFILE { if (m_context == nullptr) { #if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_DEBUG_OPTION + m_debug_enabled = enable_debug; +#endif // ENABLE_OPENGL_DEBUG_OPTION + if (required_opengl_version != std::make_pair(0, 0)) { // the user specified a required version in the command line using --opengl=M.m m_required_version = required_opengl_version; const bool supports_core_profile = (m_required_version.first < 3) ? false : - (m_required_version.first > 3) ? true : m_required_version.second >= 3; + (m_required_version.first > 3) ? true : m_required_version.second >= 2; if (supports_core_profile) { // disable wxWidgets logging to avoid showing the log dialog in case the following code fails generating a valid gl context wxLogNull logNo; wxGLContextAttrs attrs; +#if ENABLE_OPENGL_DEBUG_OPTION + attrs.MajorVersion(m_required_version.first).MinorVersion(m_required_version.second).CoreProfile().ForwardCompatible(); + if (m_debug_enabled) + attrs.DebugCtx(); + attrs.EndList(); +#else attrs.MajorVersion(m_required_version.first).MinorVersion(m_required_version.second).CoreProfile().ForwardCompatible().EndList(); +#endif // ENABLE_OPENGL_DEBUG_OPTION m_context = new wxGLContext(&canvas, nullptr, &attrs); if (!m_context->IsOK()) { BOOST_LOG_TRIVIAL(error) << "Unable to create context for required OpenGL " << required_opengl_version.first << "." << required_opengl_version.second; @@ -393,9 +458,20 @@ wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas) // } //} +#if ENABLE_OPENGL_DEBUG_OPTION + if (m_context == nullptr) { + wxGLContextAttrs attrs; + if (m_debug_enabled) + attrs.DebugCtx(); + attrs.EndList(); + // if no valid context was created use the default one + m_context = new wxGLContext(&canvas, nullptr, &attrs); + } +#else if (m_context == nullptr) // if no valid context was created use the default one m_context = new wxGLContext(&canvas); +#endif // ENABLE_OPENGL_DEBUG_OPTION #else m_context = new wxGLContext(&canvas); #endif // ENABLE_GL_CORE_PROFILE diff --git a/src/slic3r/GUI/OpenGLManager.hpp b/src/slic3r/GUI/OpenGLManager.hpp index 12717740e..9a019ccf1 100644 --- a/src/slic3r/GUI/OpenGLManager.hpp +++ b/src/slic3r/GUI/OpenGLManager.hpp @@ -86,6 +86,9 @@ private: wxGLContext* m_context{ nullptr }; #if ENABLE_GL_CORE_PROFILE std::pair m_required_version{ 0, 0 }; +#if ENABLE_OPENGL_DEBUG_OPTION + bool m_debug_enabled{ false }; +#endif // ENABLE_OPENGL_DEBUG_OPTION #endif // ENABLE_GL_CORE_PROFILE GLShadersManager m_shaders_manager; static GLInfo s_gl_info; @@ -103,7 +106,11 @@ public: bool init_gl(); #if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_DEBUG_OPTION + wxGLContext* init_glcontext(wxGLCanvas& canvas, const std::pair& required_opengl_version, bool enable_debug); +#else wxGLContext* init_glcontext(wxGLCanvas& canvas, const std::pair& required_opengl_version); +#endif // ENABLE_OPENGL_DEBUG_OPTION #else wxGLContext* init_glcontext(wxGLCanvas& canvas); #endif // ENABLE_GL_CORE_PROFILE