9#include <QtQuick3DUtils/private/qssgutils_p.h>
10#include <QtQuick3DUtils/private/qquick3dprofiler_p.h>
12#include <QtQuick3DRuntimeRender/private/qssgruntimerenderlogging_p.h>
13#include <qtquick3d_tracepoints_p.h>
15#include <QCoreApplication>
16#include <QStandardPaths>
21#include <QtGui/qsurfaceformat.h>
23# include <QtGui/qopenglcontext.h>
26#ifdef QT_QUICK3D_HAS_RUNTIME_SHADERS
27#include <rhi/qshaderbaker.h>
30#include <QtCore/qmutex.h>
58 const char *
name =
nullptr;
96#ifdef QT_QUICK3D_HAS_RUNTIME_SHADERS
99 QVector<QShaderBaker::GeneratedShader> outputs;
121 bool isGLESModule =
false;
126 if (
format.majorVersion() >= 3)
158 baker->setGeneratedShaders(outputs);
164 QVector<QShaderBaker::GeneratedShader> outputs;
188 baker->setBreakOnShaderTranslationError(
false);
190 baker->setGeneratedShaders(outputs);
224 static bool checked =
false;
225 static QString currentCacheDir;
226 static bool cacheWritable =
false;
229 return cacheWritable ? currentCacheDir :
QString();
235 if (!cachePath.isEmpty()) {
236 currentCacheDir = cachePath +
subPath;
240 return cacheWritable ? currentCacheDir :
QString();
246 if (!cacheDir.isEmpty())
255 m_initBaker(initBakeFn),
256 m_builtInShaders(*
this)
261 if (!m_persistentShaderStorageFileName.
isEmpty()) {
265 qDebug(
"Attempting to seed material shader cache from %s",
qPrintable(m_persistentShaderStorageFileName));
266 if (m_persistentShaderBakingCache.
load(m_persistentShaderStorageFileName)) {
269 qDebug(
"Loaded %d shader pipelines into the material shader cache",
count);
291 if (!m_persistentShaderStorageFileName.
isEmpty())
292 m_persistentShaderBakingCache.
save(m_persistentShaderStorageFileName);
299 m_rhiShaders.
clear();
312 if (theIter != m_rhiShaders.
cend())
313 return theIter.value();
320 ShaderType shaderType,
326 m_insertStr +=
"#version 440\n";
328 if (!inKey.isNull()) {
329 m_insertStr +=
"//Shader name -";
330 m_insertStr += inKey;
334 m_insertStr +=
"#define texture2D texture\n";
337 m_insertStr +=
"#define QSHADER_VIEW_COUNT ";
347 m_insertStr.
append(
"#define ");
348 m_insertStr.
append(def.name);
350 m_insertStr.
append(inFeatures.isSet(def.feature) ?
"1" :
"0");
355 insertPos += int(m_insertStr.
size());
358 if (fragOutputEnabled)
359 m_insertStr +=
"layout(location = 0) out vec4 fragOutput;\n";
377 bool perTargetCompilation)
379#ifdef QT_QUICK3D_HAS_RUNTIME_SHADERS
385 tempKey.m_features = inFeatures;
386 tempKey.updateHashCode();
391 if (!vertexCode.isEmpty())
394 if (!fragmentCode.isEmpty())
403 m_initBaker(&baker, m_rhiContext.
rhi());
408 baker.setPerTargetCompilation(perTargetCompilation);
412 baker.setMultiViewCount(viewCount);
421 qDebug(
"VERTEX SHADER:\n*****\n");
424 qDebug(
"FRAGMENT SHADER:\n*****\n");
427 qDebug(
"SHADER:\n*****\n");
430 const auto lines = code.
split(
'\n');
431 for (
int i = 0;
i < lines.size();
i++)
432 qDebug(
"%3d %s",
i + 1, lines.at(
i).constData());
444 QShader vertexShader = baker.bake();
445 const auto vertShaderValid = vertexShader.
isValid();
446 if (!vertShaderValid) {
447 vertErr = baker.errorMessage();
457 if (!vertShaderValid)
462 QShader fragmentShader = baker.bake();
463 const bool fragShaderValid = fragmentShader.
isValid();
464 if (!fragShaderValid) {
465 fragErr = baker.errorMessage();
475 if (!fragShaderValid)
479 if (vertShaderValid && fragShaderValid) {
480 shaders = std::make_shared<QSSGRhiShaderPipeline>(m_rhiContext);
484 qDebug(
"Compilation for vertex and fragment stages succeeded");
489 const auto vertStatus = vertShaderValid ? Status::Success : Status::Error;
490 const auto fragStatus = fragShaderValid ? Status::Success : Status::Error;
501 result->vertexStage()->shader(),
502 result->fragmentStage()->shader()
504 m_persistentShaderBakingCache.
addEntry(entryDesc.generateSha(), entryDesc);
514 qWarning(
"Cannot compile and condition shaders at runtime because this build of Qt Quick 3D is not linking to Qt Shader Tools. "
515 "Only pre-processed materials are supported.");
524 QSSGRhiShaderPipeline::StageFlags stageFlags)
535 qDebug(
"Loading pregenerated rhi shader(s)");
548 qsbc.extractEntry(
entry, entryDesc);
552 if (entryDesc.vertShader.isValid() && entryDesc.fragShader.isValid()) {
556 qDebug(
"Loading of vertex and fragment stages succeeded");
559#if !QT_CONFIG(qml_debug)
571 return inserted.value();
577 QSSGRhiShaderPipeline::StageFlags stageFlags)
593 if (entryDesc.vertShader.isValid() && entryDesc.fragShader.isValid()) {
596 qDebug(
"Loading rhi shaders from disk cache for %s (%s)", qsbcKey.constData(), inKey.constData());
614 qDebug(
"Loading builtin rhi shader: %s (view count: %d)", inKey.constData(), viewCount);
631 if (viewCount == 2) {
648 f.setFileName(fragmentFileName);
661 qDebug(
"Loading of vertex and fragment stages succeeded");
683 return ::isAutoDiskCacheEnabled();
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
void clear()
Clears the contents of the byte array and makes it null.
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QDir root()
Returns the root directory.
bool isWritable() const
Returns true if the user can write to the file system entry this QFileInfo refers to; otherwise retur...
bool exists() const
Returns true if the file system entry this QFileInfo refers to exists; otherwise returns false.
void setFileName(const QString &name)
Sets the name of the file.
const_iterator constFind(const Key &key) const noexcept
const_iterator cend() 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.
static OpenGLModuleType openGLModuleType()
Returns the underlying OpenGL implementation type.
static FeatureSet toFeatureSet(const T &ssgFeatureSet)
Entry addEntry(const QByteArray &key, const EntryDesc &entryDesc) override
bool load(const QString &filename)
bool save(const QString &filename)
EntryMap availableEntries() const override
bool extractEntry(Entry entry, EntryDesc &entryDesc) override
\variable QRhiGles2InitParams::format
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Implementation backend() const
const QRhiNativeHandles * nativeHandles()
void releaseCachedResources()
static bool shaderDebuggingEnabled()
QSSGRhiShaderPipelinePtr tryGetRhiShaderPipeline(const QByteArray &inKey, const QSSGShaderFeatures &inFeatures)
QSSGShaderCache(QSSGRhiContext &ctx, const InitBakerFunc initBakeFn=nullptr)
static QByteArray shaderCollectionFile()
static QByteArray resourceFolder()
QSSGRhiShaderPipelinePtr newPipelineFromPregenerated(const QByteArray &inKey, const QSSGShaderFeatures &inFeatures, QQsbCollection::Entry entry, const QSSGRenderGraphObject &obj, QSSGRhiShaderPipeline::StageFlags stageFlags={})
void releaseCachedResources()
QSSGRhiShaderPipelinePtr compileForRhi(const QByteArray &inKey, const QByteArray &inVert, const QByteArray &inFrag, const QSSGShaderFeatures &inFeatures, QSSGRhiShaderPipeline::StageFlags stageFlags, int viewCount, bool perTargetCompilation)
QSSGRhiShaderPipelinePtr tryNewPipelineFromPersistentCache(const QByteArray &qsbcKey, const QByteArray &inKey, const QSSGShaderFeatures &inFeatures, QSSGRhiShaderPipeline::StageFlags stageFlags={})
void(*)(QShaderBaker *baker, QRhi *rhi) InitBakerFunc
static QShader fromSerialized(const QByteArray &data)
Creates a new QShader instance from the given data.
Stage
Describes the stage of the graphics pipeline the shader is suitable for.
static QString writableLocation(StandardLocation type)
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString & insert(qsizetype i, QChar c)
static QString buildAbi()
Combined button and popup list for selecting options.
Q_QUICK3DRUNTIMERENDER_EXPORT void setStatusCallback(StatusCallback cb)
void(*)(const QByteArray &descKey, Status status, const QString &err, QShader::Stage stage) StatusCallback
Q_QUICK3DRUNTIMERENDER_EXPORT void setAutomaticDiskCache(bool enable)
Q_QUICK3DRUNTIMERENDER_EXPORT bool isAutomaticDiskCacheEnabled()
@ AA_DisableShaderDiskCache
#define QByteArrayLiteral(str)
static const QPainterPath::ElementType * subPath(const QPainterPath::ElementType *t, const QPainterPath::ElementType *end, const qreal *points, bool *closed)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
static QByteArray cacheKey(Args &&...args)
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei GLsizei GLenum format
GLfloat GLfloat GLfloat GLfloat h
GLsizei GLsizei GLuint * shaders
QT_BEGIN_NAMESPACE constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
#define Q_QUICK3D_PROFILE_START(Type)
#define Q_QUICK3D_PROFILE_END_WITH_ID(Type, Payload, POID)
#define Q_QUICK3D_PROFILE_END_WITH_STRING(Type, Payload, Str)
static QString persistentQsbcFileName()
static bool isAutoDiskCacheEnabled()
size_t qHash(QSSGShaderFeatures features) noexcept
static bool ensureWritableDir(const QString &name)
static constexpr DefineEntry DefineTable[]
static bool s_autoDiskCacheEnabled
static QString dumpFilename(QShader::Stage stage)
static void initBakerForPersistentUse(QShaderBaker *, QRhi *)
static QT_BEGIN_NAMESPACE QtQuick3DEditorHelpers::ShaderBaker::StatusCallback s_statusCallback
static QString persistentQsbcDir()
static void initBakerForNonPersistentUse(QShaderBaker *, QRhi *)
std::shared_ptr< QSSGRhiShaderPipeline > QSSGRhiShaderPipelinePtr
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define qPrintable(string)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define Q_TRACE_SCOPE(x,...)
#define Q_TRACE_POINT(provider, tracepoint,...)
QSSGShaderFeatures::Feature feature
\inmodule QtCore \reentrant
static constexpr FlagType IndexMask
void set(Feature feature, bool val)
static constexpr quint32 Count
static const char * asDefineString(QSSGShaderFeatures::Feature feature)
static Feature fromIndex(quint32 idx)