Revision control

++ // Copyright (C) 2025 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++
++ #ifndef QSSG_RENDER_PARTICLE_SHADER_KEY_H
++ #define QSSG_RENDER_PARTICLE_SHADER_KEY_H
++
++ //
++ // W A R N I N G
++ // -------------
++ //
++ // This file is not part of the Qt API. It exists purely as an
++ // implementation detail. This header file may change from version to
++ // version without notice, or even be removed.
++ //
++ // We mean it.
++ //
++
++ #include "qssgrendershaderkeys_p.h"
++
++ QT_BEGIN_NAMESPACE
++
++ struct QSSGShaderParticleMaterialKeyProperties
++ {
++ qsizetype m_stringBufferSizeHint = 0;
++ QSSGShaderKeyBoolean m_isSpriteLinear;
++ QSSGShaderKeyBoolean m_isColorTableLinear;
++ QSSGShaderKeyBoolean m_hasLighting;
++ QSSGShaderKeyBoolean m_isLineParticle;
++ QSSGShaderKeyBoolean m_isMapped;
++ QSSGShaderKeyBoolean m_isAnimated;
++ QSSGShaderKeyBoolean m_oitMSAA;
++ QSSGShaderKeyUnsigned<3> m_viewCount;
++ QSSGShaderKeyUnsigned<3> m_orderIndependentTransparency;
++
++ QSSGShaderParticleMaterialKeyProperties()
++ : m_isSpriteLinear("isSpriteLinear")
++ , m_isColorTableLinear("isColorTableLinear")
++ , m_hasLighting("hasLighting")
++ , m_isLineParticle("isLineParticle")
++ , m_isMapped("isMapped")
++ , m_isAnimated("isAnimated")
++ , m_oitMSAA("oitMSAA")
++ , m_viewCount("viewCount")
++ , m_orderIndependentTransparency("orderIndependentTransparency")
++ {
++ init();
++ }
++
++ template<typename TVisitor>
++ void visitProperties(TVisitor &inVisitor)
++ {
++ inVisitor.visit(m_isSpriteLinear);
++ inVisitor.visit(m_isColorTableLinear);
++ inVisitor.visit(m_hasLighting);
++ inVisitor.visit(m_isLineParticle);
++ inVisitor.visit(m_isMapped);
++ inVisitor.visit(m_isAnimated);
++ inVisitor.visit(m_oitMSAA);
++ inVisitor.visit(m_viewCount);
++ inVisitor.visit(m_orderIndependentTransparency);
++ }
++
++ struct OffsetVisitor
++ {
++ quint32 m_offset;
++ OffsetVisitor() : m_offset(0) {}
++ template<typename TPropType>
++ void visit(TPropType &inProp)
++ {
++ // if we cross the 32 bit border we just move
++ // to the next dword.
++ // This cost a few extra bits but prevents tedious errors like
++ // loosing shader key bits because they got moved beyond the 32 border
++ quint32 bit = m_offset % 32;
++ if (bit + TPropType::BitWidth > 32) {
++ m_offset += 32 - bit;
++ }
++
++ inProp.setOffset(m_offset);
++ m_offset += TPropType::BitWidth;
++ }
++ };
++
++ struct StringSizeVisitor
++ {
++ qsizetype size = 0;
++ template<typename P>
++ constexpr void visit(const P &prop)
++ {
++ size += prop.name.size();
++ }
++ };
++
++ struct InitVisitor
++ {
++ OffsetVisitor offsetVisitor;
++ StringSizeVisitor stringSizeVisitor;
++
++ template<typename P>
++ void visit(P &prop)
++ {
++ offsetVisitor.visit(prop);
++ stringSizeVisitor.visit(prop);
++ }
++ };
++
++ void init()
++ {
++ InitVisitor visitor;
++ visitProperties(visitor);
++
++ // If this assert fires, then the material key needs more bits.
++ Q_ASSERT(visitor.offsetVisitor.m_offset < 32);
++ // This is so we can do some guestimate of how big the string buffer needs
++ // to be to avoid doing a lot of allocations when concatenating the strings.
++ m_stringBufferSizeHint = visitor.stringSizeVisitor.size;
++ }
++ };
++
++ typedef QSSGShaderBaseMaterialKey<QSSGShaderParticleMaterialKeyProperties, 1> QSSGShaderParticleMaterialKey;
++
++ Q_STATIC_ASSERT(std::is_trivially_destructible<QSSGShaderParticleMaterialKey>::value);
++
++ inline size_t qHash(const QSSGShaderParticleMaterialKey &key)
++ {
++ return key.hash();
++ }
++
++ QT_END_NAMESPACE
++
++ #endif