2019-03-22 08:55:03 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** Copyright (C) 2019 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
|
|
|
**
|
|
|
|
** This file is part of the test suite of the Qt Toolkit.
|
|
|
|
**
|
|
|
|
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
|
|
**
|
|
|
|
** GNU General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
|
|
**
|
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <QtTest/QtTest>
|
|
|
|
#include <QFile>
|
|
|
|
#include <QtGui/private/qshaderdescription_p_p.h>
|
|
|
|
#include <QtGui/private/qshader_p_p.h>
|
|
|
|
|
|
|
|
class tst_QShader : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void simpleCompileCheckResults();
|
|
|
|
void genVariants();
|
|
|
|
void shaderDescImplicitSharing();
|
|
|
|
void bakedShaderImplicitSharing();
|
2019-10-28 15:37:57 +00:00
|
|
|
void mslResourceMapping();
|
|
|
|
void loadV3();
|
|
|
|
void serializeShaderDesc();
|
2020-01-12 16:33:31 +00:00
|
|
|
void comparison();
|
|
|
|
void loadV4();
|
2019-03-22 08:55:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static QShader getShader(const QString &name)
|
|
|
|
{
|
|
|
|
QFile f(name);
|
|
|
|
if (f.open(QIODevice::ReadOnly))
|
|
|
|
return QShader::fromSerialized(f.readAll());
|
|
|
|
|
|
|
|
return QShader();
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QShader::simpleCompileCheckResults()
|
|
|
|
{
|
2019-10-28 15:37:57 +00:00
|
|
|
QShader s = getShader(QLatin1String(":/data/color_spirv_v1.vert.qsb"));
|
2019-03-22 08:55:03 +00:00
|
|
|
QVERIFY(s.isValid());
|
2019-10-28 15:37:57 +00:00
|
|
|
QCOMPARE(QShaderPrivate::get(&s)->qsbVersion, 1);
|
2019-03-22 08:55:03 +00:00
|
|
|
QCOMPARE(s.availableShaders().count(), 1);
|
|
|
|
|
|
|
|
const QShaderCode shader = s.shader(QShaderKey(QShader::SpirvShader,
|
|
|
|
QShaderVersion(100)));
|
|
|
|
QVERIFY(!shader.shader().isEmpty());
|
|
|
|
QCOMPARE(shader.entryPoint(), QByteArrayLiteral("main"));
|
|
|
|
|
|
|
|
const QShaderDescription desc = s.description();
|
|
|
|
QVERIFY(desc.isValid());
|
|
|
|
QCOMPARE(desc.inputVariables().count(), 2);
|
|
|
|
for (const QShaderDescription::InOutVariable &v : desc.inputVariables()) {
|
|
|
|
switch (v.location) {
|
|
|
|
case 0:
|
|
|
|
QCOMPARE(v.name, QLatin1String("position"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Vec4);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
QCOMPARE(v.name, QLatin1String("color"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Vec3);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
QVERIFY(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QCOMPARE(desc.outputVariables().count(), 1);
|
|
|
|
for (const QShaderDescription::InOutVariable &v : desc.outputVariables()) {
|
|
|
|
switch (v.location) {
|
|
|
|
case 0:
|
|
|
|
QCOMPARE(v.name, QLatin1String("v_color"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Vec3);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
QVERIFY(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QCOMPARE(desc.uniformBlocks().count(), 1);
|
|
|
|
const QShaderDescription::UniformBlock blk = desc.uniformBlocks().first();
|
|
|
|
QCOMPARE(blk.blockName, QLatin1String("buf"));
|
|
|
|
QCOMPARE(blk.structName, QLatin1String("ubuf"));
|
|
|
|
QCOMPARE(blk.size, 68);
|
|
|
|
QCOMPARE(blk.binding, 0);
|
|
|
|
QCOMPARE(blk.descriptorSet, 0);
|
|
|
|
QCOMPARE(blk.members.count(), 2);
|
|
|
|
for (int i = 0; i < blk.members.count(); ++i) {
|
|
|
|
const QShaderDescription::BlockVariable v = blk.members[i];
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
QCOMPARE(v.offset, 0);
|
|
|
|
QCOMPARE(v.size, 64);
|
|
|
|
QCOMPARE(v.name, QLatin1String("mvp"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Mat4);
|
|
|
|
QCOMPARE(v.matrixStride, 16);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
QCOMPARE(v.offset, 64);
|
|
|
|
QCOMPARE(v.size, 4);
|
|
|
|
QCOMPARE(v.name, QLatin1String("opacity"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Float);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
QVERIFY(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QShader::genVariants()
|
|
|
|
{
|
2019-10-28 15:37:57 +00:00
|
|
|
QShader s = getShader(QLatin1String(":/data/color_all_v1.vert.qsb"));
|
2019-03-22 08:55:03 +00:00
|
|
|
// spirv, glsl 100, glsl 330, glsl 120, hlsl 50, msl 12
|
|
|
|
// + batchable variants
|
|
|
|
QVERIFY(s.isValid());
|
2019-10-28 15:37:57 +00:00
|
|
|
QCOMPARE(QShaderPrivate::get(&s)->qsbVersion, 1);
|
2019-03-22 08:55:03 +00:00
|
|
|
QCOMPARE(s.availableShaders().count(), 2 * 6);
|
|
|
|
|
|
|
|
int batchableVariantCount = 0;
|
|
|
|
int batchableGlslVariantCount = 0;
|
|
|
|
for (const QShaderKey &key : s.availableShaders()) {
|
|
|
|
if (key.sourceVariant() == QShader::BatchableVertexShader) {
|
|
|
|
++batchableVariantCount;
|
|
|
|
if (key.source() == QShader::GlslShader) {
|
|
|
|
++batchableGlslVariantCount;
|
|
|
|
const QByteArray src = s.shader(key).shader();
|
|
|
|
QVERIFY(src.contains(QByteArrayLiteral("_qt_order * ")));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QCOMPARE(batchableVariantCount, 6);
|
|
|
|
QCOMPARE(batchableGlslVariantCount, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QShader::shaderDescImplicitSharing()
|
|
|
|
{
|
2019-10-28 15:37:57 +00:00
|
|
|
QShader s = getShader(QLatin1String(":/data/color_spirv_v1.vert.qsb"));
|
2019-03-22 08:55:03 +00:00
|
|
|
QVERIFY(s.isValid());
|
2019-10-28 15:37:57 +00:00
|
|
|
QCOMPARE(QShaderPrivate::get(&s)->qsbVersion, 1);
|
2019-03-22 08:55:03 +00:00
|
|
|
QCOMPARE(s.availableShaders().count(), 1);
|
|
|
|
QVERIFY(s.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
|
|
|
|
|
|
|
|
QShaderDescription d0 = s.description();
|
|
|
|
QVERIFY(d0.isValid());
|
|
|
|
QCOMPARE(d0.inputVariables().count(), 2);
|
|
|
|
QCOMPARE(d0.outputVariables().count(), 1);
|
|
|
|
QCOMPARE(d0.uniformBlocks().count(), 1);
|
|
|
|
|
|
|
|
QShaderDescription d1 = d0;
|
|
|
|
QVERIFY(QShaderDescriptionPrivate::get(&d0) == QShaderDescriptionPrivate::get(&d1));
|
|
|
|
QCOMPARE(d0.inputVariables().count(), 2);
|
|
|
|
QCOMPARE(d0.outputVariables().count(), 1);
|
|
|
|
QCOMPARE(d0.uniformBlocks().count(), 1);
|
|
|
|
QCOMPARE(d1.inputVariables().count(), 2);
|
|
|
|
QCOMPARE(d1.outputVariables().count(), 1);
|
|
|
|
QCOMPARE(d1.uniformBlocks().count(), 1);
|
2019-10-28 15:37:57 +00:00
|
|
|
QCOMPARE(d0, d1);
|
2019-03-22 08:55:03 +00:00
|
|
|
|
|
|
|
d1.detach();
|
|
|
|
QVERIFY(QShaderDescriptionPrivate::get(&d0) != QShaderDescriptionPrivate::get(&d1));
|
|
|
|
QCOMPARE(d0.inputVariables().count(), 2);
|
|
|
|
QCOMPARE(d0.outputVariables().count(), 1);
|
|
|
|
QCOMPARE(d0.uniformBlocks().count(), 1);
|
|
|
|
QCOMPARE(d1.inputVariables().count(), 2);
|
|
|
|
QCOMPARE(d1.outputVariables().count(), 1);
|
|
|
|
QCOMPARE(d1.uniformBlocks().count(), 1);
|
2019-10-28 15:37:57 +00:00
|
|
|
QCOMPARE(d0, d1);
|
|
|
|
|
|
|
|
d1 = QShaderDescription();
|
|
|
|
QVERIFY(d0 != d1);
|
2019-03-22 08:55:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QShader::bakedShaderImplicitSharing()
|
|
|
|
{
|
2019-10-28 15:37:57 +00:00
|
|
|
QShader s0 = getShader(QLatin1String(":/data/color_spirv_v1.vert.qsb"));
|
2019-03-22 08:55:03 +00:00
|
|
|
QVERIFY(s0.isValid());
|
2019-10-28 15:37:57 +00:00
|
|
|
QCOMPARE(QShaderPrivate::get(&s0)->qsbVersion, 1);
|
2019-03-22 08:55:03 +00:00
|
|
|
QCOMPARE(s0.availableShaders().count(), 1);
|
|
|
|
QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
|
|
|
|
|
|
|
|
{
|
|
|
|
QShader s1 = s0;
|
|
|
|
QVERIFY(QShaderPrivate::get(&s0) == QShaderPrivate::get(&s1));
|
|
|
|
QCOMPARE(s0.availableShaders().count(), 1);
|
|
|
|
QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
|
|
|
|
QCOMPARE(s1.availableShaders().count(), 1);
|
|
|
|
QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
|
|
|
|
QCOMPARE(s0.stage(), s1.stage());
|
|
|
|
QCOMPARE(s0, s1);
|
|
|
|
|
|
|
|
s1.detach();
|
|
|
|
QVERIFY(QShaderPrivate::get(&s0) != QShaderPrivate::get(&s1));
|
|
|
|
QCOMPARE(s0.availableShaders().count(), 1);
|
|
|
|
QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
|
|
|
|
QCOMPARE(s1.availableShaders().count(), 1);
|
|
|
|
QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
|
|
|
|
QCOMPARE(s0.stage(), s1.stage());
|
|
|
|
QCOMPARE(s0, s1);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
QShader s1 = s0;
|
|
|
|
QVERIFY(QShaderPrivate::get(&s0) == QShaderPrivate::get(&s1));
|
|
|
|
QCOMPARE(s0.stage(), s1.stage());
|
|
|
|
|
|
|
|
s1.setStage(QShader::FragmentStage); // call a setter to trigger a detach
|
|
|
|
QVERIFY(QShaderPrivate::get(&s0) != QShaderPrivate::get(&s1));
|
|
|
|
QCOMPARE(s0.availableShaders().count(), 1);
|
|
|
|
QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
|
|
|
|
QCOMPARE(s1.availableShaders().count(), 1);
|
|
|
|
QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
|
|
|
|
QShaderDescription d0 = s0.description();
|
|
|
|
QCOMPARE(d0.inputVariables().count(), 2);
|
|
|
|
QCOMPARE(d0.outputVariables().count(), 1);
|
|
|
|
QCOMPARE(d0.uniformBlocks().count(), 1);
|
|
|
|
QShaderDescription d1 = s1.description();
|
|
|
|
QCOMPARE(d1.inputVariables().count(), 2);
|
|
|
|
QCOMPARE(d1.outputVariables().count(), 1);
|
|
|
|
QCOMPARE(d1.uniformBlocks().count(), 1);
|
|
|
|
QVERIFY(s0 != s1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-28 15:37:57 +00:00
|
|
|
void tst_QShader::mslResourceMapping()
|
|
|
|
{
|
|
|
|
QShader s = getShader(QLatin1String(":/data/texture_all_v2.frag.qsb"));
|
|
|
|
QVERIFY(s.isValid());
|
|
|
|
QCOMPARE(QShaderPrivate::get(&s)->qsbVersion, 2);
|
|
|
|
|
|
|
|
const QVector<QShaderKey> availableShaders = s.availableShaders();
|
|
|
|
QCOMPARE(availableShaders.count(), 7);
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::MslShader, QShaderVersion(12))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::HlslShader, QShaderVersion(50))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(100, QShaderVersion::GlslEs))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(120))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(150))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(330))));
|
|
|
|
|
|
|
|
const QShader::NativeResourceBindingMap *resMap =
|
|
|
|
s.nativeResourceBindingMap(QShaderKey(QShader::GlslShader, QShaderVersion(330)));
|
|
|
|
QVERIFY(!resMap);
|
|
|
|
|
|
|
|
// The Metal shader must come with a mapping table for binding points 0
|
|
|
|
// (uniform buffer) and 1 (combined image sampler mapped to a texture and
|
|
|
|
// sampler in the shader).
|
|
|
|
resMap = s.nativeResourceBindingMap(QShaderKey(QShader::MslShader, QShaderVersion(12)));
|
|
|
|
QVERIFY(resMap);
|
|
|
|
|
|
|
|
QCOMPARE(resMap->count(), 2);
|
|
|
|
QCOMPARE(resMap->value(0).first, 0); // mapped to native buffer index 0
|
|
|
|
QCOMPARE(resMap->value(1), qMakePair(0, 0)); // mapped to native texture index 0 and sampler index 0
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QShader::loadV3()
|
|
|
|
{
|
|
|
|
// qsb version 3: QShaderDescription is serialized as CBOR. Ensure the deserialized data is as expected.
|
|
|
|
QShader s = getShader(QLatin1String(":/data/texture_all_v3.frag.qsb"));
|
|
|
|
QVERIFY(s.isValid());
|
|
|
|
QCOMPARE(QShaderPrivate::get(&s)->qsbVersion, 3);
|
|
|
|
|
|
|
|
const QVector<QShaderKey> availableShaders = s.availableShaders();
|
|
|
|
QCOMPARE(availableShaders.count(), 7);
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::MslShader, QShaderVersion(12))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::HlslShader, QShaderVersion(50))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(100, QShaderVersion::GlslEs))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(120))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(150))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(330))));
|
|
|
|
|
|
|
|
const QShaderDescription desc = s.description();
|
|
|
|
QVERIFY(desc.isValid());
|
|
|
|
QCOMPARE(desc.inputVariables().count(), 1);
|
|
|
|
for (const QShaderDescription::InOutVariable &v : desc.inputVariables()) {
|
|
|
|
switch (v.location) {
|
|
|
|
case 0:
|
|
|
|
QCOMPARE(v.name, QLatin1String("qt_TexCoord"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Vec2);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
QVERIFY(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QCOMPARE(desc.outputVariables().count(), 1);
|
|
|
|
for (const QShaderDescription::InOutVariable &v : desc.outputVariables()) {
|
|
|
|
switch (v.location) {
|
|
|
|
case 0:
|
|
|
|
QCOMPARE(v.name, QLatin1String("fragColor"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Vec4);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
QVERIFY(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QCOMPARE(desc.uniformBlocks().count(), 1);
|
|
|
|
const QShaderDescription::UniformBlock blk = desc.uniformBlocks().first();
|
|
|
|
QCOMPARE(blk.blockName, QLatin1String("buf"));
|
|
|
|
QCOMPARE(blk.structName, QLatin1String("ubuf"));
|
|
|
|
QCOMPARE(blk.size, 68);
|
|
|
|
QCOMPARE(blk.binding, 0);
|
|
|
|
QCOMPARE(blk.descriptorSet, 0);
|
|
|
|
QCOMPARE(blk.members.count(), 2);
|
|
|
|
for (int i = 0; i < blk.members.count(); ++i) {
|
|
|
|
const QShaderDescription::BlockVariable v = blk.members[i];
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
QCOMPARE(v.offset, 0);
|
|
|
|
QCOMPARE(v.size, 64);
|
|
|
|
QCOMPARE(v.name, QLatin1String("qt_Matrix"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Mat4);
|
|
|
|
QCOMPARE(v.matrixStride, 16);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
QCOMPARE(v.offset, 64);
|
|
|
|
QCOMPARE(v.size, 4);
|
|
|
|
QCOMPARE(v.name, QLatin1String("opacity"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Float);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
QVERIFY(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QShader::serializeShaderDesc()
|
|
|
|
{
|
|
|
|
// default constructed QShaderDescription
|
|
|
|
{
|
|
|
|
QShaderDescription desc;
|
|
|
|
QVERIFY(!desc.isValid());
|
|
|
|
|
2020-01-12 16:33:31 +00:00
|
|
|
QByteArray data;
|
|
|
|
{
|
|
|
|
QBuffer buf(&data);
|
|
|
|
QDataStream ds(&buf);
|
|
|
|
QVERIFY(buf.open(QIODevice::WriteOnly));
|
|
|
|
desc.serialize(&ds);
|
|
|
|
}
|
2019-10-28 15:37:57 +00:00
|
|
|
QVERIFY(!data.isEmpty());
|
|
|
|
|
2020-01-12 16:33:31 +00:00
|
|
|
{
|
|
|
|
QBuffer buf(&data);
|
|
|
|
QDataStream ds(&buf);
|
|
|
|
QVERIFY(buf.open(QIODevice::ReadOnly));
|
2020-03-03 10:19:14 +00:00
|
|
|
QShaderDescription desc2 = QShaderDescription::deserialize(&ds, QShaderPrivate::QSB_VERSION);
|
2020-01-12 16:33:31 +00:00
|
|
|
QVERIFY(!desc2.isValid());
|
|
|
|
}
|
2019-10-28 15:37:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// a QShaderDescription with inputs, outputs, uniform block and combined image sampler
|
|
|
|
{
|
2020-01-12 16:33:31 +00:00
|
|
|
QShader s = getShader(QLatin1String(":/data/texture_all_v4.frag.qsb"));
|
2019-10-28 15:37:57 +00:00
|
|
|
QVERIFY(s.isValid());
|
|
|
|
const QShaderDescription desc = s.description();
|
|
|
|
QVERIFY(desc.isValid());
|
|
|
|
|
2020-01-12 16:33:31 +00:00
|
|
|
QByteArray data;
|
|
|
|
{
|
|
|
|
QBuffer buf(&data);
|
|
|
|
QDataStream ds(&buf);
|
|
|
|
QVERIFY(buf.open(QIODevice::WriteOnly));
|
|
|
|
desc.serialize(&ds);
|
|
|
|
}
|
2019-10-28 15:37:57 +00:00
|
|
|
QVERIFY(!data.isEmpty());
|
|
|
|
|
2020-01-13 15:45:28 +00:00
|
|
|
{
|
|
|
|
QShaderDescription desc2;
|
|
|
|
QVERIFY(!desc2.isValid());
|
|
|
|
QVERIFY(!(desc == desc2));
|
|
|
|
QVERIFY(desc != desc2);
|
|
|
|
}
|
2019-10-28 15:37:57 +00:00
|
|
|
|
2020-01-12 16:33:31 +00:00
|
|
|
{
|
|
|
|
QBuffer buf(&data);
|
|
|
|
QDataStream ds(&buf);
|
|
|
|
QVERIFY(buf.open(QIODevice::ReadOnly));
|
2020-03-03 10:19:14 +00:00
|
|
|
QShaderDescription desc2 = QShaderDescription::deserialize(&ds, QShaderPrivate::QSB_VERSION);
|
2020-01-12 16:33:31 +00:00
|
|
|
QVERIFY(desc2.isValid());
|
|
|
|
QCOMPARE(desc, desc2);
|
|
|
|
}
|
2019-10-28 15:37:57 +00:00
|
|
|
}
|
2020-01-12 16:33:31 +00:00
|
|
|
}
|
2019-10-28 15:37:57 +00:00
|
|
|
|
2020-01-12 16:33:31 +00:00
|
|
|
void tst_QShader::comparison()
|
|
|
|
{
|
2019-10-28 15:37:57 +00:00
|
|
|
// exercise QShader and QShaderDescription comparisons
|
|
|
|
{
|
2020-01-12 16:33:31 +00:00
|
|
|
QShader s1 = getShader(QLatin1String(":/data/texture_all_v4.frag.qsb"));
|
2019-10-28 15:37:57 +00:00
|
|
|
QVERIFY(s1.isValid());
|
|
|
|
QShader s2 = getShader(QLatin1String(":/data/color_all_v1.vert.qsb"));
|
|
|
|
QVERIFY(s2.isValid());
|
|
|
|
|
|
|
|
QVERIFY(s1.description().isValid());
|
|
|
|
QVERIFY(s2.description().isValid());
|
|
|
|
|
|
|
|
QVERIFY(s1 != s2);
|
|
|
|
QVERIFY(s1.description() != s2.description());
|
|
|
|
}
|
2020-01-12 16:33:31 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
QShader s1 = getShader(QLatin1String(":/data/texture_all_v4.frag.qsb"));
|
|
|
|
QVERIFY(s1.isValid());
|
|
|
|
QShader s2 = getShader(QLatin1String(":/data/texture_all_v4.frag.qsb"));
|
|
|
|
QVERIFY(s2.isValid());
|
|
|
|
|
|
|
|
QVERIFY(s1.description().isValid());
|
|
|
|
QVERIFY(s2.description().isValid());
|
|
|
|
|
|
|
|
QVERIFY(s1 == s2);
|
|
|
|
QVERIFY(s1.description() == s2.description());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QShader::loadV4()
|
|
|
|
{
|
|
|
|
// qsb version 4: QShaderDescription is serialized via QDataStream. Ensure the deserialized data is as expected.
|
|
|
|
QShader s = getShader(QLatin1String(":/data/texture_all_v4.frag.qsb"));
|
|
|
|
QVERIFY(s.isValid());
|
|
|
|
QCOMPARE(QShaderPrivate::get(&s)->qsbVersion, 4);
|
|
|
|
|
|
|
|
const QVector<QShaderKey> availableShaders = s.availableShaders();
|
|
|
|
QCOMPARE(availableShaders.count(), 7);
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::MslShader, QShaderVersion(12))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::HlslShader, QShaderVersion(50))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(100, QShaderVersion::GlslEs))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(120))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(150))));
|
|
|
|
QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(330))));
|
|
|
|
|
|
|
|
const QShaderDescription desc = s.description();
|
|
|
|
QVERIFY(desc.isValid());
|
|
|
|
QCOMPARE(desc.inputVariables().count(), 1);
|
|
|
|
for (const QShaderDescription::InOutVariable &v : desc.inputVariables()) {
|
|
|
|
switch (v.location) {
|
|
|
|
case 0:
|
|
|
|
QCOMPARE(v.name, QLatin1String("qt_TexCoord"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Vec2);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
QVERIFY(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QCOMPARE(desc.outputVariables().count(), 1);
|
|
|
|
for (const QShaderDescription::InOutVariable &v : desc.outputVariables()) {
|
|
|
|
switch (v.location) {
|
|
|
|
case 0:
|
|
|
|
QCOMPARE(v.name, QLatin1String("fragColor"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Vec4);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
QVERIFY(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QCOMPARE(desc.uniformBlocks().count(), 1);
|
|
|
|
const QShaderDescription::UniformBlock blk = desc.uniformBlocks().first();
|
|
|
|
QCOMPARE(blk.blockName, QLatin1String("buf"));
|
|
|
|
QCOMPARE(blk.structName, QLatin1String("ubuf"));
|
|
|
|
QCOMPARE(blk.size, 68);
|
|
|
|
QCOMPARE(blk.binding, 0);
|
|
|
|
QCOMPARE(blk.descriptorSet, 0);
|
|
|
|
QCOMPARE(blk.members.count(), 2);
|
|
|
|
for (int i = 0; i < blk.members.count(); ++i) {
|
|
|
|
const QShaderDescription::BlockVariable v = blk.members[i];
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
QCOMPARE(v.offset, 0);
|
|
|
|
QCOMPARE(v.size, 64);
|
|
|
|
QCOMPARE(v.name, QLatin1String("qt_Matrix"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Mat4);
|
|
|
|
QCOMPARE(v.matrixStride, 16);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
QCOMPARE(v.offset, 64);
|
|
|
|
QCOMPARE(v.size, 4);
|
|
|
|
QCOMPARE(v.name, QLatin1String("opacity"));
|
|
|
|
QCOMPARE(v.type, QShaderDescription::Float);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
QVERIFY(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-10-28 15:37:57 +00:00
|
|
|
}
|
|
|
|
|
2019-03-22 08:55:03 +00:00
|
|
|
#include <tst_qshader.moc>
|
|
|
|
QTEST_MAIN(tst_QShader)
|