aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/coreapi/qsgmaterialshader.cpp')
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialshader.cpp611
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