opengl: restructure code for computing format support.

This commit is contained in:
Alex Szpakowski
2022-04-23 13:15:58 -03:00
parent 28a64c2b29
commit ee336e5393
2 changed files with 77 additions and 82 deletions
+33 -40
View File
@@ -112,7 +112,7 @@ Graphics::Graphics()
, bufferMapMemory(nullptr) , bufferMapMemory(nullptr)
, bufferMapMemorySize(2 * 1024 * 1024) , bufferMapMemorySize(2 * 1024 * 1024)
, defaultBuffers() , defaultBuffers()
, supportedFormats() , pixelFormatUsage()
{ {
gl = OpenGL(); gl = OpenGL();
@@ -1670,6 +1670,13 @@ void Graphics::initCapabilities()
for (int i = 0; i < TEXTURE_MAX_ENUM; i++) for (int i = 0; i < TEXTURE_MAX_ENUM; i++)
capabilities.textureTypes[i] = gl.isTextureTypeSupported((TextureType) i); capabilities.textureTypes[i] = gl.isTextureTypeSupported((TextureType) i);
for (int i = 0; i < PIXELFORMAT_MAX_ENUM; i++)
{
auto format = (PixelFormat) i;
pixelFormatUsage[i][0] = computePixelFormatUsage(format, false);
pixelFormatUsage[i][1] = computePixelFormatUsage(format, true);
}
} }
PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const
@@ -1697,56 +1704,27 @@ PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool
} }
} }
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable)
{ {
if (sRGB) uint32 usage = OpenGL::getPixelFormatUsageFlags(format);
{
format = getSRGBPixelFormat(format);
sRGB = false;
}
bool rendertarget = (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0; if (readable && (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) == 0)
bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0; return 0;
bool computewrite = (usage & PIXELFORMATUSAGEFLAGS_COMPUTEWRITE) != 0;
format = getSizedFormat(format, rendertarget, readable);
OptionalBool &supported = supportedFormats[format][rendertarget ? 1 : 0][readable ? 1 : 0][computewrite ? 1 : 0][sRGB ? 1 : 0];
if (supported.hasValue)
return supported.value;
uint32 supportedflags = OpenGL::getPixelFormatUsageFlags(format);
if ((usage & supportedflags) != usage)
{
supported.set(false);
return supported.value;
}
if (!rendertarget)
{
supported.set(true);
return supported.value;
}
// Even though we might have the necessary OpenGL version or extension, // Even though we might have the necessary OpenGL version or extension,
// drivers are still allowed to throw FRAMEBUFFER_UNSUPPORTED when attaching // drivers are still allowed to throw FRAMEBUFFER_UNSUPPORTED when attaching
// a texture to a FBO whose format the driver doesn't like. So we should // a texture to a FBO whose format the driver doesn't like. So we should
// test with an actual FBO. // test with an actual FBO.
GLuint texture = 0;
GLuint renderbuffer = 0;
// Avoid the test for depth/stencil formats - not every GL version // Avoid the test for depth/stencil formats - not every GL version
// guarantees support for depth/stencil-only render targets (which we would // guarantees support for depth/stencil-only render targets (which we would
// need for the test below to work), and we already do some finagling in // need for the test below to work), and we already do some finagling in
// convertPixelFormat to try to use the best-supported internal // convertPixelFormat to try to use the best-supported internal
// depth/stencil format for a particular driver. // depth/stencil format for a particular driver.
if (isPixelFormatDepthStencil(format)) if ((usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0 && !isPixelFormatDepthStencil(format))
{ {
supported.set(true); GLuint texture = 0;
return true; GLuint renderbuffer = 0;
} bool sRGB = isPixelFormatSRGB(format);
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, !readable, sRGB); OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, !readable, sRGB);
@@ -1790,7 +1768,8 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbuffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbuffer);
} }
supported.set(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
usage &= ~PIXELFORMATUSAGEFLAGS_RENDERTARGET;
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, current_fbo); gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, current_fbo);
gl.deleteFramebuffer(fbo); gl.deleteFramebuffer(fbo);
@@ -1800,8 +1779,22 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
if (renderbuffer != 0) if (renderbuffer != 0)
glDeleteRenderbuffers(1, &renderbuffer); glDeleteRenderbuffers(1, &renderbuffer);
}
return supported.value; return usage;
}
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB)
{
if (sRGB)
format = getSRGBPixelFormat(format);
bool rendertarget = (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0;
bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0;
format = getSizedFormat(format, rendertarget, readable);
return (usage & pixelFormatUsage[format][readable ? 1 : 0]) == usage;
} }
} // opengl } // opengl
+4 -2
View File
@@ -155,6 +155,8 @@ private:
void setDebug(bool enable); void setDebug(bool enable);
uint32 computePixelFormatUsage(PixelFormat format, bool readable);
std::unordered_map<RenderTargets, GLuint, CachedFBOHasher> framebufferObjects; std::unordered_map<RenderTargets, GLuint, CachedFBOHasher> framebufferObjects;
bool windowHasStencil; bool windowHasStencil;
GLuint mainVAO; GLuint mainVAO;
@@ -170,8 +172,8 @@ private:
// Only needed for buffer types that can be bound to shaders. // Only needed for buffer types that can be bound to shaders.
StrongRef<love::graphics::Buffer> defaultBuffers[BUFFERUSAGE_MAX_ENUM]; StrongRef<love::graphics::Buffer> defaultBuffers[BUFFERUSAGE_MAX_ENUM];
// [rendertarget][readable][computewrite][srgb] // [non-readable, readable]
OptionalBool supportedFormats[PIXELFORMAT_MAX_ENUM][2][2][2][2]; uint32 pixelFormatUsage[PIXELFORMAT_MAX_ENUM][2];
}; // Graphics }; // Graphics