aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph')
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp5
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h3
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp5
-rw-r--r--src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp48
-rw-r--r--src/quick/scenegraph/coreapi/qsgabstractrenderer.h10
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp39
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h14
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.cpp4
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialrhishader.cpp105
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialrhishader.h12
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendererinterface.cpp36
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendererinterface.h3
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture.cpp3
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture.h1
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp5
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h1
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp38
-rw-r--r--src/quick/scenegraph/qsgdefaultinternalimagenode.cpp4
-rw-r--r--src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp4
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp8
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext_p.h19
-rw-r--r--src/quick/scenegraph/qsgdefaultspritenode.cpp8
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp28
-rw-r--r--src/quick/scenegraph/qsgopengllayer.cpp2
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp90
-rw-r--r--src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp4
-rw-r--r--src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h2
-rw-r--r--src/quick/scenegraph/qsgrhilayer.cpp5
-rw-r--r--src/quick/scenegraph/qsgrhishadereffectnode.cpp12
-rw-r--r--src/quick/scenegraph/qsgrhisupport.cpp43
-rw-r--r--src/quick/scenegraph/qsgrhisupport_p.h3
-rw-r--r--src/quick/scenegraph/qsgrhitextureglyphcache.cpp4
-rw-r--r--src/quick/scenegraph/qsgrhitextureglyphcache_p.h2
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp166
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/scenegraph.pri8
-rw-r--r--src/quick/scenegraph/util/qsgflatcolormaterial.cpp4
-rw-r--r--src/quick/scenegraph/util/qsgrhiatlastexture.cpp7
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial.cpp6
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial_p.h6
-rw-r--r--src/quick/scenegraph/util/qsgvertexcolormaterial.cpp4
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*/)
{