diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp
index 64a716508..e10b26f38 100644
--- a/src/libslic3r/Format/3mf.cpp
+++ b/src/libslic3r/Format/3mf.cpp
@@ -710,7 +710,7 @@ namespace Slic3r {
 #endif // ENABLE_RELOAD_FROM_DISK_FOR_3MF
 
         for (const IdToModelObjectMap::value_type& object : m_objects) {
-            if (object.second >= m_model->objects.size()) {
+            if (object.second >= int(m_model->objects.size())) {
                 add_error("Unable to find object");
                 return false;
             }
@@ -1395,7 +1395,7 @@ namespace Slic3r {
     {
         // deletes all non-built or non-instanced objects
         for (const IdToModelObjectMap::value_type& object : m_objects) {
-            if (object.second >= m_model->objects.size()) {
+            if (object.second >= int(m_model->objects.size())) {
                 add_error("Unable to find object");
                 return false;
             }
diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp
index 17e463b70..7ba0b5e8f 100644
--- a/src/libslic3r/SupportMaterial.cpp
+++ b/src/libslic3r/SupportMaterial.cpp
@@ -291,7 +291,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
 
     BOOST_LOG_TRIVIAL(info) << "Support generator - Creating base layers";
 
-    // Fill in intermediate layers between the top / bottom support contact layers, trimm them by the object.
+    // Fill in intermediate layers between the top / bottom support contact layers, trim them by the object.
     this->generate_base_layers(object, bottom_contacts, top_contacts, intermediate_layers, layer_support_areas);
 
 #ifdef SLIC3R_DEBUG
@@ -312,9 +312,9 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
 
     BOOST_LOG_TRIVIAL(info) << "Support generator - Creating interfaces";
 
-    // Propagate top / bottom contact layers to generate interface layers.
-    MyLayersPtr interface_layers = this->generate_interface_layers(
-        bottom_contacts, top_contacts, intermediate_layers, layer_storage);
+    // Propagate top / bottom contact layers to generate interface layers 
+    // and base interface layers (for soluble interface / non souble base only)
+    auto [interface_layers, base_interface_layers] = this->generate_interface_layers(bottom_contacts, top_contacts, intermediate_layers, layer_storage);
 
     BOOST_LOG_TRIVIAL(info) << "Support generator - Creating raft";
 
@@ -324,11 +324,15 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
     MyLayersPtr raft_layers = this->generate_raft_base(top_contacts, interface_layers, intermediate_layers, layer_storage);
 
 #ifdef SLIC3R_DEBUG
-    for (MyLayersPtr::const_iterator it = interface_layers.begin(); it != interface_layers.end(); ++ it)
+    for (const MyLayer *l : interface_layers)
         Slic3r::SVG::export_expolygons(
-            debug_out_path("support-interface-layers-%d-%lf.svg", iRun, (*it)->print_z), 
-            union_ex((*it)->polygons, false));
-#endif /* SLIC3R_DEBUG */
+            debug_out_path("support-interface-layers-%d-%lf.svg", iRun, l->print_z), 
+            union_ex(l->polygons, false));
+    for (const MyLayer *l : base_interface_layers)
+        Slic3r::SVG::export_expolygons(
+            debug_out_path("support-base-interface-layers-%d-%lf.svg", iRun, l->print_z), 
+            union_ex(l->polygons, false));
+#endif // SLIC3R_DEBUG
 
 /*
     // Clip with the pillars.
@@ -350,12 +354,13 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
     // Install support layers into the object.
     // A support layer installed on a PrintObject has a unique print_z.
     MyLayersPtr layers_sorted;
-    layers_sorted.reserve(raft_layers.size() + bottom_contacts.size() + top_contacts.size() + intermediate_layers.size() + interface_layers.size());
+    layers_sorted.reserve(raft_layers.size() + bottom_contacts.size() + top_contacts.size() + intermediate_layers.size() + interface_layers.size() + base_interface_layers.size());
     layers_append(layers_sorted, raft_layers);
     layers_append(layers_sorted, bottom_contacts);
     layers_append(layers_sorted, top_contacts);
     layers_append(layers_sorted, intermediate_layers);
     layers_append(layers_sorted, interface_layers);
+    layers_append(layers_sorted, base_interface_layers);
     // Sort the layers lexicographically by a raising print_z and a decreasing height.
     std::sort(layers_sorted.begin(), layers_sorted.end(), MyLayersPtrCompare());
     int layer_id = 0;
@@ -388,7 +393,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
     BOOST_LOG_TRIVIAL(info) << "Support generator - Generating tool paths";
 
     // Generate the actual toolpaths and save them into each layer.
-    this->generate_toolpaths(object.support_layers(), raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers);
+    this->generate_toolpaths(object.support_layers(), raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers, base_interface_layers);
 
 #ifdef SLIC3R_DEBUG
     {
@@ -1661,13 +1666,13 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
 // If no vec item with Z value >= of an internal threshold of fn_higher_equal is found, return vec.size()
 // If the initial idx is size_t(-1), then use binary search.
 // Otherwise search linearly upwards.
-template<typename IT, typename FN_HIGHER_EQUAL>
-size_t idx_higher_or_equal(IT begin, IT end, size_t idx, FN_HIGHER_EQUAL fn_higher_equal)
+template<typename IteratorType, typename IndexType, typename FN_HIGHER_EQUAL>
+IndexType idx_higher_or_equal(IteratorType begin, IteratorType end, IndexType idx, FN_HIGHER_EQUAL fn_higher_equal)
 {
     auto size = int(end - begin);
     if (size == 0) {
         idx = 0;
-    } else if (idx == size_t(-1)) {
+    } else if (idx == IndexType(-1)) {
         // First of the batch of layers per thread pool invocation. Use binary search.
         int idx_low  = 0;
         int idx_high = std::max(0, size - 1);
@@ -1687,8 +1692,8 @@ size_t idx_higher_or_equal(IT begin, IT end, size_t idx, FN_HIGHER_EQUAL fn_high
     }
     return idx;
 }
-template<typename T, typename FN_HIGHER_EQUAL>
-size_t idx_higher_or_equal(const std::vector<T>& vec, size_t idx, FN_HIGHER_EQUAL fn_higher_equal)
+template<typename T, typename IndexType, typename FN_HIGHER_EQUAL>
+IndexType idx_higher_or_equal(const std::vector<T>& vec, IndexType idx, FN_HIGHER_EQUAL fn_higher_equal)
 {
     return idx_higher_or_equal(vec.begin(), vec.end(), idx, fn_higher_equal);
 }
@@ -1983,7 +1988,7 @@ void PrintObjectSupportMaterial::generate_base_layers(
                 Polygons polygons_new;
 
                 // Use the precomputed layer_support_areas.
-                idx_object_layer_above = std::max(0, idx_lower_or_equal(object.layers().begin(), object.layers().end(), idx_object_layer_above,
+                idx_object_layer_above = std::max(0, idx_lower_or_equal(object.layers().begin(), object.layers().end(), idx_object_layer_above, 
                     [&layer_intermediate](const Layer *layer){ return layer->print_z <= layer_intermediate.print_z + EPSILON; }));
                 polygons_new = layer_support_areas[idx_object_layer_above];
 
@@ -2249,8 +2254,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
     return raft_layers;
 }
 
-// Convert some of the intermediate layers into top/bottom interface layers.
-PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_interface_layers(
+// Convert some of the intermediate layers into top/bottom interface layers as well as base interface layers.
+std::pair<PrintObjectSupportMaterial::MyLayersPtr, PrintObjectSupportMaterial::MyLayersPtr> PrintObjectSupportMaterial::generate_interface_layers(
     const MyLayersPtr   &bottom_contacts,
     const MyLayersPtr   &top_contacts,
     MyLayersPtr         &intermediate_layers,
@@ -2258,73 +2263,125 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_int
 {
 //    my $area_threshold = $self->interface_flow->scaled_spacing ** 2;
 
-    MyLayersPtr interface_layers;
+    std::pair<MyLayersPtr, MyLayersPtr> base_and_interface_layers;
+    MyLayersPtr &interface_layers       = base_and_interface_layers.first;
+    MyLayersPtr &base_interface_layers  = base_and_interface_layers.second;
+
+    // distinguish between interface and base interface layers
     // Contact layer is considered an interface layer, therefore run the following block only if support_material_interface_layers > 1.
-    if (! intermediate_layers.empty() && m_object_config->support_material_interface_layers.value > 1) {
+    // Contact layer needs a base_interface layer, therefore run the following block if support_material_interface_layers > 0, has soluble support and extruders are different.
+    bool   soluble_interface_non_soluble_base =
+        // Zero z-gap between the overhangs and the support interface.
+        m_slicing_params.soluble_interface && 
+        // Interface extruder soluble.
+        m_object_config->support_material_interface_extruder.value > 0 && m_print_config->filament_soluble.get_at(m_object_config->support_material_interface_extruder.value - 1) && 
+        // Base extruder: Either "print with active extruder" not soluble.
+        (m_object_config->support_material_extruder.value == 0 || ! m_print_config->filament_soluble.get_at(m_object_config->support_material_extruder.value - 1));
+    int num_interface_layers      = m_object_config->support_material_interface_layers.value;
+    int num_base_interface_layers = soluble_interface_non_soluble_base ? std::min(num_interface_layers / 2, 2) : 0;
+
+    if (! intermediate_layers.empty() && num_interface_layers > 1) {
         // For all intermediate layers, collect top contact surfaces, which are not further than support_material_interface_layers.
         BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_interface_layers() in parallel - start";
+        // Since the intermediate layer index starts at zero the number of interface layer needs to be reduced by 1.
+        -- num_interface_layers;
+        int num_interface_layers_only = num_interface_layers - num_base_interface_layers;
         interface_layers.assign(intermediate_layers.size(), nullptr);
+        if (num_base_interface_layers)
+            base_interface_layers.assign(intermediate_layers.size(), nullptr);
         tbb::spin_mutex layer_storage_mutex;
-        tbb::parallel_for(tbb::blocked_range<size_t>(0, intermediate_layers.size()),
-            [this, &bottom_contacts, &top_contacts, &intermediate_layers, &layer_storage, &layer_storage_mutex, &interface_layers](const tbb::blocked_range<size_t>& range) {
+        // Insert a new layer into base_interface_layers, if intersection with base exists.
+        auto insert_layer = [&layer_storage, &layer_storage_mutex](MyLayer &intermediate_layer, Polygons &bottom, Polygons &&top, const Polygons *subtract, SupporLayerType type) {
+            assert(! bottom.empty() || ! top.empty());
+            MyLayer &layer_new = layer_allocate(layer_storage, layer_storage_mutex, type);
+            layer_new.print_z    = intermediate_layer.print_z;
+            layer_new.bottom_z   = intermediate_layer.bottom_z;
+            layer_new.height     = intermediate_layer.height;
+            layer_new.bridging   = intermediate_layer.bridging;
+            // Merge top into bottom, unite them with a safety offset.
+            append(bottom, std::move(top));
+            layer_new.polygons   = union_(std::move(bottom), true);
+            // Subtract the interface from the base regions.
+            intermediate_layer.polygons = diff(intermediate_layer.polygons, layer_new.polygons, false);
+            if (subtract)
+                // Trim the base interface layer with the interface layer.
+                layer_new.polygons = diff(std::move(layer_new.polygons), *subtract);
+            //FIXME filter layer_new.polygons islands by a minimum area?
+//                  $interface_area = [ grep abs($_->area) >= $area_threshold, @$interface_area ];
+            return &layer_new;
+        };
+        tbb::parallel_for(tbb::blocked_range<int>(0, int(intermediate_layers.size())),
+            [&bottom_contacts, &top_contacts, &intermediate_layers, &insert_layer, num_interface_layers, num_base_interface_layers, num_interface_layers_only,
+             &interface_layers, &base_interface_layers](const tbb::blocked_range<int>& range) {                
+                // Gather the top / bottom contact layers intersecting with num_interface_layers resp. num_interface_layers_only intermediate layers above / below
+                // this intermediate layer.
                 // Index of the first top contact layer intersecting the current intermediate layer.
-                size_t idx_top_contact_first = size_t(-1);
+                auto idx_top_contact_first      = -1;
                 // Index of the first bottom contact layer intersecting the current intermediate layer.
-                size_t idx_bottom_contact_first = size_t(-1);
-                for (size_t idx_intermediate_layer = range.begin(); idx_intermediate_layer < range.end(); ++ idx_intermediate_layer) {
+                auto idx_bottom_contact_first   = -1;
+                auto num_intermediate = int(intermediate_layers.size());
+                for (int idx_intermediate_layer = range.begin(); idx_intermediate_layer < range.end(); ++ idx_intermediate_layer) {
                     MyLayer &intermediate_layer = *intermediate_layers[idx_intermediate_layer];
-                    // Top / bottom Z coordinate of a slab, over which we are collecting the top / bottom contact surfaces.
-                    coordf_t top_z    = intermediate_layers[std::min<int>(intermediate_layers.size()-1, idx_intermediate_layer + m_object_config->support_material_interface_layers - 1)]->print_z;
-                    coordf_t bottom_z = intermediate_layers[std::max<int>(0, int(idx_intermediate_layer) - int(m_object_config->support_material_interface_layers) + 1)]->bottom_z;
+                    // Top / bottom Z coordinate of a slab, over which we are collecting the top / bottom contact surfaces
+                    coordf_t top_z              = intermediate_layers[std::min(num_intermediate - 1, idx_intermediate_layer + num_interface_layers - 1)]->print_z;
+                    coordf_t top_inteface_z     = std::numeric_limits<coordf_t>::max();
+                    coordf_t bottom_z           = intermediate_layers[std::max(0, idx_intermediate_layer - num_interface_layers + 1)]->bottom_z;
+                    coordf_t bottom_interface_z = - std::numeric_limits<coordf_t>::max();
+                    if (num_base_interface_layers > 0) {
+                        // Some base interface layers will be generated.
+                        if (num_interface_layers_only == 0)
+                            // Only base interface layers to generate.
+                            std::swap(top_inteface_z, bottom_interface_z);
+                        else {
+                            top_inteface_z     = intermediate_layers[std::min(num_intermediate - 1, idx_intermediate_layer + num_interface_layers_only - 1)]->print_z;
+                            bottom_interface_z = intermediate_layers[std::max(0, idx_intermediate_layer - num_interface_layers_only)]->bottom_z;
+                        }
+                    }
                     // Move idx_top_contact_first up until above the current print_z.
                     idx_top_contact_first = idx_higher_or_equal(top_contacts, idx_top_contact_first, [&intermediate_layer](const MyLayer *layer){ return layer->print_z >= intermediate_layer.print_z; }); //  - EPSILON
                     // Collect the top contact areas above this intermediate layer, below top_z.
-                    Polygons polygons_top_contact_projected;
-                    for (size_t idx_top_contact = idx_top_contact_first; idx_top_contact < top_contacts.size(); ++ idx_top_contact) {
+                    Polygons polygons_top_contact_projected_interface;
+                    Polygons polygons_top_contact_projected_base;
+                    for (int idx_top_contact = idx_top_contact_first; idx_top_contact < int(top_contacts.size()); ++ idx_top_contact) {
                         const MyLayer &top_contact_layer = *top_contacts[idx_top_contact];
                         //FIXME maybe this adds one interface layer in excess?
                         if (top_contact_layer.bottom_z - EPSILON > top_z)
                             break;
-                        polygons_append(polygons_top_contact_projected, top_contact_layer.polygons);
+                        polygons_append(top_contact_layer.bottom_z - EPSILON > top_inteface_z ? polygons_top_contact_projected_base : polygons_top_contact_projected_interface, top_contact_layer.polygons);
                     }
                     // Move idx_bottom_contact_first up until touching bottom_z.
                     idx_bottom_contact_first = idx_higher_or_equal(bottom_contacts, idx_bottom_contact_first, [bottom_z](const MyLayer *layer){ return layer->print_z >= bottom_z - EPSILON; });
                     // Collect the top contact areas above this intermediate layer, below top_z.
-                    Polygons polygons_bottom_contact_projected;
-                    for (size_t idx_bottom_contact = idx_bottom_contact_first; idx_bottom_contact < bottom_contacts.size(); ++ idx_bottom_contact) {
+                    Polygons polygons_bottom_contact_projected_interface;
+                    Polygons polygons_bottom_contact_projected_base;
+                    for (int idx_bottom_contact = idx_bottom_contact_first; idx_bottom_contact < int(bottom_contacts.size()); ++ idx_bottom_contact) {
                         const MyLayer &bottom_contact_layer = *bottom_contacts[idx_bottom_contact];
                         if (bottom_contact_layer.print_z - EPSILON > intermediate_layer.bottom_z)
                             break;
-                        polygons_append(polygons_bottom_contact_projected, bottom_contact_layer.polygons);
+                        polygons_append(bottom_contact_layer.print_z - EPSILON > bottom_interface_z ? polygons_bottom_contact_projected_interface : polygons_bottom_contact_projected_base, bottom_contact_layer.polygons);
                     }
 
-                    if (polygons_top_contact_projected.empty() && polygons_bottom_contact_projected.empty())
-                        continue;
-
-                    // Insert a new layer into top_interface_layers.
-                    MyLayer &layer_new = layer_allocate(layer_storage, layer_storage_mutex,
-                        polygons_top_contact_projected.empty() ? sltBottomInterface : sltTopInterface);
-                    layer_new.print_z    = intermediate_layer.print_z;
-                    layer_new.bottom_z   = intermediate_layer.bottom_z;
-                    layer_new.height     = intermediate_layer.height;
-                    layer_new.bridging   = intermediate_layer.bridging;
-                    interface_layers[idx_intermediate_layer] = &layer_new;
-
-                    polygons_append(polygons_top_contact_projected, polygons_bottom_contact_projected);
-                    polygons_top_contact_projected = union_(polygons_top_contact_projected, true);
-                    layer_new.polygons = intersection(intermediate_layer.polygons, polygons_top_contact_projected);
-                    //FIXME filter layer_new.polygons islands by a minimum area?
-        //                $interface_area = [ grep abs($_->area) >= $area_threshold, @$interface_area ];
-                    intermediate_layer.polygons = diff(intermediate_layer.polygons, polygons_top_contact_projected, false);
+                    MyLayer *interface_layer = nullptr;
+                    if (! polygons_bottom_contact_projected_interface.empty() || ! polygons_top_contact_projected_interface.empty()) {
+                        interface_layer = insert_layer(
+                            intermediate_layer, polygons_bottom_contact_projected_interface, std::move(polygons_top_contact_projected_interface), nullptr,
+                            polygons_top_contact_projected_interface.empty() ? sltBottomInterface : sltTopInterface);
+                        interface_layers[idx_intermediate_layer] = interface_layer;
+                    }
+                    if (! polygons_bottom_contact_projected_base.empty() || ! polygons_top_contact_projected_base.empty())
+                        base_interface_layers[idx_intermediate_layer] = insert_layer(
+                            intermediate_layer, polygons_bottom_contact_projected_base, std::move(polygons_top_contact_projected_base), 
+                            interface_layer ? &interface_layer->polygons : nullptr, sltBase);
                 }
             });
 
         // Compress contact_out, remove the nullptr items.
         remove_nulls(interface_layers);
+        remove_nulls(base_interface_layers);
         BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_interface_layers() in parallel - start";
     }
     
-    return interface_layers;
+    return base_and_interface_layers;
 }
 
 static inline void fill_expolygons_generate_paths(
@@ -2373,9 +2430,9 @@ struct MyLayerExtruded
     const Polygons& polygons_to_extrude() const { return (m_polygons_to_extrude == nullptr) ? layer->polygons : *m_polygons_to_extrude; }
 
     bool could_merge(const MyLayerExtruded &other) const {
-        return ! this->empty() && ! other.empty() &&
+        return ! this->empty() && ! other.empty() && 
             std::abs(this->layer->height - other.layer->height) < EPSILON &&
-            this->layer->bridging == other.layer->bridging;
+            this->layer->bridging == other.layer->bridging; 
     }
 
     // Merge regions, perform boolean union over the merged polygons.
@@ -2921,7 +2978,8 @@ void PrintObjectSupportMaterial::generate_toolpaths(
     const MyLayersPtr   &bottom_contacts,
     const MyLayersPtr   &top_contacts,
     const MyLayersPtr   &intermediate_layers,
-    const MyLayersPtr   &interface_layers) const
+    const MyLayersPtr   &interface_layers,
+    const MyLayersPtr   &base_interface_layers) const
 {
 //    Slic3r::debugf "Generating patterns\n";
     // loop_interface_processor with a given circle radius.
@@ -2985,7 +3043,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
     // Insert the raft base layers.
     size_t n_raft_layers = size_t(std::max(0, int(m_slicing_params.raft_layers()) - 1));
     tbb::parallel_for(tbb::blocked_range<size_t>(0, n_raft_layers),
-        [this, &support_layers, &raft_layers,
+        [this, &support_layers, &raft_layers, 
             infill_pattern, &bbox_object, support_density, interface_density, raft_angle_1st_layer, raft_angle_base, raft_angle_interface, link_max_length_factor, with_sheath]
             (const tbb::blocked_range<size_t>& range) {
         for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id)
@@ -3085,22 +3143,27 @@ void PrintObjectSupportMaterial::generate_toolpaths(
         MyLayerExtruded                 top_contact_layer;
         MyLayerExtruded                 base_layer;
         MyLayerExtruded                 interface_layer;
+        MyLayerExtruded                 base_interface_layer;
         std::vector<LayerCacheItem>     overlaps;
     };
     std::vector<LayerCache>             layer_caches(support_layers.size(), LayerCache());
 
     tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, support_layers.size()),
-        [this, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &layer_caches, &loop_interface_processor,
+        [this, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &base_interface_layers, &layer_caches, &loop_interface_processor, 
             infill_pattern, &bbox_object, support_density, interface_density, interface_angle, &angles, link_max_length_factor, with_sheath]
             (const tbb::blocked_range<size_t>& range) {
         // Indices of the 1st layer in their respective container at the support layer height.
         size_t idx_layer_bottom_contact   = size_t(-1);
         size_t idx_layer_top_contact      = size_t(-1);
         size_t idx_layer_intermediate     = size_t(-1);
-        size_t idx_layer_inteface         = size_t(-1);
-        std::unique_ptr<Fill> filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(m_slicing_params.soluble_interface ? ipConcentric : ipRectilinear));
-        std::unique_ptr<Fill> filler_support   = std::unique_ptr<Fill>(Fill::new_from_type(infill_pattern));
+        size_t idx_layer_interface         = size_t(-1);
+        size_t idx_layer_base_interface    = size_t(-1);
+        auto filler_interface       = std::unique_ptr<Fill>(Fill::new_from_type(m_slicing_params.soluble_interface ? ipConcentric : ipRectilinear));
+        auto filler_base_interface  = std::unique_ptr<Fill>(base_interface_layers.empty() ? nullptr : Fill::new_from_type(ipRectilinear));
+        auto filler_support         = std::unique_ptr<Fill>(Fill::new_from_type(infill_pattern));
         filler_interface->set_bounding_box(bbox_object);
+        if (filler_base_interface)
+            filler_base_interface->set_bounding_box(bbox_object);
         filler_support->set_bounding_box(bbox_object);
         for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id)
         {
@@ -3112,21 +3175,25 @@ void PrintObjectSupportMaterial::generate_toolpaths(
             MyLayerExtruded &top_contact_layer    = layer_cache.top_contact_layer;
             MyLayerExtruded &base_layer           = layer_cache.base_layer;
             MyLayerExtruded &interface_layer      = layer_cache.interface_layer;
+            MyLayerExtruded &base_interface_layer = layer_cache.base_interface_layer;
             // Increment the layer indices to find a layer at support_layer.print_z.
             {
                 auto fun = [&support_layer](const MyLayer *l){ return l->print_z >= support_layer.print_z - EPSILON; };
                 idx_layer_bottom_contact  = idx_higher_or_equal(bottom_contacts,     idx_layer_bottom_contact,  fun);
                 idx_layer_top_contact     = idx_higher_or_equal(top_contacts,        idx_layer_top_contact,     fun);
                 idx_layer_intermediate    = idx_higher_or_equal(intermediate_layers, idx_layer_intermediate,    fun);
-                idx_layer_inteface        = idx_higher_or_equal(interface_layers,    idx_layer_inteface,        fun);
+                idx_layer_interface       = idx_higher_or_equal(interface_layers,    idx_layer_interface,       fun);
+                idx_layer_base_interface  = idx_higher_or_equal(base_interface_layers, idx_layer_base_interface,fun);
             }
             // Copy polygons from the layers.
             if (idx_layer_bottom_contact < bottom_contacts.size() && bottom_contacts[idx_layer_bottom_contact]->print_z < support_layer.print_z + EPSILON)
                 bottom_contact_layer.layer = bottom_contacts[idx_layer_bottom_contact];
             if (idx_layer_top_contact < top_contacts.size() && top_contacts[idx_layer_top_contact]->print_z < support_layer.print_z + EPSILON)
                 top_contact_layer.layer = top_contacts[idx_layer_top_contact];
-            if (idx_layer_inteface < interface_layers.size() && interface_layers[idx_layer_inteface]->print_z < support_layer.print_z + EPSILON)
-                interface_layer.layer = interface_layers[idx_layer_inteface];
+            if (idx_layer_interface < interface_layers.size() && interface_layers[idx_layer_interface]->print_z < support_layer.print_z + EPSILON)
+                interface_layer.layer = interface_layers[idx_layer_interface];
+            if (idx_layer_base_interface < base_interface_layers.size() && base_interface_layers[idx_layer_base_interface]->print_z < support_layer.print_z + EPSILON)
+                base_interface_layer.layer = base_interface_layers[idx_layer_base_interface];
             if (idx_layer_intermediate < intermediate_layers.size() && intermediate_layers[idx_layer_intermediate]->print_z < support_layer.print_z + EPSILON)
                 base_layer.layer = intermediate_layers[idx_layer_intermediate];
 
@@ -3151,7 +3218,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
                     top_contact_layer.merge(std::move(interface_layer));
             } 
 
-            if (! interface_layer.empty() && ! base_layer.empty()) {
+            if ( ! interface_layer.empty() && ! base_layer.empty()) {
                 // turn base support into interface when it's contained in our holes
                 // (this way we get wider interface anchoring)
                 //FIXME one wants to fill in the inner most holes of the interfaces, not all the holes.
@@ -3192,6 +3259,31 @@ void PrintObjectSupportMaterial::generate_toolpaths(
                     erSupportMaterialInterface, interface_flow);
             }
 
+            // Base interface layers under soluble interfaces
+            if ( ! base_interface_layer.empty() && ! base_interface_layer.polygons_to_extrude().empty()){ 
+                Fill *filler = filler_base_interface.get();
+                //FIXME Bottom interfaces are extruded with the briding flow. Some bridging layers have its height slightly reduced, therefore
+                // the bridging flow does not quite apply. Reduce the flow to area of an ellipse? (A = pi * a * b)
+                Flow interface_flow(
+                    float(base_interface_layer.layer->bridging ? base_interface_layer.layer->height : m_support_material_flow.width), // m_support_material_interface_flow.width)),
+                    float(base_interface_layer.layer->height),
+                    m_support_material_flow.nozzle_diameter,
+                    base_interface_layer.layer->bridging);
+                filler->angle   = interface_angle;
+                filler->spacing = m_support_material_interface_flow.spacing();
+                filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / interface_density));
+                fill_expolygons_generate_paths(
+                    // Destination
+                    base_interface_layer.extrusions, 
+                    //base_layer_interface.extrusions,
+                    // Regions to fill
+                    union_ex(base_interface_layer.polygons_to_extrude(), true),
+                    // Filler and its parameters
+                    filler, float(interface_density),
+                    // Extrusion parameters
+                    erSupportMaterial, interface_flow);
+            }
+
             // Base support or flange.
             if (! base_layer.empty() && ! base_layer.polygons_to_extrude().empty()) {
                 //FIXME When paralellizing, each thread shall have its own copy of the fillers.
@@ -3245,13 +3337,20 @@ void PrintObjectSupportMaterial::generate_toolpaths(
                     erSupportMaterial, flow);
             }
 
-            layer_cache.overlaps.reserve(4);
+            // Merge base_interface_layers to base_layers to avoid unneccessary retractions
+            if (! base_layer.empty() && ! base_interface_layer.empty() && ! base_layer.polygons_to_extrude().empty() && ! base_interface_layer.polygons_to_extrude().empty() &&
+                base_layer.could_merge(base_interface_layer))
+                base_layer.merge(std::move(base_interface_layer));
+
+            layer_cache.overlaps.reserve(5);
             if (! bottom_contact_layer.empty())
                 layer_cache.overlaps.push_back(&bottom_contact_layer);
             if (! top_contact_layer.empty())
                 layer_cache.overlaps.push_back(&top_contact_layer);
             if (! interface_layer.empty())
                 layer_cache.overlaps.push_back(&interface_layer);
+            if (! base_interface_layer.empty())
+                layer_cache.overlaps.push_back(&base_interface_layer);
             if (! base_layer.empty())
                 layer_cache.overlaps.push_back(&base_layer);
             // Sort the layers with the same print_z coordinate by their heights, thickest first.
@@ -3272,7 +3371,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
                 // where it overlaps with another support layer.
                 //FIXME When printing a briging path, what is an equivalent height of the squished extrudate of the same width?
                 // Collect overlapping top/bottom surfaces.
-                layer_cache_item.overlapping.reserve(16);
+                layer_cache_item.overlapping.reserve(20);
                 coordf_t bottom_z = layer_cache_item.layer_extruded->layer->bottom_print_z() + EPSILON;
                 for (int i = int(idx_layer_bottom_contact) - 1; i >= 0 && bottom_contacts[i]->print_z > bottom_z; -- i)
                     layer_cache_item.overlapping.push_back(bottom_contacts[i]);
@@ -3282,8 +3381,10 @@ void PrintObjectSupportMaterial::generate_toolpaths(
                     // Bottom contact layer may overlap with a base layer, which may be changed to interface layer.
                     for (int i = int(idx_layer_intermediate) - 1; i >= 0 && intermediate_layers[i]->print_z > bottom_z; -- i)
                         layer_cache_item.overlapping.push_back(intermediate_layers[i]);
-                    for (int i = int(idx_layer_inteface) - 1; i >= 0 && interface_layers[i]->print_z > bottom_z; -- i)
+                    for (int i = int(idx_layer_interface) - 1; i >= 0 && interface_layers[i]->print_z > bottom_z; -- i)
                         layer_cache_item.overlapping.push_back(interface_layers[i]);
+                    for (int i = int(idx_layer_base_interface) - 1; i >= 0 && base_interface_layers[i]->print_z > bottom_z; -- i)
+                        layer_cache_item.overlapping.push_back(base_interface_layers[i]);
                 }
                 std::sort(layer_cache_item.overlapping.begin(), layer_cache_item.overlapping.end(), MyLayersPtrCompare());
             }
@@ -3406,7 +3507,7 @@ sub clip_with_shape {
     
     foreach my $i (keys %$support) {
         // don't clip bottom layer with shape so that we 
-        // can generate a continuous base flange
+        // can generate a continuous base flange 
         // also don't clip raft layers
         next if $i == 0;
         next if $i < $self->object_config->raft_layers;
diff --git a/src/libslic3r/SupportMaterial.hpp b/src/libslic3r/SupportMaterial.hpp
index e579fd66f..030d2219a 100644
--- a/src/libslic3r/SupportMaterial.hpp
+++ b/src/libslic3r/SupportMaterial.hpp
@@ -201,12 +201,15 @@ private:
 	    const MyLayersPtr   &base_layers,
 	    MyLayerStorage      &layer_storage) const;
 
-    // Turn some of the base layers into interface layers.
-	MyLayersPtr generate_interface_layers(
+	// Turn some of the base layers into base interface layers.
+	// For soluble interfaces with non-soluble bases, print maximum two first interface layers with the base
+	// extruder to improve adhesion of the soluble filament to the base.
+	std::pair<MyLayersPtr, MyLayersPtr> generate_interface_layers(
 	    const MyLayersPtr   &bottom_contacts,
 	    const MyLayersPtr   &top_contacts,
 	    MyLayersPtr         &intermediate_layers,
 	    MyLayerStorage      &layer_storage) const;
+	
 
 	// Trim support layers by an object to leave a defined gap between
 	// the support volume and the object.
@@ -224,12 +227,13 @@ private:
 
 	// Produce the actual G-code.
 	void generate_toolpaths(
-        SupportLayerPtrs	&support_layers,
+		SupportLayerPtrs    &support_layers,
         const MyLayersPtr 	&raft_layers,
         const MyLayersPtr   &bottom_contacts,
         const MyLayersPtr   &top_contacts,
         const MyLayersPtr   &intermediate_layers,
-        const MyLayersPtr   &interface_layers) const;
+		const MyLayersPtr   &interface_layers,
+        const MyLayersPtr   &base_interface_layers) const;
 
 	// Following objects are not owned by SupportMaterial class.
 	const PrintObject 		*m_object;
@@ -246,7 +250,7 @@ private:
 	bool 				 m_can_merge_support_regions;
 
     coordf_t 			 m_support_layer_height_min;
-    // coordf_t		 	 m_support_layer_height_max;
+//	coordf_t		 	 m_support_layer_height_max;
 
 	coordf_t			 m_gap_xy;
 };