diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2023-06-19 11:56:48 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2023-06-22 15:20:26 +0200 |
commit | f9d90c6fbab1d4f66dcc3fbc06f7f157693d04d1 (patch) | |
tree | a51ead7381684a8cb484b229f162241c0481c4ad /src/gui | |
parent | 2b9ef2eb44c084d39ef8324cfe1ae42a98b3038f (diff) |
rhi: Introduce multiview starting with OpenGL (ES)
Fixes: QTBUG-114770
Change-Id: Ibb1ced7f19d15a5116c60e95fd3e6b86ace63155
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/opengl/qopenglextensions_p.h | 4 | ||||
-rw-r--r-- | src/gui/opengl/qopenglfunctions.cpp | 4 | ||||
-rw-r--r-- | src/gui/rhi/qrhi.cpp | 80 | ||||
-rw-r--r-- | src/gui/rhi/qrhi.h | 7 | ||||
-rw-r--r-- | src/gui/rhi/qrhid3d11.cpp | 2 | ||||
-rw-r--r-- | src/gui/rhi/qrhid3d12.cpp | 2 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2.cpp | 20 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2_p.h | 6 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal.mm | 2 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan.cpp | 2 |
10 files changed, 124 insertions, 5 deletions
diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h index fdb9b51f06..58231545c6 100644 --- a/src/gui/opengl/qopenglextensions_p.h +++ b/src/gui/opengl/qopenglextensions_p.h @@ -59,7 +59,9 @@ public: StandardDerivatives = 0x02000000, ASTCTextureCompression = 0x04000000, ETC2TextureCompression = 0x08000000, - HalfFloatVertex = 0x10000000 + HalfFloatVertex = 0x10000000, + MultiView = 0x20000000, + MultiViewExtended = 0x40000000 }; Q_DECLARE_FLAGS(OpenGLExtensions, OpenGLExtension) diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index ee76987566..0b760eb2dd 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -348,6 +348,10 @@ static int qt_gl_resolve_extensions() extensions |= QOpenGLExtensions::StandardDerivatives; if (extensionMatcher.match("GL_ARB_half_float_vertex")) extensions |= QOpenGLExtensions::HalfFloatVertex; + if (extensionMatcher.match("GL_OVR_multiview")) + extensions |= QOpenGLExtensions::MultiView; + if (extensionMatcher.match("GL_OVR_multiview2")) + extensions |= QOpenGLExtensions::MultiViewExtended; if (ctx->isOpenGLES()) { if (format.majorVersion() >= 2) diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index 16c508b36c..6b3a4bd7c3 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -967,6 +967,22 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general") \value ThreeDimensionalTextureMipmaps Indicates that generating 3D texture mipmaps are supported. In practice this feature will be unsupported with Direct 3D 12. + + \value MultiView Indicates that multiview, see e.g. + \l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_multiview.html}{VK_KHR_multiview} + is supported. With OpenGL ES 2.0, Direct 3D 11, and OpenGL (ES) + implementations without \c{GL_OVR_multiview2} this feature will not be + supported. With Vulkan 1.1 and newer, and Direct 3D 12 multiview is + typically supported. When reported as supported, creating a + QRhiTextureRenderTarget with a QRhiColorAttachment that references a texture + array and has \l{QRhiColorAttachment::setMultiViewCount()}{multiViewCount} + set enables recording a render pass that uses multiview rendering. Note that + multiview is only available in combination with 2D texture arrays. It cannot + be used to optimize the rendering into individual textures (e.g. two, for + the left and right eyes). Rather, the target of a multiview render pass is + always a texture array, automatically rendering to the layer (array element) + corresponding to each view. Therefore this feature implies \l TextureArrays + as well. This enum value has been introduced in Qt 6.7. */ /*! @@ -2297,6 +2313,70 @@ QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer) */ /*! + \fn int QRhiColorAttachment::multiViewCount() const + + \return the currently set number of views. Defaults to 0 which indicates + the render target with this color attachment is not going to be used with + multiview rendering. + + \since 6.7 + */ + +/*! + \fn void QRhiColorAttachment::setMultiViewCount(int count) + + Sets the view \a count. Setting a value larger than 1 indicates that the + render target with this color attachment is going to be used with multiview + rendering. The default value is 0. Values smaller than 2 indicate no + multiview rendering. + + When \a count is set to \c 2 or greater, the color attachment must be + associated with a 2D texture array. layer() and multiViewCount() together + define the range of texture array elements that are targeted during + multiview rendering. + + For example, if \c layer is \c 0 and \c multiViewCount is \c 2, the texture + array must have 2 (or more) elements, and the multiview rendering will + target elements 0 and 1. The \c{gl_ViewIndex} variable in the shaders has a + value of \c 0 or \c 1 then, where view \c 0 corresponds to the texture array + element \c 0, and view \c 1 to the array element \c 1. + + \note Setting a \a count larger than 1, using a texture array as texture(), + and calling \l{QRhiCommandBuffer::beginPass()}{beginPass()} on a + QRhiTextureRenderTarget with this color attachment implies multiview + rendering for the entire render pass. multiViewCount() should not be set + unless multiview rendering is wanted. Multiview cannot be used with texture + types other than 2D texture arrays. (although 3D textures may work, + depending on the graphics API and backend; applications are nonetheless + advised not to rely on that and only use 2D texture arrays as the render + targets of multiview rendering) + + See + \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview} + for more details regarding multiview rendering. Do note that Qt requires + \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview2.txt}{GL_OVR_multiview2} + as well, when running on OpenGL (ES). + + Multiview rendering is available only when the + \l{QRhi::MultiView}{MultiView} feature is reported as supported from + \l{QRhi::isFeatureSupported()}{isFeatureSupported()}. + + \note For portability, be aware of limitations that exist for multiview + rendering with some of the graphics APIs. For example, OpenGL disallows + tessellation or geometry shaders with multiview. With other APIs, e.g. + Vulkan, some of these are optional features, the actual support depending + on the implementation. It is therefore recommended that multiview render + passes do not rely on any of the features that + \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview} + declares as unsupported. The one exception is shader stage outputs other + than \c{gl_Position} depending on \c{gl_ViewIndex}: that can be relied on + (even with OpenGL) because QRhi never reports multiview as supported without + \c{GL_OVR_multiview2} also being present. + + \since 6.7 + */ + +/*! \class QRhiTextureRenderTargetDescription \inmodule QtGui \since 6.6 diff --git a/src/gui/rhi/qrhi.h b/src/gui/rhi/qrhi.h index eb300f5873..585bead7b3 100644 --- a/src/gui/rhi/qrhi.h +++ b/src/gui/rhi/qrhi.h @@ -592,6 +592,9 @@ public: int resolveLevel() const { return m_resolveLevel; } void setResolveLevel(int level) { m_resolveLevel = level; } + int multiViewCount() const { return m_multiViewCount; } + void setMultiViewCount(int count) { m_multiViewCount = count; } + private: QRhiTexture *m_texture = nullptr; QRhiRenderBuffer *m_renderBuffer = nullptr; @@ -600,6 +603,7 @@ private: QRhiTexture *m_resolveTexture = nullptr; int m_resolveLayer = 0; int m_resolveLevel = 0; + int m_multiViewCount = 0; }; Q_DECLARE_TYPEINFO(QRhiColorAttachment, Q_RELOCATABLE_TYPE); @@ -1822,7 +1826,8 @@ public: OneDimensionalTextureMipmaps, HalfAttributes, RenderToOneDimensionalTexture, - ThreeDimensionalTextureMipmaps + ThreeDimensionalTextureMipmaps, + MultiView }; enum BeginFrameFlag { diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index feda195c51..f8284462ee 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -588,6 +588,8 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const return true; case QRhi::ThreeDimensionalTextureMipmaps: return true; + case QRhi::MultiView: + return false; default: Q_UNREACHABLE(); return false; diff --git a/src/gui/rhi/qrhid3d12.cpp b/src/gui/rhi/qrhid3d12.cpp index 7c55ff9f5c..55e2d626e0 100644 --- a/src/gui/rhi/qrhid3d12.cpp +++ b/src/gui/rhi/qrhid3d12.cpp @@ -638,6 +638,8 @@ bool QRhiD3D12::isFeatureSupported(QRhi::Feature feature) const return true; case QRhi::ThreeDimensionalTextureMipmaps: return false; // we generate mipmaps ourselves with compute and this is not implemented + case QRhi::MultiView: + return false; } return false; } diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 0a4bc8d01c..af5f07d6de 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -1009,6 +1009,15 @@ bool QRhiGles2::create(QRhi::Flags flags) caps.halfAttributes = f->hasOpenGLExtension(QOpenGLExtensions::HalfFloatVertex); + // We always require GL_OVR_multiview2 for symmetry with other backends. + caps.multiView = f->hasOpenGLExtension(QOpenGLExtensions::MultiView) + && f->hasOpenGLExtension(QOpenGLExtensions::MultiViewExtended); + if (caps.multiView) { + glFramebufferTextureMultiviewOVR = + reinterpret_cast<void(QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei)>( + ctx->getProcAddress(QByteArrayLiteral("glFramebufferTextureMultiviewOVR"))); + } + nativeHandlesStruct.context = ctx; contextLost = false; @@ -1371,6 +1380,8 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const return caps.texture1D; case QRhi::ThreeDimensionalTextureMipmaps: return caps.texture3D; + case QRhi::MultiView: + return caps.multiView && caps.maxTextureArraySize > 0; default: Q_UNREACHABLE_RETURN(false); } @@ -5554,8 +5565,13 @@ bool QGles2TextureRenderTarget::create() QGles2Texture *texD = QRHI_RES(QGles2Texture, texture); Q_ASSERT(texD->texture && texD->specified); if (texD->flags().testFlag(QRhiTexture::ThreeDimensional) || texD->flags().testFlag(QRhiTexture::TextureArray)) { - rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture, - colorAtt.level(), colorAtt.layer()); + if (it->multiViewCount() < 2) { + rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture, + colorAtt.level(), colorAtt.layer()); + } else { + rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture, + colorAtt.level(), colorAtt.layer(), colorAtt.multiViewCount()); + } } else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) { rhiD->glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->target + uint(colorAtt.layer()), texD->texture, diff --git a/src/gui/rhi/qrhigles2_p.h b/src/gui/rhi/qrhigles2_p.h index 76779fdca8..fecb15698f 100644 --- a/src/gui/rhi/qrhigles2_p.h +++ b/src/gui/rhi/qrhigles2_p.h @@ -909,6 +909,8 @@ public: GLsizei, const GLvoid *) = nullptr; void(QOPENGLF_APIENTRYP glFramebufferTexture1D)(GLenum, GLenum, GLenum, GLuint, GLint) = nullptr; + void(QOPENGLF_APIENTRYP glFramebufferTextureMultiviewOVR)(GLenum, GLenum, GLuint, GLint, + GLint, GLsizei) = nullptr; uint vao = 0; struct Caps { @@ -962,7 +964,8 @@ public: geometryShader(false), texture1D(false), hasDrawBuffersFunc(false), - halfAttributes(false) + halfAttributes(false), + multiView(false) { } int ctxMajor; int ctxMinor; @@ -1016,6 +1019,7 @@ public: uint texture1D : 1; uint hasDrawBuffersFunc : 1; uint halfAttributes : 1; + uint multiView : 1; } caps; QGles2SwapChain *currentSwapChain = nullptr; QSet<GLint> supportedCompressedFormats; diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 699e7a09be..e47ee9118a 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -833,6 +833,8 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const return false; case QRhi::ThreeDimensionalTextureMipmaps: return true; + case QRhi::MultiView: + return false; default: Q_UNREACHABLE(); return false; diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 4b7af8a89e..ae0e705106 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -4437,6 +4437,8 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const return true; case QRhi::ThreeDimensionalTextureMipmaps: return true; + case QRhi::MultiView: + return false; default: Q_UNREACHABLE_RETURN(false); } |