Bläddra i källkod

Workaround for love.graphics.clear + love.graphics.setCanvas AMD driver bug, take two.

Alex Szpakowski 9 år sedan
förälder
incheckning
6d6d805858

+ 14 - 25
src/modules/graphics/opengl/Graphics.cpp

@@ -438,27 +438,6 @@ void Graphics::reset()
 	origin();
 }
 
-void Graphics::dummyDraw()
-{
-	gl.prepareDraw();
-
-	// Draw a triangle using a single vertex position indexed 3 times. The
-	// triangle will be degenerate and won't be rasterized (so the pixel shader
-	// won't be run), and an index array with a single vertex is used so the
-	// vertex shader can't prevent the triangle from being degenerate by using
-	// gl_VertexID.
-	// NOTE: This code will have to be changed to use a vertex and index buffer,
-	// for it to work with a Core Profile GL3 backend. But the bug should be
-	// re-tested in that case as well.
-	const GLfloat vertex[] = {0.0f, 0.0f};
-	const GLushort indices[] = {0, 0, 0};
-
-	gl.useVertexAttribArrays(ATTRIBFLAG_POS);
-	glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, vertex);
-
-	gl.drawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices);
-}
-
 void Graphics::clear(Colorf c)
 {
 	Colorf nc = Colorf(c.r/255.0f, c.g/255.0f, c.b/255.0f, c.a/255.0f);
@@ -468,8 +447,13 @@ void Graphics::clear(Colorf c)
 	glClearColor(nc.r, nc.g, nc.b, nc.a);
 	glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-	if (gl.bugs.clearRequiresDummyDraw)
-		dummyDraw();
+	if (gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
+	{
+		// This seems to be enough to fix the bug for me. Other methods I've
+		// tried (e.g. dummy draws) don't work in all cases.
+		glUseProgram(0);
+		glUseProgram(Shader::current->getProgram());
+	}
 }
 
 void Graphics::clear(const std::vector<OptionalColorf> &colors)
@@ -535,8 +519,13 @@ void Graphics::clear(const std::vector<OptionalColorf> &colors)
 			glDrawBuffer(GL_COLOR_ATTACHMENT0);
 	}
 
-	if (gl.bugs.clearRequiresDummyDraw)
-		dummyDraw();
+	if (gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
+	{
+		// This seems to be enough to fix the bug for me. Other methods I've
+		// tried (e.g. dummy draws) don't work in all cases.
+		glUseProgram(0);
+		glUseProgram(Shader::current->getProgram());
+	}
 }
 
 void Graphics::discard(const std::vector<bool> &colorbuffers, bool stencil)

+ 0 - 2
src/modules/graphics/opengl/Graphics.h

@@ -518,8 +518,6 @@ private:
 	void restoreState(const DisplayState &s);
 	void restoreStateChecked(const DisplayState &s);
 
-	void dummyDraw();
-
 	void checkSetDefaultFont();
 
 	StrongRef<love::window::Window> currentWindow;

+ 1 - 1
src/modules/graphics/opengl/OpenGL.cpp

@@ -95,7 +95,7 @@ bool OpenGL::initContext()
 #if defined(LOVE_WINDOWS) || defined(LOVE_LINUX)
 	// See the comment in OpenGL.h.
 	if (getVendor() == VENDOR_AMD)
-		bugs.clearRequiresDummyDraw = true;
+		bugs.clearRequiresDriverTextureStateUpdate = true;
 #endif
 
 	contextInitialized = true;

+ 7 - 6
src/modules/graphics/opengl/OpenGL.h

@@ -172,14 +172,15 @@ public:
 	struct Bugs
 	{
 		// On AMD's Windows (and probably Linux) drivers,
-		// glBindFramebuffer + glClear + glBindFramebuffer won't work unless
-		// there's a draw in between the glBindFramebuffer calls (or unless
-		// there's some other thing that causes the driver to avoid the buggy
-		// "fast path", e.g. if the scissor test is active and its rectangle
-		// doesn't cover the whole framebuffer).
+		// glBindFramebuffer + glClear + glBindFramebuffer + draw(fbo_tex) won't
+		// work unless there's some kind of draw or state change which causes
+		// the texture's contents to update (just drawing the texture won't
+		// always do it).
+		// Activating shader program 0 and then activating the actual program
+		// seems to always 'fix' it for me.
 		// Bug observed January 2016 with multiple AMD GPUs and driver versions.
 		// https://love2d.org/forums/viewtopic.php?f=4&t=81496
-		bool clearRequiresDummyDraw;
+		bool clearRequiresDriverTextureStateUpdate;
 	} bugs;
 
 	OpenGL();

+ 5 - 0
src/modules/graphics/opengl/Shader.h

@@ -194,6 +194,11 @@ public:
 
 	const std::map<std::string, Object *> &getBoundRetainables() const;
 
+	GLuint getProgram() const
+	{
+		return program;
+	}
+
 	static std::string getGLSLVersion();
 	static bool isSupported();