1/****************************************************************************
2**
3** Copyright (C) 2017 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
30#include <QtTest/QTest>
31#include <Qt3DRender/qshaderprogram.h>
32#include <Qt3DRender/qshaderprogrambuilder.h>
33#include <Qt3DRender/private/qshaderprogrambuilder_p.h>
34#include <QObject>
35#include <QSignalSpy>
36#include <Qt3DCore/qpropertyupdatedchange.h>
37#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
38#include <Qt3DCore/qnodecreatedchange.h>
39#include "testpostmanarbiter.h"
40
41class tst_QShaderProgramBuilder : public Qt3DRender::QShaderProgramBuilder
42{
43 Q_OBJECT
44public:
45 tst_QShaderProgramBuilder()
46 : Qt3DRender::QShaderProgramBuilder()
47 {
48 qRegisterMetaType<Qt3DRender::QShaderProgram*>(typeName: "Qt3DRender::QShaderProgram*");
49 }
50
51private Q_SLOTS:
52 void checkDefaultConstruction()
53 {
54 // GIVEN
55 Qt3DRender::QShaderProgramBuilder builder;
56
57 // THEN
58 QVERIFY(!builder.shaderProgram());
59 QVERIFY(builder.enabledLayers().isEmpty());
60 QCOMPARE(builder.vertexShaderGraph(), QUrl());
61 QCOMPARE(builder.tessellationControlShaderGraph(), QUrl());
62 QCOMPARE(builder.tessellationEvaluationShaderGraph(), QUrl());
63 QCOMPARE(builder.geometryShaderGraph(), QUrl());
64 QCOMPARE(builder.fragmentShaderGraph(), QUrl());
65 QCOMPARE(builder.computeShaderGraph(), QUrl());
66 QCOMPARE(builder.vertexShaderCode(), QByteArray());
67 QCOMPARE(builder.fragmentShaderCode(), QByteArray());
68 QCOMPARE(builder.computeShaderCode(), QByteArray());
69 QCOMPARE(builder.geometryShaderCode(), QByteArray());
70 QCOMPARE(builder.tessellationEvaluationShaderCode(), QByteArray());
71 QCOMPARE(builder.tessellationControlShaderCode(), QByteArray());
72 }
73
74 void checkPropertyChanges()
75 {
76 // GIVEN
77 Qt3DRender::QShaderProgramBuilder builder;
78
79 {
80 // WHEN
81 QSignalSpy spy(&builder, SIGNAL(shaderProgramChanged(Qt3DRender::QShaderProgram*)));
82 auto newValue = new Qt3DRender::QShaderProgram(&builder);
83 builder.setShaderProgram(newValue);
84
85 // THEN
86 QVERIFY(spy.isValid());
87 QCOMPARE(builder.shaderProgram(), newValue);
88 QCOMPARE(spy.count(), 1);
89
90 // WHEN
91 spy.clear();
92 builder.setShaderProgram(newValue);
93
94 // THEN
95 QCOMPARE(builder.shaderProgram(), newValue);
96 QCOMPARE(spy.count(), 0);
97 }
98 {
99 // WHEN
100 QSignalSpy spy(&builder, SIGNAL(enabledLayersChanged(QStringList)));
101 const auto newValue = QStringList() << "foo" << "bar";
102 builder.setEnabledLayers(newValue);
103
104 // THEN
105 QVERIFY(spy.isValid());
106 QCOMPARE(builder.enabledLayers(), newValue);
107 QCOMPARE(spy.count(), 1);
108
109 // WHEN
110 spy.clear();
111 builder.setEnabledLayers(newValue);
112
113 // THEN
114 QCOMPARE(builder.enabledLayers(), newValue);
115 QCOMPARE(spy.count(), 0);
116 }
117 {
118 // WHEN
119 QSignalSpy spy(&builder, SIGNAL(vertexShaderGraphChanged(QUrl)));
120 const auto newValue = QUrl::fromEncoded(url: "qrc:/vertex.json");
121 builder.setVertexShaderGraph(newValue);
122
123 // THEN
124 QVERIFY(spy.isValid());
125 QCOMPARE(builder.vertexShaderGraph(), newValue);
126 QCOMPARE(spy.count(), 1);
127
128 // WHEN
129 spy.clear();
130 builder.setVertexShaderGraph(newValue);
131
132 // THEN
133 QCOMPARE(builder.vertexShaderGraph(), newValue);
134 QCOMPARE(spy.count(), 0);
135 }
136 {
137 // WHEN
138 QSignalSpy spy(&builder, SIGNAL(tessellationControlShaderGraphChanged(QUrl)));
139 const auto newValue = QUrl::fromEncoded(url: "qrc:/tesscontrol.json");
140 builder.setTessellationControlShaderGraph(newValue);
141
142 // THEN
143 QVERIFY(spy.isValid());
144 QCOMPARE(builder.tessellationControlShaderGraph(), newValue);
145 QCOMPARE(spy.count(), 1);
146
147 // WHEN
148 spy.clear();
149 builder.setTessellationControlShaderGraph(newValue);
150
151 // THEN
152 QCOMPARE(builder.tessellationControlShaderGraph(), newValue);
153 QCOMPARE(spy.count(), 0);
154 }
155 {
156 // WHEN
157 QSignalSpy spy(&builder, SIGNAL(tessellationEvaluationShaderGraphChanged(QUrl)));
158 const auto newValue = QUrl::fromEncoded(url: "qrc:/tesseval.json");
159 builder.setTessellationEvaluationShaderGraph(newValue);
160
161 // THEN
162 QVERIFY(spy.isValid());
163 QCOMPARE(builder.tessellationEvaluationShaderGraph(), newValue);
164 QCOMPARE(spy.count(), 1);
165
166 // WHEN
167 spy.clear();
168 builder.setTessellationEvaluationShaderGraph(newValue);
169
170 // THEN
171 QCOMPARE(builder.tessellationEvaluationShaderGraph(), newValue);
172 QCOMPARE(spy.count(), 0);
173 }
174 {
175 // WHEN
176 QSignalSpy spy(&builder, SIGNAL(geometryShaderGraphChanged(QUrl)));
177 const auto newValue = QUrl::fromEncoded(url: "qrc:/geometry.json");
178 builder.setGeometryShaderGraph(newValue);
179
180 // THEN
181 QVERIFY(spy.isValid());
182 QCOMPARE(builder.geometryShaderGraph(), newValue);
183 QCOMPARE(spy.count(), 1);
184
185 // WHEN
186 spy.clear();
187 builder.setGeometryShaderGraph(newValue);
188
189 // THEN
190 QCOMPARE(builder.geometryShaderGraph(), newValue);
191 QCOMPARE(spy.count(), 0);
192 }
193 {
194 // WHEN
195 QSignalSpy spy(&builder, SIGNAL(fragmentShaderGraphChanged(QUrl)));
196 const auto newValue = QUrl::fromEncoded(url: "qrc:/fragment.json");
197 builder.setFragmentShaderGraph(newValue);
198
199 // THEN
200 QVERIFY(spy.isValid());
201 QCOMPARE(builder.fragmentShaderGraph(), newValue);
202 QCOMPARE(spy.count(), 1);
203
204 // WHEN
205 spy.clear();
206 builder.setFragmentShaderGraph(newValue);
207
208 // THEN
209 QCOMPARE(builder.fragmentShaderGraph(), newValue);
210 QCOMPARE(spy.count(), 0);
211 }
212 {
213 // WHEN
214 QSignalSpy spy(&builder, SIGNAL(computeShaderGraphChanged(QUrl)));
215 const auto newValue = QUrl::fromEncoded(url: "qrc:/compute.json");
216 builder.setComputeShaderGraph(newValue);
217
218 // THEN
219 QVERIFY(spy.isValid());
220 QCOMPARE(builder.computeShaderGraph(), newValue);
221 QCOMPARE(spy.count(), 1);
222
223 // WHEN
224 spy.clear();
225 builder.setComputeShaderGraph(newValue);
226
227 // THEN
228 QCOMPARE(builder.computeShaderGraph(), newValue);
229 QCOMPARE(spy.count(), 0);
230 }
231 }
232
233 void checkShaderProgramBookkeeping()
234 {
235 // GIVEN
236 QScopedPointer<Qt3DRender::QShaderProgramBuilder> builder(new Qt3DRender::QShaderProgramBuilder);
237 {
238 // WHEN
239 Qt3DRender::QShaderProgram program;
240 builder->setShaderProgram(&program);
241
242 // THEN
243 QCOMPARE(program.parent(), builder.data());
244 QCOMPARE(builder->shaderProgram(), &program);
245 }
246 // THEN (Should not crash and effect be unset)
247 QVERIFY(!builder->shaderProgram());
248
249 {
250 // WHEN
251 Qt3DRender::QShaderProgramBuilder someOtherBuilder;
252 QScopedPointer<Qt3DRender::QShaderProgram> program(new Qt3DRender::QShaderProgram(&someOtherBuilder));
253 builder->setShaderProgram(program.data());
254
255 // THEN
256 QCOMPARE(program->parent(), &someOtherBuilder);
257 QCOMPARE(builder->shaderProgram(), program.data());
258
259 // WHEN
260 builder.reset();
261 program.reset();
262
263 // THEN Should not crash when the effect is destroyed (tests for failed removal of destruction helper)
264 }
265 }
266
267 void checkCreationData()
268 {
269 // GIVEN
270 Qt3DRender::QShaderProgramBuilder builder;
271
272 builder.setShaderProgram(new Qt3DRender::QShaderProgram(&builder));
273 builder.setEnabledLayers({"foo", "bar"});
274 builder.setVertexShaderGraph(QUrl::fromEncoded(url: "qrc:/vertex.json"));
275 builder.setTessellationControlShaderGraph(QUrl::fromEncoded(url: "qrc:/tesscontrol.json"));
276 builder.setTessellationEvaluationShaderGraph(QUrl::fromEncoded(url: "qrc:/tesseval.json"));
277 builder.setGeometryShaderGraph(QUrl::fromEncoded(url: "qrc:/geometry.json"));
278 builder.setFragmentShaderGraph(QUrl::fromEncoded(url: "qrc:/fragment.json"));
279 builder.setComputeShaderGraph(QUrl::fromEncoded(url: "qrc:/compute.json"));
280
281 // WHEN
282 QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
283
284 {
285 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&builder);
286 creationChanges = creationChangeGenerator.creationChanges();
287 }
288
289 // THEN
290 {
291 QCOMPARE(creationChanges.size(), 2); // second one is for the shader program child
292
293 const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QShaderProgramBuilderData>>(src: creationChanges.first());
294 const Qt3DRender::QShaderProgramBuilderData cloneData = creationChangeData->data;
295
296 QCOMPARE(builder.shaderProgram()->id(), cloneData.shaderProgramId);
297 QCOMPARE(builder.enabledLayers(), cloneData.enabledLayers);
298 QCOMPARE(builder.vertexShaderGraph(), cloneData.vertexShaderGraph);
299 QCOMPARE(builder.tessellationControlShaderGraph(), cloneData.tessellationControlShaderGraph);
300 QCOMPARE(builder.tessellationEvaluationShaderGraph(), cloneData.tessellationEvaluationShaderGraph);
301 QCOMPARE(builder.geometryShaderGraph(), cloneData.geometryShaderGraph);
302 QCOMPARE(builder.fragmentShaderGraph(), cloneData.fragmentShaderGraph);
303 QCOMPARE(builder.computeShaderGraph(), cloneData.computeShaderGraph);
304 QCOMPARE(builder.id(), creationChangeData->subjectId());
305 QCOMPARE(builder.isEnabled(), true);
306 QCOMPARE(builder.isEnabled(), creationChangeData->isNodeEnabled());
307 QCOMPARE(builder.metaObject(), creationChangeData->metaObject());
308 }
309
310 // WHEN
311 builder.setEnabled(false);
312
313 {
314 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&builder);
315 creationChanges = creationChangeGenerator.creationChanges();
316 }
317
318 // THEN
319 {
320 QCOMPARE(creationChanges.size(), 2); // second one is for the shader program child
321
322 const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QShaderProgramBuilderData>>(src: creationChanges.first());
323 const Qt3DRender::QShaderProgramBuilderData cloneData = creationChangeData->data;
324
325 QCOMPARE(builder.shaderProgram()->id(), cloneData.shaderProgramId);
326 QCOMPARE(builder.enabledLayers(), cloneData.enabledLayers);
327 QCOMPARE(builder.vertexShaderGraph(), cloneData.vertexShaderGraph);
328 QCOMPARE(builder.tessellationControlShaderGraph(), cloneData.tessellationControlShaderGraph);
329 QCOMPARE(builder.tessellationEvaluationShaderGraph(), cloneData.tessellationEvaluationShaderGraph);
330 QCOMPARE(builder.geometryShaderGraph(), cloneData.geometryShaderGraph);
331 QCOMPARE(builder.fragmentShaderGraph(), cloneData.fragmentShaderGraph);
332 QCOMPARE(builder.computeShaderGraph(), cloneData.computeShaderGraph);
333 QCOMPARE(builder.id(), creationChangeData->subjectId());
334 QCOMPARE(builder.isEnabled(), false);
335 QCOMPARE(builder.isEnabled(), creationChangeData->isNodeEnabled());
336 QCOMPARE(builder.metaObject(), creationChangeData->metaObject());
337 }
338 }
339
340 void checkShaderProgramUpdate()
341 {
342 // GIVEN
343 TestArbiter arbiter;
344 Qt3DRender::QShaderProgramBuilder builder;
345 arbiter.setArbiterOnNode(&builder);
346 auto program = new Qt3DRender::QShaderProgram(&builder);
347
348 {
349 // WHEN
350 builder.setShaderProgram(program);
351 QCoreApplication::processEvents();
352
353 // THEN
354 QCOMPARE(arbiter.events.size(), 0);
355 QCOMPARE(arbiter.dirtyNodes.size(), 1);
356 QCOMPARE(arbiter.dirtyNodes.front(), &builder);
357
358 arbiter.dirtyNodes.clear();
359 }
360
361 {
362 // WHEN
363 builder.setShaderProgram(program);
364 QCoreApplication::processEvents();
365
366 // THEN
367 QCOMPARE(arbiter.events.size(), 0);
368 QCOMPARE(arbiter.dirtyNodes.size(), 0);
369 }
370 }
371
372 void checkEnabledLayersUpdate()
373 {
374 // GIVEN
375 TestArbiter arbiter;
376 Qt3DRender::QShaderProgramBuilder builder;
377 arbiter.setArbiterOnNode(&builder);
378 const auto layers = QStringList() << "foo" << "bar";
379
380 {
381 // WHEN
382 builder.setEnabledLayers(layers);
383 QCoreApplication::processEvents();
384
385 // THEN
386 QCOMPARE(arbiter.events.size(), 0);
387 QCOMPARE(arbiter.dirtyNodes.size(), 1);
388 QCOMPARE(arbiter.dirtyNodes.front(), &builder);
389
390 arbiter.dirtyNodes.clear();
391 }
392
393 {
394 // WHEN
395 builder.setEnabledLayers(layers);
396 QCoreApplication::processEvents();
397
398 // THEN
399 QCOMPARE(arbiter.events.size(), 0);
400 QCOMPARE(arbiter.dirtyNodes.size(), 0);
401 }
402 }
403
404 void checkVertexShaderGraphUpdate()
405 {
406 // GIVEN
407 TestArbiter arbiter;
408 Qt3DRender::QShaderProgramBuilder builder;
409 arbiter.setArbiterOnNode(&builder);
410
411 {
412 // WHEN
413 builder.setVertexShaderGraph(QUrl::fromEncoded(url: "qrc:/vertex.json"));
414 QCoreApplication::processEvents();
415
416 // THEN
417 QCOMPARE(arbiter.events.size(), 0);
418 QCOMPARE(arbiter.dirtyNodes.size(), 1);
419 QCOMPARE(arbiter.dirtyNodes.front(), &builder);
420
421 arbiter.dirtyNodes.clear();
422 }
423
424 {
425 // WHEN
426 builder.setVertexShaderGraph(QUrl::fromEncoded(url: "qrc:/vertex.json"));
427 QCoreApplication::processEvents();
428
429 // THEN
430 QCOMPARE(arbiter.events.size(), 0);
431 QCOMPARE(arbiter.dirtyNodes.size(), 0);
432 }
433
434 }
435
436 void checkTessellationControlShaderGraphUpdate()
437 {
438 // GIVEN
439 TestArbiter arbiter;
440 Qt3DRender::QShaderProgramBuilder builder;
441 arbiter.setArbiterOnNode(&builder);
442
443 {
444 // WHEN
445 builder.setTessellationControlShaderGraph(QUrl::fromEncoded(url: "qrc:/tesscontrol.json"));
446 QCoreApplication::processEvents();
447
448 // THEN
449 QCOMPARE(arbiter.events.size(), 0);
450 QCOMPARE(arbiter.dirtyNodes.size(), 1);
451 QCOMPARE(arbiter.dirtyNodes.front(), &builder);
452
453 arbiter.dirtyNodes.clear();
454 }
455
456 {
457 // WHEN
458 builder.setTessellationControlShaderGraph(QUrl::fromEncoded(url: "qrc:/tesscontrol.json"));
459 QCoreApplication::processEvents();
460
461 // THEN
462 QCOMPARE(arbiter.events.size(), 0);
463 QCOMPARE(arbiter.dirtyNodes.size(), 0);
464 }
465
466 }
467
468 void checkTessellationEvaluationShaderGraphUpdate()
469 {
470 // GIVEN
471 TestArbiter arbiter;
472 Qt3DRender::QShaderProgramBuilder builder;
473 arbiter.setArbiterOnNode(&builder);
474
475 {
476 // WHEN
477 builder.setTessellationEvaluationShaderGraph(QUrl::fromEncoded(url: "qrc:/tesseval.json"));
478 QCoreApplication::processEvents();
479
480 // THEN
481 QCOMPARE(arbiter.events.size(), 0);
482 QCOMPARE(arbiter.dirtyNodes.size(), 1);
483 QCOMPARE(arbiter.dirtyNodes.front(), &builder);
484
485 arbiter.dirtyNodes.clear();
486 }
487
488 {
489 // WHEN
490 builder.setTessellationEvaluationShaderGraph(QUrl::fromEncoded(url: "qrc:/tesseval.json"));
491 QCoreApplication::processEvents();
492
493 // THEN
494 QCOMPARE(arbiter.events.size(), 0);
495 QCOMPARE(arbiter.dirtyNodes.size(), 0);
496 }
497
498 }
499
500 void checkGeometryShaderGraphUpdate()
501 {
502 // GIVEN
503 TestArbiter arbiter;
504 Qt3DRender::QShaderProgramBuilder builder;
505 arbiter.setArbiterOnNode(&builder);
506
507 {
508 // WHEN
509 builder.setGeometryShaderGraph(QUrl::fromEncoded(url: "qrc:/geometry.json"));
510 QCoreApplication::processEvents();
511
512 // THEN
513 QCOMPARE(arbiter.events.size(), 0);
514 QCOMPARE(arbiter.dirtyNodes.size(), 1);
515 QCOMPARE(arbiter.dirtyNodes.front(), &builder);
516
517 arbiter.dirtyNodes.clear();
518 }
519
520 {
521 // WHEN
522 builder.setGeometryShaderGraph(QUrl::fromEncoded(url: "qrc:/geometry.json"));
523 QCoreApplication::processEvents();
524
525 // THEN
526 QCOMPARE(arbiter.events.size(), 0);
527 QCOMPARE(arbiter.dirtyNodes.size(), 0);
528 }
529
530 }
531
532 void checkFragmentShaderGraphUpdate()
533 {
534 // GIVEN
535 TestArbiter arbiter;
536 Qt3DRender::QShaderProgramBuilder builder;
537 arbiter.setArbiterOnNode(&builder);
538
539 {
540 // WHEN
541 builder.setFragmentShaderGraph(QUrl::fromEncoded(url: "qrc:/fragment.json"));
542 QCoreApplication::processEvents();
543
544 // THEN
545 QCOMPARE(arbiter.events.size(), 0);
546 QCOMPARE(arbiter.dirtyNodes.size(), 1);
547 QCOMPARE(arbiter.dirtyNodes.front(), &builder);
548
549 arbiter.dirtyNodes.clear();
550 }
551
552 {
553 // WHEN
554 builder.setFragmentShaderGraph(QUrl::fromEncoded(url: "qrc:/fragment.json"));
555 QCoreApplication::processEvents();
556
557 // THEN
558 QCOMPARE(arbiter.events.size(), 0);
559 QCOMPARE(arbiter.dirtyNodes.size(), 0);
560 }
561
562 }
563
564 void checkComputeShaderGraphUpdate()
565 {
566 // GIVEN
567 TestArbiter arbiter;
568 Qt3DRender::QShaderProgramBuilder builder;
569 arbiter.setArbiterOnNode(&builder);
570
571 {
572 // WHEN
573 builder.setComputeShaderGraph(QUrl::fromEncoded(url: "qrc:/compute.json"));
574 QCoreApplication::processEvents();
575
576 // THEN
577 QCOMPARE(arbiter.events.size(), 0);
578 QCOMPARE(arbiter.dirtyNodes.size(), 1);
579 QCOMPARE(arbiter.dirtyNodes.front(), &builder);
580
581 arbiter.dirtyNodes.clear();
582 }
583
584 {
585 // WHEN
586 builder.setComputeShaderGraph(QUrl::fromEncoded(url: "qrc:/compute.json"));
587 QCoreApplication::processEvents();
588
589 // THEN
590 QCOMPARE(arbiter.events.size(), 0);
591 QCOMPARE(arbiter.dirtyNodes.size(), 0);
592 }
593 }
594
595 void checkGeneratedCodePropertyUpdates()
596 {
597 Qt3DRender::QShaderProgramBuilderPrivate *dBuilder = static_cast<decltype(dBuilder)>(Qt3DCore::QNodePrivate::get(q: this));
598 {
599 // WHEN
600 QSignalSpy spy(this, SIGNAL(vertexShaderCodeChanged(QByteArray)));
601 dBuilder->setShaderCode(QByteArrayLiteral("vertex"), type: Qt3DRender::QShaderProgram::Vertex);
602
603 // THEN
604 QVERIFY(spy.isValid());
605 QCOMPARE(spy.count(), 1);
606 QCOMPARE(vertexShaderCode(), QByteArrayLiteral("vertex"));
607 }
608 {
609 // WHEN
610 QSignalSpy spy(this, SIGNAL(fragmentShaderCodeChanged(QByteArray)));
611 dBuilder->setShaderCode(QByteArrayLiteral("fragment"), type: Qt3DRender::QShaderProgram::Fragment);
612
613 // THEN
614 QVERIFY(spy.isValid());
615 QCOMPARE(spy.count(), 1);
616 QCOMPARE(fragmentShaderCode(), QByteArrayLiteral("fragment"));
617 }
618 {
619 // WHEN
620 QSignalSpy spy(this, SIGNAL(geometryShaderCodeChanged(QByteArray)));
621 dBuilder->setShaderCode(QByteArrayLiteral("geometry"), type: Qt3DRender::QShaderProgram::Geometry);
622
623 // THEN
624 QVERIFY(spy.isValid());
625 QCOMPARE(spy.count(), 1);
626 QCOMPARE(geometryShaderCode(), QByteArrayLiteral("geometry"));
627 }
628 {
629 // WHEN
630 QSignalSpy spy(this, SIGNAL(computeShaderCodeChanged(QByteArray)));
631 dBuilder->setShaderCode(QByteArrayLiteral("compute"), type: Qt3DRender::QShaderProgram::Compute);
632
633
634 // THEN
635 QVERIFY(spy.isValid());
636 QCOMPARE(spy.count(), 1);
637 QCOMPARE(computeShaderCode(), QByteArrayLiteral("compute"));
638 }
639 {
640 // WHEN
641 QSignalSpy spy(this, SIGNAL(tessellationControlShaderCodeChanged(QByteArray)));
642 dBuilder->setShaderCode(QByteArrayLiteral("control"), type: Qt3DRender::QShaderProgram::TessellationControl);
643
644 // THEN
645 QVERIFY(spy.isValid());
646 QCOMPARE(spy.count(), 1);
647 QCOMPARE(tessellationControlShaderCode(), QByteArrayLiteral("control"));
648 }
649 {
650 // WHEN
651 QSignalSpy spy(this, SIGNAL(tessellationEvaluationShaderCodeChanged(QByteArray)));
652 dBuilder->setShaderCode(QByteArrayLiteral("eval"), type: Qt3DRender::QShaderProgram::TessellationEvaluation);
653
654 // THEN
655 QVERIFY(spy.isValid());
656 QCOMPARE(spy.count(), 1);
657 QCOMPARE(tessellationEvaluationShaderCode(), QByteArrayLiteral("eval"));
658 }
659 }
660
661};
662
663QTEST_MAIN(tst_QShaderProgramBuilder)
664
665#include "tst_qshaderprogrambuilder.moc"
666

source code of qt3d/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp