diff options
author | Kevin Ottens <kevin.ottens@kdab.com> | 2017-02-23 13:53:23 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-02-24 16:58:51 +0000 |
commit | 12111fd494d927bb75a8a41e3771ff6983119274 (patch) | |
tree | 6590daea24184e851502beb0e94dbe76e2cca640 | |
parent | 92a2759a8cf7a77958a788216f1bee762789ca59 (diff) |
QShaderData: fix texture support in properties
There was only code dealing with sub-shader data but nothing allowing to
check if a property was a texture, this is now properly handled.
Change-Id: I48984727eff975e9f3e2c21c5185b336efc963fd
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r-- | src/quick3d/quick3drender/items/quick3dshaderdata.cpp | 8 | ||||
-rw-r--r-- | src/render/backend/renderview.cpp | 2 | ||||
-rw-r--r-- | src/render/jobs/renderviewjobutils.cpp | 19 | ||||
-rw-r--r-- | src/render/jobs/renderviewjobutils_p.h | 2 | ||||
-rw-r--r-- | src/render/materialsystem/qshaderdata_p.h | 6 | ||||
-rw-r--r-- | tests/auto/render/renderviewutils/tst_renderviewutils.cpp | 156 |
6 files changed, 179 insertions, 14 deletions
diff --git a/src/quick3d/quick3drender/items/quick3dshaderdata.cpp b/src/quick3d/quick3drender/items/quick3dshaderdata.cpp index dbf351695..1287f1603 100644 --- a/src/quick3d/quick3drender/items/quick3dshaderdata.cpp +++ b/src/quick3d/quick3drender/items/quick3dshaderdata.cpp @@ -84,11 +84,9 @@ public: } } return innerValues; - } else if (v.userType() == quick3DShaderDataTypeId) { - Qt3DCore::QNodeId id; - QShaderData *shaderData = v.value<Quick3DShaderData *>(); - if (shaderData) - id = shaderData->id(); + } else if (v.canConvert<Qt3DCore::QNode*>()) { + const auto node = v.value<Qt3DCore::QNode *>(); + const auto id = Qt3DCore::qIdForNode(node); return QVariant::fromValue(id); } return v; diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp index c7d2c7864..bd184594f 100644 --- a/src/render/backend/renderview.cpp +++ b/src/render/backend/renderview.cpp @@ -361,6 +361,7 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit // is only accessed from the same thread UniformBlockValueBuilder *builder = new UniformBlockValueBuilder(); builder->shaderDataManager = m_manager->shaderDataManager(); + builder->textureManager = m_manager->textureManager(); m_localData.setLocalData(builder); QVector<RenderCommand *> commands; @@ -479,6 +480,7 @@ QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<En // is only accessed from the same thread UniformBlockValueBuilder *builder = new UniformBlockValueBuilder(); builder->shaderDataManager = m_manager->shaderDataManager(); + builder->textureManager = m_manager->textureManager(); m_localData.setLocalData(builder); // If the RenderView contains only a ComputeDispatch then it cares about diff --git a/src/render/jobs/renderviewjobutils.cpp b/src/render/jobs/renderviewjobutils.cpp index f75ea3f0c..500fcc56a 100644 --- a/src/render/jobs/renderviewjobutils.cpp +++ b/src/render/jobs/renderviewjobutils.cpp @@ -416,6 +416,7 @@ const int qNodeIdTypeId = qMetaTypeId<QNodeId>(); UniformBlockValueBuilder::UniformBlockValueBuilder() : updatedPropertiesOnly(false) , shaderDataManager(nullptr) + , textureManager(nullptr) { } @@ -432,11 +433,16 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData * if (list.at(0).userType() == qNodeIdTypeId) { // Array of struct qmlPropertyName[i].structMember for (int i = 0; i < list.size(); ++i) { if (list.at(i).userType() == qNodeIdTypeId) { - ShaderData *subShaderData = shaderDataManager->lookupResource(list.at(i).value<QNodeId>()); - if (subShaderData) + const auto nodeId = value.value<QNodeId>(); + ShaderData *subShaderData = shaderDataManager->lookupResource(nodeId); + if (subShaderData) { buildActiveUniformNameValueMapStructHelper(subShaderData, blockName + QLatin1Char('.') + qmlPropertyName + blockArray.arg(i), QLatin1String("")); + } else if (textureManager->contains(nodeId)) { + const auto varId = StringToInt::lookupId(blockName + QLatin1Char('.') + qmlPropertyName + blockArray.arg(i)); + activeUniformNamesToValue.insert(varId, value); + } } } } else { // Array of scalar/vec qmlPropertyName[0] @@ -447,11 +453,16 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData * } } } else if (value.userType() == qNodeIdTypeId) { // Struct qmlPropertyName.structMember - ShaderData *rSubShaderData = shaderDataManager->lookupResource(value.value<QNodeId>()); - if (rSubShaderData) + const auto nodeId = value.value<QNodeId>(); + ShaderData *rSubShaderData = shaderDataManager->lookupResource(nodeId); + if (rSubShaderData) { buildActiveUniformNameValueMapStructHelper(rSubShaderData, blockName, qmlPropertyName); + } else if (textureManager->contains(nodeId)) { + const auto varId = StringToInt::lookupId(blockName + QLatin1Char('.') + qmlPropertyName); + activeUniformNamesToValue.insert(varId, value); + } } else { // Scalar / Vec QString varName = blockName + QLatin1Char('.') + qmlPropertyName; if (uniforms.contains(varName)) { diff --git a/src/render/jobs/renderviewjobutils_p.h b/src/render/jobs/renderviewjobutils_p.h index bc042a582..c1d37b28a 100644 --- a/src/render/jobs/renderviewjobutils_p.h +++ b/src/render/jobs/renderviewjobutils_p.h @@ -83,6 +83,7 @@ class NodeManagers; class ShaderDataManager; struct ShaderUniform; class ShaderData; +class TextureManager; class RenderStateManager; class RenderStateCollection; @@ -169,6 +170,7 @@ struct Q_AUTOTEST_EXPORT UniformBlockValueBuilder QHash<QString, ShaderUniform> uniforms; UniformBlockValueBuilderHash activeUniformNamesToValue; ShaderDataManager *shaderDataManager; + TextureManager *textureManager; QMatrix4x4 viewMatrix; }; diff --git a/src/render/materialsystem/qshaderdata_p.h b/src/render/materialsystem/qshaderdata_p.h index bfa139890..53e3caefd 100644 --- a/src/render/materialsystem/qshaderdata_p.h +++ b/src/render/materialsystem/qshaderdata_p.h @@ -70,10 +70,10 @@ class QShaderDataPropertyReader: public PropertyReaderInterface { QVariant readProperty(const QVariant &v) Q_DECL_OVERRIDE { - QShaderData *shaderData = nullptr; + const auto node = v.value<Qt3DCore::QNode *>(); - if (v.userType() == qShaderDataTypeId && (shaderData = v.value<QShaderData *>()) != nullptr) { - return QVariant::fromValue(shaderData->id()); + if (node) { + return QVariant::fromValue(node->id()); } else if (v.userType() == qVectorShaderDataTypeId) { QVariantList vlist; const auto data_ = v.value<QVector<QShaderData *> >(); diff --git a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp b/tests/auto/render/renderviewutils/tst_renderviewutils.cpp index e4681a257..c38b2795e 100644 --- a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp +++ b/tests/auto/render/renderviewutils/tst_renderviewutils.cpp @@ -43,6 +43,8 @@ class tst_RenderViewUtils : public Qt3DCore::QBackendNodeTester private Q_SLOTS: void topLevelScalarValueNoUniforms(); void topLevelScalarValue(); + void topLevelTextureValueNoUniforms(); + void topLevelTextureValue(); void topLevelArrayValue(); void topLevelStructValue_data(); void topLevelStructValue(); @@ -66,6 +68,15 @@ private: // Init the backend element simulateInitialization(frontend, backend); } + + void initBackendTexture(Qt3DRender::QAbstractTexture *frontend, + Qt3DRender::Render::TextureManager *manager) + { + // Create backend element for frontend one + Qt3DRender::Render::Texture *backend = manager->getOrCreateResource(frontend->id()); + // Init the backend element + simulateInitialization(frontend, backend); + } }; class ScalarShaderData : public Qt3DRender::QShaderData @@ -109,6 +120,47 @@ private: float m_scalar; }; +class TextureShaderData : public Qt3DRender::QShaderData +{ + Q_OBJECT + Q_PROPERTY(Qt3DRender::QAbstractTexture* texture READ texture WRITE setTexture NOTIFY textureChanged) + +public: + TextureShaderData() + : Qt3DRender::QShaderData() + , m_texture(nullptr) + { + } + + void setTexture(Qt3DRender::QAbstractTexture *texture) + { + if (texture != m_texture) { + m_texture = texture; + emit textureChanged(); + } + } + + Qt3DRender::QAbstractTexture *texture() const + { + return m_texture; + } + + QHash<QString, Qt3DRender::Render::ShaderUniform> buildUniformMap(const QString &blockName) + { + QHash<QString, Qt3DRender::Render::ShaderUniform> uniforms; + + uniforms.insert(blockName + QStringLiteral(".texture"), Qt3DRender::Render::ShaderUniform()); + + return uniforms; + } + +Q_SIGNALS: + void textureChanged(); + +private: + Qt3DRender::QAbstractTexture *m_texture; +}; + class ArrayShaderData : public Qt3DRender::QShaderData { @@ -294,6 +346,7 @@ void tst_RenderViewUtils::topLevelScalarValueNoUniforms() // GIVEN QScopedPointer<ScalarShaderData> shaderData(new ScalarShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); // WHEN shaderData->setScalar(883.0f); @@ -306,6 +359,7 @@ void tst_RenderViewUtils::topLevelScalarValueNoUniforms() // WHEB Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("")); @@ -320,6 +374,7 @@ void tst_RenderViewUtils::topLevelScalarValue() // GIVEN QScopedPointer<ScalarShaderData> shaderData(new ScalarShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); // WHEN shaderData->setScalar(883.0f); @@ -332,6 +387,7 @@ void tst_RenderViewUtils::topLevelScalarValue() // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); // build name-value map @@ -353,11 +409,83 @@ void tst_RenderViewUtils::topLevelScalarValue() } } +void tst_RenderViewUtils::topLevelTextureValueNoUniforms() +{ + // GIVEN + QScopedPointer<TextureShaderData> shaderData(new TextureShaderData); + QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager); + QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); + + // WHEN + shaderData->setTexture(texture.data()); + initBackendShaderData(shaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + + // WHEB + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("")); + + // THEN + // activeUniformNamesToValue should be empty as blockBuilder.uniforms is + QVERIFY(blockBuilder.activeUniformNamesToValue.isEmpty()); +} + +void tst_RenderViewUtils::topLevelTextureValue() +{ + // GIVEN + QScopedPointer<TextureShaderData> shaderData(new TextureShaderData); + QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager); + QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); + + // WHEN + initBackendTexture(texture.data(), textureManager.data()); + shaderData->setTexture(texture.data()); + initBackendShaderData(shaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); + + // THEN + QVERIFY(blockBuilder.uniforms.count() == 1); + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); + const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); + + while (it != end) { + // THEN + QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); + QCOMPARE(it.value(), QVariant::fromValue(shaderData->texture()->id())); + ++it; + } +} + void tst_RenderViewUtils::topLevelArrayValue() { // GIVEN QScopedPointer<ArrayShaderData> shaderData(new ArrayShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); // WHEN QVariantList arrayValues = QVariantList() << 454 << 350 << 383 << 427 << 552; @@ -371,6 +499,7 @@ void tst_RenderViewUtils::topLevelArrayValue() // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); // build name-value map @@ -430,6 +559,7 @@ void tst_RenderViewUtils::topLevelStructValue() QFETCH(StructShaderData *, shaderData); QFETCH(QString, blockName); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); // WHEN initBackendShaderData(shaderData, manager.data()); @@ -441,6 +571,7 @@ void tst_RenderViewUtils::topLevelStructValue() // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; blockBuilder.uniforms = shaderData->buildUniformMap(blockName); const QHash<QString, QVariant> expectedValues = shaderData->buildUniformMapValues(blockName); @@ -468,10 +599,14 @@ void tst_RenderViewUtils::topLevelDynamicProperties() // GIVEN QScopedPointer<Qt3DRender::QShaderData> shaderData(new Qt3DRender::QShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); // WHEN + initBackendTexture(texture.data(), textureManager.data()); shaderData->setProperty("scalar", 883.0f); shaderData->setProperty("array", QVariantList() << 454 << 350 << 383 << 427 << 552); + shaderData->setProperty("texture", QVariant::fromValue(texture.data())); initBackendShaderData(shaderData.data(), manager.data()); // THEN @@ -481,20 +616,24 @@ void tst_RenderViewUtils::topLevelDynamicProperties() // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; blockBuilder.uniforms.insert(QStringLiteral("MyBlock.scalar"), Qt3DRender::Render::ShaderUniform()); blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0]"), Qt3DRender::Render::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.texture"), Qt3DRender::Render::ShaderUniform()); // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); // THEN - QVERIFY(blockBuilder.uniforms.count() == 2); - QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 2); + QVERIFY(blockBuilder.uniforms.count() == 3); + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 3); QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.scalar")), shaderData->property("scalar")); QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.array[0]")), shaderData->property("array")); + QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.texture")), + QVariant::fromValue(texture->id())); } void tst_RenderViewUtils::transformedProperties() @@ -558,6 +697,19 @@ void tst_RenderViewUtils::shouldNotifyDynamicPropertyChanges() QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); QCOMPARE(change->propertyName(), QByteArrayLiteral("scalar")); QCOMPARE(change->value().toFloat(), 883.0f); + + arbiter.events.clear(); + + // WHEN + QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D); + shaderData->setProperty("texture", QVariant::fromValue(texture.data())); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().dynamicCast<Qt3DCore::QDynamicPropertyUpdatedChange>(); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->propertyName(), QByteArrayLiteral("texture")); + QCOMPARE(change->value(), QVariant::fromValue(texture->id())); } QTEST_MAIN(tst_RenderViewUtils) |