Fix a freeze on Intel drivers when using mipmapped Canvases

Fixes #1585

Also disallow generateMipmaps on depth/stencil canvases because it's not really supported.
This commit is contained in:
Alex Szpakowski
2020-12-26 16:37:37 -04:00
parent 4f730e930b
commit 95ab4054ff
3 changed files with 20 additions and 21 deletions
+3
View File
@@ -69,6 +69,9 @@ Canvas::Canvas(const Settings &settings)
filter.mipmap = defaultMipmapFilter;
}
if (settings.mipmaps == MIPMAPS_AUTO && isPixelFormatDepthStencil(format))
throw love::Exception("Automatic mipmap generation cannot be used for depth/stencil Canvases.");
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
const Graphics::Capabilities &caps = gfx->getCapabilities();
+17 -17
View File
@@ -67,19 +67,6 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
if (texType == TEXTURE_VOLUME)
nlayers = std::max(layers >> mip, 1);
GLuint tempframebuffer = 0;
if (mip > 0)
{
// Some Intel drivers on Windows don't like reusing the same
// FBO for different sized attachments, so use a temporary one
// to clear smaller mips.
// https://github.com/love2d/love/issues/1585
glGenFramebuffers(1, &tempframebuffer);
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, tempframebuffer);
}
else
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, framebuffer);
for (int layer = nlayers - 1; layer >= 0; layer--)
{
for (int face = faces - 1; face >= 0; face--)
@@ -112,9 +99,6 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
}
}
}
if (tempframebuffer != 0)
gl.deleteFramebuffer(tempframebuffer);
}
}
@@ -278,8 +262,18 @@ bool Canvas::loadVolatile()
return false;
}
// All mipmap levels need to be initialized - for color formats we can
// clear the base mip and use glGenerateMipmap after that's done. Depth
// and stencil formats don't always support glGenerateMipmap so we need
// to individually clear each mip level in that case. We avoid doing that
// for color formats because of an Intel driver bug:
// https://github.com/love2d/love/issues/1585
int clearmips = 1;
if (isPixelFormatDepthStencil(format))
clearmips = mipmapCount;
// Create a canvas-local FBO used for glReadPixels as well as MSAA blitting.
status = createFBO(fbo, texType, format, texture, texType == TEXTURE_VOLUME ? depth : layers, mipmapCount);
status = createFBO(fbo, texType, format, texture, texType == TEXTURE_VOLUME ? depth : layers, clearmips);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
@@ -290,6 +284,9 @@ bool Canvas::loadVolatile()
}
return false;
}
if (clearmips < mipmapCount && getMipmapMode() != MIPMAPS_NONE)
generateMipmaps();
}
if (!isReadable() || actualSamples > 0)
@@ -488,6 +485,9 @@ void Canvas::generateMipmaps()
if (getMipmapCount() == 1 || getMipmapMode() == MIPMAPS_NONE)
throw love::Exception("generateMipmaps can only be called on a Canvas which was created with mipmaps enabled.");
if (isPixelFormatDepthStencil(format))
throw love::Exception("generateMipmaps cannot be called on a depth/stencil Canvas.");
gl.bindTextureToUnit(this, 0, false);
GLenum gltextype = OpenGL::getGLTextureType(texType);
-4
View File
@@ -587,10 +587,6 @@ void Graphics::endPass()
if (rt.canvas->getMipmapMode() == Canvas::MIPMAPS_AUTO && rt.mipmap == 0)
rt.canvas->generateMipmaps();
}
int dsmipmap = rts.depthStencil.mipmap;
if (depthstencil != nullptr && depthstencil->getMipmapMode() == Canvas::MIPMAPS_AUTO && dsmipmap == 0)
depthstencil->generateMipmaps();
}
void Graphics::clear(OptionalColorf c, OptionalInt stencil, OptionalDouble depth)