1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt3D module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include <QtTest/QTest> |
30 | #include <Qt3DCore/qentity.h> |
31 | #include <Qt3DCore/qtransform.h> |
32 | #include <Qt3DCore/private/qaspectjobmanager_p.h> |
33 | #include <Qt3DCore/private/qnodevisitor_p.h> |
34 | #include <Qt3DCore/private/qnode_p.h> |
35 | |
36 | #include <Qt3DRender/private/nodemanagers_p.h> |
37 | #include <Qt3DRender/private/managers_p.h> |
38 | #include <Qt3DRender/private/entity_p.h> |
39 | #include <materialparametergathererjob_p.h> |
40 | #include <Qt3DRender/private/techniquefilternode_p.h> |
41 | #include <Qt3DRender/private/technique_p.h> |
42 | #include <Qt3DRender/private/techniquemanager_p.h> |
43 | #include <Qt3DRender/private/renderpassfilternode_p.h> |
44 | #include <Qt3DRender/qrendersettings.h> |
45 | #include <Qt3DRender/qrenderaspect.h> |
46 | #include <Qt3DRender/qeffect.h> |
47 | #include <Qt3DRender/qmaterial.h> |
48 | #include <Qt3DRender/qparameter.h> |
49 | #include <Qt3DRender/qtechniquefilter.h> |
50 | #include <Qt3DRender/qtechnique.h> |
51 | #include <Qt3DRender/qrenderpassfilter.h> |
52 | #include <Qt3DRender/qrenderpass.h> |
53 | #include <Qt3DRender/qshaderprogram.h> |
54 | #include <Qt3DRender/qviewport.h> |
55 | #include <Qt3DRender/private/qrenderaspect_p.h> |
56 | |
57 | QT_BEGIN_NAMESPACE |
58 | |
59 | namespace Qt3DRender { |
60 | |
61 | class TestAspect : public Qt3DRender::QRenderAspect |
62 | { |
63 | public: |
64 | TestAspect(Qt3DCore::QNode *root) |
65 | : Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous) |
66 | , m_jobManager(new Qt3DCore::QAspectJobManager()) |
67 | { |
68 | Qt3DCore::QAbstractAspectPrivate::get(aspect: this)->m_jobManager = m_jobManager.data(); |
69 | QRenderAspect::onRegistered(); |
70 | |
71 | QVector<Qt3DCore::QNode *> nodes; |
72 | Qt3DCore::QNodeVisitor v; |
73 | v.traverse(rootNode_: root, fN: [&nodes](Qt3DCore::QNode *node) { |
74 | Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(q: node); |
75 | d->m_typeInfo = const_cast<QMetaObject*>(Qt3DCore::QNodePrivate::findStaticMetaObject(metaObject: node->metaObject())); |
76 | d->m_hasBackendNode = true; |
77 | nodes << node; |
78 | }); |
79 | |
80 | for (const auto node: nodes) |
81 | d_func()->createBackendNode(change: { |
82 | .id: node->id(), |
83 | .metaObj: Qt3DCore::QNodePrivate::get(q: node)->m_typeInfo, |
84 | .type: Qt3DCore::NodeTreeChange::Added, |
85 | .node: node |
86 | }); |
87 | |
88 | const auto handles = nodeManagers()->techniqueManager()->activeHandles(); |
89 | for (const auto &handle: handles) { |
90 | Render::Technique *technique = nodeManagers()->techniqueManager()->data(handle); |
91 | technique->setCompatibleWithRenderer(true); |
92 | } |
93 | } |
94 | |
95 | ~TestAspect() |
96 | { |
97 | QRenderAspect::onUnregistered(); |
98 | } |
99 | |
100 | Qt3DRender::Render::NodeManagers *nodeManagers() const |
101 | { |
102 | return d_func()->m_renderer->nodeManagers(); |
103 | } |
104 | |
105 | void initializeRenderer() |
106 | { |
107 | d_func()->m_renderer->initialize(); |
108 | } |
109 | |
110 | Render::OpenGL::MaterialParameterGathererJobPtr materialGathererJob() const |
111 | { |
112 | Render::OpenGL::MaterialParameterGathererJobPtr job = Render::OpenGL::MaterialParameterGathererJobPtr::create(); |
113 | job->setNodeManagers(nodeManagers()); |
114 | return job; |
115 | } |
116 | |
117 | void onRegistered() { QRenderAspect::onRegistered(); } |
118 | void onUnregistered() { QRenderAspect::onUnregistered(); } |
119 | |
120 | private: |
121 | QScopedPointer<Qt3DCore::QAspectJobManager> m_jobManager; |
122 | }; |
123 | |
124 | } // namespace Qt3DRender |
125 | |
126 | QT_END_NAMESPACE |
127 | |
128 | namespace { |
129 | |
130 | class TestMaterial : public Qt3DRender::QMaterial |
131 | { |
132 | Q_OBJECT |
133 | public: |
134 | explicit TestMaterial(Qt3DCore::QNode *parent = nullptr) |
135 | : Qt3DRender::QMaterial(parent) |
136 | , m_effect(new Qt3DRender::QEffect()) |
137 | , m_gl3Technique(new Qt3DRender::QTechnique()) |
138 | , m_gl2Technique(new Qt3DRender::QTechnique()) |
139 | , m_es2Technique(new Qt3DRender::QTechnique()) |
140 | , m_gl3Pass(new Qt3DRender::QRenderPass()) |
141 | , m_gl2Pass(new Qt3DRender::QRenderPass()) |
142 | , m_es2Pass(new Qt3DRender::QRenderPass()) |
143 | , m_gl3Program(new Qt3DRender::QShaderProgram()) |
144 | , m_gl2es2Program(new Qt3DRender::QShaderProgram()) |
145 | { |
146 | m_gl3Pass->setShaderProgram(m_gl3Program); |
147 | m_gl2Pass->setShaderProgram(m_gl2es2Program); |
148 | m_es2Pass->setShaderProgram(m_gl2es2Program); |
149 | |
150 | m_gl3Technique->addRenderPass(pass: m_gl3Pass); |
151 | m_gl2Technique->addRenderPass(pass: m_gl2Pass); |
152 | m_es2Technique->addRenderPass(pass: m_es2Pass); |
153 | |
154 | m_effect->addTechnique(t: m_gl3Technique); |
155 | m_effect->addTechnique(t: m_gl2Technique); |
156 | m_effect->addTechnique(t: m_es2Technique); |
157 | |
158 | setEffect(m_effect); |
159 | } |
160 | |
161 | Qt3DRender::QTechnique *gl3Technique() const { return m_gl3Technique; } |
162 | Qt3DRender::QTechnique *gl2Technique() const { return m_gl2Technique; } |
163 | Qt3DRender::QTechnique *es2Technique() const { return m_es2Technique; } |
164 | |
165 | Qt3DRender::QRenderPass *gl3Pass() const { return m_gl3Pass; } |
166 | Qt3DRender::QRenderPass *gl2Pass() const { return m_gl2Pass; } |
167 | Qt3DRender::QRenderPass *es2Pass() const { return m_es2Pass; } |
168 | |
169 | Qt3DRender::QShaderProgram *gl3Shader() const { return m_gl3Program; } |
170 | Qt3DRender::QShaderProgram *gl2shader() const { return m_gl2es2Program; } |
171 | Qt3DRender::QShaderProgram *es2Shader() const { return m_gl2es2Program; } |
172 | |
173 | private: |
174 | Qt3DRender::QEffect *m_effect; |
175 | Qt3DRender::QTechnique *m_gl3Technique; |
176 | Qt3DRender::QTechnique *m_gl2Technique; |
177 | Qt3DRender::QTechnique *m_es2Technique; |
178 | Qt3DRender::QRenderPass *m_gl3Pass; |
179 | Qt3DRender::QRenderPass *m_gl2Pass; |
180 | Qt3DRender::QRenderPass *m_es2Pass; |
181 | Qt3DRender::QShaderProgram *m_gl3Program; |
182 | Qt3DRender::QShaderProgram *m_gl2es2Program; |
183 | }; |
184 | |
185 | Qt3DRender::QViewport *viewportFrameGraph() |
186 | { |
187 | Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); |
188 | return viewport; |
189 | } |
190 | |
191 | Qt3DRender::QTechniqueFilter *techniqueFilterFrameGraph() |
192 | { |
193 | Qt3DRender::QTechniqueFilter *techniqueFilter = new Qt3DRender::QTechniqueFilter(); |
194 | return techniqueFilter; |
195 | } |
196 | |
197 | Qt3DRender::QRenderPassFilter *renderPassFilter() |
198 | { |
199 | Qt3DRender::QRenderPassFilter *passFilter = new Qt3DRender::QRenderPassFilter(); |
200 | return passFilter; |
201 | } |
202 | |
203 | Qt3DCore::QEntity *buildScene(Qt3DRender::QFrameGraphNode *frameGraph, Qt3DRender::QMaterial *material = nullptr) |
204 | { |
205 | Qt3DCore::QEntity *root = new Qt3DCore::QEntity(); |
206 | |
207 | // FrameGraph |
208 | Qt3DRender::QRenderSettings* renderSettings = new Qt3DRender::QRenderSettings(); |
209 | renderSettings->setActiveFrameGraph(frameGraph); |
210 | root->addComponent(comp: renderSettings); |
211 | |
212 | // Scene |
213 | for (int i = 0; i < 10; i++) { |
214 | Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); |
215 | if (material != nullptr) |
216 | e->addComponent(comp: material); |
217 | e->setParent(root); |
218 | } |
219 | |
220 | return root; |
221 | } |
222 | |
223 | } // anonymous |
224 | |
225 | class tst_MaterialParameterGatherer : public QObject |
226 | { |
227 | Q_OBJECT |
228 | private Q_SLOTS: |
229 | |
230 | void checkRunNoHandlesNoTechniqueFilterNoPassFilter() |
231 | { |
232 | // GIVEN |
233 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: viewportFrameGraph()); |
234 | Qt3DRender::TestAspect testAspect(sceneRoot); |
235 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
236 | |
237 | testAspect.initializeRenderer(); |
238 | |
239 | // THEN |
240 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 0); |
241 | |
242 | // WHEN |
243 | gatherer->run(); |
244 | |
245 | // THEN |
246 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); |
247 | } |
248 | |
249 | void checkRunSelectAllNoTechniqueFilterNoPassFilter() |
250 | { |
251 | // GIVEN |
252 | TestMaterial material; |
253 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: viewportFrameGraph(), material: &material); |
254 | Qt3DRender::TestAspect testAspect(sceneRoot); |
255 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
256 | |
257 | testAspect.initializeRenderer(); |
258 | |
259 | // THEN |
260 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
261 | |
262 | // WHEN |
263 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
264 | gatherer->run(); |
265 | |
266 | // THEN |
267 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); |
268 | } |
269 | |
270 | void checkRunDisabledMaterial() |
271 | { |
272 | // GIVEN |
273 | TestMaterial material; |
274 | material.setEnabled(false); |
275 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: viewportFrameGraph(), material: &material); |
276 | Qt3DRender::TestAspect testAspect(sceneRoot); |
277 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
278 | |
279 | testAspect.initializeRenderer(); |
280 | |
281 | // THEN |
282 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
283 | |
284 | // WHEN |
285 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
286 | gatherer->run(); |
287 | |
288 | // THEN |
289 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); |
290 | } |
291 | |
292 | void checkRunSelectAllTechniqueFilterWithNoFilterNoPassFilter() |
293 | { |
294 | // GIVEN |
295 | Qt3DRender::QTechniqueFilter *frameGraphFilter = techniqueFilterFrameGraph(); |
296 | |
297 | TestMaterial material; |
298 | |
299 | Qt3DRender::QFilterKey techniqueFilterKey; |
300 | techniqueFilterKey.setName(QStringLiteral("renderingStyle" )); |
301 | techniqueFilterKey.setValue(QVariant(QStringLiteral("backward" ))); |
302 | |
303 | material.gl2Technique()->addFilterKey(filterKey: &techniqueFilterKey); |
304 | material.gl3Technique()->addFilterKey(filterKey: &techniqueFilterKey); |
305 | material.es2Technique()->addFilterKey(filterKey: &techniqueFilterKey); |
306 | |
307 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: frameGraphFilter, material: &material); |
308 | Qt3DRender::TestAspect testAspect(sceneRoot); |
309 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
310 | |
311 | testAspect.initializeRenderer(); |
312 | |
313 | // THEN |
314 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
315 | Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast<Qt3DRender::Render::TechniqueFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: frameGraphFilter->id())); |
316 | QVERIFY(backendTechniqueFilter != nullptr); |
317 | |
318 | // WHEN |
319 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
320 | gatherer->setTechniqueFilter(backendTechniqueFilter); |
321 | gatherer->run(); |
322 | |
323 | // THEN |
324 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); |
325 | } |
326 | |
327 | void checkRunSelectAllTechniqueFilterWithIncompatibleFilterNoPassFilter() |
328 | { |
329 | // GIVEN |
330 | Qt3DRender::QTechniqueFilter *frameGraphFilter = techniqueFilterFrameGraph(); |
331 | TestMaterial material; |
332 | |
333 | Qt3DRender::QFilterKey techniqueFilterFilterKey; |
334 | techniqueFilterFilterKey.setName(QStringLiteral("renderingStyle" )); |
335 | techniqueFilterFilterKey.setValue(QVariant(QStringLiteral("forward" ))); |
336 | |
337 | Qt3DRender::QFilterKey techniqueFilterKey; |
338 | techniqueFilterKey.setName(QStringLiteral("renderingStyle" )); |
339 | techniqueFilterKey.setValue(QVariant(QStringLiteral("backward" ))); |
340 | |
341 | frameGraphFilter->addMatch(filterKey: &techniqueFilterFilterKey); |
342 | |
343 | material.gl2Technique()->addFilterKey(filterKey: &techniqueFilterKey); |
344 | material.gl3Technique()->addFilterKey(filterKey: &techniqueFilterKey); |
345 | material.es2Technique()->addFilterKey(filterKey: &techniqueFilterKey); |
346 | |
347 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: frameGraphFilter, material: &material); |
348 | Qt3DRender::TestAspect testAspect(sceneRoot); |
349 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
350 | |
351 | testAspect.initializeRenderer(); |
352 | |
353 | // THEN |
354 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
355 | Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast<Qt3DRender::Render::TechniqueFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: frameGraphFilter->id())); |
356 | QVERIFY(backendTechniqueFilter != nullptr); |
357 | |
358 | // WHEN |
359 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
360 | gatherer->setTechniqueFilter(backendTechniqueFilter); |
361 | gatherer->run(); |
362 | |
363 | // THEN |
364 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); |
365 | } |
366 | |
367 | void checkRunSelectAllTechniqueFilterWithCompatibleFilterNoPassFilter() |
368 | { |
369 | // GIVEN |
370 | Qt3DRender::QTechniqueFilter *frameGraphFilter = techniqueFilterFrameGraph(); |
371 | TestMaterial material; |
372 | |
373 | Qt3DRender::QFilterKey techniqueFilterKey; |
374 | techniqueFilterKey.setName(QStringLiteral("renderingStyle" )); |
375 | techniqueFilterKey.setValue(QVariant(QStringLiteral("backward" ))); |
376 | |
377 | frameGraphFilter->addMatch(filterKey: &techniqueFilterKey); |
378 | |
379 | material.gl2Technique()->addFilterKey(filterKey: &techniqueFilterKey); |
380 | material.gl3Technique()->addFilterKey(filterKey: &techniqueFilterKey); |
381 | material.es2Technique()->addFilterKey(filterKey: &techniqueFilterKey); |
382 | |
383 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: frameGraphFilter, material: &material); |
384 | Qt3DRender::TestAspect testAspect(sceneRoot); |
385 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
386 | |
387 | testAspect.initializeRenderer(); |
388 | |
389 | // THEN |
390 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
391 | Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast<Qt3DRender::Render::TechniqueFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: frameGraphFilter->id())); |
392 | QVERIFY(backendTechniqueFilter != nullptr); |
393 | |
394 | // WHEN |
395 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
396 | gatherer->setTechniqueFilter(backendTechniqueFilter); |
397 | gatherer->run(); |
398 | |
399 | // THEN |
400 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); |
401 | } |
402 | |
403 | void checkRunSelectAllNoTechniqueFilterPassFilterWithNoFilter() |
404 | { |
405 | // GIVEN |
406 | Qt3DRender::QRenderPassFilter *frameGraphFilter = renderPassFilter(); |
407 | TestMaterial material; |
408 | |
409 | Qt3DRender::QFilterKey passFilterKey; |
410 | passFilterKey.setName(QStringLiteral("renderingStyle" )); |
411 | passFilterKey.setValue(QVariant(QStringLiteral("backward" ))); |
412 | |
413 | material.gl3Pass()->addFilterKey(filterKey: &passFilterKey); |
414 | material.gl2Pass()->addFilterKey(filterKey: &passFilterKey); |
415 | material.es2Pass()->addFilterKey(filterKey: &passFilterKey); |
416 | |
417 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: frameGraphFilter, material: &material); |
418 | Qt3DRender::TestAspect testAspect(sceneRoot); |
419 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
420 | |
421 | testAspect.initializeRenderer(); |
422 | |
423 | // THEN |
424 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
425 | Qt3DRender::Render::RenderPassFilter *backendPassFilter = static_cast<Qt3DRender::Render::RenderPassFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: frameGraphFilter->id())); |
426 | QVERIFY(backendPassFilter != nullptr); |
427 | |
428 | // WHEN |
429 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
430 | gatherer->setRenderPassFilter(backendPassFilter); |
431 | gatherer->run(); |
432 | |
433 | // THEN |
434 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); |
435 | } |
436 | |
437 | void checkRunSelectAllNoTechniqueFilterPassFilterWithIncompatibleFilter() |
438 | { |
439 | // GIVEN |
440 | Qt3DRender::QRenderPassFilter *frameGraphFilter = renderPassFilter(); |
441 | TestMaterial material; |
442 | |
443 | Qt3DRender::QFilterKey passFilterFilterKey; |
444 | passFilterFilterKey.setName(QStringLiteral("renderingStyle" )); |
445 | passFilterFilterKey.setValue(QVariant(QStringLiteral("forward" ))); |
446 | |
447 | Qt3DRender::QFilterKey passFilterKey; |
448 | passFilterKey.setName(QStringLiteral("renderingStyle" )); |
449 | passFilterKey.setValue(QVariant(QStringLiteral("backward" ))); |
450 | |
451 | frameGraphFilter->addMatch(filterKey: &passFilterFilterKey); |
452 | |
453 | material.gl3Pass()->addFilterKey(filterKey: &passFilterKey); |
454 | material.gl2Pass()->addFilterKey(filterKey: &passFilterKey); |
455 | material.es2Pass()->addFilterKey(filterKey: &passFilterKey); |
456 | |
457 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: frameGraphFilter, material: &material); |
458 | Qt3DRender::TestAspect testAspect(sceneRoot); |
459 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
460 | |
461 | testAspect.initializeRenderer(); |
462 | |
463 | // THEN |
464 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
465 | Qt3DRender::Render::RenderPassFilter *backendPassFilter = static_cast<Qt3DRender::Render::RenderPassFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: frameGraphFilter->id())); |
466 | QVERIFY(backendPassFilter != nullptr); |
467 | |
468 | // WHEN |
469 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
470 | gatherer->setRenderPassFilter(backendPassFilter); |
471 | gatherer->run(); |
472 | |
473 | // THEN |
474 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); |
475 | } |
476 | |
477 | void checkParameterPriorityGathering() |
478 | { |
479 | { |
480 | // GIVEN |
481 | Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); |
482 | Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); |
483 | |
484 | renderPassFG->setParent(techniqueFilterFG); |
485 | |
486 | TestMaterial material; |
487 | |
488 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: techniqueFilterFG, material: &material); |
489 | |
490 | // WHEN |
491 | techniqueFilterFG->addParameter(p: new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::red)))); |
492 | |
493 | auto renderPassParameter = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::cyan))); |
494 | |
495 | renderPassFG->addParameter(parameter: renderPassParameter); |
496 | material.addParameter(parameter: new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::green)))); |
497 | material.effect()->addParameter(parameter: new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::blue)))); |
498 | |
499 | auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::white))); |
500 | |
501 | material.gl3Technique()->addParameter(p: techniqueParam); |
502 | material.gl2Technique()->addParameter(p: techniqueParam); |
503 | material.es2Technique()->addParameter(p: techniqueParam); |
504 | |
505 | auto passParam = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::gray))); |
506 | |
507 | material.gl3Pass()->addParameter(p: passParam); |
508 | material.gl2Pass()->addParameter(p: passParam); |
509 | material.es2Pass()->addParameter(p: passParam); |
510 | |
511 | Qt3DRender::TestAspect testAspect(sceneRoot); |
512 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
513 | testAspect.initializeRenderer(); |
514 | |
515 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
516 | Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast<Qt3DRender::Render::TechniqueFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: techniqueFilterFG->id())); |
517 | Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast<Qt3DRender::Render::RenderPassFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: renderPassFG->id())); |
518 | QVERIFY(backendTechniqueFilter != nullptr); |
519 | QVERIFY(backendRenderPassFilter != nullptr); |
520 | |
521 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
522 | gatherer->setRenderPassFilter(backendRenderPassFilter); |
523 | gatherer->setTechniqueFilter(backendTechniqueFilter); |
524 | gatherer->run(); |
525 | |
526 | // THEN -> RenderPassFilter wins |
527 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); |
528 | |
529 | const QVector<Qt3DRender::Render::OpenGL::RenderPassParameterData> passParameterData = gatherer->materialToPassAndParameter().begin().value(); |
530 | QCOMPARE(passParameterData.size(), 1); |
531 | |
532 | const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); |
533 | |
534 | QCOMPARE(data.parameterInfo.size(), 1); |
535 | QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(renderPassParameter->id())); |
536 | } |
537 | { |
538 | // GIVEN |
539 | Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); |
540 | Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); |
541 | |
542 | renderPassFG->setParent(techniqueFilterFG); |
543 | |
544 | TestMaterial material; |
545 | |
546 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: techniqueFilterFG, material: &material); |
547 | |
548 | // WHEN |
549 | auto techniqueFilterParameter = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::cyan))); |
550 | techniqueFilterFG->addParameter(p: techniqueFilterParameter); |
551 | |
552 | material.addParameter(parameter: new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::green)))); |
553 | material.effect()->addParameter(parameter: new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::blue)))); |
554 | |
555 | auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::white))); |
556 | |
557 | material.gl3Technique()->addParameter(p: techniqueParam); |
558 | material.gl2Technique()->addParameter(p: techniqueParam); |
559 | material.es2Technique()->addParameter(p: techniqueParam); |
560 | |
561 | auto passParam = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::gray))); |
562 | |
563 | material.gl3Pass()->addParameter(p: passParam); |
564 | material.gl2Pass()->addParameter(p: passParam); |
565 | material.es2Pass()->addParameter(p: passParam); |
566 | |
567 | Qt3DRender::TestAspect testAspect(sceneRoot); |
568 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
569 | testAspect.initializeRenderer(); |
570 | |
571 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
572 | Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast<Qt3DRender::Render::TechniqueFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: techniqueFilterFG->id())); |
573 | Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast<Qt3DRender::Render::RenderPassFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: renderPassFG->id())); |
574 | QVERIFY(backendTechniqueFilter != nullptr); |
575 | QVERIFY(backendRenderPassFilter != nullptr); |
576 | |
577 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
578 | gatherer->setRenderPassFilter(backendRenderPassFilter); |
579 | gatherer->setTechniqueFilter(backendTechniqueFilter); |
580 | gatherer->run(); |
581 | |
582 | // THEN -> TechniqueFilter wins |
583 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); |
584 | |
585 | const QVector<Qt3DRender::Render::OpenGL::RenderPassParameterData> passParameterData = gatherer->materialToPassAndParameter().begin().value(); |
586 | QCOMPARE(passParameterData.size(), 1); |
587 | |
588 | const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); |
589 | |
590 | QCOMPARE(data.parameterInfo.size(), 1); |
591 | QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(techniqueFilterParameter->id())); |
592 | } |
593 | { |
594 | // GIVEN |
595 | Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); |
596 | Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); |
597 | |
598 | renderPassFG->setParent(techniqueFilterFG); |
599 | |
600 | TestMaterial material; |
601 | |
602 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: techniqueFilterFG, material: &material); |
603 | |
604 | // WHEN |
605 | auto materialParameter = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::cyan))); |
606 | |
607 | material.addParameter(parameter: materialParameter); |
608 | material.effect()->addParameter(parameter: new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::blue)))); |
609 | |
610 | auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::white))); |
611 | |
612 | material.gl3Technique()->addParameter(p: techniqueParam); |
613 | material.gl2Technique()->addParameter(p: techniqueParam); |
614 | material.es2Technique()->addParameter(p: techniqueParam); |
615 | |
616 | auto passParam = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::gray))); |
617 | |
618 | material.gl3Pass()->addParameter(p: passParam); |
619 | material.gl2Pass()->addParameter(p: passParam); |
620 | material.es2Pass()->addParameter(p: passParam); |
621 | |
622 | Qt3DRender::TestAspect testAspect(sceneRoot); |
623 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
624 | testAspect.initializeRenderer(); |
625 | |
626 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
627 | Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast<Qt3DRender::Render::TechniqueFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: techniqueFilterFG->id())); |
628 | Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast<Qt3DRender::Render::RenderPassFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: renderPassFG->id())); |
629 | QVERIFY(backendTechniqueFilter != nullptr); |
630 | QVERIFY(backendRenderPassFilter != nullptr); |
631 | |
632 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
633 | gatherer->setRenderPassFilter(backendRenderPassFilter); |
634 | gatherer->setTechniqueFilter(backendTechniqueFilter); |
635 | gatherer->run(); |
636 | |
637 | // THEN -> TechniqueFilter wins |
638 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); |
639 | |
640 | const QVector<Qt3DRender::Render::OpenGL::RenderPassParameterData> passParameterData = gatherer->materialToPassAndParameter().begin().value(); |
641 | QCOMPARE(passParameterData.size(), 1); |
642 | |
643 | const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); |
644 | |
645 | QCOMPARE(data.parameterInfo.size(), 1); |
646 | QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(materialParameter->id())); |
647 | } |
648 | { |
649 | // GIVEN |
650 | Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); |
651 | Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); |
652 | |
653 | renderPassFG->setParent(techniqueFilterFG); |
654 | |
655 | TestMaterial material; |
656 | |
657 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: techniqueFilterFG, material: &material); |
658 | |
659 | // WHEN |
660 | auto effectParameter = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::cyan))); |
661 | |
662 | material.effect()->addParameter(parameter: effectParameter); |
663 | |
664 | auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::white))); |
665 | |
666 | material.gl3Technique()->addParameter(p: techniqueParam); |
667 | material.gl2Technique()->addParameter(p: techniqueParam); |
668 | material.es2Technique()->addParameter(p: techniqueParam); |
669 | |
670 | auto passParam = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::gray))); |
671 | |
672 | material.gl3Pass()->addParameter(p: passParam); |
673 | material.gl2Pass()->addParameter(p: passParam); |
674 | material.es2Pass()->addParameter(p: passParam); |
675 | |
676 | Qt3DRender::TestAspect testAspect(sceneRoot); |
677 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
678 | testAspect.initializeRenderer(); |
679 | |
680 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
681 | Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast<Qt3DRender::Render::TechniqueFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: techniqueFilterFG->id())); |
682 | Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast<Qt3DRender::Render::RenderPassFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: renderPassFG->id())); |
683 | QVERIFY(backendTechniqueFilter != nullptr); |
684 | QVERIFY(backendRenderPassFilter != nullptr); |
685 | |
686 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
687 | gatherer->setRenderPassFilter(backendRenderPassFilter); |
688 | gatherer->setTechniqueFilter(backendTechniqueFilter); |
689 | gatherer->run(); |
690 | |
691 | // THEN -> TechniqueFilter wins |
692 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); |
693 | |
694 | const QVector<Qt3DRender::Render::OpenGL::RenderPassParameterData> passParameterData = gatherer->materialToPassAndParameter().begin().value(); |
695 | QCOMPARE(passParameterData.size(), 1); |
696 | |
697 | const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); |
698 | |
699 | QCOMPARE(data.parameterInfo.size(), 1); |
700 | QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(effectParameter->id())); |
701 | } |
702 | { |
703 | // GIVEN |
704 | Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); |
705 | Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); |
706 | |
707 | renderPassFG->setParent(techniqueFilterFG); |
708 | |
709 | TestMaterial material; |
710 | |
711 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: techniqueFilterFG, material: &material); |
712 | |
713 | // WHEN |
714 | auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::white))); |
715 | |
716 | material.gl3Technique()->addParameter(p: techniqueParam); |
717 | material.gl2Technique()->addParameter(p: techniqueParam); |
718 | material.es2Technique()->addParameter(p: techniqueParam); |
719 | |
720 | auto passParam = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::gray))); |
721 | |
722 | material.gl3Pass()->addParameter(p: passParam); |
723 | material.gl2Pass()->addParameter(p: passParam); |
724 | material.es2Pass()->addParameter(p: passParam); |
725 | |
726 | Qt3DRender::TestAspect testAspect(sceneRoot); |
727 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
728 | testAspect.initializeRenderer(); |
729 | |
730 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
731 | Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast<Qt3DRender::Render::TechniqueFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: techniqueFilterFG->id())); |
732 | Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast<Qt3DRender::Render::RenderPassFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: renderPassFG->id())); |
733 | QVERIFY(backendTechniqueFilter != nullptr); |
734 | QVERIFY(backendRenderPassFilter != nullptr); |
735 | |
736 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
737 | gatherer->setRenderPassFilter(backendRenderPassFilter); |
738 | gatherer->setTechniqueFilter(backendTechniqueFilter); |
739 | gatherer->run(); |
740 | |
741 | // THEN -> TechniqueFilter wins |
742 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); |
743 | |
744 | const QVector<Qt3DRender::Render::OpenGL::RenderPassParameterData> passParameterData = gatherer->materialToPassAndParameter().begin().value(); |
745 | QCOMPARE(passParameterData.size(), 1); |
746 | |
747 | const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); |
748 | |
749 | QCOMPARE(data.parameterInfo.size(), 1); |
750 | QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(techniqueParam->id())); |
751 | } |
752 | { |
753 | // GIVEN |
754 | Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); |
755 | Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); |
756 | |
757 | renderPassFG->setParent(techniqueFilterFG); |
758 | |
759 | TestMaterial material; |
760 | |
761 | Qt3DCore::QEntity *sceneRoot = buildScene(frameGraph: techniqueFilterFG, material: &material); |
762 | |
763 | // WHEN |
764 | auto passParam = new Qt3DRender::QParameter(QStringLiteral("color" ), QVariant(QColor(Qt::gray))); |
765 | |
766 | material.gl3Pass()->addParameter(p: passParam); |
767 | material.gl2Pass()->addParameter(p: passParam); |
768 | material.es2Pass()->addParameter(p: passParam); |
769 | |
770 | Qt3DRender::TestAspect testAspect(sceneRoot); |
771 | Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); |
772 | testAspect.initializeRenderer(); |
773 | |
774 | QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); |
775 | Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast<Qt3DRender::Render::TechniqueFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: techniqueFilterFG->id())); |
776 | Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast<Qt3DRender::Render::RenderPassFilter *>(testAspect.nodeManagers()->frameGraphManager()->lookupNode(id: renderPassFG->id())); |
777 | QVERIFY(backendTechniqueFilter != nullptr); |
778 | QVERIFY(backendRenderPassFilter != nullptr); |
779 | |
780 | gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); |
781 | gatherer->setRenderPassFilter(backendRenderPassFilter); |
782 | gatherer->setTechniqueFilter(backendTechniqueFilter); |
783 | gatherer->run(); |
784 | |
785 | // THEN -> TechniqueFilter wins |
786 | QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); |
787 | |
788 | const QVector<Qt3DRender::Render::OpenGL::RenderPassParameterData> passParameterData = gatherer->materialToPassAndParameter().begin().value(); |
789 | QCOMPARE(passParameterData.size(), 1); |
790 | |
791 | const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); |
792 | |
793 | QCOMPARE(data.parameterInfo.size(), 1); |
794 | QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(passParam->id())); |
795 | } |
796 | } |
797 | }; |
798 | |
799 | QTEST_MAIN(tst_MaterialParameterGatherer) |
800 | |
801 | #include "tst_materialparametergathererjob.moc" |
802 | |