FIX:cancel glmultidraw or improved glmultidraw stability

jira: STUDIO-12202
Change-Id: I4ad99686b42125c998dfb1dfcf2c533a49375af0
This commit is contained in:
zhou.xu 2025-05-17 14:44:41 +08:00 committed by lane.wei
parent c28e4be2ca
commit 3a8c7527c1
6 changed files with 95 additions and 81 deletions

View File

@ -195,6 +195,8 @@ void AppConfig::set_defaults()
set_bool("user_bed_type", true); set_bool("user_bed_type", true);
if (get("grabber_size_factor").empty()) if (get("grabber_size_factor").empty())
set("grabber_size_factor", "1.0"); set("grabber_size_factor", "1.0");
if (get("cancel_glmultidraw").empty())
set_bool("cancel_glmultidraw", false);
//#ifdef SUPPORT_SHOW_HINTS //#ifdef SUPPORT_SHOW_HINTS
if (get("show_hints").empty()) if (get("show_hints").empty())
set_bool("show_hints", false); set_bool("show_hints", false);

View File

@ -1375,7 +1375,7 @@ static void debug_calibration_output_thumbnail(const ThumbnailData& thumbnail_da
image.SaveFile("D:/calibrate.png", wxBITMAP_TYPE_PNG); image.SaveFile("D:/calibrate.png", wxBITMAP_TYPE_PNG);
} }
#endif #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) 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; 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.zoom_to_box(plate_box, 1.0f);
camera.apply_projection(plate_box); camera.apply_projection(plate_box);
auto render_as_triangles = [
#if ENABLE_GCODE_VIEWER_STATISTICS
this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
](TBuffer &buffer, std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::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<const GLfloat*>(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 = [ auto render_as_instanced_model = [
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
this this
@ -1564,7 +1546,7 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai
switch (buffer.render_primitive_type) switch (buffer.render_primitive_type)
{ {
case TBuffer::ERenderPrimitiveType::Triangle: { 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; break;
} }
default: { 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::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count(); statistics->refresh_paths_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
} }
template<typename Iterator>
void GCodeViewer::render_sub_paths(Iterator it_path, Iterator it_end, GLShaderProgram &shader, int uniform_color, unsigned int draw_type)
{
//std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::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<const GLfloat *>(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() void GCodeViewer::render_toolpaths()
{ {
@ -3919,68 +3941,10 @@ void GCodeViewer::render_toolpaths()
shader.set_uniform("near_plane_height", near_plane_height); 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<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::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<const GLfloat*>(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) { auto shader_init_as_lines = [light_intensity](GLShaderProgram &shader) {
shader.set_uniform("light_intensity", light_intensity); shader.set_uniform("light_intensity", light_intensity);
}; };
auto render_as_lines = [
#if ENABLE_GCODE_VIEWER_STATISTICS
this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
](std::vector<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::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<const GLfloat*>(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<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::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<const GLfloat*>(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 = [ auto render_as_instanced_model = [
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
@ -4151,16 +4115,16 @@ void GCodeViewer::render_toolpaths()
switch (buffer.render_primitive_type) switch (buffer.render_primitive_type)
{ {
case TBuffer::ERenderPrimitiveType::Point: { 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; break;
} }
case TBuffer::ERenderPrimitiveType::Line: { case TBuffer::ERenderPrimitiveType::Line: {
p_ogl_manager->set_line_width(static_cast<float>(line_width(zoom))); p_ogl_manager->set_line_width(static_cast<float>(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; break;
} }
case TBuffer::ERenderPrimitiveType::Triangle: { 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; break;
} }
default: { break; } default: { break; }

View File

@ -920,6 +920,8 @@ private:
//BBS: always load shell at preview //BBS: always load shell at preview
//void load_shells(const Print& print, bool initialized); //void load_shells(const Print& print, bool initialized);
void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const; void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const;
template<typename Iterator>
void render_sub_paths(Iterator it_path, Iterator it_end, GLShaderProgram &shader, int uniform_color, unsigned int draw_type);
void render_toolpaths(); void render_toolpaths();
void render_shells(); void render_shells();

View File

@ -2925,6 +2925,9 @@ bool GUI_App::on_init_inner()
const bool gizmo_keep_screen_size = app_config->get_bool("gizmo_keep_screen_size"); 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); 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; BBLSplashScreen * scrn = nullptr;

View File

@ -316,6 +316,7 @@ OpenGLManager::EMultisampleState OpenGLManager::s_multisample = OpenGLManager::E
OpenGLManager::EFramebufferType OpenGLManager::s_framebuffers_type = OpenGLManager::EFramebufferType::Unknown; OpenGLManager::EFramebufferType OpenGLManager::s_framebuffers_type = OpenGLManager::EFramebufferType::Unknown;
bool OpenGLManager::s_b_initialized = false; bool OpenGLManager::s_b_initialized = false;
ColorRGBA OpenGLManager::s_cut_plane_color = {1.0f, 0.37f, 0.0f, 1.0f}; ColorRGBA OpenGLManager::s_cut_plane_color = {1.0f, 0.37f, 0.0f, 1.0f};
bool OpenGLManager::s_cancle_glmultidraw = false;
#ifdef __APPLE__ #ifdef __APPLE__
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets // 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; OpenGLManager::OSInfo OpenGLManager::s_os_info;
@ -851,6 +852,34 @@ const ColorRGBA &OpenGLManager::get_cut_plane_color(){
return s_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) void OpenGLManager::detect_multisample(int* attribList)
{ {
int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER;

View File

@ -45,6 +45,16 @@ enum class EPixelDataType : uint16_t
Float Float
}; };
enum class EDrawPrimitiveType : uint8_t{
Points,
Triangles,
TriangleStrip,
TriangleFan,
Lines,
LineStrip,
LineLoop
};
struct FrameBufferParams struct FrameBufferParams
{ {
uint32_t m_width{ 0 }; uint32_t m_width{ 0 };
@ -232,6 +242,7 @@ private:
static EFramebufferType s_framebuffers_type; static EFramebufferType s_framebuffers_type;
static bool m_use_manually_generated_mipmaps; static bool m_use_manually_generated_mipmaps;
static ColorRGBA s_cut_plane_color; static ColorRGBA s_cut_plane_color;
static bool s_cancle_glmultidraw;
public: public:
OpenGLManager(); OpenGLManager();
@ -279,6 +290,9 @@ public:
static bool use_manually_generated_mipmaps() { return m_use_manually_generated_mipmaps; } static bool use_manually_generated_mipmaps() { return m_use_manually_generated_mipmaps; }
static void set_cut_plane_color(ColorRGBA); static void set_cut_plane_color(ColorRGBA);
static const ColorRGBA &get_cut_plane_color(); 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: private:
static void detect_multisample(int* attribList); static void detect_multisample(int* attribList);