diff options
Diffstat (limited to 'src/quick/scenegraph')
42 files changed, 553 insertions, 222 deletions
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp index f5a41410ee..c97dcb9326 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp @@ -100,7 +100,7 @@ void QSGSoftwareRenderLoop::windowDestroyed(QQuickWindow *window) rc->invalidate(); } - delete d->animationController; + d->animationController.reset(); } void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window, bool isNewExpose) diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp index d4e5e98d68..17e8bdc2f9 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp @@ -49,6 +49,11 @@ QSGSoftwareSpriteNode::QSGSoftwareSpriteNode() setGeometry((QSGGeometry*)1); } +QSGSoftwareSpriteNode::~QSGSoftwareSpriteNode() +{ + delete m_texture; +} + void QSGSoftwareSpriteNode::setTexture(QSGTexture *texture) { m_texture = qobject_cast<QSGSoftwarePixmapTexture*>(texture); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h index 577a30c051..4015537395 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h @@ -64,6 +64,7 @@ class QSGSoftwareSpriteNode : public QSGSpriteNode { public: QSGSoftwareSpriteNode(); + ~QSGSoftwareSpriteNode() override; void setTexture(QSGTexture *texture) override; void setTime(float time) override; @@ -81,7 +82,7 @@ public: private: - QSGSoftwarePixmapTexture *m_texture; + QSGSoftwarePixmapTexture *m_texture = nullptr; float m_time; QPoint m_sourceA; QPoint m_sourceB; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp index 2d4dcd928d..c6b463bb02 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp @@ -292,7 +292,7 @@ bool QSGSoftwareRenderThread::event(QEvent *e) QCoreApplication::processEvents(); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); if (wme->destroying) - delete wd->animationController; + wd->animationController.reset(); } if (wme->destroying) active = false; @@ -844,7 +844,8 @@ void QSGSoftwareThreadedRenderLoop::handleExposure(QQuickWindow *window) if (!w->thread->isRunning()) { qCDebug(QSG_RASTER_LOG_RENDERLOOP, "starting render thread"); // Push a few things to the render thread. - QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController; + QQuickAnimatorController *controller + = QQuickWindowPrivate::get(w->window)->animationController.get(); if (controller->thread() != w->thread) controller->moveToThread(w->thread); if (w->thread->thread() == QThread::currentThread()) { diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp b/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp index 679ad1d445..62ed342244 100644 --- a/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp @@ -73,6 +73,22 @@ QT_BEGIN_NAMESPACE */ /*! + \enum QSGAbstractRenderer::MatrixTransformFlag + + Used with setProjectionMatrixToRect() to indicate the expectations towards + the generated projection matrix. + + \value MatrixTransformFlipY The traditional assumption in Qt Quick is that + Y points up in the normalized device coordinate system. There is at least + one modern graphics API where this is not the case (Vulkan). This flag can + then be used to get a projection that is appropriate for such an API. + + \sa setProjectionMatrixToRect() + + \since 5.14 + */ + +/*! \fn void QSGAbstractRenderer::renderScene(GLuint fboId = 0) Render the scene to the specified \a fboId @@ -224,14 +240,38 @@ QRect QSGAbstractRenderer::viewportRect() const Convenience method that calls setProjectionMatrix() with an orthographic matrix generated from \a rect. - \a flipY must be \c true when the graphics API uses Y down in its - normalized device coordinate system (for example, Vulkan), \c false - otherwise. + \note This function assumes that the graphics API uses Y up in its + normalized device coordinate system. \sa setProjectionMatrix(), projectionMatrix() */ -void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect, bool flipY) +void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect) +{ + QMatrix4x4 matrix; + matrix.ortho(rect.x(), + rect.x() + rect.width(), + rect.y() + rect.height(), + rect.y(), + 1, + -1); + setProjectionMatrix(matrix); + setProjectionMatrixWithNativeNDC(matrix); +} + +/*! + Convenience method that calls setProjectionMatrix() with an + orthographic matrix generated from \a rect. + + Set MatrixTransformFlipY in \a flags when the graphics API uses Y down in + its normalized device coordinate system (for example, Vulkan). + + \sa setProjectionMatrix(), projectionMatrix() + + \since 5.14 + */ +void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect, MatrixTransformFlags flags) { + const bool flipY = flags.testFlag(MatrixTransformFlipY); QMatrix4x4 matrix; matrix.ortho(rect.x(), rect.x() + rect.width(), diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer.h b/src/quick/scenegraph/coreapi/qsgabstractrenderer.h index 08e600e0b8..1594352dab 100644 --- a/src/quick/scenegraph/coreapi/qsgabstractrenderer.h +++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer.h @@ -63,6 +63,13 @@ public: Q_DECLARE_FLAGS(ClearMode, ClearModeBit) Q_FLAG(ClearMode) + enum MatrixTransformFlag + { + MatrixTransformFlipY = 0x01 + }; + Q_DECLARE_FLAGS(MatrixTransformFlags, MatrixTransformFlag) + Q_FLAG(MatrixTransformFlags) + ~QSGAbstractRenderer() override; void setRootNode(QSGRootNode *node); @@ -75,7 +82,8 @@ public: inline void setViewportRect(const QSize &size) { setViewportRect(QRect(QPoint(), size)); } QRect viewportRect() const; - void setProjectionMatrixToRect(const QRectF &rect, bool flipY = false); + void setProjectionMatrixToRect(const QRectF &rect); + void setProjectionMatrixToRect(const QRectF &rect, MatrixTransformFlags flags); void setProjectionMatrix(const QMatrix4x4 &matrix); void setProjectionMatrixWithNativeNDC(const QMatrix4x4 &matrix); QMatrix4x4 projectionMatrix() const; diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index a566a2bed6..45b00d43c4 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -187,7 +187,7 @@ static QRhiVertexInputLayout calculateVertexInputLayout(const QSGMaterialRhiShad } const int attrCount = geometry->attributeCount(); - QVector<QRhiVertexInputAttribute> inputAttributes; + QVarLengthArray<QRhiVertexInputAttribute, 8> inputAttributes; inputAttributes.reserve(attrCount + 1); int offset = 0; for (int i = 0; i < attrCount; ++i) { @@ -205,15 +205,14 @@ static QRhiVertexInputLayout calculateVertexInputLayout(const QSGMaterialRhiShad } Q_ASSERT(VERTEX_BUFFER_BINDING == 0 && ZORDER_BUFFER_BINDING == 1); // not very flexible - QVector<QRhiVertexInputBinding> inputBindings; - inputBindings.reserve(2); + QVarLengthArray<QRhiVertexInputBinding, 2> inputBindings; inputBindings.append(QRhiVertexInputBinding(geometry->sizeOfVertex())); if (batchable) inputBindings.append(QRhiVertexInputBinding(sizeof(float))); QRhiVertexInputLayout inputLayout; - inputLayout.setBindings(inputBindings); - inputLayout.setAttributes(inputAttributes); + inputLayout.setBindings(inputBindings.cbegin(), inputBindings.cend()); + inputLayout.setAttributes(inputAttributes.cbegin(), inputAttributes.cend()); return inputLayout; } @@ -400,14 +399,14 @@ void ShaderManager::clearCachedRendererData() } } -QRhiShaderResourceBindings *ShaderManager::srb(const QVector<QRhiShaderResourceBinding> &bindings) +QRhiShaderResourceBindings *ShaderManager::srb(const ShaderResourceBindingList &bindings) { auto it = srbCache.constFind(bindings); if (it != srbCache.constEnd()) return *it; QRhiShaderResourceBindings *srb = context->rhi()->newShaderResourceBindings(); - srb->setBindings(bindings); + srb->setBindings(bindings.cbegin(), bindings.cend()); if (srb->build()) { srbCache.insert(bindings, srb); } else { @@ -1123,6 +1122,9 @@ void Renderer::releaseCachedResources() m_pipelines.clear(); m_samplers.clear(); m_dummyTexture = nullptr; + + if (m_rhi) + m_rhi->releaseCachedResources(); } void Renderer::invalidateAndRecycleBatch(Batch *b) @@ -2846,7 +2848,7 @@ void Renderer::updateClipState(const QSGClipNode *clipList, Batch *batch) // RHI else { if (qsg_topology(g->drawingMode()) != m_stencilClipCommon.topology) qWarning("updateClipState: Clip list entries have different primitive topologies, this is not currently supported."); - if (qsg_vertexInputFormat(*a) != m_stencilClipCommon.inputLayout.attributes().first().format()) + if (qsg_vertexInputFormat(*a) != m_stencilClipCommon.inputLayout.cbeginAttributes()->format()) qWarning("updateClipState: Clip list entries have different vertex input layouts, this is must not happen."); } #endif @@ -3250,7 +3252,7 @@ bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms) // Build a new one. This is potentially expensive. QRhiGraphicsPipeline *ps = m_rhi->newGraphicsPipeline(); - ps->setShaderStages(sms->programRhi.shaderStages); + ps->setShaderStages(sms->programRhi.shaderStages.cbegin(), sms->programRhi.shaderStages.cend()); ps->setVertexInputLayout(sms->programRhi.inputLayout); ps->setShaderResourceBindings(e->srb); ps->setRenderPassDescriptor(renderPassDescriptor()); @@ -3423,9 +3425,9 @@ static void materialToRendererGraphicsState(GraphicsState *dst, } void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms, - const QSGMaterialRhiShader::RenderState &renderState, + QSGMaterialRhiShader::RenderState &renderState, QSGMaterial *material, - QVector<QRhiShaderResourceBinding> *bindings, + ShaderManager::ShaderResourceBindingList *bindings, const Batch *batch, int ubufOffset, int ubufRegionSize) // RHI only, [prepare step] @@ -3437,6 +3439,7 @@ void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms, if (pd->ubufBinding >= 0) { m_current_uniform_data = &pd->masterUniformData; const bool changed = shader->updateUniformData(renderState, material, m_currentMaterial); + m_current_uniform_data = nullptr; if (changed || !batch->ubufDataValid) m_resourceUpdates->updateDynamicBuffer(batch->ubuf, ubufOffset, ubufRegionSize, pd->masterUniformData.constData()); @@ -3513,7 +3516,7 @@ void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms, } void Renderer::updateMaterialStaticData(ShaderManager::Shader *sms, - const QSGMaterialRhiShader::RenderState &renderState, + QSGMaterialRhiShader::RenderState &renderState, QSGMaterial *material, Batch *batch, bool *gstateChanged) // RHI only, [prepare step] @@ -3621,12 +3624,12 @@ bool Renderer::prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *rende } } - const QSGMaterialRhiShader::RenderState renderState = rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty))); + QSGMaterialRhiShader::RenderState renderState = rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty))); bool pendingGStatePop = false; updateMaterialStaticData(sms, renderState, material, batch, &pendingGStatePop); - QVector<QRhiShaderResourceBinding> bindings; + ShaderManager::ShaderResourceBindingList bindings; updateMaterialDynamicData(sms, renderState, material, &bindings, batch, 0, ubufSize); #ifndef QT_NO_DEBUG @@ -3798,8 +3801,9 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren } } + QSGMaterialRhiShader::RenderState renderState = rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty))); bool pendingGStatePop = false; - updateMaterialStaticData(sms, rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty))), + updateMaterialStaticData(sms, renderState, material, batch, &pendingGStatePop); int ubufOffset = 0; @@ -3818,8 +3822,9 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren m_current_projection_matrix(2, 3) = 1.0f - e->order * m_zRange; } - QVector<QRhiShaderResourceBinding> bindings; - updateMaterialDynamicData(sms, rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty))), + QSGMaterialRhiShader::RenderState renderState = rhiState(QSGMaterialRhiShader::RenderState::DirtyStates(int(dirty))); + ShaderManager::ShaderResourceBindingList bindings; + updateMaterialDynamicData(sms, renderState, material, &bindings, batch, ubufOffset, ubufSize); #ifndef QT_NO_DEBUG diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 4e374522d4..297df2232a 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -642,7 +642,7 @@ public: struct { QSGMaterialRhiShader *program = nullptr; QRhiVertexInputLayout inputLayout; - QVector<QRhiGraphicsShaderStage> shaderStages; + QVarLengthArray<QRhiGraphicsShaderStage, 2> shaderStages; } programRhi; float lastOpacity; @@ -656,7 +656,9 @@ public: void clearCachedRendererData(); - QRhiShaderResourceBindings *srb(const QVector<QRhiShaderResourceBinding> &bindings); + using ShaderResourceBindingList = QVarLengthArray<QRhiShaderResourceBinding, 8>; + + QRhiShaderResourceBindings *srb(const ShaderResourceBindingList &bindings); public Q_SLOTS: void invalidated(); @@ -672,7 +674,7 @@ private: QOpenGLShaderProgram *blitProgram; QSGDefaultRenderContext *context; - QHash<QVector<QRhiShaderResourceBinding>, QRhiShaderResourceBindings *> srbCache; + QHash<ShaderResourceBindingList, QRhiShaderResourceBindings *> srbCache; }; struct GraphicsState @@ -796,10 +798,10 @@ private: void renderBatches(); bool ensurePipelineState(Element *e, const ShaderManager::Shader *sms); QRhiTexture *dummyTexture(); - void updateMaterialDynamicData(ShaderManager::Shader *sms, const QSGMaterialRhiShader::RenderState &renderState, - QSGMaterial *material, QVector<QRhiShaderResourceBinding> *bindings, + void updateMaterialDynamicData(ShaderManager::Shader *sms, QSGMaterialRhiShader::RenderState &renderState, + QSGMaterial *material, ShaderManager::ShaderResourceBindingList *bindings, const Batch *batch, int ubufOffset, int ubufRegionSize); - void updateMaterialStaticData(ShaderManager::Shader *sms, const QSGMaterialRhiShader::RenderState &renderState, + void updateMaterialStaticData(ShaderManager::Shader *sms, QSGMaterialRhiShader::RenderState &renderState, QSGMaterial *material, Batch *batch, bool *gstateChanged); void checkLineWidth(QSGGeometry *g); bool prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *renderBatch); diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp index 5218b6b1d5..a28eee5288 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.cpp +++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp @@ -576,6 +576,10 @@ const void *QSGGeometry::indexData() const \value IntType \value UnsignedIntType \value FloatType + \value Bytes2Type Added in Qt 5.14. + \value Bytes3Type Added in Qt 5.14. + \value Bytes4Type Added in Qt 5.14. + \value DoubleType Added in Qt 5.14. */ /*! diff --git a/src/quick/scenegraph/coreapi/qsgmaterialrhishader.cpp b/src/quick/scenegraph/coreapi/qsgmaterialrhishader.cpp index 03f74df6b7..117d477f9a 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterialrhishader.cpp +++ b/src/quick/scenegraph/coreapi/qsgmaterialrhishader.cpp @@ -301,9 +301,9 @@ void QSGMaterialRhiShader::setFlag(Flags flags, bool on) memcpy calls) when updating material states. When \a oldMaterial is null, this shader was just activated. */ -bool QSGMaterialRhiShader::updateUniformData(const RenderState &state, - QSGMaterial *newMaterial, - QSGMaterial *oldMaterial) +bool QSGMaterialRhiShader::updateUniformData(RenderState &state, + QSGMaterial *newMaterial, + QSGMaterial *oldMaterial) { Q_UNUSED(state); Q_UNUSED(newMaterial); @@ -334,11 +334,11 @@ bool QSGMaterialRhiShader::updateUniformData(const RenderState &state, \a oldMaterial can be used to minimize changes. When \a oldMaterial is null, this shader was just activated. */ -void QSGMaterialRhiShader::updateSampledImage(const RenderState &state, - int binding, - QSGTexture **texture, - QSGMaterial *newMaterial, - QSGMaterial *oldMaterial) +void QSGMaterialRhiShader::updateSampledImage(RenderState &state, + int binding, + QSGTexture **texture, + QSGMaterial *newMaterial, + QSGMaterial *oldMaterial) { Q_UNUSED(state); Q_UNUSED(binding); @@ -367,8 +367,8 @@ void QSGMaterialRhiShader::updateSampledImage(const RenderState &state, The subclass specific state can be extracted from \a newMaterial. When \a oldMaterial is null, this shader was just activated. */ -bool QSGMaterialRhiShader::updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps, - QSGMaterial *newMaterial, QSGMaterial *oldMaterial) +bool QSGMaterialRhiShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, + QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { Q_UNUSED(state); Q_UNUSED(ps); @@ -426,12 +426,77 @@ bool QSGMaterialRhiShader::updateGraphicsPipelineState(const RenderState &state, */ /*! + \class QSGMaterialRhiShader::GraphicsPipelineState + + \brief Describes state changes that the material wants to apply to the + currently active graphics pipeline state. + + \inmodule QtQuick + \since 5.14 + + Unlike QSGMaterialShader, directly issuing state change commands with the + underlying graphics API is not possible with QSGMaterialRhiShader. This is + mainly because the concept of individually changeable states is considered + deprecated and not supported with modern graphics APIs. + + Therefore, it is up to QSGMaterialRhiShader to expose a data structure with + the set of supported states, which the material can change in its + updatePipelineState() implementation, if there is one. The scenegraph will + then internally apply these changes to the active graphics pipeline state, + then rolling them back as appropriate. + */ + +/*! + \enum QSGMaterialRhiShader::GraphicsPipelineState::BlendFactor + \since 5.14 + + \value Zero + \value One + \value SrcColor + \value OneMinusSrcColor + \value DstColor + \value OneMinusDstColor + \value SrcAlpha + \value OneMinusSrcAlpha + \value DstAlpha + \value OneMinusDstAlpha + \value ConstantColor + \value OneMinusConstantColor + \value ConstantAlpha + \value OneMinusConstantAlpha + \value SrcAlphaSaturate + \value Src1Color + \value OneMinusSrc1Color + \value Src1Alpha + \value OneMinusSrc1Alpha + */ + +/*! + \enum QSGMaterialRhiShader::GraphicsPipelineState::ColorMaskComponent + \since 5.14 + + \value R + \value G + \value B + \value A + */ + +/*! + \enum QSGMaterialRhiShader::GraphicsPipelineState::CullMode + \since 5.14 + + \value CullNone + \value CullFront + \value CullBack + */ + +/*! Returns the accumulated opacity to be used for rendering. */ float QSGMaterialRhiShader::RenderState::opacity() const { Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->currentOpacity(); + return float(static_cast<const QSGRenderer *>(m_data)->currentOpacity()); } /*! @@ -440,7 +505,7 @@ float QSGMaterialRhiShader::RenderState::opacity() const float QSGMaterialRhiShader::RenderState::determinant() const { Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->determinant(); + return float(static_cast<const QSGRenderer *>(m_data)->determinant()); } /*! @@ -459,7 +524,7 @@ QMatrix4x4 QSGMaterialRhiShader::RenderState::combinedMatrix() const float QSGMaterialRhiShader::RenderState::devicePixelRatio() const { Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->devicePixelRatio(); + return float(static_cast<const QSGRenderer *>(m_data)->devicePixelRatio()); } /*! @@ -511,7 +576,10 @@ QRect QSGMaterialRhiShader::RenderState::deviceRect() const /*! Returns a pointer to the data for the uniform (constant) buffer in the - shader. + shader. Uniform data must only be updated from + QSGMaterialRhiShader::updateUniformData(). The return value is null in the + other reimplementable functions, such as, + QSGMaterialRhiShader::updateSampledImage(). \note It is strongly recommended to declare the uniform block with \c std140 in the shader, and to carefully study the standard uniform block @@ -525,11 +593,8 @@ QRect QSGMaterialRhiShader::RenderState::deviceRect() const \note Avoid copying from C++ POD types, such as, structs, in order to update multiple members at once, unless it has been verified that the layouts of the C++ struct and the GLSL uniform block match. - - \note Uniform data must only be updated from - QSGMaterialRhiShader::updateUniformData(). */ -QByteArray *QSGMaterialRhiShader::RenderState::uniformData() const +QByteArray *QSGMaterialRhiShader::RenderState::uniformData() { Q_ASSERT(m_data); return static_cast<const QSGRenderer *>(m_data)->currentUniformData(); @@ -541,7 +606,7 @@ QByteArray *QSGMaterialRhiShader::RenderState::uniformData() const QSGMaterialRhiShader::updateSampledImage() to enqueue texture image content updates. */ -QRhiResourceUpdateBatch *QSGMaterialRhiShader::RenderState::resourceUpdateBatch() const +QRhiResourceUpdateBatch *QSGMaterialRhiShader::RenderState::resourceUpdateBatch() { Q_ASSERT(m_data); return static_cast<const QSGRenderer *>(m_data)->currentResourceUpdateBatch(); @@ -550,7 +615,7 @@ QRhiResourceUpdateBatch *QSGMaterialRhiShader::RenderState::resourceUpdateBatch( /*! Returns the current QRhi. */ -QRhi *QSGMaterialRhiShader::RenderState::rhi() const +QRhi *QSGMaterialRhiShader::RenderState::rhi() { Q_ASSERT(m_data); return static_cast<const QSGRenderer *>(m_data)->currentRhi(); diff --git a/src/quick/scenegraph/coreapi/qsgmaterialrhishader.h b/src/quick/scenegraph/coreapi/qsgmaterialrhishader.h index 01991135ec..86208516cd 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterialrhishader.h +++ b/src/quick/scenegraph/coreapi/qsgmaterialrhishader.h @@ -76,9 +76,9 @@ public: float determinant() const; float devicePixelRatio() const; - QByteArray *uniformData() const; - QRhiResourceUpdateBatch *resourceUpdateBatch() const; - QRhi *rhi() const; + QByteArray *uniformData(); + QRhiResourceUpdateBatch *resourceUpdateBatch(); + QRhi *rhi(); private: friend class QSGRenderer; @@ -146,13 +146,13 @@ public: QSGMaterialRhiShader(); virtual ~QSGMaterialRhiShader(); - virtual bool updateUniformData(const RenderState &state, + virtual bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); - virtual void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, + virtual void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); - virtual bool updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps, + virtual bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); Flags flags() const; diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp index e504fe1c62..0fee1486cf 100644 --- a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp +++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp @@ -78,11 +78,11 @@ QT_BEGIN_NAMESPACE \value OpenGL OpenGL ES 2.0 or higher \value Direct3D12 Direct3D 12 \value OpenVG OpenVG via EGL - \value OpenGLRhi OpenGL ES 2.0 or higher via a graphics abstraction layer - \value Direct3D11Rhi Direct3D 11 via a graphics abstraction layer - \value VulkanRhi Vulkan 1.0 via a graphics abstraction layer - \value MetalRhi Metal via a graphics abstraction layer - \value NullRhi Null (no output) via a graphics abstraction layer + \value OpenGLRhi OpenGL ES 2.0 or higher via a graphics abstraction layer. This value was introduced in Qt 5.14. + \value Direct3D11Rhi Direct3D 11 via a graphics abstraction layer. This value was introduced in Qt 5.14. + \value VulkanRhi Vulkan 1.0 via a graphics abstraction layer. This value was introduced in Qt 5.14. + \value MetalRhi Metal via a graphics abstraction layer. This value was introduced in Qt 5.14. + \value NullRhi Null (no output) via a graphics abstraction layer. This value was introduced in Qt 5.14. */ /*! @@ -111,29 +111,36 @@ QT_BEGIN_NAMESPACE used by the scenegraph, when running with the software backend. \value RhiResource The resource is a pointer to the QRhi instance used by - the scenegraph, when applicable. + the scenegraph, when applicable. This value was introduced in Qt 5.14. \value PhysicalDeviceResource The resource is a pointer to the pysical device object used by the scenegraph, when applicable. For example, a \c{VkPhysicalDevice *}. Note that with Vulkan the returned value is a - pointer to the VkPhysicalDevice, not the handle itself. + pointer to the VkPhysicalDevice, not the handle itself. This value was + introduced in Qt 5.14. \value OpenGLContextResource The resource is a pointer to the QOpenGLContext used by the scenegraph (on the render thread), when - applicable. + applicable. This value was introduced in Qt 5.14. \value DeviceContextResource The resource is a pointer to the device context used by the scenegraph, when applicable. For example, a - \c{ID3D11DeviceContext *}. + \c{ID3D11DeviceContext *}. This value was introduced in Qt 5.14. \value CommandEncoderResource The resource is a pointer to the currently active render command encoder object used by the scenegraph, when applicable. For example, a \c{MTLRenderCommandEncoder *}. This object has limited validity, and is only valid while the scene graph is recording a - render pass for the next frame. + render pass for the next frame. This value was introduced in Qt 5.14. \value VulkanInstanceResource The resource is a pointer to the - QVulkanInstance used by the scenegraph, when applicable. + QVulkanInstance used by the scenegraph, when applicable. This value was + introduced in Qt 5.14. + + \value RenderPassResource The resource is a pointer to the render pass used + by the scenegraph, describing the color and depth/stecil attachments and + how they are used. For example, a \c{VkRenderPass *}. This value was + introduced in Qt 5.14. */ /*! @@ -141,8 +148,9 @@ QT_BEGIN_NAMESPACE \value UnknownShadingLanguage Not yet known due to no window and scenegraph associated \value GLSL GLSL or GLSL ES \value HLSL HLSL - \value RhiShader Consumes QShader instances containing shader - variants for multiple target languages and bytecode formats + \value RhiShader Consumes QShader instances containing shader variants for + multiple target languages and intermediate formats. This value was introduced in + Qt 5.14. */ /*! @@ -218,6 +226,8 @@ void *QSGRendererInterface::getResource(QQuickWindow *window, const char *resour instead of directly calling the native graphics API. \note This function can be called on any thread. + + \since 5.14 */ bool QSGRendererInterface::isApiRhiBased(GraphicsApi api) { diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.h b/src/quick/scenegraph/coreapi/qsgrendererinterface.h index 3052c81f6c..7aa7d0e769 100644 --- a/src/quick/scenegraph/coreapi/qsgrendererinterface.h +++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.h @@ -72,7 +72,8 @@ public: OpenGLContextResource, DeviceContextResource, CommandEncoderResource, - VulkanInstanceResource + VulkanInstanceResource, + RenderPassResource }; enum ShaderType { diff --git a/src/quick/scenegraph/coreapi/qsgtexture.cpp b/src/quick/scenegraph/coreapi/qsgtexture.cpp index c47401e5c0..edcee96bdb 100644 --- a/src/quick/scenegraph/coreapi/qsgtexture.cpp +++ b/src/quick/scenegraph/coreapi/qsgtexture.cpp @@ -717,6 +717,9 @@ void QSGTexture::updateRhiTexture(QRhi *rhi, QRhiResourceUpdateBatch *resourceUp d->updateRhiTexture(rhi, resourceUpdates); } +/*! + \internal + */ void QSGTexture::setWorkResourceUpdateBatch(QRhiResourceUpdateBatch *resourceUpdates) { Q_D(QSGTexture); diff --git a/src/quick/scenegraph/coreapi/qsgtexture.h b/src/quick/scenegraph/coreapi/qsgtexture.h index 4cd2a5cddd..2efdd8b7c3 100644 --- a/src/quick/scenegraph/coreapi/qsgtexture.h +++ b/src/quick/scenegraph/coreapi/qsgtexture.h @@ -141,6 +141,7 @@ class Q_QUICK_EXPORT QSGDynamicTexture : public QSGTexture Q_OBJECT public: + QSGDynamicTexture() = default; virtual bool updateTexture() = 0; protected: diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 97fd49e4c7..17eb1e312c 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -341,6 +341,11 @@ void QSGRenderContext::invalidate() { } +void QSGRenderContext::prepareSync(qreal devicePixelRatio) +{ + Q_UNUSED(devicePixelRatio); +} + void QSGRenderContext::beginNextFrame(QSGRenderer *renderer, RenderPassCallback mainPassRecordingStart, RenderPassCallback mainPassRecordingEnd, diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index 4e712ab7c3..244bcfabd1 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -174,6 +174,7 @@ public: using RenderPassCallback = void (*)(void *); + virtual void prepareSync(qreal devicePixelRatio); virtual void beginNextFrame(QSGRenderer *renderer, RenderPassCallback mainPassRecordingStart, RenderPassCallback mainPassRecordingEnd, diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index 8fc8c711c6..be6ef25feb 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp @@ -410,9 +410,9 @@ class QSGTextMaskRhiShader : public QSGMaterialRhiShader public: QSGTextMaskRhiShader(QFontEngine::GlyphFormat glyphFormat); - bool updateUniformData(const RenderState &state, + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, + void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; protected: @@ -428,7 +428,7 @@ QSGTextMaskRhiShader::QSGTextMaskRhiShader(QFontEngine::GlyphFormat glyphFormat) QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/textmask.frag.qsb")); } -bool QSGTextMaskRhiShader::updateUniformData(const RenderState &state, +bool QSGTextMaskRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type()); @@ -471,7 +471,7 @@ bool QSGTextMaskRhiShader::updateUniformData(const RenderState &state, return changed; } -void QSGTextMaskRhiShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, +void QSGTextMaskRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *) { Q_UNUSED(state); @@ -498,10 +498,10 @@ public: QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/8bittextmask.frag.qsb")); } - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; -bool QSG8BitTextMaskRhiShader::updateUniformData(const RenderState &state, +bool QSG8BitTextMaskRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { bool changed = QSGTextMaskRhiShader::updateUniformData(state, newMaterial, oldMaterial); @@ -532,8 +532,8 @@ public: QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/24bittextmask.frag.qsb")); } - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - bool updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps, + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; @@ -544,7 +544,7 @@ public: // framebuffer update and blending always on... Could we do gamma correction in // the shader for text? (but that's bad for blending?) -bool QSG24BitTextMaskRhiShader::updateUniformData(const RenderState &state, +bool QSG24BitTextMaskRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { bool changed = QSGTextMaskRhiShader::updateUniformData(state, newMaterial, oldMaterial); @@ -565,7 +565,7 @@ bool QSG24BitTextMaskRhiShader::updateUniformData(const RenderState &state, return changed; } -bool QSG24BitTextMaskRhiShader::updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps, +bool QSG24BitTextMaskRhiShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { Q_UNUSED(state); @@ -596,10 +596,10 @@ public: QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/32bitcolortext.frag.qsb")); } - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; -bool QSG32BitColorTextRhiShader::updateUniformData(const RenderState &state, +bool QSG32BitColorTextRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { bool changed = QSGTextMaskRhiShader::updateUniformData(state, newMaterial, oldMaterial); @@ -636,11 +636,11 @@ public: QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/styledtext.frag.qsb")); } - bool updateUniformData(const RenderState &state, + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; -bool QSGStyledTextRhiShader::updateUniformData(const RenderState &state, +bool QSGStyledTextRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { bool changed = QSG8BitTextMaskRhiShader::updateUniformData(state, newMaterial, oldMaterial); @@ -751,15 +751,15 @@ void QSGTextMaskMaterial::updateCache(QFontEngine::GlyphFormat glyphFormat) void *cacheKey; if (m_rhi) { cacheKey = m_rhi; - // ### no idea what the QWindow is (esp. since we are not even - // rendering at this point), and anyway is the original logic correct - // even... - devicePixelRatio = qGuiApp->devicePixelRatio(); + // Get the dpr the modern way. This value retrieved via the + // rendercontext matches what RenderState::devicePixelRatio() + // exposes to the material shaders later on. + devicePixelRatio = m_rc->currentDevicePixelRatio(); } else { ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); Q_ASSERT(ctx != nullptr); cacheKey = ctx; - devicePixelRatio = qsg_device_pixel_ratio(ctx); + devicePixelRatio = qsg_device_pixel_ratio(ctx); // this is technically incorrect, see other branch above } QTransform glyphCacheTransform = QTransform::fromScale(devicePixelRatio, devicePixelRatio); diff --git a/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp b/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp index d1711f7524..500d4e6e95 100644 --- a/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp +++ b/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp @@ -66,7 +66,7 @@ class SmoothTextureMaterialRhiShader : public QSGTextureMaterialRhiShader public: SmoothTextureMaterialRhiShader(); - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; @@ -136,7 +136,7 @@ SmoothTextureMaterialRhiShader::SmoothTextureMaterialRhiShader() setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/smoothtexture.frag.qsb")); } -bool SmoothTextureMaterialRhiShader::updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) +bool SmoothTextureMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { bool changed = false; QByteArray *buf = state.uniformData(); diff --git a/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp b/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp index 417b63dee3..5e4affbf90 100644 --- a/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp +++ b/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp @@ -111,7 +111,7 @@ class SmoothColorMaterialRhiShader : public QSGMaterialRhiShader public: SmoothColorMaterialRhiShader(); - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; SmoothColorMaterialRhiShader::SmoothColorMaterialRhiShader() @@ -120,7 +120,7 @@ SmoothColorMaterialRhiShader::SmoothColorMaterialRhiShader() setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/smoothcolor.frag.qsb")); } -bool SmoothColorMaterialRhiShader::updateUniformData(const RenderState &state, QSGMaterial *, QSGMaterial *oldMaterial) +bool SmoothColorMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *, QSGMaterial *oldMaterial) { bool changed = false; QByteArray *buf = state.uniformData(); diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp index 60a525b877..e8c3ac4abb 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp +++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp @@ -68,6 +68,7 @@ QSGDefaultRenderContext::QSGDefaultRenderContext(QSGContext *context) , m_glAtlasManager(nullptr) , m_rhiAtlasManager(nullptr) , m_currentFrameCommandBuffer(nullptr) + , m_currentFrameRenderPass(nullptr) { } @@ -199,6 +200,11 @@ void QSGDefaultRenderContext::invalidate() emit invalidated(); } +void QSGDefaultRenderContext::prepareSync(qreal devicePixelRatio) +{ + m_currentDevicePixelRatio = devicePixelRatio; +} + static QBasicMutex qsg_framerender_mutex; void QSGDefaultRenderContext::beginNextFrame(QSGRenderer *renderer, @@ -239,6 +245,7 @@ void QSGDefaultRenderContext::beginNextRhiFrame(QSGRenderer *renderer, QRhiRende renderer->setRenderPassRecordingCallbacks(mainPassRecordingStart, mainPassRecordingEnd, callbackUserData); m_currentFrameCommandBuffer = cb; + m_currentFrameRenderPass = rp; } void QSGDefaultRenderContext::renderNextRhiFrame(QSGRenderer *renderer) @@ -250,6 +257,7 @@ void QSGDefaultRenderContext::endNextRhiFrame(QSGRenderer *renderer) { Q_UNUSED(renderer); m_currentFrameCommandBuffer = nullptr; + m_currentFrameRenderPass = nullptr; } /*! diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h index 79bc9dd76d..2fdb3a48dd 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h +++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h @@ -62,6 +62,7 @@ QT_BEGIN_NAMESPACE class QRhi; class QRhiCommandBuffer; +class QRhiRenderPassDescriptor; class QOpenGLContext; class QSGMaterialShader; class QSGMaterialRhiShader; @@ -103,6 +104,7 @@ public: void initialize(const QSGRenderContext::InitParams *params) override; void invalidate() override; + void prepareSync(qreal devicePixelRatio) override; void beginNextFrame(QSGRenderer *renderer, RenderPassCallback mainPassRecordingStart, RenderPassCallback mainPassRecordingEnd, @@ -145,6 +147,21 @@ public: // may be null if not in an active frame, but returning null is valid then return m_currentFrameCommandBuffer; } + QRhiRenderPassDescriptor *currentFrameRenderPass() const { + // may be null if not in an active frame, but returning null is valid then + return m_currentFrameRenderPass; + } + + qreal currentDevicePixelRatio() const + { + // Valid starting from QQuickWindow::syncSceneGraph(). This takes the + // redirections, e.g. QQuickWindow::setRenderTarget(), into account. + // This calculation logic matches what the renderer does, so this is + // the same value that gets exposed in RenderState::devicePixelRatio() + // to material shaders. This getter is useful to perform dpr-related + // operations in the sync phase (in updatePaintNode()). + return m_currentDevicePixelRatio; + } protected: static QString fontKey(const QRawFont &font); @@ -160,6 +177,8 @@ protected: QSGOpenGLAtlasTexture::Manager *m_glAtlasManager; QSGRhiAtlasTexture::Manager *m_rhiAtlasManager; QRhiCommandBuffer *m_currentFrameCommandBuffer; + QRhiRenderPassDescriptor *m_currentFrameRenderPass; + qreal m_currentDevicePixelRatio; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgdefaultspritenode.cpp b/src/quick/scenegraph/qsgdefaultspritenode.cpp index 4d4d9f6971..6422a252d9 100644 --- a/src/quick/scenegraph/qsgdefaultspritenode.cpp +++ b/src/quick/scenegraph/qsgdefaultspritenode.cpp @@ -141,9 +141,9 @@ class SpriteMaterialRhiShader : public QSGMaterialRhiShader public: SpriteMaterialRhiShader(); - bool updateUniformData(const RenderState &state, + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, + void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; @@ -153,7 +153,7 @@ SpriteMaterialRhiShader::SpriteMaterialRhiShader() setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/sprite.frag.qsb")); } -bool SpriteMaterialRhiShader::updateUniformData(const RenderState &state, +bool SpriteMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { #ifdef QT_NO_DEBUG @@ -186,7 +186,7 @@ bool SpriteMaterialRhiShader::updateUniformData(const RenderState &state, return changed; } -void SpriteMaterialRhiShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, +void SpriteMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { if (binding != 1) diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp index 9121363159..e8e9f76d04 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp @@ -212,10 +212,10 @@ class QSGDistanceFieldTextMaterialRhiShader : public QSGMaterialRhiShader public: QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture); - bool updateUniformData(const RenderState &state, + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, + void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; protected: @@ -235,7 +235,7 @@ QSGDistanceFieldTextMaterialRhiShader::QSGDistanceFieldTextMaterialRhiShader(boo QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.frag.qsb")); } -bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(const RenderState &state, +bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type()); @@ -291,7 +291,7 @@ bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(const RenderState return changed; } -void QSGDistanceFieldTextMaterialRhiShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, +void QSGDistanceFieldTextMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *) { Q_UNUSED(state); @@ -432,7 +432,7 @@ class DistanceFieldStyledTextMaterialRhiShader : public QSGDistanceFieldTextMate public: DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture); - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; DistanceFieldStyledTextMaterialRhiShader::DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture) @@ -440,7 +440,7 @@ DistanceFieldStyledTextMaterialRhiShader::DistanceFieldStyledTextMaterialRhiShad { } -bool DistanceFieldStyledTextMaterialRhiShader::updateUniformData(const RenderState &state, +bool DistanceFieldStyledTextMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); @@ -548,7 +548,7 @@ class DistanceFieldOutlineTextMaterialRhiShader : public DistanceFieldStyledText public: DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture); - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; DistanceFieldOutlineTextMaterialRhiShader::DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture) @@ -564,7 +564,7 @@ DistanceFieldOutlineTextMaterialRhiShader::DistanceFieldOutlineTextMaterialRhiSh QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.frag.qsb")); } -bool DistanceFieldOutlineTextMaterialRhiShader::updateUniformData(const RenderState &state, +bool DistanceFieldOutlineTextMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); @@ -670,7 +670,7 @@ class DistanceFieldShiftedStyleTextMaterialRhiShader : public DistanceFieldStyle public: DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture); - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; DistanceFieldShiftedStyleTextMaterialRhiShader::DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture) @@ -686,7 +686,7 @@ DistanceFieldShiftedStyleTextMaterialRhiShader::DistanceFieldShiftedStyleTextMat QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.frag.qsb")); } -bool DistanceFieldShiftedStyleTextMaterialRhiShader::updateUniformData(const RenderState &state, +bool DistanceFieldShiftedStyleTextMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); @@ -809,8 +809,8 @@ class QSGHiQSubPixelDistanceFieldTextMaterialRhiShader : public QSGDistanceField public: QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture); - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - bool updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps, + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; @@ -829,7 +829,7 @@ QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::QSGHiQSubPixelDistanceFieldTex QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag.qsb")); } -bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(const RenderState &state, +bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); @@ -855,7 +855,7 @@ bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(const R return changed; } -bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps, +bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { Q_UNUSED(state); diff --git a/src/quick/scenegraph/qsgopengllayer.cpp b/src/quick/scenegraph/qsgopengllayer.cpp index 8db4cba58a..ae5032231d 100644 --- a/src/quick/scenegraph/qsgopengllayer.cpp +++ b/src/quick/scenegraph/qsgopengllayer.cpp @@ -408,7 +408,7 @@ void QSGOpenGLLayer::grab() m_mirrorVertical ? m_rect.bottom() : m_rect.top(), m_mirrorHorizontal ? -m_rect.width() : m_rect.width(), m_mirrorVertical ? -m_rect.height() : m_rect.height()); - m_renderer->setProjectionMatrixToRect(mirrored, false); + m_renderer->setProjectionMatrixToRect(mirrored); m_renderer->setClearColor(Qt::transparent); if (m_multisampling) { diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 08d1c726ab..f609055677 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -190,6 +190,7 @@ public: QSGRenderContext *createRenderContext(QSGContext *) const override { return rc; } void releaseSwapchain(QQuickWindow *window); + void handleDeviceLoss(); bool eventFilter(QObject *watched, QEvent *event) override; @@ -435,7 +436,26 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window) gl->doneCurrent(); } - delete d->animationController; + d->animationController.reset(); +} + +void QSGGuiThreadRenderLoop::handleDeviceLoss() +{ + if (!rhi || !rhi->isDeviceLost()) + return; + + qWarning("Graphics device lost, cleaning up scenegraph and releasing RHI"); + + for (auto it = m_windows.constBegin(), itEnd = m_windows.constEnd(); it != itEnd; ++it) + QQuickWindowPrivate::get(it.key())->cleanupNodesOnShutdown(); + + rc->invalidate(); + + for (auto it = m_windows.constBegin(), itEnd = m_windows.constEnd(); it != itEnd; ++it) + releaseSwapchain(it.key()); + + delete rhi; + rhi = nullptr; } void QSGGuiThreadRenderLoop::releaseSwapchain(QQuickWindow *window) @@ -488,8 +508,11 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) const bool enableRhi = rhiSupport->isRhiEnabled(); if (enableRhi && !rhi) { - offscreenSurface = rhiSupport->maybeCreateOffscreenSurface(window); + if (!offscreenSurface) + offscreenSurface = rhiSupport->maybeCreateOffscreenSurface(window); + rhi = rhiSupport->createRhi(window, offscreenSurface); + if (rhi) { if (rhiSupport->isProfilingRequested()) QSGRhiProfileConnection::instance()->initialize(rhi); @@ -561,6 +584,14 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) QRhiSwapChain::Flags flags = QRhiSwapChain::UsedAsTransferSource; // may be used in a grab + // QQ is always premul alpha. Decide based on alphaBufferSize in + // requestedFormat(). (the platform plugin can override format() but + // what matters here is what the application wanted, hence using the + // requested one) + const bool alpha = window->requestedFormat().alphaBufferSize() > 0; + if (alpha) + flags |= QRhiSwapChain::SurfaceHasPreMulAlpha; + cd->swapchain = rhi->newSwapChain(); cd->depthStencilForSwapchain = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(), @@ -568,7 +599,8 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) QRhiRenderBuffer::UsedWithSwapChainOnly); cd->swapchain->setWindow(window); cd->swapchain->setDepthStencil(cd->depthStencilForSwapchain); - qCDebug(QSG_LOG_INFO, "MSAA sample count for the swapchain is %d", rhiSampleCount); + qCDebug(QSG_LOG_INFO, "MSAA sample count for the swapchain is %d. Alpha channel requested = %s", + rhiSampleCount, alpha ? "yes" : "no"); cd->swapchain->setSampleCount(rhiSampleCount); cd->swapchain->setFlags(flags); cd->rpDescForSwapchain = cd->swapchain->newCompatibleRenderPassDescriptor(); @@ -587,6 +619,24 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) i++; } + // Check for context loss. + if (!current && !rhi && !gl->isValid()) { + for (auto it = m_windows.constBegin() ; it != m_windows.constEnd(); it++) { + QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(it.key()); + windowPrivate->cleanupNodesOnShutdown(); + } + rc->invalidate(); + current = gl->create() && gl->makeCurrent(window); + if (current) { + QSGDefaultRenderContext::InitParams rcParams; + rcParams.sampleCount = qMax(1, gl->format().samples()); + rcParams.openGLContext = gl; + rcParams.initialSurfacePixelSize = window->size() * window->effectiveDevicePixelRatio(); + rcParams.maybeSurface = window; + rc->initialize(&rcParams); + } + } + if (!current) return; @@ -634,24 +684,34 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) if (previousOutputSize != effectiveOutputSize || cd->swapchainJustBecameRenderable) { if (cd->swapchainJustBecameRenderable) qCDebug(QSG_LOG_RENDERLOOP, "just became exposed"); - cd->swapchainJustBecameRenderable = false; - cd->depthStencilForSwapchain->setPixelSize(effectiveOutputSize); - cd->depthStencilForSwapchain->build(); cd->hasActiveSwapchain = cd->swapchain->buildOrResize(); + if (!cd->hasActiveSwapchain && rhi->isDeviceLost()) { + handleDeviceLoss(); + return; + } + cd->swapchainJustBecameRenderable = false; cd->hasRenderableSwapchain = cd->hasActiveSwapchain; - if (!cd->hasActiveSwapchain) - qWarning("Failed to build or resize swapchain"); - else + + if (cd->hasActiveSwapchain) { + // surface size atomicity: now that buildOrResize() succeeded, + // query the size that was used in there by the swapchain, and + // that is the size we will use while preparing the next frame. + effectiveOutputSize = cd->swapchain->currentPixelSize(); qCDebug(QSG_LOG_RENDERLOOP) << "rhi swapchain size" << effectiveOutputSize; + } else { + qWarning("Failed to build or resize swapchain"); + } } Q_ASSERT(rhi == cd->rhi); - QRhi::FrameOpResult frameResult = rhi->beginFrame(cd->swapchain); + // ### the flag should only be set when the app requests it, but there's no way to do that right now + QRhi::BeginFrameFlags frameFlags = QRhi::ExternalContentsInPass; + QRhi::FrameOpResult frameResult = rhi->beginFrame(cd->swapchain, frameFlags); if (frameResult != QRhi::FrameOpSuccess) { if (frameResult == QRhi::FrameOpDeviceLost) - qWarning("Device lost"); + handleDeviceLoss(); else if (frameResult == QRhi::FrameOpError) qWarning("Failed to start frame"); // out of date is not worth warning about - it may happen even during resizing on some platforms @@ -690,7 +750,13 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) QRhi::EndFrameFlags flags = 0; if (!needsPresent) flags |= QRhi::SkipPresent; - rhi->endFrame(cd->swapchain, flags); + QRhi::FrameOpResult frameResult = rhi->endFrame(cd->swapchain, flags); + if (frameResult != QRhi::FrameOpSuccess) { + if (frameResult == QRhi::FrameOpDeviceLost) + handleDeviceLoss(); + else if (frameResult == QRhi::FrameOpError) + qWarning("Failed to end frame"); + } } else if (needsPresent) { if (!cd->customRenderStage || !cd->customRenderStage->swap()) gl->swapBuffers(window); diff --git a/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp index 28fc10e413..53b6fe117f 100644 --- a/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp @@ -182,7 +182,9 @@ void QSGRhiDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField> &gly for (int i = 0; i < glyphs.size(); ++i) { TextureInfo *texInfo = m_glyphsTexture.value(glyphs.at(i).glyph()); if (!texInfo->uploads.isEmpty()) { - m_resourceUpdates->uploadTexture(texInfo->texture, texInfo->uploads); + QRhiTextureUploadDescription desc; + desc.setEntries(texInfo->uploads.cbegin(), texInfo->uploads.cend()); + m_resourceUpdates->uploadTexture(texInfo->texture, desc); texInfo->uploads.clear(); } } diff --git a/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h index ddd3d92ba7..d43b0aa5d4 100644 --- a/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h @@ -88,7 +88,7 @@ private: QRect allocatedArea; QDistanceField image; int padding = -1; - QVector<QRhiTextureUploadEntry> uploads; + QVarLengthArray<QRhiTextureUploadEntry, 16> uploads; TextureInfo(const QRect &preallocRect = QRect()) : texture(nullptr), allocatedArea(preallocRect) { } }; diff --git a/src/quick/scenegraph/qsgrhilayer.cpp b/src/quick/scenegraph/qsgrhilayer.cpp index 80ca40d50a..757410eded 100644 --- a/src/quick/scenegraph/qsgrhilayer.cpp +++ b/src/quick/scenegraph/qsgrhilayer.cpp @@ -388,7 +388,10 @@ void QSGRhiLayer::grab() m_mirrorHorizontal ? -m_rect.width() : m_rect.width(), m_mirrorVertical ? m_rect.height() : -m_rect.height()); } - m_renderer->setProjectionMatrixToRect(mirrored, !m_rhi->isYUpInNDC()); + QSGAbstractRenderer::MatrixTransformFlags matrixFlags = 0; + if (!m_rhi->isYUpInNDC()) + matrixFlags |= QSGAbstractRenderer::MatrixTransformFlipY; + m_renderer->setProjectionMatrixToRect(mirrored, matrixFlags); m_renderer->setClearColor(Qt::transparent); m_renderer->setRenderTarget(m_rt); m_renderer->setCommandBuffer(m_context->currentFrameCommandBuffer()); diff --git a/src/quick/scenegraph/qsgrhishadereffectnode.cpp b/src/quick/scenegraph/qsgrhishadereffectnode.cpp index fe9cecb51b..6f6544548c 100644 --- a/src/quick/scenegraph/qsgrhishadereffectnode.cpp +++ b/src/quick/scenegraph/qsgrhishadereffectnode.cpp @@ -211,9 +211,9 @@ class QSGRhiShaderEffectMaterialShader : public QSGMaterialRhiShader public: QSGRhiShaderEffectMaterialShader(const QSGRhiShaderEffectMaterial *material); - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - bool updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; QSGRhiShaderEffectMaterialShader::QSGRhiShaderEffectMaterialShader(const QSGRhiShaderEffectMaterial *material) @@ -228,7 +228,7 @@ static inline QColor qsg_premultiply_color(const QColor &c) return QColor::fromRgbF(c.redF() * c.alphaF(), c.greenF() * c.alphaF(), c.blueF() * c.alphaF(), c.alphaF()); } -bool QSGRhiShaderEffectMaterialShader::updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) +bool QSGRhiShaderEffectMaterialShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { Q_UNUSED(oldMaterial); QSGRhiShaderEffectMaterial *mat = static_cast<QSGRhiShaderEffectMaterial *>(newMaterial); @@ -381,7 +381,7 @@ bool QSGRhiShaderEffectMaterialShader::updateUniformData(const RenderState &stat return changed; } -void QSGRhiShaderEffectMaterialShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, +void QSGRhiShaderEffectMaterialShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { Q_UNUSED(oldMaterial); @@ -426,7 +426,7 @@ void QSGRhiShaderEffectMaterialShader::updateSampledImage(const RenderState &sta *texture = mat->m_dummyTexture; } -bool QSGRhiShaderEffectMaterialShader::updateGraphicsPipelineState(const RenderState &state, GraphicsPipelineState *ps, +bool QSGRhiShaderEffectMaterialShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { Q_UNUSED(state); diff --git a/src/quick/scenegraph/qsgrhisupport.cpp b/src/quick/scenegraph/qsgrhisupport.cpp index a92b6b0c84..12c6742342 100644 --- a/src/quick/scenegraph/qsgrhisupport.cpp +++ b/src/quick/scenegraph/qsgrhisupport.cpp @@ -101,7 +101,8 @@ QSGRhiSupport::QSGRhiSupport() m_enableRhi(false), m_debugLayer(false), m_profile(false), - m_shaderEffectDebug(false) + m_shaderEffectDebug(false), + m_preferSoftwareRenderer(false) { } @@ -140,7 +141,7 @@ void QSGRhiSupport::applySettings() } } else { // check env.vars., fall back to platform-specific defaults when backend is not set - m_enableRhi = qEnvironmentVariableIntValue("QSG_RHI"); + m_enableRhi = uint(qEnvironmentVariableIntValue("QSG_RHI")); const QByteArray rhiBackend = qgetenv("QSG_RHI_BACKEND"); if (rhiBackend == QByteArrayLiteral("gl") || rhiBackend == QByteArrayLiteral("gles2") @@ -171,12 +172,18 @@ void QSGRhiSupport::applySettings() return; // validation layers (Vulkan) or debug layer (D3D) - m_debugLayer = qEnvironmentVariableIntValue("QSG_RHI_DEBUG_LAYER"); + m_debugLayer = uint(qEnvironmentVariableIntValue("QSG_RHI_DEBUG_LAYER")); // EnableProfiling + DebugMarkers - m_profile = qEnvironmentVariableIntValue("QSG_RHI_PROFILE"); + m_profile = uint(qEnvironmentVariableIntValue("QSG_RHI_PROFILE")); - m_shaderEffectDebug = qEnvironmentVariableIntValue("QSG_RHI_SHADEREFFECT_DEBUG"); + m_shaderEffectDebug = uint(qEnvironmentVariableIntValue("QSG_RHI_SHADEREFFECT_DEBUG")); + + m_preferSoftwareRenderer = uint(qEnvironmentVariableIntValue("QSG_RHI_PREFER_SOFTWARE_RENDERER")); + + m_killDeviceFrameCount = qEnvironmentVariableIntValue("QSG_RHI_SIMULATE_DEVICE_LOSS"); + if (m_killDeviceFrameCount > 0 && m_rhiBackend == QRhi::D3D11) + qDebug("Graphics device will be reset every %d frames", m_killDeviceFrameCount); const char *backendName = "unknown"; switch (m_rhiBackend) { @@ -201,6 +208,8 @@ void QSGRhiSupport::applySettings() qCDebug(QSG_LOG_INFO, "Using QRhi with backend %s\n graphics API debug/validation layers: %d\n QRhi profiling and debug markers: %d", backendName, m_debugLayer, m_profile); + if (m_preferSoftwareRenderer) + qCDebug(QSG_LOG_INFO, "Prioritizing software renderers"); } QSGRhiSupport *QSGRhiSupport::staticInst() @@ -279,12 +288,16 @@ QSurface::SurfaceType QSGRhiSupport::windowSurfaceType() const } #if QT_CONFIG(vulkan) -static const void *qsgrhi_vk_rifResource(QSGRendererInterface::Resource res, const QRhiNativeHandles *nat, - const QRhiNativeHandles *cbNat) +static const void *qsgrhi_vk_rifResource(QSGRendererInterface::Resource res, + const QRhiNativeHandles *nat, + const QRhiNativeHandles *cbNat, + const QRhiNativeHandles *rpNat) { const QRhiVulkanNativeHandles *vknat = static_cast<const QRhiVulkanNativeHandles *>(nat); const QRhiVulkanCommandBufferNativeHandles *maybeVkCbNat = static_cast<const QRhiVulkanCommandBufferNativeHandles *>(cbNat); + const QRhiVulkanRenderPassNativeHandles *maybeVkRpNat = + static_cast<const QRhiVulkanRenderPassNativeHandles *>(rpNat); switch (res) { case QSGRendererInterface::DeviceResource: @@ -298,6 +311,11 @@ static const void *qsgrhi_vk_rifResource(QSGRendererInterface::Resource res, con return nullptr; case QSGRendererInterface::PhysicalDeviceResource: return &vknat->physDev; + case QSGRendererInterface::RenderPassResource: + if (maybeVkRpNat) + return &maybeVkRpNat->renderPass; + else + return nullptr; default: return nullptr; } @@ -376,7 +394,10 @@ const void *QSGRhiSupport::rifResource(QSGRendererInterface::Resource res, const case QRhi::Vulkan: { QRhiCommandBuffer *cb = rc->currentFrameCommandBuffer(); - return qsgrhi_vk_rifResource(res, nat, cb ? cb->nativeHandles() : nullptr); + QRhiRenderPassDescriptor *rp = rc->currentFrameRenderPass(); + return qsgrhi_vk_rifResource(res, nat, + cb ? cb->nativeHandles() : nullptr, + rp ? rp->nativeHandles() : nullptr); } #endif #if QT_CONFIG(opengl) @@ -447,6 +468,8 @@ QRhi *QSGRhiSupport::createRhi(QWindow *window, QOffscreenSurface *offscreenSurf QRhi::Flags flags = 0; if (isProfilingRequested()) flags |= QRhi::EnableProfiling | QRhi::EnableDebugMarkers; + if (isSoftwareRendererRequested()) + flags |= QRhi::PreferSoftwareRenderer; QRhi::Implementation backend = rhiBackend(); if (backend == QRhi::Null) { @@ -477,6 +500,10 @@ QRhi *QSGRhiSupport::createRhi(QWindow *window, QOffscreenSurface *offscreenSurf if (backend == QRhi::D3D11) { QRhiD3D11InitParams rhiParams; rhiParams.enableDebugLayer = isDebugLayerRequested(); + if (m_killDeviceFrameCount > 0) { + rhiParams.framesUntilKillingDeviceViaTdr = m_killDeviceFrameCount; + rhiParams.repeatDeviceKill = true; + } rhi = QRhi::create(backend, &rhiParams, flags); } #endif diff --git a/src/quick/scenegraph/qsgrhisupport_p.h b/src/quick/scenegraph/qsgrhisupport_p.h index f2d5837bba..d008ecd0af 100644 --- a/src/quick/scenegraph/qsgrhisupport_p.h +++ b/src/quick/scenegraph/qsgrhisupport_p.h @@ -114,6 +114,7 @@ public: bool isDebugLayerRequested() const { return m_debugLayer; } bool isProfilingRequested() const { return m_profile; } bool isShaderEffectDebuggingRequested() const { return m_shaderEffectDebug; } + bool isSoftwareRendererRequested() const { return m_preferSoftwareRenderer; } QSurface::SurfaceType windowSurfaceType() const; @@ -138,11 +139,13 @@ private: uint rhi : 1; } m_requested; QRhi::Implementation m_rhiBackend = QRhi::Null; + int m_killDeviceFrameCount; uint m_set : 1; uint m_enableRhi : 1; uint m_debugLayer : 1; uint m_profile : 1; uint m_shaderEffectDebug : 1; + uint m_preferSoftwareRenderer : 1; }; // Sends QRhi resource statistics over a QTcpSocket. To be initialized by the diff --git a/src/quick/scenegraph/qsgrhitextureglyphcache.cpp b/src/quick/scenegraph/qsgrhitextureglyphcache.cpp index 99761302e2..d0108bc56e 100644 --- a/src/quick/scenegraph/qsgrhitextureglyphcache.cpp +++ b/src/quick/scenegraph/qsgrhitextureglyphcache.cpp @@ -223,7 +223,9 @@ void QSGRhiTextureGlyphCache::endFillTexture() if (!m_resourceUpdates) m_resourceUpdates = m_rhi->nextResourceUpdateBatch(); - m_resourceUpdates->uploadTexture(m_texture, m_uploads); + QRhiTextureUploadDescription desc; + desc.setEntries(m_uploads.cbegin(), m_uploads.cend()); + m_resourceUpdates->uploadTexture(m_texture, desc); m_uploads.clear(); } diff --git a/src/quick/scenegraph/qsgrhitextureglyphcache_p.h b/src/quick/scenegraph/qsgrhitextureglyphcache_p.h index 75d82de90d..a7374d91a4 100644 --- a/src/quick/scenegraph/qsgrhitextureglyphcache_p.h +++ b/src/quick/scenegraph/qsgrhitextureglyphcache_p.h @@ -90,7 +90,7 @@ private: QRhiTexture *m_texture = nullptr; QSize m_size; bool m_bgra = false; - QVector<QRhiTextureUploadEntry> m_uploads; + QVarLengthArray<QRhiTextureUploadEntry, 16> m_uploads; QSet<QRhiTexture *> m_pendingDispose; }; diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 9e34a2b201..86d9590863 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -199,7 +199,7 @@ public: WMSyncEvent(QQuickWindow *c, bool inExpose, bool force) : WMWindowEvent(c, WM_RequestSync) , size(c->size()) - , dpr(c->effectiveDevicePixelRatio()) + , dpr(float(c->effectiveDevicePixelRatio())) , syncInExpose(inExpose) , forceRenderPass(force) {} @@ -306,8 +306,7 @@ public: delete offscreenSurface; } - void invalidateOpenGL(QQuickWindow *window, bool inDestructor, QOffscreenSurface *backupSurface); - void initializeOpenGL(); + void invalidateGraphics(QQuickWindow *window, bool inDestructor, QOffscreenSurface *backupSurface); bool event(QEvent *) override; void run() override; @@ -340,6 +339,9 @@ public: ExposeRequest = 0x04 | RepaintRequest | SyncRequest }; + void ensureRhi(); + void handleDeviceLoss(); + QSGThreadedRenderLoop *wm; QOpenGLContext *gl; bool enableRhi; @@ -419,9 +421,9 @@ bool QSGRenderThread::event(QEvent *e) WMTryReleaseEvent *wme = static_cast<WMTryReleaseEvent *>(e); if (!window || wme->inDestructor) { qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- setting exit flag and invalidating OpenGL"); - invalidateOpenGL(wme->window, wme->inDestructor, wme->needsFallback ? offscreenSurface : nullptr); + invalidateGraphics(wme->window, wme->inDestructor, wme->needsFallback ? offscreenSurface : nullptr); active = gl || rhi; - Q_ASSERT_X(!wme->inDestructor || !active, "QSGRenderThread::invalidateOpenGL()", "Thread's active state is not set to false when shutting down"); + Q_ASSERT_X(!wme->inDestructor || !active, "QSGRenderThread::invalidateGraphics()", "Thread's active state is not set to false when shutting down"); if (sleeping) stopEventProcessing = true; } else { @@ -512,9 +514,9 @@ bool QSGRenderThread::event(QEvent *e) return QThread::event(e); } -void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor, QOffscreenSurface *fallback) +void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor, QOffscreenSurface *fallback) { - qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "invalidateOpenGL()"); + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "invalidateGraphics()"); if (!gl && !rhi) return; @@ -562,7 +564,7 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor, QCoreApplication::processEvents(); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); if (inDestructor) - delete dd->animationController; + dd->animationController.reset(); if (current && gl) gl->doneCurrent(); qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- invalidating scene graph"); @@ -615,7 +617,7 @@ void QSGRenderThread::sync(bool inExpose, bool inGrab) QSGDefaultRenderContext::InitParams rcParams; rcParams.sampleCount = qMax(1, gl->format().samples()); rcParams.openGLContext = gl; - rcParams.initialSurfacePixelSize = windowSize * dpr; + rcParams.initialSurfacePixelSize = windowSize * qreal(dpr); rcParams.maybeSurface = window; sgrc->initialize(&rcParams); } @@ -658,6 +660,19 @@ void QSGRenderThread::sync(bool inExpose, bool inGrab) } } +void QSGRenderThread::handleDeviceLoss() +{ + if (!rhi || !rhi->isDeviceLost()) + return; + + qWarning("Graphics device lost, cleaning up scenegraph and releasing RHI"); + QQuickWindowPrivate::get(window)->cleanupNodesOnShutdown(); + sgrc->invalidate(); + wm->releaseSwapchain(window); + delete rhi; + rhi = nullptr; +} + void QSGRenderThread::syncAndRender(QImage *grabImage) { bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled(); @@ -699,30 +714,35 @@ void QSGRenderThread::syncAndRender(QImage *grabImage) if (previousOutputSize != effectiveOutputSize || cd->swapchainJustBecameRenderable) { if (cd->swapchainJustBecameRenderable) qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "just became exposed"); - cd->swapchainJustBecameRenderable = false; - cd->depthStencilForSwapchain->setPixelSize(effectiveOutputSize); - cd->depthStencilForSwapchain->build(); cd->hasActiveSwapchain = cd->swapchain->buildOrResize(); + if (!cd->hasActiveSwapchain && rhi->isDeviceLost()) { + handleDeviceLoss(); + QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest))); + return; + } + cd->swapchainJustBecameRenderable = false; cd->hasRenderableSwapchain = cd->hasActiveSwapchain; + if (!cd->hasActiveSwapchain) qWarning("Failed to build or resize swapchain"); else - qCDebug(QSG_LOG_RENDERLOOP) << "rhi swapchain size" << effectiveOutputSize; + qCDebug(QSG_LOG_RENDERLOOP) << "rhi swapchain size" << cd->swapchain->currentPixelSize(); } Q_ASSERT(rhi == cd->rhi); - QRhi::FrameOpResult frameResult = rhi->beginFrame(cd->swapchain); + // ### the flag should only be set when the app requests it, but there's no way to do that right now + QRhi::BeginFrameFlags frameFlags = QRhi::ExternalContentsInPass; + QRhi::FrameOpResult frameResult = rhi->beginFrame(cd->swapchain, frameFlags); if (frameResult != QRhi::FrameOpSuccess) { if (frameResult == QRhi::FrameOpDeviceLost) - qWarning("Device lost"); + handleDeviceLoss(); else if (frameResult == QRhi::FrameOpError) qWarning("Failed to start frame"); // try again later if (frameResult == QRhi::FrameOpDeviceLost || frameResult == QRhi::FrameOpSwapChainOutOfDate) QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest))); - // Before returning we need to ensure the same wake up logic that // would have happened if beginFrame() had suceeded. if (exposeRequested) { @@ -787,8 +807,9 @@ void QSGRenderThread::syncAndRender(QImage *grabImage) } } if (current) { + const QSize outputSize = rhi ? cd->swapchain->currentPixelSize() : windowSize; - d->renderSceneGraph(windowSize); + d->renderSceneGraph(outputSize); if (profileFrames) renderTime = threadTimer.nsecsElapsed(); @@ -808,7 +829,15 @@ void QSGRenderThread::syncAndRender(QImage *grabImage) QRhi::EndFrameFlags flags = 0; if (grabImage) flags |= QRhi::SkipPresent; - rhi->endFrame(cd->swapchain, flags); + QRhi::FrameOpResult frameResult = rhi->endFrame(cd->swapchain, flags); + if (frameResult != QRhi::FrameOpSuccess) { + if (frameResult == QRhi::FrameOpDeviceLost) + handleDeviceLoss(); + else if (frameResult == QRhi::FrameOpError) + qWarning("Failed to end frame"); + if (frameResult == QRhi::FrameOpDeviceLost || frameResult == QRhi::FrameOpSwapChainOutOfDate) + QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest))); + } } else { if (!cd->customRenderStage || !cd->customRenderStage->swap()) gl->swapBuffers(window); @@ -882,6 +911,57 @@ void QSGRenderThread::processEventsAndWaitForMore() qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "--- done processEventsAndWaitForMore()"); } +void QSGRenderThread::ensureRhi() +{ + if (!rhi) { + QSGRhiSupport *rhiSupport = QSGRhiSupport::instance(); + rhi = rhiSupport->createRhi(window, offscreenSurface); + if (rhi) { + rhiSampleCount = rhiSupport->chooseSampleCountForWindowWithRhi(window, rhi); + if (rhiSupport->isProfilingRequested()) + QSGRhiProfileConnection::instance()->initialize(rhi); // ### this breaks down with multiple windows + } else { + qWarning("Failed to create QRhi on the render thread; scenegraph is not functional"); + return; + } + } + if (!sgrc->rhi() && windowSize.width() > 0 && windowSize.height() > 0) { + rhi->makeThreadLocalNativeContextCurrent(); + QSGDefaultRenderContext::InitParams rcParams; + rcParams.rhi = rhi; + rcParams.sampleCount = rhiSampleCount; + rcParams.openGLContext = nullptr; + rcParams.initialSurfacePixelSize = windowSize * qreal(dpr); + rcParams.maybeSurface = window; + sgrc->initialize(&rcParams); + } + QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); + if (rhi && !cd->swapchain) { + cd->rhi = rhi; + QRhiSwapChain::Flags flags = QRhiSwapChain::UsedAsTransferSource; // may be used in a grab + // QQ is always premul alpha. Decide based on alphaBufferSize in + // requestedFormat(). (the platform plugin can override format() but + // what matters here is what the application wanted, hence using the + // requested one) + const bool alpha = window->requestedFormat().alphaBufferSize() > 0; + if (alpha) + flags |= QRhiSwapChain::SurfaceHasPreMulAlpha; + cd->swapchain = rhi->newSwapChain(); + cd->depthStencilForSwapchain = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, + QSize(), + rhiSampleCount, + QRhiRenderBuffer::UsedWithSwapChainOnly); + cd->swapchain->setWindow(window); + cd->swapchain->setDepthStencil(cd->depthStencilForSwapchain); + qCDebug(QSG_LOG_INFO, "MSAA sample count for the swapchain is %d. Alpha channel requested = %s.", + rhiSampleCount, alpha ? "yes" : "no"); + cd->swapchain->setSampleCount(rhiSampleCount); + cd->swapchain->setFlags(flags); + cd->rpDescForSwapchain = cd->swapchain->newCompatibleRenderPassDescriptor(); + cd->swapchain->setRenderPassDescriptor(cd->rpDescForSwapchain); + } +} + void QSGRenderThread::run() { qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "run()"); @@ -897,55 +977,20 @@ void QSGRenderThread::run() if (window) { if (enableRhi) { - if (!rhi) { - QSGRhiSupport *rhiSupport = QSGRhiSupport::instance(); - rhi = rhiSupport->createRhi(window, offscreenSurface); - if (rhi) { - rhiSampleCount = rhiSupport->chooseSampleCountForWindowWithRhi(window, rhi); - if (rhiSupport->isProfilingRequested()) - QSGRhiProfileConnection::instance()->initialize(rhi); // ### this breaks down with multiple windows - } else { - qWarning("Failed to create QRhi on the render thread; scenegraph is not functional"); - } - } - if (!sgrc->rhi() && windowSize.width() > 0 && windowSize.height() > 0) { - rhi->makeThreadLocalNativeContextCurrent(); - QSGDefaultRenderContext::InitParams rcParams; - rcParams.rhi = rhi; - rcParams.sampleCount = rhiSampleCount; - rcParams.openGLContext = gl; - rcParams.initialSurfacePixelSize = windowSize * dpr; - rcParams.maybeSurface = window; - sgrc->initialize(&rcParams); - } - QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); - if (rhi && !cd->swapchain) { - cd->rhi = rhi; - QRhiSwapChain::Flags flags = QRhiSwapChain::UsedAsTransferSource; // may be used in a grab - cd->swapchain = rhi->newSwapChain(); - cd->depthStencilForSwapchain = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, - QSize(), - rhiSampleCount, - QRhiRenderBuffer::UsedWithSwapChainOnly); - cd->swapchain->setWindow(window); - cd->swapchain->setDepthStencil(cd->depthStencilForSwapchain); - qCDebug(QSG_LOG_INFO, "MSAA sample count for the swapchain is %d", rhiSampleCount); - cd->swapchain->setSampleCount(rhiSampleCount); - cd->swapchain->setFlags(flags); - cd->rpDescForSwapchain = cd->swapchain->newCompatibleRenderPassDescriptor(); - cd->swapchain->setRenderPassDescriptor(cd->rpDescForSwapchain); - } + ensureRhi(); + if (rhi) + syncAndRender(); } else { if (!sgrc->openglContext() && windowSize.width() > 0 && windowSize.height() > 0 && gl->makeCurrent(window)) { QSGDefaultRenderContext::InitParams rcParams; rcParams.sampleCount = qMax(1, gl->format().samples()); rcParams.openGLContext = gl; - rcParams.initialSurfacePixelSize = windowSize * dpr; + rcParams.initialSurfacePixelSize = windowSize * qreal(dpr); rcParams.maybeSurface = window; sgrc->initialize(&rcParams); } + syncAndRender(); } - syncAndRender(); } processEvents(); @@ -1257,7 +1302,8 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window) } } - QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController; + QQuickAnimatorController *controller + = QQuickWindowPrivate::get(w->window)->animationController.get(); if (controller->thread() != w->thread) controller->moveToThread(w->thread); @@ -1352,6 +1398,8 @@ void QSGThreadedRenderLoop::maybeUpdate(Window *w) return; QThread *current = QThread::currentThread(); + if (current == w->thread && w->thread->rhi && w->thread->rhi->isDeviceLost()) + return; if (current != QCoreApplication::instance()->thread() && (current != w->thread || !m_lockedForSync)) { qWarning() << "Updates can only be scheduled from GUI thread or from QQuickItem::updatePaintNode()"; return; diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index 220c70c299..5b48b86568 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -269,7 +269,7 @@ void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window) m_gl->doneCurrent(); } - delete d->animationController; + d->animationController.reset(); } bool QSGWindowsRenderLoop::anyoneShowing() const diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri index c345f3b16d..56d97226fb 100644 --- a/src/quick/scenegraph/scenegraph.pri +++ b/src/quick/scenegraph/scenegraph.pri @@ -94,7 +94,6 @@ qtConfig(opengl(es1|es2)?) { # rhi, still tied to OpenGL-enabled Qt builds for now HEADERS += \ - $$PWD/qsgrhisupport_p.h \ $$PWD/qsgrhitextureglyphcache_p.h \ $$PWD/util/qsgrhiatlastexture_p.h \ $$PWD/qsgrhilayer_p.h \ @@ -102,7 +101,6 @@ qtConfig(opengl(es1|es2)?) { $$PWD/qsgrhidistancefieldglyphcache_p.h SOURCES += \ - $$PWD/qsgrhisupport.cpp \ $$PWD/qsgrhitextureglyphcache.cpp \ $$PWD/qsgrhilayer.cpp \ $$PWD/qsgrhishadereffectnode.cpp \ @@ -118,7 +116,8 @@ HEADERS += \ $$PWD/qsgbasicinternalrectanglenode_p.h \ $$PWD/qsgbasicinternalimagenode_p.h \ $$PWD/qsgbasicglyphnode_p.h \ - $$PWD/qsgrenderloop_p.h + $$PWD/qsgrenderloop_p.h \ + $$PWD/qsgrhisupport_p.h SOURCES += \ $$PWD/qsgadaptationlayer.cpp \ @@ -127,7 +126,8 @@ SOURCES += \ $$PWD/qsgbasicinternalrectanglenode.cpp \ $$PWD/qsgbasicinternalimagenode.cpp \ $$PWD/qsgbasicglyphnode.cpp \ - $$PWD/qsgrenderloop.cpp + $$PWD/qsgrenderloop.cpp \ + $$PWD/qsgrhisupport.cpp qtConfig(opengl(es1|es2)?) { SOURCES += \ diff --git a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp index f121d2a9e2..87941bf31a 100644 --- a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp +++ b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp @@ -121,7 +121,7 @@ class FlatColorMaterialRhiShader : public QSGMaterialRhiShader public: FlatColorMaterialRhiShader(); - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; FlatColorMaterialRhiShader::FlatColorMaterialRhiShader() @@ -130,7 +130,7 @@ FlatColorMaterialRhiShader::FlatColorMaterialRhiShader() setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/flatcolor.frag.qsb")); } -bool FlatColorMaterialRhiShader::updateUniformData(const RenderState &state, +bool FlatColorMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { diff --git a/src/quick/scenegraph/util/qsgrhiatlastexture.cpp b/src/quick/scenegraph/util/qsgrhiatlastexture.cpp index 665e9bb412..3dc1f5f526 100644 --- a/src/quick/scenegraph/util/qsgrhiatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgrhiatlastexture.cpp @@ -295,8 +295,7 @@ void Atlas::enqueueTextureUpload(TextureBase *t, QRhiResourceUpdateBatch *resour const int tmpBitsSize = tmpBits.size() * 4; const quint32 *src = reinterpret_cast<const quint32 *>(image.constBits()); quint32 *dst = tmpBits.data(); - QVector<QRhiTextureUploadEntry> entries; - entries.reserve(5); + QVarLengthArray<QRhiTextureUploadEntry, 5> entries; // top row, padding corners dst[0] = src[0]; @@ -361,7 +360,9 @@ void Atlas::enqueueTextureUpload(TextureBase *t, QRhiResourceUpdateBatch *resour entries.append(QRhiTextureUploadEntry(0, 0, subresDesc)); } - resourceUpdates->uploadTexture(m_texture, QRhiTextureUploadDescription(entries)); + QRhiTextureUploadDescription desc; + desc.setEntries(entries.cbegin(), entries.cend()); + resourceUpdates->uploadTexture(m_texture, desc); const QSize textureSize = t->textureSize(); if (textureSize.width() > m_atlas_transient_image_threshold || textureSize.height() > m_atlas_transient_image_threshold) diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp index df4e5cfde2..67b8748119 100644 --- a/src/quick/scenegraph/util/qsgtexturematerial.cpp +++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp @@ -125,7 +125,7 @@ QSGOpaqueTextureMaterialRhiShader::QSGOpaqueTextureMaterialRhiShader() setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/opaquetexture.frag.qsb")); } -bool QSGOpaqueTextureMaterialRhiShader::updateUniformData(const RenderState &state, QSGMaterial *, QSGMaterial *) +bool QSGOpaqueTextureMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *, QSGMaterial *) { bool changed = false; QByteArray *buf = state.uniformData(); @@ -139,7 +139,7 @@ bool QSGOpaqueTextureMaterialRhiShader::updateUniformData(const RenderState &sta return changed; } -void QSGOpaqueTextureMaterialRhiShader::updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, +void QSGOpaqueTextureMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { if (binding != 1) @@ -473,7 +473,7 @@ QSGTextureMaterialRhiShader::QSGTextureMaterialRhiShader() setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/texture.frag.qsb")); } -bool QSGTextureMaterialRhiShader::updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) +bool QSGTextureMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { bool changed = false; QByteArray *buf = state.uniformData(); diff --git a/src/quick/scenegraph/util/qsgtexturematerial_p.h b/src/quick/scenegraph/util/qsgtexturematerial_p.h index 7ef17af526..d1ef7d1d7f 100644 --- a/src/quick/scenegraph/util/qsgtexturematerial_p.h +++ b/src/quick/scenegraph/util/qsgtexturematerial_p.h @@ -75,8 +75,8 @@ class Q_QUICK_PRIVATE_EXPORT QSGOpaqueTextureMaterialRhiShader : public QSGMater public: QSGOpaqueTextureMaterialRhiShader(); - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - void updateSampledImage(const RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; class QSGTextureMaterialShader : public QSGOpaqueTextureMaterialShader @@ -96,7 +96,7 @@ class QSGTextureMaterialRhiShader : public QSGOpaqueTextureMaterialRhiShader public: QSGTextureMaterialRhiShader(); - bool updateUniformData(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; + bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp index 23f57141a6..c27dd7d1f0 100644 --- a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp +++ b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp @@ -100,7 +100,7 @@ class QSGVertexColorMaterialRhiShader : public QSGMaterialRhiShader public: QSGVertexColorMaterialRhiShader(); - bool updateUniformData(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; + bool updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; }; QSGVertexColorMaterialRhiShader::QSGVertexColorMaterialRhiShader() @@ -109,7 +109,7 @@ QSGVertexColorMaterialRhiShader::QSGVertexColorMaterialRhiShader() setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/vertexcolor.frag.qsb")); } -bool QSGVertexColorMaterialRhiShader::updateUniformData(const RenderState &state, +bool QSGVertexColorMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial * /*newEffect*/, QSGMaterial * /*oldEffect*/) { |