Commit a7a76303 authored by Laszlo Agocs's avatar Laszlo Agocs
Browse files

Improve shadertools docs

parent 7408a0e6
......@@ -16,28 +16,23 @@ Experiments for more modern graphics shader management in future Qt (QtShaderToo
Uses https://github.com/KhronosGroup/SPIRV-Cross and https://github.com/KhronosGroup/glslang
1. qmake && (n)make
QShaderBaker: Compile (Vulkan-flavor) GLSL to SPIR-V. Generate reflection info.
Translate to HLSL, MSL, and various GLSL versions. Optionally rewrite vertex
shaders to make them suitable for Qt Quick scenegraph batching. Pack all this
into conveniently (de)serializable QBakedShader instances. Complemented by a
command-line tool (qsb) to allow doing the expensive work offline. This
optionally allows invoking fxc or metal/metallib to include compiled bytecode
for HLSL and MSL as well.
2. QT += shadertools
Documentation
=============
3. Use QSpirvCompiler to compile (Vulkan-flavored) GLSL to SPIR-V. This can also optionally rewrite the input source to make it suitable for the batched pass of Qt Quick's default OpenGL renderer.
4. Use QSpirvShader parse a SPIR-V binary to get reflection data, to strip the binary, and to translate to GLSL suitable for various OpenGL (ES) versions. (or to HLSL/MSL)
5. The reflection data (QShaderDescription) can also be serialized to binary and human-readable JSON, and deserialized from binary JSON.
Alternatively,
3. Run the qsb tool to generate a single file with reflection info and multiple variants (SPIR-V, HLSL, various GLSL versions) of the input shader source.
4. Use QBakedShader to load and access those at run time.
The latter is what the RHI uses, and expects applications to provide QBakedShader packs.
Generated docs are now online at https://alpqr.github.io
In action
=========
Needs Qt 5.12. Tested on Windows 10 with MSVC2015 and 2017, Ubuntu 16.04, and macOS 10.13.
Needs Qt 5.12. Tested on Windows 10 with MSVC2015 and 2017, and macOS 10.14 with XCode 10.
Screenshots from the test application demonstrating basic drawing, pipeline
state (blending, depth), indexed drawing, texturing, and rendering into a
......
......@@ -205,7 +205,9 @@ struct Q_RHI_EXPORT QRhiShaderResourceBinding
TessellationControlStage = 1 << 2,
TessellationEvaluationStage = 1 << 3
};
#ifndef Q_CLANG_QDOC
Q_DECLARE_FLAGS(StageFlags, StageFlag)
#endif
static QRhiShaderResourceBinding uniformBuffer(int binding_, StageFlags stage_, QRhiBuffer *buf_);
......@@ -394,7 +396,9 @@ public:
IndexBuffer = 1 << 1,
UniformBuffer = 1 << 2
};
#ifndef Q_CLANG_QDOC
Q_DECLARE_FLAGS(UsageFlags, UsageFlag)
#endif
Type type() const { return m_type; }
void setType(Type t) { m_type = t; }
......@@ -431,7 +435,9 @@ public:
UsedAsTransferSource = 1 << 5, // will (also) be used as the source of a copy or readback
UsedWithGenerateMips = 1 << 6
};
#ifndef Q_CLANG_QDOC
Q_DECLARE_FLAGS(Flags, Flag)
#endif
enum Format {
UnknownFormat,
......@@ -569,7 +575,9 @@ public:
enum Flag {
UsedWithSwapChainOnly = 1 << 0 // use implicit winsys buffers, don't create anything (GL)
};
#ifndef Q_CLANG_QDOC
Q_DECLARE_FLAGS(Flags, Flag)
#endif
Type type() const { return m_type; }
void setType(Type t) { m_type = t; }
......@@ -636,7 +644,9 @@ public:
PreserveColorContents = 1 << 0,
PreserveDepthStencilContents = 1 << 1
};
#ifndef Q_CLANG_QDOC
Q_DECLARE_FLAGS(Flags, Flag)
#endif
QRhiTextureRenderTargetDescription description() const { return m_desc; }
void setDescription(const QRhiTextureRenderTargetDescription &desc) { m_desc = desc; }
......@@ -682,7 +692,9 @@ public:
UsesStencilRef = 1 << 1,
UsesScissor = 1 << 2
};
#ifndef Q_CLANG_QDOC
Q_DECLARE_FLAGS(Flags, Flag)
#endif
enum Topology {
Triangles,
......@@ -709,7 +721,9 @@ public:
B = 1 << 2,
A = 1 << 3
};
#ifndef Q_CLANG_QDOC
Q_DECLARE_FLAGS(ColorMask, ColorMaskComponent)
#endif
enum BlendFactor {
Zero,
......@@ -874,7 +888,9 @@ public:
UsedAsTransferSource = 1 << 3, // will be read back
NoVSync = 1 << 4 // may be implementation specific what this results in
};
#ifndef Q_CLANG_QDOC
Q_DECLARE_FLAGS(Flags, Flag)
#endif
QWindow *window() const { return m_window; }
void setWindow(QWindow *window) { m_window = window; }
......@@ -1054,7 +1070,9 @@ public:
TextureRead = 1 << 0,
TextureWrite = 1 << 1
};
#ifndef Q_CLANG_QDOC
Q_DECLARE_FLAGS(TexturePrepareFlags, TexturePrepareFlag)
#endif
~QRhiResourceUpdateBatch();
// Puts the batch back to the pool without any processing.
......@@ -1120,7 +1138,9 @@ public:
EnableProfiling = 1 << 0,
EnableDebugMarkers = 1 << 1
};
#ifndef Q_CLANG_QDOC
Q_DECLARE_FLAGS(Flags, Flag)
#endif
enum FrameOpResult {
FrameOpSuccess = 0,
......
......@@ -29,6 +29,30 @@
\title Qt Shader Tools
\page qtshadertools-index.html
\section1 Introduction
The Qt Shader Tools module builds on the SPIR-V Open Source Ecosystem as
described at \l{https://www.khronos.org/spir/}{the Khronos SPIR-V web
site}. For compiling into SPIR-V
\l{https://github.com/KhronosGroup/glslang}{glslang} is used, while
translating and reflecting is done via
\l{https://github.com/KhronosGroup/SPIRV-Cross}{SPIRV-Cross}.
In order to allow shader code to be written once in Qt applications and
libraries, all shaders are expected to be written in a single language
which is then compiled into SPIR-V. Versions for various shading language
are then generated from that, together with reflection information (inputs,
outputs, shader resources). This is then packed into easily and efficiently
serializable QBakedShader instances. The Qt Rendering Hardware Interface
consumes QBakedShader instances directly.
The two main components are:
\list
\li QShaderBaker and the \c qsb command-line tool, and
\li QBakedShader
\endlist
\section1 Table of Contents
\list
......
......@@ -64,12 +64,6 @@ QT_BEGIN_NAMESPACE
restricted to cases where run time compilation cannot be avoided, such as
when working with user-provided shader source strings.
QShaderBaker builds on the SPIR-V Open Source Ecosystem as described at
\l{https://www.khronos.org/spir/}{the Khronos SPIR-V web site}. For
compiling into SPIR-V \l{https://github.com/KhronosGroup/glslang}{glslang}
is used, while translating and reflecting is done via
\l{https://github.com/KhronosGroup/SPIRV-Cross}{SPIRV-Cross}.
The input format is always assumed to be Vulkan-flavored GLSL at the
moment. See the
\l{https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_vulkan_glsl.txt}{GL_KHR_vulkan_glsl
......
......@@ -202,21 +202,34 @@ QT_BEGIN_NAMESPACE
/*!
\class QShaderDescription::InOutVariable
\inmodule QtShaderTools
\brief Describes an input or output variable in the shader.
*/
/*!
\class QShaderDescription::BlockVariable
\inmodule QtShaderTools
\brief Describes a member of a uniform or push constant block.
*/
/*!
\class QShaderDescription::UniformBlock
\inmodule QtShaderTools
\brief Describes a uniform block.
\note When translating to shading languages without uniform block support
(like GLSL 120 or GLSL/ES 100), uniform blocks are replaced with ordinary
uniforms in a struct. The name of the struct, and so the prefix for the
uniforms generated from the block members, is given by structName.
*/
/*!
\class QShaderDescription::PushConstantBlock
\inmodule QtShaderTools
\brief Describes a push constant block.
*/
/*!
......
......@@ -50,6 +50,7 @@ private slots:
void reuse();
void compileError();
void translateError();
void genVariants();
};
void tst_QShaderBaker::initTestCase()
......@@ -321,5 +322,42 @@ void tst_QShaderBaker::translateError()
qDebug() << baker.errorMessage();
}
void tst_QShaderBaker::genVariants()
{
QShaderBaker baker;
baker.setSourceFileName(QLatin1String(":/data/color.vert"));
baker.setGeneratedShaderVariants({
QBakedShaderKey::StandardShader,
QBakedShaderKey::BatchableVertexShader
});
QVector<QShaderBaker::GeneratedShader> targets;
targets.append({ QBakedShaderKey::SpirvShader, QBakedShaderVersion(100) });
targets.append({ QBakedShaderKey::GlslShader, QBakedShaderVersion(100, QBakedShaderVersion::GlslEs) });
targets.append({ QBakedShaderKey::GlslShader, QBakedShaderVersion(330) });
targets.append({ QBakedShaderKey::SpirvShader, QBakedShaderVersion(120) });
targets.append({ QBakedShaderKey::HlslShader, QBakedShaderVersion(50) });
targets.append({ QBakedShaderKey::MslShader, QBakedShaderVersion(12) });
baker.setGeneratedShaders(targets);
QBakedShader s = baker.bake();
QVERIFY(s.isValid());
QVERIFY(baker.errorMessage().isEmpty());
QCOMPARE(s.availableShaders().count(), 2 * 6);
int batchableVariantCount = 0;
int batchableGlslVariantCount = 0;
for (const QBakedShaderKey &key : s.availableShaders()) {
if (key.sourceVariant() == QBakedShaderKey::BatchableVertexShader) {
++batchableVariantCount;
if (key.source() == QBakedShaderKey::GlslShader) {
++batchableGlslVariantCount;
const QByteArray src = s.shader(key).shader();
QVERIFY(src.contains(QByteArrayLiteral("gl_Position.z * _qt.zRange")));
}
}
}
QCOMPARE(batchableVariantCount, 6);
QCOMPARE(batchableGlslVariantCount, 2);
}
#include <tst_qshaderbaker.moc>
QTEST_MAIN(tst_QShaderBaker)
......@@ -20,6 +20,7 @@ gl: ubuf structs, arrays
test cubemap face as target
test cubemap face readback
object names for other than buf/rb/tex
clang_qdoc ifdefs for q_declare_flags to be removed once qdoc does not choke on them
optional:
compute?
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment