diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index e827694da..2eb48e8b7 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -438,6 +438,27 @@ 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); @@ -446,6 +467,9 @@ 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(); } void Graphics::clear(const std::vector &colors) @@ -510,6 +534,9 @@ void Graphics::clear(const std::vector &colors) else glDrawBuffer(GL_COLOR_ATTACHMENT0); } + + if (gl.bugs.clearRequiresDummyDraw) + dummyDraw(); } void Graphics::discard(const std::vector &colorbuffers, bool stencil) diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index d602af78f..e50c2c839 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -518,6 +518,8 @@ private: void restoreState(const DisplayState &s); void restoreStateChecked(const DisplayState &s); + void dummyDraw(); + void checkSetDefaultFont(); StrongRef currentWindow; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index e3f10ce70..b18b8aa96 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -90,6 +90,14 @@ bool OpenGL::initContext() initVendor(); initMatrices(); + bugs = {}; + +#if defined(LOVE_WINDOWS) || defined(LOVE_LINUX) + // See the comment in OpenGL.h. + if (getVendor() == VENDOR_AMD) + bugs.clearRequiresDummyDraw = true; +#endif + contextInitialized = true; return true; diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index d1d98a470..51af13c1f 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -169,6 +169,19 @@ public: int framebufferBinds; } stats; + 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). + // Bug observed January 2016 with multiple AMD GPUs and driver versions. + // https://love2d.org/forums/viewtopic.php?f=4&t=81496 + bool clearRequiresDummyDraw; + } bugs; + OpenGL(); /**