9#include <private/qsgplaintexture_p.h>
13#include <QFileSelector>
14#include <QMutexLocker>
42 for (
int i = 0;
i <
shader.shaderInfo.variables.size(); ++
i) {
48 c.specialType = vd.specialType;
51 if (shaderEffectDebug) {
54 <<
"offset" <<
var.offset <<
"value" <<
c.
value;
57 <<
"offset" <<
var.offset <<
"special" <<
c.specialType;
62 c.value =
var.name.mid(11);
68 for (
int idx : *dirtyIndices) {
69 const int offset =
shader.shaderInfo.variables.at(idx).offset;
72 if (shaderEffectDebug) {
83 for (
int i = 0;
i <
shader.shaderInfo.variables.size(); ++
i) {
91 Q_ASSERT(existingBindPoint < 0 || existingBindPoint ==
var.bindPoint);
99 for (
int idx : *dirtyIndices) {
105 Q_ASSERT(existingBindPoint < 0 || existingBindPoint ==
var.bindPoint);
121 if (
c.value.userType() == QMetaType::QByteArray) {
124 qWarning(
"ShaderEffect: qt_SubRect_%s refers to unknown source texture",
name.constData());
136 qDebug() <<
"Failed to generate program data";
148 debug <<
"size" <<
c.size;
150 debug <<
"special" <<
c.specialType;
152 debug <<
"value" <<
c.value;
270 c.getRgbF(&
r, &
g, &
b, &
a);
277 const size_t valueBytes =
sizeof(T) * valueCount;
278 const size_t fieldBytes = fieldSizeBytes;
279 if (valueBytes <= fieldBytes) {
281 if (valueBytes < fieldBytes)
282 memset(
dst + valueBytes, 0, fieldBytes - valueBytes);
293 bool changed =
false;
296 for (
auto it = mat->m_linker.m_constants.
constBegin(), itEnd = mat->m_linker.m_constants.constEnd();
it != itEnd; ++
it) {
301 if (
state.isOpacityDirty()) {
302 const float f =
state.opacity();
303 fillUniformBlockMember<float>(
dst, &
f, 1,
c.size);
307 if (
state.isMatrixDirty()) {
309 const int rendererViewCount =
state.projectionMatrixCount();
310 const int shaderMatrixCount =
c.size / 64;
311 if (shaderMatrixCount < mat->viewCount() && mat->viewCount() >= 2) {
312 qWarning(
"qt_Matrix uniform block member size is wrong: expected at least view_count * 64 bytes, "
313 "where view_count is %d, meaning %d bytes in total, but got only %d bytes. "
314 "This may be due to the ShaderEffect and its shaders not being multiview-capable, "
315 "or they are used with an unexpected render target. "
316 "Check if the shaders declare qt_Matrix as appropriate, "
317 "and if gl_ViewIndex is used correctly in the vertex shader.",
318 mat->viewCount(), mat->viewCount() * 64,
c.size);
320 const int matrixCount =
qMin(rendererViewCount, shaderMatrixCount);
322 for (
int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) {
324 fillUniformBlockMember<float>(
dst +
offset,
m.constData(), 16, 64);
333 QRectF subRect(0, 0, 1, 1);
334 const int binding =
c.value.toInt();
338 subRect =
t->normalizedTextureSubRect();
341 const float f[4] = { float(subRect.x()), float(subRect.y()),
342 float(subRect.width()), float(subRect.height()) };
343 fillUniformBlockMember<float>(
dst,
f, 4,
c.size);
346 switch (
int(
c.value.userType())) {
347 case QMetaType::QColor: {
349 const float f[4] = { float(
v.redF()), float(
v.greenF()), float(
v.blueF()), float(
v.alphaF()) };
350 fillUniformBlockMember<float>(
dst,
f, 4,
c.size);
353 case QMetaType::Float: {
354 const float f = qvariant_cast<float>(
c.value);
355 fillUniformBlockMember<float>(
dst, &
f, 1,
c.size);
358 case QMetaType::Double: {
359 const float f = float(qvariant_cast<double>(
c.value));
360 fillUniformBlockMember<float>(
dst, &
f, 1,
c.size);
363 case QMetaType::Int: {
365 fillUniformBlockMember<qint32>(
dst, &
i, 1,
c.size);
368 case QMetaType::Bool: {
370 fillUniformBlockMember<qint32>(
dst, &
b, 1,
c.size);
373 case QMetaType::QTransform: {
374 const QTransform v = qvariant_cast<QTransform>(
c.value);
375 const float m[3][3] = {
376 { float(
v.m11()), float(
v.m12()), float(
v.m13()) },
377 { float(
v.m21()), float(
v.m22()), float(
v.m23()) },
378 { float(
v.m31()), float(
v.m32()), float(
v.m33()) }
381 memset(
dst, 0,
c.size);
382 const size_t bytesPerColumn = 4 *
sizeof(float);
383 if (
c.size >= bytesPerColumn)
384 fillUniformBlockMember<float>(
dst,
m[0], 3, 3 *
sizeof(
float));
385 if (
c.size >= 2 * bytesPerColumn)
386 fillUniformBlockMember<float>(
dst + bytesPerColumn,
m[1], 3, 3 *
sizeof(
float));
387 if (
c.size >= 3 * bytesPerColumn)
388 fillUniformBlockMember<float>(
dst + 2 * bytesPerColumn,
m[2], 3, 3 *
sizeof(
float));
391 case QMetaType::QSize:
392 case QMetaType::QSizeF: {
394 const float f[2] = { float(
v.width()), float(
v.height()) };
395 fillUniformBlockMember<float>(
dst,
f, 2,
c.size);
398 case QMetaType::QPoint:
399 case QMetaType::QPointF: {
401 const float f[2] = { float(
v.x()), float(
v.y()) };
402 fillUniformBlockMember<float>(
dst,
f, 2,
c.size);
405 case QMetaType::QRect:
406 case QMetaType::QRectF: {
408 const float f[4] = { float(
v.x()), float(
v.y()), float(
v.width()), float(
v.height()) };
409 fillUniformBlockMember<float>(
dst,
f, 4,
c.size);
412 case QMetaType::QVector2D: {
413 const QVector2D v = qvariant_cast<QVector2D>(
c.value);
414 const float f[2] = { float(
v.x()), float(
v.y()) };
415 fillUniformBlockMember<float>(
dst,
f, 2,
c.size);
418 case QMetaType::QVector3D: {
419 const QVector3D v = qvariant_cast<QVector3D>(
c.value);
420 const float f[3] = { float(
v.x()), float(
v.y()), float(
v.z()) };
421 fillUniformBlockMember<float>(
dst,
f, 3,
c.size);
424 case QMetaType::QVector4D: {
425 const QVector4D v = qvariant_cast<QVector4D>(
c.value);
426 const float f[4] = { float(
v.x()), float(
v.y()), float(
v.z()), float(
v.w()) };
427 fillUniformBlockMember<float>(
dst,
f, 4,
c.size);
430 case QMetaType::QQuaternion: {
432 const float f[4] = { float(
v.x()), float(
v.y()), float(
v.z()), float(
v.scalar()) };
433 fillUniformBlockMember<float>(
dst,
f, 4,
c.size);
436 case QMetaType::QMatrix4x4: {
437 const QMatrix4x4 m = qvariant_cast<QMatrix4x4>(
c.value);
438 fillUniformBlockMember<float>(
dst,
m.constData(), 16,
c.size);
462 t->commitTextureOperations(
state.rhi(),
state.resourceUpdateBatch());
464 if (
t->isAtlasTexture() && !mat->m_geometryUsesTextureSubRect && !mat->usesSubRectUniform(binding)) {
483 if (!mat->m_dummyTexture) {
490 mat->m_dummyTexture->setImage(
img);
491 mat->m_dummyTexture->commitTextureOperations(
state.rhi(),
state.resourceUpdateBatch());
493 *
texture = mat->m_dummyTexture;
503 switch (mat->m_cullMode) {
505 ps->
cullMode = GraphicsPipelineState::CullFront;
508 ps->
cullMode = GraphicsPipelineState::CullBack;
532 if (tp && tp->texture() && tp->texture()->isAtlasTexture())
565 const qint64 diff =
t1->comparisonKey() -
t2->comparisonKey();
567 return diff < 0 ? -1 : 1;
602 SLOT(handleTextureChange()));
611 const int binding =
it.key();
615 qWarning(
"Sampler at binding %d exceeds the available ShaderEffect binding slots; ignored",
620 if (newProvider != activeProvider) {
621 if (activeProvider) {
623 SLOT(handleTextureChange()));
629 "QSGRhiShaderEffectMaterial::updateTextureProviders",
630 "Texture provider must belong to the rendering thread");
636 qWarning(
"ShaderEffect: Texture t%d is not assigned a valid texture provider (%s).",
639 activeProvider = newProvider;
654 QRectF srcRect(0, 0, 1, 1);
655 bool geometryUsesTextureSubRect =
false;
656 if (supportsAtlasTextures) {
669 srcRect = tp->
texture()->normalizedTextureSubRect();
670 geometryUsesTextureSubRect =
true;
686 qWarning() <<
"Failed to find shader" << filename;
705 const QList<QShaderDescription::BlockVariable> uboMembers =
s.shader.description().uniformBlocks().constFirst().members;
706 for (
const auto &member: uboMembers) {
708 s.matrixArrayByteSize = member.size;
710 s.opacityOffset = member.offset;
718 static const int defaultVertexShaderCount = 2;
723 static const int defaultFragmentShaderCount = 2;
734 if (m_material.
m_cullMode != syncData->cullMode) {
746 quint32 defaultMatrixArrayByteSize = 0;
751 for (
int i = 0;
i < defaultVertexShaderCount; ++
i) {
752 if (defaultVertexShaders[
i].viewCount == syncData->viewCount) {
754 defaultMatrixArrayByteSize = defaultVertexShaders[
i].matrixArrayByteSize;
760 qWarning(
"No default vertex shader found for view count %d", syncData->viewCount);
762 defaultMatrixArrayByteSize = 64;
767 quint32 defaultOpacityOffset = 0;
772 for (
int i = 0;
i < defaultFragmentShaderCount; ++
i) {
773 if (defaultFragmentShaders[
i].viewCount == syncData->viewCount) {
775 defaultOpacityOffset = defaultFragmentShaders[
i].opacityOffset;
781 qWarning(
"No default fragment shader found for view count %d", syncData->viewCount);
783 defaultOpacityOffset = 64;
806 v.size = defaultMatrixArrayByteSize;
807 defaultSD.shaderInfo.variables.append(
v);
810 defaultSD.varData.append(vd);
826 v.offset = defaultOpacityOffset;
827 v.size =
sizeof(float);
828 defaultSD.shaderInfo.variables.append(
v);
831 defaultSD.varData.append(vd);
836 defaultSD.shaderInfo.variables.append(
v);
839 vd.value = extVarData.value;
844 defaultSD.varData.append(vd);
857 if (!syncData->vertex.dirtyConstants->isEmpty())
859 if (!syncData->fragment.dirtyConstants->isEmpty())
865 if (!syncData->vertex.dirtyTextures->isEmpty())
867 if (!syncData->fragment.dirtyTextures->isEmpty())
881void QSGRhiShaderEffectNode::handleTextureChange()
887void QSGRhiShaderEffectNode::handleTextureProviderDestroyed(
QObject *
object)
923 if (!m_fileSelector) {
930 qWarning(
"ShaderEffect: Failed to deserialize QShader from %s. "
931 "Either the filename is incorrect, or it is not a valid .qsb file. "
932 "In Qt 6 shaders must be preprocessed using the Qt Shader Tools infrastructure. "
933 "The vertexShader and fragmentShader properties are now URLs that are expected to point to .qsb files generated by the qsb tool. "
934 "See https://doc.qt.io/qt-6/qtshadertools-index.html for more information.",
948 qWarning(
"rhi shader effect only supports files (qrc or local) at the moment");
953bool QSGRhiGuiThreadShaderEffectManager::reflect(ShaderInfo *
result)
955 switch (
result->rhiShader.stage()) {
957 result->type = ShaderInfo::TypeVertex;
960 result->type = ShaderInfo::TypeFragment;
963 result->type = ShaderInfo::TypeOther;
964 qWarning(
"Unsupported shader stage (%d)",
result->rhiShader.stage());
970 int ubufBinding = -1;
971 const QVector<QShaderDescription::UniformBlock> ubufs =
desc.uniformBlocks();
972 const int ubufCount = ubufs.size();
973 for (
int i = 0;
i < ubufCount; ++
i) {
975 if (ubufBinding == -1 && ubuf.binding >= 0) {
976 ubufBinding = ubuf.binding;
978 ShaderInfo::Variable
v;
979 v.type = ShaderInfo::Constant;
980 v.name = member.name;
981 v.offset = member.offset;
982 v.size = member.size;
986 qWarning(
"Uniform block %s (binding %d) ignored", ubuf.blockName.constData(),
991 const QVector<QShaderDescription::InOutVariable> combinedImageSamplers =
desc.combinedImageSamplers();
992 const int samplerCount = combinedImageSamplers.size();
993 for (
int i = 0;
i < samplerCount; ++
i) {
995 ShaderInfo::Variable
v;
996 v.type = ShaderInfo::Sampler;
997 v.name = combinedImageSampler.name;
998 v.bindPoint = combinedImageSampler.binding;
1007#include "moc_qsgrhishadereffectnode_p.cpp"
The QColor class provides colors based on RGB, HSV or CMYK values.
static QColor fromRgbF(float r, float g, float b, float a=1.0)
Static convenience function that returns a QColor constructed from the RGB color values,...
void setExtraSelectors(const QStringList &list)
Sets the list of extra selectors which have been added programmatically to this instance.
QString select(const QString &filePath) const
This function returns the selected version of the path, based on the conditions at runtime.
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
void reserve(qsizetype size)
Ensures that the QHash's internal hash table has space to store at least size items without having to...
const_iterator constBegin() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
T value(const Key &key) const noexcept
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
@ Format_ARGB32_Premultiplied
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
\inmodule QtCore\reentrant
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to \l{QFile}.
The QQuaternion class represents a quaternion consisting of a vector and scalar.
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
\inmodule QtCore\reentrant
The QSGDynamicTexture class serves as a baseclass for dynamically changing textures,...
void setMaterial(QSGMaterial *material)
Sets the material of this geometry node to material.
void shaderCodePrepared(bool ok, ShaderInfo::Type typeHint, const QUrl &src, ShaderInfo *result)
void logAndStatusChanged()
Encapsulates the current rendering state during a call to QSGMaterialShader::updateUniformData() and ...
The QSGMaterialShader class represents a graphics API independent shader program.
void setShader(Stage stage, const QShader &shader)
Sets the shader for the specified stage.
void setFlag(Flags flags, bool on=true)
Sets the flags on this material shader if on is true; otherwise clears the specified flags.
@ UpdatesGraphicsPipelineState
The QSGMaterial class encapsulates rendering state for a shader program.
QSGMaterial::Flags flags() const
Returns the material's flags.
void setFlag(Flags flags, bool on=true)
Sets the flags flags on this material if on is true; otherwise clears the attribute.
void markDirty(DirtyState bits)
Notifies all connected renderers that the node has dirty bits.
void setFlag(Flag, bool=true)
Sets the flag f on this node if enabled is true; otherwise clears the flag.
RenderMode
\value RenderMode2D Normal 2D rendering \value RenderMode2DNoDepthBuffer Normal 2D rendering with dep...
QString log() const override
void prepareShaderCode(ShaderInfo::Type typeHint, const QUrl &src, ShaderInfo *result) override
Status status() const override
bool hasSeparateSamplerAndTextureObjects() const override
void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to prepare use of sampled images in the shader,...
QSGRhiShaderEffectMaterialShader(const QSGRhiShaderEffectMaterial *material)
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to get the contents of the shader program's uniform buffer...
bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to enable the material to provide a custom set of graphics...
QSGRhiShaderLinker m_linker
QVector< QSGTextureProvider * > m_textureProviders
bool m_hasCustomFragmentShader
static const int MAX_BINDINGS
QSGMaterialType * m_materialType
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
~QSGRhiShaderEffectMaterial()
QSGRhiShaderEffectMaterial(QSGRhiShaderEffectNode *node)
int compare(const QSGMaterial *other) const override
Compares this material to other and returns 0 if they are equal; -1 if this material should sort befo...
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode renderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
QSGRhiShaderEffectNode * m_node
void * m_materialTypeCacheKey
QSGPlainTexture * m_dummyTexture
QSGShaderEffectNode::CullMode m_cullMode
void updateTextureProviders(bool layoutChange)
bool m_geometryUsesTextureSubRect
bool m_hasCustomVertexShader
void preprocess() override
Override this function to do processing on the node before it is rendered.
static void garbageCollectMaterialTypeCache(void *materialTypeCacheKey)
QRectF updateNormalizedTextureSubRect(bool supportsAtlasTextures) override
QSGRhiShaderEffectNode(QSGDefaultRenderContext *rc)
void syncMaterial(SyncData *syncData) override
static void resetMaterialTypeCache(void *materialTypeCacheKey)
void feedSamplers(const QSGShaderEffectNode::ShaderData &shader, const QSet< int > *dirtyIndices=nullptr)
QHash< QByteArray, int > m_samplerNameMap
void reset(const QShader &vs, const QShader &fs)
QHash< uint, Constant > m_constants
void linkTextureSubRects()
QSet< int > m_subRectBindings
QHash< int, QVariant > m_samplers
void feedConstants(const QSGShaderEffectNode::ShaderData &shader, const QSet< int > *dirtyIndices=nullptr)
The QSGTextureProvider class encapsulates texture based entities in QML.
virtual QSGTexture * texture() const =0
Returns a pointer to the texture object.
virtual void commitTextureOperations(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates)
Call this function to enqueue image upload operations to resourceUpdates, in case there are any pendi...
virtual QSGTexture * removedFromAtlas(QRhiResourceUpdateBatch *resourceUpdates=nullptr) const
This function returns a copy of the current texture which is removed from its atlas.
void setFiltering(Filtering filter)
Sets the sampling mode to filter.
const_iterator constBegin() const noexcept
iterator insert(const T &value)
QShaderCode shader(const QShaderKey &key) const
static QShader fromSerialized(const QByteArray &data)
Creates a new QShader instance from the given data.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QThread * currentThread()
The QVector2D class represents a vector or vertex in 2D space.
The QVector3D class represents a vector or vertex in 3D space.
The QVector4D class represents a vector or vertex in 4D space.
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Combined button and popup list for selecting options.
#define QByteArrayLiteral(str)
QList< QString > QStringList
Constructs a string list that contains the given string, str.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr const T & qMin(const T &a, const T &b)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei count
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
[4]
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLuint GLintptr offset
GLsizei GLsizei GLchar * source
Members members(const Members &candidates, QTypeRevision maxMajorVersion, Postprocess &&process)
QQuickItem * qobject_cast< QQuickItem * >(QObject *o)
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
#define Q_ASSERT_X(cond, x, msg)
static void fillUniformBlockMember(char *dst, const T *value, int valueCount, int fieldSizeBytes)
static QShader loadShaderFromFile(const QString &filename)
size_t qHash(const QSGRhiShaderMaterialTypeCache::Key &key, size_t seed=0)
static QMutex shaderMaterialTypeCacheMutex
static QColor qsg_premultiply_color(const QColor &c)
static QHash< void *, QSGRhiShaderMaterialTypeCache > shaderMaterialTypeCache
static bool hasAtlasTexture(const QVector< QSGTextureProvider * > &textureProviders)
QDebug operator<<(QDebug debug, const QSGRhiShaderLinker::Constant &c)
#define qPrintable(string)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
QT_BEGIN_NAMESPACE typedef signed char qint8
Describes state changes that the material wants to apply to the currently active graphics pipeline st...
The QSGMaterialType class is used as a unique type token in combination with QSGMaterial.
quint32 matrixArrayByteSize
static QSGRhiShaderEffectDefaultShader create(const QString &filename, int viewCount)
bool operator==(const Key &other) const
Key(const QShader &vs, const QShader &fs)
QHash< Key, MaterialType > m_types
void unref(const QShader &vs, const QShader &fs)
QSGMaterialType * ref(const QShader &vs, const QShader &fs)
QHash< Key, QSGMaterialType * > m_graveyard
QSGGuiThreadShaderEffectManager::ShaderInfo shaderInfo
\variable QShaderDescription::InOutVariable::name