diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 22e3a71f9ede4a06d4e55330446a2323bdc2682f..67cf04dda8c688547b2543a500b7e9b8512e4a7f 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -1140,6 +1140,14 @@ LLRender::~LLRender()
 
 void LLRender::init()
 {
+	if (mDummyVAO != 0)
+	{ //bind a dummy vertex array object so we're core profile compliant
+#ifdef GL_ARB_vertex_array_object
+		glDeleteVertexArrays(1, &mDummyVAO);
+#endif
+		mDummyVAO = 0;
+	}
+
 	if (sGLCoreProfile && !LLVertexBuffer::sUseVAO)
 	{ //bind a dummy vertex array object so we're core profile compliant
 #ifdef GL_ARB_vertex_array_object
@@ -1147,28 +1155,12 @@ void LLRender::init()
 		glBindVertexArray(mDummyVAO);
 #endif
 	}
-
-
-	llassert_always(mBuffer.isNull()) ;
-	stop_glerror();
-	mBuffer = new LLVertexBuffer(immediate_mask, 0);
-	mBuffer->allocateBuffer(4096, 0, TRUE);
-	mBuffer->getVertexStrider(mVerticesp);
-	mBuffer->getTexCoord0Strider(mTexcoordsp);
-	mBuffer->getColorStrider(mColorsp);
 	stop_glerror();
+	restoreVertexBuffers();
 }
 
 void LLRender::shutdown()
 {
-    if (mDummyVAO != 0)
-    { //bind a dummy vertex array object so we're core profile compliant
-#ifdef GL_ARB_vertex_array_object
-        glDeleteVertexArrays(1, &mDummyVAO);
-#endif
-        mDummyVAO = 0;
-    }
-
 	for (U32 i = 0; i < mTexUnits.size(); i++)
 	{
 		delete mTexUnits[i];
@@ -1182,7 +1174,16 @@ void LLRender::shutdown()
 		delete mLightState[i];
 	}
 	mLightState.clear();
-	mBuffer = NULL ;
+
+	mBuffer = nullptr;
+	
+	if (mDummyVAO != 0)
+    { //bind a dummy vertex array object so we're core profile compliant
+#ifdef GL_ARB_vertex_array_object
+        glDeleteVertexArrays(1, &mDummyVAO);
+#endif
+        mDummyVAO = 0;
+    }
 }
 
 void LLRender::refreshState(void)
@@ -1197,14 +1198,38 @@ void LLRender::refreshState(void)
 	}
 	
 	mTexUnits[active_unit]->activate();
+	stop_glerror();
 
 	setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]);
+	stop_glerror();
 	
 	setAlphaRejectSettings(mCurrAlphaFunc, mCurrAlphaFuncVal);
+	stop_glerror();
 
 	mDirty = false;
 }
 
+void LLRender::resetVertexBuffers()
+{
+	mBuffer = nullptr;
+}
+
+void LLRender::restoreVertexBuffers()
+{
+	llassert_always(mBuffer.isNull());
+	stop_glerror();
+	mBuffer = new LLVertexBuffer(immediate_mask, 0);
+	stop_glerror();
+	mBuffer->allocateBuffer(4096, 0, TRUE);
+	stop_glerror();
+	mBuffer->getVertexStrider(mVerticesp);
+	stop_glerror();
+	mBuffer->getTexCoord0Strider(mTexcoordsp);
+	stop_glerror();
+	mBuffer->getColorStrider(mColorsp);
+	stop_glerror();
+}
+
 void LLRender::syncLightState()
 {
     LLGLSLShader *shader = LLGLSLShader::sCurBoundShaderPtr;
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 0a966932d8a2c8a65c5fc9b1005c9c8d2713eb86..667d8ec02d53b0cc5aa3cbc17a623fafc701d1b5 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -376,6 +376,9 @@ class LLRender
 	// Needed when the render context has changed and invalidated the current state
 	void refreshState(void);
 
+	void resetVertexBuffers();
+	void restoreVertexBuffers();
+
 	void translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
 	void scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
 	void rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z);
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index def4a0e0b669570a9d445fc622811c4837e0c5cc..470bc637340490ae79d621a1a099fe910bf47125 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -5498,6 +5498,7 @@ void LLViewerWindow::stopGL(BOOL save_state)
 		stop_glerror();
 
 		LLVOPartGroup::destroyGL();
+		stop_glerror();
 
 		LLViewerDynamicTexture::destroyGL();
 		stop_glerror();
@@ -5506,8 +5507,10 @@ void LLViewerWindow::stopGL(BOOL save_state)
 		{
 			gPipeline.destroyGL();
 		}
+		stop_glerror();
 		
 		gBox.cleanupGL();
+		stop_glerror();
 		
 		if(gPostProcess)
 		{
@@ -5521,12 +5524,18 @@ void LLViewerWindow::stopGL(BOOL save_state)
 		stop_glerror();
 
 		//unload shader's
-		while (LLGLSLShader::sInstances.size())
+		while (!LLGLSLShader::sInstances.empty())
 		{
 			LLGLSLShader* shader = *(LLGLSLShader::sInstances.begin());
 			shader->unload();
 		}
 		
+		gGL.resetVertexBuffers();
+
+		LLVertexBuffer::cleanupClass();
+
+		stop_glerror();
+		
 		LL_INFOS() << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemory.value() << " bytes" << LL_ENDL;
 	}
 }
@@ -5542,7 +5551,9 @@ void LLViewerWindow::restoreGL(const std::string& progress_message)
 		LL_INFOS() << "Restoring GL..." << LL_ENDL;
 		gGLManager.mIsDisabled = FALSE;
 		
+		gGL.init();
 		initGLDefaults();
+		gGL.refreshState();
 		LLGLState::restoreGL();
 		
 		gTextureList.restoreGL();
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 2938b81fd8d8e02a0701993ff4d9d56517f4ece4..1b3b619d23bf4d37377692b4259af01dbdaa521b 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -7395,6 +7395,7 @@ void LLPipeline::doResetVertexBuffers(bool forced)
 	}
 	LLVOPartGroup::destroyGL();
 
+	gGL.resetVertexBuffers();
 	SUBSYSTEM_CLEANUP(LLVertexBuffer);
 	
 	if (LLVertexBuffer::sGLCount > 0)
@@ -7420,6 +7421,7 @@ void LLPipeline::doResetVertexBuffers(bool forced)
 	LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping);
 
 	LLVOPartGroup::restoreGL();
+	gGL.restoreVertexBuffers();
 }
 
 void LLPipeline::renderObjects(U32 type, U32 mask, bool texture, bool batch_texture)