diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index ad6de77ed..8552484c1 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -114,7 +114,8 @@ #define ENABLE_2_3_1 1 #define ENABLE_SPLITTED_VERTEX_BUFFER (1 && ENABLE_2_3_1) -#define ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING (1 && ENABLE_SPLITTED_VERTEX_BUFFER) +#define ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING (0 && ENABLE_SPLITTED_VERTEX_BUFFER) +#define ENABLE_UNSIGNED_SHORT_INDEX_BUFFER (1 && ENABLE_SPLITTED_VERTEX_BUFFER) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 61c34d25c..a0cdbcf05 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -884,8 +884,13 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer.ibo)); for (size_t j = 0; j < render_path.sizes.size(); ++j) { IndexBuffer indices(render_path.sizes[j]); +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(render_path.offsets[j]), + static_cast(render_path.sizes[j] * sizeof(IBufferType)), static_cast(indices.data()))); +#else glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(render_path.offsets[j]), static_cast(render_path.sizes[j] * sizeof(unsigned int)), static_cast(indices.data()))); +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER const size_t triangles_count = render_path.sizes[j] / 3; for (size_t k = 0; k < triangles_count; ++k) { @@ -904,17 +909,17 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const } #else // get vertices data from vertex buffer on gpu - size_t floats_per_vertex = buffer.vertices.vertex_size_floats(); - VertexBuffer vertices = VertexBuffer(buffer.vertices.count * floats_per_vertex); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.vertices.id)); - glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, 0, buffer.vertices.data_size_bytes(), vertices.data())); + size_t floats_per_vertex = t_buffer.vertices.vertex_size_floats(); + VertexBuffer vertices = VertexBuffer(t_buffer.vertices.count * floats_per_vertex); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, t_buffer.vertices.id)); + glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, 0, t_buffer.vertices.data_size_bytes(), vertices.data())); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); // get indices data from index buffer on gpu MultiIndexBuffer indices; - for (size_t i = 0; i < buffer.indices.size(); ++i) { - indices.push_back(IndexBuffer(buffer.indices[i].count)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.indices[i].id)); + for (size_t i = 0; i < t_buffer.indices.size(); ++i) { + indices.push_back(IndexBuffer(t_buffer.indices[i].count)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, t_buffer.indices[i].id)); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, static_cast(indices.back().size() * sizeof(unsigned int)), indices.back().data())); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } @@ -968,15 +973,15 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const }; size_t out_vertices_count = 0; - unsigned int indices_per_segment = buffer.indices_per_segment(); - unsigned int start_vertex_offset = buffer.start_segment_vertex_offset(); - unsigned int end_vertex_offset = buffer.end_segment_vertex_offset(); + unsigned int indices_per_segment = t_buffer.indices_per_segment(); + unsigned int start_vertex_offset = t_buffer.start_segment_vertex_offset(); + unsigned int end_vertex_offset = t_buffer.end_segment_vertex_offset(); size_t i = 0; - for (const RenderPath& render_path : buffer.render_paths) { + for (const RenderPath& render_path : t_buffer.render_paths) { // get paths segments from buffer paths const IndexBuffer& ibuffer = indices[render_path.index_buffer_id]; - const Path& path = buffer.paths[render_path.path_id]; + const Path& path = t_buffer.paths[render_path.path_id]; float half_width = 0.5f * path.width; // clamp height to avoid artifacts due to z-fighting when importing the obj file into blender and similar @@ -1151,8 +1156,10 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const #if ENABLE_SPLITTED_VERTEX_BUFFER void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) { +#if !ENABLE_UNSIGNED_SHORT_INDEX_BUFFER // max vertex buffer size, in bytes static const size_t VBUFFER_THRESHOLD_BYTES = 64 * 1024 * 1024; +#endif // !ENABLE_UNSIGNED_SHORT_INDEX_BUFFER // max index buffer size, in bytes static const size_t IBUFFER_THRESHOLD_BYTES = 64 * 1024 * 1024; @@ -1166,7 +1173,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) int64_t indices_size = 0; for (const MultiIndexBuffer& buffers : indices) { for (const IndexBuffer& buffer : buffers) { +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + indices_size += SLIC3R_STDVEC_MEMSIZE(buffer, IBufferType); +#else indices_size += SLIC3R_STDVEC_MEMSIZE(buffer, unsigned int); +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER } } log_memory_used(label, vertices_size + indices_size); @@ -1181,7 +1192,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) auto add_indices_as_point = [](const GCodeProcessor::MoveVertex& curr, TBuffer& buffer, unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) { buffer.add_path(curr, ibuffer_id, indices.size(), move_id); +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + indices.push_back(static_cast(indices.size())); +#else indices.push_back(static_cast(indices.size())); +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER }; // format data into the buffers to be rendered as lines @@ -1287,20 +1302,35 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) static Vec3f prev_dir; static Vec3f prev_up; static float sq_prev_length; +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + auto store_triangle = [](IndexBuffer& indices, IBufferType i1, IBufferType i2, IBufferType i3) { +#else auto store_triangle = [](IndexBuffer& indices, unsigned int i1, unsigned int i2, unsigned int i3) { +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER indices.push_back(i1); indices.push_back(i2); indices.push_back(i3); }; +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + auto append_dummy_cap = [store_triangle](IndexBuffer& indices, IBufferType id) { +#else auto append_dummy_cap = [store_triangle](IndexBuffer& indices, unsigned int id) { +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER store_triangle(indices, id, id, id); store_triangle(indices, id, id, id); }; auto store_main_triangles = [&](IndexBuffer& indices, size_t vbuffer_size, const std::array& v_offsets) { +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + std::array v_ids; + for (size_t i = 0; i < v_ids.size(); ++i) { + v_ids[i] = static_cast(static_cast(vbuffer_size) + v_offsets[i]); + } +#else std::array v_ids; for (size_t i = 0; i < v_ids.size(); ++i) { v_ids[i] = static_cast(static_cast(vbuffer_size) + v_offsets[i]); } +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER // triangles starting cap store_triangle(indices, v_ids[0], v_ids[2], v_ids[1]); @@ -1557,7 +1587,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) static Vec3f prev_dir; static Vec3f prev_up; static float prev_length; +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + auto store_triangle = [](IndexBuffer& indices, IBufferType i1, IBufferType i2, IBufferType i3) { +#else auto store_triangle = [](IndexBuffer& indices, unsigned int i1, unsigned int i2, unsigned int i3) { +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER indices.push_back(i1); indices.push_back(i2); indices.push_back(i3); @@ -1758,7 +1792,12 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer // add another vertex buffer #if ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + if (v_multibuffer.back().size() * sizeof(float) > t_buffer.vertices.max_size_bytes() - t_buffer.max_vertices_per_segment_size_bytes()) { + std::cout << "Splitted v buffer at " << i << "\n"; +#else if (v_multibuffer.back().size() * sizeof(float) > VBUFFER_THRESHOLD_BYTES - t_buffer.max_vertices_per_segment_size_bytes()) { +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER v_multibuffer.push_back(VertexBuffer()); if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) { Path& last_path = t_buffer.paths.back(); @@ -1766,9 +1805,16 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) last_path.add_sub_path(prev, static_cast(v_multibuffer.size()) - 1, 0, i - 1); } } +#else +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + if (v_multibuffer.back().size() * sizeof(float) > t_buffer.vertices.max_size_bytes() - t_buffer.max_vertices_per_segment_size_bytes()) { +// std::cout << "Splitted v buffer at " << i << "\n"; + v_multibuffer.push_back(VertexBuffer()); + } #else if (v_multibuffer.back().size() * sizeof(float) > VBUFFER_THRESHOLD_BYTES - t_buffer.max_vertices_per_segment_size_bytes()) v_multibuffer.push_back(VertexBuffer()); +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER #endif // ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING VertexBuffer& v_buffer = v_multibuffer.back(); @@ -2005,7 +2051,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // if adding the indices for the current segment exceeds the threshold size of the current index buffer // create another index buffer +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - t_buffer.indices_per_segment_size_bytes()) { +#else if (i_multibuffer.back().size() * sizeof(unsigned int) >= IBUFFER_THRESHOLD_BYTES - t_buffer.indices_per_segment_size_bytes()) { +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER i_multibuffer.push_back(IndexBuffer()); vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { @@ -2016,7 +2066,12 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer // create another index buffer +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + if (curr_vertex_buffer.second * t_buffer.vertices.vertex_size_bytes() > t_buffer.vertices.max_size_bytes() - t_buffer.max_vertices_per_segment_size_bytes()) { +// std::cout << "Splitted i buffer at " << i << "\n"; +#else if (curr_vertex_buffer.second * t_buffer.vertices.vertex_size_bytes() > VBUFFER_THRESHOLD_BYTES - t_buffer.max_vertices_per_segment_size_bytes()) { +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER i_multibuffer.push_back(IndexBuffer()); ++curr_vertex_buffer.first; @@ -2062,7 +2117,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) const MultiIndexBuffer& i_multibuffer = indices[i]; for (const IndexBuffer& i_buffer : i_multibuffer) { size_t size_elements = i_buffer.size(); +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + size_t size_bytes = size_elements * sizeof(IBufferType); +#else size_t size_bytes = size_elements * sizeof(unsigned int); +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER // stores index buffer informations into TBuffer t_buffer.indices.push_back(IBuffer()); @@ -3055,7 +3114,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool const IBuffer& i_buffer = buffer.indices[sub_path.first.b_id]; unsigned int index = 0; glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(offset * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&index))); +#else glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(offset * sizeof(unsigned int)), static_cast(sizeof(unsigned int)), static_cast(&index))); +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); // gets the position from the vertices buffer on gpu @@ -3133,7 +3196,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (buffer->render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) delta_1st *= buffer->indices_per_segment(); +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + render_path->offsets.push_back(static_cast((sub_path.first.i_id + delta_1st) * sizeof(IBufferType))); +#else render_path->offsets.push_back(static_cast((sub_path.first.i_id + delta_1st) * sizeof(unsigned int))); +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER #if 0 // check sizes and offsets against index buffer size on gpu @@ -3141,7 +3208,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->indices[render_path->index_buffer_id].ibo)); glsafe(::glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &buffer_size)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + if (render_path->offsets.back() + render_path->sizes.back() * sizeof(IBufferType) > buffer_size) +#else if (render_path->offsets.back() + render_path->sizes.back() * sizeof(unsigned int) > buffer_size) +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER BOOST_LOG_TRIVIAL(error) << "GCodeViewer::refresh_render_paths: Invalid render path data"; #endif } @@ -3452,7 +3523,11 @@ void GCodeViewer::render_toolpaths() const for (const RenderPath& path : buffer.render_paths) { if (path.index_buffer_id == i_buffer_id) { +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); +#else glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_INT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_points_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -3468,7 +3543,11 @@ void GCodeViewer::render_toolpaths() const for (const RenderPath& path : buffer.render_paths) { if (path.index_buffer_id == index_buffer_id) { set_uniform_color(path.color, shader); +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); +#else glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_INT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_lines_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -3480,7 +3559,11 @@ void GCodeViewer::render_toolpaths() const for (const RenderPath& path : buffer.render_paths) { if (path.index_buffer_id == index_buffer_id) { set_uniform_color(path.color, shader); +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); +#else glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_INT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_triangles_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index f33a718dd..d80cc9dfc 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -19,12 +19,19 @@ namespace GUI { class GCodeViewer { +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + using IBufferType = unsigned short; +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER using Color = std::array; using VertexBuffer = std::vector; #if ENABLE_SPLITTED_VERTEX_BUFFER using MultiVertexBuffer = std::vector; #endif // ENABLE_SPLITTED_VERTEX_BUFFER +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + using IndexBuffer = std::vector; +#else using IndexBuffer = std::vector; +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER using MultiIndexBuffer = std::vector; static const std::vector Extrusion_Role_Colors; @@ -70,6 +77,11 @@ class GCodeViewer size_t count{ 0 }; size_t data_size_bytes() const { return count * vertex_size_bytes(); } +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + // We set 65536 as max count of vertices inside a vertex buffer to allow + // to use unsigned short in place of unsigned int for indices in the index buffer, to save memory + size_t max_size_bytes() const { return 65536 * vertex_size_bytes(); } +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER size_t vertex_size_floats() const { return position_size_floats() + normal_size_floats(); } size_t vertex_size_bytes() const { return vertex_size_floats() * sizeof(float); } @@ -291,7 +303,11 @@ class GCodeViewer } } #if ENABLE_SPLITTED_VERTEX_BUFFER +#if ENABLE_UNSIGNED_SHORT_INDEX_BUFFER + size_t indices_per_segment_size_bytes() const { return static_cast(indices_per_segment() * sizeof(IBufferType)); } +#else size_t indices_per_segment_size_bytes() const { return static_cast(indices_per_segment() * sizeof(unsigned int)); } +#endif // ENABLE_UNSIGNED_SHORT_INDEX_BUFFER #endif // ENABLE_SPLITTED_VERTEX_BUFFER unsigned int start_segment_vertex_offset() const { return 0; } unsigned int end_segment_vertex_offset() const {