Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qssgrendershaderlibrarymanager.cpp
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
5
6
8
9#include "../qssgrendercontextcore.h"
10#include <QtQuick3DRuntimeRender/private/qssgrenderloadedtexture_p.h>
11
12#include <QXmlStreamReader>
13#include <QFileInfo>
14#include <QCryptographicHash>
15
16#include <QtQuick3DRuntimeRender/private/qssgruntimerenderlogging_p.h>
17
19
20QString QSSGShaderLibraryManager::getShaderCodeLibraryDirectory()
21{
22 return QStringLiteral("res/effectlib");
23}
24static QByteArray includeSearch() { return QByteArrayLiteral("#include \""); };
25static QByteArray copyrightHeaderStart() { return QByteArrayLiteral("/****************************************************************************"); }
26static QByteArray copyrightHeaderEnd() { return QByteArrayLiteral("****************************************************************************/"); }
27
28QSSGShaderLibraryManager::QSSGShaderLibraryManager() {}
29
30QSSGShaderLibraryManager::~QSSGShaderLibraryManager() {}
31
32static inline char stageKey(QSSGShaderCache::ShaderType type)
33{
34 switch (type) {
35 case QSSGShaderCache::ShaderType::Vertex:
36 return 'V';
37 case QSSGShaderCache::ShaderType::Fragment:
38 return 'F';
39 default:
40 break;
41 }
42 return '?';
43}
44
45void QSSGShaderLibraryManager::setShaderSource(const QByteArray &inShaderPathKey, QSSGShaderCache::ShaderType type,
46 const QByteArray &inSource, const QSSGCustomShaderMetaData &meta)
47{
48 QWriteLocker locker(&m_lock);
49
50 const QByteArray perStageKey = stageKey(type) + inShaderPathKey;
51 {
52 auto it = m_expandedFiles.find(perStageKey);
53 if (it != m_expandedFiles.end())
54 it.value() = inSource;
55 else
56 m_expandedFiles.insert(perStageKey, inSource);
57 }
58
59 {
60 auto it = m_metadata.find(perStageKey);
61 if (it != m_metadata.end())
62 it.value() = meta;
63 else
64 m_metadata.insert(perStageKey, meta);
65 }
66}
67
68void QSSGShaderLibraryManager::resolveIncludeFiles(QByteArray &theReadBuffer, const QByteArray &inMaterialInfoString)
69{
70 // Now do search and replace for the headers
71 for (int thePos = theReadBuffer.indexOf(includeSearch()); thePos != -1;
72 thePos = theReadBuffer.indexOf(includeSearch(), thePos + 1)) {
73 int theEndQuote = theReadBuffer.indexOf('\"', thePos + includeSearch().size() + 1);
74 // Indicates an unterminated include file.
75 if (theEndQuote == -1) {
76 qCCritical(INVALID_OPERATION, "Unterminated include in file: %s", inMaterialInfoString.constData());
77 theReadBuffer.clear();
78 break;
79 }
80 const int theActualBegin = thePos + includeSearch().size();
81 const auto &theInclude = theReadBuffer.mid(theActualBegin, theEndQuote - theActualBegin);
82 // If we haven't included the file yet this round
83 auto contents = getIncludeContents(theInclude);
84 // Strip copywrite headers from include if present
85 if (contents.startsWith(copyrightHeaderStart())) {
86 int clipPos = contents.indexOf(copyrightHeaderEnd()) ;
87 if (clipPos >= 0)
88 contents.remove(0, clipPos + copyrightHeaderEnd().size());
89 }
90 // Write insert comment for begin source
91 contents.prepend(QByteArrayLiteral("\n// begin \"") + theInclude + QByteArrayLiteral("\"\n"));
92 // Write insert comment for end source
93 contents.append(QByteArrayLiteral("\n// end \"" ) + theInclude + QByteArrayLiteral("\"\n"));
94
95 theReadBuffer = theReadBuffer.replace(thePos, (theEndQuote + 1) - thePos, contents);
96 }
97}
98
99QByteArray QSSGShaderLibraryManager::getIncludeContents(const QByteArray &inShaderPathKey)
100{
101 QWriteLocker locker(&m_lock);
102
103 auto theInsert = m_expandedFiles.constFind(inShaderPathKey);
104 const bool found = (theInsert != m_expandedFiles.cend());
105
106 QByteArray theReadBuffer;
107 if (!found) {
108 const QString defaultDir = getShaderCodeLibraryDirectory();
109 const auto ver = QByteArrayLiteral("rhi");
110
111 QString fullPath;
112 QSharedPointer<QIODevice> theStream;
113 QTextStream stream(&fullPath);
114 stream << defaultDir << QLatin1Char('/') << ver << QLatin1Char('/') << QString::fromLocal8Bit(inShaderPathKey);
115 theStream = QSSGInputUtil::getStreamForFile(fullPath, true);
116 if (theStream.isNull()) {
117 fullPath.clear();
118 QTextStream stream(&fullPath);
119 stream << defaultDir << QLatin1Char('/') << QString::fromLocal8Bit(inShaderPathKey);
120 theStream = QSSGInputUtil::getStreamForFile(fullPath, false);
121 }
122 if (!theStream.isNull()) {
123 char readBuf[1024];
124 qint64 amountRead = 0;
125 do {
126 amountRead = theStream->read(readBuf, 1024);
127 if (amountRead)
128 theReadBuffer.append(readBuf, int(amountRead));
129 } while (amountRead);
130 } else {
131 qCCritical(INVALID_OPERATION, "Failed to find include file %s", qPrintable(QString::fromLocal8Bit(inShaderPathKey)));
132 Q_ASSERT(false);
133 }
134 theInsert = m_expandedFiles.insert(inShaderPathKey, theReadBuffer);
135 } else {
136 theReadBuffer = theInsert.value();
137 }
138
139 locker.unlock();
140 resolveIncludeFiles(theReadBuffer, inShaderPathKey);
141
142 return theReadBuffer;
143}
144
145QByteArray QSSGShaderLibraryManager::getShaderSource(const QByteArray &inShaderPathKey, QSSGShaderCache::ShaderType type)
146{
147 QReadLocker locker(&m_lock);
148
149 const QByteArray perStageKey = stageKey(type) + inShaderPathKey;
150 auto it = m_expandedFiles.constFind(perStageKey);
151 if (it != m_expandedFiles.cend())
152 return it.value();
153
154 qWarning("No shader source stored for key %s", perStageKey.constData());
155 return QByteArray();
156}
157
158QSSGCustomShaderMetaData QSSGShaderLibraryManager::getShaderMetaData(const QByteArray &inShaderPathKey, QSSGShaderCache::ShaderType type)
159{
160 QReadLocker locker(&m_lock);
161
162 const QByteArray perStageKey = stageKey(type) + inShaderPathKey;
163 auto it = m_metadata.constFind(perStageKey);
164 if (it != m_metadata.cend())
165 return it.value();
166
167 qWarning("No shader metadata stored for key %s", perStageKey.constData());
168 return {};
169}
170
171void QSSGShaderLibraryManager::loadPregeneratedShaderInfo()
172{
173 const auto collectionFilePath = QString::fromLatin1(QSSGShaderCache::resourceFolder() + QSSGShaderCache::shaderCollectionFile());
174 QFile file(collectionFilePath);
175 if (file.exists()) {
176 QQsbIODeviceCollection qsbc(file);
177 if (qsbc.map(QQsbIODeviceCollection::Read))
178 m_preGeneratedShaderEntries = qsbc.availableEntries();
179 qsbc.unmap();
180 }
181}
182
183QQsbCollection::EntryMap QSSGShaderLibraryManager::getParticleShaderEntries() const
184{
185 QQsbCollection::EntryMap map;
186 const auto collectionFilePath = QString::fromLatin1(QSSGShaderCache::resourceFolder() + QSSGShaderCache::particleShaderCollectionFile());
187 QFile file(collectionFilePath);
188 if (file.exists()) {
189 QQsbIODeviceCollection qsbc(file);
190 if (qsbc.map(QQsbIODeviceCollection::Read))
191 map = qsbc.availableEntries();
192 qsbc.unmap();
193 }
194 return map;
195}
196
197bool QSSGShaderLibraryManager::compare(const QSSGShaderDefaultMaterialKey &key1, const QSSGShaderDefaultMaterialKey &key2)
198{
199 QSSGShaderDefaultMaterialKeyProperties props;
200#define COMPARE_PROP(x)
201 if (props.x.getValue(key1) < props.x.getValue(key2)) return true;
202
203 COMPARE_PROP(m_hasLighting)
204 COMPARE_PROP(m_hasIbl)
205 COMPARE_PROP(m_fresnelEnabled)
206 COMPARE_PROP(m_fresnelScaleBiasEnabled)
207 COMPARE_PROP(m_clearcoatFresnelScaleBiasEnabled)
208 COMPARE_PROP(m_baseColorSingleChannelEnabled)
209 COMPARE_PROP(m_specularSingleChannelEnabled)
210 COMPARE_PROP(m_emissiveSingleChannelEnabled)
211 COMPARE_PROP(m_invertOpacityMapValue)
212 COMPARE_PROP(m_vertexColorsEnabled)
213 COMPARE_PROP(m_vertexColorsMaskEnabled)
214 COMPARE_PROP(m_vertexColorRedMask)
215 COMPARE_PROP(m_vertexColorGreenMask)
216 COMPARE_PROP(m_vertexColorBlueMask)
217 COMPARE_PROP(m_vertexColorAlphaMask)
218 COMPARE_PROP(m_vertexAttributes)
219 COMPARE_PROP(m_alphaMode)
220
221 for (int i = 0; i < QSSGShaderDefaultMaterialKeyProperties::ImageMapCount; i++) {
222 COMPARE_PROP(m_imageMaps[i])
223 }
224 for (int i = 0; i < QSSGShaderDefaultMaterialKeyProperties::SingleChannelImageCount; i++) {
225 COMPARE_PROP(m_textureChannels[i])
226 }
227#undef COMPARE_PROP
228 return false;
229}
230
231QT_END_NAMESPACE
Combined button and popup list for selecting options.
static QByteArray copyrightHeaderStart()
#define COMPARE_PROP(x)
static QByteArray includeSearch()
static QByteArray copyrightHeaderEnd()
static char stageKey(QSSGShaderCache::ShaderType type)