From 7c6f53b128d57cfb746509b10b1abdcd5b65205e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 19 Jun 2020 15:39:34 +0200 Subject: Make it possible to specify device extensions in a future proof manner Follow the pattern of QQuickRenderTarget and QQuickGraphicsDevice. This makes it possible to integrate with real world frameworks, such as OpenXR, that, especially with Vulkan, expect this level of configurability. (i.e. one pulls the list of extensions to be enabled on the device, that then needs to be taken into account by Quick, otherwise it will end up with a VkDevice that is not usable by OpenXR) Same goes when integrating native Vulkan rendering into an application: if certain extensions need to be enabled on the VkDevice, today that can only be done with an environment variable which is not entirely ideal. These issues are now solved by a new simple (and extensible) container QQuickGraphicsConfiguration, which is associated with the QQuickWindow. When applicable, the scene graph will then pick up the relevant settings. Expand the related docs everywhere. Also rename the vulkanInstance() to defaultVulkanInstance() to emphasize that it is the instance that is used for normal QQuickWindows, and is not provided when redirecting via QQuickRenderControl. While we are at it, include another obvious candidate: the use-depth-buffer flag. It turns out that Quick3D's Overlay render mode can be pretty problematic if Quick writes to the depth buffer. In order to avoid relying on environment variables (QSG_NO_DEPTH_BUFFER), we now provide a proper API for controlling that as well. Change-Id: Iefdb62c1f53de8bd34e3f0d393b00c5020d6188a Reviewed-by: Andy Nichols --- src/quick/scenegraph/qsgcontext.cpp | 5 ++++- src/quick/scenegraph/qsgcontext_p.h | 6 +++++- src/quick/scenegraph/qsgdefaultrendercontext.cpp | 12 ++++++------ src/quick/scenegraph/qsgdefaultrendercontext_p.h | 10 +++++++--- src/quick/scenegraph/qsgrenderloop.cpp | 2 +- src/quick/scenegraph/qsgrhilayer.cpp | 6 +++--- src/quick/scenegraph/qsgrhisupport.cpp | 8 +++++--- src/quick/scenegraph/qsgrhisupport_p.h | 4 ++-- 8 files changed, 33 insertions(+), 20 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 761f35bdd6..d550b2c66a 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -341,10 +341,13 @@ void QSGRenderContext::invalidate() { } -void QSGRenderContext::prepareSync(qreal devicePixelRatio, QRhiCommandBuffer *cb) +void QSGRenderContext::prepareSync(qreal devicePixelRatio, + QRhiCommandBuffer *cb, + const QQuickGraphicsConfiguration &config) { Q_UNUSED(devicePixelRatio); Q_UNUSED(cb); + Q_UNUSED(config); } void QSGRenderContext::beginNextFrame(QSGRenderer *renderer, diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index 650accd28d..fc3e3fc854 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -94,6 +94,7 @@ class QRhi; class QRhiRenderTarget; class QRhiRenderPassDescriptor; class QRhiCommandBuffer; +class QQuickGraphicsConfiguration; Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_RENDERLOOP) Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_COMPILATION) @@ -174,7 +175,10 @@ public: using RenderPassCallback = void (*)(void *); - virtual void prepareSync(qreal devicePixelRatio, QRhiCommandBuffer *cb); + virtual void prepareSync(qreal devicePixelRatio, + QRhiCommandBuffer *cb, + const QQuickGraphicsConfiguration &config); + virtual void beginNextFrame(QSGRenderer *renderer, RenderPassCallback mainPassRecordingStart, RenderPassCallback mainPassRecordingEnd, diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp index 1c7f6c5c59..6dbc20d9cb 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp +++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp @@ -50,6 +50,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -62,6 +63,7 @@ QSGDefaultRenderContext::QSGDefaultRenderContext(QSGContext *context) , m_currentFrameCommandBuffer(nullptr) , m_currentFrameRenderPass(nullptr) , m_separateIndexBuffer(false) + , m_useDepthBufferFor2D(true) { } @@ -150,9 +152,12 @@ void QSGDefaultRenderContext::invalidate() emit invalidated(); } -void QSGDefaultRenderContext::prepareSync(qreal devicePixelRatio, QRhiCommandBuffer *cb) +void QSGDefaultRenderContext::prepareSync(qreal devicePixelRatio, + QRhiCommandBuffer *cb, + const QQuickGraphicsConfiguration &config) { m_currentDevicePixelRatio = devicePixelRatio; + m_useDepthBufferFor2D = config.isDepthBufferEnabledFor2D(); // we store the command buffer already here, in case there is something in // an updatePaintNode() implementation that leads to needing it (for @@ -277,11 +282,6 @@ void QSGDefaultRenderContext::initializeRhiShader(QSGMaterialShader *shader, QSh QSGMaterialShaderPrivate::get(shader)->prepare(shaderVariant); } -bool QSGDefaultRenderContext::separateIndexBuffer() const -{ - return m_separateIndexBuffer; -} - void QSGDefaultRenderContext::preprocess() { for (auto it = m_glyphCaches.begin(); it != m_glyphCaches.end(); ++it) { diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h index 35a0695dab..a110172a6f 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h +++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h @@ -90,7 +90,10 @@ public: void initialize(const QSGRenderContext::InitParams *params) override; void invalidate() override; - void prepareSync(qreal devicePixelRatio, QRhiCommandBuffer *cb) override; + void prepareSync(qreal devicePixelRatio, + QRhiCommandBuffer *cb, + const QQuickGraphicsConfiguration &config) override; + void beginNextFrame(QSGRenderer *renderer, RenderPassCallback mainPassRecordingStart, RenderPassCallback mainPassRecordingEnd, @@ -116,8 +119,8 @@ public: virtual void initializeRhiShader(QSGMaterialShader *shader, QShader::Variant shaderVariant); int maxTextureSize() const override { return m_maxTextureSize; } - bool separateIndexBuffer() const; - + bool separateIndexBuffer() const { return m_separateIndexBuffer; } + bool useDepthBufferFor2D() const { return m_useDepthBufferFor2D; } int msaaSampleCount() const { return m_initParams.sampleCount; } QRhiCommandBuffer *currentFrameCommandBuffer() const { @@ -152,6 +155,7 @@ protected: QRhiRenderPassDescriptor *m_currentFrameRenderPass; qreal m_currentDevicePixelRatio; bool m_separateIndexBuffer; + bool m_useDepthBufferFor2D; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index c025e8d9af..8388fa9576 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -107,7 +107,7 @@ void QSGRenderLoop::cleanup() s_instance = nullptr; #ifdef ENABLE_DEFAULT_BACKEND - QSGRhiSupport::cleanupVulkanInstance(); + QSGRhiSupport::cleanupDefaultVulkanInstance(); QSGRhiProfileConnection::instance()->cleanup(); #endif } diff --git a/src/quick/scenegraph/qsgrhilayer.cpp b/src/quick/scenegraph/qsgrhilayer.cpp index 9d3db8354d..0e7eb1932e 100644 --- a/src/quick/scenegraph/qsgrhilayer.cpp +++ b/src/quick/scenegraph/qsgrhilayer.cpp @@ -352,9 +352,9 @@ void QSGRhiLayer::grab() return; if (!m_renderer) { - static const bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER"); - static const QSGRendererInterface::RenderMode renderMode = useDepth ? QSGRendererInterface::RenderMode2D - : QSGRendererInterface::RenderMode2DNoDepthBuffer; + const bool useDepth = m_context->useDepthBufferFor2D(); + const QSGRendererInterface::RenderMode renderMode = useDepth ? QSGRendererInterface::RenderMode2D + : QSGRendererInterface::RenderMode2DNoDepthBuffer; m_renderer = m_context->createRenderer(renderMode); connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture())); } diff --git a/src/quick/scenegraph/qsgrhisupport.cpp b/src/quick/scenegraph/qsgrhisupport.cpp index 618e1f1411..aa5661fc94 100644 --- a/src/quick/scenegraph/qsgrhisupport.cpp +++ b/src/quick/scenegraph/qsgrhisupport.cpp @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE QVulkanInstance *s_vulkanInstance = nullptr; #endif -QVulkanInstance *QSGRhiSupport::vulkanInstance() +QVulkanInstance *QSGRhiSupport::defaultVulkanInstance() { #if QT_CONFIG(vulkan) QSGRhiSupport *inst = QSGRhiSupport::instance(); @@ -97,7 +97,7 @@ QVulkanInstance *QSGRhiSupport::vulkanInstance() #endif } -void QSGRhiSupport::cleanupVulkanInstance() +void QSGRhiSupport::cleanupDefaultVulkanInstance() { #if QT_CONFIG(vulkan) delete s_vulkanInstance; @@ -537,7 +537,8 @@ QOffscreenSurface *QSGRhiSupport::maybeCreateOffscreenSurface(QWindow *window) // must be called on the render thread QRhi *QSGRhiSupport::createRhi(QQuickWindow *window, QOffscreenSurface *offscreenSurface) { - const QQuickGraphicsDevice &customDev(QQuickWindowPrivate::get(window)->customDeviceObjects); + QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window); + const QQuickGraphicsDevice &customDev(wd->customDeviceObjects); const QQuickGraphicsDevicePrivate *customDevD = QQuickGraphicsDevicePrivate::get(&customDev); QRhi *rhi = nullptr; @@ -580,6 +581,7 @@ QRhi *QSGRhiSupport::createRhi(QQuickWindow *window, QOffscreenSurface *offscree qWarning("No QVulkanInstance set for QQuickWindow, this is wrong."); if (window->handle()) // only used for vkGetPhysicalDeviceSurfaceSupportKHR and that implies having a valid native window rhiParams.window = window; + rhiParams.deviceExtensions = wd->graphicsConfig.deviceExtensions(); if (customDevD->type == QQuickGraphicsDevicePrivate::Type::DeviceObjects) { QRhiVulkanNativeHandles importDev; importDev.physDev = reinterpret_cast(customDevD->u.deviceObjects.physicalDevice); diff --git a/src/quick/scenegraph/qsgrhisupport_p.h b/src/quick/scenegraph/qsgrhisupport_p.h index 9e81706f41..24cd787afc 100644 --- a/src/quick/scenegraph/qsgrhisupport_p.h +++ b/src/quick/scenegraph/qsgrhisupport_p.h @@ -104,8 +104,8 @@ class Q_QUICK_PRIVATE_EXPORT QSGRhiSupport public: static void configure(QSGRendererInterface::GraphicsApi api); static QSGRhiSupport *instance(); - static QVulkanInstance *vulkanInstance(); - static void cleanupVulkanInstance(); + static QVulkanInstance *defaultVulkanInstance(); + static void cleanupDefaultVulkanInstance(); bool isRhiEnabled() const { return m_enableRhi; } QRhi::Implementation rhiBackend() const { return m_rhiBackend; } -- cgit v1.2.3