diff options
Diffstat (limited to 'src/quick/scenegraph/coreapi/qsgmaterialshader.cpp')
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgmaterialshader.cpp | 611 |
1 files changed, 387 insertions, 224 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp b/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp index 64956e2ca4..57c6007e47 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp +++ b/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp @@ -40,37 +40,26 @@ #include "qsgmaterial.h" #include "qsgrenderer_p.h" #include "qsgmaterialshader_p.h" -#if QT_CONFIG(opengl) -# include <private/qsgshadersourcebuilder_p.h> -# include <private/qsgdefaultcontext_p.h> -# include <private/qsgdefaultrendercontext_p.h> -# include <QOpenGLFunctions> -# include <QOpenGLContext> -#endif +#include <QtCore/QFile> QT_BEGIN_NAMESPACE -#if QT_CONFIG(opengl) -const char *QSGMaterialShaderPrivate::loadShaderSource(QOpenGLShader::ShaderType type) const -{ - const QStringList files = m_sourceFiles[type]; - QSGShaderSourceBuilder builder; - for (const QString &file : files) - builder.appendSourceFile(file); - m_sources[type] = builder.source(); - return m_sources[type].constData(); -} -#endif - /*! \class QSGMaterialShader - \brief The QSGMaterialShader class represents an OpenGL shader program - in the renderer. + \brief The QSGMaterialShader class represents a graphics API independent shader program. \inmodule QtQuick \ingroup qtquick-scenegraph-materials + \since 5.14 + + // ### glpurge Rewrite to not talk about OpenGL and GLSL directly anymore + + QSGMaterialShader is a modern, cross-platform alternative to + QSGMaterialShader. The latter is tied to OpenGL and GLSL by design, whereas + QSGMaterialShader is based on QShader, a container for multiple + versions of a graphics shader together with reflection information. - \warning This class is only functional when running with the legacy OpenGL - renderer of the Qt Quick scenegraph. + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. The QSGMaterial and QSGMaterialShader form a tight relationship. For one scene graph (including nested graphs), there is one unique QSGMaterialShader @@ -160,16 +149,150 @@ const char *QSGMaterialShaderPrivate::loadShaderSource(QOpenGLShader::ShaderType \note All classes with QSG prefix should be used solely on the scene graph's rendering thread. See \l {Scene Graph and Rendering} for more information. + */ + +/*! + \enum QSGMaterialShader::Flag + Flag values to indicate special material properties. + \value UpdatesGraphicsPipelineState Setting this flag enables calling + updateGraphicsPipelineState(). */ +QShader QSGMaterialShaderPrivate::loadShader(const QString &filename) +{ + QFile f(filename); + if (!f.open(QIODevice::ReadOnly)) { + qWarning() << "Failed to find shader" << filename; + return QShader(); + } + return QShader::fromSerialized(f.readAll()); +} + +void QSGMaterialShaderPrivate::clearCachedRendererData() +{ + for (int i = 0; i < MAX_SHADER_RESOURCE_BINDINGS; ++i) + textureBindingTable[i] = nullptr; + for (int i = 0; i < MAX_SHADER_RESOURCE_BINDINGS; ++i) + samplerBindingTable[i] = nullptr; +} + +static inline QRhiShaderResourceBinding::StageFlags toSrbStage(QShader::Stage stage) +{ + switch (stage) { + case QShader::VertexStage: + return QRhiShaderResourceBinding::VertexStage; + case QShader::FragmentStage: + return QRhiShaderResourceBinding::FragmentStage; + default: + Q_UNREACHABLE(); + break; + } + return { }; +} + +void QSGMaterialShaderPrivate::prepare(QShader::Variant vertexShaderVariant) +{ + ubufBinding = -1; + ubufSize = 0; + ubufStages = { }; + memset(combinedImageSamplerBindings, 0, sizeof(combinedImageSamplerBindings)); + vertexShader = fragmentShader = nullptr; + masterUniformData.clear(); + + clearCachedRendererData(); + + for (QShader::Stage stage : { QShader::VertexStage, QShader::FragmentStage }) { + auto it = shaderFileNames.find(stage); + if (it != shaderFileNames.end()) { + QString fn = *it; + const QShader s = loadShader(*it); + if (!s.isValid()) + continue; + shaders[stage] = ShaderStageData(s); + // load only once, subsequent prepare() calls will have it all in shaders already + shaderFileNames.erase(it); + } + } + + auto vsIt = shaders.find(QShader::VertexStage); + if (vsIt != shaders.end()) { + vsIt->shaderVariant = vertexShaderVariant; + vsIt->vertexInputLocations.clear(); + vsIt->qt_order_attrib_location = -1; + + const QShaderDescription desc = vsIt->shader.description(); + const QVector<QShaderDescription::InOutVariable> vertexInputs = desc.inputVariables(); + for (const QShaderDescription::InOutVariable &v : vertexInputs) { + const QByteArray name = v.name.toUtf8(); + if (vertexShaderVariant == QShader::BatchableVertexShader + && name == QByteArrayLiteral("_qt_order")) + { + vsIt->qt_order_attrib_location = v.location; + } else { + vsIt->vertexInputLocations.append(v.location); + } + } + + if (vsIt->vertexInputLocations.contains(vsIt->qt_order_attrib_location)) { + qWarning("Vertex input clash in rewritten (batchable) vertex shader at input location %d. " + "Vertex shaders must avoid using this location.", vsIt->qt_order_attrib_location); + } + } + + for (auto it = shaders.begin(); it != shaders.end(); ++it) { + const QShaderDescription desc = it->shader.description(); + + const QVector<QShaderDescription::UniformBlock> ubufs = desc.uniformBlocks(); + const int ubufCount = ubufs.count(); + if (ubufCount > 1) { + qWarning("Multiple uniform blocks found in shader. " + "This should be avoided as Qt Quick supports only one."); + } + for (int i = 0; i < ubufCount; ++i) { + const QShaderDescription::UniformBlock &ubuf(ubufs[i]); + if (ubufBinding == -1 && ubuf.binding >= 0) { + ubufBinding = ubuf.binding; + ubufSize = ubuf.size; + ubufStages |= toSrbStage(it->shader.stage()); + masterUniformData.fill('\0', ubufSize); + } else if (ubufBinding == ubuf.binding && ubuf.binding >= 0) { + if (ubuf.size > ubufSize) { + ubufSize = ubuf.size; + masterUniformData.fill('\0', ubufSize); + } + ubufStages |= toSrbStage(it->shader.stage()); + } else { + qWarning("Uniform block %s (binding %d) ignored", qPrintable(ubuf.blockName), ubuf.binding); + } + } + + const QVector<QShaderDescription::InOutVariable> imageSamplers = desc.combinedImageSamplers(); + const int imageSamplersCount = imageSamplers.count(); + for (int i = 0; i < imageSamplersCount; ++i) { + const QShaderDescription::InOutVariable &var(imageSamplers[i]); + if (var.binding >= 0 && var.binding < MAX_SHADER_RESOURCE_BINDINGS) + combinedImageSamplerBindings[var.binding] |= toSrbStage(it->shader.stage()); + else + qWarning("Encountered invalid combined image sampler (%s) binding %d", + qPrintable(var.name), var.binding); + } + + if (it.key() == QShader::VertexStage) + vertexShader = &it.value(); + else if (it.key() == QShader::FragmentStage) + fragmentShader = &it.value(); + } + if (vertexShader && vertexShaderVariant == QShader::BatchableVertexShader && vertexShader->qt_order_attrib_location == -1) + qWarning("No rewriter-inserted attribute found, this should not happen."); +} /*! - Creates a new QSGMaterialShader. + Constructs a new QSGMaterialShader. */ QSGMaterialShader::QSGMaterialShader() - : d_ptr(new QSGMaterialShaderPrivate) + : d_ptr(new QSGMaterialShaderPrivate(this)) { } @@ -188,217 +311,189 @@ QSGMaterialShader::~QSGMaterialShader() { } -/*! - \fn char const *const *QSGMaterialShader::attributeNames() const - - Returns a zero-terminated array describing the names of the - attributes used in the vertex shader. - - This function is called when the shader is compiled to specify - which attributes exist. The order of the attribute names - defines the attribute register position in the vertex shader. - */ - -#if QT_CONFIG(opengl) -/*! - \fn const char *QSGMaterialShader::vertexShader() const - - Called when the shader is being initialized to get the vertex - shader source code. - - The contents returned from this function should never change. -*/ -const char *QSGMaterialShader::vertexShader() const +// We have our own enum as QShader is not initially public. Internally +// everything works with QShader::Stage however. So convert. +static inline QShader::Stage toShaderStage(QSGMaterialShader::Stage stage) { - Q_D(const QSGMaterialShader); - return d->loadShaderSource(QOpenGLShader::Vertex); + switch (stage) { + case QSGMaterialShader::VertexStage: + return QShader::VertexStage; + case QSGMaterialShader::FragmentStage: + return QShader::FragmentStage; + default: + Q_UNREACHABLE(); + return QShader::VertexStage; + } } - /*! - \fn const char *QSGMaterialShader::fragmentShader() const - - Called when the shader is being initialized to get the fragment - shader source code. - - The contents returned from this function should never change. -*/ -const char *QSGMaterialShader::fragmentShader() const + Sets the \a shader for the specified \a stage. + */ +void QSGMaterialShader::setShader(Stage stage, const QShader &shader) { - Q_D(const QSGMaterialShader); - return d->loadShaderSource(QOpenGLShader::Fragment); + Q_D(QSGMaterialShader); + d->shaders[toShaderStage(stage)] = QSGMaterialShaderPrivate::ShaderStageData(shader); } - -/*! - \fn QOpenGLShaderProgram *QSGMaterialShader::program() - - Returns the shader program used by this QSGMaterialShader. - */ -#endif - /*! - \fn void QSGMaterialShader::initialize() + Sets the \a filename for the shader for the specified \a stage. - Reimplement this function to do one-time initialization when the - shader program is compiled. The OpenGL shader program is compiled - and linked, but not bound, when this function is called. + The file is expected to contain a serialized QShader. */ - +void QSGMaterialShader::setShaderFileName(Stage stage, const QString &filename) +{ + Q_D(QSGMaterialShader); + d->shaderFileNames[toShaderStage(stage)] = filename; +} /*! - This function is called by the scene graph to indicate that geometry is - about to be rendered using this shader. - - State that is global for all uses of the shader, independent of the geometry - that is being drawn, can be setup in this function. + \return the currently set flags for this material shader. */ - -void QSGMaterialShader::activate() +QSGMaterialShader::Flags QSGMaterialShader::flags() const { + Q_D(const QSGMaterialShader); + return d->flags; } - - /*! - This function is called by the scene graph to indicate that geometry will - no longer to be rendered using this shader. - */ - -void QSGMaterialShader::deactivate() + Sets the \a flags on this material shader if \a on is true; + otherwise clears the specified flags. +*/ +void QSGMaterialShader::setFlag(Flags flags, bool on) { + Q_D(QSGMaterialShader); + if (on) + d->flags |= flags; + else + d->flags &= ~flags; } - - /*! - This function is called by the scene graph before geometry is rendered - to make sure the shader is in the right state. + This function is called by the scene graph to get the contents of the + shader program's uniform buffer updated. The implementation is not expected + to perform any real graphics operations, it is merely responsible for + copying data to the QByteArray returned from RenderState::uniformData(). + The scene graph takes care of making that buffer visible in the shaders. The current rendering \a state is passed from the scene graph. If the state - indicates that any state is dirty, the updateState implementation must - update accordingly for the geometry to render correctly. + indicates that any relevant state is dirty, the implementation must update + the appropriate region in the buffer data that is accessible via + RenderState::uniformData(). When a state, such as, matrix or opacity, is + not dirty, there is no need to touch the corresponding region since the + data is persistent. - The subclass specific state, such as the color of a flat color material, should - be extracted from \a newMaterial to update the color uniforms accordingly. + The return value must be \c true whenever any change was made to the uniform data. - The \a oldMaterial can be used to minimze state changes when updating - material states. The \a oldMaterial is 0 if this shader was just activated. + The subclass specific state, such as the color of a flat color material, + should be extracted from \a newMaterial to update the relevant regions in + the buffer accordingly. - \sa activate(), deactivate() + \a oldMaterial can be used to minimize buffer changes (which are typically + memcpy calls) when updating material states. When \a oldMaterial is null, + this shader was just activated. */ - -void QSGMaterialShader::updateState(const RenderState & /* state */, QSGMaterial * /* newMaterial */, QSGMaterial * /* oldMaterial */) +bool QSGMaterialShader::updateUniformData(RenderState &state, + QSGMaterial *newMaterial, + QSGMaterial *oldMaterial) { + Q_UNUSED(state); + Q_UNUSED(newMaterial); + Q_UNUSED(oldMaterial); + return false; } -#if QT_CONFIG(opengl) /*! - Sets the GLSL source file for the shader stage \a type to \a sourceFile. The - default implementation of the vertexShader() and fragmentShader() functions - will load the source files set by this function. + This function is called by the scene graph to prepare using a sampled image + in the shader, typically in form of a combined image sampler. - This function is useful when you have a single source file for a given shader - stage. If your shader consists of multiple source files then use - setShaderSourceFiles() + \a binding is the binding number of the sampler. The function is called for + each variable in the material's shaders' + \l{QShaderDescription::combinedImageSamplers()}. - \sa setShaderSourceFiles(), vertexShader(), fragmentShader() - */ -void QSGMaterialShader::setShaderSourceFile(QOpenGLShader::ShaderType type, const QString &sourceFile) -{ - Q_D(QSGMaterialShader); - d->m_sourceFiles[type] = (QStringList() << sourceFile); -} + When *\a{texture} is null, it must be set to a QSGTexture pointer before + returning. When non-null, it is up to the material to decide if a new + \c{QSGTexture *} is stored to it, or if it updates some parameters on the + already known QSGTexture. The ownership of the QSGTexture is not + transferred. -/*! - Sets the GLSL source files for the shader stage \a type to \a sourceFiles. The - default implementation of the vertexShader() and fragmentShader() functions - will load the source files set by this function in the order given. + The current rendering \a state is passed from the scene graph. It is up to + the material to enqueue the texture data uploads to the + QRhiResourceUpdateBatch retriveable via RenderState::resourceUpdateBatch(). - \sa setShaderSourceFile(), vertexShader(), fragmentShader() + The subclass specific state can be extracted from \a newMaterial. + + \a oldMaterial can be used to minimize changes. When \a oldMaterial is null, + this shader was just activated. */ -void QSGMaterialShader::setShaderSourceFiles(QOpenGLShader::ShaderType type, const QStringList &sourceFiles) +void QSGMaterialShader::updateSampledImage(RenderState &state, + int binding, + QSGTexture **texture, + QSGMaterial *newMaterial, + QSGMaterial *oldMaterial) { - Q_D(QSGMaterialShader); - d->m_sourceFiles[type] = sourceFiles; + Q_UNUSED(state); + Q_UNUSED(binding); + Q_UNUSED(texture); + Q_UNUSED(newMaterial); + Q_UNUSED(oldMaterial); } /*! - This function is called when the shader is initialized to compile the - actual QOpenGLShaderProgram. Do not call it explicitly. + This function is called by the scene graph to enable the material to + provide a custom set of graphics state. The set of states that are + customizable by material is limited to blending and related settings. - The default implementation will extract the vertexShader() and - fragmentShader() and bind the names returned from attributeNames() - to consecutive vertex attribute registers starting at 0. - */ + \note This function is only called when the UpdatesGraphicsPipelineState + flag was enabled via setFlags(). By default it is not set, and so this + function is never called. -void QSGMaterialShader::compile() -{ - Q_ASSERT_X(!m_program.isLinked(), "QSGSMaterialShader::compile()", "Compile called multiple times!"); - - program()->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader()); - program()->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader()); - - char const *const *attr = attributeNames(); -#ifndef QT_NO_DEBUG - int maxVertexAttribs = 0; - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - funcs->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); - for (int i = 0; attr[i]; ++i) { - if (i >= maxVertexAttribs) { - qFatal("List of attribute names is either too long or not null-terminated.\n" - "Maximum number of attributes on this hardware is %i.\n" - "Vertex shader:\n%s\n" - "Fragment shader:\n%s\n", - maxVertexAttribs, vertexShader(), fragmentShader()); - } - if (*attr[i]) - program()->bindAttributeLocation(attr[i], i); - } -#else - for (int i = 0; attr[i]; ++i) { - if (*attr[i]) - program()->bindAttributeLocation(attr[i], i); - } -#endif + The return value must be \c true whenever a change was made to any of the + members in \a ps. - if (!program()->link()) { - qWarning("QSGMaterialShader: Shader compilation failed:"); - qWarning() << program()->log(); - } -} + \note The contents of \a ps is not persistent between invocations of this + function. -#endif + The current rendering \a state is passed from the scene graph. + + The subclass specific state can be extracted from \a newMaterial. When \a + oldMaterial is null, this shader was just activated. + */ +bool QSGMaterialShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, + QSGMaterial *newMaterial, QSGMaterial *oldMaterial) +{ + Q_UNUSED(state); + Q_UNUSED(ps); + Q_UNUSED(newMaterial); + Q_UNUSED(oldMaterial); + return false; +} /*! \class QSGMaterialShader::RenderState - \brief The QSGMaterialShader::RenderState encapsulates the current rendering state - during a call to QSGMaterialShader::updateState(). - \inmodule QtQuick - The render state contains a number of accessors that the shader needs to respect - in order to conform to the current state of the scene graph. - - The instance is only valid inside a call to QSGMaterialShader::updateState() and - should not be used outisde this function. - */ + \brief Encapsulates the current rendering state during a call to + QSGMaterialShader::updateUniformData() and the other \c update type of + functions. + \inmodule QtQuick + \since 5.14 + The render state contains a number of accessors that the shader needs to + respect in order to conform to the current state of the scene graph. + */ /*! \enum QSGMaterialShader::RenderState::DirtyState - \value DirtyMatrix Used to indicate that the matrix has changed and must be updated. - - \value DirtyOpacity Used to indicate that the opacity has changed and must be updated. + \value DirtyMatrix Used to indicate that the matrix has changed and must be + updated. - \value DirtyCachedMaterialData Used to indicate that the cached material data have changed and must be updated. + \value DirtyOpacity Used to indicate that the opacity has changed and must + be updated. \value DirtyAll Used to indicate that everything needs to be updated. */ - - /*! \fn bool QSGMaterialShader::RenderState::isMatrixDirty() const @@ -406,8 +501,6 @@ void QSGMaterialShader::compile() otherwise returns \c false. */ - - /*! \fn bool QSGMaterialShader::RenderState::isOpacityDirty() const @@ -416,13 +509,6 @@ void QSGMaterialShader::compile() */ /*! - \fn bool QSGMaterialShader::RenderState::isCachedMaterialDataDirty() const - - Returns \c true if the dirtyStates() contains the dirty cached material state, - otherwise returns \c false. - */ - -/*! \fn QSGMaterialShader::RenderState::DirtyStates QSGMaterialShader::RenderState::dirtyStates() const Returns which rendering states that have changed and needs to be updated @@ -430,37 +516,98 @@ void QSGMaterialShader::compile() rendering state. */ +/*! + \class QSGMaterialShader::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 QSGMaterialShader. 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 QSGMaterialShader 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. + */ /*! - Returns the accumulated opacity to be used for rendering. + \enum QSGMaterialShader::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 QSGMaterialShader::GraphicsPipelineState::ColorMaskComponent + \since 5.14 + + \value R + \value G + \value B + \value A */ +/*! + \enum QSGMaterialShader::GraphicsPipelineState::CullMode + \since 5.14 + + \value CullNone + \value CullFront + \value CullBack + */ + +/*! + Returns the accumulated opacity to be used for rendering. + */ float QSGMaterialShader::RenderState::opacity() const { Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->currentOpacity(); + return float(static_cast<const QSGRenderer *>(m_data)->currentOpacity()); } /*! Returns the modelview determinant to be used for rendering. */ - float QSGMaterialShader::RenderState::determinant() const { Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->determinant(); + return float(static_cast<const QSGRenderer *>(m_data)->determinant()); } /*! Returns the matrix combined of modelview matrix and project matrix. */ - QMatrix4x4 QSGMaterialShader::RenderState::combinedMatrix() const { Q_ASSERT(m_data); return static_cast<const QSGRenderer *>(m_data)->currentCombinedMatrix(); } + /*! Returns the ratio between physical pixels and device-independent pixels to be used for rendering. @@ -468,29 +615,23 @@ QMatrix4x4 QSGMaterialShader::RenderState::combinedMatrix() const float QSGMaterialShader::RenderState::devicePixelRatio() const { Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->devicePixelRatio(); + return float(static_cast<const QSGRenderer *>(m_data)->devicePixelRatio()); } - - /*! Returns the model view matrix. - If the material has the RequiresFullMatrix flag - set, this is guaranteed to be the complete transform - matrix calculated from the scenegraph. + If the material has the RequiresFullMatrix flag set, this is guaranteed to + be the complete transform matrix calculated from the scenegraph. - However, if this flag is not set, the renderer may - choose to alter this matrix. For example, it may - pre-transform vertices on the CPU and set this matrix - to identity. + However, if this flag is not set, the renderer may choose to alter this + matrix. For example, it may pre-transform vertices on the CPU and set this + matrix to identity. - In a situation such as the above, it is still possible - to retrieve the actual matrix determinant by setting - the RequiresDeterminant flag in the material and - calling the determinant() accessor. + In a situation such as the above, it is still possible to retrieve the + actual matrix determinant by setting the RequiresDeterminant flag in the + material and calling the determinant() accessor. */ - QMatrix4x4 QSGMaterialShader::RenderState::modelViewMatrix() const { Q_ASSERT(m_data); @@ -500,53 +641,75 @@ QMatrix4x4 QSGMaterialShader::RenderState::modelViewMatrix() const /*! Returns the projection matrix. */ - QMatrix4x4 QSGMaterialShader::RenderState::projectionMatrix() const { Q_ASSERT(m_data); return static_cast<const QSGRenderer *>(m_data)->currentProjectionMatrix(); } - - /*! Returns the viewport rect of the surface being rendered to. */ - QRect QSGMaterialShader::RenderState::viewportRect() const { Q_ASSERT(m_data); return static_cast<const QSGRenderer *>(m_data)->viewportRect(); } - - /*! Returns the device rect of the surface being rendered to */ - QRect QSGMaterialShader::RenderState::deviceRect() const { Q_ASSERT(m_data); return static_cast<const QSGRenderer *>(m_data)->deviceRect(); } -#if QT_CONFIG(opengl) - /*! - Returns the QOpenGLContext that is being used for rendering + Returns a pointer to the data for the uniform (constant) buffer in the + shader. Uniform data must only be updated from + QSGMaterialShader::updateUniformData(). The return value is null in the + other reimplementable functions, such as, + QSGMaterialShader::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 + layout as described in section 7.6.2.2 of the OpenGL specification. It is + up to the QSGMaterialShader implementation to ensure data gets placed + at the right location in this QByteArray, taking alignment requirements + into account. Shader code translated to other shading languages is expected + to use the same offsets for block members, even when the target language + uses different packing rules by default. + + \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. */ +QByteArray *QSGMaterialShader::RenderState::uniformData() +{ + Q_ASSERT(m_data); + return static_cast<const QSGRenderer *>(m_data)->currentUniformData(); +} -QOpenGLContext *QSGMaterialShader::RenderState::context() const +/*! + Returns a resource update batch to which upload and copy operatoins can be + queued. This is typically used by + QSGMaterialShader::updateSampledImage() to enqueue texture image + content updates. + */ +QRhiResourceUpdateBatch *QSGMaterialShader::RenderState::resourceUpdateBatch() { - // Only the QSGDefaultRenderContext will have an OpenGL Context to query - auto openGLRenderContext = static_cast<const QSGDefaultRenderContext *>(static_cast<const QSGRenderer *>(m_data)->context()); - if (openGLRenderContext != nullptr) - return openGLRenderContext->openglContext(); - else - return nullptr; + Q_ASSERT(m_data); + return static_cast<const QSGRenderer *>(m_data)->currentResourceUpdateBatch(); } -#endif +/*! + Returns the current QRhi. + */ +QRhi *QSGMaterialShader::RenderState::rhi() +{ + Q_ASSERT(m_data); + return static_cast<const QSGRenderer *>(m_data)->currentRhi(); +} QT_END_NAMESPACE |