summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2023-06-19 11:56:48 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2023-06-22 15:20:26 +0200
commitf9d90c6fbab1d4f66dcc3fbc06f7f157693d04d1 (patch)
treea51ead7381684a8cb484b229f162241c0481c4ad /src
parent2b9ef2eb44c084d39ef8324cfe1ae42a98b3038f (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')
-rw-r--r--src/gui/opengl/qopenglextensions_p.h4
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp4
-rw-r--r--src/gui/rhi/qrhi.cpp80
-rw-r--r--src/gui/rhi/qrhi.h7
-rw-r--r--src/gui/rhi/qrhid3d11.cpp2
-rw-r--r--src/gui/rhi/qrhid3d12.cpp2
-rw-r--r--src/gui/rhi/qrhigles2.cpp20
-rw-r--r--src/gui/rhi/qrhigles2_p.h6
-rw-r--r--src/gui/rhi/qrhimetal.mm2
-rw-r--r--src/gui/rhi/qrhivulkan.cpp2
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);
}