SPE-2344: Fix performance hit on MAC in GCodeViewer:

squashed et_spe2344_bis (5c6bba6)
This commit is contained in:
enricoturri1966 2024-06-17 09:42:38 +02:00 committed by Lukas Matena
parent e96bf263b9
commit bafd65d55b
13 changed files with 108 additions and 87 deletions

View File

@ -109,11 +109,6 @@ void AppConfig::set_defaults()
if (!get("use_legacy_opengl").empty())
erase("", "use_legacy_opengl");
#ifdef __APPLE__
if (get("use_retina_opengl").empty())
set("use_retina_opengl", "1");
#endif
if (get("single_instance").empty())
set("single_instance",
#ifdef __APPLE__
@ -182,6 +177,11 @@ void AppConfig::set_defaults()
#endif // _WIN32
}
#ifdef __APPLE__
if (get("use_retina_opengl").empty())
set("use_retina_opengl", "1");
#endif // __APPLE__
if (get("seq_top_layer_only").empty())
set("seq_top_layer_only", "1");

View File

@ -55,4 +55,9 @@
// Enable extension of tool position imgui dialog to show actual speed profile
#define ENABLE_ACTUAL_SPEED_DEBUG 1
// This technology enables a hack which resolves the slow down on MAC when running the application as GCodeViewer.
// For yet unknow reason the slow down disappears if any of the toolbars is renderered.
// This hack keeps the collapse toolbar enabled and renders it outside of the screen.
#define ENABLE_HACK_GCODEVIEWER_SLOW_ON_MAC 1
#endif // _prusaslicer_technologies_h_

View File

@ -1878,8 +1878,12 @@ void ViewerImpl::render_segments(const Mat4x4& view_matrix, const Mat4x4& projec
m_segment_template.render(count);
}
#else
int curr_bound_texture = 0;
glsafe(glGetIntegerv(GL_TEXTURE_BINDING_BUFFER, &curr_bound_texture));
std::array<int, 4> curr_bound_texture = { 0, 0, 0, 0 };
for (int i = 0; i < curr_bound_texture.size(); ++i) {
glsafe(glActiveTexture(GL_TEXTURE0 + i));
glsafe(glGetIntegerv(GL_TEXTURE_BINDING_BUFFER, &curr_bound_texture[i]));
//assert(curr_bound_texture[i] == 0);
}
glsafe(glActiveTexture(GL_TEXTURE0));
glsafe(glBindTexture(GL_TEXTURE_BUFFER, m_positions_tex_id));
@ -1904,7 +1908,10 @@ void ViewerImpl::render_segments(const Mat4x4& view_matrix, const Mat4x4& projec
#ifdef ENABLE_OPENGL_ES
glsafe(glBindTexture(GL_TEXTURE_2D, curr_bound_texture));
#else
glsafe(glBindTexture(GL_TEXTURE_BUFFER, curr_bound_texture));
for (int i = 0; i < curr_bound_texture.size(); ++i) {
glsafe(glActiveTexture(GL_TEXTURE0 + i));
glsafe(glBindTexture(GL_TEXTURE_BUFFER, curr_bound_texture[i]));
}
#endif // ENABLE_OPENGL_ES
glsafe(glActiveTexture(curr_active_texture));
}
@ -1958,8 +1965,12 @@ void ViewerImpl::render_options(const Mat4x4& view_matrix, const Mat4x4& project
m_option_template.render(count);
}
#else
int curr_bound_texture = 0;
glsafe(glGetIntegerv(GL_TEXTURE_BINDING_BUFFER, &curr_bound_texture));
std::array<int, 4> curr_bound_texture = { 0, 0, 0, 0 };
for (int i = 0; i < curr_bound_texture.size(); ++i) {
glsafe(glActiveTexture(GL_TEXTURE0 + i));
glsafe(glGetIntegerv(GL_TEXTURE_BINDING_BUFFER, &curr_bound_texture[i]));
//assert(curr_bound_texture[i] == 0);
}
glsafe(glActiveTexture(GL_TEXTURE0));
glsafe(glBindTexture(GL_TEXTURE_BUFFER, m_positions_tex_id));
@ -1984,7 +1995,10 @@ void ViewerImpl::render_options(const Mat4x4& view_matrix, const Mat4x4& project
#ifdef ENABLE_OPENGL_ES
glsafe(glBindTexture(GL_TEXTURE_2D, curr_bound_texture));
#else
glsafe(glBindTexture(GL_TEXTURE_BUFFER, curr_bound_texture));
for (int i = 0; i < curr_bound_texture.size(); ++i) {
glsafe(glActiveTexture(GL_TEXTURE0 + i));
glsafe(glBindTexture(GL_TEXTURE_BUFFER, curr_bound_texture[i]));
}
#endif // ENABLE_OPENGL_ES
glsafe(glActiveTexture(curr_active_texture));
}

View File

@ -4600,29 +4600,6 @@ bool GLCanvas3D::_render_arrange_menu(float pos_x)
return true;
}
#define ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT 0
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
static void debug_output_thumbnail(const ThumbnailData& thumbnail_data)
{
// debug export of generated image
wxImage image(thumbnail_data.width, thumbnail_data.height);
image.InitAlpha();
for (unsigned int r = 0; r < thumbnail_data.height; ++r)
{
unsigned int rr = (thumbnail_data.height - 1 - r) * thumbnail_data.width;
for (unsigned int c = 0; c < thumbnail_data.width; ++c)
{
unsigned char* px = (unsigned char*)thumbnail_data.pixels.data() + 4 * (rr + c);
image.SetRGB((int)c, (int)r, px[0], px[1], px[2]);
image.SetAlpha((int)c, (int)r, px[3]);
}
}
image.SaveFile("C:/prusa/test/test.png", wxBITMAP_TYPE_PNG);
}
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type)
{
auto is_visible = [](const GLVolume& v) {
@ -4758,8 +4735,9 @@ void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, un
if (!thumbnail_data.is_valid())
return;
bool multisample = m_multisample_allowed;
if (multisample)
const bool multisample = ::glIsEnabled(GL_MULTISAMPLE);
glcheck();
if (m_multisample_allowed && !multisample)
glsafe(::glEnable(GL_MULTISAMPLE));
GLint max_samples;
@ -4833,10 +4811,6 @@ void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, un
}
else
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
debug_output_thumbnail(thumbnail_data);
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
}
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
@ -4847,7 +4821,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, un
glsafe(::glDeleteTextures(1, &render_tex));
glsafe(::glDeleteFramebuffers(1, &render_fbo));
if (multisample)
if (!multisample)
glsafe(::glDisable(GL_MULTISAMPLE));
}
@ -4857,8 +4831,9 @@ void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data
if (!thumbnail_data.is_valid())
return;
bool multisample = m_multisample_allowed;
if (multisample)
const bool multisample = ::glIsEnabled(GL_MULTISAMPLE);
glcheck();
if (m_multisample_allowed && !multisample)
glsafe(::glEnable(GL_MULTISAMPLE));
GLint max_samples;
@ -4932,10 +4907,6 @@ void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data
}
else
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
debug_output_thumbnail(thumbnail_data);
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
}
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
@ -4946,7 +4917,7 @@ void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data
glsafe(::glDeleteTextures(1, &render_tex));
glsafe(::glDeleteFramebuffersEXT(1, &render_fbo));
if (multisample)
if (!multisample)
glsafe(::glDisable(GL_MULTISAMPLE));
}
@ -4969,9 +4940,6 @@ void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigne
_render_thumbnail_internal(thumbnail_data, thumbnail_params, volumes, camera_type);
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
debug_output_thumbnail(thumbnail_data);
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
// restore the default framebuffer size to avoid flickering on the 3D scene
wxGetApp().plater()->get_camera().apply_viewport();
@ -4996,8 +4964,8 @@ bool GLCanvas3D::_init_toolbars()
bool GLCanvas3D::_init_main_toolbar()
{
if (!m_main_toolbar.is_enabled())
return true;
//if (!m_main_toolbar.is_enabled())
// return true;
BackgroundTexture::Metadata background_data;
background_data.filename = "toolbar_background.png";
@ -5180,13 +5148,16 @@ bool GLCanvas3D::_init_main_toolbar()
if (!m_main_toolbar.add_item(item))
return false;
if (!m_main_toolbar.generate_icons_texture())
return false;
return true;
}
bool GLCanvas3D::_init_undoredo_toolbar()
{
if (!m_undoredo_toolbar.is_enabled())
return true;
//if (!m_undoredo_toolbar.is_enabled())
// return true;
BackgroundTexture::Metadata background_data;
background_data.filename = "toolbar_background.png";
@ -5293,6 +5264,10 @@ bool GLCanvas3D::_init_undoredo_toolbar()
if (!m_undoredo_toolbar.add_separator())
return false;
*/
if (!m_undoredo_toolbar.generate_icons_texture())
return false;
return true;
}
@ -6167,7 +6142,13 @@ void GLCanvas3D::_render_collapse_toolbar() const
const Size cnv_size = get_canvas_size();
const float band = m_layers_editing.is_enabled() ? (wxGetApp().imgui()->get_style_scaling() * LayersEditing::THICKNESS_BAR_WIDTH) : 0.0;
const float top = 0.5f * (float)cnv_size.get_height();
#if ENABLE_HACK_GCODEVIEWER_SLOW_ON_MAC
// When the application is run as GCodeViewer, render the collapse toolbar outside of the screen
const float left = wxGetApp().is_gcode_viewer() ? 0.5f * (float)cnv_size.get_width() :
0.5f * (float)cnv_size.get_width() - collapse_toolbar.get_width() - band;
#else
const float left = 0.5f * (float)cnv_size.get_width() - collapse_toolbar.get_width() - band;
#endif // ENABLE_HACK_GCODEVIEWER_SLOW_ON_MAC
collapse_toolbar.set_position(top, left);
collapse_toolbar.render(*this);

View File

@ -349,7 +349,7 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right,
init_data.add_vertex(Vec2f(right, top), Vec2f(uvs.right_top.u, uvs.right_top.v));
init_data.add_vertex(Vec2f(left, top), Vec2f(uvs.left_top.u, uvs.left_top.v));
// indices
// indices
init_data.add_triangle(0, 1, 2);
init_data.add_triangle(2, 3, 0);

View File

@ -244,8 +244,7 @@ void GLToolbar::set_gap_size(float size)
void GLToolbar::set_icons_size(float size)
{
if (m_layout.icons_size != size)
{
if (m_layout.icons_size != size) {
m_layout.icons_size = size;
m_layout.dirty = true;
m_icons_texture_dirty = true;

View File

@ -335,6 +335,9 @@ public:
bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent);
// get item pointer for highlighter timer
GLToolbarItem* get_item(const std::string& item_name);
bool generate_icons_texture();
private:
void calc_layout();
float get_width_horizontal() const;
@ -355,8 +358,6 @@ private:
void render_horizontal(const GLCanvas3D& parent);
void render_vertical(const GLCanvas3D& parent);
bool generate_icons_texture();
// returns true if any item changed its state
bool update_items_visibility();
// returns true if any item changed its state

View File

@ -3370,14 +3370,10 @@ void GUI_App::gcode_thumbnails_debug()
boost::nowide::ifstream in_file(in_filename.c_str());
std::vector<std::string> rows;
std::string row;
if (in_file.good())
{
while (std::getline(in_file, gcode_line))
{
if (in_file.good())
{
if (boost::starts_with(gcode_line, BEGIN_MASK))
{
if (in_file.good()) {
while (std::getline(in_file, gcode_line)) {
if (in_file.good()) {
if (boost::starts_with(gcode_line, BEGIN_MASK)) {
reading_image = true;
gcode_line = gcode_line.substr(BEGIN_MASK.length() + 1);
std::string::size_type x_pos = gcode_line.find('x');
@ -3387,12 +3383,10 @@ void GUI_App::gcode_thumbnails_debug()
height = (unsigned int)::atoi(height_str.c_str());
row.clear();
}
else if (reading_image && boost::starts_with(gcode_line, END_MASK))
{
else if (reading_image && boost::starts_with(gcode_line, END_MASK)) {
std::string out_filename = out_path + std::to_string(width) + "x" + std::to_string(height) + ".png";
boost::nowide::ofstream out_file(out_filename.c_str(), std::ios::binary);
if (out_file.good())
{
if (out_file.good()) {
std::string decoded;
decoded.resize(boost::beast::detail::base64::decoded_size(row.size()));
decoded.resize(boost::beast::detail::base64::decode((void*)&decoded[0], row.data(), row.size()).first);

View File

@ -320,7 +320,13 @@ void Preview::render_sliders(GLCanvas3D& canvas)
const float extra_scale = cnv_size.get_scale_factor();
GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar();
#if ENABLE_HACK_GCODEVIEWER_SLOW_ON_MAC
// When the application is run as GCodeViewer the collapse toolbar is enabled but invisible, as it is renderer
// outside of the screen
const bool is_collapse_btn_shown = wxGetApp().is_editor() ? collapse_toolbar.is_enabled() : false;
#else
const bool is_collapse_btn_shown = collapse_toolbar.is_enabled();
#endif // ENABLE_HACK_GCODEVIEWER_SLOW_ON_MAC
if (m_layers_slider)
m_layers_slider->Render(canvas_width, canvas_height, extra_scale, is_collapse_btn_shown ? collapse_toolbar.get_height() : 0.f);

View File

@ -1133,9 +1133,9 @@ void ImGuiWrapper::init_font(bool compress)
io.Fonts->Clear();
// Create ranges of characters from m_glyph_ranges, possibly adding some OS specific special characters.
ImVector<ImWchar> ranges;
ImVector<ImWchar> ranges;
ImFontGlyphRangesBuilder builder;
builder.AddRanges(m_glyph_ranges);
builder.AddRanges(m_glyph_ranges);
builder.AddChar(ImWchar(0x2026)); // …
@ -1243,6 +1243,7 @@ void ImGuiWrapper::init_font(bool compress)
// Upload texture to graphics system
GLint last_texture;
glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
glsafe(::glGenTextures(1, &m_font_texture));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_font_texture));

View File

@ -311,7 +311,13 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
update_ui_from_settings(); // FIXME (?)
if (m_plater != nullptr) {
#if ENABLE_HACK_GCODEVIEWER_SLOW_ON_MAC
// When the application is run as GCodeViewer the collapse toolbar is set as enabled, but rendered outside of the screen
m_plater->get_collapse_toolbar().set_enabled(wxGetApp().is_gcode_viewer() ?
true : wxGetApp().app_config->get_bool("show_collapse_button"));
#else
m_plater->get_collapse_toolbar().set_enabled(wxGetApp().app_config->get_bool("show_collapse_button"));
#endif // ENABLE_HACK_GCODEVIEWER_SLOW_ON_MAC
m_plater->show_action_buttons(true);
preferences_dialog = new PreferencesDialog(this);
@ -433,7 +439,11 @@ void MainFrame::update_layout()
{
m_main_sizer->Add(m_plater, 1, wxEXPAND);
m_plater->set_default_bed_shape();
#if ENABLE_HACK_GCODEVIEWER_SLOW_ON_MAC
m_plater->get_collapse_toolbar().set_enabled(true);
#else
m_plater->get_collapse_toolbar().set_enabled(false);
#endif // !ENABLE_HACK_GCODEVIEWER_SLOW_ON_MAC
m_plater->collapse_sidebar(true);
m_plater->Show();
break;

View File

@ -539,25 +539,27 @@ wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent, bool enable_auto_
if (platform_flavor() != PlatformFlavor::LinuxOnChromium) {
for (int i = enable_auto_aa_samples ? 16 : 4; i >= 4; i /= 2) {
attribList.Reset();
attribList.PlatformDefaults().RGBA().DoubleBuffer().MinRGBA(8, 8, 8, 8).Depth(24).SampleBuffers(1).Samplers(i).EndList();
attribList.PlatformDefaults().RGBA().DoubleBuffer().MinRGBA(8, 8, 8, 8).Depth(24).SampleBuffers(1).Samplers(i);
#ifdef __APPLE__
// on MAC the method RGBA() has no effect
attribList.SetNeedsARB(true);
#endif // __APPLE__
attribList.EndList();
if (wxGLCanvas::IsDisplaySupported(attribList)) {
s_multisample = EMultisampleState::Enabled;
break;
}
}
}
#ifdef __APPLE__
// on MAC the method RGBA() has no effect
attribList.SetNeedsARB(true);
#endif // __APPLE__
if (s_multisample != EMultisampleState::Enabled) {
attribList.Reset();
attribList.PlatformDefaults().RGBA().DoubleBuffer().MinRGBA(8, 8, 8, 8).Depth(24).EndList();
attribList.PlatformDefaults().RGBA().DoubleBuffer().MinRGBA(8, 8, 8, 8).Depth(24);
#ifdef __APPLE__
// on MAC the method RGBA() has no effect
attribList.SetNeedsARB(true);
#endif // __APPLE__
attribList.EndList();
}
return new wxGLCanvas(&parent, attribList, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);

View File

@ -634,7 +634,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
background_process.set_thumbnail_cb([this](const ThumbnailsParams& params) { return this->generate_thumbnails(params, Camera::EType::Ortho); });
background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED);
background_process.set_finished_event(EVT_PROCESS_COMPLETED);
background_process.set_export_began_event(EVT_EXPORT_BEGAN);
background_process.set_export_began_event(EVT_EXPORT_BEGAN);
// Default printer technology for default config.
background_process.select_technology(this->printer_technology);
// Register progress callback from the Print class to the Plater.
@ -3325,8 +3325,8 @@ void Plater::priv::reset_canvas_volumes()
bool Plater::priv::init_view_toolbar()
{
if (wxGetApp().is_gcode_viewer())
return true;
//if (wxGetApp().is_gcode_viewer())
// return true;
if (view_toolbar.get_items_count() > 0)
// already initialized
@ -3367,16 +3367,20 @@ bool Plater::priv::init_view_toolbar()
if (!view_toolbar.add_item(item))
return false;
if (!view_toolbar.generate_icons_texture())
return false;
view_toolbar.select_item("3D");
view_toolbar.set_enabled(true);
if (wxGetApp().is_editor())
view_toolbar.set_enabled(true);
return true;
}
bool Plater::priv::init_collapse_toolbar()
{
if (wxGetApp().is_gcode_viewer())
return true;
//if (wxGetApp().is_gcode_viewer())
// return true;
if (collapse_toolbar.get_items_count() > 0)
// already initialized
@ -3411,9 +3415,13 @@ bool Plater::priv::init_collapse_toolbar()
if (!collapse_toolbar.add_item(item))
return false;
if (!collapse_toolbar.generate_icons_texture())
return false;
// Now "collapse" sidebar to current state. This is done so the tooltip
// is updated before the toolbar is first used.
wxGetApp().plater()->collapse_sidebar(wxGetApp().plater()->is_sidebar_collapsed());
if (wxGetApp().is_editor())
wxGetApp().plater()->collapse_sidebar(wxGetApp().plater()->is_sidebar_collapsed());
return true;
}