diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp
index 665c222ea0..e1e309a123 100644
--- a/common/gal/opengl/opengl_gal.cpp
+++ b/common/gal/opengl/opengl_gal.cpp
@@ -1923,7 +1923,7 @@ void OPENGL_GAL::Translate( const VECTOR2D& aVector )
 
 void OPENGL_GAL::Scale( const VECTOR2D& aScale )
 {
-    m_currentManager->Scale( aScale.x, aScale.y, 0.0f );
+    m_currentManager->Scale( aScale.x, aScale.y, 1.0f );
 }
 
 
diff --git a/common/view/view_group.cpp b/common/view/view_group.cpp
index 5888779c21..aaeefb6fc0 100644
--- a/common/view/view_group.cpp
+++ b/common/view/view_group.cpp
@@ -138,6 +138,9 @@ void VIEW_GROUP::ViewDraw( int aLayer, VIEW* aView ) const
     for( const std::pair<const int, std::vector<VIEW_ITEM*>>& entry : layer_item_map )
         layers[ layers_count++ ] = entry.first;
 
+    if( layers_count == 0 )
+        return;
+
     aView->SortLayers( layers, layers_count );
 
     // Now draw the layers in sorted order
diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h
index e340dd029d..5eca43709a 100644
--- a/include/gal/graphics_abstraction_layer.h
+++ b/include/gal/graphics_abstraction_layer.h
@@ -363,8 +363,8 @@ public:
      */
     virtual void SetLayerDepth( double aLayerDepth )
     {
-        assert( aLayerDepth <= m_depthRange.y );
-        assert( aLayerDepth >= m_depthRange.x );
+        wxCHECK_MSG( aLayerDepth <= m_depthRange.y, /* void */, "SetLayerDepth: below minimum" );
+        wxCHECK_MSG( aLayerDepth >= m_depthRange.x, /* void */, "SetLayerDepth: above maximum" );
 
         m_layerDepth = aLayerDepth;
     }
@@ -931,7 +931,7 @@ public:
      */
     inline void AdvanceDepth()
     {
-        m_layerDepth -= 0.05;
+        m_layerDepth -= 0.1;
     }
 
     /**
diff --git a/include/layer_ids.h b/include/layer_ids.h
index 95a2114ea8..b72c0c503f 100644
--- a/include/layer_ids.h
+++ b/include/layer_ids.h
@@ -174,6 +174,8 @@ enum NETNAMES_LAYER_ID: int
 /// Macro for obtaining netname layer for a given PCB layer
 #define NETNAMES_LAYER_INDEX( layer )   ( NETNAMES_LAYER_ID_START + layer )
 
+#define GAL_UI_LAYER_COUNT 10
+
 /**
  *  GAL layers are "virtual" layers, i.e. not tied into design data.
  *  Some layers here are shared between applications.
@@ -258,6 +260,10 @@ enum GAL_LAYER_ID: int
     LAYER_BITMAP_START,
     LAYER_BITMAP_END = LAYER_BITMAP_START + PCB_LAYER_ID_COUNT,
 
+    // Layers for drawing on-canvas UI
+    LAYER_UI_START,
+    LAYER_UI_END = LAYER_UI_START + GAL_UI_LAYER_COUNT,
+
     GAL_LAYER_ID_END
 };
 
diff --git a/pcbnew/generators/pcb_tuning_pattern.cpp b/pcbnew/generators/pcb_tuning_pattern.cpp
index c37f39d234..c10467e6de 100644
--- a/pcbnew/generators/pcb_tuning_pattern.cpp
+++ b/pcbnew/generators/pcb_tuning_pattern.cpp
@@ -129,8 +129,8 @@ public:
 
     void ViewGetLayers( int aLayers[], int& aCount ) const override
     {
-        aLayers[0] = LAYER_SELECT_OVERLAY;
-        aLayers[1] = LAYER_GP_OVERLAY;
+        aLayers[0] = LAYER_UI_START;
+        aLayers[1] = LAYER_UI_START + 1;
         aCount = 2;
     }
 
@@ -138,19 +138,19 @@ public:
     {
         KIGFX::GAL* gal = aView->GetGAL();
         bool        viewFlipped = gal->IsFlippedX();
-        bool        drawingDropShadows = ( aLayer == LAYER_GP_OVERLAY );
+        bool        drawingDropShadows = ( aLayer == LAYER_UI_START );
 
-        gal->PushDepth();
-        gal->SetLayerDepth( gal->GetMinDepth() );
+        gal->Save();
+        gal->Scale( { 1., 1. } );
 
-        KIGFX::PREVIEW::TEXT_DIMS headerDims = KIGFX::PREVIEW::GetConstantGlyphHeight( gal, -3 );
-        KIGFX::PREVIEW::TEXT_DIMS textDims = KIGFX::PREVIEW::GetConstantGlyphHeight( gal, -2 );
+        KIGFX::PREVIEW::TEXT_DIMS headerDims = KIGFX::PREVIEW::GetConstantGlyphHeight( gal, -2 );
+        KIGFX::PREVIEW::TEXT_DIMS textDims = KIGFX::PREVIEW::GetConstantGlyphHeight( gal, -1 );
         KIFONT::FONT*             font = KIFONT::FONT::GetFont();
         const KIFONT::METRICS&    fontMetrics = KIFONT::METRICS::Default();
         TEXT_ATTRIBUTES           textAttrs;
 
         int      glyphWidth = textDims.GlyphSize.x;
-        VECTOR2I margin( KiROUND( glyphWidth * 0.4 ), KiROUND( glyphWidth * 0.9 ) );
+        VECTOR2I margin( KiROUND( glyphWidth * 0.4 ), KiROUND( glyphWidth ) );
         VECTOR2I size( glyphWidth * 25 + margin.x * 2, headerDims.GlyphSize.y + textDims.GlyphSize.y );
         VECTOR2I offset( margin.x * 2, -( size.y + margin.y * 2 ) );
 
@@ -158,13 +158,14 @@ public:
         {
             gal->SetIsFill( true );
             gal->SetIsStroke( true );
-            gal->SetLineWidth( 1 );
+            gal->SetLineWidth( gal->GetScreenWorldMatrix().GetScale().x * 2 );
             gal->SetStrokeColor( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT ) );
-            gal->SetFillColor( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
+            KIGFX::COLOR4D bgColor( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
+            gal->SetFillColor( bgColor.WithAlpha( 0.9 ) );
 
             gal->DrawRectangle( GetPosition() + offset - margin,
                                 GetPosition() + offset + size + margin );
-            gal->PopDepth();
+            gal->Restore();
             return;
         }
 
@@ -221,7 +222,7 @@ public:
         gal->SetStrokeColor( m_current > m_max ? red : normal );
         font->Draw( gal, m_maxText, textPos, textAttrs, fontMetrics );
 
-        gal->PopDepth();
+        gal->Restore();
     }
 
 protected:
@@ -2060,7 +2061,9 @@ int DRAWING_TOOL::PlaceTuningPattern( const TOOL_EVENT& aEvent )
                     m_preview.FreeItems();
 
                     for( EDA_ITEM* item : dummyPattern->GetPreviewItems( generatorTool, m_frame ) )
+                    {
                         m_preview.Add( item );
+                    }
 
                     generatorTool->Router()->StopRouting();
 
diff --git a/pcbnew/pcb_draw_panel_gal.cpp b/pcbnew/pcb_draw_panel_gal.cpp
index 4133f3b27b..d27c36708a 100644
--- a/pcbnew/pcb_draw_panel_gal.cpp
+++ b/pcbnew/pcb_draw_panel_gal.cpp
@@ -57,9 +57,21 @@ using namespace std::placeholders;
 
 const int GAL_LAYER_ORDER[] =
 {
+    LAYER_UI_START + 9,
+    LAYER_UI_START + 8,
+    LAYER_UI_START + 7,
+    LAYER_UI_START + 6,
+    LAYER_UI_START + 5,
+    LAYER_UI_START + 4,
+    LAYER_UI_START + 3,
+    LAYER_UI_START + 2,
+    LAYER_UI_START + 1,
+    LAYER_UI_START,
+
     LAYER_GP_OVERLAY,
     LAYER_SELECT_OVERLAY,
     LAYER_CONFLICTS_SHADOW,
+
     LAYER_DRC_ERROR, LAYER_DRC_WARNING, LAYER_DRC_EXCLUSION, LAYER_MARKER_SHADOWS,
     LAYER_PAD_NETNAMES, LAYER_VIA_NETNAMES,
     Dwgs_User, ZONE_LAYER_FOR( Dwgs_User ),
@@ -358,6 +370,9 @@ void PCB_DRAW_PANEL_GAL::SetHighContrastLayer( PCB_LAYER_ID aLayer )
         for( int i : layers )
             rSettings->SetLayerIsHighContrast( i );
 
+        for( int i = LAYER_UI_START; i < LAYER_UI_END; ++i )
+            rSettings->SetLayerIsHighContrast( i );
+
         // Pads should be shown too
         if( aLayer == B_Cu )
         {
@@ -396,6 +411,9 @@ void PCB_DRAW_PANEL_GAL::SetTopLayer( PCB_LAYER_ID aLayer )
     for( auto layer : layers )
         m_view->SetTopLayer( layer );
 
+    for( int i = LAYER_UI_START; i < LAYER_UI_END; i++ )
+        m_view->SetTopLayer( i );
+
     // Extra layers that are brought to the top if a F.* or B.* is selected
     const std::vector<int> frontLayers = {
         F_Cu, F_Adhes, F_Paste, F_SilkS, F_Mask, F_Fab, F_CrtYd, LAYER_PADS_SMD_FR,
@@ -483,6 +501,9 @@ void PCB_DRAW_PANEL_GAL::SyncLayersVisibility( const BOARD* aBoard )
     for( int i = LAYER_BITMAP_START; i < LAYER_BITMAP_END; i++ )
         m_view->SetLayerVisible( i, true );
 
+    for( int i = LAYER_UI_START; i < LAYER_UI_END; i++ )
+        m_view->SetLayerVisible( i, true );
+
     // Enable some layers that are GAL specific
     m_view->SetLayerVisible( LAYER_PAD_PLATEDHOLES, true );
     m_view->SetLayerVisible( LAYER_PAD_HOLEWALLS, true );
@@ -583,10 +604,10 @@ void PCB_DRAW_PANEL_GAL::setDefaultLayerOrder()
 
         // MW: Gross hack to make SetTopLayer bring the correct bitmap layer to
         // the top of the other bitmaps, but still below all the other layers
-        if( layer < LAYER_BITMAP_START )
-            m_view->SetLayerOrder( layer, i );
-        else
+        if( layer >= LAYER_BITMAP_START && layer < LAYER_BITMAP_END )
             m_view->SetLayerOrder( layer, i - KIGFX::VIEW::TOP_LAYER_MODIFIER );
+        else
+            m_view->SetLayerOrder( layer, i );
     }
 }
 
@@ -705,6 +726,12 @@ void PCB_DRAW_PANEL_GAL::setDefaultLayerDeps()
     m_view->SetLayerTarget( LAYER_DRAWINGSHEET, KIGFX::TARGET_NONCACHED );
     m_view->SetLayerDisplayOnly( LAYER_DRAWINGSHEET ) ;
     m_view->SetLayerDisplayOnly( LAYER_GRID );
+
+    for( int i = LAYER_UI_START; i < LAYER_UI_END; ++i )
+    {
+        m_view->SetLayerTarget( i, KIGFX::TARGET_OVERLAY );
+        m_view->SetLayerDisplayOnly( i );
+    }
 }
 
 
diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp
index fa54f1ebeb..cd443f94b0 100644
--- a/pcbnew/router/pns_kicad_iface.cpp
+++ b/pcbnew/router/pns_kicad_iface.cpp
@@ -1694,7 +1694,7 @@ void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool
 void PNS_KICAD_IFACE::DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance )
 {
     ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aLine, m_view );
-    pitem->SetDepth( ROUTER_PREVIEW_ITEM::PathOverlayDepth );
+    pitem->SetDepth( pitem->GetOriginDepth() - ROUTER_PREVIEW_ITEM::PathOverlayDepth );
 
     COLOR4D color;
 
diff --git a/pcbnew/router/router_preview_item.cpp b/pcbnew/router/router_preview_item.cpp
index f3c854ac02..f827ac2290 100644
--- a/pcbnew/router/router_preview_item.cpp
+++ b/pcbnew/router/router_preview_item.cpp
@@ -69,7 +69,7 @@ ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem, KIGFX::VIEW* a
     // initialize variables, overwritten by Update( aItem ), if aItem != NULL
     m_type = PR_SHAPE;
     m_width = ( aFlags & PNS_SEMI_SOLID ) ? 1 : 0;
-    m_depth = 0;
+    m_depth = m_originDepth = aView->GetLayerOrder( m_originLayer );
 
     if( aItem )
         Update( aItem );
@@ -86,14 +86,14 @@ ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const SHAPE& aShape, KIGFX::VIEW* aVie
     m_hole = nullptr;
 
     m_clearance = -1;
-    m_originLayer = m_layer = LAYER_SELECT_OVERLAY ;
+    m_originLayer = m_layer = LAYER_SELECT_OVERLAY;
 
     m_showClearance = false;
 
     // initialize variables, overwritten by Update( aItem ), if aItem != NULL
     m_type = PR_SHAPE;
     m_width = 0;
-    m_depth = 0;
+    m_depth = m_originDepth = aView->GetLayerOrder( m_originLayer );
 }
 
 
@@ -124,7 +124,7 @@ void ROUTER_PREVIEW_ITEM::Update( const PNS::ITEM* aItem )
     m_layer = m_originLayer;
     m_color = getLayerColor( m_originLayer );
     m_color.a = 0.8;
-    m_depth = BaseOverlayDepth - aItem->Layers().Start();
+    m_depth = m_originDepth - ( aItem->Layers().Start() * LayerDepthFactor );
 
     switch( aItem->Kind() )
     {
@@ -148,7 +148,7 @@ void ROUTER_PREVIEW_ITEM::Update( const PNS::ITEM* aItem )
         m_type = PR_SHAPE;
         m_width = 0;
         m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 );
-        m_depth = ViaOverlayDepth;
+        m_depth = m_originDepth - ( PCB_LAYER_ID_COUNT * LayerDepthFactor );
 
         delete m_shape;
         m_shape = nullptr;
@@ -477,7 +477,7 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
         // N.B. The order of draw here is important
         // Cairo doesn't current support z-ordering, so we need
         // to draw the clearance first to ensure it is in the background
-        gal->SetLayerDepth( ClearanceOverlayDepth );
+        gal->SetLayerDepth( m_originDepth );
 
         //TODO(snh) Add configuration option for the color/alpha here
         gal->SetStrokeColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.9 ) );
@@ -520,7 +520,7 @@ const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor( int aLayer ) const
 }
 
 
-const int ROUTER_PREVIEW_ITEM::ClearanceOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 10;
-const int ROUTER_PREVIEW_ITEM::BaseOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 20;
-const int ROUTER_PREVIEW_ITEM::ViaOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 50;
-const int ROUTER_PREVIEW_ITEM::PathOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 55;
+//const int ROUTER_PREVIEW_ITEM::ClearanceOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 10;
+//const int ROUTER_PREVIEW_ITEM::BaseOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 20;
+//const int ROUTER_PREVIEW_ITEM::ViaOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 50;
+//const int ROUTER_PREVIEW_ITEM::PathOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 55;
diff --git a/pcbnew/router/router_preview_item.h b/pcbnew/router/router_preview_item.h
index 9339482791..96418ad675 100644
--- a/pcbnew/router/router_preview_item.h
+++ b/pcbnew/router/router_preview_item.h
@@ -61,13 +61,21 @@ public:
         PR_SHAPE
     };
 
-    // fixme: shouldn't this go to VIEW?
-    static const int ClearanceOverlayDepth;
-    static const int BaseOverlayDepth;
-    static const int ViaOverlayDepth;
-    static const int PathOverlayDepth;
+    /**
+     * We draw this item on a single layer, but we stack up all the layers from
+     * the various components that form this preview item.  In order to make this
+     * work, we need to map that layer stack onto fractional depths that are less
+     * than 1.0 so that this preview item doesn't draw on top of other overlays
+     * that are in front of it.
+     *
+     * This factor is chosen to be fairly small so that we can fit an entire
+     * GAL layer stack into the space of one view group sublayer (which is
+     * currently hard-coded via GAL::AdvanceDepth take a depth of 0.1)
+     */
+    static constexpr double LayerDepthFactor = 0.0001;
+    static constexpr double PathOverlayDepth = LayerDepthFactor * LAYER_ZONE_END;
 
-    ROUTER_PREVIEW_ITEM( const SHAPE& aShape, KIGFX::VIEW* aView = nullptr);
+    ROUTER_PREVIEW_ITEM( const SHAPE& aShape, KIGFX::VIEW* aView = nullptr );
     ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem = nullptr, KIGFX::VIEW* aView = nullptr,
                          int aFlags = 0 );
     ~ROUTER_PREVIEW_ITEM();
@@ -81,6 +89,8 @@ public:
     void SetClearance( int aClearance ) { m_clearance = aClearance; }
     void ShowClearance( bool aEnabled ) { m_showClearance = aEnabled; }
 
+    double GetOriginDepth() const { return m_originDepth; }
+
 #if defined(DEBUG)
     void Show( int aA, std::ostream& aB ) const override {}
 #endif
@@ -125,6 +135,7 @@ private:
     int            m_clearance;
     bool           m_showClearance;
 
+    double         m_originDepth;
     double         m_depth;
 
     KIGFX::COLOR4D m_color;