1// Copyright (C) 2008-2012 NVIDIA Corporation.
2// Copyright (C) 2019 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4
5#ifndef QSSG_RENDER_SHADER_CACHE_H
6#define QSSG_RENDER_SHADER_CACHE_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtQuick3DRuntimeRender/private/qtquick3druntimerenderglobal_p.h>
20#include <QtQuick3DUtils/private/qssgdataref_p.h>
21#include <QtQuick3DUtils/private/qqsbcollection_p.h>
22
23#include <QtQuick3DRuntimeRender/private/qssgrhicontext_p.h>
24#include <QtQuick3DRuntimeRender/private/qssgrendererimplshaders_p.h>
25
26#include <QtCore/QString>
27#include <QtCore/qcryptographichash.h>
28#include <QtCore/QSharedPointer>
29#include <QtCore/QVector>
30
31QT_BEGIN_NAMESPACE
32
33class QSSGRenderContextInterface;
34class QSSGRhiShaderPipeline;
35class QShaderBaker;
36class QRhi;
37
38struct Q_QUICK3DRUNTIMERENDER_EXPORT QSSGShaderFeatures
39{
40
41// There are a number of macros used to turn on or off various features.
42// This allows those features to be propagated into the shader cache's caching mechanism.
43// They will be translated into #define name value where value is 1 or zero depending on
44// if the feature is enabled or not.
45//
46// In snippets that use this feature the code would look something like this:
47
48/*
49#ifndef QSSG_ENABLE_<FEATURE>
50#define QSSG_ENABLE_<FEATURE> 0
51#endif
52
53void func()
54{
55 ...
56#if QSSG_ENABLE_<FEATURE>
57 ...
58#endif
59 ...
60}
61*/
62
63// NOTE: The order of these will affect generated keys, so re-ordering these
64// will break already baked shaders (e.g. shadergen).
65using FlagType = quint32;
66enum class Feature : FlagType
67{
68 LightProbe = (1 << 8),
69 IblOrientation = (1 << 9) + 1,
70 Ssm = (1 << 10) + 2,
71 Ssao = (1 << 11) + 3,
72 DepthPass = (1 << 12) + 4,
73 OrthoShadowPass = (1 << 13) + 5,
74 PerspectiveShadowPass = (1 << 14) + 6,
75 LinearTonemapping = (1 << 15) + 7,
76 AcesTonemapping = (1 << 16) + 8,
77 HejlDawsonTonemapping = (1 << 17) + 9,
78 FilmicTonemapping = (1 << 18) + 10,
79 RGBELightProbe = (1 << 19) + 11,
80 OpaqueDepthPrePass = (1 << 20) + 12,
81 ReflectionProbe = (1 << 21) + 13,
82 ReduceMaxNumLights = (1 << 22) + 14,
83 Lightmap = (1 << 23) + 15,
84 DisableMultiView = (1 << 24) + 16,
85 ForceIblExposure = (1 << 25) + 17,
86
87 LastFeature
88};
89
90static constexpr FlagType IndexMask = 0xff;
91static constexpr quint32 Count = (static_cast<FlagType>(Feature::LastFeature) & IndexMask);
92
93static const char *asDefineString(QSSGShaderFeatures::Feature feature);
94static Feature fromIndex(quint32 idx);
95
96constexpr bool isNull() const { return flags == 0; }
97constexpr bool isSet(Feature feature) const { return (static_cast<FlagType>(feature) & flags); }
98void set(Feature feature, bool val);
99
100FlagType flags = 0;
101
102inline friend bool operator==(QSSGShaderFeatures a, QSSGShaderFeatures b) { return a.flags == b.flags; }
103
104void disableTonemapping()
105{
106 set(feature: Feature::LinearTonemapping, val: false);
107 set(feature: Feature::AcesTonemapping, val: false);
108 set(feature: Feature::FilmicTonemapping, val: false);
109 set(feature: Feature::HejlDawsonTonemapping, val: false);
110 set(feature: Feature::ForceIblExposure, val: false);
111}
112
113inline friend QDebug operator<<(QDebug stream, const QSSGShaderFeatures &features)
114{
115 QVarLengthArray<const char *, Count> enabledFeatureStrings;
116 for (quint32 idx = 0; idx < Count; ++idx) {
117 const Feature feature = fromIndex(idx);
118 if (features.isSet(feature))
119 enabledFeatureStrings.append(t: asDefineString(feature));
120 }
121 stream.nospace() << "QSSGShaderFeatures(";
122 for (int i = 0; i < enabledFeatureStrings.size(); ++i)
123 stream.nospace() << (i > 0 ? ", " : "") << enabledFeatureStrings[i];
124 stream.nospace() << ")";
125 return stream;
126}
127
128};
129
130Q_QUICK3DRUNTIMERENDER_EXPORT size_t qHash(QSSGShaderFeatures features) noexcept;
131
132struct QSSGShaderCacheKey
133{
134 QByteArray m_key;
135 QSSGShaderFeatures m_features;
136 size_t m_hashCode = 0;
137
138 explicit QSSGShaderCacheKey(const QByteArray &key = QByteArray()) : m_key(key), m_hashCode(0) {}
139
140 QSSGShaderCacheKey(const QSSGShaderCacheKey &other) = default;
141 QSSGShaderCacheKey &operator=(const QSSGShaderCacheKey &other) = default;
142
143 static inline size_t generateHashCode(const QByteArray &key, QSSGShaderFeatures features)
144 {
145 return qHash(key) ^ qHash(features);
146 }
147
148 void updateHashCode()
149 {
150 m_hashCode = generateHashCode(key: m_key, features: m_features);
151 }
152
153 bool operator==(const QSSGShaderCacheKey &inOther) const
154 {
155 return m_key == inOther.m_key && m_features == inOther.m_features;
156 }
157};
158
159inline size_t qHash(const QSSGShaderCacheKey &key)
160{
161 return key.m_hashCode;
162}
163
164class Q_QUICK3DRUNTIMERENDER_EXPORT QSSGShaderCache
165{
166 Q_DISABLE_COPY(QSSGShaderCache)
167public:
168 enum class ShaderType
169 {
170 Vertex = 0,
171 Fragment = 1
172 };
173
174 using InitBakerFunc = void (*)(QShaderBaker *baker, QRhi *rhi);
175private:
176 friend class QSSGBuiltInRhiShaderCache;
177
178 typedef QHash<QSSGShaderCacheKey, QSSGRhiShaderPipelinePtr> TRhiShaderMap;
179 QSSGRhiContext &m_rhiContext; // Not own, the RCI owns us and the QSSGRhiContext.
180 TRhiShaderMap m_rhiShaders;
181 QByteArray m_insertStr; // member to potentially reuse the allocation after clear
182 QByteArray m_cacheKeyStr; // same here
183 InitBakerFunc m_initBaker;
184 QQsbInMemoryCollection m_persistentShaderBakingCache;
185 QString m_persistentShaderStorageFileName;
186 QSSGBuiltInRhiShaderCache m_builtInShaders;
187
188 QSSGRhiShaderPipelinePtr loadBuiltinUncached(const QByteArray &inKey, int viewCount);
189
190 void addShaderPreprocessor(QByteArray &str,
191 const QByteArray &inKey,
192 ShaderType shaderType,
193 const QSSGShaderFeatures &inFeatures,
194 int viewCount);
195
196public:
197 QSSGShaderCache(QSSGRhiContext &ctx,
198 const InitBakerFunc initBakeFn = nullptr);
199 ~QSSGShaderCache();
200
201 void releaseCachedResources();
202
203 QQsbInMemoryCollection &persistentShaderBakingCache() { return m_persistentShaderBakingCache; }
204
205 QSSGRhiShaderPipelinePtr tryGetRhiShaderPipeline(const QByteArray &inKey,
206 const QSSGShaderFeatures &inFeatures);
207
208 QSSGRhiShaderPipelinePtr tryNewPipelineFromPersistentCache(const QByteArray &qsbcKey,
209 const QByteArray &inKey,
210 const QSSGShaderFeatures &inFeatures,
211 QSSGRhiShaderPipeline::StageFlags stageFlags = {});
212
213 QSSGRhiShaderPipelinePtr newPipelineFromPregenerated(const QByteArray &inKey,
214 const QSSGShaderFeatures &inFeatures,
215 QQsbCollection::Entry entry,
216 const QSSGRenderGraphObject &obj,
217 QSSGRhiShaderPipeline::StageFlags stageFlags = {});
218
219 QSSGRhiShaderPipelinePtr compileForRhi(const QByteArray &inKey,
220 const QByteArray &inVert,
221 const QByteArray &inFrag,
222 const QSSGShaderFeatures &inFeatures,
223 QSSGRhiShaderPipeline::StageFlags stageFlags,
224 int viewCount,
225 bool perTargetCompilation);
226
227 QSSGBuiltInRhiShaderCache &getBuiltInRhiShaders() { return m_builtInShaders; }
228
229 static QByteArray resourceFolder();
230 static QByteArray shaderCollectionFile();
231};
232
233namespace QtQuick3DEditorHelpers {
234namespace ShaderBaker
235{
236 enum class Status : quint8
237 {
238 Success,
239 Error
240 };
241 using StatusCallback = void(*)(const QByteArray &descKey, Status status, const QString &err, QShader::Stage stage);
242 Q_QUICK3DRUNTIMERENDER_EXPORT void setStatusCallback(StatusCallback cb);
243}
244
245namespace ShaderCache
246{
247 // Used by DS and the QML puppet!
248 // Note: Needs to be called before any QSSGShaderCache instance is created.
249 Q_QUICK3DRUNTIMERENDER_EXPORT void setAutomaticDiskCache(bool enable);
250 Q_QUICK3DRUNTIMERENDER_EXPORT bool isAutomaticDiskCacheEnabled();
251}
252
253}
254
255QT_END_NAMESPACE
256
257#endif
258

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtquick3d/src/runtimerender/qssgrendershadercache_p.h