diff --git a/src/core/gpu_hw_d3d11.cpp b/src/core/gpu_hw_d3d11.cpp
index 9acef095f..1f7fe907e 100644
--- a/src/core/gpu_hw_d3d11.cpp
+++ b/src/core/gpu_hw_d3d11.cpp
@@ -118,19 +118,30 @@ void GPU_HW_D3D11::UpdateSettings()
 {
   GPU_HW::UpdateSettings();
 
-  bool needs_new_framebuffer, needs_new_shaders;
-  UpdateHWSettings(&needs_new_framebuffer, &needs_new_shaders);
+  bool framebuffer_changed, shaders_changed;
+  UpdateHWSettings(&framebuffer_changed, &shaders_changed);
 
-  if (needs_new_framebuffer)
+  m_context->ClearState();
+
+  if (framebuffer_changed)
   {
     m_host_display->ClearDisplayTexture();
     CreateFramebuffer();
   }
-  if (needs_new_shaders)
-    CompileShaders();
 
-  RestoreGraphicsAPIState();
-  UpdateDisplay();
+  if (shaders_changed)
+  {
+    DestroyShaders();
+    CompileShaders();
+  }
+
+  if (framebuffer_changed)
+  {
+    RestoreGraphicsAPIState();
+    UpdateDepthBufferFromMaskBit();
+    UpdateDisplay();
+    ResetGraphicsAPIState();
+  }
 }
 
 void GPU_HW_D3D11::MapBatchVertexPointer(u32 required_vertices)
@@ -208,12 +219,10 @@ bool GPU_HW_D3D11::CreateFramebuffer()
     BlitTexture(m_vram_texture.GetD3DRTV(), 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight(),
                 old_vram_texture.GetD3DSRV(), 0, 0, old_vram_texture.GetWidth(), old_vram_texture.GetHeight(),
                 old_vram_texture.GetWidth(), old_vram_texture.GetHeight(), linear_filter);
-    UpdateDepthBufferFromMaskBit();
   }
 
   m_context->OMSetRenderTargets(1, m_vram_texture.GetD3DRTVArray(), nullptr);
   SetFullVRAMDirtyRectangle();
-  RestoreGraphicsAPIState();
   return true;
 }
 
@@ -456,6 +465,22 @@ bool GPU_HW_D3D11::CompileShaders()
   return true;
 }
 
+void GPU_HW_D3D11::DestroyShaders()
+{
+  m_display_pixel_shaders = {};
+  m_vram_update_depth_pixel_shader.Reset();
+  m_vram_copy_pixel_shader.Reset();
+  m_vram_write_pixel_shader.Reset();
+  m_vram_read_pixel_shader.Reset();
+  m_vram_interlaced_fill_pixel_shader.Reset();
+  m_vram_fill_pixel_shader.Reset();
+  m_copy_pixel_shader.Reset();
+  m_screen_quad_vertex_shader.Reset();
+  m_batch_pixel_shaders = {};
+  m_batch_vertex_shaders = {};
+  m_batch_input_layout.Reset();
+}
+
 void GPU_HW_D3D11::UploadUniformBuffer(const void* data, u32 data_size)
 {
   Assert(data_size <= MAX_UNIFORM_BUFFER_SIZE);
diff --git a/src/core/gpu_hw_d3d11.h b/src/core/gpu_hw_d3d11.h
index ef1203a3c..bc8f3543e 100644
--- a/src/core/gpu_hw_d3d11.h
+++ b/src/core/gpu_hw_d3d11.h
@@ -59,6 +59,7 @@ private:
   bool CreateStateObjects();
 
   bool CompileShaders();
+  void DestroyShaders();
   void SetViewport(u32 x, u32 y, u32 width, u32 height);
   void SetScissor(u32 x, u32 y, u32 width, u32 height);
   void SetViewportAndScissor(u32 x, u32 y, u32 width, u32 height);
diff --git a/src/core/gpu_hw_opengl.cpp b/src/core/gpu_hw_opengl.cpp
index 592d1ec52..6d8844389 100644
--- a/src/core/gpu_hw_opengl.cpp
+++ b/src/core/gpu_hw_opengl.cpp
@@ -133,7 +133,13 @@ void GPU_HW_OpenGL::UpdateSettings()
   if (shaders_changed)
     CompilePrograms();
 
-  UpdateDisplay();
+  if (framebuffer_changed)
+  {
+    RestoreGraphicsAPIState();
+    UpdateDepthBufferFromMaskBit();
+    UpdateDisplay();
+    ResetGraphicsAPIState();
+  }
 }
 
 void GPU_HW_OpenGL::MapBatchVertexPointer(u32 required_vertices)
@@ -274,8 +280,6 @@ bool GPU_HW_OpenGL::CreateFramebuffer()
     glEnable(GL_SCISSOR_TEST);
     old_vram_texture.Destroy();
     glDeleteFramebuffers(1, &old_vram_fbo);
-
-    UpdateDepthBufferFromMaskBit();
   }
 
   SetFullVRAMDirtyRectangle();
diff --git a/src/core/gpu_hw_vulkan.cpp b/src/core/gpu_hw_vulkan.cpp
index ad4ec4dff..12f2b0ae8 100644
--- a/src/core/gpu_hw_vulkan.cpp
+++ b/src/core/gpu_hw_vulkan.cpp
@@ -145,11 +145,11 @@ void GPU_HW_Vulkan::UpdateSettings()
   // this has to be done here, because otherwise we're using destroyed pipelines in the same cmdbuffer
   if (framebuffer_changed)
   {
+    RestoreGraphicsAPIState();
     UpdateDepthBufferFromMaskBit();
     UpdateDisplay();
+    ResetGraphicsAPIState();
   }
-
-  RestoreGraphicsAPIState();
 }
 
 void GPU_HW_Vulkan::MapBatchVertexPointer(u32 required_vertices)
diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp
index 673f39f9e..acbe22aa6 100644
--- a/src/core/host_interface.cpp
+++ b/src/core/host_interface.cpp
@@ -499,9 +499,7 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings)
         g_settings.display_aspect_ratio != old_settings.display_aspect_ratio ||
         g_settings.gpu_pgxp_enable != old_settings.gpu_pgxp_enable)
     {
-      g_gpu->RestoreGraphicsAPIState();
       g_gpu->UpdateSettings();
-      g_gpu->ResetGraphicsAPIState();
     }
 
     if (g_settings.gpu_pgxp_enable != old_settings.gpu_pgxp_enable ||