Add RHI feature check for screen space derivatives

Fragment shader functions like fwidth() are useful for antialiasing
distance field text in the case of perspective projections. In order
to enable this as an alternative code path, we need to detect support.

- OpenGL: Supported with GL_OES_standard_derivatives or GLES3 and up
- Direct 3D: Supported for ps_2_x, so always supported on Direct3D 11
- Vulkan/Metal: Always supported

Task-number: QTBUG-84695
Change-Id: I5e3fa8014c808a9a2d639305c5e90ec25d44655c
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2020-06-08 12:16:14 +02:00
parent 3f6142f5a1
commit eb72d788fe
8 changed files with 22 additions and 3 deletions

View File

@ -92,6 +92,7 @@ public:
DiscardFramebuffer = 0x00400000,
Sized16Formats = 0x00800000,
TextureSwizzle = 0x01000000,
StandardDerivatives = 0x02000000,
};
Q_DECLARE_FLAGS(OpenGLExtensions, OpenGLExtension)

View File

@ -376,6 +376,8 @@ static int qt_gl_resolve_extensions()
extensions |= QOpenGLExtensions::PixelBufferObject;
if (extensionMatcher.match("GL_ARB_texture_swizzle") || extensionMatcher.match("GL_EXT_texture_swizzle"))
extensions |= QOpenGLExtensions::TextureSwizzle;
if (extensionMatcher.match("GL_OES_standard_derivatives"))
extensions |= QOpenGLExtensions::StandardDerivatives;
if (ctx->isOpenGLES()) {
if (format.majorVersion() >= 2)
@ -388,7 +390,8 @@ static int qt_gl_resolve_extensions()
| QOpenGLExtensions::MapBufferRange
| QOpenGLExtensions::FramebufferBlit
| QOpenGLExtensions::FramebufferMultisample
| QOpenGLExtensions::Sized8Formats;
| QOpenGLExtensions::Sized8Formats
| QOpenGLExtensions::StandardDerivatives;
#ifndef Q_OS_WASM
// WebGL 2.0 specification explicitly does not support texture swizzles
// https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.19
@ -445,6 +448,9 @@ static int qt_gl_resolve_extensions()
if (format.version() >= qMakePair(1, 4) || extensionMatcher.match("GL_SGIS_generate_mipmap"))
extensions |= QOpenGLExtensions::GenerateMipmap;
if (format.majorVersion() >= 2)
extensions |= QOpenGLExtensions::StandardDerivatives;
if (format.majorVersion() >= 3 || extensionMatcher.match("GL_ARB_framebuffer_object")) {
extensions |= QOpenGLExtensions::FramebufferMultisample
| QOpenGLExtensions::FramebufferBlit

View File

@ -1456,7 +1456,8 @@ public:
ReadBackNonBaseMipLevel,
TexelFetch,
RenderToNonBaseMipLevel,
UIntAttributes
UIntAttributes,
ScreenSpaceDerivatives
};
enum BeginFrameFlag {

View File

@ -479,6 +479,8 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::UIntAttributes:
return true;
case QRhi::ScreenSpaceDerivatives:
return true;
default:
Q_UNREACHABLE();
return false;

View File

@ -522,6 +522,7 @@ bool QRhiGles2::create(QRhi::Flags flags)
caps.texelFetch = caps.ctxMajor >= 3; // 3.0 or ES 3.0
caps.uintAttributes = caps.ctxMajor >= 3; // 3.0 or ES 3.0
caps.screenSpaceDerivatives = f->hasOpenGLExtension(QOpenGLExtensions::StandardDerivatives);
if (!caps.gles) {
f->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
@ -872,6 +873,8 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const
return caps.nonBaseLevelFramebufferTexture;
case QRhi::UIntAttributes:
return caps.uintAttributes;
case QRhi::ScreenSpaceDerivatives:
return caps.screenSpaceDerivatives;
default:
Q_UNREACHABLE();
return false;

View File

@ -869,7 +869,8 @@ public:
properMapBuffer(false),
nonBaseLevelFramebufferTexture(false),
texelFetch(false),
uintAttributes(true)
uintAttributes(true),
screenSpaceDerivatives(false)
{ }
int ctxMajor;
int ctxMinor;
@ -904,6 +905,7 @@ public:
uint nonBaseLevelFramebufferTexture : 1;
uint texelFetch : 1;
uint uintAttributes : 1;
uint screenSpaceDerivatives : 1;
} caps;
QGles2SwapChain *currentSwapChain = nullptr;
QVector<GLint> supportedCompressedFormats;

View File

@ -568,6 +568,8 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::UIntAttributes:
return true;
case QRhi::ScreenSpaceDerivatives:
return true;
default:
Q_UNREACHABLE();
return false;

View File

@ -4050,6 +4050,8 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::UIntAttributes:
return true;
case QRhi::ScreenSpaceDerivatives:
return true;
default:
Q_UNREACHABLE();
return false;