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, DiscardFramebuffer = 0x00400000,
Sized16Formats = 0x00800000, Sized16Formats = 0x00800000,
TextureSwizzle = 0x01000000, TextureSwizzle = 0x01000000,
StandardDerivatives = 0x02000000,
}; };
Q_DECLARE_FLAGS(OpenGLExtensions, OpenGLExtension) Q_DECLARE_FLAGS(OpenGLExtensions, OpenGLExtension)

View File

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

View File

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

View File

@ -479,6 +479,8 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
return true; return true;
case QRhi::UIntAttributes: case QRhi::UIntAttributes:
return true; return true;
case QRhi::ScreenSpaceDerivatives:
return true;
default: default:
Q_UNREACHABLE(); Q_UNREACHABLE();
return false; 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.texelFetch = caps.ctxMajor >= 3; // 3.0 or ES 3.0
caps.uintAttributes = 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) { if (!caps.gles) {
f->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); f->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
@ -872,6 +873,8 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const
return caps.nonBaseLevelFramebufferTexture; return caps.nonBaseLevelFramebufferTexture;
case QRhi::UIntAttributes: case QRhi::UIntAttributes:
return caps.uintAttributes; return caps.uintAttributes;
case QRhi::ScreenSpaceDerivatives:
return caps.screenSpaceDerivatives;
default: default:
Q_UNREACHABLE(); Q_UNREACHABLE();
return false; return false;

View File

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

View File

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

View File

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