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