1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 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 <qbackendnodetester.h> |
31 | #include <private/qframeallocator_p.h> |
32 | #include <private/qframeallocator_p_p.h> |
33 | #include <private/memorybarrier_p.h> |
34 | #include <testpostmanarbiter.h> |
35 | #include <testrenderer.h> |
36 | #include <private/shader_p.h> |
37 | #include <Qt3DRender/qshaderprogram.h> |
38 | #include <renderview_p.h> |
39 | #include <renderviewjobutils_p.h> |
40 | #include <rendercommand_p.h> |
41 | #include <renderer_p.h> |
42 | #include <glresourcemanagers_p.h> |
43 | #include <private/shader_p.h> |
44 | |
45 | QT_BEGIN_NAMESPACE |
46 | |
47 | namespace Qt3DRender { |
48 | |
49 | namespace Render { |
50 | |
51 | namespace OpenGL { |
52 | |
53 | namespace { |
54 | |
55 | void compareShaderParameterPacks(const ShaderParameterPack &t1, |
56 | const ShaderParameterPack &t2) |
57 | { |
58 | const PackUniformHash hash1 = t1.uniforms(); |
59 | const PackUniformHash hash2 = t2.uniforms(); |
60 | |
61 | QCOMPARE(hash1.keys.size(), hash2.keys.size()); |
62 | |
63 | for (int i = 0, m = hash1.keys.size(); i < m; ++i) { |
64 | const int key = hash1.keys.at(n: i); |
65 | QCOMPARE(hash1.value(key), hash2.value(key)); |
66 | } |
67 | } |
68 | |
69 | } // anonymous |
70 | |
71 | class tst_RenderViews : public Qt3DCore::QBackendNodeTester |
72 | { |
73 | Q_OBJECT |
74 | |
75 | private Q_SLOTS: |
76 | |
77 | void checkRenderViewSizeFitsWithAllocator() |
78 | { |
79 | QSKIP("Allocated Disabled" ); |
80 | QVERIFY(sizeof(RenderView) <= 192); |
81 | } |
82 | |
83 | void checkRenderViewInitialState() |
84 | { |
85 | // GIVEN |
86 | RenderView renderView; |
87 | |
88 | // THEN |
89 | QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None); |
90 | } |
91 | |
92 | void checkMemoryBarrierInitialization() |
93 | { |
94 | // GIVEN |
95 | RenderView renderView; |
96 | |
97 | // THEN |
98 | QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None); |
99 | |
100 | // WHEN |
101 | const QMemoryBarrier::Operations barriers(QMemoryBarrier::BufferUpdate|QMemoryBarrier::ShaderImageAccess); |
102 | renderView.setMemoryBarrier(barriers); |
103 | |
104 | // THEN |
105 | QCOMPARE(renderView.memoryBarrier(), barriers); |
106 | } |
107 | |
108 | void checkSetRenderViewConfig() |
109 | { |
110 | TestRenderer renderer; |
111 | { |
112 | // GIVEN |
113 | const QMemoryBarrier::Operations barriers(QMemoryBarrier::AtomicCounter|QMemoryBarrier::ShaderStorage); |
114 | Qt3DRender::QMemoryBarrier frontendBarrier; |
115 | FrameGraphManager frameGraphManager; |
116 | MemoryBarrier backendBarrier; |
117 | RenderView renderView; |
118 | // setRenderViewConfigFromFrameGraphLeafNode assumes node has a manager |
119 | backendBarrier.setFrameGraphManager(&frameGraphManager); |
120 | backendBarrier.setRenderer(&renderer); |
121 | |
122 | // WHEN |
123 | frontendBarrier.setWaitOperations(barriers); |
124 | simulateInitializationSync(frontend: &frontendBarrier, backend: &backendBarrier); |
125 | |
126 | // THEN |
127 | QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None); |
128 | QCOMPARE(backendBarrier.waitOperations(), barriers); |
129 | |
130 | // WHEN |
131 | Qt3DRender::Render::OpenGL::setRenderViewConfigFromFrameGraphLeafNode(rv: &renderView, fgLeaf: &backendBarrier); |
132 | |
133 | // THEN |
134 | QCOMPARE(backendBarrier.waitOperations(), renderView.memoryBarrier()); |
135 | } |
136 | // TO DO: Complete tests for other framegraph node types |
137 | } |
138 | |
139 | void checkDoesntCrashWhenNoCommandsToSort() |
140 | { |
141 | // GIVEN |
142 | Qt3DRender::Render::NodeManagers nodeManagers; |
143 | Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); |
144 | RenderView renderView; |
145 | |
146 | renderer.setNodeManagers(&nodeManagers); |
147 | renderView.setRenderer(&renderer); |
148 | |
149 | QVector<QSortPolicy::SortType> sortTypes; |
150 | sortTypes.push_back(t: QSortPolicy::BackToFront); |
151 | |
152 | // WHEN |
153 | renderView.addSortType(sortTypes); |
154 | |
155 | EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); |
156 | renderView.setRenderCommandDataView(view); |
157 | |
158 | // THEN -> shouldn't crash |
159 | renderView.sort(); |
160 | |
161 | // RenderCommands are deleted by RenderView dtor |
162 | renderer.shutdown(); |
163 | } |
164 | |
165 | void checkRenderCommandBackToFrontSorting() |
166 | { |
167 | // GIVEN |
168 | Qt3DRender::Render::NodeManagers nodeManagers; |
169 | Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); |
170 | RenderView renderView; |
171 | std::vector<RenderCommand> rawCommands; |
172 | |
173 | QVector<QSortPolicy::SortType> sortTypes; |
174 | |
175 | renderer.setNodeManagers(&nodeManagers); |
176 | renderView.setRenderer(&renderer); |
177 | |
178 | sortTypes.push_back(t: QSortPolicy::BackToFront); |
179 | |
180 | for (int i = 0; i < 200; ++i) { |
181 | RenderCommand c; |
182 | c.m_depth = float(i); |
183 | rawCommands.push_back(x: c); |
184 | } |
185 | |
186 | // WHEN |
187 | renderView.addSortType(sortTypes); |
188 | |
189 | EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); |
190 | view->data.commands = rawCommands; |
191 | view->indices.resize(new_size: rawCommands.size()); |
192 | std::iota(first: view->indices.begin(), last: view->indices.end(), value: 0); |
193 | |
194 | renderView.setRenderCommandDataView(view); |
195 | |
196 | renderView.sort(); |
197 | |
198 | // THEN |
199 | int j = 0; |
200 | RenderCommand previousRC; |
201 | renderView.forEachCommand(func: [&] (const RenderCommand &command) { |
202 | if (j > 0) |
203 | QVERIFY(previousRC.m_depth > command.m_depth); |
204 | previousRC = command; |
205 | ++j; |
206 | }); |
207 | |
208 | // RenderCommands are deleted by RenderView dtor |
209 | renderer.shutdown(); |
210 | } |
211 | |
212 | void checkRenderCommandMaterialSorting() |
213 | { |
214 | // GIVEN |
215 | Qt3DRender::Render::NodeManagers nodeManagers; |
216 | Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); |
217 | RenderView renderView; |
218 | std::vector<RenderCommand> rawCommands; |
219 | |
220 | QVector<QSortPolicy::SortType> sortTypes; |
221 | |
222 | renderer.setNodeManagers(&nodeManagers); |
223 | renderView.setRenderer(&renderer); |
224 | |
225 | sortTypes.push_back(t: QSortPolicy::Material); |
226 | |
227 | GLShader *dnas[5] = { |
228 | reinterpret_cast<GLShader *>(0x250), |
229 | reinterpret_cast<GLShader *>(0x500), |
230 | reinterpret_cast<GLShader *>(0x1000), |
231 | reinterpret_cast<GLShader *>(0x1500), |
232 | reinterpret_cast<GLShader *>(0x2000) |
233 | }; |
234 | |
235 | for (int i = 0; i < 20; ++i) { |
236 | RenderCommand c; |
237 | c.m_glShader = dnas[i % 5]; |
238 | rawCommands.push_back(x: c); |
239 | } |
240 | |
241 | // WHEN |
242 | renderView.addSortType(sortTypes); |
243 | |
244 | EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); |
245 | view->data.commands = rawCommands; |
246 | view->indices.resize(new_size: rawCommands.size()); |
247 | std::iota(first: view->indices.begin(), last: view->indices.end(), value: 0); |
248 | |
249 | renderView.setRenderCommandDataView(view); |
250 | |
251 | renderView.sort(); |
252 | |
253 | // THEN |
254 | int j = 0; |
255 | GLShader *targetShader; |
256 | RenderCommand previousRC; |
257 | |
258 | renderView.forEachCommand(func: [&] (const RenderCommand &command) { |
259 | if (j % 4 == 0) { |
260 | targetShader = command.m_glShader; |
261 | if (j > 0) |
262 | QVERIFY(targetShader != previousRC.m_glShader); |
263 | } |
264 | QCOMPARE(targetShader, command.m_glShader); |
265 | previousRC = command; |
266 | ++j; |
267 | }); |
268 | |
269 | // RenderCommands are deleted by RenderView dtor |
270 | renderer.shutdown(); |
271 | } |
272 | |
273 | void checkRenderViewUniformMinification_data() |
274 | { |
275 | QTest::addColumn<QVector<QShaderProgram*>>(name: "shaders" ); |
276 | QTest::addColumn<QVector<ShaderParameterPack>>(name: "rawParameters" ); |
277 | QTest::addColumn<QVector<ShaderParameterPack>>(name: "expectedMinimizedParameters" ); |
278 | |
279 | Qt3DCore::QNodeId fakeTextureNodeId = Qt3DCore::QNodeId::createId(); |
280 | |
281 | ShaderParameterPack pack1; |
282 | pack1.setUniform(glslNameId: 1, val: UniformValue(883)); |
283 | pack1.setUniform(glslNameId: 2, val: UniformValue(1584.0f)); |
284 | pack1.setTexture(glslNameId: 3, uniformArrayIndex: 0, id: fakeTextureNodeId); |
285 | |
286 | QShaderProgram *shader1 = new QShaderProgram(); |
287 | QShaderProgram *shader2 = new QShaderProgram(); |
288 | |
289 | shader1->setShaderCode(type: QShaderProgram::Vertex, QByteArrayLiteral("1" )); |
290 | shader2->setShaderCode(type: QShaderProgram::Vertex, QByteArrayLiteral("2" )); |
291 | |
292 | ShaderParameterPack minifiedPack1; |
293 | |
294 | QTest::newRow(dataTag: "NoMinification" ) |
295 | << (QVector<QShaderProgram*>() << shader1 << shader2) |
296 | << (QVector<ShaderParameterPack>() << pack1 << pack1) |
297 | << (QVector<ShaderParameterPack>() << pack1 << pack1); |
298 | |
299 | QTest::newRow(dataTag: "SingleShaderMinified" ) |
300 | << (QVector<QShaderProgram*>() << shader1 << shader1 << shader1) |
301 | << (QVector<ShaderParameterPack>() << pack1 << pack1 << pack1) |
302 | << (QVector<ShaderParameterPack>() << pack1 << minifiedPack1 << minifiedPack1); |
303 | |
304 | QTest::newRow(dataTag: "MultipleShadersMinified" ) |
305 | << (QVector<QShaderProgram*>() << shader1 << shader1 << shader1 << shader2 << shader2 << shader2) |
306 | << (QVector<ShaderParameterPack>() << pack1 << pack1 << pack1 << pack1 << pack1 << pack1) |
307 | << (QVector<ShaderParameterPack>() << pack1 << minifiedPack1 << minifiedPack1 << pack1 << minifiedPack1 << minifiedPack1); |
308 | } |
309 | |
310 | void checkRenderViewUniformMinification() |
311 | { |
312 | QFETCH(QVector<QShaderProgram*>, shaders); |
313 | QFETCH(QVector<ShaderParameterPack>, rawParameters); |
314 | QFETCH(QVector<ShaderParameterPack>, expectedMinimizedParameters); |
315 | |
316 | Qt3DRender::Render::NodeManagers nodeManagers; |
317 | Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); |
318 | renderer.setNodeManagers(&nodeManagers); |
319 | |
320 | GLShaderManager *shaderManager = renderer.glResourceManagers()->glShaderManager(); |
321 | for (int i = 0, m = shaders.size(); i < m; ++i) { |
322 | Shader* backend = new Shader(); |
323 | backend->setRenderer(&renderer); |
324 | simulateInitializationSync(frontend: shaders.at(i), backend); |
325 | shaderManager->createOrAdoptExisting(shader: backend); |
326 | } |
327 | |
328 | RenderView renderView; |
329 | std::vector<RenderCommand> rawCommands; |
330 | |
331 | renderView.setRenderer(&renderer); |
332 | |
333 | for (int i = 0, m = shaders.size(); i < m; ++i) { |
334 | RenderCommand c; |
335 | c.m_shaderId = shaders.at(i)->id(); |
336 | c.m_glShader = shaderManager->lookupResource(shaderId: c.m_shaderId); |
337 | c.m_parameterPack = rawParameters.at(i); |
338 | rawCommands.push_back(x: c); |
339 | } |
340 | |
341 | // WHEN |
342 | renderView.addSortType(sortTypes: (QVector<QSortPolicy::SortType>() << QSortPolicy::Uniform)); |
343 | |
344 | EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); |
345 | view->data.commands = rawCommands; |
346 | view->indices.resize(new_size: rawCommands.size()); |
347 | std::iota(first: view->indices.begin(), last: view->indices.end(), value: 0); |
348 | |
349 | renderView.setRenderCommandDataView(view); |
350 | |
351 | renderView.sort(); |
352 | |
353 | // THEN |
354 | int j = 0; |
355 | renderView.forEachCommand(func: [&] (const RenderCommand &command) { |
356 | QCOMPARE(command.m_shaderId, shaders.at(j)->id()); |
357 | compareShaderParameterPacks(t1: command.m_parameterPack, t2: expectedMinimizedParameters.at(i: j)); |
358 | ++j; |
359 | }); |
360 | |
361 | renderer.shutdown(); |
362 | } |
363 | |
364 | |
365 | void checkRenderCommandFrontToBackSorting() |
366 | { |
367 | // GIVEN |
368 | Qt3DRender::Render::NodeManagers nodeManagers; |
369 | Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); |
370 | RenderView renderView; |
371 | std::vector<RenderCommand> rawCommands; |
372 | |
373 | QVector<QSortPolicy::SortType> sortTypes; |
374 | |
375 | renderer.setNodeManagers(&nodeManagers); |
376 | renderView.setRenderer(&renderer); |
377 | |
378 | sortTypes.push_back(t: QSortPolicy::FrontToBack); |
379 | |
380 | for (int i = 0; i < 200; ++i) { |
381 | RenderCommand c; |
382 | c.m_depth = float(i); |
383 | rawCommands.push_back(x: c); |
384 | } |
385 | |
386 | // WHEN |
387 | renderView.addSortType(sortTypes); |
388 | |
389 | EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); |
390 | view->data.commands = rawCommands; |
391 | view->indices.resize(new_size: rawCommands.size()); |
392 | std::iota(first: view->indices.begin(), last: view->indices.end(), value: 0); |
393 | |
394 | renderView.setRenderCommandDataView(view); |
395 | |
396 | renderView.sort(); |
397 | |
398 | // THEN |
399 | int j = 0; |
400 | RenderCommand previousRC; |
401 | renderView.forEachCommand(func: [&] (const RenderCommand &command) { |
402 | if (j > 0) |
403 | QVERIFY(previousRC.m_depth < command.m_depth); |
404 | previousRC = command; |
405 | ++j; |
406 | }); |
407 | |
408 | // RenderCommands are deleted by RenderView dtor |
409 | renderer.shutdown(); |
410 | } |
411 | |
412 | void checkRenderCommandStateCostSorting() |
413 | { |
414 | // GIVEN |
415 | Qt3DRender::Render::NodeManagers nodeManagers; |
416 | Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); |
417 | RenderView renderView; |
418 | std::vector<RenderCommand> rawCommands; |
419 | |
420 | QVector<QSortPolicy::SortType> sortTypes; |
421 | |
422 | renderer.setNodeManagers(&nodeManagers); |
423 | renderView.setRenderer(&renderer); |
424 | |
425 | sortTypes.push_back(t: QSortPolicy::StateChangeCost); |
426 | |
427 | for (int i = 0; i < 200; ++i) { |
428 | RenderCommand c; |
429 | c.m_changeCost = i; |
430 | rawCommands.push_back(x: c); |
431 | } |
432 | |
433 | // WHEN |
434 | renderView.addSortType(sortTypes); |
435 | |
436 | EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); |
437 | view->data.commands = rawCommands; |
438 | view->indices.resize(new_size: rawCommands.size()); |
439 | std::iota(first: view->indices.begin(), last: view->indices.end(), value: 0); |
440 | |
441 | renderView.setRenderCommandDataView(view); |
442 | |
443 | renderView.sort(); |
444 | |
445 | // THEN |
446 | int j = 0; |
447 | RenderCommand previousRC; |
448 | renderView.forEachCommand(func: [&] (const RenderCommand &command) { |
449 | if (j > 0) |
450 | QVERIFY(previousRC.m_changeCost > command.m_changeCost); |
451 | previousRC = command; |
452 | ++j; |
453 | }); |
454 | |
455 | |
456 | // RenderCommands are deleted by RenderView dtor |
457 | renderer.shutdown(); |
458 | } |
459 | |
460 | void checkRenderCommandCombinedStateMaterialDepthSorting() |
461 | { |
462 | // GIVEN |
463 | Qt3DRender::Render::NodeManagers nodeManagers; |
464 | Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); |
465 | RenderView renderView; |
466 | std::vector<RenderCommand> rawCommands; |
467 | |
468 | QVector<QSortPolicy::SortType> sortTypes; |
469 | |
470 | renderer.setNodeManagers(&nodeManagers); |
471 | renderView.setRenderer(&renderer); |
472 | |
473 | sortTypes.push_back(t: QSortPolicy::StateChangeCost); |
474 | sortTypes.push_back(t: QSortPolicy::Material); |
475 | sortTypes.push_back(t: QSortPolicy::BackToFront); |
476 | |
477 | GLShader *dna[5] = { |
478 | reinterpret_cast<GLShader *>(0x250), |
479 | reinterpret_cast<GLShader *>(0x500), |
480 | reinterpret_cast<GLShader *>(0x1000), |
481 | reinterpret_cast<GLShader *>(0x1500), |
482 | reinterpret_cast<GLShader *>(0x2000) |
483 | }; |
484 | |
485 | float depth[3] = { |
486 | 10.0f, |
487 | 25.0f, |
488 | 30.0f |
489 | }; |
490 | |
491 | int stateChangeCost[2] = { |
492 | 100, |
493 | 200 |
494 | }; |
495 | |
496 | auto buildRC = [] (GLShader *dna, float depth, int changeCost) { |
497 | RenderCommand c; |
498 | c.m_glShader = dna; |
499 | c.m_depth = depth; |
500 | c.m_changeCost = changeCost; |
501 | return c; |
502 | }; |
503 | |
504 | RenderCommand c5 = buildRC(dna[3], depth[1], stateChangeCost[1]); |
505 | RenderCommand c3 = buildRC(dna[3], depth[0], stateChangeCost[1]); |
506 | RenderCommand c4 = buildRC(dna[2], depth[1], stateChangeCost[1]); |
507 | RenderCommand c8 = buildRC(dna[1], depth[1], stateChangeCost[1]); |
508 | RenderCommand c0 = buildRC(dna[0], depth[2], stateChangeCost[1]); |
509 | |
510 | RenderCommand c2 = buildRC(dna[2], depth[2], stateChangeCost[0]); |
511 | RenderCommand c9 = buildRC(dna[2], depth[0], stateChangeCost[0]); |
512 | RenderCommand c1 = buildRC(dna[1], depth[0], stateChangeCost[0]); |
513 | RenderCommand c7 = buildRC(dna[0], depth[2], stateChangeCost[0]); |
514 | RenderCommand c6 = buildRC(dna[0], depth[1], stateChangeCost[0]); |
515 | |
516 | rawCommands = { c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 }; |
517 | |
518 | // WHEN |
519 | renderView.addSortType(sortTypes); |
520 | |
521 | EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); |
522 | view->data.commands = rawCommands; |
523 | view->indices.resize(new_size: rawCommands.size()); |
524 | std::iota(first: view->indices.begin(), last: view->indices.end(), value: 0); |
525 | |
526 | renderView.setRenderCommandDataView(view); |
527 | |
528 | |
529 | renderView.sort(); |
530 | |
531 | // THEN |
532 | const std::vector<RenderCommand> &sortedCommands = view->data.commands; |
533 | const std::vector<size_t> &sortedCommandIndices = view->indices; |
534 | QCOMPARE(rawCommands.size(), sortedCommands.size()); |
535 | |
536 | // Ordered by higher state, higher shaderDNA and higher depth |
537 | QCOMPARE(c0, sortedCommands.at(sortedCommandIndices[4])); |
538 | QCOMPARE(c3, sortedCommands.at(sortedCommandIndices[1])); |
539 | QCOMPARE(c4, sortedCommands.at(sortedCommandIndices[2])); |
540 | QCOMPARE(c5, sortedCommands.at(sortedCommandIndices[0])); |
541 | QCOMPARE(c8, sortedCommands.at(sortedCommandIndices[3])); |
542 | |
543 | QCOMPARE(c1, sortedCommands.at(sortedCommandIndices[7])); |
544 | QCOMPARE(c2, sortedCommands.at(sortedCommandIndices[5])); |
545 | QCOMPARE(c6, sortedCommands.at(sortedCommandIndices[9])); |
546 | QCOMPARE(c7, sortedCommands.at(sortedCommandIndices[8])); |
547 | QCOMPARE(c9, sortedCommands.at(sortedCommandIndices[6])); |
548 | |
549 | // RenderCommands are deleted by RenderView dtor |
550 | renderer.shutdown(); |
551 | } |
552 | |
553 | void checkRenderCommandTextureSorting() |
554 | { |
555 | // GIVEN |
556 | RenderView renderView; |
557 | QVector<QSortPolicy::SortType> sortTypes; |
558 | |
559 | sortTypes.push_back(t: QSortPolicy::Texture); |
560 | |
561 | |
562 | Qt3DCore::QNodeId tex1 = Qt3DCore::QNodeId::createId(); |
563 | Qt3DCore::QNodeId tex2 = Qt3DCore::QNodeId::createId(); |
564 | Qt3DCore::QNodeId tex3 = Qt3DCore::QNodeId::createId(); |
565 | Qt3DCore::QNodeId tex4 = Qt3DCore::QNodeId::createId(); |
566 | |
567 | RenderCommand a; |
568 | { |
569 | ShaderParameterPack pack; |
570 | pack.setTexture(glslNameId: 0, uniformArrayIndex: 0, id: tex1); |
571 | pack.setTexture(glslNameId: 1, uniformArrayIndex: 0, id: tex3); |
572 | pack.setTexture(glslNameId: 2, uniformArrayIndex: 0, id: tex4); |
573 | pack.setTexture(glslNameId: 3, uniformArrayIndex: 0, id: tex2); |
574 | a.m_parameterPack = pack; |
575 | } |
576 | RenderCommand b; |
577 | RenderCommand c; |
578 | { |
579 | ShaderParameterPack pack; |
580 | pack.setTexture(glslNameId: 0, uniformArrayIndex: 0, id: tex1); |
581 | pack.setTexture(glslNameId: 3, uniformArrayIndex: 0, id: tex2); |
582 | c.m_parameterPack = pack; |
583 | } |
584 | RenderCommand d; |
585 | { |
586 | ShaderParameterPack pack; |
587 | pack.setTexture(glslNameId: 1, uniformArrayIndex: 0, id: tex3); |
588 | pack.setTexture(glslNameId: 2, uniformArrayIndex: 0, id: tex4); |
589 | d.m_parameterPack = pack; |
590 | } |
591 | RenderCommand e; |
592 | { |
593 | ShaderParameterPack pack; |
594 | pack.setTexture(glslNameId: 3, uniformArrayIndex: 0, id: tex2); |
595 | e.m_parameterPack = pack; |
596 | } |
597 | RenderCommand f; |
598 | { |
599 | ShaderParameterPack pack; |
600 | pack.setTexture(glslNameId: 3, uniformArrayIndex: 0, id: tex2); |
601 | f.m_parameterPack = pack; |
602 | } |
603 | RenderCommand g; |
604 | { |
605 | ShaderParameterPack pack; |
606 | pack.setTexture(glslNameId: 0, uniformArrayIndex: 0, id: tex1); |
607 | pack.setTexture(glslNameId: 1, uniformArrayIndex: 0, id: tex3); |
608 | pack.setTexture(glslNameId: 2, uniformArrayIndex: 0, id: tex4); |
609 | pack.setTexture(glslNameId: 3, uniformArrayIndex: 0, id: tex2); |
610 | g.m_parameterPack = pack; |
611 | } |
612 | |
613 | // WHEN |
614 | std::vector<RenderCommand> rawCommands = {a, b, c, d, e, f, g}; |
615 | renderView.addSortType(sortTypes); |
616 | |
617 | EntityRenderCommandDataViewPtr view = EntityRenderCommandDataViewPtr::create(); |
618 | view->data.commands = rawCommands; |
619 | view->indices.resize(new_size: rawCommands.size()); |
620 | std::iota(first: view->indices.begin(), last: view->indices.end(), value: 0); |
621 | |
622 | renderView.setRenderCommandDataView(view); |
623 | |
624 | renderView.sort(); |
625 | |
626 | // THEN |
627 | const std::vector<RenderCommand> &sortedCommands = view->data.commands; |
628 | const std::vector<size_t> &sortedCommandIndices = view->indices; |
629 | QCOMPARE(rawCommands.size(), sortedCommands.size()); |
630 | QCOMPARE(sortedCommands.at(sortedCommandIndices[0]), a); |
631 | QCOMPARE(sortedCommands.at(sortedCommandIndices[1]), g); |
632 | QCOMPARE(sortedCommands.at(sortedCommandIndices[2]), d); |
633 | QCOMPARE(sortedCommands.at(sortedCommandIndices[3]), c); |
634 | QCOMPARE(sortedCommands.at(sortedCommandIndices[4]), e); |
635 | QCOMPARE(sortedCommands.at(sortedCommandIndices[5]), f); |
636 | QCOMPARE(sortedCommands.at(sortedCommandIndices[6]), b); |
637 | // RenderCommands are deleted by RenderView dtor |
638 | } |
639 | private: |
640 | }; |
641 | |
642 | } // OpenGL |
643 | |
644 | } // Render |
645 | |
646 | } // Qt3DRender |
647 | |
648 | QT_END_NAMESPACE |
649 | |
650 | //APPLESS_ |
651 | QTEST_MAIN(Qt3DRender::Render::OpenGL::tst_RenderViews) |
652 | |
653 | #include "tst_renderviews.moc" |
654 | |