From 3a8c7527c1db93a4790ccabb3204dea71c9dac1f Mon Sep 17 00:00:00 2001 From: "zhou.xu" Date: Sat, 17 May 2025 14:44:41 +0800 Subject: [PATCH] FIX:cancel glmultidraw or improved glmultidraw stability jira: STUDIO-12202 Change-Id: I4ad99686b42125c998dfb1dfcf2c533a49375af0 --- src/libslic3r/AppConfig.cpp | 2 + src/slic3r/GUI/GCodeViewer.cpp | 126 +++++++++++-------------------- src/slic3r/GUI/GCodeViewer.hpp | 2 + src/slic3r/GUI/GUI_App.cpp | 3 + src/slic3r/GUI/OpenGLManager.cpp | 29 +++++++ src/slic3r/GUI/OpenGLManager.hpp | 14 ++++ 6 files changed, 95 insertions(+), 81 deletions(-) diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 3bd9944ca..e7cf7974a 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -195,6 +195,8 @@ void AppConfig::set_defaults() set_bool("user_bed_type", true); if (get("grabber_size_factor").empty()) set("grabber_size_factor", "1.0"); + if (get("cancel_glmultidraw").empty()) + set_bool("cancel_glmultidraw", false); //#ifdef SUPPORT_SHOW_HINTS if (get("show_hints").empty()) set_bool("show_hints", false); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index a814be5ba..da484cabe 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1375,7 +1375,7 @@ static void debug_calibration_output_thumbnail(const ThumbnailData& thumbnail_da image.SaveFile("D:/calibrate.png", wxBITMAP_TYPE_PNG); } #endif - +const int MAX_DRAWS_PER_BATCH = 1024; void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, OpenGLManager& opengl_manager) { int plate_idx = thumbnail_params.plate_id; @@ -1395,24 +1395,6 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai camera.zoom_to_box(plate_box, 1.0f); camera.apply_projection(plate_box); - auto render_as_triangles = [ -#if ENABLE_GCODE_VIEWER_STATISTICS - this -#endif // ENABLE_GCODE_VIEWER_STATISTICS - ](TBuffer &buffer, std::vector::iterator it_path, std::vector::iterator it_end, GLShaderProgram& shader, int uniform_color) { - for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { - const RenderPath& path = *it; - // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. - assert(!path.sizes.empty()); - assert(!path.offsets.empty()); - glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); - glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); -#if ENABLE_GCODE_VIEWER_STATISTICS - ++m_statistics.gl_multi_triangles_calls_count; -#endif // ENABLE_GCODE_VIEWER_STATISTICS - } - }; - auto render_as_instanced_model = [ #if ENABLE_GCODE_VIEWER_STATISTICS this @@ -1564,7 +1546,7 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai switch (buffer.render_primitive_type) { case TBuffer::ERenderPrimitiveType::Triangle: { - render_as_triangles(buffer, it_path, buffer.render_paths.end(), *shader, uniform_color); + render_sub_paths(it_path, buffer.render_paths.end(), *shader, uniform_color, (unsigned int) EDrawPrimitiveType::Triangles); break; } default: { break; } @@ -3891,6 +3873,46 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool statistics->refresh_paths_time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); #endif // ENABLE_GCODE_VIEWER_STATISTICS } +template +void GCodeViewer::render_sub_paths(Iterator it_path, Iterator it_end, GLShaderProgram &shader, int uniform_color, unsigned int draw_type) +{ + //std::vector::iterator it_path, std::vector::iterator it_end + if ((EDrawPrimitiveType) draw_type == EDrawPrimitiveType::Points) { + glsafe(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE)); + glsafe(::glEnable(GL_POINT_SPRITE)); + } + bool cancel_glmultidraw = wxGetApp().get_opengl_manager()->get_cancle_glmultidraw(); + for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { + const RenderPath &path = *it; + assert(!path.sizes.empty()); + assert(!path.offsets.empty()); + glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); + if (cancel_glmultidraw) { + for (size_t i = 0; i < path.sizes.size(); ++i) { + GLsizei count = path.sizes[i]; + glsafe(::glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const void *) path.offsets[i])); + } + } else { + int total_draws = path.sizes.size(); + int number = path.sizes.size() / MAX_DRAWS_PER_BATCH + 1; + for (size_t batch = 0; batch < number; batch++) { + int start = batch * MAX_DRAWS_PER_BATCH; + int count = std::min(MAX_DRAWS_PER_BATCH, total_draws - start); + if (count == 0) { continue; } + glsafe(::glMultiDrawElements(OpenGLManager::get_draw_primitive_type((EDrawPrimitiveType)draw_type), (const GLsizei *) path.sizes.data() + start, GL_UNSIGNED_SHORT, + (const void *const *) (path.offsets.data() + start), + (GLsizei) count)); + } + } +#if ENABLE_GCODE_VIEWER_STATISTICS + ++m_statistics.gl_multi_triangles_calls_count; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + } + if ((EDrawPrimitiveType) draw_type == EDrawPrimitiveType::Points) { + glsafe(::glDisable(GL_POINT_SPRITE)); + glsafe(::glDisable(GL_VERTEX_PROGRAM_POINT_SIZE)); + } +} void GCodeViewer::render_toolpaths() { @@ -3919,68 +3941,10 @@ void GCodeViewer::render_toolpaths() shader.set_uniform("near_plane_height", near_plane_height); }; - auto render_as_points = [ -#if ENABLE_GCODE_VIEWER_STATISTICS - this -#endif // ENABLE_GCODE_VIEWER_STATISTICS - ](std::vector::reverse_iterator it_path, std::vector::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) { - glsafe(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE)); - glsafe(::glEnable(GL_POINT_SPRITE)); - - for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { - const RenderPath& path = *it; - // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. - assert(! path.sizes.empty()); - assert(! path.offsets.empty()); - glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); - glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); -#if ENABLE_GCODE_VIEWER_STATISTICS - ++m_statistics.gl_multi_points_calls_count; -#endif // ENABLE_GCODE_VIEWER_STATISTICS - } - - glsafe(::glDisable(GL_POINT_SPRITE)); - glsafe(::glDisable(GL_VERTEX_PROGRAM_POINT_SIZE)); - }; - auto shader_init_as_lines = [light_intensity](GLShaderProgram &shader) { shader.set_uniform("light_intensity", light_intensity); }; - auto render_as_lines = [ -#if ENABLE_GCODE_VIEWER_STATISTICS - this -#endif // ENABLE_GCODE_VIEWER_STATISTICS - ](std::vector::reverse_iterator it_path, std::vector::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) { - for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { - const RenderPath& path = *it; - // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. - assert(! path.sizes.empty()); - assert(! path.offsets.empty()); - glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); - glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); -#if ENABLE_GCODE_VIEWER_STATISTICS - ++m_statistics.gl_multi_lines_calls_count; -#endif // ENABLE_GCODE_VIEWER_STATISTICS - } - }; - auto render_as_triangles = [ -#if ENABLE_GCODE_VIEWER_STATISTICS - this -#endif // ENABLE_GCODE_VIEWER_STATISTICS - ](std::vector::reverse_iterator it_path, std::vector::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) { - for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { - const RenderPath& path = *it; - // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. - assert(! path.sizes.empty()); - assert(! path.offsets.empty()); - glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); - glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); -#if ENABLE_GCODE_VIEWER_STATISTICS - ++m_statistics.gl_multi_triangles_calls_count; -#endif // ENABLE_GCODE_VIEWER_STATISTICS - } - }; auto render_as_instanced_model = [ #if ENABLE_GCODE_VIEWER_STATISTICS @@ -4151,16 +4115,16 @@ void GCodeViewer::render_toolpaths() switch (buffer.render_primitive_type) { case TBuffer::ERenderPrimitiveType::Point: { - render_as_points(it_path, buffer.render_paths.rend(), *shader, uniform_color); + render_sub_paths(it_path, buffer.render_paths.rend(), *shader, uniform_color, (unsigned int) EDrawPrimitiveType::Points); break; } case TBuffer::ERenderPrimitiveType::Line: { p_ogl_manager->set_line_width(static_cast(line_width(zoom))); - render_as_lines(it_path, buffer.render_paths.rend(), *shader, uniform_color); + render_sub_paths(it_path, buffer.render_paths.rend(), *shader, uniform_color, (unsigned int) EDrawPrimitiveType::Lines); break; } case TBuffer::ERenderPrimitiveType::Triangle: { - render_as_triangles(it_path, buffer.render_paths.rend(), *shader, uniform_color); + render_sub_paths(it_path, buffer.render_paths.rend(), *shader, uniform_color, (unsigned int) EDrawPrimitiveType::Triangles); break; } default: { break; } diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index af22b5d1e..261c40637 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -920,6 +920,8 @@ private: //BBS: always load shell at preview //void load_shells(const Print& print, bool initialized); void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const; + template + void render_sub_paths(Iterator it_path, Iterator it_end, GLShaderProgram &shader, int uniform_color, unsigned int draw_type); void render_toolpaths(); void render_shells(); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 12e72888f..ddab1a714 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2925,6 +2925,9 @@ bool GUI_App::on_init_inner() const bool gizmo_keep_screen_size = app_config->get_bool("gizmo_keep_screen_size"); p_ogl_manager->set_gizmo_keep_screen_size_enabled(gizmo_keep_screen_size); + + const bool cancel_glmultidraw = app_config->get_bool("cancel_glmultidraw"); + p_ogl_manager->set_cancle_glmultidraw(cancel_glmultidraw); } BBLSplashScreen * scrn = nullptr; diff --git a/src/slic3r/GUI/OpenGLManager.cpp b/src/slic3r/GUI/OpenGLManager.cpp index 13e7d06cf..15fb3e9cc 100644 --- a/src/slic3r/GUI/OpenGLManager.cpp +++ b/src/slic3r/GUI/OpenGLManager.cpp @@ -316,6 +316,7 @@ OpenGLManager::EMultisampleState OpenGLManager::s_multisample = OpenGLManager::E OpenGLManager::EFramebufferType OpenGLManager::s_framebuffers_type = OpenGLManager::EFramebufferType::Unknown; bool OpenGLManager::s_b_initialized = false; ColorRGBA OpenGLManager::s_cut_plane_color = {1.0f, 0.37f, 0.0f, 1.0f}; +bool OpenGLManager::s_cancle_glmultidraw = false; #ifdef __APPLE__ // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets OpenGLManager::OSInfo OpenGLManager::s_os_info; @@ -851,6 +852,34 @@ const ColorRGBA &OpenGLManager::get_cut_plane_color(){ return s_cut_plane_color; } +unsigned int OpenGLManager::get_draw_primitive_type(EDrawPrimitiveType type) +{ + switch (type) { + case EDrawPrimitiveType::Points: { + return GL_POINTS; + } + default: + case EDrawPrimitiveType::Triangles: { + return GL_TRIANGLES; + } + case EDrawPrimitiveType::TriangleStrip: { + return GL_TRIANGLE_STRIP; + } + case EDrawPrimitiveType::TriangleFan: { + return GL_TRIANGLE_FAN; + } + case EDrawPrimitiveType::Lines: { + return GL_LINES; + } + case EDrawPrimitiveType::LineStrip: { + return GL_LINE_STRIP; + } + case EDrawPrimitiveType::LineLoop: { + return GL_LINE_LOOP; + } + } +} + void OpenGLManager::detect_multisample(int* attribList) { int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; diff --git a/src/slic3r/GUI/OpenGLManager.hpp b/src/slic3r/GUI/OpenGLManager.hpp index 9ef142448..ea09ca752 100644 --- a/src/slic3r/GUI/OpenGLManager.hpp +++ b/src/slic3r/GUI/OpenGLManager.hpp @@ -45,6 +45,16 @@ enum class EPixelDataType : uint16_t Float }; +enum class EDrawPrimitiveType : uint8_t{ + Points, + Triangles, + TriangleStrip, + TriangleFan, + Lines, + LineStrip, + LineLoop +}; + struct FrameBufferParams { uint32_t m_width{ 0 }; @@ -232,6 +242,7 @@ private: static EFramebufferType s_framebuffers_type; static bool m_use_manually_generated_mipmaps; static ColorRGBA s_cut_plane_color; + static bool s_cancle_glmultidraw; public: OpenGLManager(); @@ -279,6 +290,9 @@ public: static bool use_manually_generated_mipmaps() { return m_use_manually_generated_mipmaps; } static void set_cut_plane_color(ColorRGBA); static const ColorRGBA &get_cut_plane_color(); + static bool get_cancle_glmultidraw() { return s_cancle_glmultidraw; } + static void set_cancle_glmultidraw(bool flag) { s_cancle_glmultidraw = flag; } + static unsigned int get_draw_primitive_type(EDrawPrimitiveType type); private: static void detect_multisample(int* attribList);