summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2019-12-18 10:14:57 +0100
committerPaul Lemire <paul.lemire@kdab.com>2019-12-18 10:15:32 +0100
commit1776037b0443dc57d59afe0772a83b1d47aced14 (patch)
tree56213eee7188e5f1d2e4abe290b3757603c835ef
parentc2ea752f684290d156c500c6a7174fe3f27fa086 (diff)
parentc754eb2883394852f155e31f5366fa25a4ffad42 (diff)
Merge branch '5.15' into dev
-rw-r--r--.qmake.conf1
-rw-r--r--dist/changes-5.13.220
-rw-r--r--dist/changes-5.14.049
-rw-r--r--examples/qt3d/advancedcustommaterial/doc/src/advancedcustommaterial.qdoc6
-rw-r--r--examples/qt3d/audio-visualizer-qml/doc/src/audio-visualizer-qml.qdoc8
-rw-r--r--examples/qt3d/planets-qml/SolarSystem.qml14
-rw-r--r--examples/qt3d/planets-qml/android/AndroidManifest.xml8
-rw-r--r--examples/qt3d/planets-qml/doc/src/planets-qml.qdoc14
-rw-r--r--examples/qt3d/planets-qml/planets.js32
-rw-r--r--examples/qt3d/simplecustommaterial/doc/src/simplecustommaterial.qdoc2
-rw-r--r--src/animation/backend/abstractevaluateclipanimatorjob.cpp5
-rw-r--r--src/animation/backend/animationclip.cpp2
-rw-r--r--src/animation/backend/buildblendtreesjob.cpp3
-rw-r--r--src/animation/backend/channelmapping.cpp7
-rw-r--r--src/animation/backend/evaluateblendclipanimatorjob.cpp1
-rw-r--r--src/animation/backend/evaluateclipanimatorjob.cpp1
-rw-r--r--src/animation/backend/findrunningclipanimatorsjob.cpp3
-rw-r--r--src/animation/backend/gltfimporter.cpp10
-rw-r--r--src/animation/backend/loadanimationclipjob.cpp1
-rw-r--r--src/animation/backend/skeleton.cpp1
-rw-r--r--src/animation/frontend/qabstractanimationclip.cpp8
-rw-r--r--src/animation/frontend/qabstractanimationclip.h3
-rw-r--r--src/animation/frontend/qabstractchannelmapping.cpp1
-rw-r--r--src/animation/frontend/qabstractclipanimator.cpp5
-rw-r--r--src/animation/frontend/qabstractclipanimator.h2
-rw-r--r--src/animation/frontend/qanimationcallback.qdoc51
-rw-r--r--src/animation/frontend/qanimationclip.cpp4
-rw-r--r--src/animation/frontend/qanimationclipdata.cpp2
-rw-r--r--src/animation/frontend/qanimationcliploader.cpp6
-rw-r--r--src/animation/frontend/qanimationcliploader.h2
-rw-r--r--src/animation/frontend/qcallbackmapping.cpp3
-rw-r--r--src/animation/frontend/qchannel.cpp2
-rw-r--r--src/animation/frontend/qchannelmapper.cpp2
-rw-r--r--src/animation/frontend/qchannelmapping.cpp2
-rw-r--r--src/animation/frontend/qclipanimator.cpp3
-rw-r--r--src/animation/frontend/qclipblendvalue.cpp4
-rw-r--r--src/animation/frontend/qmorphtarget.cpp4
-rw-r--r--src/animation/frontend/qvertexblendanimation.cpp4
-rw-r--r--src/core/aspects/aspectcommanddebugger.cpp20
-rw-r--r--src/core/aspects/aspectcommanddebugger_p.h18
-rw-r--r--src/core/aspects/aspects.pri10
-rw-r--r--src/core/aspects/qabstractaspect.cpp21
-rw-r--r--src/core/aspects/qabstractaspect.h3
-rw-r--r--src/core/aspects/qabstractaspect_p.h2
-rw-r--r--src/core/aspects/qaspectengine.cpp24
-rw-r--r--src/core/aspects/qaspectengine_p.h10
-rw-r--r--src/core/aspects/qaspectmanager.cpp106
-rw-r--r--src/core/aspects/qaspectmanager_p.h9
-rw-r--r--src/core/changes/qcomponentaddedchange.h10
-rw-r--r--src/core/changes/qcomponentremovedchange.h10
-rw-r--r--src/core/changes/qdynamicpropertyupdatedchange.h4
-rw-r--r--src/core/changes/qnodecommand.h4
-rw-r--r--src/core/changes/qnodecreatedchange.h6
-rw-r--r--src/core/changes/qnodedestroyedchange.h4
-rw-r--r--src/core/changes/qpropertynodeaddedchange.h4
-rw-r--r--src/core/changes/qpropertynoderemovedchange.h4
-rw-r--r--src/core/changes/qpropertyupdatedchange.h4
-rw-r--r--src/core/changes/qpropertyupdatedchangebase.h4
-rw-r--r--src/core/changes/qpropertyvalueaddedchange.h4
-rw-r--r--src/core/changes/qpropertyvalueaddedchangebase.h6
-rw-r--r--src/core/changes/qpropertyvalueremovedchange.h4
-rw-r--r--src/core/changes/qpropertyvalueremovedchangebase.h6
-rw-r--r--src/core/changes/qscenechange.cpp1
-rw-r--r--src/core/changes/qscenechange.h18
-rw-r--r--src/core/changes/qscenechange_p.h7
-rw-r--r--src/core/changes/qskeletoncreatedchange_p.h6
-rw-r--r--src/core/changes/qstaticpropertyupdatedchangebase.h6
-rw-r--r--src/core/changes/qstaticpropertyvalueaddedchangebase.h2
-rw-r--r--src/core/changes/qstaticpropertyvalueremovedchangebase.h2
-rw-r--r--src/core/configure.json3
-rw-r--r--src/core/jobs/qaspectjob_p.h67
-rw-r--r--src/core/jobs/qaspectjobmanager.cpp14
-rw-r--r--src/core/jobs/qaspectjobmanager_p.h4
-rw-r--r--src/core/jobs/qaspectjobproviderinterface_p.h2
-rw-r--r--src/core/jobs/qthreadpooler.cpp128
-rw-r--r--src/core/jobs/qthreadpooler_p.h17
-rw-r--r--src/core/jobs/task.cpp21
-rw-r--r--src/core/jobs/task_p.h4
-rw-r--r--src/core/nodes/qbackendnode.cpp12
-rw-r--r--src/core/nodes/qbackendnode.h12
-rw-r--r--src/core/nodes/qentity.cpp2
-rw-r--r--src/core/nodes/qnode.cpp29
-rw-r--r--src/core/nodes/qnode.h12
-rw-r--r--src/core/nodes/qnode_p.h21
-rw-r--r--src/core/qchangearbiter_p.h1
-rw-r--r--src/core/qpostman_p.h2
-rw-r--r--src/core/qscheduler.cpp16
-rw-r--r--src/core/qscheduler_p.h4
-rw-r--r--src/core/qt3dcore_global.h6
-rw-r--r--src/core/resources/qframeallocator.cpp2
-rw-r--r--src/core/resources/qloadgltf_p.h80
-rw-r--r--src/core/resources/resources.pri1
-rw-r--r--src/core/services/nullservices_p.h14
-rw-r--r--src/core/services/qservicelocator.cpp16
-rw-r--r--src/core/services/qservicelocator_p.h3
-rw-r--r--src/core/services/qsysteminformationservice.cpp302
-rw-r--r--src/core/services/qsysteminformationservice_p.h24
-rw-r--r--src/core/services/qsysteminformationservice_p_p.h87
-rw-r--r--src/core/transforms/qabstractskeleton.cpp19
-rw-r--r--src/core/transforms/qabstractskeleton.h3
-rw-r--r--src/core/transforms/qskeletonloader.cpp50
-rw-r--r--src/core/transforms/qskeletonloader_p.h1
-rw-r--r--src/core/transforms/qtransform.cpp1
-rw-r--r--src/core/transforms/qtransform.h1
-rw-r--r--src/core/transforms/sqt_p.h2
-rw-r--r--src/doc/src/qmlextramaterials.qdoc35
-rw-r--r--src/extras/defaults/qabstractspritesheet.cpp2
-rw-r--r--src/extras/defaults/qt3dwindow.cpp2
-rw-r--r--src/extras/shaders/es2/distancefieldtext.frag2
-rw-r--r--src/extras/shaders/gl3/distancefieldtext.frag2
-rw-r--r--src/extras/text/qtext2dentity.cpp13
-rw-r--r--src/input/backend/keyboardeventfilter.cpp1
-rw-r--r--src/input/backend/keyboardhandler.cpp1
-rw-r--r--src/input/backend/mouseeventfilter.cpp1
-rw-r--r--src/input/backend/mousehandler.cpp1
-rw-r--r--src/input/frontend/qabstractphysicaldeviceproxy.cpp1
-rw-r--r--src/input/frontend/qaction.cpp6
-rw-r--r--src/input/frontend/qaction.h4
-rw-r--r--src/input/frontend/qactioninput.cpp2
-rw-r--r--src/input/frontend/qaxis.cpp6
-rw-r--r--src/input/frontend/qaxis.h4
-rw-r--r--src/input/frontend/qaxisaccumulator.cpp6
-rw-r--r--src/input/frontend/qaxisaccumulator.h4
-rw-r--r--src/input/frontend/qkeyboarddevice.cpp12
-rw-r--r--src/input/frontend/qkeyboarddevice.h1
-rw-r--r--src/input/frontend/qkeyboardhandler.cpp6
-rw-r--r--src/input/frontend/qkeyboardhandler.h4
-rw-r--r--src/input/frontend/qkeyevent.cpp6
-rw-r--r--src/input/frontend/qmouseevent.cpp6
-rw-r--r--src/input/frontend/qmouseevent.h15
-rw-r--r--src/input/frontend/qmousehandler.cpp12
-rw-r--r--src/input/frontend/qmousehandler.h2
-rw-r--r--src/input/frontend/qphysicaldevicecreatedchange.cpp2
-rw-r--r--src/logic/callbackjob.cpp2
-rw-r--r--src/logic/manager.cpp2
-rw-r--r--src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp11
-rw-r--r--src/plugins/sceneparsers/gltf/gltfimporter.cpp14
-rw-r--r--src/quick3d/imports/animation/plugins.qmltypes55
-rw-r--r--src/quick3d/imports/core/plugins.qmltypes73
-rw-r--r--src/quick3d/imports/extras/plugins.qmltypes55
-rw-r--r--src/quick3d/imports/input/plugins.qmltypes2
-rw-r--r--src/quick3d/imports/logic/plugins.qmltypes2
-rw-r--r--src/quick3d/imports/render/plugins.qmltypes255
-rw-r--r--src/quick3d/imports/scene2d/plugins.qmltypes2
-rw-r--r--src/quick3d/imports/scene3d/plugins.qmltypes38
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem.cpp81
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer.cpp23
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer_p.h3
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp1
-rw-r--r--src/quick3d/imports/scene3d/scene3dview.cpp2
-rw-r--r--src/quick3d/quick3d/qquaternionanimation.cpp2
-rw-r--r--src/quick3d/quick3dextras/qt3dquickwindow.cpp2
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d.cpp6
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d.h5
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2d.cpp16
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp1
-rw-r--r--src/render/backend/abstractrenderer_p.h4
-rw-r--r--src/render/backend/bufferutils_p.h4
-rw-r--r--src/render/backend/cameralens.cpp60
-rw-r--r--src/render/backend/cameralens_p.h7
-rw-r--r--src/render/backend/commandexecuter.cpp20
-rw-r--r--src/render/backend/computecommand.cpp29
-rw-r--r--src/render/backend/computecommand_p.h3
-rw-r--r--src/render/backend/render-backend.pri13
-rw-r--r--src/render/backend/rendersettings.cpp18
-rw-r--r--src/render/backend/segmentsvisitor.cpp52
-rw-r--r--src/render/backend/stringtoint.cpp39
-rw-r--r--src/render/backend/transform.cpp1
-rw-r--r--src/render/backend/trianglesvisitor.cpp11
-rw-r--r--src/render/backend/uniform_p.h4
-rw-r--r--src/render/backend/visitorutils_p.h2
-rw-r--r--src/render/framegraph/qblitframebuffer.cpp4
-rw-r--r--src/render/framegraph/qbuffercapture.cpp12
-rw-r--r--src/render/framegraph/qrendercapture.cpp4
-rw-r--r--src/render/framegraph/qsetfence.cpp9
-rw-r--r--src/render/framegraph/qwaitfence.cpp12
-rw-r--r--src/render/framegraph/rendercapture.cpp26
-rw-r--r--src/render/framegraph/rendercapture_p.h2
-rw-r--r--src/render/framegraph/subtreeenabler.cpp18
-rw-r--r--src/render/frontend/qcamera.cpp2
-rw-r--r--src/render/frontend/qcameralens.cpp38
-rw-r--r--src/render/frontend/qcameralens_p.h21
-rw-r--r--src/render/frontend/qcomputecommand.cpp6
-rw-r--r--src/render/frontend/qlevelofdetail.cpp5
-rw-r--r--src/render/frontend/qlevelofdetail.h2
-rw-r--r--src/render/frontend/qlevelofdetailswitch.cpp6
-rw-r--r--src/render/frontend/qlevelofdetailswitch.h2
-rw-r--r--src/render/frontend/qrenderaspect.cpp18
-rw-r--r--src/render/frontend/qrenderaspect_p.h2
-rw-r--r--src/render/frontend/qrendersettings.cpp14
-rw-r--r--src/render/frontend/qrendersettings.h1
-rw-r--r--src/render/frontend/sphere.cpp48
-rw-r--r--src/render/geometry/buffer.cpp44
-rw-r--r--src/render/geometry/geometryrenderer.cpp10
-rw-r--r--src/render/geometry/gltfskeletonloader.cpp8
-rw-r--r--src/render/geometry/qbuffer.cpp40
-rw-r--r--src/render/geometry/qbuffer.h7
-rw-r--r--src/render/geometry/qbuffer_p.h2
-rw-r--r--src/render/geometry/qgeometryrenderer.cpp5
-rw-r--r--src/render/geometry/qgeometryrenderer.h2
-rw-r--r--src/render/geometry/qmesh.cpp27
-rw-r--r--src/render/geometry/qmesh.h2
-rw-r--r--src/render/geometry/skeleton.cpp2
-rw-r--r--src/render/io/qsceneloader.cpp8
-rw-r--r--src/render/io/qsceneloader.h2
-rw-r--r--src/render/io/scene.cpp4
-rw-r--r--src/render/jobs/abstractpickingjob.cpp2
-rw-r--r--src/render/jobs/calcboundingvolumejob.cpp2
-rw-r--r--src/render/jobs/calcgeometrytrianglevolumes.cpp2
-rw-r--r--src/render/jobs/computefilteredboundingvolumejob.cpp37
-rw-r--r--src/render/jobs/computefilteredboundingvolumejob_p.h4
-rw-r--r--src/render/jobs/expandboundingvolumejob.cpp6
-rw-r--r--src/render/jobs/filterentitybycomponentjob_p.h6
-rw-r--r--src/render/jobs/filterlayerentityjob.cpp2
-rw-r--r--src/render/jobs/filterproximitydistancejob.cpp6
-rw-r--r--src/render/jobs/framecleanupjob.cpp2
-rw-r--r--src/render/jobs/frustumcullingjob.cpp2
-rw-r--r--src/render/jobs/genericlambdajob_p.h4
-rw-r--r--src/render/jobs/job_common_p.h10
-rw-r--r--src/render/jobs/jobs.pri2
-rw-r--r--src/render/jobs/lightgatherer.cpp5
-rw-r--r--src/render/jobs/loadbufferjob.cpp32
-rw-r--r--src/render/jobs/loadbufferjob_p.h4
-rw-r--r--src/render/jobs/loadgeometryjob.cpp2
-rw-r--r--src/render/jobs/loadscenejob.cpp2
-rw-r--r--src/render/jobs/loadskeletonjob.cpp2
-rw-r--r--src/render/jobs/sendbuffercapturejob.cpp68
-rw-r--r--src/render/jobs/sendbuffercapturejob_p.h10
-rw-r--r--src/render/jobs/sendrendercapturejob.cpp86
-rw-r--r--src/render/jobs/sendrendercapturejob_p.h90
-rw-r--r--src/render/jobs/updateentitylayersjob.cpp2
-rw-r--r--src/render/jobs/updatemeshtrianglelistjob.cpp2
-rw-r--r--src/render/jobs/updateshaderdatatransformjob.cpp2
-rw-r--r--src/render/jobs/updateskinningpalettejob.cpp2
-rw-r--r--src/render/jobs/updatetreeenabledjob.cpp3
-rw-r--r--src/render/jobs/updateworldboundingvolumejob.cpp4
-rw-r--r--src/render/jobs/updateworldtransformjob.cpp13
-rw-r--r--src/render/lights/qdirectionallight.cpp10
-rw-r--r--src/render/lights/qenvironmentlight.cpp12
-rw-r--r--src/render/lights/qpointlight.cpp30
-rw-r--r--src/render/lights/qspotlight.cpp50
-rw-r--r--src/render/materialsystem/qshaderimage.cpp25
-rw-r--r--src/render/materialsystem/qshaderprogrambuilder.cpp5
-rw-r--r--src/render/materialsystem/qshaderprogrambuilder.h2
-rw-r--r--src/render/materialsystem/shader.cpp71
-rw-r--r--src/render/materialsystem/shader_p.h26
-rw-r--r--src/render/picking/qabstractraycaster.cpp4
-rw-r--r--src/render/picking/qobjectpicker.cpp7
-rw-r--r--src/render/picking/qobjectpicker.h4
-rw-r--r--src/render/picking/qobjectpicker_p.h1
-rw-r--r--src/render/picking/raycaster.cpp1
-rw-r--r--src/render/raycasting/qcollisionqueryresult.cpp1
-rw-r--r--src/render/raycasting/qcollisionqueryresult_p.h2
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp10
-rw-r--r--src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp28
-rw-r--r--src/render/renderers/opengl/jobs/filtercompatibletechniquejob.cpp2
-rw-r--r--src/render/renderers/opengl/jobs/jobs.pri6
-rw-r--r--src/render/renderers/opengl/jobs/materialparametergathererjob.cpp2
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp81
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h (renamed from src/render/renderers/opengl/jobs/renderviewbuilderjob_p.h)38
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp (renamed from src/render/renderers/opengl/jobs/renderviewbuilderjob.cpp)24
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h103
-rw-r--r--src/render/renderers/opengl/jobs/renderviewinitializerjob.cpp2
-rw-r--r--src/render/renderers/opengl/jobs/renderviewjobutils.cpp28
-rw-r--r--src/render/renderers/opengl/renderer/rendercommand.cpp15
-rw-r--r--src/render/renderers/opengl/renderer/rendercommand_p.h52
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp452
-rw-r--r--src/render/renderers/opengl/renderer/renderer_p.h50
-rw-r--r--src/render/renderers/opengl/renderer/renderercache_p.h13
-rw-r--r--src/render/renderers/opengl/renderer/renderview.cpp693
-rw-r--r--src/render/renderers/opengl/renderer/renderview_p.h23
-rw-r--r--src/render/renderers/opengl/renderer/renderviewbuilder.cpp586
-rw-r--r--src/render/renderers/opengl/renderer/renderviewbuilder_p.h56
-rw-r--r--src/render/renderers/opengl/renderer/shaderparameterpack.cpp1
-rw-r--r--src/render/renderers/opengl/renderer/shaderparameterpack_p.h51
-rw-r--r--src/render/renderers/opengl/textures/gltexture.cpp22
-rw-r--r--src/render/renderstates/qrastermode.cpp4
-rw-r--r--src/render/services/vsyncframeadvanceservice.cpp11
-rw-r--r--src/render/texture/qabstracttexture.cpp18
-rw-r--r--src/render/texture/qabstracttextureimage.cpp4
-rw-r--r--src/render/texture/qtexture.cpp18
-rw-r--r--src/render/texture/qtexturegenerator.cpp3
-rw-r--r--src/render/texture/texture.cpp10
-rw-r--r--tests/auto/animation/animationclip/tst_animationclip.cpp2
-rw-r--r--tests/auto/animation/animationutils/tst_animationutils.cpp4
-rw-r--r--tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp2
-rw-r--r--tests/auto/animation/channelmapping/tst_channelmapping.cpp32
-rw-r--r--tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp1
-rw-r--r--tests/auto/animation/skeleton/tst_skeleton.cpp1
-rw-r--r--tests/auto/core/core.pro4
-rw-r--r--tests/auto/core/nodes/tst_nodes.cpp106
-rw-r--r--tests/auto/core/qaspectengine/tst_qaspectengine.cpp14
-rw-r--r--tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp12
-rw-r--r--tests/auto/core/qservicelocator/tst_qservicelocator.cpp16
-rw-r--r--tests/auto/core/qskeleton/tst_qskeleton.cpp36
-rw-r--r--tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp65
-rw-r--r--tests/auto/core/threadpooler/tst_threadpooler.cpp16
-rw-r--r--tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp2
-rw-r--r--tests/auto/input/action/tst_action.cpp1
-rw-r--r--tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp2
-rw-r--r--tests/auto/input/axis/tst_axis.cpp1
-rw-r--r--tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp1
-rw-r--r--tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp2
-rw-r--r--tests/auto/input/input.pro3
-rw-r--r--tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp1
-rw-r--r--tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp2
-rw-r--r--tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp1
-rw-r--r--tests/auto/input/qaction/tst_qaction.cpp1
-rw-r--r--tests/auto/input/qaxis/tst_qaxis.cpp1
-rw-r--r--tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp1
-rw-r--r--tests/auto/input/qmouseevent/qmouseevent.pro11
-rw-r--r--tests/auto/input/qmouseevent/tst_qmouseevent.cpp93
-rw-r--r--tests/auto/render/buffer/tst_buffer.cpp60
-rw-r--r--tests/auto/render/commons/testrenderer.cpp8
-rw-r--r--tests/auto/render/commons/testrenderer.h19
-rw-r--r--tests/auto/render/computecommand/tst_computecommand.cpp137
-rw-r--r--tests/auto/render/entity/tst_entity.cpp6
-rw-r--r--tests/auto/render/objectpicker/tst_objectpicker.cpp1
-rw-r--r--tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp16
-rw-r--r--tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp2
-rw-r--r--tests/auto/render/raycaster/tst_raycaster.cpp1
-rw-r--r--tests/auto/render/render.pro1
-rw-r--r--tests/auto/render/renderer/tst_renderer.cpp119
-rw-r--r--tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp188
-rw-r--r--tests/auto/render/renderviews/tst_renderviews.cpp139
-rw-r--r--tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp27
-rw-r--r--tests/auto/render/sendrendercapturejob/sendrendercapturejob.pro12
-rw-r--r--tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp85
-rw-r--r--tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp1
-rw-r--r--tests/auto/render/skeleton/tst_skeleton.cpp85
-rw-r--r--tests/auto/render/transform/tst_transform.cpp1
-rw-r--r--tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp26
-rw-r--r--tests/auto/render/uniform/tst_uniform.cpp2
-rw-r--r--tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp2
-rw-r--r--tests/manual/compute-manual/ComputeFrameGraph.qml91
-rw-r--r--tests/manual/compute-manual/ComputeMaterial.qml118
-rw-r--r--tests/manual/compute-manual/ParticlesScene.qml200
-rw-r--r--tests/manual/compute-manual/compute-manual.pro14
-rw-r--r--tests/manual/compute-manual/compute-manual.qrc11
-rw-r--r--tests/manual/compute-manual/main.cpp66
-rw-r--r--tests/manual/compute-manual/main.qml109
-rw-r--r--tests/manual/compute-manual/particles.comp31
-rw-r--r--tests/manual/compute-manual/particles.frag33
-rw-r--r--tests/manual/compute-manual/particles.vert27
-rw-r--r--tests/manual/manual-renderloop/main.cpp211
-rw-r--r--tests/manual/manual-renderloop/manual-renderloop.pro8
-rw-r--r--tests/manual/manual.pro8
-rw-r--r--tests/manual/rendercapture-qml/main.qml2
-rw-r--r--tests/manual/scene3d-visibility/main.cpp66
-rw-r--r--tests/manual/scene3d-visibility/main.qml161
-rw-r--r--tests/manual/scene3d-visibility/scene3d-visibility.pro10
-rw-r--r--tests/manual/scene3d-visibility/scene3d-visibility.qrc5
-rw-r--r--tests/manual/sharedtexture/main.cpp3
-rw-r--r--tests/manual/sharedtexture/videoplayer.cpp28
-rw-r--r--tests/manual/sharedtexture/videoplayer.h10
-rw-r--r--tests/manual/sharedtextureqml/main.cpp3
-rw-r--r--tests/manual/subtree-enabler-qml/FrameGraph.qml100
-rw-r--r--tests/manual/subtree-enabler-qml/SimpleCamera.qml79
-rw-r--r--tests/manual/subtree-enabler-qml/main.cpp64
-rw-r--r--tests/manual/subtree-enabler-qml/main.qml110
-rw-r--r--tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro17
-rw-r--r--tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc7
-rw-r--r--tools/qgltf/qgltf.cpp42
363 files changed, 6114 insertions, 3077 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 5c79e36dd..06c7df40b 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -5,5 +5,6 @@ load(qt_build_config)
DEFINES += QT_NO_FOREACH
DEFINES += QT_NO_JAVA_STYLE_ITERATORS
+DEFINES += BUILD_QT3D_MODULE
MODULE_VERSION = 6.0.0
diff --git a/dist/changes-5.13.2 b/dist/changes-5.13.2
new file mode 100644
index 000000000..e3bb833f0
--- /dev/null
+++ b/dist/changes-5.13.2
@@ -0,0 +1,20 @@
+Qt 5.13.2 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.13.0 through 5.13.1.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.13 series is binary compatible with the 5.12.x series.
+Applications compiled for 5.12 will continue to run with 5.13.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+ - This release contains only minor code improvements.
diff --git a/dist/changes-5.14.0 b/dist/changes-5.14.0
new file mode 100644
index 000000000..442296db8
--- /dev/null
+++ b/dist/changes-5.14.0
@@ -0,0 +1,49 @@
+Qt 5.14 introduces many new features and improvements as well as bugfixes
+over the 5.13.x series. For more details, refer to the online documentation
+included in this distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.14 series is binary compatible with the 5.13.x series.
+Applications compiled for 5.13 will continue to run with 5.14.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Qt3DExtras *
+****************************************************************************
+
+ - QDistanceFieldGlyphCache:
+ * make sure the change arbiter of atlas for QText2DEntity can be set
+ when traversing node tree, and add new auto test for this.
+
+****************************************************************************
+* Qt3DRender *
+****************************************************************************
+
+ - QNoPicking: control picking execution in the FrameGraph
+ - Textures: internal data sharing removed
+ - QSortPolicy can now sort by Texture
+ - QPickEvent adds property for picked entity
+
+ - QImageTextureDataFunctor:
+ * return a invalid image data when url is invalid to ensure the property
+ of GLTexture will not be set to NoFormat
+
+****************************************************************************
+* UNSPECIFIED *
+****************************************************************************
+
+ - Add basic support for KTX container format.
+ - Add worldMatrix property on QTransform
+ - Added SubtreeEnabler to allow easing enabling
+ and disabling of frame graph subtrees.
+ - [QTBUG-74977] Scene3D add compositingMode property. Allows underlay
+ rendering.
+ - Introduce Scene3DView to render multiple distinct 3D scenes
diff --git a/examples/qt3d/advancedcustommaterial/doc/src/advancedcustommaterial.qdoc b/examples/qt3d/advancedcustommaterial/doc/src/advancedcustommaterial.qdoc
index 377bb952c..d845fa8da 100644
--- a/examples/qt3d/advancedcustommaterial/doc/src/advancedcustommaterial.qdoc
+++ b/examples/qt3d/advancedcustommaterial/doc/src/advancedcustommaterial.qdoc
@@ -42,7 +42,7 @@
Advanced custom material example shows more complex shaders, and demonstrates controlling your
shader properties with QtQuick user interface and Animation. Water is a 3D mesh, that is
modeled and uv mapped inside Blender, and then brought into Scene 3D as an \c {.obj} file.
- Shader properties that user can control, are defined in \l {advancedcustommaterial/WaterMaterial.qml}{WaterMaterial}.
+ Shader properties that user can control, are defined in \c {advancedcustommaterial/WaterMaterial.qml}.
\section1 Controls
\section2 Texture scale slider
@@ -53,7 +53,7 @@
\section2 Texture speed slider
Offsets values for texture coordinates which are animated in
- \l {advancedcustommaterial/Water.qml}{Water.qml} and then passed to vertex shader.
+ \c {advancedcustommaterial/Water.qml} and then passed to vertex shader.
Creates the effect of textures scrolling over the surface.
\section2 Specularity
@@ -80,5 +80,5 @@
\section2 Mesh rotation
- Rotates the water mesh in \l {advancedcustommaterial/Water.qml}{Water.qml}.
+ Rotates the water mesh in \c {advancedcustommaterial/Water.qml}.
*/
diff --git a/examples/qt3d/audio-visualizer-qml/doc/src/audio-visualizer-qml.qdoc b/examples/qt3d/audio-visualizer-qml/doc/src/audio-visualizer-qml.qdoc
index 5a204757e..6c0b40301 100644
--- a/examples/qt3d/audio-visualizer-qml/doc/src/audio-visualizer-qml.qdoc
+++ b/examples/qt3d/audio-visualizer-qml/doc/src/audio-visualizer-qml.qdoc
@@ -41,7 +41,7 @@
\section1 Qt Quick 2D Implementation
- The Qt Quick Implementation \l{audio-visualizer-qml/main.qml}{main.qml} of the example uses
+ The Qt Quick Implementation in \c {audio-visualizer-qml/main.qml} of the example uses
\c{MediaPlayer} to play audio content.
\snippet audio-visualizer-qml/main.qml 0
@@ -57,8 +57,8 @@
\section1 Qt 3D Implementation
- The 3D elements of the example are created in the
- \l{audio-visualizer-qml/Visualizer.qml}{Visualizer.qml}. The camera is set to a fixed position
+ The 3D elements of the example are created in
+ \c {audio-visualizer-qml/Visualizer.qml}. The camera is set to a fixed position
to show the visualized bars from a correct angle.
\snippet audio-visualizer-qml/Visualizer.qml 0
@@ -73,7 +73,7 @@
\snippet audio-visualizer-qml/Visualizer.qml 2
- In \l{audio-visualizer-qml/BarEntity.qml}{BarEntity.qml} there are animations for rotating the
+ In \c {audio-visualizer-qml/BarEntity.qml} there are animations for rotating the
bars and changing the bar color. The bars are rotated on a level following a ring form. At the
same time the color of the bars is animated.
diff --git a/examples/qt3d/planets-qml/SolarSystem.qml b/examples/qt3d/planets-qml/SolarSystem.qml
index 8c0cfccd4..2b56237f5 100644
--- a/examples/qt3d/planets-qml/SolarSystem.qml
+++ b/examples/qt3d/planets-qml/SolarSystem.qml
@@ -133,8 +133,8 @@ Entity {
projectionType: CameraLens.PerspectiveProjection
fieldOfView: 45
aspectRatio: width / height
- nearPlane: 2500000.0
- farPlane: 20000000.0
+ nearPlane: 2500.0
+ farPlane: 20000.0
position: defaultCameraPosition
upVector: defaultUp
viewCenter: Qt.vector3d( xLookAtOffset, yLookAtOffset, zLookAtOffset )
@@ -211,9 +211,9 @@ Entity {
//saturnRing.makeRing()
//uranusRing.makeRing()
saturnRingOuterRadius = planetData[Planets.SATURN].radius + Planets.saturnOuterRadius
- saturnRingInnerRadius = planetData[Planets.SATURN].radius + 6.630
+ saturnRingInnerRadius = planetData[Planets.SATURN].radius + 0.006630
uranusRingOuterRadius = planetData[Planets.URANUS].radius + Planets.uranusOuterRadius
- uranusRingInnerRadius = planetData[Planets.URANUS].radius + 2
+ uranusRingInnerRadius = planetData[Planets.URANUS].radius + 0.002
ready = true
changeScale(1200)
changeSpeed(0.2)
@@ -286,7 +286,7 @@ Entity {
// Limit minimum scaling in focus mode to avoid jitter caused by rounding errors
if (actualScale <= focusedMinimumScale) {
planetScale = focusedMinimumScale
- changeScale(focusedMinimumScale, true)
+ changeScale(focusedMinimumSfocusedPlanetcale, true)
}
focusedScaling = true
} else if (focusedScaling === true) {
@@ -423,7 +423,7 @@ Entity {
return
var scaling = setScale(scale, focused)
- sun.r = planetData[Planets.SUN].radius * scaling / 100
+ sun.r = planetData[Planets.SUN].radius * scaling / 10
mercury.r = planetData[Planets.MERCURY].radius * scaling
venus.r = planetData[Planets.VENUS].radius * scaling
earth.r = planetData[Planets.EARTH].radius * scaling
@@ -511,7 +511,7 @@ Entity {
}
property Transform transformStarfield: Transform {
- scale: 8500000
+ scale: 8500
translation: Qt.vector3d(0, 0, 0)
}
diff --git a/examples/qt3d/planets-qml/android/AndroidManifest.xml b/examples/qt3d/planets-qml/android/AndroidManifest.xml
index 0252a83b8..2acbd7b0b 100644
--- a/examples/qt3d/planets-qml/android/AndroidManifest.xml
+++ b/examples/qt3d/planets-qml/android/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<manifest package="org.qtproject.planets.qml" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
- <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+ <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:extractNativeLibs="true">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="unspecified" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
@@ -13,12 +13,10 @@
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
- <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
- <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
- <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
+ <meta-data android:name="android.app.load_local_libs_resource_id" android:resource="@array/load_local_libs"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Messages maps -->
@@ -42,7 +40,7 @@
<!-- Background running -->
</activity>
</application>
- <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/>
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
diff --git a/examples/qt3d/planets-qml/doc/src/planets-qml.qdoc b/examples/qt3d/planets-qml/doc/src/planets-qml.qdoc
index 2dae457a0..a8c89fbe2 100644
--- a/examples/qt3d/planets-qml/doc/src/planets-qml.qdoc
+++ b/examples/qt3d/planets-qml/doc/src/planets-qml.qdoc
@@ -50,14 +50,14 @@
\section1 Qt Quick 2D Implementation
- The Qt Quick Implementation \l{planets-qml/PlanetsMain.qml}{PlanetsMain.qml} of the
+ The Qt Quick Implementation in \c {planets-qml/PlanetsMain.qml} of the
example renders the 3D content using the \c Scene3D type.
\snippet planets-qml/PlanetsMain.qml 0
The planet related information is stored into a \c{ListModel}. The selection buttons for the
planets and the information sheet are created based on the model. The 2D elements, selection
- buttons and sliders, are implemented in the \l{planets-qml/PlanetsMain.qml}{PlanetsMain.qml}.
+ buttons and sliders, are implemented in \c {planets-qml/PlanetsMain.qml}.
The selection buttons change the \c{focusedPlanet} property of the \c{mainview}. As the property
changes, the planet information is updated, and the camera is animated to the new position.
@@ -65,14 +65,14 @@
\snippet planets-qml/PlanetsMain.qml 1
The camera position and the camera look at point are updated based on values that are animated
- in the \l{planets-qml/SolarSystem.qml}{SolarSystem.qml}, triggered from the
+ in \c {planets-qml/SolarSystem.qml}, triggered from the
\c{changePlanetFocus()} function.
\snippet planets-qml/SolarSystem.qml 0
The sliders are used to adjust the rotation speed, the planet size, and the viewing distance.
- When a slider value changes, a JavaScript function in \l{planets-qml/SolarSystem.qml}
- {SolarSystem.qml} is called to adjust the given property. For example, changing the value of
+ When a slider value changes, a JavaScript function in \c {planets-qml/SolarSystem.qml}
+ is called to adjust the given property. For example, changing the value of
the \e{Viewing Distance} slider calls the \c{changeCameraDistance()} method.
\snippet planets-qml/PlanetsMain.qml 2
@@ -80,7 +80,7 @@
\section1 Qt 3D Implementation
The main part of the implementation, including the movement and rotation maths for the planets,
- is done in the \l{planets-qml/SolarSystem.qml}{SolarSystem.qml}.
+ is done in \c {planets-qml/SolarSystem.qml}.
First, a \c Camera, a \c{Light}, and a \c Configuration are added, followed by \c{Effect}s for
the planet \c{Material}s, and finally the planets themselves. For example, Earth is constructed
@@ -89,7 +89,7 @@
\snippet planets-qml/SolarSystem.qml 1
Planet data, which is needed for the movement and rotation calculations, among other things, is
- constructed with JavaScript in \l{planets-qml/planets.js}{planets.js} by calling
+ constructed with JavaScript in \c {planets-qml/planets.js} by calling
\c{loadPlanetData()} as the component completes. Other initializations, such as inserting the
planets into an array for easier handling, calculating the ring radii for Saturn and Uranus
rings, and setting the default scale, speed, and camera offset, are done as well:
diff --git a/examples/qt3d/planets-qml/planets.js b/examples/qt3d/planets-qml/planets.js
index f64ec3149..b3517ac5a 100644
--- a/examples/qt3d/planets-qml/planets.js
+++ b/examples/qt3d/planets-qml/planets.js
@@ -115,11 +115,13 @@ function planetIndex(planetName) {
var planets = []; // Planet data info
-var solarDistance = 2600000;
-var saturnOuterRadius = 120.700;
-var uranusOuterRadius = 40;
+// Units are in 10^3 KM
-var auScale = 149597.870700; // AU in thousands of kilometers
+var solarDistance = 2600.000;
+var saturnOuterRadius = 0.120700;
+var uranusOuterRadius = 0.040;
+
+var auScale = 149.597870700; // 0.001 AU (in thousands of kilometers)
function loadPlanetData() {
@@ -136,11 +138,11 @@ function loadPlanetData() {
// centerOfOrbit - the planet in the center of the orbit
// (orbital elements based on http://www.stjarnhimlen.se/comp/ppcomp.html)
- var sun = { radius: 694.439, tilt: 63.87, period: 25.05, x: 0, y: 0, z: 0,
+ var sun = { radius: 0.694439, tilt: 63.87, period: 25.05, x: 0, y: 0, z: 0,
roll: 0 };
planets.push(sun);
var mercury = {
- radius: 2.433722, tilt: 0.04, N1: 48.3313, N2: 0.0000324587,
+ radius: 0.002433722, tilt: 0.04, N1: 48.3313, N2: 0.0000324587,
i1: 7.0047, i2: 0.0000000500, w1: 29.1241, w2: 0.0000101444,
a1: 0.387098, a2: 0, e1: 0.205635, e2: 0.000000000559,
M1: 168.6562, M2: 4.0923344368, period: 58.646, x: 0, y: 0, z: 0,
@@ -148,7 +150,7 @@ function loadPlanetData() {
};
planets.push(mercury);
var venus = {
- radius: 6.046079, tilt: 177.36, N1: 76.6799, N2: 0.0000246590,
+ radius: 0.006046079, tilt: 177.36, N1: 76.6799, N2: 0.0000246590,
i1: 3.3946, i2: 0.0000000275, w1: 54.8910, w2: 0.0000138374,
a1: 0.723330, a2: 0, e1: 0.006773, e2: -0.000000001302,
M1: 48.0052, M2: 1.6021302244, period: 243.0185, x: 0, y: 0, z: 0,
@@ -156,7 +158,7 @@ function loadPlanetData() {
};
planets.push(venus);
var earth = {
- radius: 6.371, tilt: 25.44, N1: 174.873, N2: 0,
+ radius: 0.006371, tilt: 25.44, N1: 174.873, N2: 0,
i1: 0.00005, i2: 0, w1: 102.94719, w2: 0,
a1: 1, a2: 0, e1: 0.01671022, e2: 0,
M1: 357.529, M2: 0.985608, period: 0.997, x: 0, y: 0, z: 0,
@@ -164,7 +166,7 @@ function loadPlanetData() {
};
planets.push(earth);
var mars = {
- radius: 3.389372, tilt: 25.19, N1: 49.5574, N2: 0.0000211081,
+ radius: 0.003389372, tilt: 25.19, N1: 49.5574, N2: 0.0000211081,
i1: 1.8497, i2: -0.0000000178, w1: 286.5016, w2: 0.0000292961,
a1: 1.523688, a2: 0, e1: 0.093405, e2: 0.000000002516,
M1: 18.6021, M2: 0.5240207766, period: 1.025957, x: 0, y: 0, z: 0,
@@ -172,7 +174,7 @@ function loadPlanetData() {
};
planets.push(mars);
var jupiter = {
- radius: 71.41254, tilt: 3.13, N1: 100.4542, N2: 0.0000276854,
+ radius: 0.07141254, tilt: 3.13, N1: 100.4542, N2: 0.0000276854,
i1: 1.3030, i2: -0.0000001557, w1: 273.8777, w2: 0.0000164505,
a1: 5.20256, a2: 0, e1: 0.048498, e2: 0.000000004469,
M1: 19.8950, M2: 0.0830853001, period: 0.4135, x: 0, y: 0, z: 0,
@@ -180,7 +182,7 @@ function loadPlanetData() {
};
planets.push(jupiter);
var saturn = {
- radius: 60.19958, tilt: 26.73, N1: 113.6634, N2: 0.0000238980,
+ radius: 0.06019958, tilt: 26.73, N1: 113.6634, N2: 0.0000238980,
i1: 2.4886, i2: -0.0000001081, w1: 339.3939, w2: 0.0000297661,
a1: 9.55475, a2: 0, e1: 0.055546, e2: -0.000000009499,
M1: 316.9670, M2: 0.0334442282, period: 0.4395, x: 0, y: 0, z: 0,
@@ -188,7 +190,7 @@ function loadPlanetData() {
};
planets.push(saturn);
var uranus = {
- radius: 25.5286, tilt: 97.77, N1: 74.0005, N2: 0.000013978,
+ radius: 0.0255286, tilt: 97.77, N1: 74.0005, N2: 0.000013978,
i1: 0.7733, i2: 0.000000019, w1: 96.6612, w2: 0.000030565,
a1: 19.18171, a2: -0.0000000155, e1: 0.047318, e2: 0.00000000745,
M1: 142.5905, M2: 0.011725806, period: 0.71833, x: 0, y: 0, z: 0,
@@ -196,7 +198,7 @@ function loadPlanetData() {
};
planets.push(uranus);
var neptune = {
- radius: 24.73859, tilt: 28.32, N1: 131.7806, N2: 0.000030173,
+ radius: 0.02473859, tilt: 28.32, N1: 131.7806, N2: 0.000030173,
i1: 1.7700, i2: -0.000000255, w1: 272.8461, w2: 0.000006027,
a1: 30.05826, a2: 0.00000003313, e1: 0.008606, e2: 0.00000000215,
M1: 260.2471, M2: 0.005995147, period: 0.6713, x: 0, y: 0, z: 0,
@@ -204,7 +206,7 @@ function loadPlanetData() {
};
planets.push(neptune);
var moon = {
- radius: 1.5424, tilt: 28.32, N1: 125.1228, N2: -0.0529538083,
+ radius: 0.0015424, tilt: 28.32, N1: 125.1228, N2: -0.0529538083,
i1: 5.1454, i2: 0, w1: 318.0634, w2: 0.1643573223,
a1: 0.273, a2: 0, e1: 0.054900, e2: 0,
M1: 115.3654, M2: 13.0649929509, period: 27.321582, x: 0, y: 0, z: 0,
@@ -224,7 +226,7 @@ function getOuterRadius(planet) {
} else if (planet === URANUS) {
outerRadius =+ uranusOuterRadius;
} else if (planet === SUN) {
- outerRadius = planets[planet]["radius"] / 100;
+ outerRadius = planets[planet]["radius"] / 10;
}
}
diff --git a/examples/qt3d/simplecustommaterial/doc/src/simplecustommaterial.qdoc b/examples/qt3d/simplecustommaterial/doc/src/simplecustommaterial.qdoc
index d10927d39..7ec7c7abb 100644
--- a/examples/qt3d/simplecustommaterial/doc/src/simplecustommaterial.qdoc
+++ b/examples/qt3d/simplecustommaterial/doc/src/simplecustommaterial.qdoc
@@ -48,7 +48,7 @@
\section1 Specifying the Material
- The material is specified in \l{simplecustommaterial/SimpleMaterial.qml}{SimpleMaterial.qml}
+ The material is specified in \c {simplecustommaterial/SimpleMaterial.qml}
using \l Material type. First the material specifies parameters,
which are mapped to the corresponding uniforms in the shaders so that they can be
changed from the qml.
diff --git a/src/animation/backend/abstractevaluateclipanimatorjob.cpp b/src/animation/backend/abstractevaluateclipanimatorjob.cpp
index 236a96efe..5267d4526 100644
--- a/src/animation/backend/abstractevaluateclipanimatorjob.cpp
+++ b/src/animation/backend/abstractevaluateclipanimatorjob.cpp
@@ -53,13 +53,8 @@ public:
void postFrame(Qt3DCore::QAspectManager *manager) override;
- Q_DECLARE_PUBLIC(AbstractEvaluateClipAnimatorJob)
-
AnimationRecord m_record;
QVector<AnimationCallbackAndValue> m_callbacks;
-
-private:
- AbstractEvaluateClipAnimatorJob *q_ptr;
};
AbstractEvaluateClipAnimatorJob::AbstractEvaluateClipAnimatorJob()
diff --git a/src/animation/backend/animationclip.cpp b/src/animation/backend/animationclip.cpp
index 2dea81b52..2c7e4fffb 100644
--- a/src/animation/backend/animationclip.cpp
+++ b/src/animation/backend/animationclip.cpp
@@ -68,6 +68,7 @@ AnimationClip::AnimationClip()
, m_name()
, m_channels()
, m_duration(0.0f)
+ , m_channelComponentCount(0)
{
}
@@ -81,6 +82,7 @@ void AnimationClip::cleanup()
m_dataType = Unknown;
m_channels.clear();
m_duration = 0.0f;
+ m_channelComponentCount = 0;
clearData();
}
diff --git a/src/animation/backend/buildblendtreesjob.cpp b/src/animation/backend/buildblendtreesjob.cpp
index 3cfa81446..b4cc04323 100644
--- a/src/animation/backend/buildblendtreesjob.cpp
+++ b/src/animation/backend/buildblendtreesjob.cpp
@@ -50,8 +50,9 @@ namespace Animation {
BuildBlendTreesJob::BuildBlendTreesJob()
: Qt3DCore::QAspectJob()
+ , m_handler(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::BuildBlendTree, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::BuildBlendTree, 0)
}
void BuildBlendTreesJob::setBlendedClipAnimators(const QVector<HBlendedClipAnimator> &blendedClipAnimatorHandles)
diff --git a/src/animation/backend/channelmapping.cpp b/src/animation/backend/channelmapping.cpp
index 83e7322da..1e3aa76f0 100644
--- a/src/animation/backend/channelmapping.cpp
+++ b/src/animation/backend/channelmapping.cpp
@@ -59,7 +59,6 @@ ChannelMapping::ChannelMapping()
, m_componentCount(0)
, m_propertyName(nullptr)
, m_callback(nullptr)
- , m_callbackFlags(0)
, m_skeletonId()
, m_mappingType(MappingType::ChannelMappingType)
{
@@ -74,7 +73,7 @@ void ChannelMapping::cleanup()
m_propertyName = nullptr;
m_componentCount = 0;
m_callback = nullptr;
- m_callbackFlags = 0;
+ m_callbackFlags = {};
m_skeletonId = Qt3DCore::QNodeId();
}
@@ -106,9 +105,9 @@ void ChannelMapping::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firs
const QCallbackMapping *callbackMapping = qobject_cast<const QCallbackMapping *>(frontEnd);
if (callbackMapping) {
m_mappingType = ChannelMappingType;
- m_channelName = channelMapping->channelName();
+ m_channelName = callbackMapping->channelName();
- const QCallbackMappingPrivate *d = static_cast<const QCallbackMappingPrivate *>(Qt3DCore::QNodePrivate::get(channelMapping));
+ const QCallbackMappingPrivate *d = static_cast<const QCallbackMappingPrivate *>(Qt3DCore::QNodePrivate::get(callbackMapping));
m_type = d->m_type;
m_callback = d->m_callback;
m_callbackFlags = d->m_callbackFlags;
diff --git a/src/animation/backend/evaluateblendclipanimatorjob.cpp b/src/animation/backend/evaluateblendclipanimatorjob.cpp
index 9b6802d3b..765531902 100644
--- a/src/animation/backend/evaluateblendclipanimatorjob.cpp
+++ b/src/animation/backend/evaluateblendclipanimatorjob.cpp
@@ -54,6 +54,7 @@ namespace Animation {
EvaluateBlendClipAnimatorJob::EvaluateBlendClipAnimatorJob()
: AbstractEvaluateClipAnimatorJob()
+ , m_handler(nullptr)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateBlendClipAnimator, 0)
}
diff --git a/src/animation/backend/evaluateclipanimatorjob.cpp b/src/animation/backend/evaluateclipanimatorjob.cpp
index 7a568e829..914a38139 100644
--- a/src/animation/backend/evaluateclipanimatorjob.cpp
+++ b/src/animation/backend/evaluateclipanimatorjob.cpp
@@ -52,6 +52,7 @@ namespace Animation {
EvaluateClipAnimatorJob::EvaluateClipAnimatorJob()
: AbstractEvaluateClipAnimatorJob()
+ , m_handler(nullptr)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateClipAnimator, 0)
}
diff --git a/src/animation/backend/findrunningclipanimatorsjob.cpp b/src/animation/backend/findrunningclipanimatorsjob.cpp
index fde3f7db8..1005914c7 100644
--- a/src/animation/backend/findrunningclipanimatorsjob.cpp
+++ b/src/animation/backend/findrunningclipanimatorsjob.cpp
@@ -48,8 +48,9 @@ namespace Animation {
FindRunningClipAnimatorsJob::FindRunningClipAnimatorsJob()
: Qt3DCore::QAspectJob()
+ , m_handler(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::FindRunningClipAnimator, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::FindRunningClipAnimator, 0)
}
void FindRunningClipAnimatorsJob::setDirtyClipAnimators(const QVector<HClipAnimator> &clipAnimatorHandles)
diff --git a/src/animation/backend/gltfimporter.cpp b/src/animation/backend/gltfimporter.cpp
index a2630fc5e..a5127efd0 100644
--- a/src/animation/backend/gltfimporter.cpp
+++ b/src/animation/backend/gltfimporter.cpp
@@ -35,6 +35,9 @@
****************************************************************************/
#include "gltfimporter_p.h"
+
+#include <Qt3DCore/private/qloadgltf_p.h>
+
#include <Qt3DAnimation/private/animationlogging_p.h>
#include <Qt3DAnimation/private/fcurve_p.h>
#include <Qt3DAnimation/private/keyframe_p.h>
@@ -434,12 +437,7 @@ GLTFImporter::GLTFImporter()
bool GLTFImporter::load(QIODevice *ioDev)
{
- QByteArray jsonData = ioDev->readAll();
- QJsonDocument sceneDocument = QJsonDocument::fromBinaryData(jsonData);
- if (sceneDocument.isNull())
- sceneDocument = QJsonDocument::fromJson(jsonData);
-
- if (Q_UNLIKELY(!setJSON(sceneDocument))) {
+ if (Q_UNLIKELY(!setJSON(qLoadGLTF(ioDev->readAll())))) {
qWarning("not a JSON document");
return false;
}
diff --git a/src/animation/backend/loadanimationclipjob.cpp b/src/animation/backend/loadanimationclipjob.cpp
index 977564c7f..93d4c2d9d 100644
--- a/src/animation/backend/loadanimationclipjob.cpp
+++ b/src/animation/backend/loadanimationclipjob.cpp
@@ -64,6 +64,7 @@ public:
LoadAnimationClipJob::LoadAnimationClipJob()
: Qt3DCore::QAspectJob(*new LoadAnimationClipJobPrivate)
, m_animationClipHandles()
+ , m_handler(nullptr)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadAnimationClip, 0)
}
diff --git a/src/animation/backend/skeleton.cpp b/src/animation/backend/skeleton.cpp
index 60e436a71..3788fd0f1 100644
--- a/src/animation/backend/skeleton.cpp
+++ b/src/animation/backend/skeleton.cpp
@@ -35,7 +35,6 @@
****************************************************************************/
#include "skeleton_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qabstractskeleton_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/animation/frontend/qabstractanimationclip.cpp b/src/animation/frontend/qabstractanimationclip.cpp
index e662a1408..08133072c 100644
--- a/src/animation/frontend/qabstractanimationclip.cpp
+++ b/src/animation/frontend/qabstractanimationclip.cpp
@@ -36,7 +36,6 @@
#include "qabstractanimationclip.h"
#include "qabstractanimationclip_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -122,7 +121,7 @@ void QAbstractAnimationClipPrivate::setDuration(float duration)
animator->setRunning(true);
\endcode
- \sa QAnimationClip, QAnimationClipLoader
+ \sa Qt3DAnimation::QAnimationClip, Qt3DAnimation::QAnimationClipLoader
*/
/*!
@@ -134,6 +133,11 @@ QAbstractAnimationClip::QAbstractAnimationClip(QAbstractAnimationClipPrivate &dd
{
}
+// TODO Unused remove in Qt6
+void QAbstractAnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
/*!
Destroys this animation clip.
*/
diff --git a/src/animation/frontend/qabstractanimationclip.h b/src/animation/frontend/qabstractanimationclip.h
index f68950c4c..fddee3dec 100644
--- a/src/animation/frontend/qabstractanimationclip.h
+++ b/src/animation/frontend/qabstractanimationclip.h
@@ -62,7 +62,8 @@ Q_SIGNALS:
protected:
QAbstractAnimationClip(QAbstractAnimationClipPrivate &dd, Qt3DCore::QNode *parent = nullptr);
-
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QAbstractAnimationClip)
};
diff --git a/src/animation/frontend/qabstractchannelmapping.cpp b/src/animation/frontend/qabstractchannelmapping.cpp
index 3249e6876..599ec6ed7 100644
--- a/src/animation/frontend/qabstractchannelmapping.cpp
+++ b/src/animation/frontend/qabstractchannelmapping.cpp
@@ -46,6 +46,7 @@ namespace Qt3DAnimation {
QAbstractChannelMappingPrivate::QAbstractChannelMappingPrivate()
: Qt3DCore::QNodePrivate()
+ , m_mappingType(QChannelMappingCreatedChangeBase::ChannelMapping)
{
}
diff --git a/src/animation/frontend/qabstractclipanimator.cpp b/src/animation/frontend/qabstractclipanimator.cpp
index cb4621182..8c282da49 100644
--- a/src/animation/frontend/qabstractclipanimator.cpp
+++ b/src/animation/frontend/qabstractclipanimator.cpp
@@ -122,6 +122,11 @@ QAbstractClipAnimator::QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Q
{
}
+// TODO Unused remove in Qt6
+void QAbstractClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
QAbstractClipAnimator::~QAbstractClipAnimator()
{
}
diff --git a/src/animation/frontend/qabstractclipanimator.h b/src/animation/frontend/qabstractclipanimator.h
index 687589b5e..dc9dc9077 100644
--- a/src/animation/frontend/qabstractclipanimator.h
+++ b/src/animation/frontend/qabstractclipanimator.h
@@ -94,6 +94,8 @@ protected:
explicit QAbstractClipAnimator(Qt3DCore::QNode *parent = nullptr);
QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QAbstractClipAnimator)
};
diff --git a/src/animation/frontend/qanimationcallback.qdoc b/src/animation/frontend/qanimationcallback.qdoc
new file mode 100644
index 000000000..5c6e8e212
--- /dev/null
+++ b/src/animation/frontend/qanimationcallback.qdoc
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class Qt3DAnimation::QAnimationCallback
+ \inmodule Qt3DAnimation
+ \brief Represents an animation callback object.
+*/
+
+/*!
+ \enum Qt3DAnimation::QAnimationCallback::Flag
+
+ Flags to indicate how the valueChanged() function is called.
+
+ \value OnOwningThread
+ Callback function is called on the owning (GUI or main) thread.
+ \value OnThreadPool
+ Callback function is called on the thread pool's worker thread.
+*/
+
+/*!
+ \fn Qt3DAnimation::QAnimationCallback::valueChanged(const QVariant &value)
+
+ Callback function that is triggered for changes in the animated \a value.
+
+ \sa QCallbackMapping::setCallback()
+*/
diff --git a/src/animation/frontend/qanimationclip.cpp b/src/animation/frontend/qanimationclip.cpp
index d624a246a..74a9b8371 100644
--- a/src/animation/frontend/qanimationclip.cpp
+++ b/src/animation/frontend/qanimationclip.cpp
@@ -51,8 +51,8 @@ QAnimationClipPrivate::QAnimationClipPrivate()
}
/*!
- \class QAnimationClip
- \inherits QAbstractAnimationClip
+ \class Qt3DAnimation::QAnimationClip
+ \inherits Qt3dAnimation::QAbstractAnimationClip
\inmodule Qt3DAnimation
\brief Specifies key frame animation data.
*/
diff --git a/src/animation/frontend/qanimationclipdata.cpp b/src/animation/frontend/qanimationclipdata.cpp
index 49de71e79..e105b7b43 100644
--- a/src/animation/frontend/qanimationclipdata.cpp
+++ b/src/animation/frontend/qanimationclipdata.cpp
@@ -53,7 +53,7 @@ public:
};
/*!
- \class QAnimationClipData
+ \class Qt3DAnimation::QAnimationClipData
\inmodule Qt3DAnimation
\brief Class containing the animation data.
*/
diff --git a/src/animation/frontend/qanimationcliploader.cpp b/src/animation/frontend/qanimationcliploader.cpp
index 446995b17..bf901e54f 100644
--- a/src/animation/frontend/qanimationcliploader.cpp
+++ b/src/animation/frontend/qanimationcliploader.cpp
@@ -36,7 +36,6 @@
#include "qanimationcliploader.h"
#include "qanimationcliploader_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -113,6 +112,11 @@ QAnimationClipLoader::QAnimationClipLoader(QAnimationClipLoaderPrivate &dd, Qt3D
{
}
+// TODO Unused remove in Qt6
+void QAnimationClipLoader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
QAnimationClipLoader::~QAnimationClipLoader()
{
}
diff --git a/src/animation/frontend/qanimationcliploader.h b/src/animation/frontend/qanimationcliploader.h
index 1ff388297..1b68e852f 100644
--- a/src/animation/frontend/qanimationcliploader.h
+++ b/src/animation/frontend/qanimationcliploader.h
@@ -78,6 +78,8 @@ Q_SIGNALS:
protected:
explicit QAnimationClipLoader(QAnimationClipLoaderPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QAnimationClipLoader)
diff --git a/src/animation/frontend/qcallbackmapping.cpp b/src/animation/frontend/qcallbackmapping.cpp
index 53f7a5e33..a86785012 100644
--- a/src/animation/frontend/qcallbackmapping.cpp
+++ b/src/animation/frontend/qcallbackmapping.cpp
@@ -51,13 +51,12 @@ QCallbackMappingPrivate::QCallbackMappingPrivate()
, m_channelName()
, m_type(static_cast<int>(QVariant::Invalid))
, m_callback(nullptr)
- , m_callbackFlags(0)
{
m_mappingType = QChannelMappingCreatedChangeBase::CallbackMapping;
}
/*!
- \class QCallbackMapping
+ \class Qt3DAnimation::QCallbackMapping
\inherits Qt3DCore::QAbstractChannelMapping
\inmodule Qt3DAnimation
\brief Allows to map the channels within the clip onto an invocation
diff --git a/src/animation/frontend/qchannel.cpp b/src/animation/frontend/qchannel.cpp
index eab7f0df4..1e0da3c3f 100644
--- a/src/animation/frontend/qchannel.cpp
+++ b/src/animation/frontend/qchannel.cpp
@@ -54,7 +54,7 @@ public:
};
/*!
- \class QChannel
+ \class Qt3DAnimation::QChannel
\inmodule Qt3DAnimation
\brief Defines a channel for a QAnimationClipData.
The animation system interpolates each channel component independently
diff --git a/src/animation/frontend/qchannelmapper.cpp b/src/animation/frontend/qchannelmapper.cpp
index ab98039b4..c5909adbc 100644
--- a/src/animation/frontend/qchannelmapper.cpp
+++ b/src/animation/frontend/qchannelmapper.cpp
@@ -49,7 +49,7 @@ QChannelMapperPrivate::QChannelMapperPrivate()
}
/*!
- \class QChannelMapper
+ \class Qt3DAnimation::QChannelMapper
\inmodule Qt3DAnimation
\brief Allows to map the channels within the clip onto properties of
objects in the application.
diff --git a/src/animation/frontend/qchannelmapping.cpp b/src/animation/frontend/qchannelmapping.cpp
index 59620ab49..16651afe6 100644
--- a/src/animation/frontend/qchannelmapping.cpp
+++ b/src/animation/frontend/qchannelmapping.cpp
@@ -161,7 +161,7 @@ void QChannelMappingPrivate::updatePropertyNameTypeAndComponentCount()
}
/*!
- \class QChannelMapping
+ \class Qt3DAnimation::QChannelMapping
\inherits Qt3DCore::QNode
\inmodule Qt3DAnimation
\brief Allows to map the channels within the clip onto properties of
diff --git a/src/animation/frontend/qclipanimator.cpp b/src/animation/frontend/qclipanimator.cpp
index 03510aa93..ffad588c1 100644
--- a/src/animation/frontend/qclipanimator.cpp
+++ b/src/animation/frontend/qclipanimator.cpp
@@ -107,7 +107,8 @@ bool QClipAnimatorPrivate::canPlay() const
The properties for controlling the animator are provided by the QAbstractClipAnimator base
class.
- \sa QAbstractClipAnimator, QAbstractAnimationClip, QChannelMapper, QBlendedClipAnimator
+ \sa Qt3DAnimation::QAbstractClipAnimator, Qt3DAnimation::QAbstractAnimationClip,
+ Qt3DAnimation::QChannelMapper, Qt3DAnimation::QBlendedClipAnimator
*/
QClipAnimator::QClipAnimator(Qt3DCore::QNode *parent)
diff --git a/src/animation/frontend/qclipblendvalue.cpp b/src/animation/frontend/qclipblendvalue.cpp
index 72a7dd796..053453e33 100644
--- a/src/animation/frontend/qclipblendvalue.cpp
+++ b/src/animation/frontend/qclipblendvalue.cpp
@@ -53,14 +53,14 @@ QClipBlendValuePrivate::QClipBlendValuePrivate()
}
/*!
- \class QClipBlendValue
+ \class Qt3DAnimation::QClipBlendValue
\inherits Qt3DAnimation::QAbstractClipBlendNode
\inmodule Qt3DAnimation
\brief Class used for including a clip in a blend tree.
*/
/*!
\qmltype ClipBlendValue
- \instantiates QClipBlendValue
+ \instantiates Qt3DAnimation::QClipBlendValue
\inqmlmodule Qt3D.Animation
\brief Type used for including a clip in a blend tree.
*/
diff --git a/src/animation/frontend/qmorphtarget.cpp b/src/animation/frontend/qmorphtarget.cpp
index 76b1a598e..da068d477 100644
--- a/src/animation/frontend/qmorphtarget.cpp
+++ b/src/animation/frontend/qmorphtarget.cpp
@@ -86,8 +86,8 @@ namespace Qt3DAnimation {
*/
/*!
\qmlmethod MorphTarget Qt3D.Animation::MorphTarget::fromGeometry(geometry, stringList)
- Returns a morph target based on the attributes defined by the given stringList from
- the given geometry.
+ Returns a morph target based on the attributes defined by the given \a stringList from
+ the given \a geometry.
*/
QMorphTargetPrivate::QMorphTargetPrivate()
diff --git a/src/animation/frontend/qvertexblendanimation.cpp b/src/animation/frontend/qvertexblendanimation.cpp
index 25468d4a7..143b9553a 100644
--- a/src/animation/frontend/qvertexblendanimation.cpp
+++ b/src/animation/frontend/qvertexblendanimation.cpp
@@ -192,8 +192,8 @@ void QVertexBlendAnimationPrivate::updateAnimation(float position)
Qt3DRender::QGeometry *geometry = m_target->geometry();
// remove attributes from previous frame
- if ((m_currentBase && (base != m_currentBase))
- || (m_currentTarget && (target != m_currentTarget))) {
+ if (m_currentBase && m_currentTarget &&
+ (base != m_currentBase || target != m_currentTarget)) {
const QVector<Qt3DRender::QAttribute *> baseAttributes = m_currentBase->attributeList();
const QVector<Qt3DRender::QAttribute *> targetAttributes = m_currentTarget->attributeList();
for (int i = 0; i < baseAttributes.size(); ++i) {
diff --git a/src/core/aspects/aspectcommanddebugger.cpp b/src/core/aspects/aspectcommanddebugger.cpp
index eceec1bbd..7635f44c0 100644
--- a/src/core/aspects/aspectcommanddebugger.cpp
+++ b/src/core/aspects/aspectcommanddebugger.cpp
@@ -39,12 +39,12 @@
#include "aspectcommanddebugger_p.h"
-#include <Qt3DCore/qaspectengine.h>
#include <QtNetwork/QTcpSocket>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <Qt3DCore/private/qabstractaspect_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p.h>
QT_BEGIN_NAMESPACE
@@ -64,13 +64,6 @@ struct CommandHeader
} // anonymous
-AspectCommandDebugger::ReadBuffer::ReadBuffer()
- : buffer()
- , startIdx(0)
- , endIdx(0)
-{
-}
-
void AspectCommandDebugger::ReadBuffer::insert(const QByteArray &array)
{
buffer.insert(endIdx, array);
@@ -88,9 +81,9 @@ void AspectCommandDebugger::ReadBuffer::trim()
}
}
-AspectCommandDebugger::AspectCommandDebugger(QObject *parent)
+AspectCommandDebugger::AspectCommandDebugger(QSystemInformationService *parent)
: QTcpServer(parent)
- , m_aspectEngine(nullptr)
+ , m_service(parent)
{
}
@@ -115,11 +108,6 @@ void AspectCommandDebugger::initialize()
qWarning() << Q_FUNC_INFO << "failed to listen on port 8883";
}
-void AspectCommandDebugger::setAspectEngine(QAspectEngine *engine)
-{
- m_aspectEngine = engine;
-}
-
void AspectCommandDebugger::asynchronousReplyFinished(AsynchronousCommandReply *reply)
{
Q_ASSERT(reply->isFinished());
@@ -189,7 +177,7 @@ void AspectCommandDebugger::executeCommand(const QString &command,
QTcpSocket *socket)
{
// Only a single aspect is going to reply
- const QVariant response = m_aspectEngine->executeCommand(command);
+ const QVariant response = m_service->executeCommand(command);
if (response.userType() == qMetaTypeId<AsynchronousCommandReply *>()) { // AsynchronousCommand
// Store the command | socket in a table
AsynchronousCommandReply *reply = response.value<AsynchronousCommandReply *>();
diff --git a/src/core/aspects/aspectcommanddebugger_p.h b/src/core/aspects/aspectcommanddebugger_p.h
index bb6100df5..b39708ab1 100644
--- a/src/core/aspects/aspectcommanddebugger_p.h
+++ b/src/core/aspects/aspectcommanddebugger_p.h
@@ -54,32 +54,30 @@
//
#include <QTcpServer>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-class QAspectEngine;
+class QSystemInformationService;
namespace Debug {
class AsynchronousCommandReply;
-class Q_AUTOTEST_EXPORT AspectCommandDebugger : public QTcpServer
+class Q_3DCORE_PRIVATE_EXPORT AspectCommandDebugger : public QTcpServer
{
Q_OBJECT
public:
- explicit AspectCommandDebugger(QObject *parent = nullptr);
+ explicit AspectCommandDebugger(QSystemInformationService *parent = nullptr);
void initialize();
- void setAspectEngine(QAspectEngine *engine);
-
- struct ReadBuffer {
- ReadBuffer();
+ struct Q_3DCORE_PRIVATE_EXPORT ReadBuffer {
QByteArray buffer;
- int startIdx;
- int endIdx;
+ int startIdx = 0;
+ int endIdx = 0;
inline int size() const { return endIdx - startIdx; }
void insert(const QByteArray &array);
@@ -95,7 +93,7 @@ private:
void executeCommand(const QString &command, QTcpSocket *socket);
QVector<QTcpSocket *> m_connections;
- QAspectEngine *m_aspectEngine;
+ QSystemInformationService *m_service;
ReadBuffer m_readBuffer;
QHash<AsynchronousCommandReply *, QTcpSocket *> m_asyncCommandToSocketEntries;
diff --git a/src/core/aspects/aspects.pri b/src/core/aspects/aspects.pri
index 5e8327192..068f74389 100644
--- a/src/core/aspects/aspects.pri
+++ b/src/core/aspects/aspects.pri
@@ -4,7 +4,8 @@ SOURCES += \
$$PWD/qabstractaspect.cpp \
$$PWD/qaspectengine.cpp \
$$PWD/qaspectfactory.cpp \
- $$PWD/qaspectmanager.cpp
+ $$PWD/qaspectmanager.cpp \
+ $$PWD/aspectcommanddebugger.cpp
HEADERS += \
$$PWD/qabstractaspect.h \
@@ -12,13 +13,10 @@ HEADERS += \
$$PWD/qabstractaspect_p.h \
$$PWD/qaspectengine_p.h \
$$PWD/qaspectfactory_p.h \
- $$PWD/qaspectmanager_p.h
+ $$PWD/qaspectmanager_p.h \
+ $$PWD/aspectcommanddebugger_p.h
INCLUDEPATH += $$PWD
include($$QT3D_BUILD_ROOT/src/core/qt3dcore-config.pri)
QT_FOR_CONFIG += 3dcore-private
-qtConfig(qt3d-profile-jobs): {
- HEADERS += $$PWD/aspectcommanddebugger_p.h
- SOURCES += $$PWD/aspectcommanddebugger.cpp
-}
diff --git a/src/core/aspects/qabstractaspect.cpp b/src/core/aspects/qabstractaspect.cpp
index 05afdd293..a2aed732b 100644
--- a/src/core/aspects/qabstractaspect.cpp
+++ b/src/core/aspects/qabstractaspect.cpp
@@ -198,28 +198,16 @@ void QAbstractAspect::unregisterBackendType(const QMetaObject &obj)
QVariant QAbstractAspect::executeCommand(const QStringList &args)
{
- Q_UNUSED(args);
+ Q_UNUSED(args)
return QVariant();
}
QVector<QAspectJobPtr> QAbstractAspect::jobsToExecute(qint64 time)
{
- Q_UNUSED(time);
+ Q_UNUSED(time)
return QVector<QAspectJobPtr>();
}
-void QAbstractAspect::syncDirtyFrontEndNodes(const QVector<QNode *> &nodes)
-{
- Q_D(QAbstractAspect);
- d->syncDirtyFrontEndNodes(nodes);
-}
-
-void QAbstractAspect::syncDirtyFrontEndSubNodes(const QVector<NodeRelationshipChange> &nodes)
-{
- Q_D(QAbstractAspect);
- d->syncDirtyFrontEndSubNodes(nodes);
-}
-
QAbstractAspectPrivate::BackendNodeMapperAndInfo QAbstractAspectPrivate::mapperForNode(const QMetaObject *metaObj) const
{
Q_ASSERT(metaObj);
@@ -520,6 +508,11 @@ QVector<QAspectJobPtr> QAbstractAspectPrivate::jobsToExecute(qint64 time)
return res;
}
+void QAbstractAspectPrivate::jobsDone(QAspectManager *manager)
+{
+ Q_UNUSED(manager)
+}
+
/*!
* Called in the context of the aspect thread once the aspect has been registered.
* This provides an opportunity for the aspect to do any initialization tasks that
diff --git a/src/core/aspects/qabstractaspect.h b/src/core/aspects/qabstractaspect.h
index 8059421a6..3b2f31c50 100644
--- a/src/core/aspects/qabstractaspect.h
+++ b/src/core/aspects/qabstractaspect.h
@@ -87,9 +87,6 @@ protected:
void unregisterBackendType(const QMetaObject &);
private:
- void syncDirtyFrontEndNodes(const QVector<QNode *> &nodes);
- void syncDirtyFrontEndSubNodes(const QVector<NodeRelationshipChange> &nodes);
-
virtual QVariant executeCommand(const QStringList &args);
virtual QVector<QAspectJobPtr> jobsToExecute(qint64 time);
diff --git a/src/core/aspects/qabstractaspect_p.h b/src/core/aspects/qabstractaspect_p.h
index 670302cfa..9435f2bc6 100644
--- a/src/core/aspects/qabstractaspect_p.h
+++ b/src/core/aspects/qabstractaspect_p.h
@@ -57,6 +57,7 @@
#include <Qt3DCore/private/qaspectjobproviderinterface_p.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
+#include <Qt3DCore/private/qscenechange_p.h>
#include <QtCore/private/qobject_p.h>
#include <QMutex>
@@ -126,6 +127,7 @@ public:
QAbstractAspectJobManager *jobManager() const;
QVector<QAspectJobPtr> jobsToExecute(qint64 time) override;
+ void jobsDone(Qt3DCore::QAspectManager *manager) override;
QBackendNode *createBackendNode(const NodeTreeChange &change) const;
void clearBackendNode(const NodeTreeChange &change) const;
diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp
index 426741a61..d28306197 100644
--- a/src/core/aspects/qaspectengine.cpp
+++ b/src/core/aspects/qaspectengine.cpp
@@ -55,12 +55,9 @@
#include <Qt3DCore/private/qpostman_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p.h>
#include <Qt3DCore/qt3dcore-config.h>
-#if QT_CONFIG(qt3d_profile_jobs)
-#include <Qt3DCore/private/aspectcommanddebugger_p.h>
-#endif
-
QT_BEGIN_NAMESPACE
namespace{
@@ -122,9 +119,6 @@ QAspectEnginePrivate::QAspectEnginePrivate()
, m_scene(nullptr)
, m_initialized(false)
, m_runMode(QAspectEngine::Automatic)
- #if QT_CONFIG(qt3d_profile_jobs)
- , m_commandDebugger(new Debug::AspectCommandDebugger(q_func()))
- #endif
{
qRegisterMetaType<Qt3DCore::QAbstractAspect *>();
qRegisterMetaType<Qt3DCore::QObserverInterface *>();
@@ -276,10 +270,6 @@ void QAspectEnginePrivate::initialize()
arbiter->setScene(m_scene);
m_initialized = true;
m_aspectManager->setPostConstructorInit(m_scene->postConstructorInit());
-#if QT_CONFIG(qt3d_profile_jobs)
- m_commandDebugger->setAspectEngine(q_func());
- m_commandDebugger->initialize();
-#endif
}
/*!
@@ -419,16 +409,8 @@ QVariant QAspectEngine::executeCommand(const QString &command)
if (d->m_aspects.isEmpty())
return QLatin1String("No loaded aspect");
- QString reply;
- reply += QLatin1String("Loaded aspects:");
- for (QAbstractAspect *aspect : qAsConst(d->m_aspects)) {
- const QString name = d->m_factory.aspectName(aspect);
- if (!name.isEmpty())
- reply += QLatin1String("\n * ") + name;
- else
- reply += QLatin1String("\n * <unnamed>");
- }
- return reply;
+ const QStringList names = d->m_aspectManager->serviceLocator()->systemInformation()->aspectNames();
+ return names.join(QLatin1String("\n"));
}
QStringList args = command.split(QLatin1Char(' '));
diff --git a/src/core/aspects/qaspectengine_p.h b/src/core/aspects/qaspectengine_p.h
index c83940435..8f3abcd38 100644
--- a/src/core/aspects/qaspectengine_p.h
+++ b/src/core/aspects/qaspectengine_p.h
@@ -69,12 +69,6 @@ class QAspectManager;
class QPostman;
class QScene;
-#if QT_CONFIG(qt3d_profile_jobs)
-namespace Debug {
-class AspectCommandDebugger;
-} // Debug
-#endif
-
class Q_3DCORE_PRIVATE_EXPORT QAspectEnginePrivate : public QObjectPrivate
{
public:
@@ -93,10 +87,6 @@ public:
bool m_initialized;
QAspectEngine::RunMode m_runMode;
-#if QT_CONFIG(qt3d_profile_jobs)
- Debug::AspectCommandDebugger *m_commandDebugger;
-#endif
-
void initialize();
void shutdown();
diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp
index 71e05b34f..f276d633e 100644
--- a/src/core/aspects/qaspectmanager.cpp
+++ b/src/core/aspects/qaspectmanager.cpp
@@ -57,6 +57,7 @@
#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/private/qscheduler_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p_p.h>
#include <Qt3DCore/private/qthreadpooler_p.h>
#include <Qt3DCore/private/qtickclock_p.h>
#include <Qt3DCore/private/qtickclockservice_p.h>
@@ -98,15 +99,18 @@ int RequestFrameEvent::requestEventType = QEvent::registerEventType();
\class Qt3DCore::QAspectManager
\internal
*/
-QAspectManager::QAspectManager(QObject *parent)
+QAspectManager::QAspectManager(QAspectEngine *parent)
: QObject(parent)
+ , m_engine(parent)
, m_root(nullptr)
, m_scheduler(new QScheduler(this))
, m_jobManager(new QAspectJobManager(this))
, m_changeArbiter(new QChangeArbiter(this))
- , m_serviceLocator(new QServiceLocator())
+ , m_serviceLocator(new QServiceLocator(parent))
, m_simulationLoopRunning(false)
, m_driveMode(QAspectEngine::Automatic)
+ , m_postConstructorInit(nullptr)
+ , m_jobsInLastFrame(0)
{
qRegisterMetaType<QSurface *>("QSurface*");
qCDebug(Aspects) << Q_FUNC_INFO;
@@ -413,6 +417,8 @@ bool QAspectManager::event(QEvent *e)
// the loop
if (m_simulationLoopRunning && m_driveMode == QAspectEngine::Automatic)
requestNextFrame();
+
+ return true;
}
return QObject::event(e);
@@ -423,7 +429,7 @@ void QAspectManager::requestNextFrame()
qCDebug(Aspects) << "Requesting new Frame";
// Post event in the event loop to force
// next frame to be processed
- qApp->postEvent(this, new RequestFrameEvent());
+ QCoreApplication::postEvent(this, new RequestFrameEvent());
}
void QAspectManager::processFrame()
@@ -435,6 +441,8 @@ void QAspectManager::processFrame()
m_serviceLocator->service<QAbstractFrameAdvanceService>(QServiceLocator::FrameAdvanceService);
const qint64 t = frameAdvanceService->waitForNextFrame();
+ if (t < 0)
+ return;
// Distribute accumulated changes. This includes changes sent from the frontend
// to the backend nodes. We call this before the call to m_scheduler->update() to ensure
@@ -444,57 +452,49 @@ void QAspectManager::processFrame()
//
// Doing this as the first call in the new frame ensures the lock free approach works
// without any such data race.
-#if QT_CONFIG(qt3d_profile_jobs)
- const quint32 arbiterId = 4096;
- JobRunStats changeArbiterStats;
- changeArbiterStats.jobId.typeAndInstance[0] = arbiterId;
- changeArbiterStats.jobId.typeAndInstance[1] = 0;
- changeArbiterStats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
- changeArbiterStats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
-#endif
-
- // Tell the NodePostConstructorInit to process any pending nodes which will add them to our list of
- // tree changes
- m_postConstructorInit->processNodes();
-
- // Add and Remove Nodes
- const QVector<NodeTreeChange> nodeTreeChanges = std::move(m_nodeTreeChanges);
- for (const NodeTreeChange &change : nodeTreeChanges) {
- // Buckets ensure that even if we have intermingled node added / removed
- // buckets, we preserve the order of the sequences
-
- for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
- switch (change.type) {
- case NodeTreeChange::Added:
- aspect->d_func()->createBackendNode(change);
- break;
- case NodeTreeChange::Removed:
- aspect->d_func()->clearBackendNode(change);
- break;
+ {
+ // scope for QTaskLogger
+ QTaskLogger logger(m_serviceLocator->systemInformation(), 4096, 0);
+
+ // Tell the NodePostConstructorInit to process any pending nodes which will add them to our list of
+ // tree changes
+ m_postConstructorInit->processNodes();
+
+ // Add and Remove Nodes
+ const QVector<NodeTreeChange> nodeTreeChanges = std::move(m_nodeTreeChanges);
+ for (const NodeTreeChange &change : nodeTreeChanges) {
+ // Buckets ensure that even if we have intermingled node added / removed
+ // buckets, we preserve the order of the sequences
+
+ for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
+ switch (change.type) {
+ case NodeTreeChange::Added:
+ aspect->d_func()->createBackendNode(change);
+ break;
+ case NodeTreeChange::Removed:
+ aspect->d_func()->clearBackendNode(change);
+ break;
+ }
}
}
- }
-
- // Sync node / subnode relationship changes
- const auto dirtySubNodes = m_changeArbiter->takeDirtyFrontEndSubNodes();
- if (dirtySubNodes.size())
- for (QAbstractAspect *aspect : qAsConst(m_aspects))
- aspect->syncDirtyFrontEndSubNodes(dirtySubNodes);
- // Sync property updates
- const auto dirtyFrontEndNodes = m_changeArbiter->takeDirtyFrontEndNodes();
- if (dirtyFrontEndNodes.size())
- for (QAbstractAspect *aspect : qAsConst(m_aspects))
- aspect->syncDirtyFrontEndNodes(dirtyFrontEndNodes);
-
- // TO DO: Having this done in the main thread actually means aspects could just
- // as simply read info out of the Frontend classes without risk of introducing
- // races. This could therefore be removed for Qt 6.
- m_changeArbiter->syncChanges();
-#if QT_CONFIG(qt3d_profile_jobs)
- changeArbiterStats.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- QThreadPooler::addJobLogStatsEntry(changeArbiterStats);
-#endif
+ // Sync node / subnode relationship changes
+ const auto dirtySubNodes = m_changeArbiter->takeDirtyFrontEndSubNodes();
+ if (dirtySubNodes.size())
+ for (QAbstractAspect *aspect : qAsConst(m_aspects))
+ QAbstractAspectPrivate::get(aspect)->syncDirtyFrontEndSubNodes(dirtySubNodes);
+
+ // Sync property updates
+ const auto dirtyFrontEndNodes = m_changeArbiter->takeDirtyFrontEndNodes();
+ if (dirtyFrontEndNodes.size())
+ for (QAbstractAspect *aspect : qAsConst(m_aspects))
+ QAbstractAspectPrivate::get(aspect)->syncDirtyFrontEndNodes(dirtyFrontEndNodes);
+
+ // TO DO: Having this done in the main thread actually means aspects could just
+ // as simply read info out of the Frontend classes without risk of introducing
+ // races. This could therefore be removed for Qt 6.
+ m_changeArbiter->syncChanges();
+ }
// For each Aspect
// Ask them to launch set of jobs for the current frame
@@ -503,12 +503,10 @@ void QAspectManager::processFrame()
QElapsedTimer timer;
timer.start();
#endif
- m_scheduler->scheduleAndWaitForFrameAspectJobs(t);
+ m_jobsInLastFrame = m_scheduler->scheduleAndWaitForFrameAspectJobs(t);
#if defined(QT3D_CORE_JOB_TIMING)
qDebug() << "Jobs took" << timer.nsecsElapsed() / 1.0e6;
#endif
-
- // TODO sync backend changes to frontend
}
} // namespace Qt3DCore
diff --git a/src/core/aspects/qaspectmanager_p.h b/src/core/aspects/qaspectmanager_p.h
index d9a6c41ec..ed04b314f 100644
--- a/src/core/aspects/qaspectmanager_p.h
+++ b/src/core/aspects/qaspectmanager_p.h
@@ -73,6 +73,7 @@ class QScheduler;
class QChangeArbiter;
class QAbstractAspect;
class QAbstractAspectJobManager;
+class QAspectEngine;
class QServiceLocator;
class NodePostConstructorInit;
struct NodeTreeChange;
@@ -81,7 +82,7 @@ class Q_3DCORE_PRIVATE_EXPORT QAspectManager : public QObject
{
Q_OBJECT
public:
- explicit QAspectManager(QObject *parent = nullptr);
+ explicit QAspectManager(QAspectEngine *parent = nullptr);
~QAspectManager();
void setRunMode(QAspectEngine::RunMode mode);
@@ -111,10 +112,13 @@ public:
QNode *lookupNode(QNodeId id) const;
QVector<QNode *> lookupNodes(const QVector<QNodeId> &ids) const;
+ int jobsInLastFrame() const { return m_jobsInLastFrame; }
+
private:
bool event(QEvent *event) override;
void requestNextFrame();
+ QAspectEngine *m_engine;
QVector<QAbstractAspect *> m_aspects;
QEntity *m_root;
QVariantMap m_data;
@@ -122,12 +126,11 @@ private:
QAbstractAspectJobManager *m_jobManager;
QChangeArbiter *m_changeArbiter;
QScopedPointer<QServiceLocator> m_serviceLocator;
- bool m_mainLoopRunning;
bool m_simulationLoopRunning;
QAspectEngine::RunMode m_driveMode;
QVector<NodeTreeChange> m_nodeTreeChanges;
NodePostConstructorInit* m_postConstructorInit;
-
+ int m_jobsInLastFrame;
};
} // namespace Qt3DCore
diff --git a/src/core/changes/qcomponentaddedchange.h b/src/core/changes/qcomponentaddedchange.h
index ef2f6a227..9e1522024 100644
--- a/src/core/changes/qcomponentaddedchange.h
+++ b/src/core/changes/qcomponentaddedchange.h
@@ -53,10 +53,10 @@ class QComponentAddedChangePrivate;
class Q_3DCORESHARED_EXPORT QComponentAddedChange : public QSceneChange
{
public:
- explicit QComponentAddedChange(const QEntity *entity,
- const QComponent *component);
- explicit QComponentAddedChange(const QComponent *component,
- const QEntity *entity);
+ Q3D_DECL_DEPRECATED explicit QComponentAddedChange(const QEntity *entity,
+ const QComponent *component);
+ Q3D_DECL_DEPRECATED explicit QComponentAddedChange(const QComponent *component,
+ const QEntity *entity);
~QComponentAddedChange();
QNodeId entityId() const Q_DECL_NOTHROW;
@@ -67,7 +67,7 @@ private:
Q_DECLARE_PRIVATE(QComponentAddedChange)
};
-typedef QSharedPointer<QComponentAddedChange> QComponentAddedChangePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QComponentAddedChange> QComponentAddedChangePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qcomponentremovedchange.h b/src/core/changes/qcomponentremovedchange.h
index 8108b33d5..e0b039780 100644
--- a/src/core/changes/qcomponentremovedchange.h
+++ b/src/core/changes/qcomponentremovedchange.h
@@ -53,10 +53,10 @@ class QComponentRemovedChangePrivate;
class Q_3DCORESHARED_EXPORT QComponentRemovedChange : public QSceneChange
{
public:
- explicit QComponentRemovedChange(const QEntity *entity,
- const QComponent *component);
- explicit QComponentRemovedChange(const QComponent *component,
- const QEntity *entity);
+ Q3D_DECL_DEPRECATED explicit QComponentRemovedChange(const QEntity *entity,
+ const QComponent *component);
+ Q3D_DECL_DEPRECATED explicit QComponentRemovedChange(const QComponent *component,
+ const QEntity *entity);
~QComponentRemovedChange();
QNodeId entityId() const Q_DECL_NOTHROW;
@@ -67,7 +67,7 @@ private:
Q_DECLARE_PRIVATE(QComponentRemovedChange)
};
-typedef QSharedPointer<QComponentRemovedChange> QComponentRemovedChangePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QComponentRemovedChange> QComponentRemovedChangePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qdynamicpropertyupdatedchange.h b/src/core/changes/qdynamicpropertyupdatedchange.h
index 0509582b0..7009e1fe7 100644
--- a/src/core/changes/qdynamicpropertyupdatedchange.h
+++ b/src/core/changes/qdynamicpropertyupdatedchange.h
@@ -51,7 +51,7 @@ class QDynamicPropertyUpdatedChangePrivate;
class Q_3DCORESHARED_EXPORT QDynamicPropertyUpdatedChange : public QPropertyUpdatedChangeBase
{
public:
- explicit QDynamicPropertyUpdatedChange(QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QDynamicPropertyUpdatedChange(QNodeId subjectId);
~QDynamicPropertyUpdatedChange();
QByteArray propertyName() const;
@@ -65,7 +65,7 @@ protected:
QDynamicPropertyUpdatedChange(QDynamicPropertyUpdatedChangePrivate &dd, QNodeId subjectId);
};
-typedef QSharedPointer<QDynamicPropertyUpdatedChange> QDynamicPropertyUpdatedChangePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QDynamicPropertyUpdatedChange> QDynamicPropertyUpdatedChangePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qnodecommand.h b/src/core/changes/qnodecommand.h
index 3622f7421..83d7caf4f 100644
--- a/src/core/changes/qnodecommand.h
+++ b/src/core/changes/qnodecommand.h
@@ -57,7 +57,7 @@ public:
typedef quint32 CommandId;
#endif
- explicit QNodeCommand(QNodeId id);
+ Q3D_DECL_DEPRECATED explicit QNodeCommand(QNodeId id);
~QNodeCommand();
CommandId commandId() const;
@@ -76,7 +76,7 @@ private:
Q_DECLARE_PRIVATE(QNodeCommand)
};
-typedef QSharedPointer<QNodeCommand> QNodeCommandPtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QNodeCommand> QNodeCommandPtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qnodecreatedchange.h b/src/core/changes/qnodecreatedchange.h
index f46e8abee..359cdb917 100644
--- a/src/core/changes/qnodecreatedchange.h
+++ b/src/core/changes/qnodecreatedchange.h
@@ -51,7 +51,7 @@ class QNodeCreatedChangeBasePrivate;
class Q_3DCORESHARED_EXPORT QNodeCreatedChangeBase : public QSceneChange
{
public:
- explicit QNodeCreatedChangeBase(const QNode *node);
+ Q3D_DECL_DEPRECATED explicit QNodeCreatedChangeBase(const QNode *node);
~QNodeCreatedChangeBase();
QNodeId parentId() const Q_DECL_NOTHROW;
@@ -65,7 +65,7 @@ private:
Q_DECLARE_PRIVATE(QNodeCreatedChangeBase)
};
-typedef QSharedPointer<QNodeCreatedChangeBase> QNodeCreatedChangeBasePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QNodeCreatedChangeBase> QNodeCreatedChangeBasePtr;
template<typename T>
class QNodeCreatedChange : public QNodeCreatedChangeBase
@@ -81,7 +81,7 @@ public:
};
template<typename T>
-using QNodeCreatedChangePtr = QSharedPointer<QNodeCreatedChange<T>>;
+using QNodeCreatedChangePtr Q3D_DECL_DEPRECATED = QSharedPointer<QNodeCreatedChange<T>>;
} // namespace Qt3DCore
diff --git a/src/core/changes/qnodedestroyedchange.h b/src/core/changes/qnodedestroyedchange.h
index c072dd412..dce6da59e 100644
--- a/src/core/changes/qnodedestroyedchange.h
+++ b/src/core/changes/qnodedestroyedchange.h
@@ -50,7 +50,7 @@ class QNodeDestroyedChangePrivate;
class Q_3DCORESHARED_EXPORT QNodeDestroyedChange : public QSceneChange
{
public:
- explicit QNodeDestroyedChange(const QNode *node, const QVector<QNodeIdTypePair> &subtreeIdsAndTypes);
+ Q3D_DECL_DEPRECATED explicit QNodeDestroyedChange(const QNode *node, const QVector<QNodeIdTypePair> &subtreeIdsAndTypes);
~QNodeDestroyedChange();
QVector<QNodeIdTypePair> subtreeIdsAndTypes() const;
@@ -59,7 +59,7 @@ private:
Q_DECLARE_PRIVATE(QNodeDestroyedChange)
};
-typedef QSharedPointer<QNodeDestroyedChange> QNodeDestroyedChangePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QNodeDestroyedChange> QNodeDestroyedChangePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qpropertynodeaddedchange.h b/src/core/changes/qpropertynodeaddedchange.h
index ce3288a65..062244f88 100644
--- a/src/core/changes/qpropertynodeaddedchange.h
+++ b/src/core/changes/qpropertynodeaddedchange.h
@@ -53,7 +53,7 @@ class QPropertyNodeAddedChangePrivate;
class Q_3DCORESHARED_EXPORT QPropertyNodeAddedChange : public QStaticPropertyValueAddedChangeBase
{
public:
- explicit QPropertyNodeAddedChange(QNodeId subjectId, QNode *node);
+ Q3D_DECL_DEPRECATED explicit QPropertyNodeAddedChange(QNodeId subjectId, QNode *node);
~QPropertyNodeAddedChange();
QNodeId addedNodeId() const;
@@ -63,7 +63,7 @@ private:
Q_DECLARE_PRIVATE(QPropertyNodeAddedChange)
};
-typedef QSharedPointer<QPropertyNodeAddedChange> QPropertyNodeAddedChangePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QPropertyNodeAddedChange> QPropertyNodeAddedChangePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qpropertynoderemovedchange.h b/src/core/changes/qpropertynoderemovedchange.h
index 1a4db8f1c..a8ea9d6c4 100644
--- a/src/core/changes/qpropertynoderemovedchange.h
+++ b/src/core/changes/qpropertynoderemovedchange.h
@@ -53,7 +53,7 @@ class QPropertyNodeRemovedChangePrivate;
class Q_3DCORESHARED_EXPORT QPropertyNodeRemovedChange : public QStaticPropertyValueRemovedChangeBase
{
public:
- explicit QPropertyNodeRemovedChange(QNodeId subjectId, QNode *node);
+ Q3D_DECL_DEPRECATED explicit QPropertyNodeRemovedChange(QNodeId subjectId, QNode *node);
~QPropertyNodeRemovedChange();
QNodeId removedNodeId() const;
@@ -63,7 +63,7 @@ private:
Q_DECLARE_PRIVATE(QPropertyNodeRemovedChange)
};
-typedef QSharedPointer<QPropertyNodeRemovedChange> QPropertyNodeRemovedChangePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QPropertyNodeRemovedChange> QPropertyNodeRemovedChangePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qpropertyupdatedchange.h b/src/core/changes/qpropertyupdatedchange.h
index e0c12f13d..aa0dd9364 100644
--- a/src/core/changes/qpropertyupdatedchange.h
+++ b/src/core/changes/qpropertyupdatedchange.h
@@ -51,7 +51,7 @@ class QPropertyUpdatedChangePrivate;
class Q_3DCORESHARED_EXPORT QPropertyUpdatedChange : public QStaticPropertyUpdatedChangeBase
{
public:
- explicit QPropertyUpdatedChange(QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QPropertyUpdatedChange(QNodeId subjectId);
virtual ~QPropertyUpdatedChange();
QVariant value() const;
@@ -62,7 +62,7 @@ protected:
QPropertyUpdatedChange(QPropertyUpdatedChangePrivate &dd, QNodeId subjectId);
};
-typedef QSharedPointer<QPropertyUpdatedChange> QPropertyUpdatedChangePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QPropertyUpdatedChange> QPropertyUpdatedChangePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qpropertyupdatedchangebase.h b/src/core/changes/qpropertyupdatedchangebase.h
index 800abb477..5a0f6c87f 100644
--- a/src/core/changes/qpropertyupdatedchangebase.h
+++ b/src/core/changes/qpropertyupdatedchangebase.h
@@ -56,12 +56,12 @@ public:
~QPropertyUpdatedChangeBase();
protected:
- explicit QPropertyUpdatedChangeBase(QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QPropertyUpdatedChangeBase(QNodeId subjectId);
QPropertyUpdatedChangeBase(QPropertyUpdatedChangeBasePrivate &dd, QNodeId subjectId);
Q_DECLARE_PRIVATE(QPropertyUpdatedChangeBase)
};
-typedef QSharedPointer<QPropertyUpdatedChangeBase> QPropertyUpdatedChangeBasePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QPropertyUpdatedChangeBase> QPropertyUpdatedChangeBasePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qpropertyvalueaddedchange.h b/src/core/changes/qpropertyvalueaddedchange.h
index d85720246..e70d78b7e 100644
--- a/src/core/changes/qpropertyvalueaddedchange.h
+++ b/src/core/changes/qpropertyvalueaddedchange.h
@@ -53,7 +53,7 @@ class QPropertyValueAddedChangePrivate;
class Q_3DCORESHARED_EXPORT QPropertyValueAddedChange : public QStaticPropertyValueAddedChangeBase
{
public:
- explicit QPropertyValueAddedChange(QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QPropertyValueAddedChange(QNodeId subjectId);
~QPropertyValueAddedChange();
void setAddedValue(const QVariant &value);
@@ -63,7 +63,7 @@ private:
Q_DECLARE_PRIVATE(QPropertyValueAddedChange)
};
-typedef QSharedPointer<QPropertyValueAddedChange> QPropertyValueAddedChangePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QPropertyValueAddedChange> QPropertyValueAddedChangePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qpropertyvalueaddedchangebase.h b/src/core/changes/qpropertyvalueaddedchangebase.h
index 2be39ad47..148411de8 100644
--- a/src/core/changes/qpropertyvalueaddedchangebase.h
+++ b/src/core/changes/qpropertyvalueaddedchangebase.h
@@ -56,12 +56,12 @@ public:
~QPropertyValueAddedChangeBase();
protected:
- explicit QPropertyValueAddedChangeBase(QNodeId subjectId);
- explicit QPropertyValueAddedChangeBase(QPropertyValueAddedChangeBasePrivate &dd, QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QPropertyValueAddedChangeBase(QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QPropertyValueAddedChangeBase(QPropertyValueAddedChangeBasePrivate &dd, QNodeId subjectId);
Q_DECLARE_PRIVATE(QPropertyValueAddedChangeBase)
};
-typedef QSharedPointer<QPropertyValueAddedChangeBase> QPropertyValueAddedChangeBasePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QPropertyValueAddedChangeBase> QPropertyValueAddedChangeBasePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qpropertyvalueremovedchange.h b/src/core/changes/qpropertyvalueremovedchange.h
index 2bd781ed5..70eb42db4 100644
--- a/src/core/changes/qpropertyvalueremovedchange.h
+++ b/src/core/changes/qpropertyvalueremovedchange.h
@@ -53,7 +53,7 @@ class QPropertyValueRemovedChangePrivate;
class Q_3DCORESHARED_EXPORT QPropertyValueRemovedChange : public QStaticPropertyValueRemovedChangeBase
{
public:
- explicit QPropertyValueRemovedChange(QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QPropertyValueRemovedChange(QNodeId subjectId);
~QPropertyValueRemovedChange();
void setRemovedValue(const QVariant &value);
@@ -63,7 +63,7 @@ private:
Q_DECLARE_PRIVATE(QPropertyValueRemovedChange)
};
-typedef QSharedPointer<QPropertyValueRemovedChange> QPropertyValueRemovedChangePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QPropertyValueRemovedChange> QPropertyValueRemovedChangePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qpropertyvalueremovedchangebase.h b/src/core/changes/qpropertyvalueremovedchangebase.h
index 233354078..b5ead7d22 100644
--- a/src/core/changes/qpropertyvalueremovedchangebase.h
+++ b/src/core/changes/qpropertyvalueremovedchangebase.h
@@ -57,11 +57,11 @@ public:
protected:
Q_DECLARE_PRIVATE(QPropertyValueRemovedChangeBase)
- explicit QPropertyValueRemovedChangeBase(QNodeId subjectId);
- explicit QPropertyValueRemovedChangeBase(QPropertyValueRemovedChangeBasePrivate &dd, QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QPropertyValueRemovedChangeBase(QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QPropertyValueRemovedChangeBase(QPropertyValueRemovedChangeBasePrivate &dd, QNodeId subjectId);
};
-typedef QSharedPointer<QPropertyValueRemovedChangeBase> QPropertyValueRemovedChangeBasePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QPropertyValueRemovedChangeBase> QPropertyValueRemovedChangeBasePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qscenechange.cpp b/src/core/changes/qscenechange.cpp
index 87bf06ea0..822451b5f 100644
--- a/src/core/changes/qscenechange.cpp
+++ b/src/core/changes/qscenechange.cpp
@@ -48,6 +48,7 @@ namespace Qt3DCore {
/*!
* \enum Qt3DCore::ChangeFlag
* \relates Qt3DCore::QSceneChange
+ * \obsolete
*
* The types of change that can be sent and received by Qt3D's change notification system.
*
diff --git a/src/core/changes/qscenechange.h b/src/core/changes/qscenechange.h
index e8c0ea748..792c00d0a 100644
--- a/src/core/changes/qscenechange.h
+++ b/src/core/changes/qscenechange.h
@@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-enum ChangeFlag {
+enum Q3D_DECL_DEPRECATED ChangeFlag {
NodeCreated = 1 << 0,
NodeDeleted = 1 << 1,
PropertyUpdated = 1 << 2,
@@ -64,14 +64,6 @@ Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag)
Q_DECLARE_OPERATORS_FOR_FLAGS(ChangeFlags)
class QNode;
-//! internal
-struct NodeRelationshipChange {
- QNode *node;
- QNode *subNode;
- ChangeFlag change;
- const char *property;
-};
-
class QSceneChangePrivate;
class Q_3DCORESHARED_EXPORT QSceneChange
@@ -95,9 +87,9 @@ public:
protected:
Q_DECLARE_PRIVATE(QSceneChange)
- explicit QSceneChange(ChangeFlag type, QNodeId subjectId);
- explicit QSceneChange(QSceneChangePrivate &dd,
- ChangeFlag type, QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QSceneChange(ChangeFlag type, QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QSceneChange(QSceneChangePrivate &dd,
+ ChangeFlag type, QNodeId subjectId);
QSceneChangePrivate *d_ptr;
private:
@@ -106,7 +98,7 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QSceneChange::DeliveryFlags)
-typedef QSharedPointer<QSceneChange> QSceneChangePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QSceneChange> QSceneChangePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qscenechange_p.h b/src/core/changes/qscenechange_p.h
index d32f6eec3..32006807c 100644
--- a/src/core/changes/qscenechange_p.h
+++ b/src/core/changes/qscenechange_p.h
@@ -63,6 +63,13 @@ namespace Qt3DCore {
class QSceneChange;
class QNodeId;
+struct NodeRelationshipChange {
+ QNode *node;
+ QNode *subNode;
+ ChangeFlag change;
+ const char *property;
+};
+
class Q_3DCORE_PRIVATE_EXPORT QSceneChangePrivate
{
public :
diff --git a/src/core/changes/qskeletoncreatedchange_p.h b/src/core/changes/qskeletoncreatedchange_p.h
index 09b37d545..c20bcae85 100644
--- a/src/core/changes/qskeletoncreatedchange_p.h
+++ b/src/core/changes/qskeletoncreatedchange_p.h
@@ -60,7 +60,7 @@ class QSkeletonCreatedChangeBasePrivate;
class Q_3DCORESHARED_EXPORT QSkeletonCreatedChangeBase : public QNodeCreatedChangeBase
{
public:
- explicit QSkeletonCreatedChangeBase(const QAbstractSkeleton *skeleton);
+ Q3D_DECL_DEPRECATED explicit QSkeletonCreatedChangeBase(const QAbstractSkeleton *skeleton);
~QSkeletonCreatedChangeBase();
enum SkeletonType {
@@ -74,7 +74,7 @@ private:
Q_DECLARE_PRIVATE(QSkeletonCreatedChangeBase)
};
-typedef QSharedPointer<QSkeletonCreatedChangeBase> QSkeletonCreatedChangeBasePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QSkeletonCreatedChangeBase> QSkeletonCreatedChangeBasePtr;
template<typename T>
class QSkeletonCreatedChange : public QSkeletonCreatedChangeBase
@@ -90,7 +90,7 @@ public:
};
template<typename T>
-using QSkeletonCreatedChangePtr = QSharedPointer<QSkeletonCreatedChange<T>>;
+using QSkeletonCreatedChangePtr Q3D_DECL_DEPRECATED = QSharedPointer<QSkeletonCreatedChange<T>>;
} // namespace Qt3DCore
diff --git a/src/core/changes/qstaticpropertyupdatedchangebase.h b/src/core/changes/qstaticpropertyupdatedchangebase.h
index b698d1f06..c59a87a20 100644
--- a/src/core/changes/qstaticpropertyupdatedchangebase.h
+++ b/src/core/changes/qstaticpropertyupdatedchangebase.h
@@ -57,12 +57,12 @@ public:
void setPropertyName(const char *name);
protected:
- explicit QStaticPropertyUpdatedChangeBase(QNodeId subjectId);
- explicit QStaticPropertyUpdatedChangeBase(QStaticPropertyUpdatedChangeBasePrivate &dd, QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QStaticPropertyUpdatedChangeBase(QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QStaticPropertyUpdatedChangeBase(QStaticPropertyUpdatedChangeBasePrivate &dd, QNodeId subjectId);
Q_DECLARE_PRIVATE(QStaticPropertyUpdatedChangeBase)
};
-typedef QSharedPointer<QStaticPropertyUpdatedChangeBase> QStaticPropertyUpdatedChangeBasePtr;
+Q3D_DECL_DEPRECATED typedef QSharedPointer<QStaticPropertyUpdatedChangeBase> QStaticPropertyUpdatedChangeBasePtr;
} // namespace Qt3DCore
diff --git a/src/core/changes/qstaticpropertyvalueaddedchangebase.h b/src/core/changes/qstaticpropertyvalueaddedchangebase.h
index e56e8f18a..7e6807764 100644
--- a/src/core/changes/qstaticpropertyvalueaddedchangebase.h
+++ b/src/core/changes/qstaticpropertyvalueaddedchangebase.h
@@ -59,7 +59,7 @@ public:
protected:
Q_DECLARE_PRIVATE(QStaticPropertyValueAddedChangeBase)
- explicit QStaticPropertyValueAddedChangeBase(QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QStaticPropertyValueAddedChangeBase(QNodeId subjectId);
QStaticPropertyValueAddedChangeBase(QStaticPropertyValueAddedChangeBasePrivate &dd,
QNodeId subjectId);
};
diff --git a/src/core/changes/qstaticpropertyvalueremovedchangebase.h b/src/core/changes/qstaticpropertyvalueremovedchangebase.h
index e9f53fb12..d1b96f83e 100644
--- a/src/core/changes/qstaticpropertyvalueremovedchangebase.h
+++ b/src/core/changes/qstaticpropertyvalueremovedchangebase.h
@@ -59,7 +59,7 @@ public:
protected:
Q_DECLARE_PRIVATE(QStaticPropertyValueRemovedChangeBase)
- explicit QStaticPropertyValueRemovedChangeBase(QNodeId subjectId);
+ Q3D_DECL_DEPRECATED explicit QStaticPropertyValueRemovedChangeBase(QNodeId subjectId);
QStaticPropertyValueRemovedChangeBase(QStaticPropertyValueRemovedChangeBasePrivate &dd,
QNodeId subjectId);
};
diff --git a/src/core/configure.json b/src/core/configure.json
index 2ba205530..2e13d9027 100644
--- a/src/core/configure.json
+++ b/src/core/configure.json
@@ -44,7 +44,7 @@
"output": [ "privateFeature" ]
},
"qt3d-profile-jobs": {
- "label": "Output Qt3D Job traces",
+ "label": "Output Qt3D Job traces (deprecated)",
"autoDetect": false,
"output": [ "privateFeature" ]
},
@@ -112,7 +112,6 @@
"entries": [
"assimp",
"system-assimp",
- "qt3d-profile-jobs",
"qt3d-profile-gl",
"qt3d-simd-sse2",
"qt3d-simd-avx2",
diff --git a/src/core/jobs/qaspectjob_p.h b/src/core/jobs/qaspectjob_p.h
index b16c3cad2..ddad09c86 100644
--- a/src/core/jobs/qaspectjob_p.h
+++ b/src/core/jobs/qaspectjob_p.h
@@ -54,6 +54,7 @@
#include <QtCore/QWeakPointer>
#include <Qt3DCore/private/qt3dcore_global_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p_p.h>
#include <Qt3DCore/qt3dcore-config.h>
QT_BEGIN_NAMESPACE
@@ -63,47 +64,6 @@ namespace Qt3DCore {
class QAspectJob;
class QAspectManager;
-#if QT_CONFIG(qt3d_profile_jobs)
-struct FrameHeader
-{
- FrameHeader()
- : frameId(0)
- , jobCount(0)
- , frameType(WorkerJob)
- {
- }
-
- enum FrameType {
- WorkerJob = 0,
- Submission
- };
-
- quint32 frameId;
- quint16 jobCount;
- quint16 frameType; // Submission or worker job
-};
-
-union JobId
-{
- quint32 typeAndInstance[2];
- quint64 id;
-};
-
-struct JobRunStats
-{
- JobRunStats()
- {
- jobId.id = 0;
- }
-
- qint64 startTime;
- qint64 endTime;
- JobId jobId;
- // QAspectJob subclasses should properly populate the jobId
- quint64 threadId;
-};
-#endif
-
class Q_3DCORE_PRIVATE_EXPORT QAspectJobPrivate
{
public:
@@ -115,29 +75,16 @@ public:
virtual void postFrame(QAspectManager *aspectManager);
QVector<QWeakPointer<QAspectJob> > m_dependencies;
-#if QT_CONFIG(qt3d_profile_jobs)
- JobRunStats m_stats;
-#endif
+ JobId m_jobId;
};
-
} // Qt3D
-#if QT_CONFIG(qt3d_profile_jobs)
-
-#include <Qt3DCore/private/qaspectjob_p.h>
-
#define SET_JOB_RUN_STAT_TYPE(job, type, instance) \
- Qt3DCore::QAspectJobPrivate::get(job)->m_stats.jobId.typeAndInstance[0] = type; \
- Qt3DCore::QAspectJobPrivate::get(job)->m_stats.jobId.typeAndInstance[1] = instance;
-
-#else
-
-#define SET_JOB_RUN_STAT_TYPE(job, type, instance) \
- Q_UNUSED(job) \
- Q_UNUSED(type) \
- Q_UNUSED(instance)
-
-#endif
+ { \
+ auto &jobId = Qt3DCore::QAspectJobPrivate::get(job)->m_jobId; \
+ jobId.typeAndInstance[0] = type; \
+ jobId.typeAndInstance[1] = instance; \
+ }
QT_END_NAMESPACE
diff --git a/src/core/jobs/qaspectjobmanager.cpp b/src/core/jobs/qaspectjobmanager.cpp
index 91394924f..be7942359 100644
--- a/src/core/jobs/qaspectjobmanager.cpp
+++ b/src/core/jobs/qaspectjobmanager.cpp
@@ -44,7 +44,7 @@
#include <QtCore/QDebug>
#include <QtCore/QThread>
#include <QtCore/QFuture>
-
+#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DCore/private/qthreadpooler_p.h>
#include <Qt3DCore/private/task_p.h>
@@ -52,9 +52,10 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-QAspectJobManager::QAspectJobManager(QObject *parent)
+QAspectJobManager::QAspectJobManager(QAspectManager *parent)
: QAbstractAspectJobManager(parent)
, m_threadPooler(new QThreadPooler(this))
+ , m_aspectManager(parent)
{
}
@@ -69,12 +70,16 @@ void QAspectJobManager::initialize()
// Adds all Aspect Jobs to be processed for a frame
void QAspectJobManager::enqueueJobs(const QVector<QAspectJobPtr> &jobQueue)
{
+ auto systemService = m_aspectManager ? m_aspectManager->serviceLocator()->systemInformation() : nullptr;
+ if (systemService)
+ systemService->writePreviousFrameTraces();
+
// Convert QJobs to Tasks
QHash<QAspectJob *, AspectTaskRunnable *> tasksMap;
QVector<RunnableInterface *> taskList;
taskList.reserve(jobQueue.size());
for (const QAspectJobPtr &job : jobQueue) {
- AspectTaskRunnable *task = new AspectTaskRunnable();
+ AspectTaskRunnable *task = new AspectTaskRunnable(systemService);
task->m_job = job;
tasksMap.insert(job.data(), task);
@@ -99,9 +104,6 @@ void QAspectJobManager::enqueueJobs(const QVector<QAspectJobPtr> &jobQueue)
taskDepender->m_dependerCount += dependerCount;
}
-#if QT_CONFIG(qt3d_profile_jobs)
- QThreadPooler::writeFrameJobLogStats();
-#endif
m_threadPooler->mapDependables(taskList);
}
diff --git a/src/core/jobs/qaspectjobmanager_p.h b/src/core/jobs/qaspectjobmanager_p.h
index 77e535491..acbd0263e 100644
--- a/src/core/jobs/qaspectjobmanager_p.h
+++ b/src/core/jobs/qaspectjobmanager_p.h
@@ -63,12 +63,13 @@ namespace Qt3DCore {
class QThreadPooler;
class DependencyHandler;
+class QAspectManager;
class Q_3DCORE_PRIVATE_EXPORT QAspectJobManager : public QAbstractAspectJobManager
{
Q_OBJECT
public:
- explicit QAspectJobManager(QObject *parent = 0);
+ explicit QAspectJobManager(QAspectManager *parent = nullptr);
~QAspectJobManager();
void initialize() override;
@@ -81,6 +82,7 @@ public:
private:
QThreadPooler *m_threadPooler;
+ QAspectManager *m_aspectManager;
};
} // namespace Qt3DCore
diff --git a/src/core/jobs/qaspectjobproviderinterface_p.h b/src/core/jobs/qaspectjobproviderinterface_p.h
index 29b44b3c1..b521fea68 100644
--- a/src/core/jobs/qaspectjobproviderinterface_p.h
+++ b/src/core/jobs/qaspectjobproviderinterface_p.h
@@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
class QScheduler;
+class QAspectManager;
class QAspectJobProviderInterface
{
@@ -69,6 +70,7 @@ public:
private:
virtual QVector<QAspectJobPtr> jobsToExecute(qint64 time) = 0;
+ virtual void jobsDone(QAspectManager *manager) = 0;
friend class QScheduler;
};
diff --git a/src/core/jobs/qthreadpooler.cpp b/src/core/jobs/qthreadpooler.cpp
index a9f4e7a31..f5c50062a 100644
--- a/src/core/jobs/qthreadpooler.cpp
+++ b/src/core/jobs/qthreadpooler.cpp
@@ -40,45 +40,27 @@
#include "qthreadpooler_p.h"
#include <QtCore/QDebug>
-#if QT_CONFIG(qt3d_profile_jobs)
-
-#ifdef Q_OS_ANDROID
-#include <QtCore/QStandardPaths>
-#endif
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QFile>
-#include <QtCore/QThreadStorage>
-#include <QtCore/QDateTime>
-#include <QtCore/QCoreApplication>
-#endif
-
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-#if QT_CONFIG(qt3d_profile_jobs)
-QElapsedTimer QThreadPooler::m_jobsStatTimer;
-#endif
-
QThreadPooler::QThreadPooler(QObject *parent)
: QObject(parent)
, m_futureInterface(nullptr)
, m_mutex()
, m_taskCount(0)
+ , m_threadPool(QThreadPool::globalInstance())
{
const QByteArray maxThreadCount = qgetenv("QT3D_MAX_THREAD_COUNT");
if (!maxThreadCount.isEmpty()) {
bool conversionOK = false;
const int maxThreadCountValue = maxThreadCount.toInt(&conversionOK);
if (conversionOK)
- m_threadPool.setMaxThreadCount(maxThreadCountValue);
+ m_threadPool->setMaxThreadCount(maxThreadCountValue);
}
+
// Ensures that threads will never be recycled
- m_threadPool.setExpiryTimeout(-1);
-#if QT_CONFIG(qt3d_profile_jobs)
- QThreadPooler::m_jobsStatTimer.start();
-#endif
+ m_threadPool->setExpiryTimeout(-1);
}
QThreadPooler::~QThreadPooler()
@@ -105,7 +87,7 @@ void QThreadPooler::enqueueTasks(const QVector<RunnableInterface *> &tasks)
if (!hasDependencies(*it) && !(*it)->reserved()) {
(*it)->setReserved(true);
(*it)->setPooler(this);
- m_threadPool.start((*it));
+ m_threadPool->start((*it));
}
}
}
@@ -125,7 +107,7 @@ void QThreadPooler::taskFinished(RunnableInterface *task)
if (!aspectTask->reserved()) {
aspectTask->setReserved(true);
aspectTask->setPooler(this);
- m_threadPool.start(aspectTask);
+ m_threadPool->start(aspectTask);
}
}
}
@@ -188,105 +170,9 @@ int QThreadPooler::currentCount() const
int QThreadPooler::maxThreadCount() const
{
- return m_threadPool.maxThreadCount();
-}
-
-#if QT_CONFIG(qt3d_profile_jobs)
-
-QThreadStorage<QVector<JobRunStats> *> jobStatsCached;
-
-QVector<QVector<JobRunStats> *> localStorages;
-QVector<JobRunStats> *submissionStorage = nullptr;
-
-QMutex localStoragesMutex;
-
-// Called by the jobs
-void QThreadPooler::addJobLogStatsEntry(JobRunStats &stats)
-{
- if (!jobStatsCached.hasLocalData()) {
- auto jobVector = new QVector<JobRunStats>;
- jobStatsCached.setLocalData(jobVector);
- QMutexLocker lock(&localStoragesMutex);
- localStorages.push_back(jobVector);
- }
- jobStatsCached.localData()->push_back(stats);
-}
-
-// Called after jobs have been executed (MainThread QAspectJobManager::enqueueJobs)
-void QThreadPooler::writeFrameJobLogStats()
-{
- static QScopedPointer<QFile> traceFile;
- static quint32 frameId = 0;
- if (!traceFile) {
- const QString fileName = QStringLiteral("trace_") + QCoreApplication::applicationName() + QDateTime::currentDateTime().toString(QStringLiteral("_ddd_dd_MM_yy-hh_mm_ss_"))+ QSysInfo::productType() + QStringLiteral("_") + QSysInfo::buildAbi() + QStringLiteral(".qt3d");
-#ifdef Q_OS_ANDROID
- traceFile.reset(new QFile(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + QStringLiteral("/") + fileName));
-#else
- traceFile.reset(new QFile(fileName));
-#endif
- if (!traceFile->open(QFile::WriteOnly|QFile::Truncate))
- qCritical("Failed to open trace file");
- }
-
- // Write Aspect + Job threads
- {
- FrameHeader header;
- header.frameId = frameId;
- header.jobCount = 0;
-
- for (const QVector<JobRunStats> *storage : qAsConst(localStorages))
- header.jobCount += storage->size();
-
- traceFile->write(reinterpret_cast<char *>(&header), sizeof(FrameHeader));
-
- for (QVector<JobRunStats> *storage : qAsConst(localStorages)) {
- for (const JobRunStats &stat : *storage)
- traceFile->write(reinterpret_cast<const char *>(&stat), sizeof(JobRunStats));
- storage->clear();
- }
- }
-
- // Write submission thread
- {
- QMutexLocker lock(&localStoragesMutex);
- const int submissionJobSize = submissionStorage != nullptr ? submissionStorage->size() : 0;
- if (submissionJobSize > 0) {
- FrameHeader header;
- header.frameId = frameId;
- header.jobCount = submissionJobSize;
- header.frameType = FrameHeader::Submission;
-
- traceFile->write(reinterpret_cast<char *>(&header), sizeof(FrameHeader));
-
- for (const JobRunStats &stat : *submissionStorage)
- traceFile->write(reinterpret_cast<const char *>(&stat), sizeof(JobRunStats));
- submissionStorage->clear();
- }
- }
-
- traceFile->flush();
- ++frameId;
-}
-
-// Called from Submission thread (which can be main thread in Manual drive mode)
-void QThreadPooler::addSubmissionLogStatsEntry(JobRunStats &stats)
-{
- QMutexLocker lock(&localStoragesMutex);
- if (!jobStatsCached.hasLocalData()) {
- submissionStorage = new QVector<JobRunStats>;
- jobStatsCached.setLocalData(submissionStorage);
- }
-
- // Handle the case where submission thread is also the main thread (Scene/Manual drive modes with no RenderThread)
- if (submissionStorage == nullptr && jobStatsCached.hasLocalData())
- submissionStorage = new QVector<JobRunStats>;
-
- // When having no submission thread this can be null
- submissionStorage->push_back(stats);
+ return m_threadPool->maxThreadCount();
}
-#endif
-
} // namespace Qt3DCore
QT_END_NAMESPACE
diff --git a/src/core/jobs/qthreadpooler_p.h b/src/core/jobs/qthreadpooler_p.h
index 65459efba..1970641b8 100644
--- a/src/core/jobs/qthreadpooler_p.h
+++ b/src/core/jobs/qthreadpooler_p.h
@@ -60,10 +60,6 @@
#include <Qt3DCore/private/qaspectjob_p.h>
#include <Qt3DCore/private/task_p.h>
-#if QT_CONFIG(qt3d_profile_jobs)
-#include <QtCore/QElapsedTimer>
-#endif
-
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
@@ -81,17 +77,6 @@ public:
QFuture<void> future();
int maxThreadCount() const;
-#if QT_CONFIG(qt3d_profile_jobs)
- static QElapsedTimer m_jobsStatTimer;
-
- // Aspects + Job threads
- static void addJobLogStatsEntry(JobRunStats &stats);
- static void writeFrameJobLogStats();
-
- // Submission thread
- static void addSubmissionLogStatsEntry(JobRunStats &stats);
-
-#endif
private:
void enqueueTasks(const QVector<RunnableInterface *> &tasks);
@@ -103,7 +88,7 @@ private:
QFutureInterface<void> *m_futureInterface;
QMutex m_mutex;
QAtomicInt m_taskCount;
- QThreadPool m_threadPool;
+ QThreadPool *m_threadPool;
};
} // namespace Qt3DCore
diff --git a/src/core/jobs/task.cpp b/src/core/jobs/task.cpp
index 091aabfd6..1dd5712c9 100644
--- a/src/core/jobs/task.cpp
+++ b/src/core/jobs/task.cpp
@@ -44,6 +44,7 @@
#include <QtCore/QMutexLocker>
#include <Qt3DCore/private/qthreadpooler_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p_p.h>
QT_BEGIN_NAMESPACE
@@ -55,8 +56,10 @@ RunnableInterface::~RunnableInterface()
// Aspect task
-AspectTaskRunnable::AspectTaskRunnable()
- : m_pooler(nullptr)
+AspectTaskRunnable::AspectTaskRunnable(QSystemInformationService *service)
+ : m_service(service)
+ , m_pooler(nullptr)
+ , m_id(0)
, m_reserved(false)
{
}
@@ -68,21 +71,9 @@ AspectTaskRunnable::~AspectTaskRunnable()
void AspectTaskRunnable::run()
{
if (m_job) {
-#if QT_CONFIG(qt3d_profile_jobs)
QAspectJobPrivate *jobD = QAspectJobPrivate::get(m_job.data());
- if (m_pooler) {
- jobD->m_stats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- jobD->m_stats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
- }
-#endif
+ QTaskLogger logger(m_pooler ? m_service : nullptr, jobD->m_jobId, QTaskLogger::AspectJob);
m_job->run();
-#if QT_CONFIG(qt3d_profile_jobs)
- if (m_pooler) {
- jobD->m_stats.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- // Add current job's stats to log output
- QThreadPooler::addJobLogStatsEntry(jobD->m_stats);
- }
-#endif
}
// We could have an append sub task or something in here
diff --git a/src/core/jobs/task_p.h b/src/core/jobs/task_p.h
index c81882719..ff411539f 100644
--- a/src/core/jobs/task_p.h
+++ b/src/core/jobs/task_p.h
@@ -65,6 +65,7 @@ namespace Qt3DCore {
class JobRunner;
class DependencyHandler;
class QThreadPooler;
+class QSystemInformationService;
class RunnableInterface : public QRunnable
{
@@ -92,7 +93,7 @@ public:
class AspectTaskRunnable : public RunnableInterface
{
public:
- AspectTaskRunnable();
+ AspectTaskRunnable(QSystemInformationService *service);
~AspectTaskRunnable();
void run() override;
@@ -113,6 +114,7 @@ public:
int m_dependerCount = 0;
private:
+ QSystemInformationService *m_service;
QThreadPooler *m_pooler;
int m_id; // For testing purposes for now
bool m_reserved;
diff --git a/src/core/nodes/qbackendnode.cpp b/src/core/nodes/qbackendnode.cpp
index e5f93e96f..4138ea060 100644
--- a/src/core/nodes/qbackendnode.cpp
+++ b/src/core/nodes/qbackendnode.cpp
@@ -220,6 +220,7 @@ QBackendNode::QBackendNode(QBackendNodePrivate &dd)
/*!
* Notifies observers of scene change \a e.
+ * \obsolete
*/
void QBackendNode::notifyObservers(const QSceneChangePtr &e)
{
@@ -228,6 +229,8 @@ void QBackendNode::notifyObservers(const QSceneChangePtr &e)
}
/*!
+ \obsolete
+
Send the command named \a name with contents \a data,
and specify \a replyTo as the command id to which the
reply needs to be sent.
@@ -247,6 +250,7 @@ QNodeCommand::CommandId QBackendNode::sendCommand(const QString &name,
/*!
Send the reply to \a command.
+ \obsolete
*/
void QBackendNode::sendReply(const QNodeCommandPtr &command)
{
@@ -254,9 +258,12 @@ void QBackendNode::sendReply(const QNodeCommandPtr &command)
notifyObservers(command);
}
+/*!
+ * \obsolete
+ */
void QBackendNode::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
{
- Q_UNUSED(change);
+ Q_UNUSED(change)
qCDebug(Nodes) << Q_FUNC_INFO << change->metaObject()->className() << "does not override";
}
@@ -270,8 +277,7 @@ void QBackendNode::setEnabled(bool enabled) Q_DECL_NOTHROW
}
/*!
- * TODO
- * \a e
+ * \obsolete
*/
void QBackendNode::sceneChangeEvent(const QSceneChangePtr &e)
{
diff --git a/src/core/nodes/qbackendnode.h b/src/core/nodes/qbackendnode.h
index 550ced04f..691375999 100644
--- a/src/core/nodes/qbackendnode.h
+++ b/src/core/nodes/qbackendnode.h
@@ -90,18 +90,18 @@ public:
protected:
Q_DECLARE_PRIVATE(QBackendNode)
explicit QBackendNode(QBackendNodePrivate &dd);
- void notifyObservers(const QSceneChangePtr &e);
- QNodeCommand::CommandId sendCommand(const QString &name, const QVariant &data,
- QNodeCommand::CommandId replyTo = QNodeCommand::CommandId());
- void sendReply(const QNodeCommandPtr &command);
- virtual void sceneChangeEvent(const QSceneChangePtr &e);
+ Q3D_DECL_DEPRECATED void notifyObservers(const QSceneChangePtr &e);
+ Q3D_DECL_DEPRECATED QNodeCommand::CommandId sendCommand(const QString &name, const QVariant &data,
+ QNodeCommand::CommandId replyTo = QNodeCommand::CommandId());
+ Q3D_DECL_DEPRECATED void sendReply(const QNodeCommandPtr &command);
+ Q3D_DECL_DEPRECATED virtual void sceneChangeEvent(const QSceneChangePtr &e);
QBackendNodePrivate *d_ptr;
private:
Q_DISABLE_COPY(QBackendNode)
void setPeerId(QNodeId id) Q_DECL_NOEXCEPT;
- virtual void initializeFromPeer(const QNodeCreatedChangeBasePtr &change);
+ Q3D_DECL_DEPRECATED virtual void initializeFromPeer(const QNodeCreatedChangeBasePtr &change);
friend class QBackendNodePropertyChange;
friend class QAbstractAspectPrivate;
diff --git a/src/core/nodes/qentity.cpp b/src/core/nodes/qentity.cpp
index 024991387..93601901f 100644
--- a/src/core/nodes/qentity.cpp
+++ b/src/core/nodes/qentity.cpp
@@ -75,7 +75,7 @@ namespace Qt3DCore {
*/
/*!
- \fn template<typename T> QVector<T *> QEntity::componentsOfType() const
+ \fn template<typename T> QVector<T *> Qt3DCore::QEntity::componentsOfType() const
Returns all the components added to this entity that can be cast to
type T or an empty vector if there are no such components.
diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp
index cfe83f4db..ad084242f 100644
--- a/src/core/nodes/qnode.cpp
+++ b/src/core/nodes/qnode.cpp
@@ -382,7 +382,7 @@ void QNodePrivate::unregisterNotifiedProperties()
void QNodePrivate::propertyChanged(int propertyIndex)
{
- Q_UNUSED(propertyIndex);
+ Q_UNUSED(propertyIndex)
// Bail out early if we can to avoid the cost below
if (m_blockNotifications)
@@ -539,6 +539,8 @@ void QNode::notifyObservers(const QSceneChangePtr &change)
}
/*!
+ \obsolete
+
Called when one or more backend aspects sends a notification \a change to the
current Qt3DCore::QNode instance.
@@ -547,7 +549,7 @@ void QNode::notifyObservers(const QSceneChangePtr &change)
*/
void QNode::sceneChangeEvent(const QSceneChangePtr &change)
{
- Q_UNUSED(change);
+ Q_UNUSED(change)
if (change->type() == Qt3DCore::PropertyUpdated) {
// TODO: Do this more efficiently. We could pass the metaobject and property
// index to the animation aspect via the QChannelMapping. This would
@@ -594,8 +596,8 @@ QScene *QNodePrivate::scene() const
*/
void QNodePrivate::notifyPropertyChange(const char *name, const QVariant &value)
{
- Q_UNUSED(name);
- Q_UNUSED(value);
+ Q_UNUSED(name)
+ Q_UNUSED(value)
// Bail out early if we can to avoid operator new
if (m_blockNotifications)
@@ -606,8 +608,8 @@ void QNodePrivate::notifyPropertyChange(const char *name, const QVariant &value)
void QNodePrivate::notifyDynamicPropertyChange(const QByteArray &name, const QVariant &value)
{
- Q_UNUSED(name);
- Q_UNUSED(value);
+ Q_UNUSED(name)
+ Q_UNUSED(value)
// Bail out early if we can to avoid operator new
if (m_blockNotifications)
@@ -683,6 +685,11 @@ void QNodePrivate::update()
void QNodePrivate::updateNode(QNode *node, const char *property, ChangeFlag change)
{
if (m_changeArbiter) {
+ // Ensure node has its postConstructorInit called if we reach this
+ // point, we could otherwise endup referencing a node that has yet
+ // to be created in the backend
+ QNodePrivate::get(node)->_q_ensureBackendNodeCreated();
+
Q_Q(QNode);
m_changeArbiter->addDirtyFrontEndNode(q, node, property, change);
}
@@ -787,10 +794,9 @@ QNode::~QNode()
{
Q_D(QNode);
// Disconnect each connection that was stored
- for (auto it = d->m_destructionConnections.begin(), end = d->m_destructionConnections.end(); it != end; ++it)
- QObject::disconnect(it.value());
+ for (const auto &nodeConnectionPair : qAsConst(d->m_destructionConnections))
+ QObject::disconnect(nodeConnectionPair.second);
d->m_destructionConnections.clear();
-
Q_EMIT nodeDestroyed();
// Notify the backend that the parent lost this node as a child and
@@ -993,6 +999,9 @@ void QNode::clearPropertyTrackings()
d->updatePropertyTrackMode();
}
+/*!
+ * \obsolete
+ */
QNodeCreatedChangeBasePtr QNode::createNodeCreationChange() const
{
// Uncomment this when implementing new frontend and backend types.
@@ -1045,6 +1054,7 @@ QNodeCreatedChangeBasePtr QNode::createNodeCreationChange() const
*/
/*!
* \brief Sends a command message to the backend node
+ * \obsolete
*
* Creates a QNodeCommand message and dispatches it to the backend node. The
* command is given and a \a name and some \a data which can be used in the
@@ -1075,6 +1085,7 @@ QNodeCommand::CommandId QNode::sendCommand(const QString &name,
/*!
* \brief Send a \a command back to the backend node.
+ * \obsolete
*
* Assumes the command is to be to sent back in reply to itself to the backend node.
*
diff --git a/src/core/nodes/qnode.h b/src/core/nodes/qnode.h
index 9ca817fb6..efdec8da5 100644
--- a/src/core/nodes/qnode.h
+++ b/src/core/nodes/qnode.h
@@ -99,9 +99,9 @@ public:
void clearPropertyTracking(const QString &propertyName);
void clearPropertyTrackings();
- QNodeCommand::CommandId sendCommand(const QString &name, const QVariant &data = QVariant(),
- QNodeCommand::CommandId replyTo = QNodeCommand::CommandId());
- void sendReply(const QNodeCommandPtr &command);
+ Q3D_DECL_DEPRECATED QNodeCommand::CommandId sendCommand(const QString &name, const QVariant &data = QVariant(),
+ QNodeCommand::CommandId replyTo = QNodeCommand::CommandId());
+ Q3D_DECL_DEPRECATED void sendReply(const QNodeCommandPtr &command);
public Q_SLOTS:
void setParent(QNode *parent);
@@ -116,12 +116,12 @@ Q_SIGNALS:
protected:
explicit QNode(QNodePrivate &dd, QNode *parent = nullptr);
- void notifyObservers(const QSceneChangePtr &change);
- virtual void sceneChangeEvent(const QSceneChangePtr &change);
+ Q3D_DECL_DEPRECATED void notifyObservers(const QSceneChangePtr &change);
+ Q3D_DECL_DEPRECATED virtual void sceneChangeEvent(const QSceneChangePtr &change);
private:
Q_DECLARE_PRIVATE(QNode)
- virtual QNodeCreatedChangeBasePtr createNodeCreationChange() const;
+ Q3D_DECL_DEPRECATED virtual QNodeCreatedChangeBasePtr createNodeCreationChange() const;
// We only want setParent(QNode *) to be callable
// when dealing with QNode objects
diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h
index a7a300a5e..61aa81c81 100644
--- a/src/core/nodes/qnode_p.h
+++ b/src/core/nodes/qnode_p.h
@@ -124,7 +124,7 @@ public:
// If the node is destoyed, we make sure not to keep a dangling pointer to it
Q_Q(QNode);
auto f = [q, func]() { (static_cast<Caller *>(q)->*func)(nullptr); };
- m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f));
+ m_destructionConnections.push_back({node, QObject::connect(node, &QNode::nodeDestroyed, f)});
}
template<typename Caller, typename NodeType>
@@ -133,7 +133,7 @@ public:
// If the node is destoyed, we make sure not to keep a dangling pointer to it
Q_Q(QNode);
auto f = [q, func, node]() { (static_cast<Caller *>(q)->*func)(node); };
- m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f));
+ m_destructionConnections.push_back({node, QObject::connect(node, &QNode::nodeDestroyed, f)});
}
template<typename Caller, typename ValueType>
@@ -146,7 +146,7 @@ public:
// If the node is destoyed, we make sure not to keep a dangling pointer to it
Q_Q(QNode);
auto f = [q, func, resetValue]() { (static_cast<Caller *>(q)->*func)(resetValue); };
- m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f));
+ m_destructionConnections.push_back({node, QObject::connect(node, &QNode::nodeDestroyed, f)});
}
template<typename Caller, typename NodeType>
@@ -154,12 +154,21 @@ public:
{
// If the node is destoyed, we make sure not to keep a dangling pointer to it
auto f = [this, func, node]() { (static_cast<Caller *>(this)->*func)(node); };
- m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f));
+ m_destructionConnections.push_back({node, QObject::connect(node, &QNode::nodeDestroyed, f)});
}
void unregisterDestructionHelper(QNode *node)
{
- QObject::disconnect(m_destructionConnections.take(node));
+ m_destructionConnections.erase(std::remove_if(m_destructionConnections.begin(),
+ m_destructionConnections.end(),
+ [node] (const QPair<QNode *, QMetaObject::Connection> &nodeConnectionPair) {
+ if (nodeConnectionPair.first == node) {
+ QObject::disconnect(nodeConnectionPair.second);
+ return true;
+ }
+ return false;
+ }),
+ m_destructionConnections.end());
}
static const QMetaObject *findStaticMetaObject(const QMetaObject *metaObject);
@@ -184,7 +193,7 @@ private:
friend class PropertyChangeHandler<QNodePrivate>;
bool m_propertyChangesSetup;
PropertyChangeHandler<QNodePrivate> m_signals;
- QHash<QNode *, QMetaObject::Connection> m_destructionConnections;
+ QVector<QPair<QNode *, QMetaObject::Connection>> m_destructionConnections;
};
class NodePostConstructorInit : public QObject
diff --git a/src/core/qchangearbiter_p.h b/src/core/qchangearbiter_p.h
index f31480685..7d48c390a 100644
--- a/src/core/qchangearbiter_p.h
+++ b/src/core/qchangearbiter_p.h
@@ -64,6 +64,7 @@
#include <Qt3DCore/private/qlockableobserverinterface_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
+#include <Qt3DCore/private/qscenechange_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/qpostman_p.h b/src/core/qpostman_p.h
index 23c638239..3e5f91742 100644
--- a/src/core/qpostman_p.h
+++ b/src/core/qpostman_p.h
@@ -75,7 +75,7 @@ class Q_AUTOTEST_EXPORT QPostman final
{
Q_OBJECT
public:
- explicit QPostman(QObject *parent = 0);
+ explicit QPostman(QObject *parent = nullptr);
~QPostman();
void setScene(QScene *sceneLookup) final;
diff --git a/src/core/qscheduler.cpp b/src/core/qscheduler.cpp
index edfbb391c..2294976ca 100644
--- a/src/core/qscheduler.cpp
+++ b/src/core/qscheduler.cpp
@@ -43,6 +43,7 @@
#include <Qt3DCore/private/qabstractaspect_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qaspectjob_p.h>
#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
QT_BEGIN_NAMESPACE
@@ -69,7 +70,7 @@ QAspectManager *QScheduler::aspectManager() const
return m_aspectManager;
}
-void QScheduler::scheduleAndWaitForFrameAspectJobs(qint64 time)
+int QScheduler::scheduleAndWaitForFrameAspectJobs(qint64 time)
{
QVector<QAspectJobPtr> jobQueue;
@@ -92,8 +93,17 @@ void QScheduler::scheduleAndWaitForFrameAspectJobs(qint64 time)
m_aspectManager->jobManager()->waitForAllJobs();
- for (auto &job : qAsConst(jobQueue))
- job->postFrame(m_aspectManager);
+ {
+ QTaskLogger logger(m_aspectManager->serviceLocator()->systemInformation(), 4097, 0);
+
+ for (auto &job : qAsConst(jobQueue))
+ QAspectJobPrivate::get(job.data())->postFrame(m_aspectManager);
+
+ for (QAbstractAspect *aspect : aspects)
+ QAbstractAspectPrivate::get(aspect)->jobsDone(m_aspectManager);
+ }
+
+ return jobQueue.size();
}
} // namespace Qt3DCore
diff --git a/src/core/qscheduler_p.h b/src/core/qscheduler_p.h
index 9b1685e54..dd4101ef2 100644
--- a/src/core/qscheduler_p.h
+++ b/src/core/qscheduler_p.h
@@ -64,13 +64,13 @@ class QScheduler : public QObject
{
Q_OBJECT
public:
- explicit QScheduler(QObject *parent = 0);
+ explicit QScheduler(QObject *parent = nullptr);
~QScheduler();
void setAspectManager(QAspectManager *aspectManager);
QAspectManager *aspectManager() const;
- virtual void scheduleAndWaitForFrameAspectJobs(qint64 time);
+ virtual int scheduleAndWaitForFrameAspectJobs(qint64 time);
private:
QAspectManager *m_aspectManager;
diff --git a/src/core/qt3dcore_global.h b/src/core/qt3dcore_global.h
index b2ad787c0..e932b02ba 100644
--- a/src/core/qt3dcore_global.h
+++ b/src/core/qt3dcore_global.h
@@ -55,6 +55,12 @@ QT_BEGIN_NAMESPACE
# define Q_3DCORESHARED_EXPORT
#endif
+#ifdef BUILD_QT3D_MODULE
+#define Q3D_DECL_DEPRECATED
+#else
+#define Q3D_DECL_DEPRECATED Q_DECL_DEPRECATED
+#endif
+
#define QT3D_DECLARE_TYPEINFO(NS, Class, Flags) \
} /* NS */ \
Q_DECLARE_TYPEINFO(NS :: Class, Flags); \
diff --git a/src/core/resources/qframeallocator.cpp b/src/core/resources/qframeallocator.cpp
index 61a82a2b4..e85ae4057 100644
--- a/src/core/resources/qframeallocator.cpp
+++ b/src/core/resources/qframeallocator.cpp
@@ -57,6 +57,8 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
QFrameAllocatorPrivate::QFrameAllocatorPrivate()
+ : m_maxObjectSize(0U)
+ , m_alignment(0U)
{
}
diff --git a/src/core/resources/qloadgltf_p.h b/src/core/resources/qloadgltf_p.h
new file mode 100644
index 000000000..be7ee0d5f
--- /dev/null
+++ b/src/core/resources/qloadgltf_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QLOADGLTF_P_H
+#define QT3DCORE_QLOADGLTF_P_H
+
+#include <QtCore/qcborarray.h>
+#include <QtCore/qcbormap.h>
+#include <QtCore/qcborvalue.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonobject.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+inline QJsonDocument qLoadGLTF(const QByteArray &gltfData)
+{
+#if QT_CONFIG(binaryjson)
+ {
+ QJsonDocument sceneDocument = QJsonDocument::fromBinaryData(gltfData);
+ if (!sceneDocument.isNull())
+ return sceneDocument;
+ }
+#endif
+ {
+ const QCborValue cbor = QCborValue::fromCbor(gltfData);
+ if (cbor.isMap())
+ return QJsonDocument(cbor.toMap().toJsonObject());
+ if (cbor.isArray())
+ return QJsonDocument(cbor.toArray().toJsonArray());
+ }
+ return QJsonDocument::fromJson(gltfData);
+}
+
+#endif // QT3DCORE_QLOADGLTF_P_H
diff --git a/src/core/resources/resources.pri b/src/core/resources/resources.pri
index 7f3ce4bdc..89540a36d 100644
--- a/src/core/resources/resources.pri
+++ b/src/core/resources/resources.pri
@@ -1,4 +1,5 @@
HEADERS += \
+ $$PWD/qloadgltf_p.h \
$$PWD/qresourcemanager_p.h \
$$PWD/qcircularbuffer_p.h \
$$PWD/qboundedcircularbuffer_p.h \
diff --git a/src/core/services/nullservices_p.h b/src/core/services/nullservices_p.h
index 30dc2d543..6b2d1b029 100644
--- a/src/core/services/nullservices_p.h
+++ b/src/core/services/nullservices_p.h
@@ -54,25 +54,11 @@
#include <Qt3DCore/qt3dcore_global.h>
#include <Qt3DCore/private/qopenglinformationservice_p.h>
-#include <Qt3DCore/private/qsysteminformationservice_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-class NullSystemInformationService : public QSystemInformationService
-{
-public:
- NullSystemInformationService()
- : QSystemInformationService(QStringLiteral("Null System Information Service"))
- {}
- ~NullSystemInformationService() {}
-
- QStringList aspectNames() const final { return QStringList(); }
- int threadPoolThreadCount() const final { return 0; }
-};
-
-
class NullOpenGLInformationService : public QOpenGLInformationService
{
public:
diff --git a/src/core/services/qservicelocator.cpp b/src/core/services/qservicelocator.cpp
index bdcb4a521..73a40c2e4 100644
--- a/src/core/services/qservicelocator.cpp
+++ b/src/core/services/qservicelocator.cpp
@@ -46,6 +46,7 @@
#include <Qt3DCore/private/qdownloadhelperservice_p.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
#include <Qt3DCore/private/qtickclockservice_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p.h>
QT_BEGIN_NAMESPACE
@@ -85,16 +86,19 @@ QString QAbstractServiceProvider::description() const
}
+class QAspectEngine;
+
class QServiceLocatorPrivate
{
public:
- QServiceLocatorPrivate()
- : m_nonNullDefaultServices(0)
+ QServiceLocatorPrivate(QAspectEngine *aspectEngine)
+ : m_systemInfo(aspectEngine)
+ , m_nonNullDefaultServices(0)
{}
QHash<int, QAbstractServiceProvider *> m_services;
- NullSystemInformationService m_nullSystemInfo;
+ QSystemInformationService m_systemInfo;
NullOpenGLInformationService m_nullOpenGLInfo;
QTickClockService m_defaultFrameAdvanceService;
QEventFilterService m_eventFilterService;
@@ -128,8 +132,8 @@ public:
/*
Creates an instance of QServiceLocator.
*/
-QServiceLocator::QServiceLocator()
- : d_ptr(new QServiceLocatorPrivate)
+QServiceLocator::QServiceLocator(QAspectEngine *aspectEngine)
+ : d_ptr(new QServiceLocatorPrivate(aspectEngine))
{
}
@@ -196,7 +200,7 @@ int QServiceLocator::serviceCount() const
QSystemInformationService *QServiceLocator::systemInformation()
{
Q_D(QServiceLocator);
- return static_cast<QSystemInformationService *>(d->m_services.value(SystemInformation, &d->m_nullSystemInfo));
+ return static_cast<QSystemInformationService *>(d->m_services.value(SystemInformation, &d->m_systemInfo));
}
/*
diff --git a/src/core/services/qservicelocator_p.h b/src/core/services/qservicelocator_p.h
index 9111a14ab..5bf71a996 100644
--- a/src/core/services/qservicelocator_p.h
+++ b/src/core/services/qservicelocator_p.h
@@ -85,11 +85,12 @@ class QSystemInformationService;
class QServiceLocatorPrivate;
class QEventFilterService;
class QDownloadHelperService;
+class QAspectEngine;
class Q_3DCORESHARED_EXPORT QServiceLocator
{
public:
- QServiceLocator();
+ QServiceLocator(QAspectEngine *aspectEngine = nullptr);
~QServiceLocator();
enum ServiceType {
diff --git a/src/core/services/qsysteminformationservice.cpp b/src/core/services/qsysteminformationservice.cpp
index f11e0c3d1..40f3594fb 100644
--- a/src/core/services/qsysteminformationservice.cpp
+++ b/src/core/services/qsysteminformationservice.cpp
@@ -40,10 +40,220 @@
#include "qsysteminformationservice_p.h"
#include "qsysteminformationservice_p_p.h"
+#ifdef Q_OS_ANDROID
+#include <QtCore/QStandardPaths>
+#endif
+
+#include <QtCore/QThreadPool>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFile>
+#include <QtCore/QDateTime>
+#include <QtCore/QCoreApplication>
+
+#include <Qt3DCore/QAspectEngine>
+#include <Qt3DCore/QAbstractAspect>
+#include <Qt3DCore/private/qaspectengine_p.h>
+#include <Qt3DCore/private/aspectcommanddebugger_p.h>
+
QT_BEGIN_NAMESPACE
+namespace {
+
+struct FrameHeader
+{
+ FrameHeader()
+ : frameId(0)
+ , jobCount(0)
+ , frameType(WorkerJob)
+ {
+ }
+
+ enum FrameType {
+ WorkerJob = 0,
+ Submission
+ };
+
+ quint32 frameId;
+ quint16 jobCount;
+ quint16 frameType; // Submission or worker job
+};
+
+}
namespace Qt3DCore {
+QSystemInformationServicePrivate::QSystemInformationServicePrivate(QAspectEngine *aspectEngine,
+ const QString &description)
+ : QAbstractServiceProviderPrivate(QServiceLocator::SystemInformation, description)
+ , m_aspectEngine(aspectEngine)
+ , m_submissionStorage(nullptr)
+ , m_frameId(0)
+ , m_commandDebugger(nullptr)
+{
+ m_traceEnabled = qEnvironmentVariableIsSet("QT3D_TRACE_ENABLED");
+ if (m_traceEnabled)
+ m_jobsStatTimer.start();
+
+ const bool commandServerEnabled = qEnvironmentVariableIsSet("QT3D_COMMAND_SERVER_ENABLED");
+ if (commandServerEnabled) {
+ m_commandDebugger = new Debug::AspectCommandDebugger(q_func());
+ m_commandDebugger->initialize();
+ }
+}
+
+QSystemInformationServicePrivate::~QSystemInformationServicePrivate() = default;
+
+QSystemInformationServicePrivate *QSystemInformationServicePrivate::get(QSystemInformationService *q)
+{
+ return q->d_func();
+}
+
+// Called by the jobs
+void QSystemInformationServicePrivate::addJobLogStatsEntry(QSystemInformationServicePrivate::JobRunStats &stats)
+{
+ if (!m_traceEnabled)
+ return;
+
+ if (!m_jobStatsCached.hasLocalData()) {
+ auto jobVector = new QVector<JobRunStats>;
+ m_jobStatsCached.setLocalData(jobVector);
+ QMutexLocker lock(&m_localStoragesMutex);
+ m_localStorages.push_back(jobVector);
+ }
+ m_jobStatsCached.localData()->push_back(stats);
+}
+
+// Called from Submission thread (which can be main thread in Manual drive mode)
+void QSystemInformationServicePrivate::addSubmissionLogStatsEntry(QSystemInformationServicePrivate::JobRunStats &stats)
+{
+ if (!m_traceEnabled)
+ return;
+
+ QMutexLocker lock(&m_localStoragesMutex);
+ if (!m_jobStatsCached.hasLocalData()) {
+ m_submissionStorage = new QVector<JobRunStats>;
+ m_jobStatsCached.setLocalData(m_submissionStorage);
+ }
+
+ // Handle the case where submission thread is also the main thread (Scene/Manual drive modes with no RenderThread)
+ if (m_submissionStorage == nullptr && m_jobStatsCached.hasLocalData())
+ m_submissionStorage = new QVector<JobRunStats>;
+
+ // When having no submission thread this can be null
+ m_submissionStorage->push_back(stats);
+}
+
+// Called after jobs have been executed (MainThread QAspectJobManager::enqueueJobs)
+void QSystemInformationServicePrivate::writeFrameJobLogStats()
+{
+ if (!m_traceEnabled)
+ return;
+
+ using JobRunStats = QSystemInformationServicePrivate::JobRunStats;
+
+ if (!m_traceFile) {
+ const QString fileName = QStringLiteral("trace_") + QCoreApplication::applicationName() + QDateTime::currentDateTime().toString(QStringLiteral("_ddd_dd_MM_yy-hh_mm_ss_"))+ QSysInfo::productType() + QStringLiteral("_") + QSysInfo::buildAbi() + QStringLiteral(".qt3d");
+#ifdef Q_OS_ANDROID
+ m_traceFile.reset(new QFile(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + QStringLiteral("/") + fileName));
+#else
+ // TODO fix for iOS
+ m_traceFile.reset(new QFile(fileName));
+#endif
+ if (!m_traceFile->open(QFile::WriteOnly|QFile::Truncate))
+ qCritical("Failed to open trace file");
+ }
+
+ // Write Aspect + Job threads
+ {
+ FrameHeader header;
+ header.frameId = m_frameId;
+ header.jobCount = 0;
+
+ for (const QVector<JobRunStats> *storage : qAsConst(m_localStorages))
+ header.jobCount += storage->size();
+
+ m_traceFile->write(reinterpret_cast<char *>(&header), sizeof(FrameHeader));
+
+ for (QVector<JobRunStats> *storage : qAsConst(m_localStorages)) {
+ for (const JobRunStats &stat : *storage)
+ m_traceFile->write(reinterpret_cast<const char *>(&stat), sizeof(JobRunStats));
+ storage->clear();
+ }
+ }
+
+ // Write submission thread
+ {
+ QMutexLocker lock(&m_localStoragesMutex);
+ const int submissionJobSize = m_submissionStorage != nullptr ? m_submissionStorage->size() : 0;
+ if (submissionJobSize > 0) {
+ FrameHeader header;
+ header.frameId = m_frameId;
+ header.jobCount = submissionJobSize;
+ header.frameType = FrameHeader::Submission;
+
+ m_traceFile->write(reinterpret_cast<char *>(&header), sizeof(FrameHeader));
+
+ for (const JobRunStats &stat : *m_submissionStorage)
+ m_traceFile->write(reinterpret_cast<const char *>(&stat), sizeof(JobRunStats));
+ m_submissionStorage->clear();
+ }
+ }
+
+ m_traceFile->flush();
+ ++m_frameId;
+}
+
+
+QTaskLogger::QTaskLogger(QSystemInformationService *service, const JobId &jobId, Type type)
+ : m_service(service && service->isTraceEnabled() ? service : nullptr)
+ , m_type(type)
+{
+ m_stats.jobId = jobId;
+ if (m_service) {
+ m_stats.startTime = QSystemInformationServicePrivate::get(m_service)->m_jobsStatTimer.nsecsElapsed();
+ m_stats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
+ }
+}
+
+QTaskLogger::QTaskLogger(QSystemInformationService *service,
+ const quint32 jobType,
+ const quint32 instance,
+ QTaskLogger::Type type)
+ : m_service(service && service->isTraceEnabled() ? service : nullptr)
+ , m_type(type)
+{
+ m_stats.jobId.typeAndInstance[0] = jobType;
+ m_stats.jobId.typeAndInstance[1] = instance;
+ if (m_service) {
+ m_stats.startTime = QSystemInformationServicePrivate::get(m_service)->m_jobsStatTimer.nsecsElapsed();
+ m_stats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
+ }
+}
+
+QTaskLogger::~QTaskLogger() {
+ if (m_service) {
+ auto dservice = QSystemInformationServicePrivate::get(m_service);
+ if (m_stats.endTime == 0L)
+ m_stats.endTime = dservice->m_jobsStatTimer.nsecsElapsed();
+ switch (m_type) {
+ case AspectJob: dservice->addJobLogStatsEntry(m_stats); break;
+ case Submission: dservice->addSubmissionLogStatsEntry(m_stats); break;
+ }
+ }
+}
+
+void QTaskLogger::end(qint64 t)
+{
+ m_stats.endTime = t > 0 || !m_service ? t : QSystemInformationServicePrivate::get(m_service)->m_jobsStatTimer.nsecsElapsed();
+}
+
+qint64 QTaskLogger::restart()
+{
+ if (m_service)
+ m_stats.startTime = QSystemInformationServicePrivate::get(m_service)->m_jobsStatTimer.nsecsElapsed();
+ return m_stats.startTime;
+}
+
+
/* !\internal
\class Qt3DCore::QSystemInformationService
\inmodule Qt3DCore
@@ -58,8 +268,14 @@ namespace Qt3DCore {
the new service. This constructor is protected so only subclasses can
instantiate a QSystemInformationService object.
*/
-QSystemInformationService::QSystemInformationService(const QString &description)
- : QAbstractServiceProvider(*new QSystemInformationServicePrivate(description))
+
+QSystemInformationService::QSystemInformationService(QAspectEngine *aspectEngine)
+ : QAbstractServiceProvider(*new QSystemInformationServicePrivate(aspectEngine, QLatin1String("Default System Information Service")))
+{
+}
+
+QSystemInformationService::QSystemInformationService(QAspectEngine *aspectEngine, const QString &description)
+ : QAbstractServiceProvider(*new QSystemInformationServicePrivate(aspectEngine, description))
{
}
@@ -71,19 +287,93 @@ QSystemInformationService::QSystemInformationService(QSystemInformationServicePr
{
}
+bool QSystemInformationService::isTraceEnabled() const
+{
+ Q_D(const QSystemInformationService);
+ return d->m_traceEnabled;
+}
+
+bool QSystemInformationService::isCommandServerEnabled() const
+{
+ Q_D(const QSystemInformationService);
+ return d->m_commandDebugger != nullptr;
+}
+
+void QSystemInformationService::setTraceEnabled(bool traceEnabled)
+{
+ Q_D(QSystemInformationService);
+ if (d->m_traceEnabled != traceEnabled) {
+ d->m_traceEnabled = traceEnabled;
+ emit traceEnabledChanged(d->m_traceEnabled);
+ if (d->m_traceEnabled) {
+ if (!d->m_jobsStatTimer.isValid())
+ d->m_jobsStatTimer.start();
+ } else {
+ d->m_traceFile.reset();
+ }
+ }
+}
+
/*
\fn QStringList Qt3DCore::QSystemInformationService::aspectNames() const
- Subclasses should override this function and return a string list containing the
- names of all registered aspects.
+ Returns a string list containing the names of all registered aspects.
*/
+QStringList QSystemInformationService::aspectNames() const
+{
+ Q_D(const QSystemInformationService);
+ if (!d->m_aspectEngine)
+ return {};
+
+ QStringList res;
+ const auto aspects = d->m_aspectEngine->aspects();
+ if (aspects.isEmpty())
+ return { QLatin1String("No loaded aspects") };
+
+ QAspectEnginePrivate *dengine = QAspectEnginePrivate::get(d->m_aspectEngine);
+ for (auto aspect: aspects) {
+ const QString name = dengine->m_factory.aspectName(aspect);
+ if (!name.isEmpty())
+ res << name;
+ else
+ res << QLatin1String("<unnamed>");
+ }
+
+ return res;
+}
/*
\fn int Qt3DCore::QSystemInformationService::threadPoolThreadCount() const
- Subclasses should override this function and return the number of threads in the
- Qt3D task manager's threadpool.
+ Returns the maximum number of threads in the Qt3D task manager's threadpool.
*/
+int QSystemInformationService::threadPoolThreadCount() const
+{
+ return QThreadPool::globalInstance()->maxThreadCount();
+}
+
+void QSystemInformationService::writePreviousFrameTraces()
+{
+ Q_D(QSystemInformationService);
+ d->writeFrameJobLogStats();
+}
+
+QVariant QSystemInformationService::executeCommand(const QString &command)
+{
+ Q_D(QSystemInformationService);
+
+ if (command == QLatin1String("tracing on")) {
+ setTraceEnabled(true);
+ return {isTraceEnabled()};
+ }
+
+ if (command == QLatin1String("tracing off")) {
+ setTraceEnabled(false);
+ return {isTraceEnabled()};
+ }
+
+ return d->m_aspectEngine->executeCommand(command);
+}
}
diff --git a/src/core/services/qsysteminformationservice_p.h b/src/core/services/qsysteminformationservice_p.h
index a8a83701b..64e6c779e 100644
--- a/src/core/services/qsysteminformationservice_p.h
+++ b/src/core/services/qsysteminformationservice_p.h
@@ -61,16 +61,34 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
class QSystemInformationServicePrivate;
+struct JobRunStats;
class Q_3DCORESHARED_EXPORT QSystemInformationService : public QAbstractServiceProvider
{
Q_OBJECT
+ Q_PROPERTY(bool traceEnabled READ isTraceEnabled WRITE setTraceEnabled NOTIFY traceEnabledChanged)
+ Q_PROPERTY(bool commandServerEnabled READ isCommandServerEnabled CONSTANT)
public:
- virtual QStringList aspectNames() const = 0;
- virtual int threadPoolThreadCount() const = 0;
+ QSystemInformationService(QAspectEngine *aspectEngine);
+
+ bool isTraceEnabled() const;
+ bool isCommandServerEnabled() const;
+
+ void setTraceEnabled(bool traceEnabled);
+
+ QStringList aspectNames() const;
+ int threadPoolThreadCount() const;
+
+ void writePreviousFrameTraces();
+
+ QVariant executeCommand(const QString &command);
+
+signals:
+ void traceEnabledChanged(bool traceEnabled);
protected:
- QSystemInformationService(const QString &description = QString());
+ Q_DECLARE_PRIVATE(QSystemInformationService)
+ QSystemInformationService(QAspectEngine *aspectEngine, const QString &description);
QSystemInformationService(QSystemInformationServicePrivate &dd);
};
diff --git a/src/core/services/qsysteminformationservice_p_p.h b/src/core/services/qsysteminformationservice_p_p.h
index e3ce9fe49..222f4e1af 100644
--- a/src/core/services/qsysteminformationservice_p_p.h
+++ b/src/core/services/qsysteminformationservice_p_p.h
@@ -51,21 +51,98 @@
// We mean it.
//
-#include <Qt3DCore/qt3dcore_global.h>
+#include <QtCore/QThreadStorage>
+#include <QtCore/QElapsedTimer>
+#include <QtCore/QFile>
+#include <QtCore/QMutex>
+#include <Qt3DCore/qt3dcore_global.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
#include <Qt3DCore/private/qabstractserviceprovider_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-class QSystemInformationServicePrivate : public QAbstractServiceProviderPrivate
+namespace Debug {
+class AspectCommandDebugger;
+} // Debug
+
+union Q_3DCORE_PRIVATE_EXPORT JobId
+{
+ JobId() : id(0L) { }
+ JobId(quint32 t, quint32 i) { typeAndInstance[0] = t; typeAndInstance[1] = i; }
+
+ quint32 typeAndInstance[2];
+ quint64 id;
+};
+
+class Q_3DCORE_PRIVATE_EXPORT QSystemInformationServicePrivate : public QAbstractServiceProviderPrivate
{
public:
- QSystemInformationServicePrivate(const QString &description)
- : QAbstractServiceProviderPrivate(QServiceLocator::SystemInformation, description)
- {}
+ struct JobRunStats
+ {
+ JobRunStats() { jobId.id = 0; startTime = 0L; endTime = 0L; }
+
+ qint64 startTime;
+ qint64 endTime;
+ JobId jobId; // QAspectJob subclasses should properly populate the jobId
+ quint64 threadId;
+ };
+
+ QSystemInformationServicePrivate(QAspectEngine *aspectEngine, const QString &description);
+ ~QSystemInformationServicePrivate();
+
+ static QSystemInformationServicePrivate *get(QSystemInformationService *q);
+
+ // Aspects + Job threads
+ void addJobLogStatsEntry(JobRunStats &stats);
+
+ // Submission thread
+ void addSubmissionLogStatsEntry(JobRunStats &stats);
+
+ void writeFrameJobLogStats();
+
+ QAspectEngine *m_aspectEngine;
+ bool m_traceEnabled;
+
+ QElapsedTimer m_jobsStatTimer;
+ QThreadStorage<QVector<JobRunStats> *> m_jobStatsCached;
+
+ QVector<QVector<JobRunStats> *> m_localStorages;
+ QVector<JobRunStats> *m_submissionStorage;
+
+ QMutex m_localStoragesMutex;
+
+ QScopedPointer<QFile> m_traceFile;
+ quint32 m_frameId;
+
+ Debug::AspectCommandDebugger *m_commandDebugger;
+
+ Q_DECLARE_PUBLIC(QSystemInformationService)
+};
+
+class Q_3DCORE_PRIVATE_EXPORT QTaskLogger {
+public:
+ enum Type {
+ AspectJob,
+ Submission
+ };
+
+ QTaskLogger(QSystemInformationService *service, const JobId &jobId, Type type);
+ QTaskLogger(QSystemInformationService *service, const quint32 jobType, const quint32 instance, Type type = Submission);
+
+ ~QTaskLogger();
+
+ void end(qint64 t = 0L);
+ qint64 restart();
+
+private:
+ QSystemInformationService *m_service;
+ QSystemInformationServicePrivate::JobRunStats m_stats;
+ Type m_type;
};
}
diff --git a/src/core/transforms/qabstractskeleton.cpp b/src/core/transforms/qabstractskeleton.cpp
index 5f3b05eb8..4a30d0710 100644
--- a/src/core/transforms/qabstractskeleton.cpp
+++ b/src/core/transforms/qabstractskeleton.cpp
@@ -39,7 +39,6 @@
#include "qabstractskeleton.h"
#include "qabstractskeleton_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -47,6 +46,7 @@ namespace Qt3DCore {
QAbstractSkeletonPrivate::QAbstractSkeletonPrivate()
: Qt3DCore::QNodePrivate()
+ , m_type(QSkeletonCreatedChangeBase::Skeleton)
, m_jointCount(0)
{
}
@@ -105,6 +105,13 @@ QAbstractSkeleton::~QAbstractSkeleton()
{
}
+/*! \internal */
+void QAbstractSkeleton::sceneChangeEvent(const QSceneChangePtr &change)
+{
+ // TODO Unused remove in Qt6
+ Q_UNUSED(change)
+}
+
/*!
\property Qt3DCore::QAbstractSkeleton::jointCount
@@ -127,16 +134,6 @@ void QAbstractSkeletonPrivate::setJointCount(int jointCount)
q->blockNotifications(block);
}
-void QAbstractSkeleton::sceneChangeEvent(const QSceneChangePtr &change)
-{
- Q_D(QAbstractSkeleton);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->propertyName() == QByteArrayLiteral("jointCount"))
- d->setJointCount(e->value().toInt());
- }
-}
-
} // namespace Qt3DCore
QT_END_NAMESPACE
diff --git a/src/core/transforms/qabstractskeleton.h b/src/core/transforms/qabstractskeleton.h
index 902def9f8..1c2eba08f 100644
--- a/src/core/transforms/qabstractskeleton.h
+++ b/src/core/transforms/qabstractskeleton.h
@@ -64,7 +64,8 @@ Q_SIGNALS:
protected:
QAbstractSkeleton(QAbstractSkeletonPrivate &dd, Qt3DCore::QNode *parent = nullptr);
- void sceneChangeEvent(const QSceneChangePtr &change) override;
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QAbstractSkeleton)
diff --git a/src/core/transforms/qskeletonloader.cpp b/src/core/transforms/qskeletonloader.cpp
index d5296ecc9..b1a311a0c 100644
--- a/src/core/transforms/qskeletonloader.cpp
+++ b/src/core/transforms/qskeletonloader.cpp
@@ -68,6 +68,27 @@ void QSkeletonLoaderPrivate::setStatus(QSkeletonLoader::Status status)
}
}
+void QSkeletonLoaderPrivate::setRootJoint(QJoint *rootJoint)
+{
+ Q_Q(QSkeletonLoader);
+ if (rootJoint == m_rootJoint)
+ return;
+
+ if (m_rootJoint)
+ unregisterDestructionHelper(m_rootJoint);
+
+ if (rootJoint && !rootJoint->parent())
+ rootJoint->setParent(q);
+
+ m_rootJoint = rootJoint;
+
+ // Ensures proper bookkeeping
+ if (m_rootJoint)
+ registerPrivateDestructionHelper(m_rootJoint, &QSkeletonLoaderPrivate::setRootJoint);
+
+ emit q->rootJointChanged(m_rootJoint);
+}
+
/*!
\qmltype SkeletonLoader
\inqmlmodule Qt3D.Core
@@ -217,39 +238,12 @@ void QSkeletonLoader::setCreateJointsEnabled(bool createJoints)
void QSkeletonLoader::setRootJoint(QJoint *rootJoint)
{
Q_D(QSkeletonLoader);
- if (rootJoint == d->m_rootJoint)
- return;
-
- if (d->m_rootJoint)
- d->unregisterDestructionHelper(d->m_rootJoint);
-
- if (rootJoint && !rootJoint->parent())
- rootJoint->setParent(this);
-
- d->m_rootJoint = rootJoint;
-
- // Ensures proper bookkeeping
- if (d->m_rootJoint)
- d->registerDestructionHelper(d->m_rootJoint, &QSkeletonLoader::setRootJoint, d->m_rootJoint);
-
- emit rootJointChanged(d->m_rootJoint);
+ d->setRootJoint(rootJoint);
}
/*! \internal */
void QSkeletonLoader::sceneChangeEvent(const QSceneChangePtr &change)
{
- Q_D(QSkeletonLoader);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- auto propertyChange = qSharedPointerCast<QStaticPropertyUpdatedChangeBase>(change);
- if (propertyChange->propertyName() == QByteArrayLiteral("status")) {
- const auto e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- d->setStatus(static_cast<QSkeletonLoader::Status>(e->value().toInt()));
- } else if (propertyChange->propertyName() == QByteArrayLiteral("rootJoint")) {
- auto typedChange = qSharedPointerCast<QJointChange>(propertyChange);
- auto rootJoint = std::move(typedChange->data);
- setRootJoint(rootJoint.release());
- }
- }
QAbstractSkeleton::sceneChangeEvent(change);
}
diff --git a/src/core/transforms/qskeletonloader_p.h b/src/core/transforms/qskeletonloader_p.h
index 5c415745b..6bd4e1eef 100644
--- a/src/core/transforms/qskeletonloader_p.h
+++ b/src/core/transforms/qskeletonloader_p.h
@@ -70,6 +70,7 @@ public:
QSkeletonLoaderPrivate();
void setStatus(QSkeletonLoader::Status status);
+ void setRootJoint(QJoint *rootJoint);
Q_DECLARE_PUBLIC(QSkeletonLoader)
diff --git a/src/core/transforms/qtransform.cpp b/src/core/transforms/qtransform.cpp
index e5902f11f..d41b87f79 100644
--- a/src/core/transforms/qtransform.cpp
+++ b/src/core/transforms/qtransform.cpp
@@ -237,6 +237,7 @@ QTransform::QTransform(QTransformPrivate &dd, QNode *parent)
/*!
\internal
*/
+// TODO Unused remove in Qt6
void QTransform::sceneChangeEvent(const QSceneChangePtr &change)
{
Q_D(QTransform);
diff --git a/src/core/transforms/qtransform.h b/src/core/transforms/qtransform.h
index 503ea4d4a..ce6bf42fa 100644
--- a/src/core/transforms/qtransform.h
+++ b/src/core/transforms/qtransform.h
@@ -119,6 +119,7 @@ Q_SIGNALS:
protected:
explicit QTransform(QTransformPrivate &dd, QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
diff --git a/src/core/transforms/sqt_p.h b/src/core/transforms/sqt_p.h
index 5fdefccc8..e602cc71e 100644
--- a/src/core/transforms/sqt_p.h
+++ b/src/core/transforms/sqt_p.h
@@ -71,7 +71,9 @@ struct Sqt
Sqt()
: rotation()
, scale(1.0f, 1.0f, 1.0f)
+ , pad1(0.f)
, translation()
+ , pad2(0.f)
{}
inline QMatrix4x4 toMatrix() const
diff --git a/src/doc/src/qmlextramaterials.qdoc b/src/doc/src/qmlextramaterials.qdoc
index e0a2e9edf..338bada09 100644
--- a/src/doc/src/qmlextramaterials.qdoc
+++ b/src/doc/src/qmlextramaterials.qdoc
@@ -544,6 +544,41 @@
The default value is 0.5.
*/
+/*!
+ \qmlproperty BlendEquationArguments::Blending PhongAlphaMaterial::sourceRgbArg
+
+ Holds the blend equation source RGB blending argument.
+
+ \sa Qt3DRender::QBlendEquationArguments::Blending
+*/
+/*!
+ \qmlproperty BlendEquationArguments::Blending PhongAlphaMaterial::destinationRgbArg
+
+ Holds the blend equation destination RGB blending argument.
+
+ \sa Qt3DRender::QBlendEquationArguments::Blending
+*/
+/*!
+ \qmlproperty BlendEquationArguments::Blending PhongAlphaMaterial::sourceAlphaArg
+
+ Holds the blend equation source alpha blending argument.
+
+ \sa Qt3DRender::QBlendEquationArguments::Blending
+*/
+/*!
+ \qmlproperty BlendEquationArguments::Blending PhongAlphaMaterial::destinationAlphaArg
+
+ Holds the blend equation destination alpha blending argument.
+
+ \sa Qt3DRender::QBlendEquationArguments::Blending
+*/
+/*!
+ \qmlproperty BlendEquation::BlendFunction PhongAlphaMaterial::blendFunctionArg
+
+ Holds the blend equation function argument.
+
+ \sa Qt3DRender::QBlendEquation::BlendFunction
+*/
/*!
\qmltype PhongMaterial
diff --git a/src/extras/defaults/qabstractspritesheet.cpp b/src/extras/defaults/qabstractspritesheet.cpp
index 640e600c7..2cf134f7c 100644
--- a/src/extras/defaults/qabstractspritesheet.cpp
+++ b/src/extras/defaults/qabstractspritesheet.cpp
@@ -100,7 +100,7 @@ QAbstractSpriteSheet::~QAbstractSpriteSheet()
}
/*!
- \property QAbstractSpriteSheet::texture
+ \property Qt3DExtras::QAbstractSpriteSheet::texture
Holds the current texture used by the material.
*/
diff --git a/src/extras/defaults/qt3dwindow.cpp b/src/extras/defaults/qt3dwindow.cpp
index ace40c3c1..04b8554f1 100644
--- a/src/extras/defaults/qt3dwindow.cpp
+++ b/src/extras/defaults/qt3dwindow.cpp
@@ -237,7 +237,7 @@ void Qt3DWindow::showEvent(QShowEvent *e)
void Qt3DWindow::resizeEvent(QResizeEvent *)
{
Q_D(Qt3DWindow);
- d->m_defaultCamera->setAspectRatio(float(width()) / float(height()));
+ d->m_defaultCamera->setAspectRatio(float(width()) / std::max(1.f, static_cast<float>(height())));
}
/*!
diff --git a/src/extras/shaders/es2/distancefieldtext.frag b/src/extras/shaders/es2/distancefieldtext.frag
index d2db2e306..b7563e397 100644
--- a/src/extras/shaders/es2/distancefieldtext.frag
+++ b/src/extras/shaders/es2/distancefieldtext.frag
@@ -33,5 +33,5 @@ void main()
FP float maxAlpha = threshold + range;
FP float distVal = texture2D(distanceFieldTexture, texCoord).r;
- gl_FragColor = color * smoothstep(minAlpha, maxAlpha, distVal);
+ gl_FragColor = vec4(color.rgb, color.a * smoothstep(minAlpha, maxAlpha, distVal));
}
diff --git a/src/extras/shaders/gl3/distancefieldtext.frag b/src/extras/shaders/gl3/distancefieldtext.frag
index 23dff8e0f..8e0684adc 100644
--- a/src/extras/shaders/gl3/distancefieldtext.frag
+++ b/src/extras/shaders/gl3/distancefieldtext.frag
@@ -34,6 +34,6 @@ void main()
float maxAlpha = threshold + range;
float distVal = texture(distanceFieldTexture, texCoord).r;
- fragColor = color * smoothstep(minAlpha, maxAlpha, distVal);
+ fragColor = vec4(color.rgb, color.a * smoothstep(minAlpha, maxAlpha, distVal));
gl_FragDepth = gl_FragCoord.z - zValue * 0.00001;
}
diff --git a/src/extras/text/qtext2dentity.cpp b/src/extras/text/qtext2dentity.cpp
index aa4785fe7..897672782 100644
--- a/src/extras/text/qtext2dentity.cpp
+++ b/src/extras/text/qtext2dentity.cpp
@@ -217,9 +217,6 @@ struct RenderData {
void QText2DEntityPrivate::setCurrentGlyphRuns(const QVector<QGlyphRun> &runs)
{
- if (runs.isEmpty())
- return;
-
// For each distinct texture, we need a separate DistanceFieldTextRenderer,
// for which we need vertex and index data
QHash<Qt3DRender::QAbstractTexture*, RenderData> renderData;
@@ -294,6 +291,11 @@ void QText2DEntityPrivate::setCurrentGlyphRuns(const QVector<QGlyphRun> &runs)
}
}
+ // de-ref all glyphs for previous QGlyphRuns
+ for (int i = 0; i < m_currentGlyphRuns.size(); i++)
+ m_glyphCache->derefGlyphs(m_currentGlyphRuns[i]);
+ m_currentGlyphRuns = runs;
+
// make sure we have the correct number of DistanceFieldTextRenderers
// TODO: we might keep one renderer at all times, so we won't delete and
// re-allocate one every time the text changes from an empty to a non-empty string
@@ -314,11 +316,6 @@ void QText2DEntityPrivate::setCurrentGlyphRuns(const QVector<QGlyphRun> &runs)
for (auto it = renderData.begin(); it != renderData.end(); ++it) {
m_renderers[rendererIdx++]->setGlyphData(it.key(), it.value().vertex, it.value().index);
}
-
- // de-ref all glyphs for previous QGlyphRuns
- for (int i = 0; i < m_currentGlyphRuns.size(); i++)
- m_glyphCache->derefGlyphs(m_currentGlyphRuns[i]);
- m_currentGlyphRuns = runs;
}
void QText2DEntityPrivate::clearCurrentGlyphRuns()
diff --git a/src/input/backend/keyboardeventfilter.cpp b/src/input/backend/keyboardeventfilter.cpp
index bd3bac5a7..e4f47f08e 100644
--- a/src/input/backend/keyboardeventfilter.cpp
+++ b/src/input/backend/keyboardeventfilter.cpp
@@ -53,6 +53,7 @@ namespace Input {
KeyboardEventFilter::KeyboardEventFilter(QObject *parent)
: QObject(parent)
+ , m_inputHandler(nullptr)
{
}
diff --git a/src/input/backend/keyboardhandler.cpp b/src/input/backend/keyboardhandler.cpp
index 66af527c9..026012e52 100644
--- a/src/input/backend/keyboardhandler.cpp
+++ b/src/input/backend/keyboardhandler.cpp
@@ -41,7 +41,6 @@
#include <Qt3DInput/qkeyboarddevice.h>
#include <Qt3DInput/qkeyboardhandler.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QtCore/QVariant>
#include <Qt3DInput/private/inputhandler_p.h>
diff --git a/src/input/backend/mouseeventfilter.cpp b/src/input/backend/mouseeventfilter.cpp
index 618a64b15..48b30725a 100644
--- a/src/input/backend/mouseeventfilter.cpp
+++ b/src/input/backend/mouseeventfilter.cpp
@@ -53,6 +53,7 @@ namespace Input {
MouseEventFilter::MouseEventFilter(QObject *parent)
: QObject(parent)
+ , m_inputHandler(nullptr)
{
}
diff --git a/src/input/backend/mousehandler.cpp b/src/input/backend/mousehandler.cpp
index 46bd273d6..9c7ff9817 100644
--- a/src/input/backend/mousehandler.cpp
+++ b/src/input/backend/mousehandler.cpp
@@ -41,7 +41,6 @@
#include <Qt3DInput/qmousehandler.h>
#include <Qt3DInput/qmousedevice.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
diff --git a/src/input/frontend/qabstractphysicaldeviceproxy.cpp b/src/input/frontend/qabstractphysicaldeviceproxy.cpp
index a7930ed76..4ed116440 100644
--- a/src/input/frontend/qabstractphysicaldeviceproxy.cpp
+++ b/src/input/frontend/qabstractphysicaldeviceproxy.cpp
@@ -41,7 +41,6 @@
#include "qabstractphysicaldeviceproxy_p_p.h"
#include <Qt3DInput/qphysicaldevicecreatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qaction.cpp b/src/input/frontend/qaction.cpp
index c835062a2..8cceaab51 100644
--- a/src/input/frontend/qaction.cpp
+++ b/src/input/frontend/qaction.cpp
@@ -41,7 +41,6 @@
#include "qaction_p.h"
#include <Qt3DInput/qabstractactioninput.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
@@ -149,6 +148,11 @@ QVector<QAbstractActionInput *> QAction::inputs() const
return d->m_inputs;
}
+// TODO Unused remove in Qt6
+void QAction::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
Qt3DCore::QNodeCreatedChangeBasePtr QAction::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QActionData>::create(this);
diff --git a/src/input/frontend/qaction.h b/src/input/frontend/qaction.h
index 8175bab8e..ef74debe5 100644
--- a/src/input/frontend/qaction.h
+++ b/src/input/frontend/qaction.h
@@ -67,6 +67,10 @@ public:
Q_SIGNALS:
void activeChanged(bool isActive);
+protected:
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
+
private:
Q_DECLARE_PRIVATE(QAction)
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
diff --git a/src/input/frontend/qactioninput.cpp b/src/input/frontend/qactioninput.cpp
index 9f32f57cc..f013147f2 100644
--- a/src/input/frontend/qactioninput.cpp
+++ b/src/input/frontend/qactioninput.cpp
@@ -181,7 +181,7 @@ QAbstractPhysicalDevice *QActionInput::sourceDevice() const
/*!
\qmlsignal Qt3D.Input::ActionInput::buttonsChanged(const QVector<int> &buttons)
- This signal is emitted when the buttons associated with the action input is changed.
+ This signal is emitted when the \a buttons associated with the action input is changed.
The corresponding handler is \c onbuttonsChanged
*/
diff --git a/src/input/frontend/qaxis.cpp b/src/input/frontend/qaxis.cpp
index b6018c887..d76135fd7 100644
--- a/src/input/frontend/qaxis.cpp
+++ b/src/input/frontend/qaxis.cpp
@@ -40,7 +40,6 @@
#include "qaxis_p.h"
#include <Qt3DInput/qabstractaxisinput.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
QT_BEGIN_NAMESPACE
@@ -168,6 +167,11 @@ float QAxis::value() const
return d->m_value;
}
+// TODO Unused remove in Qt6
+void QAxis::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
Qt3DCore::QNodeCreatedChangeBasePtr QAxis::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAxisData>::create(this);
diff --git a/src/input/frontend/qaxis.h b/src/input/frontend/qaxis.h
index 1a542cf22..3dbe54a4f 100644
--- a/src/input/frontend/qaxis.h
+++ b/src/input/frontend/qaxis.h
@@ -66,6 +66,10 @@ public:
Q_SIGNALS:
void valueChanged(float value);
+protected:
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
+
private:
Q_DECLARE_PRIVATE(QAxis)
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
diff --git a/src/input/frontend/qaxisaccumulator.cpp b/src/input/frontend/qaxisaccumulator.cpp
index 7e9930f66..a7bb14441 100644
--- a/src/input/frontend/qaxisaccumulator.cpp
+++ b/src/input/frontend/qaxisaccumulator.cpp
@@ -42,7 +42,6 @@
#include <Qt3DInput/qaxis.h>
#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -290,6 +289,11 @@ void QAxisAccumulator::setScale(float scale)
emit scaleChanged(scale);
}
+// TODO Unused remove in Qt6
+void QAxisAccumulator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
/*! \internal */
Qt3DCore::QNodeCreatedChangeBasePtr QAxisAccumulator::createNodeCreationChange() const
{
diff --git a/src/input/frontend/qaxisaccumulator.h b/src/input/frontend/qaxisaccumulator.h
index bb2e2696b..e711b0691 100644
--- a/src/input/frontend/qaxisaccumulator.h
+++ b/src/input/frontend/qaxisaccumulator.h
@@ -87,6 +87,10 @@ Q_SIGNALS:
void velocityChanged(float value);
void scaleChanged(float scale);
+protected:
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
+
private:
Q_DECLARE_PRIVATE(QAxisAccumulator)
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
diff --git a/src/input/frontend/qkeyboarddevice.cpp b/src/input/frontend/qkeyboarddevice.cpp
index 257a5be8c..1ec1f8ead 100644
--- a/src/input/frontend/qkeyboarddevice.cpp
+++ b/src/input/frontend/qkeyboarddevice.cpp
@@ -41,7 +41,6 @@
#include "qkeyboarddevice_p.h"
#include <Qt3DInput/qkeyboardhandler.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qscene_p.h>
@@ -310,16 +309,11 @@ QKeyboardDevice::QKeyboardDevice(QKeyboardDevicePrivate &dd, QNode *parent)
{
}
-/*! \internal */
-void QKeyboardDevice::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+// TODO Unused remove in Qt6
+void QKeyboardDevice::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
{
- Q_D(QKeyboardDevice);
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->type() == Qt3DCore::PropertyUpdated && e->propertyName() == QByteArrayLiteral("activeInput")) {
- Qt3DCore::QNodeId activeInputId = e->value().value<Qt3DCore::QNodeId>();
- setActiveInput(qobject_cast<QKeyboardHandler *>(d->scene()->lookupNode(activeInputId)));
- }
}
+
/*!
* Set the active input to \a activeInput
*/
diff --git a/src/input/frontend/qkeyboarddevice.h b/src/input/frontend/qkeyboarddevice.h
index c3478ec27..df2f47020 100644
--- a/src/input/frontend/qkeyboarddevice.h
+++ b/src/input/frontend/qkeyboarddevice.h
@@ -71,6 +71,7 @@ public:
protected:
explicit QKeyboardDevice(QKeyboardDevicePrivate &dd, QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
Q_SIGNALS:
diff --git a/src/input/frontend/qkeyboardhandler.cpp b/src/input/frontend/qkeyboardhandler.cpp
index aff136a04..92ce39c31 100644
--- a/src/input/frontend/qkeyboardhandler.cpp
+++ b/src/input/frontend/qkeyboardhandler.cpp
@@ -41,7 +41,6 @@
#include "qkeyboardhandler_p.h"
#include <Qt3DInput/qkeyboarddevice.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -238,6 +237,11 @@ void QKeyboardHandler::setFocus(bool focus)
}
}
+// TODO Unused remove in Qt6
+void QKeyboardHandler::sceneChangeEvent(const QSceneChangePtr &)
+{
+}
+
Qt3DCore::QNodeCreatedChangeBasePtr QKeyboardHandler::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QKeyboardHandlerData>::create(this);
diff --git a/src/input/frontend/qkeyboardhandler.h b/src/input/frontend/qkeyboardhandler.h
index d69476286..b4425de72 100644
--- a/src/input/frontend/qkeyboardhandler.h
+++ b/src/input/frontend/qkeyboardhandler.h
@@ -115,6 +115,10 @@ Q_SIGNALS:
void pressed(Qt3DInput::QKeyEvent *event);
void released(Qt3DInput::QKeyEvent *event);
+protected:
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
+
private:
Q_DECLARE_PRIVATE(QKeyboardHandler)
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
diff --git a/src/input/frontend/qkeyevent.cpp b/src/input/frontend/qkeyevent.cpp
index a70a2970b..efbddc771 100644
--- a/src/input/frontend/qkeyevent.cpp
+++ b/src/input/frontend/qkeyevent.cpp
@@ -160,7 +160,7 @@ QKeyEvent::~QKeyEvent()
/*!
\qmlmethod bool Qt3D.Input::KeyEvent::matches(StandardKey key)
- Returns \c true if the key event matches the given standard key; otherwise
+ Returns \c true if the key event matches the given standard \a key; otherwise
returns \c false.
\sa QKeySequence::StandardKey
@@ -174,7 +174,7 @@ QKeyEvent::~QKeyEvent()
See \l [CPP] {Qt::Key}{Qt.Key} for the list of keyboard codes.
- \sa {QKeyEvent::key}
+ \b {See also} \l [QtGui] {QKeyEvent::key()}.
*/
/*!
@@ -194,7 +194,7 @@ QKeyEvent::~QKeyEvent()
This property holds the keyboard modifier flags that existed immediately
before the event occurred.
- \sa {QKeyEvent::modifiers}
+ \b {See also} \l [QtGui] {QKeyEvent::modifiers()}.
*/
/*!
diff --git a/src/input/frontend/qmouseevent.cpp b/src/input/frontend/qmouseevent.cpp
index 2033eed36..2b06c824d 100644
--- a/src/input/frontend/qmouseevent.cpp
+++ b/src/input/frontend/qmouseevent.cpp
@@ -49,7 +49,7 @@ template<typename EventClass, typename QtEventClass>
typename EventClass::Modifiers modifiersForEvent(const QtEventClass &event)
{
const Qt::KeyboardModifiers eventModifiers = event.modifiers();
- typename EventClass::Modifiers modifiers = EventClass::NoModifier;
+ int modifiers = EventClass::NoModifier;
if (eventModifiers & Qt::ShiftModifier)
modifiers |= EventClass::ShiftModifier;
@@ -66,7 +66,9 @@ typename EventClass::Modifiers modifiersForEvent(const QtEventClass &event)
if (eventModifiers & Qt::KeypadModifier)
modifiers |= EventClass::KeypadModifier;
- return modifiers;
+ // Abuse the int used to store an enum to store multiple
+ // modifiers into one
+ return static_cast<typename EventClass::Modifiers>(modifiers);
}
} // anonymous
diff --git a/src/input/frontend/qmouseevent.h b/src/input/frontend/qmouseevent.h
index 1402d8210..ae44d9365 100644
--- a/src/input/frontend/qmouseevent.h
+++ b/src/input/frontend/qmouseevent.h
@@ -70,7 +70,7 @@ public:
};
Q_ENUM(Buttons) // LCOV_EXCL_LINE
- enum Modifier {
+ enum Modifiers {
NoModifier = Qt::NoModifier,
ShiftModifier = Qt::ShiftModifier,
ControlModifier = Qt::ControlModifier,
@@ -78,8 +78,8 @@ public:
MetaModifier = Qt::MetaModifier,
KeypadModifier = Qt::KeypadModifier
};
- Q_DECLARE_FLAGS(Modifiers, Modifier)
- Q_FLAG(Modifiers)
+ Q_ENUM(Modifiers) // LCOV_EXCL_LINE
+ // TO DO Qt6 Modifiers -> Modifier and add Q_FLAG(Modifiers)
explicit QMouseEvent(const QT_PREPEND_NAMESPACE(QMouseEvent) &e);
~QMouseEvent();
@@ -128,7 +128,7 @@ public:
};
Q_ENUM(Buttons) // LCOV_EXCL_LINE
- enum Modifier {
+ enum Modifiers {
NoModifier = Qt::NoModifier,
ShiftModifier = Qt::ShiftModifier,
ControlModifier = Qt::ControlModifier,
@@ -136,8 +136,8 @@ public:
MetaModifier = Qt::MetaModifier,
KeypadModifier = Qt::KeypadModifier
};
- Q_DECLARE_FLAGS(Modifiers, Modifier)
- Q_FLAG(Modifiers)
+ Q_ENUM(Modifiers) // LCOV_EXCL_LINE
+ // TO DO Qt6 Modifiers -> Modifier and add Q_FLAG(Modifiers)
explicit QWheelEvent(const QT_PREPEND_NAMESPACE(QWheelEvent) &e);
~QWheelEvent();
@@ -161,9 +161,6 @@ typedef QSharedPointer<QWheelEvent> QWheelEventPtr;
} // namespace Qt3DInput
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt3DInput::QMouseEvent::Modifiers)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt3DInput::QWheelEvent::Modifiers)
-
QT_END_NAMESPACE
Q_DECLARE_METATYPE(Qt3DInput::QMouseEvent*) // LCOV_EXCL_LINE
diff --git a/src/input/frontend/qmousehandler.cpp b/src/input/frontend/qmousehandler.cpp
index 944ca391a..89d76a057 100644
--- a/src/input/frontend/qmousehandler.cpp
+++ b/src/input/frontend/qmousehandler.cpp
@@ -42,7 +42,6 @@
#include <Qt3DInput/qmousedevice.h>
#include <Qt3DInput/qmouseevent.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QtCore/QTimer>
QT_BEGIN_NAMESPACE
@@ -198,21 +197,21 @@ void QMouseHandlerPrivate::mouseEvent(const QMouseEventPtr &event)
\qmlsignal Qt3D.Input::MouseHandler::wheel(MouseEvent mouse)
This signal is emitted when the mouse wheel is used with the event details
- being contained within \a wheel
+ being contained within \a mouse.
*/
/*!
\fn Qt3DInput::QMouseHandler::clicked(Qt3DInput::QMouseEvent *mouse)
This signal is emitted when a mouse button is clicked with the event details
- being contained within \a mouse
+ being contained within \a mouse.
*/
/*!
\fn Qt3DInput::QMouseHandler::doubleClicked(Qt3DInput::QMouseEvent *mouse)
This signal is emitted when a mouse button is double clicked with the event
- details being contained within \a mouse
+ details being contained within \a mouse.
*/
/*!
@@ -299,6 +298,11 @@ void QMouseHandler::setSourceDevice(QMouseDevice *mouseDevice)
}
}
+// TODO Unused remove in Qt6
+void QMouseHandler::sceneChangeEvent(const QSceneChangePtr &)
+{
+}
+
/*!
* \property Qt3DInput::QMouseHandler::sourceDevice
*
diff --git a/src/input/frontend/qmousehandler.h b/src/input/frontend/qmousehandler.h
index 5331893b2..d95dbf4c3 100644
--- a/src/input/frontend/qmousehandler.h
+++ b/src/input/frontend/qmousehandler.h
@@ -87,6 +87,8 @@ Q_SIGNALS:
#endif
protected:
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
void setContainsMouse(bool contains);
private:
diff --git a/src/input/frontend/qphysicaldevicecreatedchange.cpp b/src/input/frontend/qphysicaldevicecreatedchange.cpp
index c14770d80..905633b7f 100644
--- a/src/input/frontend/qphysicaldevicecreatedchange.cpp
+++ b/src/input/frontend/qphysicaldevicecreatedchange.cpp
@@ -54,7 +54,7 @@ QPhysicalDeviceCreatedChangeBasePrivate::QPhysicalDeviceCreatedChangeBasePrivate
}
/*!
- \class QPhysicalDeviceCreatedChangeBase
+ \class Qt3DInput::QPhysicalDeviceCreatedChangeBase
\inmodule Qt3DInput
\brief Base class for handling changes in physical devices.
*/
diff --git a/src/logic/callbackjob.cpp b/src/logic/callbackjob.cpp
index 5c04d8838..5dfc74f02 100644
--- a/src/logic/callbackjob.cpp
+++ b/src/logic/callbackjob.cpp
@@ -51,7 +51,7 @@ CallbackJob::CallbackJob()
: QAspectJob()
, m_logicManager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::Callback, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::Callback, 0)
}
void CallbackJob::setManager(Manager *manager)
diff --git a/src/logic/manager.cpp b/src/logic/manager.cpp
index 3d096a342..db90e6ad9 100644
--- a/src/logic/manager.cpp
+++ b/src/logic/manager.cpp
@@ -56,6 +56,8 @@ namespace Logic {
Manager::Manager()
: m_logicHandlerManager(new HandlerManager)
+ , m_logicAspect(nullptr)
+ , m_executor(nullptr)
, m_dt(0.0f)
{
}
diff --git a/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp b/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp
index ddb950f86..8adb70f96 100644
--- a/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp
+++ b/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp
@@ -48,6 +48,7 @@
#include <Qt3DRender/QGeometry>
#include <Qt3DRender/private/renderlogging_p.h>
+#include <Qt3DCore/private/qloadgltf_p.h>
QT_BEGIN_NAMESPACE
@@ -102,12 +103,7 @@ bool GLTFGeometryLoader::load(QIODevice *ioDev, const QString &subMesh)
{
Q_UNUSED(subMesh);
- QByteArray jsonData = ioDev->readAll();
- QJsonDocument sceneDocument = QJsonDocument::fromBinaryData(jsonData);
- if (sceneDocument.isNull())
- sceneDocument = QJsonDocument::fromJson(jsonData);
-
- if (Q_UNLIKELY(!setJSON(sceneDocument))) {
+ if (Q_UNLIKELY(!setJSON(qLoadGLTF(ioDev->readAll())))) {
qCWarning(GLTFGeometryLoaderLog, "not a JSON document");
return false;
}
@@ -139,7 +135,8 @@ GLTFGeometryLoader::BufferData::BufferData(const QJsonObject &json)
}
GLTFGeometryLoader::AccessorData::AccessorData()
- : type(QAttribute::Float)
+ : bufferViewIndex(0)
+ , type(QAttribute::Float)
, dataSize(0)
, count(0)
, offset(0)
diff --git a/src/plugins/sceneparsers/gltf/gltfimporter.cpp b/src/plugins/sceneparsers/gltf/gltfimporter.cpp
index a10a83cca..860dec3e7 100644
--- a/src/plugins/sceneparsers/gltf/gltfimporter.cpp
+++ b/src/plugins/sceneparsers/gltf/gltfimporter.cpp
@@ -108,6 +108,7 @@
#include <Qt3DExtras/qtorusmesh.h>
#include <private/qurlhelper_p.h>
+#include <private/qloadgltf_p.h>
/**
* glTF 2.0 conformance report
@@ -410,12 +411,7 @@ void GLTFImporter::setSource(const QUrl &source)
QFile f(path);
f.open(QIODevice::ReadOnly);
- QByteArray jsonData = f.readAll();
- QJsonDocument sceneDocument = QJsonDocument::fromBinaryData(jsonData);
- if (sceneDocument.isNull())
- sceneDocument = QJsonDocument::fromJson(jsonData);
-
- if (Q_UNLIKELY(!setJSON(sceneDocument))) {
+ if (Q_UNLIKELY(!setJSON(qLoadGLTF(f.readAll())))) {
qCWarning(GLTFImporterLog, "not a JSON document");
return;
}
@@ -430,11 +426,7 @@ void GLTFImporter::setSource(const QUrl &source)
*/
void GLTFImporter::setData(const QByteArray& data, const QString &basePath)
{
- QJsonDocument sceneDocument = QJsonDocument::fromBinaryData(data);
- if (sceneDocument.isNull())
- sceneDocument = QJsonDocument::fromJson(data);
-
- if (Q_UNLIKELY(!setJSON(sceneDocument))) {
+ if (Q_UNLIKELY(!setJSON(qLoadGLTF(data)))) {
qCWarning(GLTFImporterLog, "not a JSON document");
return;
}
diff --git a/src/quick3d/imports/animation/plugins.qmltypes b/src/quick3d/imports/animation/plugins.qmltypes
index a8f207245..aff5ccb9c 100644
--- a/src/quick3d/imports/animation/plugins.qmltypes
+++ b/src/quick3d/imports/animation/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Animation 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Animation 2.14'
Module {
dependencies: ["Qt3D.Core 2.0"]
@@ -699,4 +699,57 @@ Module {
isReadonly: true
}
}
+ Component {
+ name: "Qt3DCore::QNode"
+ defaultProperty: "data"
+ prototype: "QObject"
+ exports: ["Qt3D.Animation/Node 2.9"]
+ isCreatable: false
+ exportMetaObjectRevisions: [209]
+ Enum {
+ name: "PropertyTrackingMode"
+ values: {
+ "TrackFinalValues": 0,
+ "DontTrackValues": 1,
+ "TrackAllValues": 2
+ }
+ }
+ Property { name: "parent"; type: "Qt3DCore::QNode"; isPointer: true }
+ Property { name: "enabled"; type: "bool" }
+ Property { name: "defaultPropertyTrackingMode"; revision: 9; type: "PropertyTrackingMode" }
+ Signal {
+ name: "parentChanged"
+ Parameter { name: "parent"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "enabledChanged"
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ Signal {
+ name: "defaultPropertyTrackingModeChanged"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ Signal { name: "nodeDestroyed" }
+ Method {
+ name: "setParent"
+ Parameter { name: "parent"; type: "QNode"; isPointer: true }
+ }
+ Method {
+ name: "setEnabled"
+ Parameter { name: "isEnabled"; type: "bool" }
+ }
+ Method {
+ name: "setDefaultPropertyTrackingMode"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ Property { name: "propertyTrackingOverrides"; revision: 209; type: "QJSValue" }
+ Property { name: "data"; revision: 209; type: "QObject"; isList: true; isReadonly: true }
+ Property {
+ name: "childNodes"
+ revision: 209
+ type: "Qt3DCore::QNode"
+ isList: true
+ isReadonly: true
+ }
+ }
}
diff --git a/src/quick3d/imports/core/plugins.qmltypes b/src/quick3d/imports/core/plugins.qmltypes
index 390fd78fb..476bb99a7 100644
--- a/src/quick3d/imports/core/plugins.qmltypes
+++ b/src/quick3d/imports/core/plugins.qmltypes
@@ -4,11 +4,73 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable Qt3D.Core 2.13'
+// 'qmlplugindump -nonrelocatable Qt3D.Core 2.14'
Module {
dependencies: ["QtQuick 2.0"]
Component {
+ name: "QQmlEasingValueType"
+ exports: ["Qt3D.Core/Easing 2.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Type"
+ values: {
+ "Linear": 0,
+ "InQuad": 1,
+ "OutQuad": 2,
+ "InOutQuad": 3,
+ "OutInQuad": 4,
+ "InCubic": 5,
+ "OutCubic": 6,
+ "InOutCubic": 7,
+ "OutInCubic": 8,
+ "InQuart": 9,
+ "OutQuart": 10,
+ "InOutQuart": 11,
+ "OutInQuart": 12,
+ "InQuint": 13,
+ "OutQuint": 14,
+ "InOutQuint": 15,
+ "OutInQuint": 16,
+ "InSine": 17,
+ "OutSine": 18,
+ "InOutSine": 19,
+ "OutInSine": 20,
+ "InExpo": 21,
+ "OutExpo": 22,
+ "InOutExpo": 23,
+ "OutInExpo": 24,
+ "InCirc": 25,
+ "OutCirc": 26,
+ "InOutCirc": 27,
+ "OutInCirc": 28,
+ "InElastic": 29,
+ "OutElastic": 30,
+ "InOutElastic": 31,
+ "OutInElastic": 32,
+ "InBack": 33,
+ "OutBack": 34,
+ "InOutBack": 35,
+ "OutInBack": 36,
+ "InBounce": 37,
+ "OutBounce": 38,
+ "InOutBounce": 39,
+ "OutInBounce": 40,
+ "InCurve": 41,
+ "OutCurve": 42,
+ "SineCurve": 43,
+ "CosineCurve": 44,
+ "Bezier": 45
+ }
+ }
+ Property { name: "type"; type: "Type" }
+ Property { name: "amplitude"; type: "double" }
+ Property { name: "overshoot"; type: "double" }
+ Property { name: "period"; type: "double" }
+ Property { name: "bezierCurve"; type: "QVariantList" }
+ }
+ Component {
name: "Qt3DCore::QAbstractSkeleton"
prototype: "Qt3DCore::QNode"
exports: ["Qt3D.Core/AbstractSkeleton 2.10"]
@@ -266,8 +328,8 @@ Module {
Component {
name: "Qt3DCore::QTransform"
prototype: "Qt3DCore::QComponent"
- exports: ["Qt3D.Core/Transform 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["Qt3D.Core/Transform 2.0", "Qt3D.Core/Transform 2.14"]
+ exportMetaObjectRevisions: [0, 14]
Property { name: "matrix"; type: "QMatrix4x4" }
Property { name: "scale"; type: "float" }
Property { name: "scale3D"; type: "QVector3D" }
@@ -276,6 +338,7 @@ Module {
Property { name: "rotationX"; type: "float" }
Property { name: "rotationY"; type: "float" }
Property { name: "rotationZ"; type: "float" }
+ Property { name: "worldMatrix"; revision: 14; type: "QMatrix4x4"; isReadonly: true }
Signal {
name: "scaleChanged"
Parameter { name: "scale"; type: "float" }
@@ -304,6 +367,10 @@ Module {
name: "rotationZChanged"
Parameter { name: "rotationZ"; type: "float" }
}
+ Signal {
+ name: "worldMatrixChanged"
+ Parameter { name: "worldMatrix"; type: "QMatrix4x4" }
+ }
Method {
name: "setScale"
Parameter { name: "scale"; type: "float" }
diff --git a/src/quick3d/imports/extras/plugins.qmltypes b/src/quick3d/imports/extras/plugins.qmltypes
index 72857d402..fcc15e022 100644
--- a/src/quick3d/imports/extras/plugins.qmltypes
+++ b/src/quick3d/imports/extras/plugins.qmltypes
@@ -4,10 +4,51 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Extras 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Extras 2.14'
Module {
dependencies: ["Qt3D.Logic 2.0", "Qt3D.Render 2.0"]
+ Component { name: "Qt3DCore::QEntity"; prototype: "Qt3DCore::QNode" }
+ Component {
+ name: "Qt3DCore::QNode"
+ prototype: "QObject"
+ Enum {
+ name: "PropertyTrackingMode"
+ values: {
+ "TrackFinalValues": 0,
+ "DontTrackValues": 1,
+ "TrackAllValues": 2
+ }
+ }
+ Property { name: "parent"; type: "Qt3DCore::QNode"; isPointer: true }
+ Property { name: "enabled"; type: "bool" }
+ Property { name: "defaultPropertyTrackingMode"; revision: 9; type: "PropertyTrackingMode" }
+ Signal {
+ name: "parentChanged"
+ Parameter { name: "parent"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "enabledChanged"
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ Signal {
+ name: "defaultPropertyTrackingModeChanged"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ Signal { name: "nodeDestroyed" }
+ Method {
+ name: "setParent"
+ Parameter { name: "parent"; type: "QNode"; isPointer: true }
+ }
+ Method {
+ name: "setEnabled"
+ Parameter { name: "isEnabled"; type: "bool" }
+ }
+ Method {
+ name: "setDefaultPropertyTrackingMode"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ }
Component {
name: "Qt3DExtras::Extras::Quick::Quick3DLevelOfDetailLoader"
prototype: "Qt3DCore::QEntity"
@@ -758,13 +799,15 @@ Module {
prototype: "Qt3DRender::QTechniqueFilter"
exports: [
"Qt3D.Extras/ForwardRenderer 2.0",
+ "Qt3D.Extras/ForwardRenderer 2.14",
"Qt3D.Extras/ForwardRenderer 2.9"
]
- exportMetaObjectRevisions: [0, 9]
+ exportMetaObjectRevisions: [0, 14, 9]
Property { name: "surface"; type: "QObject"; isPointer: true }
Property { name: "window"; type: "QObject"; isPointer: true }
Property { name: "viewportRect"; type: "QRectF" }
Property { name: "clearColor"; type: "QColor" }
+ Property { name: "buffersToClear"; revision: 14; type: "Qt3DRender::QClearBuffers::BufferType" }
Property { name: "camera"; type: "Qt3DCore::QEntity"; isPointer: true }
Property { name: "externalRenderTargetSize"; type: "QSize" }
Property { name: "frustumCulling"; type: "bool" }
@@ -778,6 +821,10 @@ Module {
Parameter { name: "clearColor"; type: "QColor" }
}
Signal {
+ name: "buffersToClearChanged"
+ Parameter { type: "Qt3DRender::QClearBuffers::BufferType" }
+ }
+ Signal {
name: "cameraChanged"
Parameter { name: "camera"; type: "Qt3DCore::QEntity"; isPointer: true }
}
@@ -806,6 +853,10 @@ Module {
Parameter { name: "clearColor"; type: "QColor" }
}
Method {
+ name: "setBuffersToClear"
+ Parameter { type: "Qt3DRender::QClearBuffers::BufferType" }
+ }
+ Method {
name: "setCamera"
Parameter { name: "camera"; type: "Qt3DCore::QEntity"; isPointer: true }
}
diff --git a/src/quick3d/imports/input/plugins.qmltypes b/src/quick3d/imports/input/plugins.qmltypes
index 8e9cac4d1..0a70b97c3 100644
--- a/src/quick3d/imports/input/plugins.qmltypes
+++ b/src/quick3d/imports/input/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Input 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Input 2.14'
Module {
dependencies: ["Qt3D.Core 2.0"]
diff --git a/src/quick3d/imports/logic/plugins.qmltypes b/src/quick3d/imports/logic/plugins.qmltypes
index 294f6b068..1ad7b1f58 100644
--- a/src/quick3d/imports/logic/plugins.qmltypes
+++ b/src/quick3d/imports/logic/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Logic 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Logic 2.14'
Module {
dependencies: ["Qt3D.Core 2.0"]
diff --git a/src/quick3d/imports/render/plugins.qmltypes b/src/quick3d/imports/render/plugins.qmltypes
index f5f5b3c61..6408abb27 100644
--- a/src/quick3d/imports/render/plugins.qmltypes
+++ b/src/quick3d/imports/render/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Render 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Render 2.14'
Module {
dependencies: ["Qt3D.Core 2.0"]
@@ -362,7 +362,8 @@ Module {
"R5G6B5": 36194,
"RGB5A1": 32855,
"RGBA4": 32854,
- "RGB10A2": 36975,
+ "RGB10A2": 32857,
+ "RGB10A2U": 36975,
"D16": 33189,
"D24": 33190,
"D24S8": 35056,
@@ -588,6 +589,10 @@ Module {
name: "setSamples"
Parameter { name: "samples"; type: "int" }
}
+ Method {
+ name: "updateData"
+ Parameter { name: "update"; type: "QTextureDataUpdate" }
+ }
}
Component {
name: "Qt3DRender::QAbstractTextureImage"
@@ -1068,8 +1073,12 @@ Module {
Component {
name: "Qt3DRender::QCamera"
prototype: "Qt3DCore::QEntity"
- exports: ["Qt3D.Render/Camera 2.0", "Qt3D.Render/Camera 2.9"]
- exportMetaObjectRevisions: [0, 9]
+ exports: [
+ "Qt3D.Render/Camera 2.0",
+ "Qt3D.Render/Camera 2.14",
+ "Qt3D.Render/Camera 2.9"
+ ]
+ exportMetaObjectRevisions: [0, 14, 9]
Enum {
name: "CameraTranslationOption"
values: {
@@ -1093,6 +1102,20 @@ Module {
Property { name: "viewCenter"; type: "QVector3D" }
Property { name: "viewVector"; type: "QVector3D"; isReadonly: true }
Property { name: "viewMatrix"; type: "QMatrix4x4"; isReadonly: true }
+ Property {
+ name: "lens"
+ revision: 14
+ type: "Qt3DRender::QCameraLens"
+ isReadonly: true
+ isPointer: true
+ }
+ Property {
+ name: "transform"
+ revision: 14
+ type: "Qt3DCore::QTransform"
+ isReadonly: true
+ isPointer: true
+ }
Signal {
name: "projectionTypeChanged"
Parameter { name: "projectionType"; type: "QCameraLens::ProjectionType" }
@@ -1666,6 +1689,30 @@ Module {
}
}
Component {
+ name: "Qt3DRender::QDepthRange"
+ prototype: "Qt3DRender::QRenderState"
+ exports: ["Qt3D.Render/DepthRange 2.14"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "nearValue"; type: "double" }
+ Property { name: "farValue"; type: "double" }
+ Signal {
+ name: "nearValueChanged"
+ Parameter { name: "nearValue"; type: "double" }
+ }
+ Signal {
+ name: "farValueChanged"
+ Parameter { name: "farValue"; type: "double" }
+ }
+ Method {
+ name: "setNearValue"
+ Parameter { name: "value"; type: "double" }
+ }
+ Method {
+ name: "setFarValue"
+ Parameter { name: "value"; type: "double" }
+ }
+ }
+ Component {
name: "Qt3DRender::QDepthTest"
prototype: "Qt3DRender::QRenderState"
exports: ["Qt3D.Render/DepthTest 2.0"]
@@ -2335,6 +2382,12 @@ Module {
exportMetaObjectRevisions: [0]
}
Component {
+ name: "Qt3DRender::QNoPicking"
+ prototype: "Qt3DRender::QFrameGraphNode"
+ exports: ["Qt3D.Render/NoPicking 2.14"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
name: "Qt3DRender::QObjectPicker"
prototype: "Qt3DCore::QComponent"
exports: [
@@ -2429,9 +2482,9 @@ Module {
Component {
name: "Qt3DRender::QPickEvent"
prototype: "QObject"
- exports: ["Qt3D.Render/PickEvent 2.0"]
+ exports: ["Qt3D.Render/PickEvent 2.0", "Qt3D.Render/PickEvent 2.14"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [0, 14]
Enum {
name: "Buttons"
values: {
@@ -2461,6 +2514,20 @@ Module {
Property { name: "button"; type: "Qt3DRender::QPickEvent::Buttons"; isReadonly: true }
Property { name: "buttons"; type: "int"; isReadonly: true }
Property { name: "modifiers"; type: "int"; isReadonly: true }
+ Property {
+ name: "viewport"
+ revision: 14
+ type: "Qt3DRender::QViewport"
+ isReadonly: true
+ isPointer: true
+ }
+ Property {
+ name: "entity"
+ revision: 14
+ type: "Qt3DCore::QEntity"
+ isReadonly: true
+ isPointer: true
+ }
Signal {
name: "acceptedChanged"
Parameter { name: "accepted"; type: "bool" }
@@ -2654,6 +2721,46 @@ Module {
}
}
Component {
+ name: "Qt3DRender::QRasterMode"
+ prototype: "Qt3DRender::QRenderState"
+ exports: ["Qt3D.Render/RasterMode 2.13"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "RasterMode"
+ values: {
+ "Points": 6912,
+ "Lines": 6913,
+ "Fill": 6914
+ }
+ }
+ Enum {
+ name: "FaceMode"
+ values: {
+ "Front": 1028,
+ "Back": 1029,
+ "FrontAndBack": 1032
+ }
+ }
+ Property { name: "rasterMode"; type: "RasterMode" }
+ Property { name: "faceMode"; type: "FaceMode" }
+ Signal {
+ name: "rasterModeChanged"
+ Parameter { name: "rasterMode"; type: "RasterMode" }
+ }
+ Signal {
+ name: "faceModeChanged"
+ Parameter { name: "faceMode"; type: "FaceMode" }
+ }
+ Method {
+ name: "setRasterMode"
+ Parameter { name: "rasterMode"; type: "RasterMode" }
+ }
+ Method {
+ name: "setFaceMode"
+ Parameter { name: "faceMode"; type: "FaceMode" }
+ }
+ }
+ Component {
name: "Qt3DRender::QRayCaster"
prototype: "Qt3DRender::QAbstractRayCaster"
Property { name: "origin"; type: "QVector3D" }
@@ -3151,6 +3258,120 @@ Module {
exportMetaObjectRevisions: [0]
}
Component {
+ name: "Qt3DRender::QShaderImage"
+ prototype: "Qt3DCore::QNode"
+ exports: ["Qt3D.Render/ShaderImage 2.14"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Access"
+ values: {
+ "ReadOnly": 0,
+ "WriteOnly": 1,
+ "ReadWrite": 2
+ }
+ }
+ Enum {
+ name: "ImageFormat"
+ values: {
+ "NoFormat": 0,
+ "Automatic": 1,
+ "R8_UNorm": 33321,
+ "RG8_UNorm": 33323,
+ "RGBA8_UNorm": 32856,
+ "R16_UNorm": 33322,
+ "RG16_UNorm": 33324,
+ "RGBA16_UNorm": 32859,
+ "R8_SNorm": 36756,
+ "RG8_SNorm": 36757,
+ "RGBA8_SNorm": 36759,
+ "R16_SNorm": 36760,
+ "RG16_SNorm": 36761,
+ "RGBA16_SNorm": 36763,
+ "R8U": 33330,
+ "RG8U": 33336,
+ "RGBA8U": 36220,
+ "R16U": 33332,
+ "RG16U": 33338,
+ "RGBA16U": 36214,
+ "R32U": 33334,
+ "RG32U": 33340,
+ "RGBA32U": 36208,
+ "R8I": 33329,
+ "RG8I": 33335,
+ "RGBA8I": 36238,
+ "R16I": 33331,
+ "RG16I": 33337,
+ "RGBA16I": 36232,
+ "R32I": 33333,
+ "RG32I": 33339,
+ "RGBA32I": 36226,
+ "R16F": 33325,
+ "RG16F": 33327,
+ "RGBA16F": 34842,
+ "R32F": 33326,
+ "RG32F": 33328,
+ "RGBA32F": 34836,
+ "RG11B10F": 35898,
+ "RGB10A2": 32857,
+ "RGB10A2U": 36975
+ }
+ }
+ Property { name: "texture"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "layered"; type: "bool" }
+ Property { name: "mipLevel"; type: "int" }
+ Property { name: "layer"; type: "int" }
+ Property { name: "access"; type: "Access" }
+ Property { name: "format"; type: "ImageFormat" }
+ Signal {
+ name: "textureChanged"
+ Parameter { name: "texture"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "layeredChanged"
+ Parameter { name: "layered"; type: "bool" }
+ }
+ Signal {
+ name: "mipLevelChanged"
+ Parameter { name: "mipLevel"; type: "int" }
+ }
+ Signal {
+ name: "layerChanged"
+ Parameter { name: "layer"; type: "int" }
+ }
+ Signal {
+ name: "accessChanged"
+ Parameter { name: "access"; type: "Access" }
+ }
+ Signal {
+ name: "formatChanged"
+ Parameter { name: "format"; type: "ImageFormat" }
+ }
+ Method {
+ name: "setTexture"
+ Parameter { name: "texture"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setLayered"
+ Parameter { name: "layered"; type: "bool" }
+ }
+ Method {
+ name: "setMipLevel"
+ Parameter { name: "mipLevel"; type: "int" }
+ }
+ Method {
+ name: "setLayer"
+ Parameter { name: "layer"; type: "int" }
+ }
+ Method {
+ name: "setAccess"
+ Parameter { name: "access"; type: "Access" }
+ }
+ Method {
+ name: "setFormat"
+ Parameter { name: "format"; type: "ImageFormat" }
+ }
+ }
+ Component {
name: "Qt3DRender::QShaderProgram"
prototype: "Qt3DCore::QNode"
exports: [
@@ -3400,7 +3621,8 @@ Module {
"StateChangeCost": 1,
"BackToFront": 2,
"Material": 4,
- "FrontToBack": 8
+ "FrontToBack": 8,
+ "Texture": 16
}
}
Property { name: "sortTypes"; type: "QVector<int>" }
@@ -3653,6 +3875,25 @@ Module {
}
}
Component {
+ name: "Qt3DRender::QSubtreeEnabler"
+ prototype: "Qt3DRender::QFrameGraphNode"
+ exports: ["Qt3D.Render/SubtreeEnabler 2.14"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Enablement"
+ values: {
+ "Persistent": 0,
+ "SingleShot": 1
+ }
+ }
+ Property { name: "enablement"; type: "Enablement" }
+ Signal {
+ name: "enablementChanged"
+ Parameter { name: "enablement"; type: "Qt3DRender::QSubtreeEnabler::Enablement" }
+ }
+ Method { name: "requestUpdate" }
+ }
+ Component {
name: "Qt3DRender::QTechnique"
defaultProperty: "data"
prototype: "Qt3DCore::QNode"
diff --git a/src/quick3d/imports/scene2d/plugins.qmltypes b/src/quick3d/imports/scene2d/plugins.qmltypes
index 9d2c855a6..32fb8122f 100644
--- a/src/quick3d/imports/scene2d/plugins.qmltypes
+++ b/src/quick3d/imports/scene2d/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Scene2D 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Scene2D 2.14'
Module {
dependencies: ["Qt3D.Core 2.0", "Qt3D.Render 2.0"]
diff --git a/src/quick3d/imports/scene3d/plugins.qmltypes b/src/quick3d/imports/scene3d/plugins.qmltypes
index da3d7ec3e..aca01ac25 100644
--- a/src/quick3d/imports/scene3d/plugins.qmltypes
+++ b/src/quick3d/imports/scene3d/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Scene3D 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Scene3D 2.14'
Module {
dependencies: ["Qt3D.Core 2.0", "QtQuick 2.0"]
@@ -12,8 +12,11 @@ Module {
name: "Qt3DRender::Scene3DItem"
defaultProperty: "entity"
prototype: "QQuickItem"
- exports: ["QtQuick.Scene3D/Scene3D 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Scene3D/Scene3D 2.0",
+ "QtQuick.Scene3D/Scene3D 2.14"
+ ]
+ exportMetaObjectRevisions: [0, 14]
Enum {
name: "CameraAspectRatioMode"
values: {
@@ -21,11 +24,19 @@ Module {
"UserAspectRatio": 1
}
}
+ Enum {
+ name: "CompositingMode"
+ values: {
+ "FBO": 0,
+ "Underlay": 1
+ }
+ }
Property { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true }
Property { name: "aspects"; type: "QStringList" }
Property { name: "multisample"; type: "bool" }
Property { name: "cameraAspectRatioMode"; type: "CameraAspectRatioMode" }
Property { name: "hoverEnabled"; type: "bool" }
+ Property { name: "compositingMode"; revision: 14; type: "CompositingMode" }
Signal {
name: "cameraAspectRatioModeChanged"
Parameter { name: "mode"; type: "CameraAspectRatioMode" }
@@ -47,9 +58,30 @@ Module {
Parameter { name: "enabled"; type: "bool" }
}
Method {
+ name: "setCompositingMode"
+ Parameter { name: "mode"; type: "CompositingMode" }
+ }
+ Method {
name: "setItemAreaAndDevicePixelRatio"
Parameter { name: "area"; type: "QSize" }
Parameter { name: "devicePixelRatio"; type: "double" }
}
}
+ Component {
+ name: "Qt3DRender::Scene3DView"
+ defaultProperty: "entity"
+ prototype: "QQuickItem"
+ exports: ["QtQuick.Scene3D/Scene3DView 2.14"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true }
+ Property { name: "scene3D"; type: "Qt3DRender::Scene3DItem"; isPointer: true }
+ Method {
+ name: "setEntity"
+ Parameter { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true }
+ }
+ Method {
+ name: "setScene3D"
+ Parameter { name: "scene3D"; type: "Scene3DItem"; isPointer: true }
+ }
+ }
}
diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp
index f3f7acd71..f824d2c4e 100644
--- a/src/quick3d/imports/scene3d/scene3ditem.cpp
+++ b/src/quick3d/imports/scene3d/scene3ditem.cpp
@@ -137,6 +137,11 @@ namespace Qt3DRender {
\li The Scene3D instance is instantiated prior to any Scene3DView
\li The Scene3D entity property is left unset
\endlist
+
+ \note Åšetting the visibility of the Scene3D element to false will halt the
+ Qt 3D simulation loop. This means that binding the visible property to an
+ expression that depends on property updates driven by the Qt 3D simulation
+ loop (FrameAction) will never reavaluates.
*/
Scene3DItem::Scene3DItem(QQuickItem *parent)
: QQuickItem(parent)
@@ -154,6 +159,7 @@ Scene3DItem::Scene3DItem(QQuickItem *parent)
, m_disableClearWindow(false)
, m_cameraAspectRatioMode(AutomaticAspectRatio)
, m_compositingMode(FBO)
+ , m_dummySurface(nullptr)
{
setFlag(QQuickItem::ItemHasContents, true);
setAcceptedMouseButtons(Qt::MouseButtonMask);
@@ -427,12 +433,26 @@ void Scene3DItem::applyRootEntityChange()
bool Scene3DItem::needsRender()
{
+ // We need the dirty flag which is connected to the change arbiter
+ // receiving updates to know whether something in the scene has changed
+
+ // Ideally we would use shouldRender() alone but given that it becomes true
+ // only after the arbiter has sync the changes and might be reset before
+ // process jobs is completed, we cannot fully rely on it. It would require
+ // splitting processFrame in 2 parts.
+
+ // We only use it for cases where Qt3D render may require several loops of
+ // the simulation to fully process a frame (e.g shaders are loaded in frame
+ // n and we can only build render commands for the new shader at frame n +
+ // This is where renderer->shouldRender() comes into play as it knows
+ // whether some states remain dirty or not (even after processFrame is
+ // called)
+
auto renderAspectPriv = static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect));
const bool dirty = m_dirty
|| (renderAspectPriv
&& renderAspectPriv->m_renderer
- && renderAspectPriv->m_renderer->settings()
- && renderAspectPriv->m_renderer->settings()->renderPolicy() == QRenderSettings::Always);
+ && renderAspectPriv->m_renderer->shouldRender());
m_dirty = false;
return dirty;
}
@@ -454,8 +474,12 @@ bool Scene3DItem::needsRender()
// processFrame will block and wait for renderer to have been finished
void Scene3DItem::onBeforeSync()
{
- // Has anything in the 3D scene actually changed that requires us to render?
- if (!needsRender())
+ static bool dontRenderWhenHidden = !qgetenv("QT3D_SCENE3D_STOP_RENDER_HIDDEN").isEmpty();
+
+ // If we are not visible, don't processFrame changes as we would end up
+ // waiting forever for the scene to be rendered which won't happen
+ // if the Scene3D item is not visible
+ if (!isVisible() && dontRenderWhenHidden)
return;
Q_ASSERT(QThread::currentThread() == thread());
@@ -498,6 +522,7 @@ void Scene3DItem::onBeforeSync()
// start rendering before this function has been called
// We add in a safety to skip such frames as this could otherwise
// make Qt3D enter a locked state
+ m_renderer->setSkipFrame(!needsRender());
m_renderer->allowRender();
// Note: it's too early to request an update at this point as
@@ -546,7 +571,7 @@ void Scene3DItem::setWindowSurface(QObject *rootObject)
/*!
\qmlmethod void Scene3D::setItemAreaAndDevicePixelRatio(size area, real devicePixelRatio)
- \brief \TODO
+ Sets the item area to \a area and the pixel ratio to \a devicePixelRatio.
*/
void Scene3DItem::setItemAreaAndDevicePixelRatio(QSize area, qreal devicePixelRatio)
{
@@ -569,25 +594,45 @@ bool Scene3DItem::isHoverEnabled() const
void Scene3DItem::setCameraAspectModeHelper()
{
- switch (m_cameraAspectRatioMode) {
- case AutomaticAspectRatio:
- connect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
- connect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
- // Update the aspect ratio the first time the surface is set
- updateCameraAspectRatio();
- break;
- case UserAspectRatio:
- disconnect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
- disconnect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
- break;
+ if (m_compositingMode == FBO) {
+ switch (m_cameraAspectRatioMode) {
+ case AutomaticAspectRatio:
+ connect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ connect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ // Update the aspect ratio the first time the surface is set
+ updateCameraAspectRatio();
+ break;
+ case UserAspectRatio:
+ disconnect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ disconnect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ break;
+ }
+ } else {
+ // In Underlay mode, we rely on the window for aspect ratio and not the size of the Scene3DItem
+ switch (m_cameraAspectRatioMode) {
+ case AutomaticAspectRatio:
+ connect(window(), &QWindow::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ connect(window(), &QWindow::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ // Update the aspect ratio the first time the surface is set
+ updateCameraAspectRatio();
+ break;
+ case UserAspectRatio:
+ disconnect(window(), &QWindow::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ disconnect(window(), &QWindow::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ break;
+ }
}
}
void Scene3DItem::updateCameraAspectRatio()
{
if (m_camera) {
- m_camera->setAspectRatio(static_cast<float>(width()) /
- static_cast<float>(height()));
+ if (m_compositingMode == FBO)
+ m_camera->setAspectRatio(static_cast<float>(width()) /
+ static_cast<float>(height()));
+ else
+ m_camera->setAspectRatio(static_cast<float>(window()->width()) /
+ static_cast<float>(window()->height()));
}
}
diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp
index 1e375ccbb..fafeeedf4 100644
--- a/src/quick3d/imports/scene3d/scene3drenderer.cpp
+++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp
@@ -161,7 +161,9 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp
, m_forceRecreate(false)
, m_shouldRender(false)
, m_dirtyViews(false)
+ , m_skipFrame(false)
, m_allowRendering(0)
+ , m_compositingMode(Scene3DItem::FBO)
{
Q_CHECK_PTR(m_item);
Q_CHECK_PTR(m_item->window());
@@ -277,6 +279,19 @@ void Scene3DRenderer::beforeSynchronize()
// We could otherwise enter a deadlock state
if (!m_allowRendering.tryAcquire(std::max(m_allowRendering.available(), 1)))
return;
+
+ // In the case of OnDemand rendering, we still need to get to this
+ // point to ensure we have processed jobs for all aspects.
+ // We also still need to call render() to allow proceeding with the
+ // next frame. However it won't be performing any 3d rendering at all
+ // so we do it here and return early. This prevents a costly QtQuick
+ // SceneGraph update for nothing
+ if (m_skipFrame) {
+ m_skipFrame = false;
+ static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous(false);
+ return;
+ }
+
m_shouldRender = true;
// Check size / multisampling
@@ -359,6 +374,11 @@ void Scene3DRenderer::setCompositingMode(Scene3DItem::CompositingMode mode)
m_compositingMode = mode;
}
+void Scene3DRenderer::setSkipFrame(bool skip)
+{
+ m_skipFrame = skip;
+}
+
// Main Thread, Render Thread locked
void Scene3DRenderer::setScene3DViews(const QVector<Scene3DView *> views)
{
@@ -422,7 +442,8 @@ void Scene3DRenderer::render()
// Only show the node once Qt3D has rendered to it
// Avoids showing garbage on the first frame
- m_node->show();
+ if (m_node)
+ m_node->show();
}
// Reset the state used by the Qt Quick scenegraph to avoid any
diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h
index 4f3651cd3..08a2c60a3 100644
--- a/src/quick3d/imports/scene3d/scene3drenderer_p.h
+++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h
@@ -87,7 +87,7 @@ public:
void setCleanerHelper(Scene3DCleaner *cleaner);
void allowRender();
void setCompositingMode(Scene3DItem::CompositingMode mode);
-
+ void setSkipFrame(bool skip);
void setScene3DViews(const QVector<Scene3DView *> views);
public Q_SLOTS:
@@ -119,6 +119,7 @@ private:
bool m_forceRecreate;
bool m_shouldRender;
bool m_dirtyViews;
+ bool m_skipFrame;
QSemaphore m_allowRendering;
Scene3DItem::CompositingMode m_compositingMode;
QVector<Scene3DView *> m_views;
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
index 55538ad1f..cfe39e8c7 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
@@ -76,6 +76,7 @@ Scene3DSGMaterialShader::Scene3DSGMaterialShader()
: QSGMaterialShader()
, m_matrixId(-1)
, m_opacityId(-1)
+ , m_visibleId(-1)
{
}
diff --git a/src/quick3d/imports/scene3d/scene3dview.cpp b/src/quick3d/imports/scene3d/scene3dview.cpp
index 9d298b435..f38d135f0 100644
--- a/src/quick3d/imports/scene3d/scene3dview.cpp
+++ b/src/quick3d/imports/scene3d/scene3dview.cpp
@@ -278,6 +278,8 @@ QSGNode *Scene3DView::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode
if (m_dirtyFlags & DirtyTexture) {
fboNode->setTexture(m_texture);
m_dirtyFlags.setFlag(DirtyTexture, false);
+ // Show FBO Node at this point
+ fboNode->show();
}
if (m_dirtyFlags & DirtyNode) {
fboNode->markDirty(QSGNode::DirtyMaterial);
diff --git a/src/quick3d/quick3d/qquaternionanimation.cpp b/src/quick3d/quick3d/qquaternionanimation.cpp
index 22cc905f7..933a08ee4 100644
--- a/src/quick3d/quick3d/qquaternionanimation.cpp
+++ b/src/quick3d/quick3d/qquaternionanimation.cpp
@@ -144,7 +144,7 @@ void QQuaternionAnimation::setType(Type type)
switch (type) {
case Nlerp:
QT_WARNING_PUSH
-QT_WARNING_DISABLE_GCC(-Wcast-function-type)
+QT_WARNING_DISABLE_GCC("-Wcast-function-type")
d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&q_quaternionNlerpInterpolator);
QT_WARNING_POP
break;
diff --git a/src/quick3d/quick3dextras/qt3dquickwindow.cpp b/src/quick3d/quick3dextras/qt3dquickwindow.cpp
index d67dfdc71..043aca8b9 100644
--- a/src/quick3d/quick3dextras/qt3dquickwindow.cpp
+++ b/src/quick3d/quick3dextras/qt3dquickwindow.cpp
@@ -276,7 +276,7 @@ void Qt3DQuickWindow::updateCameraAspectRatio()
Q_D(Qt3DQuickWindow);
if (d->m_camera) {
d->m_camera->setAspectRatio(static_cast<float>(width()) /
- static_cast<float>(height()));
+ std::max(1.f, static_cast<float>(height())));
}
}
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d.cpp b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
index cbdc83e7d..b12adb8ed 100644
--- a/src/quick3d/quick3dscene2d/items/qscene2d.cpp
+++ b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
@@ -52,6 +52,12 @@ namespace Qt3DRender {
namespace Quick {
/*!
+ \namespace Qt3DRender::Quick
+ \inmodule Qt3DScene2D
+ \brief Internal namespace to import QML types.
+*/
+
+/*!
\class Qt3DRender::Quick::QScene2D
\inheaderfile Qt3DQuickScene2D/QScene2D
\inmodule Qt3DScene2D
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d.h b/src/quick3d/quick3dscene2d/items/qscene2d.h
index 2f5c1010e..38eaf7359 100644
--- a/src/quick3d/quick3dscene2d/items/qscene2d.h
+++ b/src/quick3d/quick3dscene2d/items/qscene2d.h
@@ -51,11 +51,6 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-/*!
- \namespace Qt3DRender::Quick
-
- \brief Internal namespace to import QML types.
-*/
namespace Quick {
class QScene2DPrivate;
diff --git a/src/quick3d/quick3dscene2d/items/scene2d.cpp b/src/quick3d/quick3dscene2d/items/scene2d.cpp
index 981b290e2..a2247705e 100644
--- a/src/quick3d/quick3dscene2d/items/scene2d.cpp
+++ b/src/quick3d/quick3dscene2d/items/scene2d.cpp
@@ -208,11 +208,16 @@ void Scene2D::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
if (!entity)
return;
- registerObjectPickerEvents(entity);
+ if (registerObjectPickerEvents(entity))
+ m_entities.push_back(id);
+ else
+ Qt3DCore::QNodePrivate::get(const_cast<Qt3DCore::QNode *>(frontEnd))->update();
}
- for (const auto &id: removedEntities)
+ for (const auto &id: removedEntities) {
+ m_entities.removeOne(id);
unregisterObjectPickerEvents(id);
- m_entities = ids;
+ }
+ std::sort(std::begin(m_entities), std::end(m_entities));
if (firstTime)
setSharedObject(dnode->m_renderManager->m_sharedObject);
@@ -428,8 +433,11 @@ bool Scene2D::registerObjectPickerEvents(Qt3DCore::QEntity *qentity)
{
Entity *entity = nullptr;
if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
- qentity->id(), (void**)&entity, nullptr))
+ qentity->id(), (void**)&entity, nullptr)) {
+ qCWarning(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO
+ << "Entity not yet available in backend";
return false;
+ }
if (!entity->containsComponentsOfType<ObjectPicker>() ||
!entity->containsComponentsOfType<GeometryRenderer>()) {
diff --git a/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp b/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp
index cb9973f0a..aed624501 100644
--- a/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp
+++ b/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp
@@ -59,6 +59,7 @@ Scene2DSharedObject::Scene2DSharedObject(Scene2DManager *manager)
, m_quickWindow(nullptr)
, m_renderManager(manager)
, m_surface(nullptr)
+ , m_renderThread(nullptr)
, m_renderObject(nullptr)
, m_disallowed(false)
, m_quit(false)
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h
index b618eda55..8bbfcd548 100644
--- a/src/render/backend/abstractrenderer_p.h
+++ b/src/render/backend/abstractrenderer_p.h
@@ -71,6 +71,7 @@ class QAbstractFrameAdvanceService;
class QEventFilterService;
class QAbstractAspectJobManager;
class QServiceLocator;
+class QAspectManager;
}
namespace Qt3DRender {
@@ -151,8 +152,9 @@ public:
#if defined(QT_BUILD_INTERNAL)
virtual void clearDirtyBits(BackendNodeDirtySet changes) = 0;
#endif
- virtual bool shouldRender() = 0;
+ virtual bool shouldRender() const = 0;
virtual void skipNextFrame() = 0;
+ virtual void jobsDone(Qt3DCore::QAspectManager *manager) = 0;
virtual QVector<Qt3DCore::QAspectJobPtr> preRenderingJobs() = 0;
virtual QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() = 0;
diff --git a/src/render/backend/bufferutils_p.h b/src/render/backend/bufferutils_p.h
index 2bb35fac6..ea783df0d 100644
--- a/src/render/backend/bufferutils_p.h
+++ b/src/render/backend/bufferutils_p.h
@@ -74,6 +74,8 @@ struct BufferInfo
, count(0)
, byteStride(0)
, byteOffset(0)
+ , restartEnabled(false)
+ , restartIndexValue(-1)
{}
QByteArray data;
@@ -82,6 +84,8 @@ struct BufferInfo
uint count;
uint byteStride;
uint byteOffset;
+ bool restartEnabled;
+ int restartIndexValue;
};
diff --git a/src/render/backend/cameralens.cpp b/src/render/backend/cameralens.cpp
index 85c5e9656..e1d72efda 100644
--- a/src/render/backend/cameralens.cpp
+++ b/src/render/backend/cameralens.cpp
@@ -46,8 +46,10 @@
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/sphere_p.h>
#include <Qt3DRender/private/computefilteredboundingvolumejob_p.h>
+#include <Qt3DRender/private/renderlogging_p.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
QT_BEGIN_NAMESPACE
@@ -62,21 +64,21 @@ namespace {
class GetBoundingVolumeWithoutCameraJob : public ComputeFilteredBoundingVolumeJob
{
public:
- GetBoundingVolumeWithoutCameraJob(CameraLens *lens,
- QNodeCommand::CommandId commandId)
- : m_lens(lens), m_commandId(commandId)
+ GetBoundingVolumeWithoutCameraJob(CameraLens *lens, QNodeId commandId)
+ : m_lens(lens), m_requestId(commandId)
{
}
protected:
- void finished(const Sphere &sphere) override
+ // called in main thread
+ void finished(Qt3DCore::QAspectManager *aspectManager, const Sphere &sphere) override
{
- m_lens->notifySceneBoundingVolume(sphere, m_commandId);
+ m_lens->processViewAllResult(aspectManager, sphere, m_requestId);
}
private:
CameraLens *m_lens;
- QNodeCommand::CommandId m_commandId;
+ QNodeId m_requestId;
};
} // namespace
@@ -114,6 +116,9 @@ Matrix4x4 CameraLens::viewMatrix(const Matrix4x4 &worldTransform)
m.lookAt(convertToQVector3D(Vector3D(position)),
convertToQVector3D(Vector3D(position + viewDirection)),
convertToQVector3D(Vector3D(upVector)));
+
+ qDebug(Jobs) << Q_FUNC_INFO << "Transform Matrix" << worldTransform << "View Matrix" << m;
+
return Matrix4x4(m);
}
@@ -131,34 +136,23 @@ void CameraLens::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTim
markDirty(AbstractRenderer::AllDirty);
}
- if (node->exposure() != m_exposure) {
+ if (!qFuzzyCompare(node->exposure(), m_exposure)) {
m_exposure = node->exposure();
markDirty(AbstractRenderer::AllDirty);
}
const QCameraLensPrivate *d = static_cast<const QCameraLensPrivate *>(QNodePrivate::get(node));
- if (d->m_pendingViewAllCommand != m_pendingViewAllCommand) {
- m_pendingViewAllCommand = d->m_pendingViewAllCommand;
-
- if (m_pendingViewAllCommand) {
- const QVariant v = m_pendingViewAllCommand.data;
- const QNodeCommand::CommandId commandId = m_pendingViewAllCommand.commandId;
-
- if (m_pendingViewAllCommand.name == QLatin1String("QueryRootBoundingVolume")) {
- const QNodeId id = v.value<QNodeId>();
- computeSceneBoundingVolume({}, id, commandId);
- } else if (m_pendingViewAllCommand.name == QLatin1String("QueryEntityBoundingVolume")) {
- const QVector<QNodeId> ids = v.value<QVector<QNodeId>>();
- if (ids.size() == 2)
- computeSceneBoundingVolume(ids[0], ids[1], commandId);
- }
- }
+ if (d->m_pendingViewAllRequest != m_pendingViewAllRequest) {
+ m_pendingViewAllRequest = d->m_pendingViewAllRequest;
+
+ if (m_pendingViewAllRequest)
+ computeSceneBoundingVolume(m_pendingViewAllRequest.entityId, m_pendingViewAllRequest.cameraId, m_pendingViewAllRequest.requestId);
}
}
void CameraLens::computeSceneBoundingVolume(QNodeId entityId,
QNodeId cameraId,
- QNodeCommand::CommandId commandId)
+ QNodeId requestId)
{
if (!m_renderer || !m_renderAspect)
return;
@@ -171,7 +165,7 @@ void CameraLens::computeSceneBoundingVolume(QNodeId entityId,
return;
Entity *camNode = nodeManagers->renderNodesManager()->lookupResource(cameraId);
- ComputeFilteredBoundingVolumeJobPtr job(new GetBoundingVolumeWithoutCameraJob(this, commandId));
+ ComputeFilteredBoundingVolumeJobPtr job(new GetBoundingVolumeWithoutCameraJob(this, requestId));
job->addDependency(m_renderer->expandBoundingVolumeJob());
job->setRoot(root);
job->setManagers(nodeManagers);
@@ -179,18 +173,18 @@ void CameraLens::computeSceneBoundingVolume(QNodeId entityId,
m_renderAspect->scheduleSingleShotJob(job);
}
-void CameraLens::notifySceneBoundingVolume(const Sphere &sphere, QNodeCommand::CommandId commandId)
+void CameraLens::processViewAllResult(QAspectManager *aspectManager, const Sphere &sphere, QNodeId commandId)
{
- if (!m_pendingViewAllCommand || m_pendingViewAllCommand.commandId != commandId)
+ if (!m_pendingViewAllRequest || m_pendingViewAllRequest.requestId != commandId)
return;
if (sphere.radius() > 0.f) {
- QVector<float> data = { sphere.center().x(), sphere.center().y(), sphere.center().z(),
- sphere.radius() };
- QVariant v;
- v.setValue(data);
- sendCommand(QLatin1String("ViewAll"), v, m_pendingViewAllCommand.commandId);
+ QCameraLens *lens = qobject_cast<QCameraLens *>(aspectManager->lookupNode(peerId()));
+ if (lens) {
+ QCameraLensPrivate *dlens = static_cast<QCameraLensPrivate *>(QCameraLensPrivate::get(lens));
+ dlens->processViewAllResult(m_pendingViewAllRequest.requestId, { sphere.center().x(), sphere.center().y(), sphere.center().z() }, sphere.radius());
+ }
}
- m_pendingViewAllCommand = {};
+ m_pendingViewAllRequest = {};
}
void CameraLens::setProjection(const Matrix4x4 &projection)
diff --git a/src/render/backend/cameralens_p.h b/src/render/backend/cameralens_p.h
index bd721d5e9..4afa38620 100644
--- a/src/render/backend/cameralens_p.h
+++ b/src/render/backend/cameralens_p.h
@@ -52,7 +52,6 @@
//
#include <Qt3DRender/private/backendnode_p.h>
-#include <Qt3DCore/private/qnodecommand_p.h>
#include <Qt3DCore/private/matrix4x4_p.h>
#include <Qt3DRender/private/qcameralens_p.h>
#include <QRectF>
@@ -99,7 +98,7 @@ public:
inline float exposure() const { return m_exposure; }
void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
- void notifySceneBoundingVolume(const Sphere &sphere, Qt3DCore::QNodeCommand::CommandId commandId);
+ void processViewAllResult(Qt3DCore::QAspectManager *aspectManager, const Sphere &sphere, Qt3DCore::QNodeId commandId);
static bool viewMatrixForCamera(EntityManager *manager, Qt3DCore::QNodeId cameraId,
Matrix4x4 &viewMatrix, Matrix4x4 &projectionMatrix);
@@ -107,10 +106,10 @@ public:
private:
void computeSceneBoundingVolume(Qt3DCore::QNodeId entityId,
Qt3DCore::QNodeId cameraId,
- Qt3DCore::QNodeCommand::CommandId commandId);
+ Qt3DCore::QNodeId requestId);
QRenderAspect *m_renderAspect;
- CameraLensCommand m_pendingViewAllCommand;
+ CameraLensRequest m_pendingViewAllRequest;
Matrix4x4 m_projection;
float m_exposure;
};
diff --git a/src/render/backend/commandexecuter.cpp b/src/render/backend/commandexecuter.cpp
index 8bccb1437..5ed0c970d 100644
--- a/src/render/backend/commandexecuter.cpp
+++ b/src/render/backend/commandexecuter.cpp
@@ -248,10 +248,10 @@ QJsonObject parameterPackToJson(const Render::ShaderParameterPack &pack)
const Render::PackUniformHash &uniforms = pack.uniforms();
QJsonArray uniformsArray;
- for (auto it = uniforms.cbegin(), end = uniforms.cend(); it != end; ++it) {
+ for (int i = 0, m = uniforms.keys.size(); i < m; ++i) {
QJsonObject uniformObj;
- uniformObj.insert(QLatin1String("name"), Render::StringToInt::lookupString(it.key()));
- const Render::UniformValue::ValueType type = it.value().valueType();
+ uniformObj.insert(QLatin1String("name"), Render::StringToInt::lookupString(uniforms.keys.at(i)));
+ const Render::UniformValue::ValueType type = uniforms.values.at(i).valueType();
uniformObj.insert(QLatin1String("type"),
type == Render::UniformValue::ScalarValue
? QLatin1String("value")
@@ -346,15 +346,15 @@ void CommandExecuter::performAsynchronousCommandExecution(const QVector<Render::
viewObj.insert(QLatin1String("clearStencilValue"), v->clearStencilValue());
QJsonArray renderCommandsArray;
- for (Render::RenderCommand *c : v->commands()) {
+ for (const Render::RenderCommand &c : v->commands()) {
QJsonObject commandObj;
Render::NodeManagers *nodeManagers = m_renderer->nodeManagers();
- commandObj.insert(QLatin1String("shader"), backendNodeToJSon(c->m_shader, nodeManagers->shaderManager()));
- commandObj.insert(QLatin1String("vao"), double(c->m_vao.handle()));
- commandObj.insert(QLatin1String("instanceCount"), c->m_instanceCount);
- commandObj.insert(QLatin1String("geometry"), backendNodeToJSon(c->m_geometry, nodeManagers->geometryManager()));
- commandObj.insert(QLatin1String("geometryRenderer"), backendNodeToJSon(c->m_geometryRenderer, nodeManagers->geometryRendererManager()));
- commandObj.insert(QLatin1String("shaderParameterPack"), parameterPackToJson(c->m_parameterPack));
+ commandObj.insert(QLatin1String("shader"), backendNodeToJSon(c.m_shader, nodeManagers->shaderManager()));
+ commandObj.insert(QLatin1String("vao"), double(c.m_vao.handle()));
+ commandObj.insert(QLatin1String("instanceCount"), c.m_instanceCount);
+ commandObj.insert(QLatin1String("geometry"), backendNodeToJSon(c.m_geometry, nodeManagers->geometryManager()));
+ commandObj.insert(QLatin1String("geometryRenderer"), backendNodeToJSon(c.m_geometryRenderer, nodeManagers->geometryRendererManager()));
+ commandObj.insert(QLatin1String("shaderParameterPack"), parameterPackToJson(c.m_parameterPack));
renderCommandsArray.push_back(commandObj);
}
diff --git a/src/render/backend/computecommand.cpp b/src/render/backend/computecommand.cpp
index df79dcbe8..bc82291f0 100644
--- a/src/render/backend/computecommand.cpp
+++ b/src/render/backend/computecommand.cpp
@@ -53,6 +53,7 @@ ComputeCommand::ComputeCommand()
: BackendNode(ReadWrite)
, m_frameCount(0)
, m_runType(QComputeCommand::Continuous)
+ , m_hasReachedFrameCount(false)
{
m_workGroups[0] = 1;
m_workGroups[1] = 1;
@@ -71,6 +72,7 @@ void ComputeCommand::cleanup()
m_workGroups[2] = 1;
m_frameCount = 0;
m_runType = QComputeCommand::Continuous;
+ m_hasReachedFrameCount = false;
}
void ComputeCommand::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
@@ -98,8 +100,12 @@ void ComputeCommand::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firs
markDirty(AbstractRenderer::ComputeDirty);
}
const QComputeCommandPrivate *d = static_cast<const QComputeCommandPrivate *>(Qt3DCore::QNodePrivate::get(node));
- if (d->m_frameCount != m_frameCount) {
+ // Check frame count only if frontend is enabled
+ // If disabled that means we might have disabled the frontend because
+ // framecount reached 0
+ if (d->m_enabled && d->m_frameCount != m_frameCount) {
m_frameCount = d->m_frameCount;
+ m_hasReachedFrameCount = m_frameCount <= 0;
markDirty(AbstractRenderer::ComputeDirty);
}
@@ -112,14 +118,19 @@ void ComputeCommand::updateFrameCount()
{
// Disable frontend node when reaching 0
--m_frameCount;
- if (m_frameCount <= 0) {
- setEnabled(false);
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("enabled");
- e->setValue(false);
- notifyObservers(e);
- }
+ if (m_frameCount <= 0)
+ m_hasReachedFrameCount = true;
+ // Backend will be disabled on the next sync
+}
+
+void ComputeCommand::resetHasReachedFrameCount()
+{
+ m_hasReachedFrameCount = false;
+}
+
+bool ComputeCommand::hasReachedFrameCount() const
+{
+ return m_hasReachedFrameCount;
}
} // Render
diff --git a/src/render/backend/computecommand_p.h b/src/render/backend/computecommand_p.h
index dc2069928..5012930ae 100644
--- a/src/render/backend/computecommand_p.h
+++ b/src/render/backend/computecommand_p.h
@@ -79,11 +79,14 @@ public:
// Called from a job
void updateFrameCount();
+ bool hasReachedFrameCount() const;
+ void resetHasReachedFrameCount();
private:
int m_workGroups[3];
int m_frameCount;
QComputeCommand::RunType m_runType;
+ bool m_hasReachedFrameCount;
};
} // Render
diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri
index 9510b9530..c910adfe4 100644
--- a/src/render/backend/render-backend.pri
+++ b/src/render/backend/render-backend.pri
@@ -37,7 +37,8 @@ HEADERS += \
$$PWD/resourceaccessor_p.h \
$$PWD/visitorutils_p.h \
$$PWD/segmentsvisitor_p.h \
- $$PWD/pointsvisitor_p.h
+ $$PWD/pointsvisitor_p.h \
+ $$PWD/commandexecuter_p.h
SOURCES += \
$$PWD/renderthread.cpp \
@@ -67,11 +68,5 @@ SOURCES += \
$$PWD/offscreensurfacehelper.cpp \
$$PWD/resourceaccessor.cpp \
$$PWD/segmentsvisitor.cpp \
- $$PWD/pointsvisitor.cpp
-
-include($$QT3D_BUILD_ROOT/src/core/qt3dcore-config.pri)
-QT_FOR_CONFIG += 3dcore-private
-qtConfig(qt3d-profile-jobs): {
- HEADERS += $$PWD/commandexecuter_p.h
- SOURCES += $$PWD/commandexecuter.cpp
-}
+ $$PWD/pointsvisitor.cpp \
+ $$PWD/commandexecuter.cpp
diff --git a/src/render/backend/rendersettings.cpp b/src/render/backend/rendersettings.cpp
index 487f6e11a..5aeaa2563 100644
--- a/src/render/backend/rendersettings.cpp
+++ b/src/render/backend/rendersettings.cpp
@@ -42,7 +42,6 @@
#include <Qt3DRender/QFrameGraphNode>
#include <Qt3DRender/private/abstractrenderer_p.h>
#include <Qt3DRender/private/qrendersettings_p.h>
-#include <Qt3DCore/qnodecommand.h>
QT_BEGIN_NAMESPACE
@@ -79,20 +78,21 @@ void RenderSettings::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firs
m_renderPolicy = node->renderPolicy();
}
- if (node->pickingSettings()->pickMethod() != m_pickMethod) {
- m_pickMethod = node->pickingSettings()->pickMethod();
+ auto ncnode = const_cast<QRenderSettings *>(node);
+ if (ncnode->pickingSettings()->pickMethod() != m_pickMethod) {
+ m_pickMethod = ncnode->pickingSettings()->pickMethod();
}
- if (node->pickingSettings()->pickResultMode() != m_pickResultMode) {
- m_pickResultMode = node->pickingSettings()->pickResultMode();
+ if (ncnode->pickingSettings()->pickResultMode() != m_pickResultMode) {
+ m_pickResultMode = ncnode->pickingSettings()->pickResultMode();
}
- if (node->pickingSettings()->worldSpaceTolerance() != m_pickWorldSpaceTolerance) {
- m_pickWorldSpaceTolerance = node->pickingSettings()->worldSpaceTolerance();
+ if (ncnode->pickingSettings()->worldSpaceTolerance() != m_pickWorldSpaceTolerance) {
+ m_pickWorldSpaceTolerance = ncnode->pickingSettings()->worldSpaceTolerance();
}
- if (node->pickingSettings()->faceOrientationPickingMode() != m_faceOrientationPickingMode) {
- m_faceOrientationPickingMode = node->pickingSettings()->faceOrientationPickingMode();
+ if (ncnode->pickingSettings()->faceOrientationPickingMode() != m_faceOrientationPickingMode) {
+ m_faceOrientationPickingMode = ncnode->pickingSettings()->faceOrientationPickingMode();
}
// Either because something above as changed or if QRenderSettingsPrivate::invalidFrame()
diff --git a/src/render/backend/segmentsvisitor.cpp b/src/render/backend/segmentsvisitor.cpp
index a3a5d059c..d9f2d79ec 100644
--- a/src/render/backend/segmentsvisitor.cpp
+++ b/src/render/backend/segmentsvisitor.cpp
@@ -135,34 +135,44 @@ void traverseSegmentStripIndexed(Index *indices,
bool loop)
{
uint i = 0;
+ uint stripStartIndex = 0;
+
const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
uint ndx[2];
Vector3D abc[2];
- ndx[0] = indices[0];
- uint idx = ndx[0] * verticesStride;
- for (uint j = 0; j < maxVerticesDataSize; ++j)
- abc[0][j] = vertices[idx + j];
- while (i < indexInfo.count - 1) {
- ndx[1] = indices[i + 1];
- if (ndx[0] != ndx[1]) {
- idx = ndx[1] * verticesStride;
- for (uint j = 0; j < maxVerticesDataSize; ++j)
- abc[1][j] = vertices[idx + j];
- visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ while (i < indexInfo.count) {
+ if (indexInfo.restartEnabled && indexInfo.restartIndexValue == static_cast<int>(indices[i])) {
+ ++i;
+ continue;
}
+ stripStartIndex = i;
+ ndx[0] = indices[stripStartIndex];
+ uint idx = ndx[0] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j)
+ abc[0][j] = vertices[idx + j];
++i;
- ndx[0] = ndx[1];
- abc[0] = abc[1];
- }
- if (loop) {
- ndx[1] = indices[0];
- if (ndx[0] != ndx[1]) {
- idx = ndx[1] * verticesStride;
- for (uint j = 0; j < maxVerticesDataSize; ++j)
- abc[1][j] = vertices[idx + j];
- visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ while (i < indexInfo.count && (!indexInfo.restartEnabled || indexInfo.restartIndexValue != static_cast<int>(indices[i]))) {
+ ndx[1] = indices[i];
+ if (ndx[0] != ndx[1]) {
+ idx = ndx[1] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j)
+ abc[1][j] = vertices[idx + j];
+ visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ }
+ ++i;
+ ndx[0] = ndx[1];
+ abc[0] = abc[1];
+ }
+ if (loop) {
+ ndx[1] = indices[stripStartIndex];
+ if (ndx[0] != ndx[1]) {
+ idx = ndx[1] * verticesStride;
+ for (uint j = 0; j < maxVerticesDataSize; ++j)
+ abc[1][j] = vertices[idx + j];
+ visitor->visit(ndx[0], abc[0], ndx[1], abc[1]);
+ }
}
}
}
diff --git a/src/render/backend/stringtoint.cpp b/src/render/backend/stringtoint.cpp
index 5659da394..0e0d38c9c 100644
--- a/src/render/backend/stringtoint.cpp
+++ b/src/render/backend/stringtoint.cpp
@@ -50,9 +50,18 @@ namespace Render {
namespace {
-QReadWriteLock lock;
-QHash<QString, int> map = QHash<QString, int>();
-QVector<QString> reverseMap = QVector<QString>();
+struct StringToIntCache
+{
+ QReadWriteLock lock;
+ QHash<QString, int> map = QHash<QString, int>();
+ QVector<QString> reverseMap = QVector<QString>();
+
+ static StringToIntCache& instance()
+ {
+ static StringToIntCache c;
+ return c;
+ }
+};
} // anonymous
@@ -64,20 +73,21 @@ int StringToInt::lookupId(QLatin1String str)
int StringToInt::lookupId(const QString &str)
{
+ auto& cache = StringToIntCache::instance();
int idx;
{
- QReadLocker readLocker(&lock);
- idx = map.value(str, -1);
+ QReadLocker readLocker(&cache.lock);
+ idx = cache.map.value(str, -1);
}
if (Q_UNLIKELY(idx < 0)) {
- QWriteLocker writeLocker(&lock);
- idx = map.value(str, -1);
+ QWriteLocker writeLocker(&cache.lock);
+ idx = cache.map.value(str, -1);
if (idx < 0) {
- idx = reverseMap.size();
- Q_ASSERT(map.size() == reverseMap.size());
- map.insert(str, idx);
- reverseMap.append(str);
+ idx = cache.reverseMap.size();
+ Q_ASSERT(cache.map.size() == cache.reverseMap.size());
+ cache.map.insert(str, idx);
+ cache.reverseMap.append(str);
}
}
return idx;
@@ -85,9 +95,10 @@ int StringToInt::lookupId(const QString &str)
QString StringToInt::lookupString(int idx)
{
- QReadLocker readLocker(&lock);
- if (Q_LIKELY(reverseMap.size() > idx))
- return reverseMap.at(idx);
+ auto& cache = StringToIntCache::instance();
+ QReadLocker readLocker(&cache.lock);
+ if (Q_LIKELY(cache.reverseMap.size() > idx))
+ return cache.reverseMap.at(idx);
return QString();
}
diff --git a/src/render/backend/transform.cpp b/src/render/backend/transform.cpp
index 8e98801b7..9e78bc96f 100644
--- a/src/render/backend/transform.cpp
+++ b/src/render/backend/transform.cpp
@@ -39,7 +39,6 @@
#include "transform_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/private/qtransform_p.h>
diff --git a/src/render/backend/trianglesvisitor.cpp b/src/render/backend/trianglesvisitor.cpp
index 87ba7bde9..a58f2d20b 100644
--- a/src/render/backend/trianglesvisitor.cpp
+++ b/src/render/backend/trianglesvisitor.cpp
@@ -153,6 +153,10 @@ void traverseTriangleStripIndexed(index *indices,
uint ndx[3];
Vector3D abc[3];
while (i < indexInfo.count - 2) {
+ if (indexInfo.restartEnabled && indexInfo.restartIndexValue == static_cast<int>(indices[i + 2])) {
+ i += 3;
+ continue;
+ }
bool degenerate = false;
for (uint u = 0; u < 3; ++u) {
ndx[u] = indices[i + u];
@@ -216,6 +220,11 @@ void traverseTriangleFanIndexed(index *indices,
ndx[0] = indices[0];
uint i = 1;
while (i < indexInfo.count - 1) {
+ if (indexInfo.restartEnabled && indexInfo.restartIndexValue == static_cast<int>(indices[i + 1])) {
+ ndx[0] = indices[i + 2];
+ i += 3;
+ continue;
+ }
for (uint u = 0; u < 2; ++u) {
ndx[u + 1] = indices[i + u];
uint idx = ndx[u + 1] * verticesStride;
@@ -224,7 +233,7 @@ void traverseTriangleFanIndexed(index *indices,
}
}
visitor->visit(ndx[2], abc[2], ndx[1], abc[1], ndx[0], abc[0]);
- i += 1;
+ ++i;
}
}
diff --git a/src/render/backend/uniform_p.h b/src/render/backend/uniform_p.h
index 09575a077..c8731637c 100644
--- a/src/render/backend/uniform_p.h
+++ b/src/render/backend/uniform_p.h
@@ -227,9 +227,9 @@ public:
return !(*this == other);
}
private:
- // Allocate 4 floats on stack
+ // Allocate 16 floats on stack
// For larger elements, heap allocation will be used
- QVarLengthArray<float, 4> m_data;
+ QVarLengthArray<float, 16> m_data;
ValueType m_valueType = ScalarValue;
diff --git a/src/render/backend/visitorutils_p.h b/src/render/backend/visitorutils_p.h
index 6a5c7b4ff..14183e11b 100644
--- a/src/render/backend/visitorutils_p.h
+++ b/src/render/backend/visitorutils_p.h
@@ -149,6 +149,8 @@ void visitPrimitives(NodeManagers *manager, const GeometryRenderer *renderer, Vi
indexBufferInfo.byteOffset = indexAttribute->byteOffset();
indexBufferInfo.byteStride = indexAttribute->byteStride();
indexBufferInfo.count = indexAttribute->count();
+ indexBufferInfo.restartEnabled = renderer->primitiveRestartEnabled();
+ indexBufferInfo.restartIndexValue = renderer->restartIndexValue();
IndexExecutor executor;
executor.m_vertexBufferInfo = vertexBufferInfo;
diff --git a/src/render/framegraph/qblitframebuffer.cpp b/src/render/framegraph/qblitframebuffer.cpp
index 3a26e3d56..252758af4 100644
--- a/src/render/framegraph/qblitframebuffer.cpp
+++ b/src/render/framegraph/qblitframebuffer.cpp
@@ -70,6 +70,10 @@ namespace Qt3DRender {
Specifies the interpolation applied if the image is stretched.
+ \value Nearest
+ Nearest-neighbor interpolation.
+ \value Linear
+ Linear interpolation.
*/
/*!
\property Qt3DRender::QBlitFramebuffer::destination
diff --git a/src/render/framegraph/qbuffercapture.cpp b/src/render/framegraph/qbuffercapture.cpp
index 0c12a3aff..3eaa5dfd2 100644
--- a/src/render/framegraph/qbuffercapture.cpp
+++ b/src/render/framegraph/qbuffercapture.cpp
@@ -39,8 +39,8 @@
#include <Qt3DRender/qbuffercapture.h>
#include <Qt3DRender/private/qbuffercapture_p.h>
-#include <Qt3DCore/QSceneChange>
-#include <Qt3DRender/QFrameGraphNodeCreatedChange>
+#include <Qt3DCore/qscenechange.h>
+#include <Qt3DRender/qframegraphnodecreatedchange.h>
QT_BEGIN_NAMESPACE
@@ -62,6 +62,14 @@ QBufferCapturePrivate::QBufferCapturePrivate()
\inmodule Qt3DRender
\brief Exchanges buffer data between GPU and CPU.
*/
+
+/*!
+ \qmltype BufferCapture
+ \inqmlmodule Qt3D.Render
+ \instantiates Qt3DRender::QBufferCapture
+ \brief Exchanges buffer data between GPU and CPU.
+*/
+
QBufferCapture::QBufferCapture(Qt3DCore::QNode *parent)
: QFrameGraphNode(*new QBufferCapturePrivate, parent)
{
diff --git a/src/render/framegraph/qrendercapture.cpp b/src/render/framegraph/qrendercapture.cpp
index cc74553b2..a10083374 100644
--- a/src/render/framegraph/qrendercapture.cpp
+++ b/src/render/framegraph/qrendercapture.cpp
@@ -36,8 +36,8 @@
#include <Qt3DRender/qrendercapture.h>
#include <Qt3DRender/private/qrendercapture_p.h>
-#include <Qt3DCore/QSceneChange>
-#include <Qt3DCore/QPropertyUpdatedChange>
+#include <Qt3DCore/qscenechange.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
#include <QPointer>
diff --git a/src/render/framegraph/qsetfence.cpp b/src/render/framegraph/qsetfence.cpp
index 5cb82f3db..262dbd4ad 100644
--- a/src/render/framegraph/qsetfence.cpp
+++ b/src/render/framegraph/qsetfence.cpp
@@ -54,7 +54,8 @@ QSetFencePrivate::QSetFencePrivate()
}
/*!
- \class QSetFence
+ \class Qt3DRender::QSetFence
+ \inmodule Qt3DRender
\brief FrameGraphNode used to insert a fence in the graphics command stream.
Fence allow to synchronosize GPU and CPU workloads. GPU commands usually
@@ -100,7 +101,7 @@ QSetFence::QSetFence(QSetFencePrivate &dd, Qt3DCore::QNode *parent)
are supported.
*/
/*!
- \property QSetFence::handleType
+ \property Qt3DRender::QSetFence::handleType
Specifies the type of handle being used. Currently only OpenGL Fence ids
are supported.
@@ -123,12 +124,12 @@ void QSetFencePrivate::setHandleType(QSetFence::HandleType type)
}
/*!
- \qmlproperty variant AbstractFence::handle
+ \qmlproperty variant SetFence::handle
Holds the underlying fence handle wrapped in a variant.
*/
/*!
- \property QAbstractFence::handle
+ \property Qt3DRender::QSetFence::handle
Holds the underlying fence handle wrapped in a QVariant.
*/
diff --git a/src/render/framegraph/qwaitfence.cpp b/src/render/framegraph/qwaitfence.cpp
index 5195653ce..737f4e54d 100644
--- a/src/render/framegraph/qwaitfence.cpp
+++ b/src/render/framegraph/qwaitfence.cpp
@@ -56,8 +56,8 @@ QWaitFencePrivate::QWaitFencePrivate()
}
/*!
- \class QWaitFence
-
+ \class Qt3DRender::QWaitFence
+ \inmodule Qt3DRender
\brief FrameGraphNode used to wait for a fence in the graphics command
stream to become signaled.
@@ -98,7 +98,7 @@ QWaitFence::~QWaitFence()
become signaled. This is false by default.
*/
/*!
- \property QWaitFence::waitOnCPU
+ \property Qt3DRender::QWaitFence::waitOnCPU
Specifies whether the CPU should be block while waiting for the fence to
become signaled. This is false by default.
@@ -125,7 +125,7 @@ void QWaitFence::setWaitOnCPU(bool waitOnCPU)
to become signaled.
*/
/*!
- \property QWaitFence::timeout
+ \property Qt3DRender::QWaitFence::timeout
Specifies the maximum amount of time in nanoseconds to wait for the fence
to become signaled.
@@ -157,7 +157,7 @@ QWaitFence::QWaitFence(QWaitFencePrivate &dd, Qt3DCore::QNode *parent)
are supported.
*/
/*!
- \property QWaitFence::handleType
+ \property Qt3DRender::QWaitFence::handleType
Specifies the type of handle being used. Currently only OpenGL Fence ids
are supported.
@@ -183,7 +183,7 @@ void QWaitFence::setHandleType(QWaitFence::HandleType type)
Holds the underlying fence handle wrapped in a variant.
*/
/*!
- \property QWaitFence::handle
+ \property Qt3DRender::QWaitFence::handle
Holds the underlying fence handle wrapped in a QVariant.
*/
diff --git a/src/render/framegraph/rendercapture.cpp b/src/render/framegraph/rendercapture.cpp
index 68d62b6a5..73d8770a7 100644
--- a/src/render/framegraph/rendercapture.cpp
+++ b/src/render/framegraph/rendercapture.cpp
@@ -37,6 +37,8 @@
#include <Qt3DRender/private/qrendercapture_p.h>
#include <Qt3DRender/private/rendercapture_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qaspectjobmanager_p.h>
QT_BEGIN_NAMESPACE
@@ -99,17 +101,25 @@ void RenderCapture::addRenderCapture(int captureId, const QImage &image)
m_renderCaptureData.push_back(data);
}
-// called by send render capture job thread
-void RenderCapture::sendRenderCaptures()
+// called to send render capture in main thread
+void RenderCapture::syncRenderCapturesToFrontend(Qt3DCore::QAspectManager *manager)
{
- QMutexLocker lock(&m_mutex);
+ auto *frontend = manager->lookupNode(peerId());
+ if (!frontend)
+ return;
+ QRenderCapturePrivate *dfrontend = static_cast<QRenderCapturePrivate *>(Qt3DCore::QNodePrivate::get(frontend));
+ QMutexLocker lock(&m_mutex);
for (const RenderCaptureDataPtr &data : qAsConst(m_renderCaptureData)) {
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("renderCaptureData");
- e->setValue(QVariant::fromValue(data));
- notifyObservers(e);
+ QPointer<QRenderCaptureReply> reply = dfrontend->takeReply(data.data()->captureId);
+ if (reply) {
+ dfrontend->setImage(reply, data.data()->image);
+ emit reply->completed();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+ emit reply->completeChanged(true);
+QT_WARNING_POP
+ }
}
m_renderCaptureData.clear();
}
diff --git a/src/render/framegraph/rendercapture_p.h b/src/render/framegraph/rendercapture_p.h
index 4560c525d..5714fb44d 100644
--- a/src/render/framegraph/rendercapture_p.h
+++ b/src/render/framegraph/rendercapture_p.h
@@ -66,9 +66,9 @@ public:
bool wasCaptureRequested() const;
QRenderCaptureRequest takeCaptureRequest();
void addRenderCapture(int captureId, const QImage &image);
- void sendRenderCaptures();
void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+ void syncRenderCapturesToFrontend(Qt3DCore::QAspectManager *manager);
private:
diff --git a/src/render/framegraph/subtreeenabler.cpp b/src/render/framegraph/subtreeenabler.cpp
index 160e1a5b5..4d912dc1d 100644
--- a/src/render/framegraph/subtreeenabler.cpp
+++ b/src/render/framegraph/subtreeenabler.cpp
@@ -52,30 +52,12 @@ SubtreeEnabler::SubtreeEnabler()
{
}
-void SubtreeEnabler::sendDisableToFrontend()
-{
- if (m_enablement != QSubtreeEnabler::SingleShot)
- return;
-
- if (isEnabled())
- return;
-
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("enabled");
- e->setValue(false);
- notifyObservers(e);
-}
-
void SubtreeEnabler::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
const QSubtreeEnabler *node = qobject_cast<const QSubtreeEnabler *>(frontEnd);
if (!node)
return;
- if (node->isEnabled() != isEnabled())
- markDirty(AbstractRenderer::AllDirty);
-
FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
const auto enablement = node->enablement();
diff --git a/src/render/frontend/qcamera.cpp b/src/render/frontend/qcamera.cpp
index 2dcec7ed6..b0fd16182 100644
--- a/src/render/frontend/qcamera.cpp
+++ b/src/render/frontend/qcamera.cpp
@@ -235,7 +235,7 @@ void QCameraPrivate::updateViewMatrixAndTransform(bool doEmit)
* \qmlmethod void Qt3D.Render::Camera::viewEntity(Entity entity)
*
* Rotates and moves the camera so that it's viewCenter is the center of the entity's bounding volume
- * and the entire entity fits in the view port.
+ * and the entire \a entity fits in the view port.
*
* \note Only works if the lens is in perspective projection mode.
* \sa Qt3D.Render::Camera::projectionType
diff --git a/src/render/frontend/qcameralens.cpp b/src/render/frontend/qcameralens.cpp
index cf30b714a..1d8059f45 100644
--- a/src/render/frontend/qcameralens.cpp
+++ b/src/render/frontend/qcameralens.cpp
@@ -233,11 +233,7 @@ void QCameraLens::viewAll(Qt3DCore::QNodeId cameraId)
{
Q_D(QCameraLens);
if (d->m_projectionType == PerspectiveProjection) {
- QVariant v;
- v.setValue(cameraId);
- d->m_pendingViewAllCommand = {QLatin1String("QueryRootBoundingVolume"),
- v,
- id()};
+ d->m_pendingViewAllRequest = {Qt3DCore::QNodeId::createId(), cameraId, {}};
d->update();
}
}
@@ -246,30 +242,19 @@ void QCameraLens::viewEntity(Qt3DCore::QNodeId entityId, Qt3DCore::QNodeId camer
{
Q_D(QCameraLens);
if (d->m_projectionType == PerspectiveProjection) {
- QVector<Qt3DCore::QNodeId> ids = {entityId, cameraId};
- QVariant v;
- v.setValue(ids);
- d->m_pendingViewAllCommand = {QLatin1String("QueryEntityBoundingVolume"),
- v,
- id()};
+ d->m_pendingViewAllRequest = {Qt3DCore::QNodeId::createId(), cameraId, entityId};
d->update();
}
}
-void QCameraLensPrivate::processViewAllCommand(Qt3DCore::QNodeCommand::CommandId commandId,
- const QVariant &data)
+void QCameraLensPrivate::processViewAllResult(Qt3DCore::QNodeId requestId, const QVector3D &center, float radius)
{
Q_Q(QCameraLens);
- if (!m_pendingViewAllCommand || m_pendingViewAllCommand.commandId != commandId)
+ if (!m_pendingViewAllRequest || m_pendingViewAllRequest.requestId != requestId)
return;
- QVector<float> boundingVolumeData = data.value< QVector<float> >();
- if (boundingVolumeData.size() != 4)
- return;
- QVector3D center(boundingVolumeData[0], boundingVolumeData[1], boundingVolumeData[2]);
- float radius = boundingVolumeData[3];
Q_EMIT q->viewSphere(center, radius);
- m_pendingViewAllCommand = {};
+ m_pendingViewAllRequest = {};
}
/*!
@@ -643,18 +628,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QCameraLens::createNodeCreationChange() cons
void QCameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
{
- Q_D(QCameraLens);
- switch (change->type()) {
- case Qt3DCore::CommandRequested: {
- Qt3DCore::QNodeCommandPtr command = qSharedPointerCast<Qt3DCore::QNodeCommand>(change);
-
- if (command->name() == QLatin1String("ViewAll"))
- d->processViewAllCommand(command->inReplyTo(), command->data());
- }
- break;
- default:
- break;
- }
+ Q_UNUSED(change)
}
} // Qt3DRender
diff --git a/src/render/frontend/qcameralens_p.h b/src/render/frontend/qcameralens_p.h
index 5c5a6a42a..eca01b890 100644
--- a/src/render/frontend/qcameralens_p.h
+++ b/src/render/frontend/qcameralens_p.h
@@ -53,7 +53,6 @@
#include <Qt3DRender/private/qt3drender_global_p.h>
#include <Qt3DCore/private/qcomponent_p.h>
-#include <Qt3DCore/private/qnodecommand_p.h>
#include "qcameralens.h"
@@ -63,21 +62,21 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-struct CameraLensCommand
+struct CameraLensRequest
{
- QString name;
- QVariant data;
- Qt3DCore::QNodeCommand::CommandId commandId;
+ Qt3DCore::QNodeId requestId;
+ Qt3DCore::QNodeId cameraId;
+ Qt3DCore::QNodeId entityId;
- inline operator bool() const { return !name.isEmpty(); }
+ inline operator bool() const { return !requestId.isNull(); }
};
-inline bool operator ==(const CameraLensCommand &a, const CameraLensCommand &b) noexcept
+inline bool operator ==(const CameraLensRequest &a, const CameraLensRequest &b) noexcept
{
- return a.name == b.name && a.data == b.data && a.commandId == b.commandId;
+ return a.cameraId == b.cameraId && a.entityId == b.entityId && a.requestId == b.requestId;
}
-inline bool operator !=(const CameraLensCommand &a, const CameraLensCommand &b) noexcept
+inline bool operator !=(const CameraLensRequest &a, const CameraLensRequest &b) noexcept
{
return !(a == b);
}
@@ -123,8 +122,8 @@ public:
float m_exposure;
- CameraLensCommand m_pendingViewAllCommand;
- void processViewAllCommand(Qt3DCore::QNodeCommand::CommandId commandId, const QVariant &data);
+ CameraLensRequest m_pendingViewAllRequest;
+ void processViewAllResult(Qt3DCore::QNodeId requestId, const QVector3D &center, float radius);
private:
inline void updatePerpectiveProjection()
diff --git a/src/render/frontend/qcomputecommand.cpp b/src/render/frontend/qcomputecommand.cpp
index d0c9f5805..dfd9c2033 100644
--- a/src/render/frontend/qcomputecommand.cpp
+++ b/src/render/frontend/qcomputecommand.cpp
@@ -92,15 +92,15 @@ namespace Qt3DRender {
*/
/*!
- \qmlproperty QComputeCommand::runType
+ \qmlproperty enumeration ComputeCommand::runType
Specifies whether the compute command should be performed every frame or
manually triggered.
- \value Continuous Compute command is executed everyframe. This is the
+ \value ComputeCommand.Continuous Compute command is executed everyframe. This is the
default.
- \value Manual CompouteCommand is executed for a given number of frames and
+ \value ComputeCommand.Manual CompouteCommand is executed for a given number of frames and
then the component disables itself.
*/
diff --git a/src/render/frontend/qlevelofdetail.cpp b/src/render/frontend/qlevelofdetail.cpp
index 3d0cb9553..ced0604c7 100644
--- a/src/render/frontend/qlevelofdetail.cpp
+++ b/src/render/frontend/qlevelofdetail.cpp
@@ -325,6 +325,11 @@ Qt3DCore::QNodeCreatedChangeBasePtr QLevelOfDetail::createNodeCreationChange() c
return creationChange;
}
+// TODO Unused remove in Qt6
+void QLevelOfDetail::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
QCamera *QLevelOfDetail::camera() const
{
Q_D(const QLevelOfDetail);
diff --git a/src/render/frontend/qlevelofdetail.h b/src/render/frontend/qlevelofdetail.h
index f6c09a287..81fcf3235 100644
--- a/src/render/frontend/qlevelofdetail.h
+++ b/src/render/frontend/qlevelofdetail.h
@@ -97,6 +97,8 @@ Q_SIGNALS:
protected:
explicit QLevelOfDetail(QLevelOfDetailPrivate &dd, Qt3DCore::QNode *parent = nullptr);
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QLevelOfDetail)
diff --git a/src/render/frontend/qlevelofdetailswitch.cpp b/src/render/frontend/qlevelofdetailswitch.cpp
index 7b888fe98..c07d4c4b1 100644
--- a/src/render/frontend/qlevelofdetailswitch.cpp
+++ b/src/render/frontend/qlevelofdetailswitch.cpp
@@ -42,7 +42,6 @@
#include "qlevelofdetail_p.h"
#include "qglobal.h"
#include <Qt3DCore/QEntity>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -134,6 +133,11 @@ QLevelOfDetailSwitch::QLevelOfDetailSwitch(QLevelOfDetailPrivate &dd, QNode *par
{
}
+// TODO Unused remove in Qt6
+void QLevelOfDetailSwitch::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/frontend/qlevelofdetailswitch.h b/src/render/frontend/qlevelofdetailswitch.h
index 90f4ee3e2..325b885ed 100644
--- a/src/render/frontend/qlevelofdetailswitch.h
+++ b/src/render/frontend/qlevelofdetailswitch.h
@@ -57,6 +57,8 @@ public:
protected:
explicit QLevelOfDetailSwitch(QLevelOfDetailPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QLevelOfDetailSwitch)
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index 271eb9c11..7a51fa0e7 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -170,10 +170,8 @@
#include <Qt3DCore/QAspectEngine>
#include <Qt3DCore/private/qservicelocator_p.h>
-#include <QDebug>
-#include <QOffscreenSurface>
#include <QThread>
-#include <QWindow>
+#include <QOpenGLContext>
QT_BEGIN_NAMESPACE
@@ -202,11 +200,16 @@ QRenderAspectPrivate::QRenderAspectPrivate(QRenderAspect::RenderType type)
, m_nodeManagers(nullptr)
, m_renderer(nullptr)
, m_initialized(false)
+ , m_renderAfterJobs(false)
, m_renderType(type)
, m_offscreenHelper(nullptr)
{
m_instances.append(this);
loadSceneParsers();
+ if (m_renderType == QRenderAspect::Threaded && !QOpenGLContext::supportsThreadedOpenGL()) {
+ m_renderType = QRenderAspect::Synchronous;
+ m_renderAfterJobs = true;
+ }
}
/*! \internal */
@@ -239,6 +242,13 @@ void QRenderAspectPrivate::syncDirtyFrontEndNode(QNode *node, QBackendNode *back
renderBackend->syncFromFrontEnd(node, firstTime);
}
+void QRenderAspectPrivate::jobsDone(QAspectManager *manager)
+{
+ m_renderer->jobsDone(manager);
+ if (m_renderAfterJobs)
+ m_renderer->doRender(true);
+}
+
/*! \internal */
void QRenderAspectPrivate::registerBackendTypes()
{
@@ -546,6 +556,8 @@ QVariant QRenderAspect::executeCommand(const QStringList &args)
void QRenderAspect::onEngineStartup()
{
Q_D(QRenderAspect);
+ if (d->m_renderAfterJobs) // synchronous rendering but using QWindow
+ d->m_renderer->initialize();
Render::NodeManagers *managers = d->m_renderer->nodeManagers();
Render::Entity *rootEntity = managers->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId());
Q_ASSERT(rootEntity);
diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h
index 62e373b11..8723180ab 100644
--- a/src/render/frontend/qrenderaspect_p.h
+++ b/src/render/frontend/qrenderaspect_p.h
@@ -87,6 +87,7 @@ public:
static QRenderAspectPrivate* findPrivate(Qt3DCore::QAspectEngine *engine);
void syncDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QBackendNode *backend, bool firstTime) const override;
+ void jobsDone(Qt3DCore::QAspectManager *manager) override;
void registerBackendTypes();
void unregisterBackendTypes();
@@ -102,6 +103,7 @@ public:
Render::AbstractRenderer *m_renderer;
bool m_initialized;
+ bool m_renderAfterJobs;
QList<QSceneImporter *> m_sceneImporter;
QVector<QString> m_loadedPlugins;
QVector<Render::QRenderPlugin *> m_renderPlugins;
diff --git a/src/render/frontend/qrendersettings.cpp b/src/render/frontend/qrendersettings.cpp
index d106e4205..491d3e442 100644
--- a/src/render/frontend/qrendersettings.cpp
+++ b/src/render/frontend/qrendersettings.cpp
@@ -104,25 +104,25 @@ void QRenderSettingsPrivate::invalidateFrame()
/*! \internal */
void QRenderSettingsPrivate::_q_onPickingMethodChanged(QPickingSettings::PickMethod pickMethod)
{
- notifyPropertyChange("pickMethod", pickMethod);// TODOSYNC
+ notifyPropertyChange("pickMethod", pickMethod);
}
/*! \internal */
void QRenderSettingsPrivate::_q_onPickResultModeChanged(QPickingSettings::PickResultMode pickResultMode)
{
- notifyPropertyChange("pickResultMode", pickResultMode);// TODOSYNC
+ notifyPropertyChange("pickResultMode", pickResultMode);
}
/*! \internal */
void QRenderSettingsPrivate::_q_onFaceOrientationPickingModeChanged(QPickingSettings::FaceOrientationPickingMode faceOrientationPickingMode)
{
- notifyPropertyChange("faceOrientationPickingMode", faceOrientationPickingMode);// TODOSYNC
+ notifyPropertyChange("faceOrientationPickingMode", faceOrientationPickingMode);
}
/*! \internal */
void QRenderSettingsPrivate::_q_onWorldSpaceToleranceChanged(float worldSpaceTolerance)
{
- notifyPropertyChange("pickWorldSpaceTolerance", worldSpaceTolerance);// TODOSYNC
+ notifyPropertyChange("pickWorldSpaceTolerance", worldSpaceTolerance);
}
QRenderSettings::QRenderSettings(Qt3DCore::QNode *parent)
@@ -161,12 +161,6 @@ QPickingSettings *QRenderSettings::pickingSettings()
return &(d->m_pickingSettings);
}
-const QPickingSettings *QRenderSettings::pickingSettings() const
-{
- Q_D(const QRenderSettings);
- return &(d->m_pickingSettings);
-}
-
/*!
\qmlproperty FrameGraphNode RenderSettings::activeFrameGraph
diff --git a/src/render/frontend/qrendersettings.h b/src/render/frontend/qrendersettings.h
index c8771a8fa..9d2baa58b 100644
--- a/src/render/frontend/qrendersettings.h
+++ b/src/render/frontend/qrendersettings.h
@@ -71,7 +71,6 @@ public:
Q_ENUM(RenderPolicy) // LCOV_EXCL_LINE
QPickingSettings* pickingSettings();
- const QPickingSettings* pickingSettings() const;
QFrameGraphNode *activeFrameGraph() const;
RenderPolicy renderPolicy() const;
diff --git a/src/render/frontend/sphere.cpp b/src/render/frontend/sphere.cpp
index 470dbfe59..0caeed9f1 100644
--- a/src/render/frontend/sphere.cpp
+++ b/src/render/frontend/sphere.cpp
@@ -93,54 +93,6 @@ bool intersectRaySphere(const Qt3DRender::RayCasting::QRay3D &ray, const Qt3DRen
return true;
}
-inline QPair<int, int> findExtremePoints(const QVector<Vector3D> &points)
-{
- // Find indices of extreme points along x, y, and z axes
- int xMin = 0, xMax = 0, yMin = 0, yMax = 0, zMin = 0, zMax = 0;
- for (int i = 1; i < points.size(); ++i) {
- const Vector3D &p = points.at(i);
- if (p.x() < points[xMin].x())
- xMin = i;
- if (p.x() > points[xMax].x())
- xMax = i;
- if (p.y() < points[yMin].y())
- yMin = i;
- if (p.y() > points[yMax].y())
- yMax = i;
- if (p.z() < points[zMin].z())
- zMin = i;
- if (p.z() > points[zMax].z())
- zMax = i;
- }
-
- // Calculate squared distance for the pairs of points
- const float xDist2 = (points.at(xMax) - points.at(xMin)).lengthSquared();
- const float yDist2 = (points.at(yMax) - points.at(yMin)).lengthSquared();
- const float zDist2 = (points.at(zMax) - points.at(zMin)).lengthSquared();
-
- // Select most distant pair
- QPair<int, int> extremeIndices(xMin, xMax);
- if (yDist2 > xDist2 && yDist2 > zDist2)
- extremeIndices = qMakePair(yMin, yMax);
- if (zDist2 > xDist2 && zDist2 > yDist2)
- extremeIndices = qMakePair(zMin, zMax);
-
- return extremeIndices;
-}
-
-inline void sphereFromExtremePoints(Qt3DRender::Render::Sphere &s, const QVector<Vector3D> &points)
-{
- // Find two most separated points on any of the basis vectors
- QPair<int, int> extremeIndices = findExtremePoints(points);
-
- // Construct sphere to contain these two points
- const Vector3D &p = points.at(extremeIndices.first);
- const Vector3D &q = points.at(extremeIndices.second);
- const Vector3D c = 0.5f * (p + q);
- s.setCenter(c);
- s.setRadius((q - c).length());
-}
-
inline void constructRitterSphere(Qt3DRender::Render::Sphere &s, const QVector<Vector3D> &points)
{
//def bounding_sphere(points):
diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp
index 0ce81efc1..6db3bab44 100644
--- a/src/render/geometry/buffer.cpp
+++ b/src/render/geometry/buffer.cpp
@@ -88,15 +88,6 @@ void Buffer::executeFunctor()
m_data = (*m_functor)();
// Request data to be loaded
forceDataUpload();
-
- if (m_syncData) {
- // Send data back to the frontend
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("data");
- e->setValue(QVariant::fromValue(m_data));
- notifyObservers(e);
- }
}
//Called from th sendBufferJob
@@ -105,12 +96,6 @@ void Buffer::updateDataFromGPUToCPU(QByteArray data)
// Note: when this is called, data is what's currently in GPU memory
// so m_data shouldn't be reuploaded
m_data = data;
- // Send data back to the frontend
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("downloadedData");
- e->setValue(QVariant::fromValue(m_data));
- notifyObservers(e);
}
void Buffer::forceDataUpload()
@@ -152,20 +137,31 @@ void Buffer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
m_manager->addDirtyBuffer(peerId());
}
{
- QVariant v = node->property("QT3D_updateData");
- if (v.isValid()) {
+ const QVariant v = node->property("QT3D_updateData");
+
+ // Make sure we record data if it's the first time we are called
+ // or if we have no partial updates
+ if (firstTime || !v.isValid()){
+ const QByteArray newData = node->data();
+ const bool dirty = m_data != newData;
+ m_bufferDirty |= dirty;
+ m_data = newData;
+
+ // Since frontend applies partial updates to its m_data
+ // if we enter this code block, there's no problem in actually
+ // ignoring the partial updates
+ if (v.isValid())
+ const_cast<QBuffer *>(node)->setProperty("QT3D_updateData", {});
+
+ if (dirty && !m_data.isEmpty())
+ forceDataUpload();
+ } else if (v.isValid()) {
+ // Apply partial updates and record them to allow partial upload to the GPU
Qt3DRender::QBufferUpdate updateData = v.value<Qt3DRender::QBufferUpdate>();
m_data.replace(updateData.offset, updateData.data.size(), updateData.data);
m_bufferUpdates.push_back(updateData);
m_bufferDirty = true;
const_cast<QBuffer *>(node)->setProperty("QT3D_updateData", {});
- } else {
- QByteArray newData = node->data();
- bool dirty = m_data != newData;
- m_bufferDirty |= dirty;
- m_data = newData;
- if (dirty && !m_data.isEmpty())
- forceDataUpload();
}
}
markDirty(AbstractRenderer::BuffersDirty);
diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp
index 3b460f48c..881c0f66b 100644
--- a/src/render/geometry/geometryrenderer.cpp
+++ b/src/render/geometry/geometryrenderer.cpp
@@ -139,8 +139,16 @@ void GeometryRenderer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
if (functorDirty) {
m_dirty = true;
m_geometryFactory = newFunctor;
- if (m_geometryFactory && m_manager != nullptr)
+ if (m_geometryFactory && m_manager != nullptr) {
m_manager->addDirtyGeometryRenderer(peerId());
+
+ const bool isQMeshFunctor = m_geometryFactory->id() == Qt3DRender::functorTypeId<MeshLoaderFunctor>();
+ if (isQMeshFunctor) {
+ const QMesh *meshNode = static_cast<const QMesh *>(node);
+ QMeshPrivate *dmeshNode = QMeshPrivate::get(const_cast<QMesh *>(meshNode));
+ dmeshNode->setStatus(QMesh::Loading);
+ }
+ }
}
markDirty(AbstractRenderer::GeometryDirty);
diff --git a/src/render/geometry/gltfskeletonloader.cpp b/src/render/geometry/gltfskeletonloader.cpp
index 56144747c..07789cd84 100644
--- a/src/render/geometry/gltfskeletonloader.cpp
+++ b/src/render/geometry/gltfskeletonloader.cpp
@@ -48,6 +48,7 @@
#include <Qt3DRender/private/renderlogging_p.h>
#include <Qt3DCore/private/qmath3d_p.h>
+#include <Qt3DCore/private/qloadgltf_p.h>
QT_BEGIN_NAMESPACE
@@ -316,12 +317,7 @@ GLTFSkeletonLoader::GLTFSkeletonLoader()
bool GLTFSkeletonLoader::load(QIODevice *ioDev)
{
- QByteArray jsonData = ioDev->readAll();
- QJsonDocument sceneDocument = QJsonDocument::fromBinaryData(jsonData);
- if (sceneDocument.isNull())
- sceneDocument = QJsonDocument::fromJson(jsonData);
-
- if (Q_UNLIKELY(!setJSON(sceneDocument))) {
+ if (Q_UNLIKELY(!setJSON(qLoadGLTF(ioDev->readAll())))) {
qCWarning(Jobs, "not a JSON document");
return false;
}
diff --git a/src/render/geometry/qbuffer.cpp b/src/render/geometry/qbuffer.cpp
index d27da25c7..8399bdd7c 100644
--- a/src/render/geometry/qbuffer.cpp
+++ b/src/render/geometry/qbuffer.cpp
@@ -58,6 +58,15 @@ QBufferPrivate::QBufferPrivate()
{
}
+void QBufferPrivate::setData(const QByteArray &data)
+{
+ Q_Q(QBuffer);
+ const bool blocked = q->blockNotifications(true);
+ m_data = data;
+ emit q->dataChanged(data);
+ q->blockNotifications(blocked);
+}
+
/*!
* \qmltype Buffer
* \instantiates Qt3DRender::QBuffer
@@ -301,36 +310,14 @@ QBuffer::~QBuffer()
}
/*!
- * \internal
- */
-void QBuffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- if (change->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(change);
- const QByteArray propertyName = e->propertyName();
- if (propertyName == QByteArrayLiteral("data")) {
- const bool blocked = blockNotifications(true);
- setData(e->value().toByteArray());
- blockNotifications(blocked);
- } else if (propertyName == QByteArrayLiteral("downloadedData")) {
- const bool blocked = blockNotifications(true);
- setData(e->value().toByteArray());
- blockNotifications(blocked);
- Q_EMIT dataAvailable();
- }
- }
-}
-
-/*!
* Sets \a bytes as data.
*/
void QBuffer::setData(const QByteArray &bytes)
{
Q_D(QBuffer);
if (bytes != d->m_data) {
- d->m_data = bytes;
+ d->setData(bytes);
d->update();
- emit dataChanged(bytes);
}
}
@@ -446,6 +433,13 @@ void QBuffer::setAccessType(QBuffer::AccessType access)
}
}
+/*! \internal */
+void QBuffer::sceneChangeEvent(const QSceneChangePtr &change)
+{
+ // TODO Unused remove in Qt6
+ Q_UNUSED(change)
+}
+
bool QBuffer::isSyncData() const
{
Q_D(const QBuffer);
diff --git a/src/render/geometry/qbuffer.h b/src/render/geometry/qbuffer.h
index 1bd1aa8fd..aa6ebca66 100644
--- a/src/render/geometry/qbuffer.h
+++ b/src/render/geometry/qbuffer.h
@@ -118,9 +118,6 @@ public Q_SLOTS:
void setSyncData(bool syncData);
void setAccessType(AccessType access);
-protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
-
Q_SIGNALS:
void dataChanged(const QByteArray &bytes);
void typeChanged(BufferType type);
@@ -129,6 +126,10 @@ Q_SIGNALS:
void accessTypeChanged(AccessType access);
void dataAvailable();
+protected:
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
+
private:
Q_DECLARE_PRIVATE(QBuffer)
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
diff --git a/src/render/geometry/qbuffer_p.h b/src/render/geometry/qbuffer_p.h
index 7a0ffdfb9..6da28e88b 100644
--- a/src/render/geometry/qbuffer_p.h
+++ b/src/render/geometry/qbuffer_p.h
@@ -75,6 +75,8 @@ public:
QBufferDataGeneratorPtr m_functor;
bool m_syncData;
QBuffer::AccessType m_access;
+
+ void setData(const QByteArray &data);
};
struct QBufferData
diff --git a/src/render/geometry/qgeometryrenderer.cpp b/src/render/geometry/qgeometryrenderer.cpp
index 6e0a24f61..64f3e058e 100644
--- a/src/render/geometry/qgeometryrenderer.cpp
+++ b/src/render/geometry/qgeometryrenderer.cpp
@@ -218,6 +218,11 @@ QGeometryRenderer::QGeometryRenderer(QGeometryRendererPrivate &dd, QNode *parent
{
}
+// TODO Unused remove in Qt6
+void QGeometryRenderer::sceneChangeEvent(const QSceneChangePtr &)
+{
+}
+
/*!
\property QGeometryRenderer::instanceCount
diff --git a/src/render/geometry/qgeometryrenderer.h b/src/render/geometry/qgeometryrenderer.h
index eceeb9173..14de40d0b 100644
--- a/src/render/geometry/qgeometryrenderer.h
+++ b/src/render/geometry/qgeometryrenderer.h
@@ -134,6 +134,8 @@ Q_SIGNALS:
protected:
explicit QGeometryRenderer(QGeometryRendererPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QGeometryRenderer)
diff --git a/src/render/geometry/qmesh.cpp b/src/render/geometry/qmesh.cpp
index 1d7d33f9a..1f05a71f6 100644
--- a/src/render/geometry/qmesh.cpp
+++ b/src/render/geometry/qmesh.cpp
@@ -148,17 +148,6 @@ void QMeshPrivate::setStatus(QMesh::Status status)
*/
/*!
- \enum QMesh::Status
-
- This enum identifies the status of shader used.
-
- \value None A source mesh hasn't been assigned a source yet
- \value Loading The mesh geometry is loading
- \value Ready The mesh geometry was successfully loaded
- \value Error An error occurred while loading the mesh
-*/
-
-/*!
\qmlproperty enumeration Mesh::status
Holds the status of the mesh loading.
@@ -197,6 +186,17 @@ void QMeshPrivate::setStatus(QMesh::Status status)
*/
/*!
+ \enum Qt3DRender::QMesh::Status
+
+ This enum identifies the status of shader used.
+
+ \value None A source mesh hasn't been assigned a source yet
+ \value Loading The mesh geometry is loading
+ \value Ready The mesh geometry was successfully loaded
+ \value Error An error occurred while loading the mesh
+*/
+
+/*!
* Constructs a new QMesh with \a parent.
*/
QMesh::QMesh(QNode *parent)
@@ -215,6 +215,11 @@ QMesh::QMesh(QMeshPrivate &dd, QNode *parent)
{
}
+// TODO Unused remove in Qt6
+void QMesh::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
void QMesh::setSource(const QUrl& source)
{
Q_D(QMesh);
diff --git a/src/render/geometry/qmesh.h b/src/render/geometry/qmesh.h
index 04fdedc20..e8ff52b35 100644
--- a/src/render/geometry/qmesh.h
+++ b/src/render/geometry/qmesh.h
@@ -88,6 +88,8 @@ Q_SIGNALS:
protected:
explicit QMesh(QMeshPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QMesh)
diff --git a/src/render/geometry/skeleton.cpp b/src/render/geometry/skeleton.cpp
index 839a1a056..0452c020b 100644
--- a/src/render/geometry/skeleton.cpp
+++ b/src/render/geometry/skeleton.cpp
@@ -60,6 +60,8 @@ namespace Render {
Skeleton::Skeleton()
: BackendNode(Qt3DCore::QBackendNode::ReadWrite)
, m_status(Qt3DCore::QSkeletonLoader::NotReady)
+ , m_createJoints(false)
+ , m_dataType(Unknown)
, m_skeletonManager(nullptr)
, m_jointManager(nullptr)
{
diff --git a/src/render/io/qsceneloader.cpp b/src/render/io/qsceneloader.cpp
index cf1e45355..2d53702f6 100644
--- a/src/render/io/qsceneloader.cpp
+++ b/src/render/io/qsceneloader.cpp
@@ -41,7 +41,6 @@
#include "qsceneloader_p.h"
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
#include <Qt3DRender/qgeometryrenderer.h>
@@ -253,6 +252,11 @@ QSceneLoader::~QSceneLoader()
{
}
+// TODO Unused remove in Qt6
+void QSceneLoader::sceneChangeEvent(const QSceneChangePtr &)
+{
+}
+
/*! \internal */
QSceneLoader::QSceneLoader(QSceneLoaderPrivate &dd, QNode *parent)
: Qt3DCore::QComponent(dd, parent)
@@ -313,7 +317,7 @@ QStringList QSceneLoader::entityNames() const
/*!
\qmlmethod Entity SceneLoader::component(string entityName, enumeration componentType)
- Returns a component matching \a componentType of a loaded entity with an \a objectName matching
+ Returns a component matching \a componentType of a loaded entity with an \e objectName matching
the \a entityName.
If the entity has multiple matching components, the first match in the component list of
the entity is returned.
diff --git a/src/render/io/qsceneloader.h b/src/render/io/qsceneloader.h
index 6842a6926..51ba42de7 100644
--- a/src/render/io/qsceneloader.h
+++ b/src/render/io/qsceneloader.h
@@ -60,6 +60,8 @@ public:
explicit QSceneLoader(Qt3DCore::QNode *parent = nullptr);
~QSceneLoader();
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
enum Status {
None = 0,
Loading,
diff --git a/src/render/io/scene.cpp b/src/render/io/scene.cpp
index 089091701..1a2000bbb 100644
--- a/src/render/io/scene.cpp
+++ b/src/render/io/scene.cpp
@@ -39,7 +39,6 @@
#include "scene_p.h"
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qdownloadhelperservice_p.h>
@@ -80,6 +79,9 @@ void Scene::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
m_sceneManager->addSceneData(m_source, peerId());
else
m_sceneManager->startSceneDownload(m_source, peerId());
+
+ const auto d = static_cast<const QSceneLoaderPrivate *>(Qt3DCore::QNodePrivate::get(node));
+ const_cast<QSceneLoaderPrivate *>(d)->setStatus(QSceneLoader::Loading);
}
markDirty(AbstractRenderer::AllDirty);
}
diff --git a/src/render/jobs/abstractpickingjob.cpp b/src/render/jobs/abstractpickingjob.cpp
index 35e658535..092ab7d3b 100644
--- a/src/render/jobs/abstractpickingjob.cpp
+++ b/src/render/jobs/abstractpickingjob.cpp
@@ -63,6 +63,7 @@ AbstractPickingJob::AbstractPickingJob()
, m_node(nullptr)
, m_frameGraphRoot(nullptr)
, m_renderSettings(nullptr)
+ , m_oneEnabledAtLeast(false)
{
}
@@ -72,6 +73,7 @@ AbstractPickingJob::AbstractPickingJob(Qt3DCore::QAspectJobPrivate &dd)
, m_node(nullptr)
, m_frameGraphRoot(nullptr)
, m_renderSettings(nullptr)
+ , m_oneEnabledAtLeast(false)
{
}
diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp
index 9af2f4f38..172c4ddca 100644
--- a/src/render/jobs/calcboundingvolumejob.cpp
+++ b/src/render/jobs/calcboundingvolumejob.cpp
@@ -354,7 +354,7 @@ CalculateBoundingVolumeJob::CalculateBoundingVolumeJob()
: m_manager(nullptr)
, m_node(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::CalcBoundingVolume, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::CalcBoundingVolume, 0)
}
void CalculateBoundingVolumeJob::run()
diff --git a/src/render/jobs/calcgeometrytrianglevolumes.cpp b/src/render/jobs/calcgeometrytrianglevolumes.cpp
index d2b12e09c..eb31a25a6 100644
--- a/src/render/jobs/calcgeometrytrianglevolumes.cpp
+++ b/src/render/jobs/calcgeometrytrianglevolumes.cpp
@@ -53,7 +53,7 @@ CalcGeometryTriangleVolumes::CalcGeometryTriangleVolumes(const Qt3DCore::QNodeId
, m_geometryRendererId(geometryRendererId)
, m_manager(manager)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::CalcTriangleVolume, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::CalcTriangleVolume, 0)
}
void CalcGeometryTriangleVolumes::run()
diff --git a/src/render/jobs/computefilteredboundingvolumejob.cpp b/src/render/jobs/computefilteredboundingvolumejob.cpp
index 02852685c..0cdbc8b6d 100644
--- a/src/render/jobs/computefilteredboundingvolumejob.cpp
+++ b/src/render/jobs/computefilteredboundingvolumejob.cpp
@@ -74,12 +74,25 @@ void expandWorldBoundingVolume(NodeManagers *manager,
} // namespace
+class ComputeFilteredBoundingVolumeJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ ComputeFilteredBoundingVolumeJobPrivate(ComputeFilteredBoundingVolumeJob *job) : Qt3DCore::QAspectJobPrivate(), m_job(job) {}
+ ~ComputeFilteredBoundingVolumeJobPrivate() {}
+
+ void postFrame(Qt3DCore::QAspectManager *aspectManager) override;
+
+ ComputeFilteredBoundingVolumeJob *m_job;
+ Qt3DRender::Render::Sphere m_sphere;
+};
+
ComputeFilteredBoundingVolumeJob::ComputeFilteredBoundingVolumeJob()
- : m_root(nullptr)
+ : Qt3DCore::QAspectJob(*new ComputeFilteredBoundingVolumeJobPrivate(this))
+ , m_root(nullptr)
, m_ignoreSubTree(nullptr)
, m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::ExpandBoundingVolume, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::ExpandBoundingVolume, 0)
}
void ComputeFilteredBoundingVolumeJob::setRoot(Entity *root)
@@ -100,11 +113,13 @@ void ComputeFilteredBoundingVolumeJob::ignoreSubTree(Entity *node)
void ComputeFilteredBoundingVolumeJob::run()
{
qCDebug(Jobs) << "Entering" << Q_FUNC_INFO << QThread::currentThread();
+ Q_D(ComputeFilteredBoundingVolumeJob);
+ d->m_sphere = {};
if (!m_root)
return;
if (!m_ignoreSubTree) {
- finished(*m_root->worldBoundingVolumeWithChildren());
+ d->m_sphere = *m_root->worldBoundingVolumeWithChildren();
return;
}
@@ -118,20 +133,24 @@ void ComputeFilteredBoundingVolumeJob::run()
parent = parent->parent();
}
if (!isFilterChildOfRoot) {
- finished(*m_root->worldBoundingVolumeWithChildren());
+ d->m_sphere = *m_root->worldBoundingVolumeWithChildren();
return;
}
- Qt3DRender::Render::Sphere sphere;
- expandWorldBoundingVolume(m_manager, &sphere, m_root, m_ignoreSubTree);
- finished(sphere);
+ expandWorldBoundingVolume(m_manager, &d->m_sphere, m_root, m_ignoreSubTree);
qCDebug(Jobs) << "Exiting" << Q_FUNC_INFO << QThread::currentThread();
}
-void ComputeFilteredBoundingVolumeJob::finished(const Qt3DRender::Render::Sphere &sphere)
+void ComputeFilteredBoundingVolumeJob::finished(Qt3DCore::QAspectManager *aspectManager, const Qt3DRender::Render::Sphere &sphere)
+{
+ Q_UNUSED(aspectManager)
+ Q_UNUSED(sphere)
+}
+
+void ComputeFilteredBoundingVolumeJobPrivate::postFrame(Qt3DCore::QAspectManager *aspectManager)
{
- Q_UNUSED(sphere);
+ m_job->finished(aspectManager, m_sphere);
}
} // namespace Render
diff --git a/src/render/jobs/computefilteredboundingvolumejob_p.h b/src/render/jobs/computefilteredboundingvolumejob_p.h
index d2aca575c..0f804e647 100644
--- a/src/render/jobs/computefilteredboundingvolumejob_p.h
+++ b/src/render/jobs/computefilteredboundingvolumejob_p.h
@@ -64,6 +64,7 @@ namespace Render {
class Entity;
class NodeManagers;
class Sphere;
+class ComputeFilteredBoundingVolumeJobPrivate;
class Q_3DRENDERSHARED_PRIVATE_EXPORT ComputeFilteredBoundingVolumeJob : public Qt3DCore::QAspectJob
{
@@ -76,9 +77,10 @@ public:
void run() override;
protected:
- virtual void finished(const Qt3DRender::Render::Sphere &sphere);
+ virtual void finished(Qt3DCore::QAspectManager *aspectManager, const Qt3DRender::Render::Sphere &sphere); // called in main thread
private:
+ Q_DECLARE_PRIVATE(ComputeFilteredBoundingVolumeJob)
Entity *m_root;
Entity *m_ignoreSubTree;
NodeManagers *m_manager;
diff --git a/src/render/jobs/expandboundingvolumejob.cpp b/src/render/jobs/expandboundingvolumejob.cpp
index d63934b54..8587634cb 100644
--- a/src/render/jobs/expandboundingvolumejob.cpp
+++ b/src/render/jobs/expandboundingvolumejob.cpp
@@ -62,7 +62,7 @@ void expandWorldBoundingVolume(NodeManagers *manager, Entity *node)
const auto childrenHandles = node->childrenHandles();
for (const HEntity &handle : childrenHandles) {
Entity *c = manager->renderNodesManager()->data(handle);
- if (c)
+ if (c && c->isEnabled())
expandWorldBoundingVolume(manager, c);
}
@@ -72,7 +72,7 @@ void expandWorldBoundingVolume(NodeManagers *manager, Entity *node)
Qt3DRender::Render::Sphere *parentBoundingVolume = node->worldBoundingVolumeWithChildren();
for (const HEntity &handle : childrenHandles) {
Entity *c = manager->renderNodesManager()->data(handle);
- if (c)
+ if (c && c->isEnabled())
parentBoundingVolume->expandToContain(*c->worldBoundingVolumeWithChildren());
}
}
@@ -84,7 +84,7 @@ ExpandBoundingVolumeJob::ExpandBoundingVolumeJob()
: m_node(nullptr)
, m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::ExpandBoundingVolume, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::ExpandBoundingVolume, 0)
}
void ExpandBoundingVolumeJob::setRoot(Entity *root)
diff --git a/src/render/jobs/filterentitybycomponentjob_p.h b/src/render/jobs/filterentitybycomponentjob_p.h
index dd64e50a7..cefcdd296 100644
--- a/src/render/jobs/filterentitybycomponentjob_p.h
+++ b/src/render/jobs/filterentitybycomponentjob_p.h
@@ -74,7 +74,7 @@ public:
: Qt3DCore::QAspectJob()
, m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::EntityComponentTypeFiltering, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::EntityComponentTypeFiltering, 0)
}
inline void setManager(EntityManager *manager) Q_DECL_NOTHROW { m_manager = manager; }
@@ -97,10 +97,6 @@ private:
QVector<Entity *> m_filteredEntities;
};
-template<typename T, typename ... Ts>
-using FilterEntityByComponentJobPtr = QSharedPointer<FilterEntityByComponentJob<T, Ts...>>;
-
-
} // Render
} // Qt3DRender
diff --git a/src/render/jobs/filterlayerentityjob.cpp b/src/render/jobs/filterlayerentityjob.cpp
index e206ef968..032004422 100644
--- a/src/render/jobs/filterlayerentityjob.cpp
+++ b/src/render/jobs/filterlayerentityjob.cpp
@@ -58,7 +58,7 @@ FilterLayerEntityJob::FilterLayerEntityJob()
: Qt3DCore::QAspectJob()
, m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LayerFiltering, layerFilterJobCounter++);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LayerFiltering, layerFilterJobCounter++)
}
diff --git a/src/render/jobs/filterproximitydistancejob.cpp b/src/render/jobs/filterproximitydistancejob.cpp
index a25e88508..02b712fc2 100644
--- a/src/render/jobs/filterproximitydistancejob.cpp
+++ b/src/render/jobs/filterproximitydistancejob.cpp
@@ -43,8 +43,10 @@ namespace Render {
FilterProximityDistanceJob::FilterProximityDistanceJob()
: m_manager(nullptr)
+ , m_targetEntity(nullptr)
+ , m_distanceThresholdSquared(0.)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::ProximityFiltering, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::ProximityFiltering, 0)
}
void FilterProximityDistanceJob::run()
@@ -55,9 +57,9 @@ void FilterProximityDistanceJob::run()
// Fill m_filteredEntities
// If no filtering needs to be done, this will be the output value
// otherwise it will be used as the base list of entities to filter
- selectAllEntities();
if (hasProximityFilter()) {
+ selectAllEntities();
QVector<Entity *> entitiesToFilter = std::move(m_filteredEntities);
FrameGraphManager *frameGraphManager = m_manager->frameGraphManager();
EntityManager *entityManager = m_manager->renderNodesManager();
diff --git a/src/render/jobs/framecleanupjob.cpp b/src/render/jobs/framecleanupjob.cpp
index 17ca60bff..fb63f005b 100644
--- a/src/render/jobs/framecleanupjob.cpp
+++ b/src/render/jobs/framecleanupjob.cpp
@@ -55,7 +55,7 @@ FrameCleanupJob::FrameCleanupJob()
: m_managers(nullptr)
, m_root(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::FrameCleanup, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::FrameCleanup, 0)
}
FrameCleanupJob::~FrameCleanupJob()
diff --git a/src/render/jobs/frustumcullingjob.cpp b/src/render/jobs/frustumcullingjob.cpp
index 0922fb0cb..e22d625df 100644
--- a/src/render/jobs/frustumcullingjob.cpp
+++ b/src/render/jobs/frustumcullingjob.cpp
@@ -58,7 +58,7 @@ FrustumCullingJob::FrustumCullingJob()
, m_manager(nullptr)
, m_active(false)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::FrustumCulling, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::FrustumCulling, 0)
}
void FrustumCullingJob::run()
diff --git a/src/render/jobs/genericlambdajob_p.h b/src/render/jobs/genericlambdajob_p.h
index 4d93f0f8d..8cf4276f6 100644
--- a/src/render/jobs/genericlambdajob_p.h
+++ b/src/render/jobs/genericlambdajob_p.h
@@ -68,7 +68,7 @@ public:
: Qt3DCore::QAspectJob()
, m_callable(callable)
{
- SET_JOB_RUN_STAT_TYPE(this, type, 0);
+ SET_JOB_RUN_STAT_TYPE(this, type, 0)
}
// QAspectJob interface
@@ -111,7 +111,7 @@ public:
: Qt3DCore::QAspectJob(*new GenericLambdaJobAndPostFramePrivate<T, U>(postFrameCallable))
, m_runCallable(runCallable)
{
- SET_JOB_RUN_STAT_TYPE(this, type, 0);
+ SET_JOB_RUN_STAT_TYPE(this, type, 0)
}
// QAspectJob interface
diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h
index 7aa6f64ba..c3b581277 100644
--- a/src/render/jobs/job_common_p.h
+++ b/src/render/jobs/job_common_p.h
@@ -80,7 +80,7 @@ namespace JobTypes {
LayerFiltering,
EntityComponentTypeFiltering,
MaterialParameterGathering,
- RenderViewBuilder,
+ RenderCommandUpdater,
GenericLambda,
FrustumCulling,
LightGathering,
@@ -92,9 +92,9 @@ namespace JobTypes {
DirtyShaderGathering,
SendRenderCapture,
SendBufferCapture,
- SyncRenderViewCommandBuilding,
+ SyncRenderViewPreCommandUpdate,
SyncRenderViewInitialization,
- SyncRenderViewCommandBuilder,
+ SyncRenderViewPostCommandUpdate,
SyncFrustumCulling,
ClearBufferDrawIndex,
UpdateMeshTriangleList,
@@ -109,7 +109,9 @@ namespace JobTypes {
UpdateLayerEntity,
SendTextureChangesToFrontend,
SendSetFenceHandlesToFrontend,
- SendDisablesToFrontend
+ SendDisablesToFrontend,
+ RenderViewCommandBuilder,
+ SyncRenderViewPreCommandBuilding
};
} // JobTypes
diff --git a/src/render/jobs/jobs.pri b/src/render/jobs/jobs.pri
index 2181e4a95..eb89ab35e 100644
--- a/src/render/jobs/jobs.pri
+++ b/src/render/jobs/jobs.pri
@@ -18,7 +18,6 @@ HEADERS += \
$$PWD/lightgatherer_p.h \
$$PWD/expandboundingvolumejob_p.h \
$$PWD/updateworldboundingvolumejob_p.h \
- $$PWD/sendrendercapturejob_p.h \
$$PWD/updateshaderdatatransformjob_p.h \
$$PWD/updatelevelofdetailjob_p.h \
$$PWD/updatemeshtrianglelistjob_p.h \
@@ -47,7 +46,6 @@ SOURCES += \
$$PWD/lightgatherer.cpp \
$$PWD/expandboundingvolumejob.cpp \
$$PWD/updateworldboundingvolumejob.cpp \
- $$PWD/sendrendercapturejob.cpp \
$$PWD/updateshaderdatatransformjob.cpp \
$$PWD/updatemeshtrianglelistjob.cpp \
$$PWD/updatelevelofdetailjob.cpp \
diff --git a/src/render/jobs/lightgatherer.cpp b/src/render/jobs/lightgatherer.cpp
index b76cd4d73..b79976aef 100644
--- a/src/render/jobs/lightgatherer.cpp
+++ b/src/render/jobs/lightgatherer.cpp
@@ -53,11 +53,14 @@ LightGatherer::LightGatherer()
, m_manager(nullptr)
, m_environmentLight(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LightGathering, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LightGathering, 0)
}
void LightGatherer::run()
{
+ m_lights.clear();
+ m_environmentLight = nullptr;
+
const QVector<HEntity> handles = m_manager->activeHandles();
int envLightCount = 0;
diff --git a/src/render/jobs/loadbufferjob.cpp b/src/render/jobs/loadbufferjob.cpp
index 49f271df5..0f4feb5d4 100644
--- a/src/render/jobs/loadbufferjob.cpp
+++ b/src/render/jobs/loadbufferjob.cpp
@@ -39,9 +39,11 @@
#include "loadbufferjob_p.h"
#include <Qt3DRender/private/buffer_p.h>
+#include <Qt3DRender/private/qbuffer_p.h>
#include <Qt3DRender/private/buffermanager_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/job_common_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
QT_BEGIN_NAMESPACE
@@ -49,13 +51,24 @@ namespace Qt3DRender {
namespace Render {
+class LoadBufferJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ LoadBufferJobPrivate() {}
+ ~LoadBufferJobPrivate() {}
+
+ void postFrame(Qt3DCore::QAspectManager *aspectManager) override;
+
+ Buffer *m_bufferToUpdate = nullptr;
+};
+
LoadBufferJob::LoadBufferJob(const HBuffer &handle)
- : QAspectJob()
+ : QAspectJob(*new LoadBufferJobPrivate)
, m_handle(handle)
, m_nodeManagers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadBuffer, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadBuffer, 0)
}
LoadBufferJob::~LoadBufferJob()
@@ -64,10 +77,25 @@ LoadBufferJob::~LoadBufferJob()
void LoadBufferJob::run()
{
+ Q_D(LoadBufferJob);
// Let's leave it for the moment until this has been properly tested
qCDebug(Jobs) << Q_FUNC_INFO;
Buffer *buffer = m_nodeManagers->data<Buffer, BufferManager>(m_handle);
buffer->executeFunctor();
+ if (buffer->isSyncData())
+ d->m_bufferToUpdate = buffer;
+}
+
+void LoadBufferJobPrivate::postFrame(Qt3DCore::QAspectManager *aspectManager)
+{
+ if (m_bufferToUpdate == nullptr)
+ return;
+ QBuffer *frontendBuffer = static_cast<decltype(frontendBuffer)>(aspectManager->lookupNode(m_bufferToUpdate->peerId()));
+ QBufferPrivate *dFrontend = static_cast<decltype(dFrontend)>(Qt3DCore::QNodePrivate::get(frontendBuffer));
+ // Calling frontendBuffer->setData would result in forcing a sync against the backend
+ // which isn't necessary
+ dFrontend->setData(m_bufferToUpdate->data());
+ m_bufferToUpdate = nullptr;
}
} // namespace Render
diff --git a/src/render/jobs/loadbufferjob_p.h b/src/render/jobs/loadbufferjob_p.h
index 6a221c7e0..e86e4f835 100644
--- a/src/render/jobs/loadbufferjob_p.h
+++ b/src/render/jobs/loadbufferjob_p.h
@@ -63,6 +63,7 @@ namespace Qt3DRender {
namespace Render {
class NodeManagers;
+class LoadBufferJobPrivate;
class Q_AUTOTEST_EXPORT LoadBufferJob : public Qt3DCore::QAspectJob
{
@@ -76,6 +77,9 @@ public:
protected:
HBuffer m_handle;
NodeManagers *m_nodeManagers;
+
+private:
+ Q_DECLARE_PRIVATE(LoadBufferJob)
};
typedef QSharedPointer<LoadBufferJob> LoadBufferJobPtr;
diff --git a/src/render/jobs/loadgeometryjob.cpp b/src/render/jobs/loadgeometryjob.cpp
index 88930038a..2069336cd 100644
--- a/src/render/jobs/loadgeometryjob.cpp
+++ b/src/render/jobs/loadgeometryjob.cpp
@@ -66,7 +66,7 @@ LoadGeometryJob::LoadGeometryJob(const HGeometryRenderer &handle)
, m_handle(handle)
, m_nodeManagers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadGeometry, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadGeometry, 0)
}
LoadGeometryJob::~LoadGeometryJob()
diff --git a/src/render/jobs/loadscenejob.cpp b/src/render/jobs/loadscenejob.cpp
index f858f82e3..be855c608 100644
--- a/src/render/jobs/loadscenejob.cpp
+++ b/src/render/jobs/loadscenejob.cpp
@@ -63,7 +63,7 @@ LoadSceneJob::LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId sceneComponent)
, m_sceneComponent(sceneComponent)
, m_managers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadScene, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadScene, 0)
}
void LoadSceneJob::setData(const QByteArray &data)
diff --git a/src/render/jobs/loadskeletonjob.cpp b/src/render/jobs/loadskeletonjob.cpp
index 8d0d47fb9..e696cc434 100644
--- a/src/render/jobs/loadskeletonjob.cpp
+++ b/src/render/jobs/loadskeletonjob.cpp
@@ -288,7 +288,7 @@ void LoadSkeletonJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
dloaderNode->setStatus(m_backendSkeleton->status());
if (m_loadedRootJoint) {
- dloaderNode->m_rootJoint = m_loadedRootJoint;
+ dloaderNode->setRootJoint(m_loadedRootJoint);
m_loadedRootJoint = nullptr;
}
}
diff --git a/src/render/jobs/sendbuffercapturejob.cpp b/src/render/jobs/sendbuffercapturejob.cpp
index 8683ea9f2..2ccb72337 100644
--- a/src/render/jobs/sendbuffercapturejob.cpp
+++ b/src/render/jobs/sendbuffercapturejob.cpp
@@ -39,11 +39,12 @@
#include "sendbuffercapturejob_p.h"
-
-#include "Qt3DRender/private/renderer_p.h"
-#include "Qt3DRender/private/nodemanagers_p.h"
+#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/job_common_p.h>
#include <Qt3DRender/private/buffer_p.h>
+#include <Qt3DRender/private/buffermanager_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DRender/private/qbuffer_p.h>
QT_BEGIN_NAMESPACE
@@ -51,36 +52,75 @@ namespace Qt3DRender {
namespace Render {
+class SendBufferCaptureJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ SendBufferCaptureJobPrivate() {}
+ ~SendBufferCaptureJobPrivate() {}
+
+ void postFrame(Qt3DCore::QAspectManager *aspectManager) override;
+
+ mutable QMutex m_mutex;
+ QVector<QPair<Qt3DCore::QNodeId, QByteArray>> m_buffersToCapture;
+ QVector<QPair<Qt3DCore::QNodeId, QByteArray>> m_buffersToNotify;
+};
+
SendBufferCaptureJob::SendBufferCaptureJob()
- : Qt3DCore::QAspectJob()
+ : Qt3DCore::QAspectJob(*new SendBufferCaptureJobPrivate)
+ , m_nodeManagers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::SendBufferCapture, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::SendBufferCapture, 0)
}
SendBufferCaptureJob::~SendBufferCaptureJob()
{
}
-void SendBufferCaptureJob::addRequest(QPair<Buffer *, QByteArray> request)
+// Called from SubmitRenderView while rendering
+void SendBufferCaptureJob::addRequest(QPair<Qt3DCore::QNodeId, QByteArray> request)
{
- QMutexLocker locker(&m_mutex);
- m_pendingSendBufferCaptures.push_back(request);
+ Q_D(SendBufferCaptureJob);
+ QMutexLocker locker(&d->m_mutex);
+ d->m_buffersToCapture.push_back(request);
}
-// Called by aspect thread jobs to execute (no concurrency at that point)
+// Called by aspect thread jobs to execute (we may still be rendering at this point)
bool SendBufferCaptureJob::hasRequests() const
{
- return m_pendingSendBufferCaptures.size() > 0;
+ Q_D(const SendBufferCaptureJob);
+ QMutexLocker locker(&d->m_mutex);
+ return d->m_buffersToCapture.size() > 0;
}
void SendBufferCaptureJob::run()
{
- QMutexLocker locker(&m_mutex);
- for (const QPair<Buffer*, QByteArray> &pendingCapture : qAsConst(m_pendingSendBufferCaptures)) {
- pendingCapture.first->updateDataFromGPUToCPU(pendingCapture.second);
+ Q_ASSERT(m_nodeManagers);
+ Q_D(SendBufferCaptureJob);
+ QMutexLocker locker(&d->m_mutex);
+ for (const QPair<Qt3DCore::QNodeId, QByteArray> &pendingCapture : qAsConst(d->m_buffersToCapture)) {
+ Buffer *buffer = m_nodeManagers->bufferManager()->lookupResource(pendingCapture.first);
+ // Buffer might have been destroyed between the time addRequest is made and this job gets run
+ // If it exists however, it cannot be destroyed before this job is done running
+ if (buffer != nullptr)
+ buffer->updateDataFromGPUToCPU(pendingCapture.second);
}
+ d->m_buffersToNotify = std::move(d->m_buffersToCapture);
+}
- m_pendingSendBufferCaptures.clear();
+void SendBufferCaptureJobPrivate::postFrame(Qt3DCore::QAspectManager *aspectManager)
+{
+ QMutexLocker locker(&m_mutex);
+ const QVector<QPair<Qt3DCore::QNodeId, QByteArray>> pendingSendBufferCaptures = std::move(m_buffersToNotify);
+ for (const auto &bufferDataPair : pendingSendBufferCaptures) {
+ QBuffer *frontendBuffer = static_cast<decltype(frontendBuffer)>(aspectManager->lookupNode(bufferDataPair.first));
+ if (!frontendBuffer)
+ continue;
+ QBufferPrivate *dFrontend = static_cast<decltype(dFrontend)>(Qt3DCore::QNodePrivate::get(frontendBuffer));
+ // Calling frontendBuffer->setData would result in forcing a sync against the backend
+ // which isn't necessary
+ dFrontend->setData(bufferDataPair.second);
+ Q_EMIT frontendBuffer->dataAvailable();
+ }
}
} // Render
diff --git a/src/render/jobs/sendbuffercapturejob_p.h b/src/render/jobs/sendbuffercapturejob_p.h
index f47c556df..3b9f5d12b 100644
--- a/src/render/jobs/sendbuffercapturejob_p.h
+++ b/src/render/jobs/sendbuffercapturejob_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DCore/qnodeid.h>
#include <Qt3DRender/qt3drender_global.h>
#include <Qt3DRender/private/qt3drender_global_p.h>
#include <QMutex>
@@ -67,6 +68,7 @@ class NodeManagers;
class Entity;
class Renderer;
class Buffer;
+class SendBufferCaptureJobPrivate;
class Q_3DRENDERSHARED_PRIVATE_EXPORT SendBufferCaptureJob : public Qt3DCore::QAspectJob
{
@@ -74,15 +76,15 @@ public:
explicit SendBufferCaptureJob();
~SendBufferCaptureJob();
- void addRequest(QPair<Buffer*, QByteArray> request);
+ void setManagers(NodeManagers *nodeManagers) { m_nodeManagers = nodeManagers; }
+ void addRequest(QPair<Qt3DCore::QNodeId, QByteArray> request);
bool hasRequests() const;
void run() final;
private:
- QMutex m_mutex;
-
- QVector<QPair<Buffer*, QByteArray> > m_pendingSendBufferCaptures;
+ Q_DECLARE_PRIVATE(SendBufferCaptureJob)
+ NodeManagers *m_nodeManagers;
};
typedef QSharedPointer<SendBufferCaptureJob> SendBufferCaptureJobPtr;
diff --git a/src/render/jobs/sendrendercapturejob.cpp b/src/render/jobs/sendrendercapturejob.cpp
deleted file mode 100644
index f622c347a..000000000
--- a/src/render/jobs/sendrendercapturejob.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "sendrendercapturejob_p.h"
-
-#include "Qt3DRender/private/renderer_p.h"
-#include "Qt3DRender/private/nodemanagers_p.h"
-#include "Qt3DRender/private/rendercapture_p.h"
-#include <Qt3DRender/private/job_common_p.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DRender {
-
-namespace Render {
-
-SendRenderCaptureJob::SendRenderCaptureJob()
- : Qt3DCore::QAspectJob()
- , m_managers(nullptr)
-{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::SendRenderCapture, 0);
-}
-
-SendRenderCaptureJob::~SendRenderCaptureJob()
-{
-
-}
-
-void SendRenderCaptureJob::setPendingCaptureRequests(const QVector<Qt3DCore::QNodeId> &requests)
-{
- m_pendingCaptures = requests;
-}
-
-void SendRenderCaptureJob::setManagers(NodeManagers *managers)
-{
- m_managers = managers;
-}
-
-void SendRenderCaptureJob::run()
-{
- for (const Qt3DCore::QNodeId id : qAsConst(m_pendingCaptures)) {
- auto *node = static_cast<Qt3DRender::Render::RenderCapture *>
- (m_managers->frameGraphManager()->lookupNode(id));
- node->sendRenderCaptures();
- }
- m_pendingCaptures.clear();
-}
-
-} // Render
-
-} // Qt3DRender
-
-QT_END_NAMESPACE
diff --git a/src/render/jobs/sendrendercapturejob_p.h b/src/render/jobs/sendrendercapturejob_p.h
deleted file mode 100644
index 8bc1e2fb0..000000000
--- a/src/render/jobs/sendrendercapturejob_p.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef SENDRENDERCAPTUREJOB_P_H
-#define SENDRENDERCAPTUREJOB_P_H
-
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <Qt3DCore/qaspectjob.h>
-#include <Qt3DCore/qnodeid.h>
-#include <Qt3DRender/qt3drender_global.h>
-#include <Qt3DRender/private/qt3drender_global_p.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DRender {
-
-namespace Render {
-
-class NodeManagers;
-class Entity;
-
-class Q_3DRENDERSHARED_PRIVATE_EXPORT SendRenderCaptureJob : public Qt3DCore::QAspectJob
-{
-public:
- SendRenderCaptureJob();
- ~SendRenderCaptureJob();
-
- void setPendingCaptureRequests(const QVector<Qt3DCore::QNodeId> &requests);
- void setManagers(NodeManagers *managers);
-
- void run() final;
-
-private:
- NodeManagers *m_managers;
- QVector<Qt3DCore::QNodeId> m_pendingCaptures;
-};
-
-typedef QSharedPointer<SendRenderCaptureJob> SendRenderCaptureJobPtr;
-
-} // namespace Render
-
-} // namespace Qt3DRender
-
-QT_END_NAMESPACE
-
-#endif // SENDRENDERCAPTUREJOB_P_H
diff --git a/src/render/jobs/updateentitylayersjob.cpp b/src/render/jobs/updateentitylayersjob.cpp
index 2c5e38364..b8c50c179 100644
--- a/src/render/jobs/updateentitylayersjob.cpp
+++ b/src/render/jobs/updateentitylayersjob.cpp
@@ -52,7 +52,7 @@ namespace Render {
UpdateEntityLayersJob::UpdateEntityLayersJob()
: m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateLayerEntity, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateLayerEntity, 0)
}
diff --git a/src/render/jobs/updatemeshtrianglelistjob.cpp b/src/render/jobs/updatemeshtrianglelistjob.cpp
index 1c61d1c90..4837dcad6 100644
--- a/src/render/jobs/updatemeshtrianglelistjob.cpp
+++ b/src/render/jobs/updatemeshtrianglelistjob.cpp
@@ -60,7 +60,7 @@ namespace Render {
UpdateMeshTriangleListJob::UpdateMeshTriangleListJob()
: m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateMeshTriangleList, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateMeshTriangleList, 0)
}
UpdateMeshTriangleListJob::~UpdateMeshTriangleListJob()
diff --git a/src/render/jobs/updateshaderdatatransformjob.cpp b/src/render/jobs/updateshaderdatatransformjob.cpp
index c29a827e3..11fe91932 100644
--- a/src/render/jobs/updateshaderdatatransformjob.cpp
+++ b/src/render/jobs/updateshaderdatatransformjob.cpp
@@ -61,7 +61,7 @@ namespace Render {
UpdateShaderDataTransformJob::UpdateShaderDataTransformJob()
: m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateShaderDataTransform, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateShaderDataTransform, 0)
}
UpdateShaderDataTransformJob::~UpdateShaderDataTransformJob()
diff --git a/src/render/jobs/updateskinningpalettejob.cpp b/src/render/jobs/updateskinningpalettejob.cpp
index 0f5d3d6d6..b77707f15 100644
--- a/src/render/jobs/updateskinningpalettejob.cpp
+++ b/src/render/jobs/updateskinningpalettejob.cpp
@@ -50,7 +50,7 @@ UpdateSkinningPaletteJob::UpdateSkinningPaletteJob()
, m_nodeManagers(nullptr)
, m_root()
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateSkinningPalette, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateSkinningPalette, 0)
}
UpdateSkinningPaletteJob::~UpdateSkinningPaletteJob()
diff --git a/src/render/jobs/updatetreeenabledjob.cpp b/src/render/jobs/updatetreeenabledjob.cpp
index e97fc6414..22d6f6083 100644
--- a/src/render/jobs/updatetreeenabledjob.cpp
+++ b/src/render/jobs/updatetreeenabledjob.cpp
@@ -71,8 +71,9 @@ void updateTreeEnabled(NodeManagers *manager, Entity *node, bool parentEnabled)
UpdateTreeEnabledJob::UpdateTreeEnabledJob()
: Qt3DCore::QAspectJob()
, m_node(nullptr)
+ , m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateTreeEnabled, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateTreeEnabled, 0)
}
void UpdateTreeEnabledJob::setRoot(Entity *root)
diff --git a/src/render/jobs/updateworldboundingvolumejob.cpp b/src/render/jobs/updateworldboundingvolumejob.cpp
index 40dd919bc..65a3ec75d 100644
--- a/src/render/jobs/updateworldboundingvolumejob.cpp
+++ b/src/render/jobs/updateworldboundingvolumejob.cpp
@@ -52,7 +52,7 @@ UpdateWorldBoundingVolumeJob::UpdateWorldBoundingVolumeJob()
: Qt3DCore::QAspectJob()
, m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateWorldBoundingVolume, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateWorldBoundingVolume, 0)
}
void UpdateWorldBoundingVolumeJob::run()
@@ -61,6 +61,8 @@ void UpdateWorldBoundingVolumeJob::run()
for (const HEntity &handle : handles) {
Entity *node = m_manager->data(handle);
+ if (!node->isEnabled())
+ continue;
*(node->worldBoundingVolume()) = node->localBoundingVolume()->transformed(*(node->worldTransform()));
*(node->worldBoundingVolumeWithChildren()) = *(node->worldBoundingVolume()); // expanded in UpdateBoundingVolumeJob
}
diff --git a/src/render/jobs/updateworldtransformjob.cpp b/src/render/jobs/updateworldtransformjob.cpp
index 13e14442f..e3c8077f4 100644
--- a/src/render/jobs/updateworldtransformjob.cpp
+++ b/src/render/jobs/updateworldtransformjob.cpp
@@ -65,11 +65,13 @@ struct TransformUpdate
QMatrix4x4 worldTransformMatrix;
};
-QVector<TransformUpdate> updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform)
+void updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform, QVector<TransformUpdate> &updatedTransforms)
{
+ if (!node->isEnabled())
+ return;
+
Matrix4x4 worldTransform(parentTransform);
Transform *nodeTransform = node->renderComponent<Transform>();
- QVector<TransformUpdate> updatedTransforms;
const bool hasTransformComponent = nodeTransform != nullptr && nodeTransform->isEnabled();
if (hasTransformComponent)
@@ -85,9 +87,8 @@ QVector<TransformUpdate> updateWorldTransformAndBounds(NodeManagers *manager, En
for (const HEntity &handle : childrenHandles) {
Entity *child = manager->renderNodesManager()->data(handle);
if (child)
- updatedTransforms += updateWorldTransformAndBounds(manager, child, worldTransform);
+ updateWorldTransformAndBounds(manager, child, worldTransform, updatedTransforms);
}
- return updatedTransforms;
}
}
@@ -108,7 +109,7 @@ UpdateWorldTransformJob::UpdateWorldTransformJob()
, m_node(nullptr)
, m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateTransform, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateTransform, 0)
}
void UpdateWorldTransformJob::setRoot(Entity *root)
@@ -137,7 +138,7 @@ void UpdateWorldTransformJob::run()
Entity *parent = m_node->parent();
if (parent != nullptr)
parentTransform = *(parent->worldTransform());
- d->m_updatedTransforms = updateWorldTransformAndBounds(m_manager, m_node, parentTransform);
+ updateWorldTransformAndBounds(m_manager, m_node, parentTransform, d->m_updatedTransforms);
qCDebug(Jobs) << "Exiting" << Q_FUNC_INFO << QThread::currentThread();
}
diff --git a/src/render/lights/qdirectionallight.cpp b/src/render/lights/qdirectionallight.cpp
index 13fb78843..51827b644 100644
--- a/src/render/lights/qdirectionallight.cpp
+++ b/src/render/lights/qdirectionallight.cpp
@@ -115,12 +115,18 @@ QDirectionalLight::QDirectionalLight(QDirectionalLightPrivate &dd, QNode *parent
/*!
\qmlproperty vector3d Qt3D.Render::DirectionalLight::worldDirection
- Specifies the world direction of the directional light
+ Specifies the world direction of the directional light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
/*!
\property Qt3DRender::QDirectionalLight::worldDirection
- Specifies the world direction of the directional light
+ Specifies the world direction of the directional light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
void QDirectionalLight::setWorldDirection(const QVector3D &direction)
{
diff --git a/src/render/lights/qenvironmentlight.cpp b/src/render/lights/qenvironmentlight.cpp
index 86ef04f95..977e117db 100644
--- a/src/render/lights/qenvironmentlight.cpp
+++ b/src/render/lights/qenvironmentlight.cpp
@@ -158,6 +158,9 @@ QEnvironmentLight::~QEnvironmentLight()
Holds the current environment irradiance map texture.
By default, the environment irradiance texture is null.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
/*!
@@ -166,6 +169,9 @@ QEnvironmentLight::~QEnvironmentLight()
Holds the current environment irradiance map texture.
By default, the environment irradiance texture is null.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
QAbstractTexture *QEnvironmentLight::irradiance() const
{
@@ -179,6 +185,9 @@ QAbstractTexture *QEnvironmentLight::irradiance() const
Holds the current environment specular map texture.
By default, the environment specular texture is null.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
/*!
@@ -187,6 +196,9 @@ QAbstractTexture *QEnvironmentLight::irradiance() const
Holds the current environment specular map texture.
By default, the environment specular texture is null.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
QAbstractTexture *QEnvironmentLight::specular() const
{
diff --git a/src/render/lights/qpointlight.cpp b/src/render/lights/qpointlight.cpp
index 2b042c91d..c16291709 100644
--- a/src/render/lights/qpointlight.cpp
+++ b/src/render/lights/qpointlight.cpp
@@ -135,12 +135,18 @@ QPointLight::QPointLight(QPointLightPrivate &dd, QNode *parent)
/*!
\qmlproperty float Qt3D.Render::PointLight::constantAttenuation
- Specifies the constant attenuation of the point light
+ Specifies the constant attenuation of the point light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
/*!
\property Qt3DRender::QPointLight::constantAttenuation
- Specifies the constant attenuation of the point light
+ Specifies the constant attenuation of the point light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
float QPointLight::constantAttenuation() const
{
@@ -159,12 +165,18 @@ void QPointLight::setConstantAttenuation(float value)
/*!
\qmlproperty float Qt3D.Render::PointLight::linearAttenuation
- Specifies the linear attenuation of the point light
+ Specifies the linear attenuation of the point light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
/*!
\property Qt3DRender::QPointLight::linearAttenuation
- Specifies the linear attenuation of the point light
+ Specifies the linear attenuation of the point light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
float QPointLight::linearAttenuation() const
{
@@ -183,12 +195,18 @@ void QPointLight::setLinearAttenuation(float value)
/*!
\qmlproperty float Qt3D.Render::PointLight::quadraticAttenuation
- Specifies the quadratic attenuation of the point light
+ Specifies the quadratic attenuation of the point light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
/*!
\property Qt3DRender::QPointLight::quadraticAttenuation
- Specifies the quadratic attenuation of the point light
+ Specifies the quadratic attenuation of the point light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
float QPointLight::quadraticAttenuation() const
{
diff --git a/src/render/lights/qspotlight.cpp b/src/render/lights/qspotlight.cpp
index eddafbe61..c725a6baf 100644
--- a/src/render/lights/qspotlight.cpp
+++ b/src/render/lights/qspotlight.cpp
@@ -140,12 +140,18 @@ QSpotLight::QSpotLight(QSpotLightPrivate &dd, QNode *parent)
/*!
\qmlproperty float Qt3D.Render::SpotLight::constantAttenuation
- Specifies the constant attenuation of the spot light
+ Specifies the constant attenuation of the spot light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
/*!
\property Qt3DRender::QSpotLight::constantAttenuation
- Specifies the constant attenuation of the spot light
+ Specifies the constant attenuation of the spot light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
float QSpotLight::constantAttenuation() const
{
@@ -164,12 +170,18 @@ void QSpotLight::setConstantAttenuation(float value)
/*!
\qmlproperty float Qt3D.Render::SpotLight::linearAttenuation
- Specifies the linear attenuation of the spot light
+ Specifies the linear attenuation of the spot light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
/*!
\property Qt3DRender::QSpotLight::linearAttenuation
- Specifies the linear attenuation of the spot light
+ Specifies the linear attenuation of the spot light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
float QSpotLight::linearAttenuation() const
{
@@ -188,12 +200,18 @@ void QSpotLight::setLinearAttenuation(float value)
/*!
\qmlproperty float Qt3D.Render::SpotLight::quadraticAttenuation
- Specifies the quadratic attenuation of the spot light
+ Specifies the quadratic attenuation of the spot light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
/*!
\property Qt3DRender::QSpotLight::quadraticAttenuation
- Specifies the quadratic attenuation of the spot light
+ Specifies the quadratic attenuation of the spot light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
float QSpotLight::quadraticAttenuation() const
{
@@ -212,12 +230,18 @@ void QSpotLight::setQuadraticAttenuation(float value)
/*!
\qmlproperty vector3d Qt3D.Render::SpotLight::localDirection
- Specifies the local direction of the spot light
+ Specifies the local direction of the spot light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
/*!
\property Qt3DRender::QSpotLight::localDirection
- Specifies the local direction of the spot light
+ Specifies the local direction of the spot light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
QVector3D QSpotLight::localDirection() const
{
@@ -227,12 +251,18 @@ QVector3D QSpotLight::localDirection() const
/*!
\qmlproperty float Qt3D.Render::SpotLight::cutOffAngle
- Specifies the cut off angle of the spot light
+ Specifies the cut off angle of the spot light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
/*!
\property Qt3DRender::QSpotLight::cutOffAngle
- Specifies the cut off angle of the spot light
+ Specifies the cut off angle of the spot light.
+
+ \note The exact meaning and use of this property is up to the
+ material implementation.
*/
float QSpotLight::cutOffAngle() const
{
diff --git a/src/render/materialsystem/qshaderimage.cpp b/src/render/materialsystem/qshaderimage.cpp
index f2ce04c3d..508cf44f2 100644
--- a/src/render/materialsystem/qshaderimage.cpp
+++ b/src/render/materialsystem/qshaderimage.cpp
@@ -342,7 +342,7 @@ QShaderImagePrivate::~QShaderImagePrivate()
*/
/*!
- \qmlproperty Qt3DRender::QShaderImage::mipLevel
+ \qmlproperty int Qt3D.Render::ShaderImage::mipLevel
Holds which mipLevel out of the referenced texture should be used for the
ShaderImage.
@@ -351,7 +351,7 @@ QShaderImagePrivate::~QShaderImagePrivate()
*/
/*!
- \qmlproperty Qt3DRender::QShaderImage::layer
+ \qmlproperty int Qt3D.Render::ShaderImage::layer
Holds which layer out of the referenced texture should be used for the
ShaderImage. This property does nothing if \a layered is set to true or if
@@ -365,11 +365,11 @@ QShaderImagePrivate::~QShaderImagePrivate()
cubeMapFace = layer - (cubeMapLayer * 6)
\endcode
- \default 0
+ Default value is 0.
*/
/*!
- * \qmlproperty Qt3DRender::QShaderImage::layered
+ * \qmlproperty bool Qt3D.Render::ShaderImage::layered
If set to true, if the referenced texture is a one-dimensional array,
two-dimensional array, three-dimensional, cube map, cube map array, or
@@ -377,21 +377,28 @@ QShaderImagePrivate::~QShaderImagePrivate()
for all layers. If set to false, only the single layer specified by the \a
layer property will be bound.
- \default false
+ Default value is \c false.
*/
/*!
- \qmlproperty Qt3DRender::QShaderImage::access
+ \qmlproperty enumeration Qt3D.Render::ShaderImage::access
Specifies the type of access we want to allow from our shader instances to
the image. If a shader tries to write or read from an image that has
incompatible access, the behavior is undefined.
- \default ShaderImage.ReadWrite
+ \value ShaderImage.ReadOnly
+ Read-only access.
+ \value ShaderImage.WriteOnly
+ Write-only access.
+ \value ShaderImage.ReadWrite
+ Read-write access.
+
+ Default value is ShaderImage.ReadWrite.
*/
/*!
- \qmlproperty Qt3DRender::QShaderImage::format
+ \qmlproperty enumeration Qt3D.Render::ShaderImage::format
Specifies the image format, which is essentially important when storing values
in the ShaderImage from a shader.
@@ -407,7 +414,7 @@ QShaderImagePrivate::~QShaderImagePrivate()
By default Qt3D will try to set the image format to match that of the
referenced texture.
- \default ShaderImage.Automatic
+ Default value is ShaderImage.Automatic.
*/
/*!
diff --git a/src/render/materialsystem/qshaderprogrambuilder.cpp b/src/render/materialsystem/qshaderprogrambuilder.cpp
index 6613661d1..7f98fbf5e 100644
--- a/src/render/materialsystem/qshaderprogrambuilder.cpp
+++ b/src/render/materialsystem/qshaderprogrambuilder.cpp
@@ -135,6 +135,11 @@ QShaderProgramBuilder::QShaderProgramBuilder(QShaderProgramBuilderPrivate &dd, Q
{
}
+// TODO Unused remove in Qt6
+void QShaderProgramBuilder::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
/*!
\qmlproperty string ShaderProgramBuilder::shaderProgram
diff --git a/src/render/materialsystem/qshaderprogrambuilder.h b/src/render/materialsystem/qshaderprogrambuilder.h
index 5dc6b54ff..48e189c8c 100644
--- a/src/render/materialsystem/qshaderprogrambuilder.h
+++ b/src/render/materialsystem/qshaderprogrambuilder.h
@@ -117,6 +117,8 @@ Q_SIGNALS:
protected:
explicit QShaderProgramBuilder(QShaderProgramBuilderPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QShaderProgramBuilder)
diff --git a/src/render/materialsystem/shader.cpp b/src/render/materialsystem/shader.cpp
index 58709b37e..0d4b5edba 100644
--- a/src/render/materialsystem/shader.cpp
+++ b/src/render/materialsystem/shader.cpp
@@ -57,11 +57,35 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
+const int Shader::modelMatrixNameId = StringToInt::lookupId(QLatin1String("modelMatrix"));
+const int Shader::viewMatrixNameId = StringToInt::lookupId(QLatin1String("viewMatrix"));
+const int Shader::projectionMatrixNameId = StringToInt::lookupId(QLatin1String("projectionMatrix"));
+const int Shader::modelViewMatrixNameId = StringToInt::lookupId(QLatin1String("modelView"));
+const int Shader::viewProjectionMatrixNameId = StringToInt::lookupId(QLatin1String("viewProjectionMatrix"));
+const int Shader::modelViewProjectionNameId = StringToInt::lookupId(QLatin1String("modelViewProjection"));
+const int Shader::mvpNameId = StringToInt::lookupId(QLatin1String("mvp"));
+const int Shader::inverseModelMatrixNameId = StringToInt::lookupId(QLatin1String("inverseModelMatrix"));
+const int Shader::inverseViewMatrixNameId = StringToInt::lookupId(QLatin1String("inverseViewMatrix"));
+const int Shader::inverseProjectionMatrixNameId = StringToInt::lookupId(QLatin1String("inverseProjectionMatrix"));
+const int Shader::inverseModelViewNameId = StringToInt::lookupId(QLatin1String("inverseModelView"));
+const int Shader::inverseViewProjectionMatrixNameId = StringToInt::lookupId(QLatin1String("inverseViewProjectionMatrix"));
+const int Shader::inverseModelViewProjectionNameId = StringToInt::lookupId(QLatin1String("inverseModelViewProjection"));
+const int Shader::modelNormalMatrixNameId = StringToInt::lookupId(QLatin1String("modelNormalMatrix"));
+const int Shader::modelViewNormalNameId = StringToInt::lookupId(QLatin1String("modelViewNormal"));
+const int Shader::viewportMatrixNameId = StringToInt::lookupId(QLatin1String("viewportMatrix"));
+const int Shader::inverseViewportMatrixNameId = StringToInt::lookupId(QLatin1String("inverseViewportMatrix"));
+const int Shader::aspectRatioNameId = StringToInt::lookupId(QLatin1String("aspectRatio"));
+const int Shader::exposureNameId = StringToInt::lookupId(QLatin1String("exposure"));
+const int Shader::gammaNameId = StringToInt::lookupId(QLatin1String("gamma"));
+const int Shader::timeNameId = StringToInt::lookupId(QLatin1String("time"));
+const int Shader::eyePositionNameId = StringToInt::lookupId(QLatin1String("eyePosition"));
+const int Shader::skinningPaletteNameId = StringToInt::lookupId(QLatin1String("skinningPalette[0]"));
Shader::Shader()
: BackendNode(ReadWrite)
, m_isLoaded(false)
, m_dna(0)
+ , m_oldDna(0)
, m_graphicsContext(nullptr)
, m_status(QShaderProgram::NotReady)
, m_requiresFrontendSync(false)
@@ -243,13 +267,13 @@ void Shader::prepareUniforms(ShaderParameterPack &pack)
{
const PackUniformHash &values = pack.uniforms();
- auto it = values.cbegin();
- const auto end = values.cend();
+ auto it = values.keys.cbegin();
+ const auto end = values.keys.cend();
while (it != end) {
// Find if there's a uniform with the same name id
for (const ShaderUniform &uniform : qAsConst(m_uniforms)) {
- if (uniform.m_nameId == it.key()) {
+ if (uniform.m_nameId == *it) {
pack.setSubmissionUniform(uniform);
break;
}
@@ -307,13 +331,47 @@ void Shader::initializeUniforms(const QVector<ShaderUniform> &uniformsDescriptio
{
m_uniforms = uniformsDescription;
m_uniformsNames.resize(uniformsDescription.size());
- m_uniformsNamesIds.resize(uniformsDescription.size());
+ m_uniformsNamesIds.reserve(uniformsDescription.size());
+ m_standardUniformNamesIds.reserve(5);
QHash<QString, ShaderUniform> activeUniformsInDefaultBlock;
+ static const QVector<int> standardUniformNameIds = {
+ modelMatrixNameId,
+ viewMatrixNameId,
+ projectionMatrixNameId,
+ modelViewMatrixNameId,
+ viewProjectionMatrixNameId,
+ modelViewProjectionNameId,
+ mvpNameId,
+ inverseModelMatrixNameId,
+ inverseViewMatrixNameId,
+ inverseProjectionMatrixNameId,
+ inverseModelViewNameId,
+ inverseViewProjectionMatrixNameId,
+ inverseModelViewProjectionNameId,
+ modelNormalMatrixNameId,
+ modelViewNormalNameId,
+ viewportMatrixNameId,
+ inverseViewportMatrixNameId,
+ aspectRatioNameId,
+ exposureNameId,
+ gammaNameId,
+ timeNameId,
+ eyePositionNameId,
+ skinningPaletteNameId,
+ };
+
for (int i = 0, m = uniformsDescription.size(); i < m; i++) {
m_uniformsNames[i] = m_uniforms[i].m_name;
- m_uniforms[i].m_nameId = StringToInt::lookupId(m_uniformsNames[i]);
- m_uniformsNamesIds[i] = m_uniforms[i].m_nameId;
+ const int nameId = StringToInt::lookupId(m_uniformsNames[i]);
+ m_uniforms[i].m_nameId = nameId;
+
+ // Is the uniform a Qt3D "Standard" uniform or a user defined one?
+ if (standardUniformNameIds.contains(nameId))
+ m_standardUniformNamesIds.push_back(nameId);
+ else
+ m_uniformsNamesIds.push_back(nameId);
+
if (uniformsDescription[i].m_blockIndex == -1) { // Uniform is in default block
qCDebug(Shaders) << "Active Uniform in Default Block " << uniformsDescription[i].m_name << uniformsDescription[i].m_blockIndex;
activeUniformsInDefaultBlock.insert(uniformsDescription[i].m_name, uniformsDescription[i]);
@@ -393,6 +451,7 @@ void Shader::initializeFromReference(const Shader &other)
{
Q_ASSERT(m_dna == other.m_dna);
m_uniformsNamesIds = other.m_uniformsNamesIds;
+ m_standardUniformNamesIds = other.m_standardUniformNamesIds;
m_uniformsNames = other.m_uniformsNames;
m_uniforms = other.m_uniforms;
m_attributesNames = other.m_attributesNames;
diff --git a/src/render/materialsystem/shader_p.h b/src/render/materialsystem/shader_p.h
index 1c9731e50..4c5bc5ea1 100644
--- a/src/render/materialsystem/shader_p.h
+++ b/src/render/materialsystem/shader_p.h
@@ -75,6 +75,30 @@ typedef uint ProgramDNA;
class Q_AUTOTEST_EXPORT Shader : public BackendNode
{
public:
+ static const int modelMatrixNameId;
+ static const int viewMatrixNameId;
+ static const int projectionMatrixNameId;
+ static const int modelViewMatrixNameId;
+ static const int viewProjectionMatrixNameId;
+ static const int modelViewProjectionNameId;
+ static const int mvpNameId;
+ static const int inverseModelMatrixNameId;
+ static const int inverseViewMatrixNameId;
+ static const int inverseProjectionMatrixNameId;
+ static const int inverseModelViewNameId;
+ static const int inverseViewProjectionMatrixNameId;
+ static const int inverseModelViewProjectionNameId;
+ static const int modelNormalMatrixNameId;
+ static const int modelViewNormalNameId;
+ static const int viewportMatrixNameId;
+ static const int inverseViewportMatrixNameId;
+ static const int aspectRatioNameId;
+ static const int exposureNameId;
+ static const int gammaNameId;
+ static const int timeNameId;
+ static const int eyePositionNameId;
+ static const int skinningPaletteNameId;
+
Shader();
~Shader();
@@ -88,6 +112,7 @@ public:
const QHash<QString, int> fragOutputs() const;
inline QVector<int> uniformsNamesIds() const { return m_uniformsNamesIds; }
+ inline QVector<int> standardUniformNameIds() const { return m_standardUniformNamesIds; }
inline QVector<int> uniformBlockNamesIds() const { return m_uniformBlockNamesIds; }
inline QVector<int> storageBlockNamesIds() const { return m_shaderStorageBlockNamesIds; }
inline QVector<int> attributeNamesIds() const { return m_attributeNamesIds; }
@@ -128,6 +153,7 @@ public:
private:
QVector<QString> m_uniformsNames;
QVector<int> m_uniformsNamesIds;
+ QVector<int> m_standardUniformNamesIds;
QVector<ShaderUniform> m_uniforms;
QVector<QString> m_attributesNames;
diff --git a/src/render/picking/qabstractraycaster.cpp b/src/render/picking/qabstractraycaster.cpp
index ab0916401..5f4c4c490 100644
--- a/src/render/picking/qabstractraycaster.cpp
+++ b/src/render/picking/qabstractraycaster.cpp
@@ -58,10 +58,6 @@ QAbstractRayCasterPrivate::QAbstractRayCasterPrivate()
m_shareable = false;
}
-/*!
- \property Qt3DRender::QAbstractRayCaster::Hits
-*/
-
QAbstractRayCasterPrivate *QAbstractRayCasterPrivate::get(QAbstractRayCaster *obj)
{
return obj->d_func();
diff --git a/src/render/picking/qobjectpicker.cpp b/src/render/picking/qobjectpicker.cpp
index 7d9741f21..4f039b361 100644
--- a/src/render/picking/qobjectpicker.cpp
+++ b/src/render/picking/qobjectpicker.cpp
@@ -152,7 +152,7 @@ namespace Qt3DRender {
This signal is emitted when the bounding volume defined by the
pickAttribute property intersects with a ray on a mouse click. Intersection
- information are accessible through the pick \a parameter.
+ information are accessible through the \a pick parameter.
*/
/*!
@@ -292,6 +292,11 @@ void QObjectPicker::setPriority(int priority)
}
}
+// TODO Unused remove in Qt6
+void QObjectPicker::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
/*!
\qmlproperty bool Qt3D.Render::ObjectPicker::dragEnabled
*/
diff --git a/src/render/picking/qobjectpicker.h b/src/render/picking/qobjectpicker.h
index ee63c9418..ea65040ba 100644
--- a/src/render/picking/qobjectpicker.h
+++ b/src/render/picking/qobjectpicker.h
@@ -77,6 +77,10 @@ public Q_SLOTS:
void setDragEnabled(bool dragEnabled);
Q_REVISION(13) void setPriority(int priority);
+protected:
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
+
Q_SIGNALS:
void pressed(Qt3DRender::QPickEvent *pick);
void released(Qt3DRender::QPickEvent *pick);
diff --git a/src/render/picking/qobjectpicker_p.h b/src/render/picking/qobjectpicker_p.h
index 69cee529d..61f8a3d94 100644
--- a/src/render/picking/qobjectpicker_p.h
+++ b/src/render/picking/qobjectpicker_p.h
@@ -50,7 +50,6 @@
#include <Qt3DCore/private/qcomponent_p.h>
#include <Qt3DCore/qnodeid.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/private/qt3drender_global_p.h>
#include <Qt3DRender/private/objectpicker_p.h>
diff --git a/src/render/picking/raycaster.cpp b/src/render/picking/raycaster.cpp
index 3a79204c7..8d3456595 100644
--- a/src/render/picking/raycaster.cpp
+++ b/src/render/picking/raycaster.cpp
@@ -44,7 +44,6 @@
#include <Qt3DRender/qlayer.h>
#include <Qt3DRender/private/qabstractraycaster_p.h>
#include <Qt3DRender/private/raycastingjob_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/raycasting/qcollisionqueryresult.cpp b/src/render/raycasting/qcollisionqueryresult.cpp
index 9d1e484b6..d2a443691 100644
--- a/src/render/raycasting/qcollisionqueryresult.cpp
+++ b/src/render/raycasting/qcollisionqueryresult.cpp
@@ -46,6 +46,7 @@ namespace RayCasting {
QCollisionQueryResultPrivate::QCollisionQueryResultPrivate()
: QSharedData()
+ , m_handle(0)
{
}
diff --git a/src/render/raycasting/qcollisionqueryresult_p.h b/src/render/raycasting/qcollisionqueryresult_p.h
index 67f6a34d0..d8e2056eb 100644
--- a/src/render/raycasting/qcollisionqueryresult_p.h
+++ b/src/render/raycasting/qcollisionqueryresult_p.h
@@ -86,8 +86,10 @@ public:
Hit(Qt3DCore::QNodeId entity, const Vector3D &intersection, float distance, const Vector3D &uvw)
: m_entityId(entity)
+ , m_type(Entity)
, m_intersection(intersection)
, m_distance(distance)
+ , m_primitiveIndex(0U)
, m_uvw(uvw)
{
}
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
index 333453ac7..71edc1c74 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
@@ -265,17 +265,15 @@ QOpenGLShaderProgram *GraphicsContext::createShaderProgram(Shader *shaderNode)
return shaderProgram.take();
}
-// Called by GL Command Thread (can't use global glHelpers)
// That assumes that the shaderProgram in Shader stays the same
void GraphicsContext::introspectShaderInterface(Shader *shader, QOpenGLShaderProgram *shaderProgram)
{
- QScopedPointer<GraphicsHelperInterface> glHelper(resolveHighestOpenGLFunctions());
- shader->initializeUniforms(glHelper->programUniformsAndLocations(shaderProgram->programId()));
- shader->initializeAttributes(glHelper->programAttributesAndLocations(shaderProgram->programId()));
+ shader->initializeUniforms(m_glHelper->programUniformsAndLocations(shaderProgram->programId()));
+ shader->initializeAttributes(m_glHelper->programAttributesAndLocations(shaderProgram->programId()));
if (m_glHelper->supportsFeature(GraphicsHelperInterface::UniformBufferObject))
- shader->initializeUniformBlocks(glHelper->programUniformBlocks(shaderProgram->programId()));
+ shader->initializeUniformBlocks(m_glHelper->programUniformBlocks(shaderProgram->programId()));
if (m_glHelper->supportsFeature(GraphicsHelperInterface::ShaderStorageObject))
- shader->initializeShaderStorageBlocks(glHelper->programShaderStorageBlocks(shaderProgram->programId()));
+ shader->initializeShaderStorageBlocks(m_glHelper->programShaderStorageBlocks(shaderProgram->programId()));
}
diff --git a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
index 4b4199820..47779dded 100644
--- a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
@@ -538,9 +538,9 @@ GLuint SubmissionContext::updateRenderTarget(Qt3DCore::QNodeId renderTargetNodeI
// ### TODO QTBUG-64757 this check is insufficient since the
// texture may have changed to another one with the same size. That
// case is not handled atm.
- needsResize |= (rTex != nullptr && rTex->size() != s);
- if (isActiveRenderTarget) {
- if (attachment.m_point == QRenderTargetOutput::Color0)
+ if (rTex) {
+ needsResize |= rTex->size() != s;
+ if (isActiveRenderTarget && attachment.m_point == QRenderTargetOutput::Color0)
m_renderTargetFormat = rTex->properties().format;
}
}
@@ -687,8 +687,8 @@ QImage SubmissionContext::readFramebuffer(const QRect &rect)
GLint samples = 0;
m_gl->functions()->glGetIntegerv(GL_SAMPLES, &samples);
if (samples > 0 && !m_glHelper->supportsFeature(GraphicsHelperInterface::BlitFramebuffer)) {
- qWarning () << Q_FUNC_INFO << "Unable to capture multisampled framebuffer; "
- "Required feature BlitFramebuffer is missing.";
+ qCWarning(Backend) << Q_FUNC_INFO << "Unable to capture multisampled framebuffer; "
+ "Required feature BlitFramebuffer is missing.";
return img;
}
@@ -711,7 +711,7 @@ QImage SubmissionContext::readFramebuffer(const QRect &rect)
if (status != GL_FRAMEBUFFER_COMPLETE) {
gl->glDeleteRenderbuffers(1, &rb);
gl->glDeleteFramebuffers(1, &fbo);
- qWarning () << Q_FUNC_INFO << "Copy-framebuffer not complete: " << status;
+ qCWarning(Backend) << Q_FUNC_INFO << "Copy-framebuffer not complete: " << status;
return img;
}
@@ -797,7 +797,7 @@ bool SubmissionContext::activateShader(ProgramDNA shaderDNA)
m_activeShaderDNA = shaderDNA;
} else {
m_glHelper->useProgram(0);
- qWarning() << "No shader program found for DNA";
+ qCWarning(Backend) << "No shader program found for DNA";
m_activeShaderDNA = 0;
return false;
}
@@ -855,7 +855,7 @@ void SubmissionContext::activateDrawBuffers(const AttachmentPack &attachments)
}
}
} else {
- qWarning() << "FBO incomplete";
+ qCWarning(Backend) << "FBO incomplete";
}
}
@@ -1171,7 +1171,7 @@ bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack)
if (uniformValues.contains(namedTex.glslNameId)) {
GLTexture *t = manager->glTextureManager()->lookupResource(namedTex.nodeId);
if (t != nullptr) {
- UniformValue &texUniform = uniformValues[namedTex.glslNameId];
+ UniformValue &texUniform = uniformValues.value(namedTex.glslNameId);
if (texUniform.valueType() == UniformValue::TextureValue) {
const int texUnit = m_textureContext.activateTexture(TextureSubmissionContext::TextureScopeMaterial, m_gl, t);
texUniform.data<int>()[namedTex.uniformArrayIndex] = texUnit;
@@ -1179,7 +1179,7 @@ bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack)
if (namedTex.glslNameId != irradianceId &&
namedTex.glslNameId != specularId) {
// Only return false if we are not dealing with env light textures
- qWarning() << "Unable to find suitable Texture Unit";
+ qCWarning(Backend) << "Unable to find suitable Texture Unit";
return false;
}
}
@@ -1198,15 +1198,15 @@ bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack)
if (img != nullptr) {
GLTexture *t = manager->glTextureManager()->lookupResource(img->textureId());
if (t == nullptr) {
- qWarning() << "Shader Image referencing invalid texture";
+ qCWarning(Backend) << "Shader Image referencing invalid texture";
continue;
} else {
- UniformValue &imgUniform = uniformValues[namedTex.glslNameId];
+ UniformValue &imgUniform = uniformValues.value(namedTex.glslNameId);
if (imgUniform.valueType() == UniformValue::ShaderImageValue) {
const int imgUnit = m_imageContext.activateImage(img, t);
imgUniform.data<int>()[namedTex.uniformArrayIndex] = imgUnit;
if (imgUnit == -1) {
- qWarning() << "Unable to bind Image to Texture";
+ qCWarning(Backend) << "Unable to bind Image to Texture";
return false;
}
}
@@ -1260,7 +1260,7 @@ bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack)
for (const ShaderUniform &uniform : activeUniforms) {
// We can use [] as we are sure the the uniform wouldn't
// be un activeUniforms if there wasn't a matching value
- const UniformValue &v = values[uniform.m_nameId];
+ const UniformValue &v = values.value(uniform.m_nameId);
// skip invalid textures/images
if ((v.valueType() == UniformValue::TextureValue ||
diff --git a/src/render/renderers/opengl/jobs/filtercompatibletechniquejob.cpp b/src/render/renderers/opengl/jobs/filtercompatibletechniquejob.cpp
index 342fd3dad..d2a01eef4 100644
--- a/src/render/renderers/opengl/jobs/filtercompatibletechniquejob.cpp
+++ b/src/render/renderers/opengl/jobs/filtercompatibletechniquejob.cpp
@@ -53,7 +53,7 @@ FilterCompatibleTechniqueJob::FilterCompatibleTechniqueJob()
: m_manager(nullptr)
, m_renderer(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::FilterCompatibleTechniques, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::FilterCompatibleTechniques, 0)
}
void FilterCompatibleTechniqueJob::setManager(TechniqueManager *manager)
diff --git a/src/render/renderers/opengl/jobs/jobs.pri b/src/render/renderers/opengl/jobs/jobs.pri
index 021cd3242..d80b8bfd9 100644
--- a/src/render/renderers/opengl/jobs/jobs.pri
+++ b/src/render/renderers/opengl/jobs/jobs.pri
@@ -3,13 +3,15 @@ INCLUDEPATH += $$PWD
SOURCES += \
$$PWD/filtercompatibletechniquejob.cpp \
$$PWD/materialparametergathererjob.cpp \
- $$PWD/renderviewbuilderjob.cpp \
+ $$PWD/renderviewcommandbuilderjob.cpp \
+ $$PWD/renderviewcommandupdaterjob.cpp \
$$PWD/renderviewinitializerjob.cpp \
$$PWD/renderviewjobutils.cpp
HEADERS += \
$$PWD/filtercompatibletechniquejob_p.h \
$$PWD/materialparametergathererjob_p.h \
- $$PWD/renderviewbuilderjob_p.h \
+ $$PWD/renderviewcommandbuilderjob_p.h \
+ $$PWD/renderviewcommandupdaterjob_p.h \
$$PWD/renderviewinitializerjob_p.h \
$$PWD/renderviewjobutils_p.h
diff --git a/src/render/renderers/opengl/jobs/materialparametergathererjob.cpp b/src/render/renderers/opengl/jobs/materialparametergathererjob.cpp
index 5e56e817f..e1f8aa403 100644
--- a/src/render/renderers/opengl/jobs/materialparametergathererjob.cpp
+++ b/src/render/renderers/opengl/jobs/materialparametergathererjob.cpp
@@ -63,7 +63,7 @@ MaterialParameterGathererJob::MaterialParameterGathererJob()
, m_techniqueFilter(nullptr)
, m_renderPassFilter(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::MaterialParameterGathering, materialParameterGathererCounter++);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::MaterialParameterGathering, materialParameterGathererCounter++)
}
// TechniqueFilter / RenderPassFilter
diff --git a/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp
new file mode 100644
index 000000000..091d49ef5
--- /dev/null
+++ b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderviewcommandbuilderjob_p.h"
+#include <Qt3DRender/private/job_common_p.h>
+#include <Qt3DRender/private/renderview_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+namespace {
+int renderViewInstanceCounter = 0;
+} // anonymous
+
+RenderViewCommandBuilderJob::RenderViewCommandBuilderJob()
+ : Qt3DCore::QAspectJob()
+ , m_offset(0)
+ , m_count(0)
+ , m_renderView(nullptr)
+{
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderViewCommandBuilder, renderViewInstanceCounter++)
+}
+
+void RenderViewCommandBuilderJob::run()
+{
+ if (!m_renderView->noDraw()) {
+ if (m_count == 0)
+ return;
+
+ const bool isDraw = !m_renderView->isCompute();
+ if (isDraw)
+ m_commandData = m_renderView->buildDrawRenderCommands(m_entities, m_offset, m_count);
+ else
+ m_commandData = m_renderView->buildComputeRenderCommands(m_entities, m_offset, m_count);
+ }
+}
+
+} // Render
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/renderers/opengl/jobs/renderviewbuilderjob_p.h b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h
index c38f788b0..556c7f241 100644
--- a/src/render/renderers/opengl/jobs/renderviewbuilderjob_p.h
+++ b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 Paul Lemire
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QT3DRENDER_RENDER_RENDERVIEWBUILDERJOB_P_H
-#define QT3DRENDER_RENDER_RENDERVIEWBUILDERJOB_P_H
+#ifndef QT3DRENDER_RENDER_RENDERVIEWCOMMANDBUILDERJOB_P_H
+#define QT3DRENDER_RENDER_RENDERVIEWCOMMANDBUILDERJOB_P_H
//
// W A R N I N G
@@ -53,6 +53,7 @@
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DRender/private/handle_types_p.h>
+#include <Qt3DRender/private/rendercommand_p.h>
QT_BEGIN_NAMESPACE
@@ -60,32 +61,31 @@ namespace Qt3DRender {
namespace Render {
-class RenderView;
-class Renderer;
-class RenderCommand;
-
-class Q_AUTOTEST_EXPORT RenderViewBuilderJob : public Qt3DCore::QAspectJob
+class Q_AUTOTEST_EXPORT RenderViewCommandBuilderJob : public Qt3DCore::QAspectJob
{
public:
- RenderViewBuilderJob();
+ RenderViewCommandBuilderJob();
inline void setRenderView(RenderView *rv) Q_DECL_NOTHROW { m_renderView = rv; }
- inline void setRenderer(Renderer *renderer) Q_DECL_NOTHROW { m_renderer = renderer; }
- inline void setIndex(int index) Q_DECL_NOTHROW { m_index = index; }
- inline void setRenderables(const QVector<Entity *> &renderables) Q_DECL_NOTHROW { m_renderables = renderables; }
- QVector<RenderCommand *> &commands() Q_DECL_NOTHROW { return m_commands; }
+ inline void setEntities(const QVector<Entity *> &entities, int offset, int count)
+ {
+ m_offset = offset;
+ m_count = count;
+ m_entities = entities;
+ }
+ inline EntityRenderCommandData &commandData() { return m_commandData; }
void run() final;
private:
+ int m_offset;
+ int m_count;
RenderView *m_renderView;
- Renderer *m_renderer;
- int m_index;
- QVector<Entity *> m_renderables;
- QVector<RenderCommand *> m_commands;
+ QVector<Entity *> m_entities;
+ EntityRenderCommandData m_commandData;
};
-typedef QSharedPointer<RenderViewBuilderJob> RenderViewBuilderJobPtr;
+typedef QSharedPointer<RenderViewCommandBuilderJob> RenderViewCommandBuilderJobPtr;
} // Render
@@ -93,4 +93,4 @@ typedef QSharedPointer<RenderViewBuilderJob> RenderViewBuilderJobPtr;
QT_END_NAMESPACE
-#endif // QT3DRENDER_RENDER_RENDERVIEWBUILDERJOB_P_H
+#endif // QT3DRENDER_RENDER_RENDERVIEWCOMMANDBUILDERJOB_P_H
diff --git a/src/render/renderers/opengl/jobs/renderviewbuilderjob.cpp b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
index 15154641e..6772279d7 100644
--- a/src/render/renderers/opengl/jobs/renderviewbuilderjob.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "renderviewbuilderjob_p.h"
+#include "renderviewcommandupdaterjob_p.h"
#include <Qt3DRender/private/job_common_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/renderview_p.h>
@@ -52,22 +52,26 @@ namespace {
int renderViewInstanceCounter = 0;
} // anonymous
-RenderViewBuilderJob::RenderViewBuilderJob()
- : Qt3DCore::QAspectJob(),
- m_renderView(nullptr)
+RenderViewCommandUpdaterJob::RenderViewCommandUpdaterJob()
+ : Qt3DCore::QAspectJob()
+ , m_offset(0)
+ , m_count(0)
+ , m_renderView(nullptr)
+ , m_renderer(nullptr)
+ , m_renderables()
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderViewBuilder, renderViewInstanceCounter++);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderCommandUpdater, renderViewInstanceCounter++)
}
-void RenderViewBuilderJob::run()
+void RenderViewCommandUpdaterJob::run()
{
// Build RenderCommand should perform the culling as we have no way to determine
// if a child has a mesh in the view frustum while its parent isn't contained in it.
if (!m_renderView->noDraw()) {
- if (!m_renderView->isCompute())
- m_commands = m_renderView->buildDrawRenderCommands(m_renderables);
- else
- m_commands = m_renderView->buildComputeRenderCommands(m_renderables);
+ if (m_count == 0)
+ return;
+ // Update Render Commands (Uniform Change, Depth Change)
+ m_renderView->updateRenderCommand(m_renderables.data(), m_offset, m_count);
}
}
diff --git a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h
new file mode 100644
index 000000000..d7f424966
--- /dev/null
+++ b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Paul Lemire
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_RENDERVIEWCOMMANDUPDATEJOB_P_H
+#define QT3DRENDER_RENDER_RENDERVIEWCOMMANDUPDATEJOB_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DRender/private/handle_types_p.h>
+#include <Qt3DRender/private/rendercommand_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class RenderView;
+class Renderer;
+
+class Q_AUTOTEST_EXPORT RenderViewCommandUpdaterJob : public Qt3DCore::QAspectJob
+{
+public:
+ RenderViewCommandUpdaterJob();
+
+ inline void setRenderView(RenderView *rv) Q_DECL_NOTHROW { m_renderView = rv; }
+ inline void setRenderer(Renderer *renderer) Q_DECL_NOTHROW { m_renderer = renderer; }
+ inline void setRenderables(const EntityRenderCommandDataPtr &renderables, int offset, int count) Q_DECL_NOTHROW
+ {
+ m_offset = offset;
+ m_count = count;
+ m_renderables = renderables;
+ }
+ EntityRenderCommandDataPtr renderables() const { return m_renderables; }
+
+ QVector<RenderCommand> &commands() Q_DECL_NOTHROW { return m_commands; }
+
+ void run() final;
+
+private:
+ int m_offset;
+ int m_count;
+ RenderView *m_renderView;
+ Renderer *m_renderer;
+ EntityRenderCommandDataPtr m_renderables;
+ QVector<RenderCommand> m_commands;
+};
+
+typedef QSharedPointer<RenderViewCommandUpdaterJob> RenderViewCommandUpdaterJobPtr;
+
+} // Render
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_RENDERVIEWCOMMANDUPDATEJOB_P_H
diff --git a/src/render/renderers/opengl/jobs/renderviewinitializerjob.cpp b/src/render/renderers/opengl/jobs/renderviewinitializerjob.cpp
index 7bf55be40..f0f72803c 100644
--- a/src/render/renderers/opengl/jobs/renderviewinitializerjob.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewinitializerjob.cpp
@@ -65,7 +65,7 @@ RenderViewInitializerJob::RenderViewInitializerJob()
, m_index(0)
, m_renderView(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderView, renderViewInstanceCounter++);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderView, renderViewInstanceCounter++)
}
RenderViewInitializerJob::~RenderViewInitializerJob()
diff --git a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
index cc211ba68..39917fb58 100644
--- a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
@@ -232,6 +232,7 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN
= static_cast<const Render::RenderSurfaceSelector *>(node);
rv->setSurface(surfaceSelector->surface());
rv->setSurfaceSize(surfaceSelector->renderTargetSize() * surfaceSelector->devicePixelRatio());
+ rv->setDevicePixelRatio(surfaceSelector->devicePixelRatio());
}
break;
}
@@ -487,7 +488,12 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData *
}
}
} else { // Array of scalar/vec qmlPropertyName[0]
- QString varName = blockName + QLatin1String(".") + qmlPropertyName + QLatin1String("[0]");
+ QString varName;
+ varName.reserve(blockName.length() + 1 + qmlPropertyName.length() + 3);
+ varName.append(blockName);
+ varName.append(QLatin1String("."));
+ varName.append(qmlPropertyName);
+ varName.append(QLatin1String("[0]"));
if (uniforms.contains(varName)) {
qCDebug(Shaders) << "UBO array member " << varName << " set for update";
activeUniformNamesToValue.insert(StringToInt::lookupId(varName), value);
@@ -505,7 +511,11 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData *
activeUniformNamesToValue.insert(varId, value);
}
} else { // Scalar / Vec
- QString varName = blockName + QLatin1Char('.') + qmlPropertyName;
+ QString varName;
+ varName.reserve(blockName.length() + 1 + qmlPropertyName.length());
+ varName.append(blockName);
+ varName.append(QLatin1String("."));
+ varName.append(qmlPropertyName);
if (uniforms.contains(varName)) {
qCDebug(Shaders) << "UBO scalar member " << varName << " set for update";
@@ -525,11 +535,15 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(Shader
const auto end = properties.end();
while (it != end) {
- const auto prefix = qmlPropertyName.isEmpty() ? QLatin1String("") : QLatin1String(".");
- buildActiveUniformNameValueMapHelper(rShaderData,
- blockName + prefix + qmlPropertyName,
- it.key(),
- it.value().value);
+ QString fullBlockName;
+ fullBlockName.reserve(blockName.length() + 1 + qmlPropertyName.length());
+ fullBlockName.append(blockName);
+ if (!qmlPropertyName.isEmpty()) {
+ fullBlockName.append(QLatin1String("."));
+ fullBlockName.append(qmlPropertyName);
+ }
+ buildActiveUniformNameValueMapHelper(rShaderData, fullBlockName,
+ it.key(), it.value().value);
++it;
}
}
diff --git a/src/render/renderers/opengl/renderer/rendercommand.cpp b/src/render/renderers/opengl/renderer/rendercommand.cpp
index e60b17668..072127391 100644
--- a/src/render/renderers/opengl/renderer/rendercommand.cpp
+++ b/src/render/renderers/opengl/renderer/rendercommand.cpp
@@ -48,6 +48,7 @@ RenderCommand::RenderCommand()
: m_stateSet(nullptr)
, m_depth(0.0f)
, m_changeCost(0)
+ , m_shaderDna(0)
, m_type(RenderCommand::Draw)
, m_primitiveCount(0)
, m_primitiveType(QGeometryRenderer::Triangles)
@@ -70,6 +71,20 @@ RenderCommand::RenderCommand()
m_workGroups[2] = 0;
}
+bool operator==(const RenderCommand &a, const RenderCommand &b) noexcept
+{
+ return (a.m_vao == b.m_vao && a.m_shader == b.m_shader && a.m_material == b.m_material &&
+ a.m_stateSet == b.m_stateSet && a.m_geometry == b.m_geometry && a.m_geometryRenderer == b.m_geometryRenderer &&
+ a.m_indirectDrawBuffer == b.m_indirectDrawBuffer && a.m_activeAttributes == b.m_activeAttributes &&
+ a.m_depth == b.m_depth && a.m_changeCost == b.m_changeCost && a.m_shaderDna == b.m_shaderDna &&
+ a.m_workGroups[0] == b.m_workGroups[0] && a.m_workGroups[1] == b.m_workGroups[1] && a.m_workGroups[2] == b.m_workGroups[2] &&
+ a.m_primitiveCount == b.m_primitiveCount && a.m_primitiveType == b.m_primitiveType && a.m_restartIndexValue == b.m_restartIndexValue &&
+ a.m_firstInstance == b.m_firstInstance && a.m_firstVertex == b.m_firstVertex && a.m_verticesPerPatch == b.m_verticesPerPatch &&
+ a.m_instanceCount == b.m_instanceCount && a.m_indexOffset == b.m_indexOffset && a.m_indexAttributeByteOffset == b.m_indexAttributeByteOffset &&
+ a.m_drawIndexed == b.m_drawIndexed && a.m_drawIndirect == b.m_drawIndirect && a.m_primitiveRestartEnabled == b.m_primitiveRestartEnabled &&
+ a.m_isValid == b.m_isValid && a.m_computeCommand == b.m_computeCommand);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/renderers/opengl/renderer/rendercommand_p.h b/src/render/renderers/opengl/renderer/rendercommand_p.h
index 61cc6d17d..be00fb753 100644
--- a/src/render/renderers/opengl/renderer/rendercommand_p.h
+++ b/src/render/renderers/opengl/renderer/rendercommand_p.h
@@ -55,6 +55,7 @@
#include <qglobal.h>
#include <Qt3DRender/private/shaderparameterpack_p.h>
#include <Qt3DRender/private/handle_types_p.h>
+#include <Qt3DRender/private/renderviewjobutils_p.h>
#include <Qt3DRender/qgeometryrenderer.h>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
@@ -69,6 +70,7 @@ namespace Qt3DRender {
namespace Render {
class RenderStateSet;
+using RenderStateSetPtr = QSharedPointer<RenderStateSet>;
class Q_AUTOTEST_EXPORT RenderCommand
{
@@ -80,12 +82,13 @@ public:
HMaterial m_material; // Purely used to ease sorting (minimize stage changes, binding changes ....)
ShaderParameterPack m_parameterPack; // Might need to be reworked so as to be able to destroy the
// Texture while submission is happening.
- RenderStateSet *m_stateSet;
+ RenderStateSetPtr m_stateSet;
HGeometry m_geometry;
HGeometryRenderer m_geometryRenderer;
HBuffer m_indirectDrawBuffer; // Reference to indirect draw buffer (valid only m_drawIndirect == true)
+ HComputeCommand m_computeCommand;
// A QAttribute pack might be interesting
// This is a temporary fix in the meantime, to remove the hacked methods in Technique
@@ -121,6 +124,53 @@ public:
bool m_isValid;
};
+Q_AUTOTEST_EXPORT bool operator==(const RenderCommand &a, const RenderCommand &b) noexcept;
+
+inline bool operator!=(const RenderCommand &lhs, const RenderCommand &rhs) noexcept
+{ return !operator==(lhs, rhs); }
+
+struct EntityRenderCommandData
+{
+ QVector<Entity *> entities;
+ QVector<RenderCommand> commands;
+ QVector<RenderPassParameterData> passesData;
+
+ void reserve(int size)
+ {
+ entities.reserve(size);
+ commands.reserve(size);
+ passesData.reserve(size);
+ }
+
+ inline int size() const { return entities.size(); }
+
+ inline void push_back(Entity *e, const RenderCommand &c, const RenderPassParameterData &p)
+ {
+ entities.push_back(e);
+ commands.push_back(c);
+ passesData.push_back(p);
+ }
+
+ inline void push_back(Entity *e, RenderCommand &&c, RenderPassParameterData &&p)
+ {
+ entities.push_back(e);
+ commands.push_back(std::move(c));
+ passesData.push_back(std::move(p));
+ }
+
+ EntityRenderCommandData &operator+=(EntityRenderCommandData &&t)
+ {
+ entities += std::move(t.entities);
+ commands += std::move(t.commands);
+ passesData += std::move(t.passesData);
+ return *this;
+ }
+
+};
+
+using EntityRenderCommandDataPtr = QSharedPointer<EntityRenderCommandData>;
+
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index 121a6aa8f..ddf57f4fe 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -93,15 +93,15 @@
#include <Qt3DRender/private/subtreeenabler_p.h>
#include <Qt3DRender/private/qshaderprogrambuilder_p.h>
#include <Qt3DRender/private/qshaderprogram_p.h>
+#include <Qt3DRender/private/filterentitybycomponentjob_p.h>
+#include <Qt3DRender/private/commandexecuter_p.h>
#include <Qt3DRender/qcameralens.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
-
-#if QT_CONFIG(qt3d_profile_jobs)
-#include <Qt3DCore/private/aspectcommanddebugger_p.h>
-#endif
+#include <Qt3DCore/private/qsysteminformationservice_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p_p.h>
#include <QStack>
#include <QOffscreenSurface>
@@ -114,19 +114,9 @@
#include <QUrl>
#include <QOffscreenSurface>
#include <QWindow>
-
-#include <QtGui/private/qopenglcontext_p.h>
-
-// For Debug purposes only
#include <QThread>
-
-#if QT_CONFIG(qt3d_profile_jobs)
-#include <Qt3DCore/private/qthreadpooler_p.h>
-#include <Qt3DRender/private/job_common_p.h>
-#include <Qt3DRender/private/commandexecuter_p.h>
-#endif
-
+#include <QtGui/private/qopenglcontext_p.h>
#include <Qt3DRender/private/frameprofiler_p.h>
QT_BEGIN_NAMESPACE
@@ -138,6 +128,82 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
+
+namespace {
+
+class SyncLightsGatherer
+{
+public:
+ explicit SyncLightsGatherer(LightGathererPtr gatherJob,
+ RendererCache *cache)
+ : m_gatherJob(gatherJob)
+ , m_cache(cache)
+ {
+ }
+
+ void operator()()
+ {
+ QMutexLocker lock(m_cache->mutex());
+ m_cache->gatheredLights = m_gatherJob->lights();
+ m_cache->environmentLight = m_gatherJob->takeEnvironmentLight();
+ }
+
+private:
+ LightGathererPtr m_gatherJob;
+ RendererCache *m_cache;
+};
+
+class SyncRenderableEntities
+{
+public:
+ explicit SyncRenderableEntities(RenderableEntityFilterPtr gatherJob,
+ RendererCache *cache)
+ : m_gatherJob(gatherJob)
+ , m_cache(cache)
+ {
+ }
+
+ void operator()()
+ {
+ QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities();
+ std::sort(selectedEntities.begin(), selectedEntities.end());
+
+ QMutexLocker lock(m_cache->mutex());
+ m_cache->renderableEntities = selectedEntities;
+ }
+
+private:
+ RenderableEntityFilterPtr m_gatherJob;
+ RendererCache *m_cache;
+};
+
+class SyncComputableEntities
+{
+public:
+ explicit SyncComputableEntities(ComputableEntityFilterPtr gatherJob,
+ RendererCache *cache)
+ : m_gatherJob(gatherJob)
+ , m_cache(cache)
+ {
+ }
+
+ void operator()()
+ {
+ QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities();
+ std::sort(selectedEntities.begin(), selectedEntities.end());
+
+ QMutexLocker lock(m_cache->mutex());
+ m_cache->computeEntities = selectedEntities;
+ }
+
+private:
+ ComputableEntityFilterPtr m_gatherJob;
+ RendererCache *m_cache;
+};
+
+} // anonymous
+
+
/*!
\internal
@@ -186,31 +252,33 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_calculateBoundingVolumeJob(Render::CalculateBoundingVolumeJobPtr::create())
, m_updateWorldBoundingVolumeJob(Render::UpdateWorldBoundingVolumeJobPtr::create())
, m_updateTreeEnabledJob(Render::UpdateTreeEnabledJobPtr::create())
- , m_sendRenderCaptureJob(Render::SendRenderCaptureJobPtr::create())
, m_sendBufferCaptureJob(Render::SendBufferCaptureJobPtr::create())
, m_updateSkinningPaletteJob(Render::UpdateSkinningPaletteJobPtr::create())
, m_updateLevelOfDetailJob(Render::UpdateLevelOfDetailJobPtr::create())
, m_updateMeshTriangleListJob(Render::UpdateMeshTriangleListJobPtr::create())
, m_filterCompatibleTechniqueJob(Render::FilterCompatibleTechniqueJobPtr::create())
, m_updateEntityLayersJob(Render::UpdateEntityLayersJobPtr::create())
+ , m_lightGathererJob(Render::LightGathererPtr::create())
+ , m_renderableEntityFilterJob(Render::RenderableEntityFilterPtr::create())
+ , m_computableEntityFilterJob(Render::ComputableEntityFilterPtr::create())
, m_bufferGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering))
, m_vaoGathererJob(SynchronizerJobPtr::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
, m_textureGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
- , m_sendTextureChangesToFrontendJob(SynchronizerPostFramePtr::create([] {},
- [this] (Qt3DCore::QAspectManager *m) { sendTextureChangesToFrontend(m); },
- JobTypes::SendTextureChangesToFrontend))
, m_sendSetFenceHandlesToFrontendJob(SynchronizerJobPtr::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend))
- , m_sendDisablesToFrontendJob(SynchronizerJobPtr::create([this] { sendDisablesToFrontend(); }, JobTypes::SendDisablesToFrontend))
, m_introspectShaderJob(SynchronizerPostFramePtr::create([this] { reloadDirtyShaders(); },
[this] (Qt3DCore::QAspectManager *m) { sendShaderChangesToFrontend(m); },
JobTypes::DirtyShaderGathering))
, m_syncLoadingJobs(SynchronizerJobPtr::create([] {}, JobTypes::SyncLoadingJobs))
+ , m_cacheRenderableEntitiesJob(SynchronizerJobPtr::create(SyncRenderableEntities(m_renderableEntityFilterJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
+ , m_cacheComputableEntitiesJob(SynchronizerJobPtr::create(SyncComputableEntities(m_computableEntityFilterJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
+ , m_cacheLightsJob(SynchronizerJobPtr::create(SyncLightsGatherer(m_lightGathererJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
, m_ownedContext(false)
, m_offscreenHelper(nullptr)
- , m_shouldSwapBuffers(true)
- #if QT_CONFIG(qt3d_profile_jobs)
, m_commandExecuter(new Qt3DRender::Debug::CommandExecuter(this))
- #endif
+ , m_shouldSwapBuffers(true)
{
// Set renderer as running - it will wait in the context of the
// RenderThread for RenderViews to be submitted
@@ -238,6 +306,10 @@ Renderer::Renderer(QRenderAspect::RenderType type)
m_introspectShaderJob->addDependency(m_filterCompatibleTechniqueJob);
+ m_cacheLightsJob->addDependency(m_lightGathererJob);
+ m_cacheRenderableEntitiesJob->addDependency(m_renderableEntityFilterJob);
+ m_cacheComputableEntitiesJob->addDependency(m_computableEntityFilterJob);
+
m_filterCompatibleTechniqueJob->setRenderer(this);
m_defaultRenderStateSet = new RenderStateSet;
@@ -299,13 +371,16 @@ void Renderer::setNodeManagers(NodeManagers *managers)
m_pickBoundingVolumeJob->setManagers(m_nodesManager);
m_rayCastingJob->setManagers(m_nodesManager);
m_updateWorldBoundingVolumeJob->setManager(m_nodesManager->renderNodesManager());
- m_sendRenderCaptureJob->setManagers(m_nodesManager);
m_updateLevelOfDetailJob->setManagers(m_nodesManager);
m_updateSkinningPaletteJob->setManagers(m_nodesManager);
m_updateMeshTriangleListJob->setManagers(m_nodesManager);
m_filterCompatibleTechniqueJob->setManager(m_nodesManager->techniqueManager());
m_updateEntityLayersJob->setManager(m_nodesManager);
m_updateTreeEnabledJob->setManagers(m_nodesManager);
+ m_sendBufferCaptureJob->setManagers(m_nodesManager);
+ m_lightGathererJob->setManager(m_nodesManager->renderNodesManager());
+ m_renderableEntityFilterJob->setManager(m_nodesManager->renderNodesManager());
+ m_computableEntityFilterJob->setManager(m_nodesManager->renderNodesManager());
}
void Renderer::setServices(QServiceLocator *services)
@@ -338,7 +413,7 @@ QOpenGLContext *Renderer::shareContext() const
// Executed in the reloadDirtyShader job
void Renderer::loadShader(Shader *shader, HShader shaderHandle)
{
- Q_UNUSED(shader);
+ Q_UNUSED(shader)
m_dirtyShaders.push_back(shaderHandle);
}
@@ -432,6 +507,9 @@ void Renderer::initialize()
m_waitForInitializationToBeCompleted.release(1);
// Allow the aspect manager to proceed
m_vsyncFrameAdvanceService->proceedToNextFrame();
+
+ // Force initial refresh
+ markDirty(AllDirty, nullptr);
}
/*!
@@ -653,19 +731,12 @@ void Renderer::doRender(bool swapBuffers)
// RenderQueue is complete (but that means it may be of size 0)
if (canSubmit && (queueIsComplete && !queueIsEmpty)) {
const QVector<Render::RenderView *> renderViews = m_renderQueue->nextFrameQueue();
-
-#if QT_CONFIG(qt3d_profile_jobs)
- // Save start of frame
- JobRunStats submissionStatsPart1;
- JobRunStats submissionStatsPart2;
- submissionStatsPart1.jobId.typeAndInstance[0] = JobTypes::FrameSubmissionPart1;
- submissionStatsPart1.jobId.typeAndInstance[1] = 0;
- submissionStatsPart1.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
- submissionStatsPart1.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- submissionStatsPart2.jobId.typeAndInstance[0] = JobTypes::FrameSubmissionPart2;
- submissionStatsPart2.jobId.typeAndInstance[1] = 0;
- submissionStatsPart2.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
-#endif
+ QTaskLogger submissionStatsPart1(m_services->systemInformation(),
+ {JobTypes::FrameSubmissionPart1, 0},
+ QTaskLogger::Submission);
+ QTaskLogger submissionStatsPart2(m_services->systemInformation(),
+ {JobTypes::FrameSubmissionPart2, 0},
+ QTaskLogger::Submission);
if (canRender()) {
{ // Scoped to destroy surfaceLock
@@ -698,15 +769,11 @@ void Renderer::doRender(bool swapBuffers)
m_vsyncFrameAdvanceService->proceedToNextFrame();
hasCleanedQueueAndProceeded = true;
-#if QT_CONFIG(qt3d_profile_jobs)
- if (preprocessingComplete) {
- submissionStatsPart2.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- submissionStatsPart1.endTime = submissionStatsPart2.startTime;
- }
-#endif
// Only try to submit the RenderViews if the preprocessing was successful
// This part of the submission is happening in parallel to the RV building for the next frame
if (preprocessingComplete) {
+ submissionStatsPart1.end(submissionStatsPart2.restart());
+
// 3) Submit the render commands for frame n (making sure we never reference something that could be changing)
// Render using current device state and renderer configuration
submissionData = submitRenderViews(renderViews);
@@ -716,33 +783,18 @@ void Renderer::doRender(bool swapBuffers)
}
}
-#if QT_CONFIG(qt3d_profile_jobs)
// Execute the pending shell commands
m_commandExecuter->performAsynchronousCommandExecution(renderViews);
-#endif
// Delete all the RenderViews which will clear the allocators
// that were used for their allocation
qDeleteAll(renderViews);
-
-#if QT_CONFIG(qt3d_profile_jobs)
- if (preprocessingComplete) {
- // Save submission elapsed time
- submissionStatsPart2.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- // Note this is safe since proceedToNextFrame is the one going to trigger
- // the write to the file, and this is performed after this step
- Qt3DCore::QThreadPooler::addSubmissionLogStatsEntry(submissionStatsPart1);
- Qt3DCore::QThreadPooler::addSubmissionLogStatsEntry(submissionStatsPart2);
- Profiling::GLTimeRecorder::writeResults();
- }
-#endif
}
// If hasCleanedQueueAndProceeded isn't true this implies that something went wrong
// with the rendering and/or the renderqueue is incomplete from some reason
// or alternatively it could be complete but empty (RenderQueue of size 0)
-
if (!hasCleanedQueueAndProceeded) {
// RenderQueue was full but something bad happened when
// trying to render it and therefore proceedToNextFrame was not called
@@ -830,12 +882,7 @@ bool Renderer::isReadyToSubmit()
// Main thread
QVariant Renderer::executeCommand(const QStringList &args)
{
-#if QT_CONFIG(qt3d_profile_jobs)
return m_commandExecuter->executeCommand(args);
-#else
- Q_UNUSED(args);
-#endif
- return QVariant();
}
/*!
@@ -860,13 +907,13 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
QHash<HVao, bool> updatedTable;
for (RenderView *rv: renderViews) {
- const QVector<RenderCommand *> commands = rv->commands();
- for (RenderCommand *command : commands) {
+ QVector<RenderCommand> &commands = rv->commands();
+ for (RenderCommand &command : commands) {
// Update/Create VAO
- if (command->m_type == RenderCommand::Draw) {
- Geometry *rGeometry = m_nodesManager->data<Geometry, GeometryManager>(command->m_geometry);
- GeometryRenderer *rGeometryRenderer = m_nodesManager->data<GeometryRenderer, GeometryRendererManager>(command->m_geometryRenderer);
- Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command->m_shader);
+ if (command.m_type == RenderCommand::Draw) {
+ Geometry *rGeometry = m_nodesManager->data<Geometry, GeometryManager>(command.m_geometry);
+ GeometryRenderer *rGeometryRenderer = m_nodesManager->data<GeometryRenderer, GeometryRendererManager>(command.m_geometryRenderer);
+ Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command.m_shader);
// We should never have inserted a command for which these are null
// in the first place
@@ -879,15 +926,15 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
// Create VAO or return already created instance associated with command shader/geometry
// (VAO is emulated if not supported)
- createOrUpdateVAO(command, &vaoHandle, &vao);
- command->m_vao = vaoHandle;
+ createOrUpdateVAO(&command, &vaoHandle, &vao);
+ command.m_vao = vaoHandle;
// Avoids redoing the same thing for the same VAO
if (!updatedTable.contains(vaoHandle)) {
updatedTable.insert(vaoHandle, true);
// Do we have any attributes that are dirty ?
- const bool requiresPartialVAOUpdate = requiresVAOAttributeUpdate(rGeometry, command);
+ const bool requiresPartialVAOUpdate = requiresVAOAttributeUpdate(rGeometry, &command);
// If true, we need to reupload all attributes to set the VAO
// Otherwise only dirty attributes will be updates
@@ -898,7 +945,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
if (rGeometry->isDirty())
m_dirtyGeometry.push_back(rGeometry);
- if (!command->m_activeAttributes.isEmpty() && (requiresFullVAOUpdate || requiresPartialVAOUpdate)) {
+ if (!command.m_activeAttributes.isEmpty() && (requiresFullVAOUpdate || requiresPartialVAOUpdate)) {
Profiling::GLTimeRecorder recorder(Profiling::VAOUpload);
// Activate shader
m_submissionContext->activateShader(shader->dna());
@@ -906,7 +953,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
vao->bind();
// Update or set Attributes and Buffers for the given rGeometry and Command
// Note: this fills m_dirtyAttributes as well
- if (updateVAOWithAttributes(rGeometry, command, shader, requiresFullVAOUpdate))
+ if (updateVAOWithAttributes(rGeometry, &command, shader, requiresFullVAOUpdate))
vao->setSpecified(true);
}
}
@@ -918,82 +965,14 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
rGeometryRenderer->unsetDirty();
// Prepare the ShaderParameterPack based on the active uniforms of the shader
- shader->prepareUniforms(command->m_parameterPack);
-
- { // Scoped to show extent
- command->m_isValid = !command->m_activeAttributes.empty();
- if (!command->m_isValid)
- continue;
-
- // Update the draw command with what's going to be needed for the drawing
- uint primitiveCount = rGeometryRenderer->vertexCount();
- uint estimatedCount = 0;
- Attribute *indexAttribute = nullptr;
- Attribute *indirectAttribute = nullptr;
-
- const QVector<Qt3DCore::QNodeId> attributeIds = rGeometry->attributes();
- for (Qt3DCore::QNodeId attributeId : attributeIds) {
- Attribute *attribute = m_nodesManager->attributeManager()->lookupResource(attributeId);
- switch (attribute->attributeType()) {
- case QAttribute::IndexAttribute:
- indexAttribute = attribute;
- break;
- case QAttribute::DrawIndirectAttribute:
- indirectAttribute = attribute;
- break;
- case QAttribute::VertexAttribute: {
- if (command->m_activeAttributes.contains(attribute->nameId()))
- estimatedCount = qMax(attribute->count(), estimatedCount);
- break;
- }
- default:
- Q_UNREACHABLE();
- break;
- }
- }
-
- command->m_drawIndexed = (indexAttribute != nullptr);
- command->m_drawIndirect = (indirectAttribute != nullptr);
-
- // Update the draw command with all the information required for the drawing
- if (command->m_drawIndexed) {
- command->m_indexAttributeDataType = GraphicsContext::glDataTypeFromAttributeDataType(indexAttribute->vertexBaseType());
- command->m_indexAttributeByteOffset = indexAttribute->byteOffset() + rGeometryRenderer->indexBufferByteOffset();
- }
-
- // Note: we only care about the primitiveCount when using direct draw calls
- // For indirect draw calls it is assumed the buffer was properly set already
- if (command->m_drawIndirect) {
- command->m_indirectAttributeByteOffset = indirectAttribute->byteOffset();
- command->m_indirectDrawBuffer = m_nodesManager->bufferManager()->lookupHandle(indirectAttribute->bufferId());
- } else {
- // Use the count specified by the GeometryRender
- // If not specify use the indexAttribute count if present
- // Otherwise tries to use the count from the attribute with the highest count
- if (primitiveCount == 0) {
- if (indexAttribute)
- primitiveCount = indexAttribute->count();
- else
- primitiveCount = estimatedCount;
- }
- }
+ shader->prepareUniforms(command.m_parameterPack);
- command->m_primitiveCount = primitiveCount;
- command->m_primitiveType = rGeometryRenderer->primitiveType();
- command->m_primitiveRestartEnabled = rGeometryRenderer->primitiveRestartEnabled();
- command->m_restartIndexValue = rGeometryRenderer->restartIndexValue();
- command->m_firstInstance = rGeometryRenderer->firstInstance();
- command->m_instanceCount = rGeometryRenderer->instanceCount();
- command->m_firstVertex = rGeometryRenderer->firstVertex();
- command->m_indexOffset = rGeometryRenderer->indexOffset();
- command->m_verticesPerPatch = rGeometryRenderer->verticesPerPatch();
- } // scope
- } else if (command->m_type == RenderCommand::Compute) {
- Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command->m_shader);
+ } else if (command.m_type == RenderCommand::Compute) {
+ Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command.m_shader);
Q_ASSERT(shader);
// Prepare the ShaderParameterPack based on the active uniforms of the shader
- shader->prepareUniforms(command->m_parameterPack);
+ shader->prepareUniforms(command.m_parameterPack);
}
}
}
@@ -1042,6 +1021,7 @@ void Renderer::lookForDirtyBuffers()
}
}
+// Called in prepareSubmission
void Renderer::lookForDownloadableBuffers()
{
m_downloadableBuffers.clear();
@@ -1049,7 +1029,7 @@ void Renderer::lookForDownloadableBuffers()
for (const HBuffer &handle : activeBufferHandles) {
Buffer *buffer = m_nodesManager->bufferManager()->data(handle);
if (buffer->access() & QBuffer::Read)
- m_downloadableBuffers.push_back(handle);
+ m_downloadableBuffers.push_back(buffer->peerId());
}
}
@@ -1106,7 +1086,7 @@ void Renderer::reloadDirtyShaders()
// If api of the renderer matches the one from the technique
if (technique->isCompatibleWithRenderer()) {
const auto passIds = technique->renderPasses();
- for (const QNodeId passId : passIds) {
+ for (const QNodeId &passId : passIds) {
RenderPass *renderPass = m_nodesManager->renderPassManager()->lookupResource(passId);
HShader shaderHandle = m_nodesManager->shaderManager()->lookupHandle(renderPass->shaderProgram());
Shader *shader = m_nodesManager->shaderManager()->data(shaderHandle);
@@ -1146,7 +1126,7 @@ void Renderer::reloadDirtyShaders()
}
}
-// Executed in job postFrame
+// Executed in job (in main thread when jobs are done)
void Renderer::sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager)
{
Q_ASSERT(isRunning());
@@ -1173,14 +1153,13 @@ void Renderer::sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager)
}
}
-// Executed in a job (as postFrame)
+// Executed in a job (in main thread when jobs are done)
void Renderer::sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager)
{
const QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> updateTextureProperties = std::move(m_updatedTextureProperties);
for (const auto &pair : updateTextureProperties) {
const Qt3DCore::QNodeIdVector targetIds = pair.second;
- for (const Qt3DCore::QNodeId targetId: targetIds) {
-
+ for (const Qt3DCore::QNodeId &targetId: targetIds) {
// Lookup texture
Texture *t = m_nodesManager->textureManager()->lookupResource(targetId);
// If backend texture is Dirty, some property has changed and the properties we are
@@ -1226,17 +1205,24 @@ void Renderer::sendSetFenceHandlesToFrontend()
}
}
-// Executed in a job
-void Renderer::sendDisablesToFrontend()
+// Executed in a job (in main thread when jobs done)
+void Renderer::sendDisablesToFrontend(Qt3DCore::QAspectManager *manager)
{
- const auto updatedDisables = std::move(m_updatedDisables);
- FrameGraphManager *fgManager = m_nodesManager->frameGraphManager();
+ // SubtreeEnabled
+ const auto updatedDisables = std::move(m_updatedDisableSubtreeEnablers);
for (const auto &nodeId : updatedDisables) {
- FrameGraphNode *fgNode = fgManager->lookupNode(nodeId);
- if (fgNode != nullptr) { // Node could have been deleted before we got a chance to notify it
- Q_ASSERT(fgNode->nodeType() == FrameGraphNode::SubtreeEnabler);
- SubtreeEnabler *enabler = static_cast<SubtreeEnabler *>(fgNode);
- enabler->sendDisableToFrontend();
+ QSubtreeEnabler *frontend = static_cast<decltype(frontend)>(manager->lookupNode(nodeId));
+ frontend->setEnabled(false);
+ }
+
+ // Compute Commands
+ const QVector<HComputeCommand> activeCommands = m_nodesManager->computeJobManager()->activeHandles();
+ for (const HComputeCommand &handle :activeCommands) {
+ ComputeCommand *c = m_nodesManager->computeJobManager()->data(handle);
+ if (c->hasReachedFrameCount()) {
+ QComputeCommand *frontend = static_cast<decltype(frontend)>(manager->lookupNode(c->peerId()));
+ frontend->setEnabled(false);
+ c->resetHasReachedFrameCount();
}
}
}
@@ -1355,6 +1341,9 @@ void Renderer::updateGLResources()
// Record ids of texture to cleanup while we are still blocking the aspect thread
m_textureIdsToCleanup += m_nodesManager->textureManager()->takeTexturesIdsToCleanup();
}
+
+ // Record list of buffer that might need uploading
+ lookForDownloadableBuffers();
}
// Render Thread
@@ -1437,12 +1426,18 @@ void Renderer::cleanupTexture(Qt3DCore::QNodeId cleanedUpTextureId)
// Called by SubmitRenderView
void Renderer::downloadGLBuffers()
{
- lookForDownloadableBuffers();
- const QVector<HBuffer> downloadableHandles = std::move(m_downloadableBuffers);
- for (const HBuffer &handle : downloadableHandles) {
- Buffer *buffer = m_nodesManager->bufferManager()->data(handle);
- QByteArray content = m_submissionContext->downloadBufferContent(buffer);
- m_sendBufferCaptureJob->addRequest(QPair<Buffer*, QByteArray>(buffer, content));
+ const QVector<Qt3DCore::QNodeId> downloadableHandles = std::move(m_downloadableBuffers);
+ for (const Qt3DCore::QNodeId &bufferId : downloadableHandles) {
+ BufferManager *bufferManager = m_nodesManager->bufferManager();
+ BufferManager::ReadLocker locker(const_cast<const BufferManager *>(bufferManager));
+ Buffer *buffer = bufferManager->lookupResource(bufferId);
+ // Buffer could have been destroyed at this point
+ if (!buffer)
+ continue;
+ // locker is protecting us from the buffer being destroy while we're looking
+ // up its content
+ const QByteArray content = m_submissionContext->downloadBufferContent(buffer);
+ m_sendBufferCaptureJob->addRequest(QPair<Qt3DCore::QNodeId, QByteArray>(bufferId, content));
}
}
@@ -1606,7 +1601,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
}
// Set the Viewport
- m_submissionContext->setViewport(renderView->viewport(), renderView->surfaceSize() * renderView->devicePixelRatio());
+ m_submissionContext->setViewport(renderView->viewport(), renderView->surfaceSize());
// Execute the render commands
if (!executeCommandsSubmission(renderView))
@@ -1617,7 +1612,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
// renderViewStateSet or m_defaultRenderStateSet)
if (!renderView->renderCaptureNodeId().isNull()) {
const QRenderCaptureRequest request = renderView->renderCaptureRequest();
- const QSize size = m_submissionContext->renderTargetSize(renderView->surfaceSize() * renderView->devicePixelRatio());
+ const QSize size = m_submissionContext->renderTargetSize(renderView->surfaceSize());
QRect rect(QPoint(0, 0), size);
if (!request.rect.isEmpty())
rect = rect.intersected(request.rect);
@@ -1632,7 +1627,8 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
Render::RenderCapture *renderCapture =
static_cast<Render::RenderCapture*>(m_nodesManager->frameGraphManager()->lookupNode(renderView->renderCaptureNodeId()));
renderCapture->addRenderCapture(request.captureId, image);
- addRenderCaptureSendRequest(renderView->renderCaptureNodeId());
+ if (!m_pendingRenderCaptureSendRequests.contains(renderView->renderCaptureNodeId()))
+ m_pendingRenderCaptureSendRequests.push_back(renderView->renderCaptureNodeId());
}
if (renderView->isDownloadBuffersEnable())
@@ -1688,7 +1684,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
void Renderer::markDirty(BackendNodeDirtySet changes, BackendNode *node)
{
- Q_UNUSED(node);
+ Q_UNUSED(node)
m_dirtyBits.marked |= changes;
}
@@ -1705,12 +1701,11 @@ void Renderer::clearDirtyBits(BackendNodeDirtySet changes)
}
#endif
-bool Renderer::shouldRender()
+bool Renderer::shouldRender() const
{
// Only render if something changed during the last frame, or the last frame
// was not rendered successfully (or render-on-demand is disabled)
return (m_settings->renderPolicy() == QRenderSettings::Always
- || m_renderThread == nullptr // <==> we use Scene3D
|| m_dirtyBits.marked != 0
|| m_dirtyBits.remaining != 0
|| !m_lastFrameCorrect.loadRelaxed());
@@ -1725,24 +1720,34 @@ void Renderer::skipNextFrame()
m_submitRenderViewsSemaphore.release(1);
}
-// Jobs we may have to run even if no rendering will happen
-QVector<QAspectJobPtr> Renderer::preRenderingJobs()
+void Renderer::jobsDone(Qt3DCore::QAspectManager *manager)
{
- QVector<QAspectJobPtr> jobs;
+ // called in main thread once all jobs are done running
+
+ // sync captured renders to frontend
+ const QVector<Qt3DCore::QNodeId> pendingCaptureIds = std::move(m_pendingRenderCaptureSendRequests);
+ for (const Qt3DCore::QNodeId &id : qAsConst(pendingCaptureIds)) {
+ auto *backend = static_cast<Qt3DRender::Render::RenderCapture *>
+ (m_nodesManager->frameGraphManager()->lookupNode(id));
+ backend->syncRenderCapturesToFrontend(manager);
+ }
// Do we need to notify any texture about property changes?
if (m_updatedTextureProperties.size() > 0)
- jobs.push_back(m_sendTextureChangesToFrontendJob);
+ sendTextureChangesToFrontend(manager);
+
+ sendDisablesToFrontend(manager);
+}
+
+// Jobs we may have to run even if no rendering will happen
+QVector<QAspectJobPtr> Renderer::preRenderingJobs()
+{
+ QVector<QAspectJobPtr> jobs;
// Do we need to notify frontend about fence change?
if (m_updatedSetFences.size() > 0)
jobs.push_back(m_sendSetFenceHandlesToFrontendJob);
- const QVector<Qt3DCore::QNodeId> pendingCaptureIds = takePendingRenderCaptureSendRequests();
- if (pendingCaptureIds.size() > 0) {
- m_sendRenderCaptureJob->setPendingCaptureRequests(pendingCaptureIds);
- jobs.push_back(m_sendRenderCaptureJob);
- }
if (m_sendBufferCaptureJob->hasRequests())
jobs.push_back(m_sendBufferCaptureJob);
@@ -1759,7 +1764,6 @@ QVector<QAspectJobPtr> Renderer::preRenderingJobs()
QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
{
QVector<QAspectJobPtr> renderBinJobs;
-
// Create the jobs to build the frame
const QVector<QAspectJobPtr> bufferJobs = createRenderBufferJobs();
@@ -1774,9 +1778,9 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
m_updateLevelOfDetailJob->setFrameGraphRoot(frameGraphRoot());
const BackendNodeDirtySet dirtyBitsForFrame = m_dirtyBits.marked | m_dirtyBits.remaining;
- m_dirtyBits.marked = 0;
- m_dirtyBits.remaining = 0;
- BackendNodeDirtySet notCleared = 0;
+ m_dirtyBits.marked = {};
+ m_dirtyBits.remaining = {};
+ BackendNodeDirtySet notCleared = {};
// Add jobs
const bool entitiesEnabledDirty = dirtyBitsForFrame & AbstractRenderer::EntityEnabledDirty;
@@ -1810,7 +1814,6 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
renderBinJobs.push_back(m_updateSkinningPaletteJob);
renderBinJobs.push_back(m_updateLevelOfDetailJob);
renderBinJobs.push_back(m_cleanupJob);
-
renderBinJobs.append(bufferJobs);
// Jobs to prepare GL Resource upload
@@ -1834,11 +1837,27 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
const bool computeableDirty = dirtyBitsForFrame & AbstractRenderer::ComputeDirty;
const bool renderableDirty = dirtyBitsForFrame & AbstractRenderer::GeometryDirty;
const bool materialCacheNeedsToBeRebuilt = shadersDirty || materialDirty || frameGraphDirty;
+ const bool renderCommandsDirty = materialCacheNeedsToBeRebuilt || renderableDirty || computeableDirty;
// Rebuild Entity Layers list if layers are dirty
if (layersDirty)
renderBinJobs.push_back(m_updateEntityLayersJob);
+ if (renderableDirty) {
+ renderBinJobs.push_back(m_renderableEntityFilterJob);
+ renderBinJobs.push_back(m_cacheRenderableEntitiesJob);
+ }
+
+ if (computeableDirty) {
+ renderBinJobs.push_back(m_computableEntityFilterJob);
+ renderBinJobs.push_back(m_cacheComputableEntitiesJob);
+ }
+
+ if (lightsDirty) {
+ renderBinJobs.push_back(m_lightGathererJob);
+ renderBinJobs.push_back(m_cacheLightsJob);
+ }
+
QMutexLocker lock(m_renderQueue->mutex());
if (m_renderQueue->wasReset()) { // Have we rendered yet? (Scene3D case)
// Traverse the current framegraph. For each leaf node create a
@@ -1859,20 +1878,18 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
// Handle single shot subtree enablers
const auto subtreeEnablers = visitor.takeEnablersToDisable();
for (auto *node : subtreeEnablers)
- m_updatedDisables.push_back(node->peerId());
- if (m_updatedDisables.size() > 0)
- renderBinJobs.push_back(m_sendDisablesToFrontendJob);
+ m_updatedDisableSubtreeEnablers.push_back(node->peerId());
}
const int fgBranchCount = m_frameGraphLeaves.size();
for (int i = 0; i < fgBranchCount; ++i) {
- RenderViewBuilder builder(m_frameGraphLeaves.at(i), i, this);
- builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt);
- builder.setRenderableCacheNeedsToBeRebuilt(renderableDirty);
- builder.setComputableCacheNeedsToBeRebuilt(computeableDirty);
- builder.setLightGathererCacheNeedsToBeRebuilt(lightsDirty);
- builder.setMaterialGathererCacheNeedsToBeRebuilt(materialCacheNeedsToBeRebuilt);
- builder.setLightGathererCacheNeedsToBeRebuilt(lightsDirty);
+ FrameGraphNode *leaf = m_frameGraphLeaves.at(i);
+ RenderViewBuilder builder(leaf, i, this);
+ // If we have a new RV (wasn't in the cache before, then it contains no cached data)
+ const bool isNewRV = !m_cache.leafNodeCache.contains(leaf);
+ builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt || isNewRV);
+ builder.setMaterialGathererCacheNeedsToBeRebuilt(materialCacheNeedsToBeRebuilt || isNewRV);
+ builder.setRenderCommandCacheNeedsToBeRebuilt(renderCommandsDirty || isNewRV);
builder.prepareJobs();
renderBinJobs.append(builder.buildJobHierachy());
@@ -2075,7 +2092,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
bool allCommandsIssued = true;
// Render drawing commands
- const QVector<RenderCommand *> commands = rv->commands();
+ QVector<RenderCommand> commands = rv->commands();
// Use the graphicscontext to submit the commands to the underlying
// graphics API (OpenGL)
@@ -2084,18 +2101,18 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
RenderStateSet *globalState = m_submissionContext->currentStateSet();
OpenGLVertexArrayObject *vao = nullptr;
- for (RenderCommand *command : qAsConst(commands)) {
+ for (RenderCommand &command : commands) {
- if (command->m_type == RenderCommand::Compute) { // Compute Call
- performCompute(rv, command);
+ if (command.m_type == RenderCommand::Compute) { // Compute Call
+ performCompute(rv, &command);
} else { // Draw Command
// Check if we have a valid command that can be drawn
- if (!command->m_isValid) {
+ if (!command.m_isValid) {
allCommandsIssued = false;
continue;
}
- vao = m_nodesManager->vaoManager()->data(command->m_vao);
+ vao = m_nodesManager->vaoManager()->data(command.m_vao);
// something may have went wrong when initializing the VAO
if (!vao->isSpecified()) {
@@ -2106,7 +2123,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
{
Profiling::GLTimeRecorder recorder(Profiling::ShaderUpdate);
//// We activate the shader here
- if (!m_submissionContext->activateShader(command->m_shaderDna)) {
+ if (!m_submissionContext->activateShader(command.m_shaderDna)) {
allCommandsIssued = false;
continue;
}
@@ -2121,7 +2138,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
{
Profiling::GLTimeRecorder recorder(Profiling::UniformUpdate);
//// Update program uniforms
- if (!m_submissionContext->setParameters(command->m_parameterPack)) {
+ if (!m_submissionContext->setParameters(command.m_parameterPack)) {
allCommandsIssued = false;
// If we have failed to set uniform (e.g unable to bind a texture)
// we won't perform the draw call which could show invalid content
@@ -2132,7 +2149,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
//// OpenGL State
// TO DO: Make states not dependendent on their backend node for this step
// Set state
- RenderStateSet *localState = command->m_stateSet;
+ RenderStateSet *localState = command.m_stateSet.data();
{
@@ -2140,8 +2157,8 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
// Merge the RenderCommand state with the globalState of the RenderView
// Or restore the globalState if no stateSet for the RenderCommand
if (localState != nullptr) {
- command->m_stateSet->merge(globalState);
- m_submissionContext->setCurrentStateSet(command->m_stateSet);
+ command.m_stateSet->merge(globalState);
+ m_submissionContext->setCurrentStateSet(localState);
} else {
m_submissionContext->setCurrentStateSet(globalState);
}
@@ -2151,7 +2168,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
// at that point
//// Draw Calls
- performDraw(command);
+ performDraw(&command);
}
} // end of RenderCommands loop
@@ -2167,7 +2184,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
}
bool Renderer::updateVAOWithAttributes(Geometry *geometry,
- RenderCommand *command,
+ const RenderCommand *command,
Shader *shader,
bool forceUpdate)
{
@@ -2227,7 +2244,7 @@ bool Renderer::updateVAOWithAttributes(Geometry *geometry,
}
bool Renderer::requiresVAOAttributeUpdate(Geometry *geometry,
- RenderCommand *command) const
+ const RenderCommand *command) const
{
const auto attributeIds = geometry->attributes();
@@ -2295,17 +2312,6 @@ SubmissionContext *Renderer::submissionContext() const
return m_submissionContext.data();
}
-void Renderer::addRenderCaptureSendRequest(Qt3DCore::QNodeId nodeId)
-{
- if (!m_pendingRenderCaptureSendRequests.contains(nodeId))
- m_pendingRenderCaptureSendRequests.push_back(nodeId);
-}
-
-const QVector<Qt3DCore::QNodeId> Renderer::takePendingRenderCaptureSendRequests()
-{
- return std::move(m_pendingRenderCaptureSendRequests);
-}
-
// Returns a vector of jobs to be performed for dirty buffers
// 1 dirty buffer == 1 job, all job can be performed in parallel
QVector<Qt3DCore::QAspectJobPtr> Renderer::createRenderBufferJobs() const
diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h
index b1cd4aac5..e770b8280 100644
--- a/src/render/renderers/opengl/renderer/renderer_p.h
+++ b/src/render/renderers/opengl/renderer/renderer_p.h
@@ -71,7 +71,6 @@
#include <Qt3DRender/private/updateworldboundingvolumejob_p.h>
#include <Qt3DRender/private/updatetreeenabledjob_p.h>
#include <Qt3DRender/private/platformsurfacefilter_p.h>
-#include <Qt3DRender/private/sendrendercapturejob_p.h>
#include <Qt3DRender/private/sendbuffercapturejob_p.h>
#include <Qt3DRender/private/genericlambdajob_p.h>
#include <Qt3DRender/private/updatemeshtrianglelistjob_p.h>
@@ -82,6 +81,7 @@
#include <Qt3DRender/private/texture_p.h>
#include <Qt3DRender/private/glfence_p.h>
#include <Qt3DRender/private/shaderbuilder_p.h>
+#include <Qt3DRender/private/lightgatherer_p.h>
#include <QHash>
#include <QMatrix4x4>
@@ -125,11 +125,9 @@ class QAbstractShapeMesh;
struct GraphicsApiFilterData;
class QSceneImporter;
-#if QT_CONFIG(qt3d_profile_jobs)
namespace Debug {
class CommandExecuter;
}
-#endif
namespace Render {
@@ -158,6 +156,13 @@ typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr;
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
using SynchronizerPostFramePtr = GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>>;
+template<typename T, typename ... Ts>
+class FilterEntityByComponentJob;
+template<typename T, typename ... Ts>
+using FilterEntityByComponentJobPtr = QSharedPointer<FilterEntityByComponentJob<T, Ts...>>;
+using ComputableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::ComputeCommand, Render::Material>;
+using RenderableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::GeometryRenderer, Render::Material>;
+
class Q_3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer
{
public:
@@ -199,8 +204,9 @@ public:
#if defined(QT_BUILD_INTERNAL)
void clearDirtyBits(BackendNodeDirtySet changes) override;
#endif
- bool shouldRender() override;
+ bool shouldRender() const override;
void skipNextFrame() override;
+ void jobsDone(Qt3DCore::QAspectManager *manager) override;
QVector<Qt3DCore::QAspectJobPtr> preRenderingJobs() override;
QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override;
@@ -225,8 +231,13 @@ public:
inline SynchronizerPostFramePtr introspectShadersJob() const { return m_introspectShaderJob; }
inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; }
inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; }
- inline Qt3DCore::QAspectJobPtr sendTextureChangesToFrontendJob() const { return m_sendTextureChangesToFrontendJob; }
inline UpdateEntityLayersJobPtr updateEntityLayersJob() const { return m_updateEntityLayersJob; }
+ inline LightGathererPtr lightGathererJob() const { return m_lightGathererJob; }
+ inline RenderableEntityFilterPtr renderableEntityFilterJob() const { return m_renderableEntityFilterJob; }
+ inline ComputableEntityFilterPtr computableEntityFilterJob() const { return m_computableEntityFilterJob; }
+ inline SynchronizerJobPtr cacheLightJob() const { return m_cacheLightsJob; }
+ inline SynchronizerJobPtr cacheRenderableEntitiesJob() const { return m_cacheRenderableEntitiesJob; }
+ inline SynchronizerJobPtr cacheComputableEntitiesJob() const { return m_cacheComputableEntitiesJob; }
Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override;
@@ -254,12 +265,12 @@ public:
void prepareCommandsSubmission(const QVector<RenderView *> &renderViews);
bool executeCommandsSubmission(const RenderView *rv);
bool updateVAOWithAttributes(Geometry *geometry,
- RenderCommand *command,
+ const RenderCommand *command,
Shader *shader,
bool forceUpdate);
bool requiresVAOAttributeUpdate(Geometry *geometry,
- RenderCommand *command) const;
+ const RenderCommand *command) const;
void setOpenGLContext(QOpenGLContext *context) override;
const GraphicsApiFilterData *contextInfo() const;
@@ -270,9 +281,6 @@ public:
QList<QPair<QObject*, QMouseEvent>> pendingPickingEvents() const;
QList<QKeyEvent> pendingKeyEvents() const;
- void addRenderCaptureSendRequest(Qt3DCore::QNodeId nodeId);
- const QVector<Qt3DCore::QNodeId> takePendingRenderCaptureSendRequests();
-
void enqueueRenderView(RenderView *renderView, int submitOrder);
bool isReadyToSubmit();
@@ -338,8 +346,8 @@ private:
QAtomicInt m_exposed;
struct DirtyBits {
- BackendNodeDirtySet marked = 0; // marked dirty since last job build
- BackendNodeDirtySet remaining = 0; // remaining dirty after jobs have finished
+ BackendNodeDirtySet marked; // marked dirty since last job build
+ BackendNodeDirtySet remaining; // remaining dirty after jobs have finished
};
DirtyBits m_dirtyBits;
@@ -362,13 +370,15 @@ private:
CalculateBoundingVolumeJobPtr m_calculateBoundingVolumeJob;
UpdateWorldBoundingVolumeJobPtr m_updateWorldBoundingVolumeJob;
UpdateTreeEnabledJobPtr m_updateTreeEnabledJob;
- SendRenderCaptureJobPtr m_sendRenderCaptureJob;
SendBufferCaptureJobPtr m_sendBufferCaptureJob;
UpdateSkinningPaletteJobPtr m_updateSkinningPaletteJob;
UpdateLevelOfDetailJobPtr m_updateLevelOfDetailJob;
UpdateMeshTriangleListJobPtr m_updateMeshTriangleListJob;
FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob;
UpdateEntityLayersJobPtr m_updateEntityLayersJob;
+ LightGathererPtr m_lightGathererJob;
+ RenderableEntityFilterPtr m_renderableEntityFilterJob;
+ ComputableEntityFilterPtr m_computableEntityFilterJob;
QVector<Qt3DCore::QNodeId> m_pendingRenderCaptureSendRequests;
@@ -381,11 +391,12 @@ private:
SynchronizerJobPtr m_bufferGathererJob;
SynchronizerJobPtr m_vaoGathererJob;
SynchronizerJobPtr m_textureGathererJob;
- SynchronizerPostFramePtr m_sendTextureChangesToFrontendJob;
SynchronizerJobPtr m_sendSetFenceHandlesToFrontendJob;
- SynchronizerJobPtr m_sendDisablesToFrontendJob;
SynchronizerPostFramePtr m_introspectShaderJob;
SynchronizerJobPtr m_syncLoadingJobs;
+ SynchronizerJobPtr m_cacheRenderableEntitiesJob;
+ SynchronizerJobPtr m_cacheComputableEntitiesJob;
+ SynchronizerJobPtr m_cacheLightsJob;
void lookForAbandonedVaos();
void lookForDirtyBuffers();
@@ -395,18 +406,18 @@ private:
void sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager);
void sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager);
void sendSetFenceHandlesToFrontend();
- void sendDisablesToFrontend();
+ void sendDisablesToFrontend(Qt3DCore::QAspectManager *manager);
QMutex m_abandonedVaosMutex;
QVector<HVao> m_abandonedVaos;
QVector<HBuffer> m_dirtyBuffers;
- QVector<HBuffer> m_downloadableBuffers;
+ QVector<Qt3DCore::QNodeId> m_downloadableBuffers;
QVector<HShader> m_dirtyShaders;
QVector<HTexture> m_dirtyTextures;
QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> m_updatedTextureProperties;
QVector<QPair<Qt3DCore::QNodeId, GLFence>> m_updatedSetFences;
- QVector<Qt3DCore::QNodeId> m_updatedDisables;
+ QVector<Qt3DCore::QNodeId> m_updatedDisableSubtreeEnablers;
Qt3DCore::QNodeIdVector m_textureIdsToCleanup;
QVector<ShaderBuilderUpdate> m_shaderBuilderUpdates;
@@ -415,10 +426,7 @@ private:
OffscreenSurfaceHelper *m_offscreenHelper;
QMutex m_offscreenSurfaceMutex;
-#if QT_CONFIG(qt3d_profile_jobs)
QScopedPointer<Qt3DRender::Debug::CommandExecuter> m_commandExecuter;
- friend class Qt3DRender::Debug::CommandExecuter;
-#endif
#ifdef QT_BUILD_INTERNAL
friend class ::tst_Renderer;
diff --git a/src/render/renderers/opengl/renderer/renderercache_p.h b/src/render/renderers/opengl/renderer/renderercache_p.h
index 0e9c5d3cd..02fe4ff41 100644
--- a/src/render/renderers/opengl/renderer/renderercache_p.h
+++ b/src/render/renderers/opengl/renderer/renderercache_p.h
@@ -56,6 +56,7 @@
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/renderviewjobutils_p.h>
#include <Qt3DRender/private/lightsource_p.h>
+#include <Qt3DRender/private/rendercommand_p.h>
QT_BEGIN_NAMESPACE
@@ -69,12 +70,16 @@ struct RendererCache
{
QVector<Entity *> filterEntitiesByLayer;
MaterialParameterGathererData materialParameterGatherer;
- QVector<LightSource> gatheredLights;
- QVector<Entity *> renderableEntities;
- QVector<Entity *> computeEntities;
- EnvironmentLight* environmentLight;
+ EntityRenderCommandData renderCommandData;
};
+ // Shared amongst all RV cache
+ QVector<Entity *> renderableEntities;
+ QVector<Entity *> computeEntities;
+ QVector<LightSource> gatheredLights;
+ EnvironmentLight* environmentLight;
+
+ // Per RV cache
QHash<FrameGraphNode *, LeafNodeData> leafNodeCache;
QMutex *mutex() { return &m_mutex; }
diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp
index aa9f4d1a5..c00a92629 100644
--- a/src/render/renderers/opengl/renderer/renderview.cpp
+++ b/src/render/renderers/opengl/renderer/renderview.cpp
@@ -119,29 +119,29 @@ RenderView::StandardUniformsNameToTypeHash RenderView::initializeStandardUniform
{
RenderView::StandardUniformsNameToTypeHash setters;
- setters.insert(StringToInt::lookupId(QLatin1String("modelMatrix")), ModelMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("viewMatrix")), ViewMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("projectionMatrix")), ProjectionMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("modelView")), ModelViewMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("viewProjectionMatrix")), ViewProjectionMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("modelViewProjection")), ModelViewProjectionMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("mvp")), ModelViewProjectionMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("inverseModelMatrix")), InverseModelMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("inverseViewMatrix")), InverseViewMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("inverseProjectionMatrix")), InverseProjectionMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("inverseModelView")), InverseModelViewMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("inverseViewProjectionMatrix")), InverseViewProjectionMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("inverseModelViewProjection")), InverseModelViewProjectionMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("modelNormalMatrix")), ModelNormalMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("modelViewNormal")), ModelViewNormalMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("viewportMatrix")), ViewportMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("inverseViewportMatrix")), InverseViewportMatrix);
- setters.insert(StringToInt::lookupId(QLatin1String("aspectRatio")), AspectRatio);
- setters.insert(StringToInt::lookupId(QLatin1String("exposure")), Exposure);
- setters.insert(StringToInt::lookupId(QLatin1String("gamma")), Gamma);
- setters.insert(StringToInt::lookupId(QLatin1String("time")), Time);
- setters.insert(StringToInt::lookupId(QLatin1String("eyePosition")), EyePosition);
- setters.insert(StringToInt::lookupId(QLatin1String("skinningPalette[0]")), SkinningPalette);
+ setters.insert(Shader::modelMatrixNameId, ModelMatrix);
+ setters.insert(Shader::viewMatrixNameId, ViewMatrix);
+ setters.insert(Shader::projectionMatrixNameId, ProjectionMatrix);
+ setters.insert(Shader::modelViewMatrixNameId, ModelViewMatrix);
+ setters.insert(Shader::viewProjectionMatrixNameId, ViewProjectionMatrix);
+ setters.insert(Shader::modelViewProjectionNameId, ModelViewProjectionMatrix);
+ setters.insert(Shader::mvpNameId, ModelViewProjectionMatrix);
+ setters.insert(Shader::inverseModelMatrixNameId, InverseModelMatrix);
+ setters.insert(Shader::inverseViewMatrixNameId, InverseViewMatrix);
+ setters.insert(Shader::inverseProjectionMatrixNameId, InverseProjectionMatrix);
+ setters.insert(Shader::inverseModelViewNameId, InverseModelViewMatrix);
+ setters.insert(Shader::inverseViewProjectionMatrixNameId, InverseViewProjectionMatrix);
+ setters.insert(Shader::inverseModelViewProjectionNameId, InverseModelViewProjectionMatrix);
+ setters.insert(Shader::modelNormalMatrixNameId, ModelNormalMatrix);
+ setters.insert(Shader::modelViewNormalNameId, ModelViewNormalMatrix);
+ setters.insert(Shader::viewportMatrixNameId, ViewportMatrix);
+ setters.insert(Shader::inverseViewportMatrixNameId, InverseViewportMatrix);
+ setters.insert(Shader::aspectRatioNameId, AspectRatio);
+ setters.insert(Shader::exposureNameId, Exposure);
+ setters.insert(Shader::gammaNameId, Gamma);
+ setters.insert(Shader::timeNameId, Time);
+ setters.insert(Shader::eyePositionNameId, EyePosition);
+ setters.insert(Shader::skinningPaletteNameId, SkinningPalette);
return setters;
}
@@ -211,7 +211,7 @@ UniformValue RenderView::standardUniformValue(RenderView::StandardUniform standa
return UniformValue(Matrix4x4(viewportMatrix.inverted()));
}
case AspectRatio:
- return float(m_surfaceSize.width()) / float(m_surfaceSize.height());
+ return float(m_surfaceSize.width()) / std::max(1.f, float(m_surfaceSize.height()));
case Exposure:
return UniformValue(m_data.m_renderCameraLens ? m_data.m_renderCameraLens->exposure() : 0.0f);
case Gamma:
@@ -238,11 +238,14 @@ RenderView::RenderView()
: m_isDownloadBuffersEnable(false)
, m_hasBlitFramebufferInfo(false)
, m_renderer(nullptr)
+ , m_manager(nullptr)
, m_devicePixelRatio(1.)
- , m_viewport(QRectF(0.0f, 0.0f, 1.0f, 1.0f))
+ , m_viewport(QRectF(0., 0., 1., 1.))
, m_gamma(2.2f)
, m_surface(nullptr)
, m_clearBuffer(QClearBuffers::None)
+ , m_clearDepthValue(1.f)
+ , m_clearStencilValue(0)
, m_stateSet(nullptr)
, m_noDraw(false)
, m_compute(false)
@@ -280,10 +283,6 @@ RenderView::RenderView()
RenderView::~RenderView()
{
delete m_stateSet;
- for (RenderCommand *command : qAsConst(m_commands)) {
- delete command->m_stateSet;
- delete command;
- }
}
namespace {
@@ -291,7 +290,7 @@ namespace {
template<int SortType>
struct AdjacentSubRangeFinder
{
- static bool adjacentSubRange(RenderCommand *, RenderCommand *)
+ static bool adjacentSubRange(const RenderCommand &, const RenderCommand &)
{
Q_UNREACHABLE();
return false;
@@ -301,47 +300,47 @@ struct AdjacentSubRangeFinder
template<>
struct AdjacentSubRangeFinder<QSortPolicy::StateChangeCost>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_changeCost == b->m_changeCost;
+ return a.m_changeCost == b.m_changeCost;
}
};
template<>
struct AdjacentSubRangeFinder<QSortPolicy::BackToFront>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_depth == b->m_depth;
+ return a.m_depth == b.m_depth;
}
};
template<>
struct AdjacentSubRangeFinder<QSortPolicy::Material>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_shaderDna == b->m_shaderDna;
+ return a.m_shaderDna == b.m_shaderDna;
}
};
template<>
struct AdjacentSubRangeFinder<QSortPolicy::FrontToBack>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_depth == b->m_depth;
+ return a.m_depth == b.m_depth;
}
};
template<>
struct AdjacentSubRangeFinder<QSortPolicy::Texture>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
// Two renderCommands are adjacent if one contains all the other command's textures
- QVector<ShaderParameterPack::NamedResource> texturesA = a->m_parameterPack.textures();
- QVector<ShaderParameterPack::NamedResource> texturesB = b->m_parameterPack.textures();
+ QVector<ShaderParameterPack::NamedResource> texturesA = a.m_parameterPack.textures();
+ QVector<ShaderParameterPack::NamedResource> texturesB = b.m_parameterPack.textures();
if (texturesB.size() > texturesA.size())
qSwap(texturesA, texturesB);
@@ -356,7 +355,7 @@ struct AdjacentSubRangeFinder<QSortPolicy::Texture>
};
template<typename Predicate>
-int advanceUntilNonAdjacent(const QVector<RenderCommand *> &commands,
+int advanceUntilNonAdjacent(const QVector<RenderCommand> &commands,
const int beg, const int end, Predicate pred)
{
int i = beg + 1;
@@ -369,7 +368,7 @@ int advanceUntilNonAdjacent(const QVector<RenderCommand *> &commands,
}
-using CommandIt = QVector<RenderCommand *>::iterator;
+using CommandIt = QVector<RenderCommand>::iterator;
template<int SortType>
struct SubRangeSorter
@@ -387,8 +386,8 @@ struct SubRangeSorter<QSortPolicy::StateChangeCost>
{
static void sortSubRange(CommandIt begin, const CommandIt end)
{
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_changeCost > b->m_changeCost;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_changeCost > b.m_changeCost;
});
}
};
@@ -398,8 +397,8 @@ struct SubRangeSorter<QSortPolicy::BackToFront>
{
static void sortSubRange(CommandIt begin, const CommandIt end)
{
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_depth > b->m_depth;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_depth > b.m_depth;
});
}
};
@@ -410,8 +409,8 @@ struct SubRangeSorter<QSortPolicy::Material>
static void sortSubRange(CommandIt begin, const CommandIt end)
{
// First we sort by shaderDNA
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_shaderDna > b->m_shaderDna;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_shaderDna > b.m_shaderDna;
});
}
};
@@ -421,8 +420,8 @@ struct SubRangeSorter<QSortPolicy::FrontToBack>
{
static void sortSubRange(CommandIt begin, const CommandIt end)
{
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_depth < b->m_depth;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_depth < b.m_depth;
});
}
};
@@ -432,9 +431,9 @@ struct SubRangeSorter<QSortPolicy::Texture>
{
static void sortSubRange(CommandIt begin, const CommandIt end)
{
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- QVector<ShaderParameterPack::NamedResource> texturesA = a->m_parameterPack.textures();
- QVector<ShaderParameterPack::NamedResource> texturesB = b->m_parameterPack.textures();
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ QVector<ShaderParameterPack::NamedResource> texturesA = a.m_parameterPack.textures();
+ QVector<ShaderParameterPack::NamedResource> texturesB = b.m_parameterPack.textures();
const int originalTextureASize = texturesA.size();
@@ -453,7 +452,7 @@ struct SubRangeSorter<QSortPolicy::Texture>
}
};
-int findSubRange(const QVector<RenderCommand *> &commands,
+int findSubRange(const QVector<RenderCommand> &commands,
const int begin, const int end,
const QSortPolicy::SortType sortType)
{
@@ -474,14 +473,14 @@ int findSubRange(const QVector<RenderCommand *> &commands,
}
}
-void sortByMaterial(QVector<RenderCommand *> &commands, int begin, const int end)
+void sortByMaterial(QVector<RenderCommand> &commands, int begin, const int end)
{
// We try to arrange elements so that their rendering cost is minimized for a given shader
int rangeEnd = advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Material>::adjacentSubRange);
while (begin != end) {
if (begin + 1 < rangeEnd) {
- std::stable_sort(commands.begin() + begin + 1, commands.begin() + rangeEnd, [] (RenderCommand *a, RenderCommand *b){
- return a->m_material.handle() < b->m_material.handle();
+ std::stable_sort(commands.begin() + begin + 1, commands.begin() + rangeEnd, [] (const RenderCommand &a, const RenderCommand &b){
+ return a.m_material.handle() < b.m_material.handle();
});
}
begin = rangeEnd;
@@ -489,7 +488,7 @@ void sortByMaterial(QVector<RenderCommand *> &commands, int begin, const int end
}
}
-void sortCommandRange(QVector<RenderCommand *> &commands, int begin, const int end, const int level,
+void sortCommandRange(QVector<RenderCommand> &commands, int begin, const int end, const int level,
const QVector<Qt3DRender::QSortPolicy::SortType> &sortingTypes)
{
if (level >= sortingTypes.size())
@@ -539,24 +538,23 @@ void RenderView::sort()
// Minimize uniform changes
int i = 0;
- while (i < m_commands.size()) {
+ const int commandSize = m_commands.size();
+ while (i < commandSize) {
int j = i;
// Advance while commands share the same shader
- while (i < m_commands.size() && m_commands[j]->m_shaderDna == m_commands[i]->m_shaderDna)
+ while (i < commandSize && m_commands[j].m_shaderDna == m_commands[i].m_shaderDna)
++i;
if (i - j > 0) { // Several commands have the same shader, so we minimize uniform changes
- PackUniformHash cachedUniforms = m_commands[j++]->m_parameterPack.uniforms();
+ PackUniformHash cachedUniforms = m_commands[j++].m_parameterPack.uniforms();
while (j < i) {
// We need the reference here as we are modifying the original container
// not the copy
- PackUniformHash &uniforms = m_commands.at(j)->m_parameterPack.m_uniforms;
- PackUniformHash::iterator it = uniforms.begin();
- const PackUniformHash::iterator end = uniforms.end();
+ PackUniformHash &uniforms = m_commands[j].m_parameterPack.m_uniforms;
- while (it != end) {
+ for (int u = 0; u < uniforms.keys.size();) {
// We are comparing the values:
// - raw uniform values
// - the texture Node id if the uniform represents a texture
@@ -564,12 +562,17 @@ void RenderView::sort()
// sharing the same material (shader) are rendered, we can't have the case
// where two uniforms, referencing the same texture eventually have 2 different
// texture unit values
- const UniformValue refValue = cachedUniforms.value(it.key());
- if (it.value() == refValue) {
- it = uniforms.erase(it);
+ const int uniformNameId = uniforms.keys.at(u);
+ const UniformValue &refValue = cachedUniforms.value(uniformNameId);
+ const UniformValue &newValue = uniforms.values.at(u);
+ if (newValue == refValue) {
+ uniforms.erase(u);
} else {
- cachedUniforms.insert(it.key(), it.value());
- ++it;
+ // Record updated value so that subsequent comparison
+ // for the next command will be made againts latest
+ // uniform value
+ cachedUniforms.insert(uniformNameId, newValue);
+ ++u;
}
}
++j;
@@ -619,20 +622,16 @@ void RenderView::addClearBuffers(const ClearBuffers *cb) {
}
// If we are there, we know that entity had a GeometryRenderer + Material
-QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities) const
+EntityRenderCommandData RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities,
+ int offset, int count) const
{
- // Note: since many threads can be building render commands
- // we need to ensure that the UniformBlockValueBuilder they are using
- // 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);
+ EntityRenderCommandData commands;
- QVector<RenderCommand *> commands;
- commands.reserve(entities.size());
+ commands.reserve(count);
- for (Entity *entity : entities) {
+ for (int i = 0; i < count; ++i) {
+ const int idx = offset + i;
+ Entity *entity = entities.at(idx);
GeometryRenderer *geometryRenderer = nullptr;
HGeometryRenderer geometryRendererHandle = entity->componentHandle<GeometryRenderer>();
@@ -645,135 +644,226 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit
const HMaterial materialHandle = entity->componentHandle<Material>();
const QVector<RenderPassParameterData> renderPassData = m_parameters.value(materialComponentId);
+ HGeometry geometryHandle = m_manager->geometryManager()->lookupHandle(geometryRenderer->geometryId());
+ Geometry *geometry = m_manager->geometryManager()->data(geometryHandle);
+
// 1 RenderCommand per RenderPass pass on an Entity with a Mesh
for (const RenderPassParameterData &passData : renderPassData) {
// Add the RenderPass Parameters
- RenderCommand *command = new RenderCommand();
- command->m_geometryRenderer = geometryRendererHandle;
- command->m_geometry = m_manager->geometryManager()->lookupHandle(geometryRenderer->geometryId());
-
- // Project the camera-to-object-center vector onto the camera
- // view vector. This gives a depth value suitable as the key
- // for BackToFront sorting.
- command->m_depth = Vector3D::dotProduct(entity->worldBoundingVolume()->center() - m_data.m_eyePos, m_data.m_eyeViewDir);
- command->m_material = materialHandle;
+ RenderCommand command = {};
+ command.m_geometryRenderer = geometryRendererHandle;
+ command.m_geometry = geometryHandle;
+
+ command.m_material = materialHandle;
// For RenderPass based states we use the globally set RenderState
// if no renderstates are defined as part of the pass. That means:
// RenderPass { renderStates: [] } will use the states defined by
// StateSet in the FrameGraph
RenderPass *pass = passData.pass;
if (pass->hasRenderStates()) {
- command->m_stateSet = new RenderStateSet();
- addStatesToRenderStateSet(command->m_stateSet, pass->renderStates(), m_manager->renderStateManager());
+ command.m_stateSet = RenderStateSetPtr::create();
+ addStatesToRenderStateSet(command.m_stateSet.data(), pass->renderStates(), m_manager->renderStateManager());
if (m_stateSet != nullptr)
- command->m_stateSet->merge(m_stateSet);
- command->m_changeCost = m_renderer->defaultRenderState()->changeCost(command->m_stateSet);
+ command.m_stateSet->merge(m_stateSet);
+ command.m_changeCost = m_renderer->defaultRenderState()->changeCost(command.m_stateSet.data());
}
+ command.m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(pass->shaderProgram());
+
+ { // Scoped to show extent
+
+ // Update the draw command with what's going to be needed for the drawing
+ int primitiveCount = geometryRenderer->vertexCount();
+ int estimatedCount = 0;
+ Attribute *indexAttribute = nullptr;
+ Attribute *indirectAttribute = nullptr;
+
+ const QVector<Qt3DCore::QNodeId> attributeIds = geometry->attributes();
+ for (Qt3DCore::QNodeId attributeId : attributeIds) {
+ Attribute *attribute = m_manager->attributeManager()->lookupResource(attributeId);
+ switch (attribute->attributeType()) {
+ case QAttribute::IndexAttribute:
+ indexAttribute = attribute;
+ break;
+ case QAttribute::DrawIndirectAttribute:
+ indirectAttribute = attribute;
+ break;
+ case QAttribute::VertexAttribute:
+ estimatedCount = std::max(int(attribute->count()), estimatedCount);
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
- // Pick which lights to take in to account.
- // For now decide based on the distance by taking the MAX_LIGHTS closest lights.
- // Replace with more sophisticated mechanisms later.
- // Copy vector so that we can sort it concurrently and we only want to sort the one for the current command
- QVector<LightSource> lightSources = m_lightSources;
- if (lightSources.size() > 1) {
- const Vector3D entityCenter = entity->worldBoundingVolume()->center();
- std::sort(lightSources.begin(), lightSources.end(),
- [&] (const LightSource &a, const LightSource &b) {
- const float distA = entityCenter.distanceToPoint(a.entity->worldBoundingVolume()->center());
- const float distB = entityCenter.distanceToPoint(b.entity->worldBoundingVolume()->center());
- return distA < distB;
- });
- }
+ command.m_drawIndexed = (indexAttribute != nullptr);
+ command.m_drawIndirect = (indirectAttribute != nullptr);
+
+ // Update the draw command with all the information required for the drawing
+ if (command.m_drawIndexed) {
+ command.m_indexAttributeDataType = GraphicsContext::glDataTypeFromAttributeDataType(indexAttribute->vertexBaseType());
+ command.m_indexAttributeByteOffset = indexAttribute->byteOffset() + geometryRenderer->indexBufferByteOffset();
+ }
+
+ // Note: we only care about the primitiveCount when using direct draw calls
+ // For indirect draw calls it is assumed the buffer was properly set already
+ if (command.m_drawIndirect) {
+ command.m_indirectAttributeByteOffset = indirectAttribute->byteOffset();
+ command.m_indirectDrawBuffer = m_manager->bufferManager()->lookupHandle(indirectAttribute->bufferId());
+ } else {
+ // Use the count specified by the GeometryRender
+ // If not specify use the indexAttribute count if present
+ // Otherwise tries to use the count from the attribute with the highest count
+ if (primitiveCount == 0) {
+ if (indexAttribute)
+ primitiveCount = indexAttribute->count();
+ else
+ primitiveCount = estimatedCount;
+ }
+ }
- ParameterInfoList globalParameters = passData.parameterInfo;
- // setShaderAndUniforms can initialize a localData
- // make sure this is cleared before we leave this function
- setShaderAndUniforms(command,
- pass,
- globalParameters,
- entity,
- lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS)),
- m_environmentLight);
-
- commands.append(command);
+ command.m_primitiveCount = primitiveCount;
+ command.m_primitiveType = geometryRenderer->primitiveType();
+ command.m_primitiveRestartEnabled = geometryRenderer->primitiveRestartEnabled();
+ command.m_restartIndexValue = geometryRenderer->restartIndexValue();
+ command.m_firstInstance = geometryRenderer->firstInstance();
+ command.m_instanceCount = geometryRenderer->instanceCount();
+ command.m_firstVertex = geometryRenderer->firstVertex();
+ command.m_indexOffset = geometryRenderer->indexOffset();
+ command.m_verticesPerPatch = geometryRenderer->verticesPerPatch();
+ } // scope
+
+
+ commands.push_back(entity,
+ std::move(command),
+ std::move(passData));
}
}
}
- // We reset the local data once we are done with it
- m_localData.setLocalData(nullptr);
-
return commands;
}
-QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities) const
+EntityRenderCommandData RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities,
+ int offset, int count) const
{
- // Note: since many threads can be building render commands
- // we need to ensure that the UniformBlockValueBuilder they are using
- // 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
// A ComputeDispatch is also implicitely a NoDraw operation
// enabled flag
// layer component
// material/effect/technique/parameters/filters/
- QVector<RenderCommand *> commands;
- commands.reserve(entities.size());
- for (Entity *entity : entities) {
+ EntityRenderCommandData commands;
+
+ commands.reserve(count);
+
+ for (int i = 0; i < count; ++i) {
+ const int idx = offset + i;
+ Entity *entity = entities.at(idx);
ComputeCommand *computeJob = nullptr;
- if ((computeJob = entity->renderComponent<ComputeCommand>()) != nullptr
+ HComputeCommand computeCommandHandle = entity->componentHandle<ComputeCommand>();
+ if ((computeJob = nodeManagers()->computeJobManager()->data(computeCommandHandle)) != nullptr
&& computeJob->isEnabled()) {
- // Note: if frameCount has reached 0 in the previous frame, isEnabled
- // would be false
- if (computeJob->runType() == QComputeCommand::Manual)
- computeJob->updateFrameCount();
-
const Qt3DCore::QNodeId materialComponentId = entity->componentUuid<Material>();
const QVector<RenderPassParameterData> renderPassData = m_parameters.value(materialComponentId);
// 1 RenderCommand per RenderPass pass on an Entity with a Mesh
for (const RenderPassParameterData &passData : renderPassData) {
// Add the RenderPass Parameters
- RenderCommand *command = new RenderCommand();
+ RenderCommand command = {};
RenderPass *pass = passData.pass;
if (pass->hasRenderStates()) {
- command->m_stateSet = new RenderStateSet();
- addStatesToRenderStateSet(command->m_stateSet, pass->renderStates(), m_manager->renderStateManager());
+ command.m_stateSet = RenderStateSetPtr::create();
+ addStatesToRenderStateSet(command.m_stateSet.data(), pass->renderStates(), m_manager->renderStateManager());
// Merge per pass stateset with global stateset
// so that the local stateset only overrides
if (m_stateSet != nullptr)
- command->m_stateSet->merge(m_stateSet);
- command->m_changeCost = m_renderer->defaultRenderState()->changeCost(command->m_stateSet);
+ command.m_stateSet->merge(m_stateSet);
+ command.m_changeCost = m_renderer->defaultRenderState()->changeCost(command.m_stateSet.data());
}
+ command.m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(pass->shaderProgram());
+ command.m_computeCommand = computeCommandHandle;
+ command.m_type = RenderCommand::Compute;
+ command.m_workGroups[0] = std::max(m_workGroups[0], computeJob->x());
+ command.m_workGroups[1] = std::max(m_workGroups[1], computeJob->y());
+ command.m_workGroups[2] = std::max(m_workGroups[2], computeJob->z());
+
+ commands.push_back(entity,
+ std::move(command),
+ std::move(passData));
+ }
+ }
+ }
- command->m_type = RenderCommand::Compute;
- command->m_workGroups[0] = std::max(m_workGroups[0], computeJob->x());
- command->m_workGroups[1] = std::max(m_workGroups[1], computeJob->y());
- command->m_workGroups[2] = std::max(m_workGroups[2], computeJob->z());
-
- ParameterInfoList globalParameters = passData.parameterInfo;
- setShaderAndUniforms(command,
- pass,
- globalParameters,
- entity,
- QVector<LightSource>(),
- nullptr);
- commands.append(command);
+ return commands;
+}
+
+void RenderView::updateRenderCommand(EntityRenderCommandData *renderCommandData,
+ int offset,
+ int count)
+{
+ // Note: since many threads can be building render commands
+ // we need to ensure that the UniformBlockValueBuilder they are using
+ // 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);
+
+ for (int i = 0, m = count; i < m; ++i) {
+ const int idx = offset + i;
+ Entity *entity = renderCommandData->entities.at(idx);
+ const RenderPassParameterData passData = renderCommandData->passesData.at(idx);
+ RenderCommand &command = renderCommandData->commands[idx];
+
+ // Pick which lights to take in to account.
+ // For now decide based on the distance by taking the MAX_LIGHTS closest lights.
+ // Replace with more sophisticated mechanisms later.
+ // Copy vector so that we can sort it concurrently and we only want to sort the one for the current command
+ QVector<LightSource> lightSources;
+ EnvironmentLight *environmentLight = nullptr;
+
+ if (command.m_type == RenderCommand::Draw) {
+ // Project the camera-to-object-center vector onto the camera
+ // view vector. This gives a depth value suitable as the key
+ // for BackToFront sorting.
+ command.m_depth = Vector3D::dotProduct(entity->worldBoundingVolume()->center() - m_data.m_eyePos, m_data.m_eyeViewDir);
+
+ environmentLight = m_environmentLight;
+ lightSources = m_lightSources;
+
+ if (lightSources.size() > 1) {
+ const Vector3D entityCenter = entity->worldBoundingVolume()->center();
+ std::sort(lightSources.begin(), lightSources.end(),
+ [&] (const LightSource &a, const LightSource &b) {
+ const float distA = entityCenter.distanceToPoint(a.entity->worldBoundingVolume()->center());
+ const float distB = entityCenter.distanceToPoint(b.entity->worldBoundingVolume()->center());
+ return distA < distB;
+ });
}
+ lightSources = lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS));
+ } else { // Compute
+ // Note: if frameCount has reached 0 in the previous frame, isEnabled
+ // would be false
+ ComputeCommand *computeJob = m_manager->computeJobManager()->data(command.m_computeCommand);
+ if (computeJob->runType() == QComputeCommand::Manual)
+ computeJob->updateFrameCount();
}
+
+ ParameterInfoList globalParameters = passData.parameterInfo;
+ // setShaderAndUniforms can initialize a localData
+ // make sure this is cleared before we leave this function
+ setShaderAndUniforms(&command,
+ globalParameters,
+ entity,
+ lightSources,
+ environmentLight);
}
// We reset the local data once we are done with it
m_localData.setLocalData(nullptr);
-
- return commands;
}
void RenderView::updateMatrices()
@@ -908,7 +998,6 @@ void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &unif
}
void RenderView::setShaderAndUniforms(RenderCommand *command,
- RenderPass *rPass,
ParameterInfoList &parameters,
Entity *entity,
const QVector<LightSource> &activeLightSources,
@@ -924,163 +1013,163 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
// For each ParameterBinder in the RenderPass -> create a QUniformPack
// Once that works, improve that to try and minimize QUniformPack updates
- if (rPass != nullptr) {
- // Index Shader by Shader UUID
- command->m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(rPass->shaderProgram());
- Shader *shader = m_manager->data<Shader, ShaderManager>(command->m_shader);
- if (shader != nullptr && shader->isLoaded()) {
- command->m_shaderDna = shader->dna();
-
- // Builds the QUniformPack, sets shader standard uniforms and store attributes name / glname bindings
- // If a parameter is defined and not found in the bindings it is assumed to be a binding of Uniform type with the glsl name
- // equals to the parameter name
- const QVector<int> uniformNamesIds = shader->uniformsNamesIds();
- const QVector<int> uniformBlockNamesIds = shader->uniformBlockNamesIds();
- const QVector<int> shaderStorageBlockNamesIds = shader->storageBlockNamesIds();
- const QVector<int> attributeNamesIds = shader->attributeNamesIds();
-
- // Set fragData Name and index
- // Later on we might want to relink the shader if attachments have changed
- // But for now we set them once and for all
+ // Index Shader by Shader UUID
+ Shader *shader = m_manager->data<Shader, ShaderManager>(command->m_shader);
+ if (shader != nullptr && shader->isLoaded()) {
+ command->m_shaderDna = shader->dna();
+
+ // Builds the QUniformPack, sets shader standard uniforms and store attributes name / glname bindings
+ // If a parameter is defined and not found in the bindings it is assumed to be a binding of Uniform type with the glsl name
+ // equals to the parameter name
+ const QVector<int> uniformNamesIds = shader->uniformsNamesIds();
+ const QVector<int> standardUniformNamesIds = shader->standardUniformNameIds();
+ const QVector<int> uniformBlockNamesIds = shader->uniformBlockNamesIds();
+ const QVector<int> shaderStorageBlockNamesIds = shader->storageBlockNamesIds();
+ const QVector<int> attributeNamesIds = shader->attributeNamesIds();
+
+ // Set fragData Name and index
+ // Later on we might want to relink the shader if attachments have changed
+ // But for now we set them once and for all
+ if (!m_renderTarget.isNull() && !shader->isLoaded()) {
QHash<QString, int> fragOutputs;
- if (!m_renderTarget.isNull() && !shader->isLoaded()) {
- const auto atts = m_attachmentPack.attachments();
- for (const Attachment &att : atts) {
- if (att.m_point <= QRenderTargetOutput::Color15)
- fragOutputs.insert(att.m_name, att.m_point);
- }
+ const auto atts = m_attachmentPack.attachments();
+ for (const Attachment &att : atts) {
+ if (att.m_point <= QRenderTargetOutput::Color15)
+ fragOutputs.insert(att.m_name, att.m_point);
}
+ // Set frag outputs in the shaders if hash not empty
+ if (!fragOutputs.isEmpty())
+ shader->setFragOutputs(fragOutputs);
+ }
- if (!uniformNamesIds.isEmpty() || !attributeNamesIds.isEmpty() ||
- !shaderStorageBlockNamesIds.isEmpty() || !attributeNamesIds.isEmpty()) {
-
- // Set default standard uniforms without bindings
- const Matrix4x4 worldTransform = *(entity->worldTransform());
- for (const int uniformNameId : uniformNamesIds) {
- if (ms_standardUniformSetters.contains(uniformNameId))
- setStandardUniformValue(command->m_parameterPack, uniformNameId, uniformNameId, entity, worldTransform);
- }
-
- // Set default attributes
- for (const int attributeNameId : attributeNamesIds)
- command->m_activeAttributes.push_back(attributeNameId);
-
- // Parameters remaining could be
- // -> uniform scalar / vector
- // -> uniform struct / arrays
- // -> uniform block / array (4.3)
- // -> ssbo block / array (4.3)
-
- ParameterInfoList::const_iterator it = parameters.cbegin();
- const ParameterInfoList::const_iterator parametersEnd = parameters.cend();
-
- while (it != parametersEnd) {
- Parameter *param = m_manager->data<Parameter, ParameterManager>(it->handle);
- const UniformValue &uniformValue = param->uniformValue();
- if (uniformNamesIds.contains(it->nameId)) { // Parameter is a regular uniform
- setUniformValue(command->m_parameterPack, it->nameId, uniformValue);
- } else if (uniformBlockNamesIds.indexOf(it->nameId) != -1) { // Parameter is a uniform block
- setUniformBlockValue(command->m_parameterPack, shader, shader->uniformBlockForBlockNameId(it->nameId), uniformValue);
- } else if (shaderStorageBlockNamesIds.indexOf(it->nameId) != -1) { // Parameters is a SSBO
- setShaderStorageValue(command->m_parameterPack, shader, shader->storageBlockForBlockNameId(it->nameId), uniformValue);
- } else { // Parameter is a struct
- ShaderData *shaderData = nullptr;
- if (uniformValue.valueType() == UniformValue::NodeId &&
- (shaderData = m_manager->shaderDataManager()->lookupResource(*uniformValue.constData<Qt3DCore::QNodeId>())) != nullptr) {
- // Try to check if we have a struct or array matching a QShaderData parameter
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, StringToInt::lookupString(it->nameId));
- }
- // Otherwise: param unused by current shader
+ if (!uniformNamesIds.isEmpty() || !standardUniformNamesIds.isEmpty() ||
+ !attributeNamesIds.isEmpty() ||
+ !shaderStorageBlockNamesIds.isEmpty() || !attributeNamesIds.isEmpty()) {
+
+ // Set default standard uniforms without bindings
+ const Matrix4x4 worldTransform = *(entity->worldTransform());
+
+ for (const int uniformNameId : standardUniformNamesIds)
+ setStandardUniformValue(command->m_parameterPack, uniformNameId, uniformNameId, entity, worldTransform);
+
+ // Set default attributes
+ command->m_activeAttributes = attributeNamesIds;
+
+ // At this point we know whether the command is a valid draw command or not
+ // We still need to process the uniforms as the command could be a compute command
+ command->m_isValid = !command->m_activeAttributes.empty();
+
+ // Parameters remaining could be
+ // -> uniform scalar / vector
+ // -> uniform struct / arrays
+ // -> uniform block / array (4.3)
+ // -> ssbo block / array (4.3)
+
+ ParameterInfoList::const_iterator it = parameters.cbegin();
+ const ParameterInfoList::const_iterator parametersEnd = parameters.cend();
+
+ while (it != parametersEnd) {
+ Parameter *param = m_manager->data<Parameter, ParameterManager>(it->handle);
+ const UniformValue &uniformValue = param->uniformValue();
+ if (uniformNamesIds.contains(it->nameId)) { // Parameter is a regular uniform
+ setUniformValue(command->m_parameterPack, it->nameId, uniformValue);
+ } else if (uniformBlockNamesIds.indexOf(it->nameId) != -1) { // Parameter is a uniform block
+ setUniformBlockValue(command->m_parameterPack, shader, shader->uniformBlockForBlockNameId(it->nameId), uniformValue);
+ } else if (shaderStorageBlockNamesIds.indexOf(it->nameId) != -1) { // Parameters is a SSBO
+ setShaderStorageValue(command->m_parameterPack, shader, shader->storageBlockForBlockNameId(it->nameId), uniformValue);
+ } else { // Parameter is a struct
+ ShaderData *shaderData = nullptr;
+ if (uniformValue.valueType() == UniformValue::NodeId &&
+ (shaderData = m_manager->shaderDataManager()->lookupResource(*uniformValue.constData<Qt3DCore::QNodeId>())) != nullptr) {
+ // Try to check if we have a struct or array matching a QShaderData parameter
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, StringToInt::lookupString(it->nameId));
}
- ++it;
+ // Otherwise: param unused by current shader
}
+ ++it;
+ }
- // Lights
-
- int lightIdx = 0;
- for (const LightSource &lightSource : activeLightSources) {
- if (lightIdx == MAX_LIGHTS)
- break;
- Entity *lightEntity = lightSource.entity;
- const Vector3D worldPos = lightEntity->worldBoundingVolume()->center();
- for (Light *light : lightSource.lights) {
- if (!light->isEnabled())
- continue;
-
- ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(light->shaderData());
- if (!shaderData)
- continue;
+ // Lights
- if (lightIdx == MAX_LIGHTS)
- break;
+ int lightIdx = 0;
+ for (const LightSource &lightSource : activeLightSources) {
+ if (lightIdx == MAX_LIGHTS)
+ break;
+ Entity *lightEntity = lightSource.entity;
+ const Matrix4x4 lightWorldTransform = *(lightEntity->worldTransform());
+ const Vector3D worldPos = lightWorldTransform * Vector3D(0.0f, 0.0f, 0.0f);
+ for (Light *light : lightSource.lights) {
+ if (!light->isEnabled())
+ continue;
- // Note: implicit conversion of values to UniformValue
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[lightIdx], worldPos);
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[lightIdx], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[lightIdx], 0.5f);
-
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[lightIdx], worldPos);
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[lightIdx], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[lightIdx], 0.5f);
-
- // There is no risk in doing that even if multithreaded
- // since we are sure that a shaderData is unique for a given light
- // and won't ever be referenced as a Component either
- Matrix4x4 *worldTransform = lightEntity->worldTransform();
- if (worldTransform)
- shaderData->updateWorldTransform(*worldTransform);
-
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_NAMES[lightIdx]);
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_UNROLL_NAMES[lightIdx]);
- ++lightIdx;
- }
- }
+ ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(light->shaderData());
+ if (!shaderData)
+ continue;
- if (uniformNamesIds.contains(LIGHT_COUNT_NAME_ID))
- setUniformValue(command->m_parameterPack, LIGHT_COUNT_NAME_ID, UniformValue(qMax((environmentLight ? 0 : 1), lightIdx)));
+ if (lightIdx == MAX_LIGHTS)
+ break;
- // If no active light sources and no environment light, add a default light
- if (activeLightSources.isEmpty() && !environmentLight) {
// Note: implicit conversion of values to UniformValue
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[0], 0.5f);
-
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[0], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[0], 0.5f);
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[lightIdx], worldPos);
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[lightIdx], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[lightIdx], 0.5f);
+
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[lightIdx], worldPos);
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[lightIdx], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[lightIdx], 0.5f);
+
+
+ // There is no risk in doing that even if multithreaded
+ // since we are sure that a shaderData is unique for a given light
+ // and won't ever be referenced as a Component either
+ Matrix4x4 *worldTransform = lightEntity->worldTransform();
+ if (worldTransform)
+ shaderData->updateWorldTransform(*worldTransform);
+
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_NAMES[lightIdx]);
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_UNROLL_NAMES[lightIdx]);
+ ++lightIdx;
}
+ }
- // Environment Light
- int envLightCount = 0;
- if (environmentLight && environmentLight->isEnabled()) {
- ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(environmentLight->shaderData());
- if (shaderData) {
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, QStringLiteral("envLight"));
- envLightCount = 1;
- }
- } else {
- // with some drivers, samplers (like the envbox sampler) need to be bound even though
- // they may not be actually used, otherwise draw calls can fail
- static const int irradianceId = StringToInt::lookupId(QLatin1String("envLight.irradiance"));
- static const int specularId = StringToInt::lookupId(QLatin1String("envLight.specular"));
- setUniformValue(command->m_parameterPack, irradianceId, m_renderer->submissionContext()->maxTextureUnitsCount());
- setUniformValue(command->m_parameterPack, specularId, m_renderer->submissionContext()->maxTextureUnitsCount());
+ if (uniformNamesIds.contains(LIGHT_COUNT_NAME_ID))
+ setUniformValue(command->m_parameterPack, LIGHT_COUNT_NAME_ID, UniformValue(qMax((environmentLight ? 0 : 1), lightIdx)));
+
+ // If no active light sources and no environment light, add a default light
+ if (activeLightSources.isEmpty() && !environmentLight) {
+ // Note: implicit conversion of values to UniformValue
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[0], 0.5f);
+
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[0], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[0], 0.5f);
+ }
+
+ // Environment Light
+ int envLightCount = 0;
+ if (environmentLight && environmentLight->isEnabled()) {
+ ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(environmentLight->shaderData());
+ if (shaderData) {
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, QStringLiteral("envLight"));
+ envLightCount = 1;
}
- setUniformValue(command->m_parameterPack, StringToInt::lookupId(QStringLiteral("envLightCount")), envLightCount);
+ } else {
+ // with some drivers, samplers (like the envbox sampler) need to be bound even though
+ // they may not be actually used, otherwise draw calls can fail
+ static const int irradianceId = StringToInt::lookupId(QLatin1String("envLight.irradiance"));
+ static const int specularId = StringToInt::lookupId(QLatin1String("envLight.specular"));
+ setUniformValue(command->m_parameterPack, irradianceId, m_renderer->submissionContext()->maxTextureUnitsCount());
+ setUniformValue(command->m_parameterPack, specularId, m_renderer->submissionContext()->maxTextureUnitsCount());
}
- // Set frag outputs in the shaders if hash not empty
- if (!fragOutputs.isEmpty())
- shader->setFragOutputs(fragOutputs);
+ setUniformValue(command->m_parameterPack, StringToInt::lookupId(QStringLiteral("envLightCount")), envLightCount);
}
}
- else {
- qCWarning(Render::Backend) << Q_FUNC_INFO << "Using default effect as none was provided";
- }
}
bool RenderView::hasBlitFramebufferInfo() const
diff --git a/src/render/renderers/opengl/renderer/renderview_p.h b/src/render/renderers/opengl/renderer/renderview_p.h
index 7ebcdb6bd..c7dc37a2c 100644
--- a/src/render/renderers/opengl/renderer/renderview_p.h
+++ b/src/render/renderers/opengl/renderer/renderview_p.h
@@ -227,10 +227,19 @@ public:
RenderPassList passesAndParameters(ParameterInfoList *parameter, Entity *node, bool useDefaultMaterials = true);
- QVector<RenderCommand *> buildDrawRenderCommands(const QVector<Entity *> &entities) const;
- QVector<RenderCommand *> buildComputeRenderCommands(const QVector<Entity *> &entities) const;
- void setCommands(QVector<RenderCommand *> &commands) Q_DECL_NOTHROW { m_commands = commands; }
- QVector<RenderCommand *> commands() const Q_DECL_NOTHROW { return m_commands; }
+ EntityRenderCommandData buildDrawRenderCommands(const QVector<Entity *> &entities,
+ int offset, int count) const;
+ EntityRenderCommandData buildComputeRenderCommands(const QVector<Entity *> &entities,
+ int offset, int count) const;
+
+
+ void updateRenderCommand(EntityRenderCommandData *renderCommandData,
+ int offset, int count);
+
+
+ void setCommands(const QVector<RenderCommand> &commands) Q_DECL_NOTHROW { m_commands = commands; }
+ QVector<RenderCommand> &commands() { return m_commands; }
+ QVector<RenderCommand> commands() const { return m_commands; }
void setAttachmentPack(const AttachmentPack &pack) { m_attachmentPack = pack; }
const AttachmentPack &attachmentPack() const { return m_attachmentPack; }
@@ -291,7 +300,6 @@ public:
private:
void setShaderAndUniforms(RenderCommand *command,
- RenderPass *pass,
ParameterInfoList &parameters,
Entity *entity,
const QVector<LightSource> &activeLightSources,
@@ -331,10 +339,7 @@ private:
QVector<Qt3DCore::QNodeId> m_insertFenceIds;
QVector<QWaitFenceData> m_waitFences;
- // We do not use pointers to RenderNodes or Drawable's here so that the
- // render aspect is free to change the drawables on the next frame whilst
- // the render thread is submitting these commands.
- QVector<RenderCommand *> m_commands;
+ QVector<RenderCommand> m_commands;
mutable QVector<LightSource> m_lightSources;
EnvironmentLight *m_environmentLight;
diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
index 83fab301a..8f1b17119 100644
--- a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
+++ b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
@@ -50,18 +50,73 @@ namespace Render {
// In some cases having less jobs is better (especially on fast cpus where
// splitting just adds more overhead). Ideally, we should try to set the value
// depending on the platform/CPU/nbr of cores
-const int RenderViewBuilder::m_optimalParallelJobCount = std::max(std::min(4, QThread::idealThreadCount()), 2);
+const int RenderViewBuilder::m_optimalParallelJobCount = QThread::idealThreadCount();
namespace {
-class SyncRenderViewCommandBuilders
+int findIdealNumberOfWorkers(int elementCount, int packetSize = 100)
+{
+ if (elementCount == 0 || packetSize == 0)
+ return 0;
+ return std::min(std::max(elementCount / packetSize, 1), RenderViewBuilder::optimalJobCount());
+}
+
+
+class SyncPreCommandBuilding
{
public:
- explicit SyncRenderViewCommandBuilders(const RenderViewInitializerJobPtr &renderViewJob,
- const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs,
- Renderer *renderer)
+ explicit SyncPreCommandBuilding(RenderViewInitializerJobPtr renderViewInitializerJob,
+ const QVector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs,
+ Renderer *renderer,
+ FrameGraphNode *leafNode)
+ : m_renderViewInitializer(renderViewInitializerJob)
+ , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
+ , m_renderer(renderer)
+ , m_leafNode(leafNode)
+ {
+ }
+
+ void operator()()
+ {
+ // Split commands to build among jobs
+ QMutexLocker lock(m_renderer->cache()->mutex());
+ // Rebuild RenderCommands for all entities in RV (ignoring filtering)
+ RendererCache *cache = m_renderer->cache();
+ const RendererCache::LeafNodeData &dataCacheForLeaf = cache->leafNodeCache[m_leafNode];
+ RenderView *rv = m_renderViewInitializer->renderView();
+ const auto entities = !rv->isCompute() ? cache->renderableEntities : cache->computeEntities;
+
+ rv->setMaterialParameterTable(dataCacheForLeaf.materialParameterGatherer);
+
+ lock.unlock();
+
+ // Split among the ideal number of command builders
+ const int idealPacketSize = std::min(std::max(100, entities.size() / RenderViewBuilder::optimalJobCount()), entities.size());
+ // Try to split work into an ideal number of workers
+ const int m = findIdealNumberOfWorkers(entities.size(), idealPacketSize);
+
+ for (int i = 0; i < m; ++i) {
+ const RenderViewCommandBuilderJobPtr renderViewCommandBuilder = m_renderViewCommandBuilderJobs.at(i);
+ const int count = (i == m - 1) ? entities.size() - (i * idealPacketSize) : idealPacketSize;
+ renderViewCommandBuilder->setEntities(entities, i * idealPacketSize, count);
+ }
+ }
+
+private:
+ RenderViewInitializerJobPtr m_renderViewInitializer;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
+ Renderer *m_renderer;
+ FrameGraphNode *m_leafNode;
+};
+
+class SyncRenderViewPostCommandUpdate
+{
+public:
+ explicit SyncRenderViewPostCommandUpdate(const RenderViewInitializerJobPtr &renderViewJob,
+ const QVector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdateJobs,
+ Renderer *renderer)
: m_renderViewJob(renderViewJob)
- , m_renderViewBuilderJobs(renderViewBuilderJobs)
+ , m_renderViewCommandUpdaterJobs(renderViewCommandUpdateJobs)
, m_renderer(renderer)
{}
@@ -70,20 +125,16 @@ public:
// Append all the commands and sort them
RenderView *rv = m_renderViewJob->renderView();
- int totalCommandCount = 0;
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
- totalCommandCount += renderViewCommandBuilder->commands().size();
-
- QVector<RenderCommand *> commands;
- commands.reserve(totalCommandCount);
+ const EntityRenderCommandDataPtr commandData = m_renderViewCommandUpdaterJobs.first()->renderables();
- // Reduction
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
- commands += std::move(renderViewCommandBuilder->commands());
- rv->setCommands(commands);
+ if (commandData) {
+ const QVector<RenderCommand> commands = std::move(commandData->commands);
+ rv->setCommands(commands);
- // Sort the commands
- rv->sort();
+ // TO DO: Find way to store commands once or at least only when required
+ // Sort the commands
+ rv->sort();
+ }
// Enqueue our fully populated RenderView with the RenderThread
m_renderer->enqueueRenderView(rv, m_renderViewJob->submitOrderIndex());
@@ -91,15 +142,15 @@ public:
private:
RenderViewInitializerJobPtr m_renderViewJob;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
Renderer *m_renderer;
};
-class SyncFrustumCulling
+class SyncPreFrustumCulling
{
public:
- explicit SyncFrustumCulling(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCulling)
+ explicit SyncPreFrustumCulling(const RenderViewInitializerJobPtr &renderViewJob,
+ const FrustumCullingJobPtr &frustumCulling)
: m_renderViewJob(renderViewJob)
, m_frustumCullingJob(frustumCulling)
{}
@@ -120,21 +171,23 @@ private:
FrustumCullingJobPtr m_frustumCullingJob;
};
-class SyncRenderViewInitialization
+class SyncRenderViewPostInitialization
{
public:
- explicit SyncRenderViewInitialization(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCullingJob,
- const FilterLayerEntityJobPtr &filterEntityByLayerJob,
- const FilterProximityDistanceJobPtr &filterProximityJob,
- const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
- const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs)
+ explicit SyncRenderViewPostInitialization(const RenderViewInitializerJobPtr &renderViewJob,
+ const FrustumCullingJobPtr &frustumCullingJob,
+ const FilterLayerEntityJobPtr &filterEntityByLayerJob,
+ const FilterProximityDistanceJobPtr &filterProximityJob,
+ const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
+ const QVector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdaterJobs,
+ const QVector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs)
: m_renderViewJob(renderViewJob)
, m_frustumCullingJob(frustumCullingJob)
, m_filterEntityByLayerJob(filterEntityByLayerJob)
, m_filterProximityJob(filterProximityJob)
, m_materialGathererJobs(materialGathererJobs)
- , m_renderViewBuilderJobs(renderViewBuilderJobs)
+ , m_renderViewCommandUpdaterJobs(renderViewCommandUpdaterJobs)
+ , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
{}
void operator()()
@@ -154,8 +207,10 @@ public:
materialGatherer->setTechniqueFilter(const_cast<TechniqueFilter *>(rv->techniqueFilter()));
}
- // Command builders
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ // Command builders and updates
+ for (const auto &renderViewCommandUpdater : qAsConst(m_renderViewCommandUpdaterJobs))
+ renderViewCommandUpdater->setRenderView(rv);
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
renderViewCommandBuilder->setRenderView(rv);
// Set whether frustum culling is enabled or not
@@ -168,26 +223,31 @@ private:
FilterLayerEntityJobPtr m_filterEntityByLayerJob;
FilterProximityDistanceJobPtr m_filterProximityJob;
QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
};
-class SyncRenderCommandBuilding
+class SyncRenderViewPreCommandUpdate
{
public:
- explicit SyncRenderCommandBuilding(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCullingJob,
- const FilterProximityDistanceJobPtr &filterProximityJob,
- const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
- const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs,
- Renderer *renderer,
- FrameGraphNode *leafNode)
+ explicit SyncRenderViewPreCommandUpdate(const RenderViewInitializerJobPtr &renderViewJob,
+ const FrustumCullingJobPtr &frustumCullingJob,
+ const FilterProximityDistanceJobPtr &filterProximityJob,
+ const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
+ const QVector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdaterJobs,
+ const QVector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs,
+ Renderer *renderer,
+ FrameGraphNode *leafNode,
+ bool fullCommandRebuild)
: m_renderViewJob(renderViewJob)
, m_frustumCullingJob(frustumCullingJob)
, m_filterProximityJob(filterProximityJob)
, m_materialGathererJobs(materialGathererJobs)
- , m_renderViewBuilderJobs(renderViewBuilderJobs)
+ , m_renderViewCommandUpdaterJobs(renderViewCommandUpdaterJobs)
+ , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
, m_renderer(renderer)
, m_leafNode(leafNode)
+ , m_fullRebuild(fullCommandRebuild)
{}
void operator()()
@@ -197,21 +257,44 @@ public:
RenderView *rv = m_renderViewJob->renderView();
if (!rv->noDraw()) {
- QVector<Entity *> renderableEntities;
- const bool isDraw = !rv->isCompute();
- QMutexLocker lock(m_renderer->cache()->mutex());
- const auto& cacheData = m_renderer->cache()->leafNodeCache.value(m_leafNode);
+ ///////// CACHE LOCKED ////////////
+ // Retrieve Data from Cache
+ RendererCache *cache = m_renderer->cache();
+ QMutexLocker lock(cache->mutex());
+ Q_ASSERT(cache->leafNodeCache.contains(m_leafNode));
- if (isDraw)
- renderableEntities = cacheData.renderableEntities;
- else
- renderableEntities = cacheData.computeEntities;
-
- const QVector<Entity *> filteredEntities = cacheData.filterEntitiesByLayer;
- QVector<LightSource> lightSources = cacheData.gatheredLights;
- rv->setEnvironmentLight(cacheData.environmentLight);
+ const bool isDraw = !rv->isCompute();
+ const RendererCache::LeafNodeData &dataCacheForLeaf = cache->leafNodeCache[m_leafNode];
+
+ // Rebuild RenderCommands if required
+ // This should happen fairly infrequently (FrameGraph Change, Geometry/Material change)
+ // and allow to skip that step most of the time
+ if (m_fullRebuild) {
+ EntityRenderCommandData commandData;
+ // Reduction
+ {
+ int totalCommandCount = 0;
+ for (const RenderViewCommandBuilderJobPtr &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
+ totalCommandCount += renderViewCommandBuilder->commandData().size();
+ commandData.reserve(totalCommandCount);
+ for (const RenderViewCommandBuilderJobPtr &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
+ commandData += std::move(renderViewCommandBuilder->commandData());
+ }
+
+
+ // Store new cache
+ RendererCache::LeafNodeData &writableCacheForLeaf = cache->leafNodeCache[m_leafNode];
+ writableCacheForLeaf.renderCommandData = std::move(commandData);
+ }
+ const EntityRenderCommandData commandData = dataCacheForLeaf.renderCommandData;
+ const QVector<Entity *> filteredEntities = dataCacheForLeaf.filterEntitiesByLayer;
+ QVector<Entity *> renderableEntities = isDraw ? cache->renderableEntities : cache->computeEntities;
+ QVector<LightSource> lightSources = cache->gatheredLights;
+ rv->setMaterialParameterTable(dataCacheForLeaf.materialParameterGatherer);
+ rv->setEnvironmentLight(cache->environmentLight);
lock.unlock();
+ ///////// END OF CACHE LOCKED ////////////
// Filter out entities that weren't selected by the layer filters
// Remove all entities from the compute and renderable vectors that aren't in the filtered layer vector
@@ -229,22 +312,52 @@ public:
if (rv->frustumCulling())
renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, m_frustumCullingJob->visibleEntities());
// Filter out entities which didn't satisfy proximity filtering
- renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, m_filterProximityJob->filteredEntities());
+ if (!rv->proximityFilterIds().empty())
+ renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, m_filterProximityJob->filteredEntities());
}
- // Split among the number of command builders
- int i = 0;
- const int m = RenderViewBuilder::optimalJobCount() - 1;
- const int packetSize = renderableEntities.size() / RenderViewBuilder::optimalJobCount();
- while (i < m) {
- const RenderViewBuilderJobPtr renderViewCommandBuilder = m_renderViewBuilderJobs.at(i);
- renderViewCommandBuilder->setRenderables(renderableEntities.mid(i * packetSize, packetSize));
- ++i;
+ // Early return in case we have nothing to filter
+ if (renderableEntities.size() == 0)
+ return;
+
+ // Filter out Render commands for which the Entity wasn't selected because
+ // of frustum, proximity or layer filtering
+ EntityRenderCommandDataPtr filteredCommandData = EntityRenderCommandDataPtr::create();
+ filteredCommandData->reserve(renderableEntities.size());
+ // Because dataCacheForLeaf.renderableEntities or computeEntities are sorted
+ // What we get out of EntityRenderCommandData is also sorted by Entity
+ auto eIt = std::cbegin(renderableEntities);
+ const auto eEnd = std::cend(renderableEntities);
+ int cIt = 0;
+ const int cEnd = commandData.size();
+
+ while (eIt != eEnd) {
+ const Entity *targetEntity = *eIt;
+ // Advance until we have commands whose Entity has a lower address
+ // than the selected filtered entity
+ while (cIt != cEnd && commandData.entities.at(cIt) < targetEntity)
+ ++cIt;
+
+ // Push pointers to command data for all commands that match the
+ // entity
+ while (cIt != cEnd && commandData.entities.at(cIt) == targetEntity) {
+ filteredCommandData->push_back(commandData.entities.at(cIt),
+ commandData.commands.at(cIt),
+ commandData.passesData.at(cIt));
+ ++cIt;
+ }
+ ++eIt;
}
- m_renderViewBuilderJobs.at(i)->setRenderables(renderableEntities.mid(i * packetSize, packetSize + renderableEntities.size() % (m + 1)));
- {
- QMutexLocker rendererCacheLock(m_renderer->cache()->mutex());
- rv->setMaterialParameterTable(m_renderer->cache()->leafNodeCache.value(m_leafNode).materialParameterGatherer);
+
+ // Split among the number of command builders
+ // The idealPacketSize is at least 100 entities per worker
+ const int idealPacketSize = std::min(std::max(100, filteredCommandData->size() / RenderViewBuilder::optimalJobCount()), filteredCommandData->size());
+ const int m = findIdealNumberOfWorkers(filteredCommandData->size(), idealPacketSize);
+
+ for (int i = 0; i < m; ++i) {
+ const RenderViewCommandUpdaterJobPtr renderViewCommandBuilder = m_renderViewCommandUpdaterJobs.at(i);
+ const int count = (i == m - 1) ? filteredCommandData->size() - (i * idealPacketSize) : idealPacketSize;
+ renderViewCommandBuilder->setRenderables(filteredCommandData, i * idealPacketSize, count);
}
}
}
@@ -254,9 +367,11 @@ private:
FrustumCullingJobPtr m_frustumCullingJob;
FilterProximityDistanceJobPtr m_filterProximityJob;
QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
Renderer *m_renderer;
FrameGraphNode *m_leafNode;
+ bool m_fullRebuild;
};
class SetClearDrawBufferIndex
@@ -335,84 +450,6 @@ private:
FrameGraphNode *m_leafNode;
};
-class SyncLightsGatherer
-{
-public:
- explicit SyncLightsGatherer(LightGathererPtr gatherJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_gatherJob(gatherJob)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- QMutexLocker lock(m_renderer->cache()->mutex());
- RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.gatheredLights = m_gatherJob->lights();
- dataCacheForLeaf.environmentLight = m_gatherJob->takeEnvironmentLight();
- }
-
-private:
- LightGathererPtr m_gatherJob;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
-class SyncRenderableEntities
-{
-public:
- explicit SyncRenderableEntities(RenderableEntityFilterPtr gatherJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_gatherJob(gatherJob)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- QMutexLocker lock(m_renderer->cache()->mutex());
- RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.renderableEntities = m_gatherJob->filteredEntities();
- std::sort(dataCacheForLeaf.renderableEntities.begin(), dataCacheForLeaf.renderableEntities.end());
- }
-
-private:
- RenderableEntityFilterPtr m_gatherJob;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
-class SyncComputableEntities
-{
-public:
- explicit SyncComputableEntities(ComputableEntityFilterPtr gatherJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_gatherJob(gatherJob)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- QMutexLocker lock(m_renderer->cache()->mutex());
- RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.computeEntities = m_gatherJob->filteredEntities();
- std::sort(dataCacheForLeaf.computeEntities.begin(), dataCacheForLeaf.computeEntities.end());
- }
-
-private:
- ComputableEntityFilterPtr m_gatherJob;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
} // anonymous
RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int renderViewIndex, Renderer *renderer)
@@ -421,13 +458,11 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende
, m_renderer(renderer)
, m_layerCacheNeedsToBeRebuilt(false)
, m_materialGathererCacheNeedsToBeRebuilt(false)
- , m_lightsCacheNeedsToBeRebuilt(false)
- , m_renderableCacheNeedsToBeRebuilt(false)
- , m_computableCacheNeedsToBeRebuilt(false)
+ , m_renderCommandCacheNeedsToBeRebuilt(false)
, m_renderViewJob(RenderViewInitializerJobPtr::create())
, m_filterEntityByLayerJob()
, m_frustumCullingJob(new Render::FrustumCullingJob())
- , m_syncFrustumCullingJob(SynchronizerJobPtr::create(SyncFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling))
+ , m_syncPreFrustumCullingJob(SynchronizerJobPtr::create(SyncPreFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling))
, m_setClearDrawBufferIndexJob(SynchronizerJobPtr::create(SetClearDrawBufferIndex(m_renderViewJob), JobTypes::ClearBufferDrawIndex))
, m_syncFilterEntityByLayerJob()
, m_filterProximityJob(Render::FilterProximityDistanceJobPtr::create())
@@ -444,54 +479,49 @@ FilterLayerEntityJobPtr RenderViewBuilder::filterEntityByLayerJob() const
return m_filterEntityByLayerJob;
}
-LightGathererPtr RenderViewBuilder::lightGathererJob() const
-{
- return m_lightGathererJob;
-}
-
-RenderableEntityFilterPtr RenderViewBuilder::renderableEntityFilterJob() const
+FrustumCullingJobPtr RenderViewBuilder::frustumCullingJob() const
{
- return m_renderableEntityFilterJob;
+ return m_frustumCullingJob;
}
-ComputableEntityFilterPtr RenderViewBuilder::computableEntityFilterJob() const
+QVector<RenderViewCommandUpdaterJobPtr> RenderViewBuilder::renderViewCommandUpdaterJobs() const
{
- return m_computableEntityFilterJob;
+ return m_renderViewCommandUpdaterJobs;
}
-FrustumCullingJobPtr RenderViewBuilder::frustumCullingJob() const
+QVector<RenderViewCommandBuilderJobPtr> RenderViewBuilder::renderViewCommandBuilderJobs() const
{
- return m_frustumCullingJob;
+ return m_renderViewCommandBuilderJobs;
}
-QVector<RenderViewBuilderJobPtr> RenderViewBuilder::renderViewBuilderJobs() const
+QVector<MaterialParameterGathererJobPtr> RenderViewBuilder::materialGathererJobs() const
{
- return m_renderViewBuilderJobs;
+ return m_materialGathererJobs;
}
-QVector<MaterialParameterGathererJobPtr> RenderViewBuilder::materialGathererJobs() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPostInitializationJob() const
{
- return m_materialGathererJobs;
+ return m_syncRenderViewPostInitializationJob;
}
-SynchronizerJobPtr RenderViewBuilder::syncRenderViewInitializationJob() const
+SynchronizerJobPtr RenderViewBuilder::syncPreFrustumCullingJob() const
{
- return m_syncRenderViewInitializationJob;
+ return m_syncPreFrustumCullingJob;
}
-SynchronizerJobPtr RenderViewBuilder::syncFrustumCullingJob() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPreCommandBuildingJob() const
{
- return m_syncFrustumCullingJob;
+ return m_syncRenderViewPreCommandBuildingJob;
}
-SynchronizerJobPtr RenderViewBuilder::syncRenderCommandBuildingJob() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPreCommandUpdateJob() const
{
- return m_syncRenderCommandBuildingJob;
+ return m_syncRenderViewPreCommandUpdateJob;
}
-SynchronizerJobPtr RenderViewBuilder::syncRenderViewCommandBuildersJob() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPostCommandUpdateJob() const
{
- return m_syncRenderViewCommandBuildersJob;
+ return m_syncRenderViewPostCommandUpdateJob;
}
SynchronizerJobPtr RenderViewBuilder::setClearDrawBufferIndexJob() const
@@ -517,37 +547,21 @@ FilterProximityDistanceJobPtr RenderViewBuilder::filterProximityJob() const
void RenderViewBuilder::prepareJobs()
{
// Init what we can here
- EntityManager *entityManager = m_renderer->nodeManagers()->renderNodesManager();
m_filterProximityJob->setManager(m_renderer->nodeManagers());
m_frustumCullingJob->setRoot(m_renderer->sceneRoot());
- if (m_lightsCacheNeedsToBeRebuilt) {
- m_lightGathererJob = Render::LightGathererPtr::create();
- m_lightGathererJob->setManager(entityManager);
-
- m_cacheLightsJob = SynchronizerJobPtr::create(SyncLightsGatherer(m_lightGathererJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
- m_cacheLightsJob->addDependency(m_lightGathererJob);
- }
-
- if (m_renderableCacheNeedsToBeRebuilt) {
- m_renderableEntityFilterJob = RenderableEntityFilterPtr::create();
- m_renderableEntityFilterJob->setManager(entityManager);
-
- m_cacheRenderableEntitiesJob = SynchronizerJobPtr::create(
- SyncRenderableEntities(m_renderableEntityFilterJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
- m_cacheRenderableEntitiesJob->addDependency(m_renderableEntityFilterJob);
- }
-
- if (m_computableCacheNeedsToBeRebuilt) {
- m_computableEntityFilterJob = ComputableEntityFilterPtr::create();
- m_computableEntityFilterJob->setManager(entityManager);
+ if (m_renderCommandCacheNeedsToBeRebuilt) {
- m_cacheComputableEntitiesJob = SynchronizerJobPtr::create(
- SyncComputableEntities(m_computableEntityFilterJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
- m_cacheComputableEntitiesJob->addDependency(m_computableEntityFilterJob);
+ m_renderViewCommandBuilderJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
+ for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) {
+ auto renderViewCommandBuilder = Render::RenderViewCommandBuilderJobPtr::create();
+ m_renderViewCommandBuilderJobs.push_back(renderViewCommandBuilder);
+ }
+ m_syncRenderViewPreCommandBuildingJob = SynchronizerJobPtr::create(SyncPreCommandBuilding(m_renderViewJob,
+ m_renderViewCommandBuilderJobs,
+ m_renderer,
+ m_leafNode),
+ JobTypes::SyncRenderViewPreCommandBuilding);
}
m_renderViewJob->setRenderer(m_renderer);
@@ -556,12 +570,11 @@ void RenderViewBuilder::prepareJobs()
// RenderCommand building is the most consuming task -> split it
// Estimate the number of jobs to create based on the number of entities
- m_renderViewBuilderJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
+ m_renderViewCommandUpdaterJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) {
- auto renderViewCommandBuilder = Render::RenderViewBuilderJobPtr::create();
- renderViewCommandBuilder->setIndex(m_renderViewIndex);
- renderViewCommandBuilder->setRenderer(m_renderer);
- m_renderViewBuilderJobs.push_back(renderViewCommandBuilder);
+ auto renderViewCommandUpdater = Render::RenderViewCommandUpdaterJobPtr::create();
+ renderViewCommandUpdater->setRenderer(m_renderer);
+ m_renderViewCommandUpdaterJobs.push_back(renderViewCommandUpdater);
}
if (m_materialGathererCacheNeedsToBeRebuilt) {
@@ -582,7 +595,7 @@ void RenderViewBuilder::prepareJobs()
m_syncMaterialGathererJob = SynchronizerJobPtr::create(SyncMaterialParameterGatherer(m_materialGathererJobs,
m_renderer,
m_leafNode),
- JobTypes::SyncMaterialGatherer);
+ JobTypes::SyncMaterialGatherer);
}
if (m_layerCacheNeedsToBeRebuilt) {
@@ -594,34 +607,37 @@ void RenderViewBuilder::prepareJobs()
JobTypes::SyncFilterEntityByLayer);
}
- m_syncRenderCommandBuildingJob = SynchronizerJobPtr::create(SyncRenderCommandBuilding(m_renderViewJob,
- m_frustumCullingJob,
- m_filterProximityJob,
- m_materialGathererJobs,
- m_renderViewBuilderJobs,
- m_renderer,
- m_leafNode),
- JobTypes::SyncRenderViewCommandBuilding);
-
- m_syncRenderViewCommandBuildersJob = SynchronizerJobPtr::create(SyncRenderViewCommandBuilders(m_renderViewJob,
- m_renderViewBuilderJobs,
- m_renderer),
- JobTypes::SyncRenderViewCommandBuilder);
-
- m_syncRenderViewInitializationJob = SynchronizerJobPtr::create(SyncRenderViewInitialization(m_renderViewJob,
- m_frustumCullingJob,
- m_filterEntityByLayerJob,
- m_filterProximityJob,
- m_materialGathererJobs,
- m_renderViewBuilderJobs),
- JobTypes::SyncRenderViewInitialization);
+ m_syncRenderViewPreCommandUpdateJob = SynchronizerJobPtr::create(SyncRenderViewPreCommandUpdate(m_renderViewJob,
+ m_frustumCullingJob,
+ m_filterProximityJob,
+ m_materialGathererJobs,
+ m_renderViewCommandUpdaterJobs,
+ m_renderViewCommandBuilderJobs,
+ m_renderer,
+ m_leafNode,
+ m_renderCommandCacheNeedsToBeRebuilt),
+ JobTypes::SyncRenderViewPreCommandUpdate);
+
+ m_syncRenderViewPostCommandUpdateJob = SynchronizerJobPtr::create(SyncRenderViewPostCommandUpdate(m_renderViewJob,
+ m_renderViewCommandUpdaterJobs,
+ m_renderer),
+ JobTypes::SyncRenderViewPostCommandUpdate);
+
+ m_syncRenderViewPostInitializationJob = SynchronizerJobPtr::create(SyncRenderViewPostInitialization(m_renderViewJob,
+ m_frustumCullingJob,
+ m_filterEntityByLayerJob,
+ m_filterProximityJob,
+ m_materialGathererJobs,
+ m_renderViewCommandUpdaterJobs,
+ m_renderViewCommandBuilderJobs),
+ JobTypes::SyncRenderViewInitialization);
}
QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
{
QVector<Qt3DCore::QAspectJobPtr> jobs;
- jobs.reserve(m_materialGathererJobs.size() + m_renderViewBuilderJobs.size() + 11);
+ jobs.reserve(m_materialGathererJobs.size() + m_renderViewCommandUpdaterJobs.size() + 11);
// Set dependencies
@@ -629,97 +645,97 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
// TODO: Maybe only update skinning palettes for non-culled entities
m_renderViewJob->addDependency(m_renderer->updateSkinningPaletteJob());
- m_syncFrustumCullingJob->addDependency(m_renderer->updateWorldTransformJob());
- m_syncFrustumCullingJob->addDependency(m_renderer->updateShaderDataTransformJob());
- m_syncFrustumCullingJob->addDependency(m_syncRenderViewInitializationJob);
+ m_syncPreFrustumCullingJob->addDependency(m_renderer->updateWorldTransformJob());
+ m_syncPreFrustumCullingJob->addDependency(m_renderer->updateShaderDataTransformJob());
+ m_syncPreFrustumCullingJob->addDependency(m_syncRenderViewPostInitializationJob);
m_frustumCullingJob->addDependency(m_renderer->expandBoundingVolumeJob());
- m_frustumCullingJob->addDependency(m_syncFrustumCullingJob);
+ m_frustumCullingJob->addDependency(m_syncPreFrustumCullingJob);
- m_setClearDrawBufferIndexJob->addDependency(m_syncRenderViewInitializationJob);
+ m_setClearDrawBufferIndexJob->addDependency(m_syncRenderViewPostInitializationJob);
- m_syncRenderViewInitializationJob->addDependency(m_renderViewJob);
+ m_syncRenderViewPostInitializationJob->addDependency(m_renderViewJob);
m_filterProximityJob->addDependency(m_renderer->expandBoundingVolumeJob());
- m_filterProximityJob->addDependency(m_syncRenderViewInitializationJob);
+ m_filterProximityJob->addDependency(m_syncRenderViewPostInitializationJob);
- m_syncRenderCommandBuildingJob->addDependency(m_syncRenderViewInitializationJob);
- m_syncRenderCommandBuildingJob->addDependency(m_filterProximityJob);
- m_syncRenderCommandBuildingJob->addDependency(m_frustumCullingJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_syncRenderViewPostInitializationJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_filterProximityJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_frustumCullingJob);
// Ensure the RenderThread won't be able to process dirtyResources
// before they have been completely gathered
- m_syncRenderCommandBuildingJob->addDependency(m_renderer->introspectShadersJob());
- m_syncRenderCommandBuildingJob->addDependency(m_renderer->bufferGathererJob());
- m_syncRenderCommandBuildingJob->addDependency(m_renderer->textureGathererJob());
-
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) {
- renderViewCommandBuilder->addDependency(m_syncRenderCommandBuildingJob);
- m_syncRenderViewCommandBuildersJob->addDependency(renderViewCommandBuilder);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->introspectShadersJob());
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->bufferGathererJob());
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->textureGathererJob());
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->cacheLightJob());
+
+ for (const auto &renderViewCommandUpdater : qAsConst(m_renderViewCommandUpdaterJobs)) {
+ renderViewCommandUpdater->addDependency(m_syncRenderViewPreCommandUpdateJob);
+ m_syncRenderViewPostCommandUpdateJob->addDependency(renderViewCommandUpdater);
}
- m_renderer->frameCleanupJob()->addDependency(m_syncRenderViewCommandBuildersJob);
+ m_renderer->frameCleanupJob()->addDependency(m_syncRenderViewPostCommandUpdateJob);
m_renderer->frameCleanupJob()->addDependency(m_setClearDrawBufferIndexJob);
// Add jobs
jobs.push_back(m_renderViewJob); // Step 1
- if (m_lightsCacheNeedsToBeRebuilt) {
- jobs.push_back(m_lightGathererJob); // Step 1
- jobs.push_back(m_cacheLightsJob);
- m_syncRenderCommandBuildingJob->addDependency(m_cacheLightsJob);
- }
+ jobs.push_back(m_syncRenderViewPostInitializationJob); // Step 2
- if (m_renderableCacheNeedsToBeRebuilt) {
- jobs.push_back(m_renderableEntityFilterJob); // Step 1
- jobs.push_back(m_cacheRenderableEntitiesJob);
- m_syncRenderCommandBuildingJob->addDependency(m_cacheRenderableEntitiesJob);
- }
+ if (m_renderCommandCacheNeedsToBeRebuilt) { // Step 3
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->cacheComputableEntitiesJob());
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->cacheRenderableEntitiesJob());
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_syncRenderViewPostInitializationJob);
- if (m_computableCacheNeedsToBeRebuilt) {
- // Note: do it only if OpenGL 4.3+ available
- jobs.push_back(m_computableEntityFilterJob); // Step 1
- jobs.push_back(m_cacheComputableEntitiesJob);
- m_syncRenderCommandBuildingJob->addDependency(m_cacheComputableEntitiesJob);
- }
+ if (m_materialGathererCacheNeedsToBeRebuilt)
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_syncMaterialGathererJob);
+
+ jobs.push_back(m_syncRenderViewPreCommandBuildingJob);
- jobs.push_back(m_syncRenderViewInitializationJob); // Step 2
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs)) {
+ renderViewCommandBuilder->addDependency(m_syncRenderViewPreCommandBuildingJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(renderViewCommandBuilder);
+ jobs.push_back(renderViewCommandBuilder);
+ }
+ }
if (m_layerCacheNeedsToBeRebuilt) {
m_filterEntityByLayerJob->addDependency(m_renderer->updateEntityLayersJob());
- m_filterEntityByLayerJob->addDependency(m_syncRenderViewInitializationJob);
+ m_filterEntityByLayerJob->addDependency(m_syncRenderViewPostInitializationJob);
m_filterEntityByLayerJob->addDependency(m_renderer->updateTreeEnabledJob());
m_syncFilterEntityByLayerJob->addDependency(m_filterEntityByLayerJob);
- m_syncRenderCommandBuildingJob->addDependency(m_syncFilterEntityByLayerJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_syncFilterEntityByLayerJob);
jobs.push_back(m_filterEntityByLayerJob); // Step 3
jobs.push_back(m_syncFilterEntityByLayerJob); // Step 4
}
- jobs.push_back(m_syncFrustumCullingJob); // Step 3
+ jobs.push_back(m_syncPreFrustumCullingJob); // Step 3
jobs.push_back(m_filterProximityJob); // Step 3
jobs.push_back(m_setClearDrawBufferIndexJob); // Step 3
if (m_materialGathererCacheNeedsToBeRebuilt) {
for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) {
- materialGatherer->addDependency(m_syncRenderViewInitializationJob);
+ materialGatherer->addDependency(m_syncRenderViewPostInitializationJob);
materialGatherer->addDependency(m_renderer->introspectShadersJob());
materialGatherer->addDependency(m_renderer->filterCompatibleTechniqueJob());
jobs.push_back(materialGatherer); // Step3
m_syncMaterialGathererJob->addDependency(materialGatherer);
}
- m_syncRenderCommandBuildingJob->addDependency(m_syncMaterialGathererJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_syncMaterialGathererJob);
jobs.push_back(m_syncMaterialGathererJob); // Step 3
}
jobs.push_back(m_frustumCullingJob); // Step 4
- jobs.push_back(m_syncRenderCommandBuildingJob); // Step 5
+ jobs.push_back(m_syncRenderViewPreCommandUpdateJob); // Step 5
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) // Step 6
+ // Build RenderCommands or Update RenderCommand Uniforms
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandUpdaterJobs)) // Step 6
jobs.push_back(renderViewCommandBuilder);
- jobs.push_back(m_syncRenderViewCommandBuildersJob); // Step 7
+ jobs.push_back(m_syncRenderViewPostCommandUpdateJob); // Step 7
return jobs;
}
@@ -754,34 +770,14 @@ bool RenderViewBuilder::materialGathererCacheNeedsToBeRebuilt() const
return m_materialGathererCacheNeedsToBeRebuilt;
}
-void RenderViewBuilder::setRenderableCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
-{
- m_renderableCacheNeedsToBeRebuilt = needsToBeRebuilt;
-}
-
-bool RenderViewBuilder::renderableCacheNeedsToBeRebuilt() const
-{
- return m_renderableCacheNeedsToBeRebuilt;
-}
-
-void RenderViewBuilder::setComputableCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
-{
- m_computableCacheNeedsToBeRebuilt = needsToBeRebuilt;
-}
-
-bool RenderViewBuilder::computableCacheNeedsToBeRebuilt() const
-{
- return m_computableCacheNeedsToBeRebuilt;
-}
-
-void RenderViewBuilder::setLightGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
+void RenderViewBuilder::setRenderCommandCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
{
- m_lightsCacheNeedsToBeRebuilt = needsToBeRebuilt;
+ m_renderCommandCacheNeedsToBeRebuilt = needsToBeRebuilt;
}
-bool RenderViewBuilder::lightGathererCacheNeedsToBeRebuilt() const
+bool RenderViewBuilder::renderCommandCacheNeedsToBeRebuilt() const
{
- return m_lightsCacheNeedsToBeRebuilt;
+ return m_renderCommandCacheNeedsToBeRebuilt;
}
int RenderViewBuilder::optimalJobCount()
diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
index e223a5f1e..a2ab80e7e 100644
--- a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
+++ b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
@@ -53,15 +53,14 @@
#include <functional>
#include <Qt3DCore/qaspectjob.h>
-#include <Qt3DRender/private/filterentitybycomponentjob_p.h>
#include <Qt3DRender/private/filterlayerentityjob_p.h>
#include <Qt3DRender/private/genericlambdajob_p.h>
#include <Qt3DRender/private/materialparametergathererjob_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
-#include <Qt3DRender/private/renderviewbuilderjob_p.h>
+#include <Qt3DRender/private/renderviewcommandbuilderjob_p.h>
+#include <Qt3DRender/private/renderviewcommandupdaterjob_p.h>
#include <Qt3DRender/private/renderview_p.h>
#include <Qt3DRender/private/frustumcullingjob_p.h>
-#include <Qt3DRender/private/lightgatherer_p.h>
#include <Qt3DRender/private/filterproximitydistancejob_p.h>
QT_BEGIN_NAMESPACE
@@ -73,8 +72,6 @@ namespace Render {
class Renderer;
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
-using ComputableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::ComputeCommand, Render::Material>;
-using RenderableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::GeometryRenderer, Render::Material>;
class Q_AUTOTEST_EXPORT RenderViewBuilder
{
@@ -83,16 +80,15 @@ public:
RenderViewInitializerJobPtr renderViewJob() const;
FilterLayerEntityJobPtr filterEntityByLayerJob() const;
- LightGathererPtr lightGathererJob() const;
- RenderableEntityFilterPtr renderableEntityFilterJob() const;
- ComputableEntityFilterPtr computableEntityFilterJob() const;
FrustumCullingJobPtr frustumCullingJob() const;
- QVector<RenderViewBuilderJobPtr> renderViewBuilderJobs() const;
+ QVector<RenderViewCommandBuilderJobPtr> renderViewCommandBuilderJobs() const;
+ QVector<RenderViewCommandUpdaterJobPtr> renderViewCommandUpdaterJobs() const;
QVector<MaterialParameterGathererJobPtr> materialGathererJobs() const;
- SynchronizerJobPtr syncRenderViewInitializationJob() const;
- SynchronizerJobPtr syncFrustumCullingJob() const;
- SynchronizerJobPtr syncRenderCommandBuildingJob() const;
- SynchronizerJobPtr syncRenderViewCommandBuildersJob() const;
+ SynchronizerJobPtr syncRenderViewPostInitializationJob() const;
+ SynchronizerJobPtr syncPreFrustumCullingJob() const;
+ SynchronizerJobPtr syncRenderViewPreCommandBuildingJob() const;
+ SynchronizerJobPtr syncRenderViewPreCommandUpdateJob() const;
+ SynchronizerJobPtr syncRenderViewPostCommandUpdateJob() const;
SynchronizerJobPtr setClearDrawBufferIndexJob() const;
SynchronizerJobPtr syncFilterEntityByLayerJob() const;
FilterProximityDistanceJobPtr filterProximityJob() const;
@@ -108,15 +104,8 @@ public:
bool layerCacheNeedsToBeRebuilt() const;
void setMaterialGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
bool materialGathererCacheNeedsToBeRebuilt() const;
-
- void setRenderableCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
- bool renderableCacheNeedsToBeRebuilt() const;
-
- void setComputableCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
- bool computableCacheNeedsToBeRebuilt() const;
-
- void setLightGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
- bool lightGathererCacheNeedsToBeRebuilt() const;
+ void setRenderCommandCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
+ bool renderCommandCacheNeedsToBeRebuilt() const;
static int optimalJobCount();
static QVector<Entity *> entitiesInSubset(const QVector<Entity *> &entities, const QVector<Entity *> &subset);
@@ -127,32 +116,25 @@ private:
Renderer *m_renderer;
bool m_layerCacheNeedsToBeRebuilt;
bool m_materialGathererCacheNeedsToBeRebuilt;
- bool m_lightsCacheNeedsToBeRebuilt;
- bool m_renderableCacheNeedsToBeRebuilt;
- bool m_computableCacheNeedsToBeRebuilt;
+ bool m_renderCommandCacheNeedsToBeRebuilt;
RenderViewInitializerJobPtr m_renderViewJob;
FilterLayerEntityJobPtr m_filterEntityByLayerJob;
- LightGathererPtr m_lightGathererJob;
- RenderableEntityFilterPtr m_renderableEntityFilterJob;
- ComputableEntityFilterPtr m_computableEntityFilterJob;
FrustumCullingJobPtr m_frustumCullingJob;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
- SynchronizerJobPtr m_syncRenderViewInitializationJob;
- SynchronizerJobPtr m_syncFrustumCullingJob;
- SynchronizerJobPtr m_syncRenderCommandBuildingJob;
- SynchronizerJobPtr m_syncRenderViewCommandBuildersJob;
+ SynchronizerJobPtr m_syncRenderViewPostInitializationJob;
+ SynchronizerJobPtr m_syncPreFrustumCullingJob;
+ SynchronizerJobPtr m_syncRenderViewPreCommandBuildingJob;
+ SynchronizerJobPtr m_syncRenderViewPreCommandUpdateJob;
+ SynchronizerJobPtr m_syncRenderViewPostCommandUpdateJob;
SynchronizerJobPtr m_setClearDrawBufferIndexJob;
SynchronizerJobPtr m_syncFilterEntityByLayerJob;
SynchronizerJobPtr m_syncMaterialGathererJob;
FilterProximityDistanceJobPtr m_filterProximityJob;
- SynchronizerJobPtr m_cacheRenderableEntitiesJob;
- SynchronizerJobPtr m_cacheComputableEntitiesJob;
- SynchronizerJobPtr m_cacheLightsJob;
-
static const int m_optimalParallelJobCount;
};
diff --git a/src/render/renderers/opengl/renderer/shaderparameterpack.cpp b/src/render/renderers/opengl/renderer/shaderparameterpack.cpp
index 13d05cac1..1cfb59343 100644
--- a/src/render/renderers/opengl/renderer/shaderparameterpack.cpp
+++ b/src/render/renderers/opengl/renderer/shaderparameterpack.cpp
@@ -57,7 +57,6 @@ namespace Render {
ShaderParameterPack::~ShaderParameterPack()
{
- m_uniforms.clear();
}
void ShaderParameterPack::setUniform(const int glslNameId, const UniformValue &val)
diff --git a/src/render/renderers/opengl/renderer/shaderparameterpack_p.h b/src/render/renderers/opengl/renderer/shaderparameterpack_p.h
index a5aee6ac4..cb599124c 100644
--- a/src/render/renderers/opengl/renderer/shaderparameterpack_p.h
+++ b/src/render/renderers/opengl/renderer/shaderparameterpack_p.h
@@ -89,7 +89,56 @@ struct BlockToSSBO {
QT3D_DECLARE_TYPEINFO_2(Qt3DRender, Render, BlockToSSBO, Q_PRIMITIVE_TYPE)
-typedef QHash<int, UniformValue> PackUniformHash;
+struct PackUniformHash
+{
+ QVector<int> keys;
+ QVector<UniformValue> values;
+
+ PackUniformHash()
+ {
+ keys.reserve(10);
+ values.reserve(10);
+ }
+
+ void insert(int key, const UniformValue &value)
+ {
+ const int idx = keys.indexOf(key);
+ if (idx != -1) {
+ values[idx] = value;
+ } else {
+ keys.push_back(key);
+ values.push_back(value);
+ }
+ }
+
+ UniformValue value(int key) const
+ {
+ const int idx = keys.indexOf(key);
+ if (idx != -1)
+ return values.at(idx);
+ return UniformValue();
+ }
+
+ UniformValue& value(int key)
+ {
+ const int idx = keys.indexOf(key);
+ if (idx != -1)
+ return values[idx];
+ insert(key, UniformValue());
+ return value(key);
+ }
+
+ void erase(int idx)
+ {
+ keys.removeAt(idx);
+ values.removeAt(idx);
+ }
+
+ bool contains(int key) const
+ {
+ return keys.contains(key);
+ }
+};
class Q_AUTOTEST_EXPORT ShaderParameterPack
{
diff --git a/src/render/renderers/opengl/textures/gltexture.cpp b/src/render/renderers/opengl/textures/gltexture.cpp
index 1b5a972ec..20e6007a0 100644
--- a/src/render/renderers/opengl/textures/gltexture.cpp
+++ b/src/render/renderers/opengl/textures/gltexture.cpp
@@ -232,11 +232,9 @@ void GLTexture::loadTextureDataFromImages()
GLTexture::TextureUpdateInfo GLTexture::createOrUpdateGLTexture()
{
TextureUpdateInfo textureInfo;
- m_properties.status = QAbstractTexture::Error;
m_wasTextureRecreated = false;
const bool hasSharedTextureId = m_sharedTextureId > 0;
-
// Only load texture data if we are not using a sharedTextureId
// Check if dataFunctor or images have changed
if (!hasSharedTextureId) {
@@ -269,17 +267,17 @@ GLTexture::TextureUpdateInfo GLTexture::createOrUpdateGLTexture()
// Reset image flag
setDirtyFlag(TextureImageData, false);
}
- }
- // Don't try to create the texture if the target or format was still not set
- // Format should either be set by user or if Automatic
- // by either the dataGenerator of the texture or the first Image
- // Target should explicitly be set by the user or the dataGenerator
- if (m_properties.target == QAbstractTexture::TargetAutomatic ||
- m_properties.format == QAbstractTexture::Automatic ||
- m_properties.format == QAbstractTexture::NoFormat) {
- textureInfo.properties.status = QAbstractTexture::Error;
- return textureInfo;
+ // Don't try to create the texture if the target or format was still not set
+ // Format should either be set by user or if Automatic
+ // by either the dataGenerator of the texture or the first Image
+ // Target should explicitly be set by the user or the dataGenerator
+ if (m_properties.target == QAbstractTexture::TargetAutomatic ||
+ m_properties.format == QAbstractTexture::Automatic ||
+ m_properties.format == QAbstractTexture::NoFormat) {
+ textureInfo.properties.status = QAbstractTexture::Error;
+ return textureInfo;
+ }
}
// If the properties changed or texture has become a shared texture from a
diff --git a/src/render/renderstates/qrastermode.cpp b/src/render/renderstates/qrastermode.cpp
index c432f1063..648872a84 100644
--- a/src/render/renderstates/qrastermode.cpp
+++ b/src/render/renderstates/qrastermode.cpp
@@ -48,7 +48,7 @@ namespace Qt3DRender {
/*!
\class Qt3DRender::QRasterMode
\brief The QRasterMode render state allows to control the type of
- rasterization to be performed
+ rasterization to be performed.
\since 5.14
\inmodule Qt3DRender
\ingroup renderstates
@@ -65,7 +65,7 @@ namespace Qt3DRender {
/*!
\qmltype RasterMode
\brief The RasterMode render state allows to control the type of
- rasterization to be performed
+ rasterization to be performed.
\since 5.14
\inqmlmodule Qt3D.Render
\inherits RenderState
diff --git a/src/render/services/vsyncframeadvanceservice.cpp b/src/render/services/vsyncframeadvanceservice.cpp
index b49870e68..d7398e2ce 100644
--- a/src/render/services/vsyncframeadvanceservice.cpp
+++ b/src/render/services/vsyncframeadvanceservice.cpp
@@ -62,7 +62,7 @@ public:
QSemaphore m_semaphore;
QElapsedTimer m_elapsed;
- quint64 m_elapsedTimeSincePreviousFrame;
+ qint64 m_elapsedTimeSincePreviousFrame;
bool m_drivenByRenderThread;
};
@@ -75,14 +75,19 @@ VSyncFrameAdvanceService::~VSyncFrameAdvanceService()
{
}
-// Aspect Thread
+// Main Thread
qint64 VSyncFrameAdvanceService::waitForNextFrame()
{
Q_D(VSyncFrameAdvanceService);
+#ifdef Q_OS_MACOS
+ if (!d->m_semaphore.tryAcquire(std::max(d->m_semaphore.available(), 1), 4))
+ return -1;
+#else
d->m_semaphore.acquire(std::max(d->m_semaphore.available(), 1));
+#endif
- const quint64 currentTime = d->m_elapsed.nsecsElapsed();
+ const qint64 currentTime = d->m_elapsed.nsecsElapsed();
qCDebug(VSyncAdvanceService) << "Elapsed nsecs since last call " << currentTime - d->m_elapsedTimeSincePreviousFrame;
d->m_elapsedTimeSincePreviousFrame = currentTime;
return currentTime;
diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp
index 7fca2ba3f..258ab44dc 100644
--- a/src/render/texture/qabstracttexture.cpp
+++ b/src/render/texture/qabstracttexture.cpp
@@ -977,7 +977,7 @@ float QAbstractTexture::maximumAnisotropy() const
}
/*!
- \property Qt3DRender::QAbstractTexture::ComparisonFunction
+ \property Qt3DRender::QAbstractTexture::comparisonFunction
Holds the comparison function of the texture provider.
*/
@@ -1008,7 +1008,7 @@ QAbstractTexture::ComparisonFunction QAbstractTexture::comparisonFunction() cons
}
/*!
- \property Qt3DRender::QAbstractTexture::ComparisonMode
+ \property Qt3DRender::QAbstractTexture::comparisonMode
Holds the comparison mode of the texture provider.
*/
@@ -1055,9 +1055,12 @@ QTextureGeneratorPtr QAbstractTexture::dataGenerator() const
*/
/*!
- * \qmlproperty handleType
+ * \qmlproperty enumeration AbstractTexture::handleType
*
* Holds the current texture handle type.
+ *
+ * \value AbstractTexture.NoHandle
+ * \value AbstractTexture.OpenGLTextureId
*/
/*!
@@ -1070,7 +1073,6 @@ QAbstractTexture::HandleType QAbstractTexture::handleType() const
return d->m_handleType;
}
-
/*!
* \property Qt3DRender::QAbstractTexture::handle
*
@@ -1079,7 +1081,7 @@ QAbstractTexture::HandleType QAbstractTexture::handleType() const
*/
/*!
- * \qmlproperty handle
+ * \qmlproperty var AbstractTexture::handle
*
* Holds the current texture handle, if Qt 3D is using the OpenGL renderer,
* handle is a texture id integer.
@@ -1098,8 +1100,8 @@ QVariant QAbstractTexture::handle() const
}
/*!
- * Allow to update a sub region of the texture without having to change the data
- * generator or rely on adding or removing texture images.
+ * Updates a sub region of the texture, defined by \a update, without having
+ * to change the data generator or rely on adding or removing texture images.
* \since 5.14
*/
void QAbstractTexture::updateData(const QTextureDataUpdate &update)
@@ -1135,7 +1137,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QAbstractTexture::createNodeCreationChange()
data.dataFunctor = d->m_dataFunctor;
data.sharedTextureId = d->m_sharedTextureId;
data.initialDataUpdates = d->m_pendingDataUpdates;
- return std::move(creationChange);
+ return creationChange;
}
/*!
diff --git a/src/render/texture/qabstracttextureimage.cpp b/src/render/texture/qabstracttextureimage.cpp
index 9ca4599c5..6f68221fd 100644
--- a/src/render/texture/qabstracttextureimage.cpp
+++ b/src/render/texture/qabstracttextureimage.cpp
@@ -131,8 +131,8 @@ QTextureImageDataGeneratorPtr QAbstractTextureImagePrivate::dataGenerator() cons
/*!
\fn Qt3DRender::QTextureImageDataGeneratorPtr Qt3DRender::QAbstractTextureImage::dataGenerator() const
- Implement this method to return the \l QTextureImageDataGeneratorPtr, which will
- provide the data for the texture image.
+ Implement this method to return the QTextureImageDataGeneratorPtr instance,
+ which will provide the data for the texture image.
*/
/*!
diff --git a/src/render/texture/qtexture.cpp b/src/render/texture/qtexture.cpp
index bca66e630..84a228428 100644
--- a/src/render/texture/qtexture.cpp
+++ b/src/render/texture/qtexture.cpp
@@ -1125,7 +1125,7 @@ TextureDownloadRequest::TextureDownloadRequest(const QTextureFromSourceGenerator
}
-// Executed in aspect thread
+// Executed in main thread
void TextureDownloadRequest::onCompleted()
{
if (cancelled() || !succeeded())
@@ -1142,16 +1142,11 @@ void TextureDownloadRequest::onCompleted()
QTextureFromSourceGeneratorPtr oldGenerator = qSharedPointerCast<QTextureFromSourceGenerator>(texture->dataGenerator());
- // We create a new functor
- // Which is a copy of the old one + the downloaded sourceData
- auto newGenerator = QTextureFromSourceGeneratorPtr::create(*oldGenerator);
-
// Set raw data on functor so that it can really load something
- newGenerator->m_sourceData = m_data;
+ oldGenerator->m_sourceData = m_data;
- // Set new generator on texture
- // it implictely marks the texture as dirty so that the functor runs again with the downloaded data
- texture->setDataGenerator(newGenerator);
+ // Mark the texture as dirty so that the functor runs again with the downloaded data
+ texture->addDirtyFlag(Render::Texture::DirtyDataGenerator);
}
/*!
@@ -1520,7 +1515,10 @@ QTextureLoader::QTextureLoader(QNode *parent)
// Regenerate the texture functor when properties we support overriding
// from QAbstractTexture get changed.
Q_D(QTextureLoader);
- auto regenerate = [=] () { d->updateGenerator(); };
+ auto regenerate = [=] () {
+ if (!notificationsBlocked()) // check the change doesn't come from the backend
+ d->updateGenerator();
+ };
connect(this, &QAbstractTexture::formatChanged, regenerate);
}
diff --git a/src/render/texture/qtexturegenerator.cpp b/src/render/texture/qtexturegenerator.cpp
index 5e350af2d..36b5f6498 100644
--- a/src/render/texture/qtexturegenerator.cpp
+++ b/src/render/texture/qtexturegenerator.cpp
@@ -52,8 +52,7 @@ QTextureGenerator::~QTextureGenerator()
}
/*!
- \class QTextureGenerator
- \inherits QAbstractFunctor
+ \class Qt3DRender::QTextureGenerator
\inmodule Qt3DRender
\brief Provides the image data for a texture.
*/
diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp
index d120c2b39..1414cd337 100644
--- a/src/render/texture/texture.cpp
+++ b/src/render/texture/texture.cpp
@@ -149,6 +149,8 @@ void Texture::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
auto newGenerator = node->dataGenerator();
if (newGenerator != m_dataFunctor) {
setDataGenerator(newGenerator);
+ QAbstractTexturePrivate *dTexture = static_cast<QAbstractTexturePrivate *>(QNodePrivate::get(const_cast<QNode *>(frontEnd)));
+ dTexture->setStatus(QAbstractTexture::Loading);
}
QAbstractTexturePrivate *dnode = dynamic_cast<QAbstractTexturePrivate *>(QAbstractTexturePrivate::get(const_cast<QAbstractTexture *>(node)));
@@ -163,11 +165,11 @@ void Texture::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
m_textureImageIds = ids;
addDirtyFlag(DirtyImageGenerators);
}
- }
- if (dnode->m_sharedTextureId != m_sharedTextureId) {
- m_sharedTextureId = dnode->m_sharedTextureId;
- addDirtyFlag(DirtySharedTextureId);
+ if (dnode->m_sharedTextureId != m_sharedTextureId) {
+ m_sharedTextureId = dnode->m_sharedTextureId;
+ addDirtyFlag(DirtySharedTextureId);
+ }
}
}
diff --git a/tests/auto/animation/animationclip/tst_animationclip.cpp b/tests/auto/animation/animationclip/tst_animationclip.cpp
index 35df21a58..d28a8fc58 100644
--- a/tests/auto/animation/animationclip/tst_animationclip.cpp
+++ b/tests/auto/animation/animationclip/tst_animationclip.cpp
@@ -31,9 +31,7 @@
#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp
index 385398bd1..463656557 100644
--- a/tests/auto/animation/animationutils/tst_animationutils.cpp
+++ b/tests/auto/animation/animationutils/tst_animationutils.cpp
@@ -1047,7 +1047,7 @@ private Q_SLOTS:
mapping.type = static_cast<int>(QVariant::Vector3D);
mapping.channelIndices = QVector<int>() << 0 << 1 << 2;
mapping.callback = &callback;
- mapping.callbackFlags = 0;
+ mapping.callbackFlags = {};
mappingData.push_back(mapping);
channelResults = QVector<float>() << 1.0f << 2.0f << 3.0f;
@@ -1073,7 +1073,7 @@ private Q_SLOTS:
mapping.type = static_cast<int>(QVariant::Double);
mapping.channelIndices = QVector<int>() << 0;
mapping.callback = &callback;
- mapping.callbackFlags = 0;
+ mapping.callbackFlags = {};
mappingData.push_back(mapping);
channelResults = QVector<float>() << 1.0f;
diff --git a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp
index bb95fe979..fb741050b 100644
--- a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp
+++ b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp
@@ -33,7 +33,6 @@
#include <Qt3DAnimation/qblendedclipanimator.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
@@ -44,7 +43,6 @@
#include <Qt3DAnimation/qchannelmapper.h>
#include <Qt3DAnimation/private/qblendedclipanimator_p.h>
#include <Qt3DAnimation/private/blendedclipanimator_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
class tst_BlendedClipAnimator : public Qt3DCore::QBackendNodeTester
diff --git a/tests/auto/animation/channelmapping/tst_channelmapping.cpp b/tests/auto/animation/channelmapping/tst_channelmapping.cpp
index e108e3d26..26a57449d 100644
--- a/tests/auto/animation/channelmapping/tst_channelmapping.cpp
+++ b/tests/auto/animation/channelmapping/tst_channelmapping.cpp
@@ -38,7 +38,6 @@
#include <Qt3DCore/qskeleton.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include "testpostmanarbiter.h"
@@ -181,16 +180,31 @@ private Q_SLOTS:
const char *testName = "translation";
QCOMPARE(qstrcmp(testName, backendMapping.propertyName()), 0);
+ }
-// // WHEN
-// const auto skeletonId = Qt3DCore::QNodeId::createId();
-// updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
-// updateChange->setPropertyName("skeleton");
-// updateChange->setValue(QVariant::fromValue(skeletonId));
-// backendMapping.sceneChangeEvent(updateChange);
+ void checkSkeletonPropertyUpdate()
+ {
+ // GIVEN
+ Qt3DAnimation::QSkeletonMapping mapping;
+ Qt3DAnimation::Animation::Handler handler;
+ Qt3DAnimation::Animation::ChannelMapping backendMapping;
+ backendMapping.setHandler(&handler);
+ simulateInitializationSync(&mapping, &backendMapping);
-// // THEN
-// QCOMPARE(backendMapping.skeletonId(), skeletonId);
+ // WHEN
+ mapping.setEnabled(false);
+ backendMapping.syncFromFrontEnd(&mapping, false);
+
+ // THEN
+ QCOMPARE(backendMapping.isEnabled(), false);
+
+ // WHEN
+ auto skeleton = new Qt3DCore::QSkeleton;
+ mapping.setSkeleton(skeleton);
+ backendMapping.syncFromFrontEnd(&mapping, false);
+
+ // THEN
+ QCOMPARE(backendMapping.skeletonId(), skeleton->id());
}
};
diff --git a/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp b/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp
index 274144d3e..00130add3 100644
--- a/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp
+++ b/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp
@@ -30,7 +30,6 @@
#include <QtTest/QTest>
#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DAnimation/private/qanimationcliploader_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <QObject>
diff --git a/tests/auto/animation/skeleton/tst_skeleton.cpp b/tests/auto/animation/skeleton/tst_skeleton.cpp
index 99acf0b43..d9b209194 100644
--- a/tests/auto/animation/skeleton/tst_skeleton.cpp
+++ b/tests/auto/animation/skeleton/tst_skeleton.cpp
@@ -32,7 +32,6 @@
#include <Qt3DAnimation/private/skeleton_p.h>
#include <Qt3DAnimation/private/handler_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
diff --git a/tests/auto/core/core.pro b/tests/auto/core/core.pro
index 001b947d5..13f4a0dc7 100644
--- a/tests/auto/core/core.pro
+++ b/tests/auto/core/core.pro
@@ -25,10 +25,10 @@ qtConfig(private_tests) {
threadpooler \
qpostman \
vector4d_base \
- vector3d_base
+ vector3d_base \
+ aspectcommanddebugger
QT_FOR_CONFIG += 3dcore-private
- qtConfig(qt3d-profile-jobs): SUBDIRS += aspectcommanddebugger
qtConfig(qt3d-simd-sse2) {
SUBDIRS += \
vector4d_sse \
diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp
index 3b93e7715..87f66bab2 100644
--- a/tests/auto/core/nodes/tst_nodes.cpp
+++ b/tests/auto/core/nodes/tst_nodes.cpp
@@ -40,6 +40,7 @@
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/private/qaspectengine_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
#include <private/qabstractaspect_p.h>
#include <private/qpostman_p.h>
@@ -92,6 +93,7 @@ private slots:
void checkConstructionWithNonRootParent(); // QTBUG-73986
void checkConstructionAsListElement();
void checkSceneIsSetOnConstructionWithParent(); // QTBUG-69352
+ void checkSubNodePostConstructIsCalledWhenReferincingNodeProperty(); // QTBUG-79350
void appendingComponentToEntity();
void appendingParentlessComponentToEntityWithoutScene();
@@ -290,22 +292,15 @@ public slots:
if (!attribute->parent())
attribute->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), attribute);
- change->setPropertyName("attribute");
- d->notifyObservers(change);
- }
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueAdded);
}
}
void removeAttribute(MyQNode *attribute)
{
Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), attribute);
- change->setPropertyName("attribute");
- d->notifyObservers(change);
- }
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved);
+
m_attributes.removeOne(attribute);
// Remove bookkeeping connection
d->unregisterDestructionHelper(attribute);
@@ -384,11 +379,7 @@ public:
if (!attribute->parent())
attribute->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), attribute);
- change->setPropertyName("attribute");
- d->notifyObservers(change);
- }
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved);
}
}
@@ -435,6 +426,29 @@ public:
}
};
+class MyFakeMaterial : public Qt3DCore::QComponent
+{
+ Q_OBJECT
+public:
+ explicit MyFakeMaterial(Qt3DCore::QNode *parent = nullptr)
+ : QComponent(parent)
+ , m_effect(new MyQNode(this))
+ , m_technique(new MyQNode(m_effect))
+ , m_renderPass(new MyQNode(m_technique))
+ {
+ }
+
+ void setArbiter(Qt3DCore::QAbstractArbiter *arbiter)
+ {
+ Q_ASSERT(arbiter);
+ Qt3DCore::QComponentPrivate::get(this)->setArbiter(arbiter);
+ }
+
+ MyQNode *m_effect;
+ MyQNode *m_technique;
+ MyQNode *m_renderPass;
+};
+
class TestAspectPrivate;
class TestAspect : public Qt3DCore::QAbstractAspect
{
@@ -1543,20 +1557,8 @@ void tst_Nodes::checkConstructionAsListElement()
QCoreApplication::processEvents();
QCOMPARE(root->children().count(), 1);
- QCOMPARE(spy.events.size(), 2); // 1 child added change, 1 property change
-
- const auto newChildEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
- QVERIFY(!newChildEvent.isNull());
- QCOMPARE(newChildEvent->subjectId(), root->id());
- QCOMPARE(newChildEvent->propertyName(), "children");
- QCOMPARE(newChildEvent->addedNodeId(), node->id());
-
- // Ensure second and last event is property set change
- const auto propertyEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
- QVERIFY(!propertyEvent.isNull());
- QCOMPARE(propertyEvent->subjectId(), root->id());
- QCOMPARE(propertyEvent->propertyName(), "attribute");
- QCOMPARE(newChildEvent->addedNodeId(), node->id());
+ QCOMPARE(spy.dirtyNodes.size(), 1); // 1 property change
+ QCOMPARE(spy.dirtySubNodes.size(), 1); // 1 child added change
}
void tst_Nodes::checkSceneIsSetOnConstructionWithParent()
@@ -1605,6 +1607,52 @@ void tst_Nodes::checkSceneIsSetOnConstructionWithParent()
QCOMPARE(spy.dirtySubNodes.size(), 5); // 5 entities changed
}
+void tst_Nodes::checkSubNodePostConstructIsCalledWhenReferincingNodeProperty()
+{
+ // GIVEN
+ ObserverSpy spy;
+ Qt3DCore::QAspectEngine engine;
+ Qt3DCore::QScene scene(&engine);
+ QScopedPointer<MyQNode> root(new MyQNode());
+
+ // WHEN
+ root->setArbiterAndScene(&spy, &scene);
+ root->setSimulateBackendCreated(true);
+
+ // THEN
+ QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->scene() != nullptr);
+
+ // WHEN
+ Qt3DCore::QEntity *subTreeRoot = new Qt3DCore::QEntity(root.data());
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(Qt3DCore::QNodePrivate::get(subTreeRoot)->m_hasBackendNode);
+
+ // WHEN
+ MyFakeMaterial *material = new MyFakeMaterial(subTreeRoot);
+ subTreeRoot->addComponent(material);
+
+ // THEN
+ QVERIFY(Qt3DCore::QNodePrivate::get(material)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(material->m_effect)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(material->m_technique)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(material->m_renderPass)->m_hasBackendNode);
+
+ // WHEN
+ MyQNode *fakeRenderState = new MyQNode(material);
+ Qt3DCore::QNodePrivate *dPtr = Qt3DCore::QNodePrivate::get(fakeRenderState);
+
+ // THEN
+ QVERIFY(!dPtr->m_hasBackendNode);
+
+ // WHEN
+ material->m_renderPass->addAttribute(fakeRenderState);
+
+ // THEN
+ QVERIFY(dPtr->m_hasBackendNode);
+}
+
void tst_Nodes::appendingParentlessComponentToEntityWithoutScene()
{
// GIVEN
diff --git a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp
index eb20536e6..48443a66f 100644
--- a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp
+++ b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp
@@ -146,6 +146,10 @@ private Q_SLOTS:
void shouldNotCrashInNormalStartupShutdownSequence()
{
+#ifdef Q_OS_MACOS
+ QSKIP("Test frequently times out. See QTBUG-80660.");
+#endif
+
// GIVEN
// An initialized aspect engine...
QAspectEngine engine;
@@ -168,7 +172,7 @@ private Q_SLOTS:
engine.setRootEntity(entity);
QEventLoop eventLoop;
- QTimer::singleShot(100, &eventLoop, SLOT(quit()));
+ QTimer::singleShot(1000, &eventLoop, SLOT(quit()));
eventLoop.exec();
// THEN
@@ -179,7 +183,7 @@ private Q_SLOTS:
// WHEN
// we set an empty/null scene root...
engine.setRootEntity(QEntityPtr());
- QTimer::singleShot(1000, &eventLoop, SLOT(quit()));
+ QTimer::singleShot(600, &eventLoop, SLOT(quit()));
// ...and allow events to process...
eventLoop.exec();
@@ -243,21 +247,21 @@ private Q_SLOTS:
// THEN
QCOMPARE(engine.executeCommand("list aspects").toString(),
- QString("Loaded aspects:\n * fake"));
+ QString("fake"));
// WHEN
engine.registerAspect("otherfake");
// THEN
QCOMPARE(engine.executeCommand("list aspects").toString(),
- QString("Loaded aspects:\n * fake\n * otherfake"));
+ QString("fake\notherfake"));
// WHEN
engine.registerAspect(new FakeAspect3);
// THEN
QCOMPARE(engine.executeCommand("list aspects").toString(),
- QString("Loaded aspects:\n * fake\n * otherfake\n * <unnamed>"));
+ QString("fake\notherfake\n<unnamed>"));
}
void shouldDelegateCommandsToAspects()
diff --git a/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp b/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp
index 4bc04fafa..7d8f6eed6 100644
--- a/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp
+++ b/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp
@@ -166,13 +166,13 @@ void tst_QCircularBuffer::construction()
QVERIFY(circ4.size() == 2);
QVERIFY(circ4.at(0) == 10);
QVERIFY(circ4.at(1) == 10);
- QVERIFY(circ4.refCount().load() == 1);
+ QVERIFY(circ4.refCount().loadRelaxed() == 1);
// Copy construct from circ4. Both circ4 and circ5 should now have a
// refCount() of 2 since we are using implicit sharing.
QCircularBuffer<int> circ5(circ4);
- QVERIFY(circ4.refCount().load() == 2);
- QVERIFY(circ5.refCount().load() == 2);
+ QVERIFY(circ4.refCount().loadRelaxed() == 2);
+ QVERIFY(circ5.refCount().loadRelaxed() == 2);
QVERIFY(circ5.capacity() == 5);
QVERIFY(circ5.size() == 2);
QVERIFY(circ5.at(0) == 10);
@@ -199,7 +199,7 @@ void tst_QCircularBuffer::destruction()
cir->append(MyComplexType(2));
cir->append(MyComplexType(3));
cir->remove(0);
- Q_UNUSED(cir);
+ Q_UNUSED(cir)
// Check that the dtor was called 2 times fewer than the constructor.
// At this stage will still have 2 items in the circular buffer.
@@ -208,7 +208,7 @@ void tst_QCircularBuffer::destruction()
// Destroy the circular buffer and check that the active count
// is 0. (Same number of calls to dtor as have been made to the constructors)
delete cir;
- cir = 0;
+ cir = nullptr;
QVERIFY(MyComplexType::ms_activeCount == 0);
}
@@ -273,7 +273,7 @@ void tst_QCircularBuffer::clear()
circ.clear();
QVERIFY(circ.size() == 0);
QVERIFY(circ.capacity() == 3);
- QVERIFY(circ.refCount().load() == 1);
+ QVERIFY(circ.refCount().loadRelaxed() == 1);
}
void tst_QCircularBuffer::contains()
diff --git a/tests/auto/core/qservicelocator/tst_qservicelocator.cpp b/tests/auto/core/qservicelocator/tst_qservicelocator.cpp
index cde9834b4..40f0610df 100644
--- a/tests/auto/core/qservicelocator/tst_qservicelocator.cpp
+++ b/tests/auto/core/qservicelocator/tst_qservicelocator.cpp
@@ -52,11 +52,8 @@ class DummySystemInfoService : public QSystemInformationService
{
public:
DummySystemInfoService()
- : QSystemInformationService(QStringLiteral("Dummy System Information Service"))
+ : QSystemInformationService(nullptr, QStringLiteral("Dummy System Information Service"))
{}
-
- QStringList aspectNames() const final { return QStringList(); }
- int threadPoolThreadCount() const final { return 4; }
};
@@ -90,8 +87,8 @@ void tst_QServiceLocator::defaultServices()
QSystemInformationService *sysInfo = locator.systemInformation();
QVERIFY(sysInfo != nullptr);
- QVERIFY(sysInfo->description() == QStringLiteral("Null System Information Service"));
- QVERIFY(sysInfo->threadPoolThreadCount() == 0);
+ QVERIFY(sysInfo->description() == QStringLiteral("Default System Information Service"));
+ QVERIFY(sysInfo->threadPoolThreadCount() != 0);
}
void tst_QServiceLocator::addRemoveDefaultService()
@@ -105,7 +102,6 @@ void tst_QServiceLocator::addRemoveDefaultService()
// Get the service from the locator and check it works as expected
QSystemInformationService *service = locator.systemInformation();
QVERIFY(service == dummy.data());
- QVERIFY(service->threadPoolThreadCount() == 4);
// Ensure the other default services work
QOpenGLInformationService *glInfo = locator.openGLInformation();
@@ -118,7 +114,7 @@ void tst_QServiceLocator::addRemoveDefaultService()
QVERIFY(locator.serviceCount() == QServiceLocator::DefaultServiceCount);
// Check the dummy service still exists
- QVERIFY(dummy->threadPoolThreadCount() == 4);
+ QVERIFY(!dummy.isNull());
}
void tst_QServiceLocator::addRemoveUserService()
@@ -138,8 +134,8 @@ void tst_QServiceLocator::addRemoveUserService()
// Ensure the default services work
QSystemInformationService *sysInfo = locator.systemInformation();
QVERIFY(sysInfo != nullptr);
- QVERIFY(sysInfo->description() == QStringLiteral("Null System Information Service"));
- QVERIFY(sysInfo->threadPoolThreadCount() == 0);
+ QVERIFY(sysInfo->description() == QStringLiteral("Default System Information Service"));
+ QVERIFY(sysInfo->threadPoolThreadCount() != 0);
// Remove custom service
locator.unregisterServiceProvider(dummy->type());
diff --git a/tests/auto/core/qskeleton/tst_qskeleton.cpp b/tests/auto/core/qskeleton/tst_qskeleton.cpp
index 299567806..5c88bd754 100644
--- a/tests/auto/core/qskeleton/tst_qskeleton.cpp
+++ b/tests/auto/core/qskeleton/tst_qskeleton.cpp
@@ -30,7 +30,6 @@
#include <Qt3DCore/qskeleton.h>
#include <Qt3DCore/private/qskeleton_p.h>
#include <Qt3DCore/qjoint.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
@@ -160,41 +159,6 @@ private Q_SLOTS:
// THEN Should not crash when the joint is destroyed (tests for failed removal of destruction helper)
}
}
-
- void checkJointCountPropertyUpdate()
- {
- // GIVEN
- TestArbiter arbiter;
- arbiter.setArbiterOnNode(this);
- QSignalSpy spy(this, SIGNAL(jointCountChanged(int)));
- const int newJointCount = 99;
-
- // THEN
- QVERIFY(spy.isValid());
-
- // WHEN
- auto valueChange = QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- valueChange->setPropertyName("jointCount");
- valueChange->setValue(QVariant(newJointCount));
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 1);
- QCOMPARE(arbiter.events.size(), 0);
- QCOMPARE(jointCount(), newJointCount);
-
- // WHEN
- spy.clear();
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 0);
- QCOMPARE(arbiter.events.size(), 0);
- QCOMPARE(jointCount(), newJointCount);
-
- // Cleanup
- QNodePrivate::get(this)->setArbiter(nullptr);
- }
};
QTEST_MAIN(tst_QSkeleton)
diff --git a/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp b/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp
index 7fcdc4bbe..f0f4c3872 100644
--- a/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp
+++ b/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp
@@ -209,71 +209,6 @@ private Q_SLOTS:
QCOMPARE(arbiter.events.size(), 0);
}
}
-
- void checkStatusPropertyUpdate()
- {
- // GIVEN
- qRegisterMetaType<Qt3DCore::QSkeletonLoader::Status>("Status");
- TestArbiter arbiter;
- arbiter.setArbiterOnNode(this);
- QSignalSpy spy(this, SIGNAL(statusChanged(Status)));
- const QSkeletonLoader::Status newStatus = QSkeletonLoader::Error;
-
- // THEN
- QVERIFY(spy.isValid());
-
- // WHEN
- QPropertyUpdatedChangePtr valueChange(new QPropertyUpdatedChange(QNodeId()));
- valueChange->setPropertyName("status");
- valueChange->setValue(QVariant::fromValue(newStatus));
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 1);
- QCOMPARE(arbiter.events.size(), 0);
- QCOMPARE(status(), newStatus);
-
- // WHEN
- spy.clear();
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 0);
- QCOMPARE(arbiter.events.size(), 0);
- QCOMPARE(status(), newStatus);
-
- // Cleanup
- QNodePrivate::get(this)->setArbiter(nullptr);
- }
-
- void checkRootJointPropertyUpdate()
- {
- // GIVEN
- qRegisterMetaType<Qt3DCore::QJoint*>();
- TestArbiter arbiter;
- arbiter.setArbiterOnNode(this);
- QSignalSpy spy(this, SIGNAL(rootJointChanged(Qt3DCore::QJoint*)));
- std::unique_ptr<QJoint> root(new QJoint());
-
- // THEN
- QVERIFY(spy.isValid());
- QVERIFY(rootJoint() == nullptr);
-
- // WHEN
- auto valueChange = QJointChangePtr::create(id());
- valueChange->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- valueChange->setPropertyName("rootJoint");
- valueChange->data = std::move(root);
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 1);
- QCOMPARE(arbiter.dirtyNodes.size(), 1);
- QVERIFY(rootJoint() != nullptr);
-
- // Cleanup
- QNodePrivate::get(this)->setArbiter(nullptr);
- }
};
QTEST_MAIN(tst_QSkeletonLoader)
diff --git a/tests/auto/core/threadpooler/tst_threadpooler.cpp b/tests/auto/core/threadpooler/tst_threadpooler.cpp
index a656c25c1..289f0b103 100644
--- a/tests/auto/core/threadpooler/tst_threadpooler.cpp
+++ b/tests/auto/core/threadpooler/tst_threadpooler.cpp
@@ -182,7 +182,7 @@ void massTestFunction(QVector3D *data)
void tst_ThreadPooler::initTestCase()
{
- m_jobManager = new JobManager(this);
+ m_jobManager = new JobManager(nullptr);
}
void tst_ThreadPooler::cleanupTestCase()
@@ -195,13 +195,13 @@ void tst_ThreadPooler::defaultPerThread()
// GIVEN
QAtomicInt callCounter;
int maxThreadCount = QThread::idealThreadCount();
- callCounter.store(0);
+ callCounter.storeRelaxed(0);
// WHEN
m_jobManager->waitForPerThreadFunction(perThreadFunction, &callCounter);
// THEN
- QVERIFY(maxThreadCount == callCounter.load());
+ QVERIFY(maxThreadCount == callCounter.loadRelaxed());
}
void tst_ThreadPooler::defaultAspectQueue()
@@ -210,7 +210,7 @@ void tst_ThreadPooler::defaultAspectQueue()
QAtomicInt callCounter;
int value = 0; // Not used in this test
QVector<QSharedPointer<Qt3DCore::QAspectJob> > jobList;
- callCounter.store(0);
+ callCounter.storeRelaxed(0);
const int jobCount = 5;
// WHEN
@@ -223,7 +223,7 @@ void tst_ThreadPooler::defaultAspectQueue()
m_jobManager->waitForAllJobs();
// THEN
- QVERIFY(jobCount == callCounter.load());
+ QVERIFY(jobCount == callCounter.loadRelaxed());
}
/*
@@ -236,7 +236,7 @@ void tst_ThreadPooler::doubleAspectQueue()
QAtomicInt callCounter;
int value = 0; // Not used in this test
QVector<QSharedPointer<Qt3DCore::QAspectJob> > jobList;
- callCounter.store(0);
+ callCounter.storeRelaxed(0);
const int jobCount = 3;
// WHEN
@@ -258,7 +258,7 @@ void tst_ThreadPooler::doubleAspectQueue()
m_jobManager->waitForAllJobs();
// THEN
- QVERIFY(jobCount * 2 == callCounter.load());
+ QVERIFY(jobCount * 2 == callCounter.loadRelaxed());
}
/*
@@ -335,7 +335,7 @@ public:
quint64 globalAtomicValue() const
{
- return m_globalAtomic.load();
+ return m_globalAtomic.loadRelaxed();
}
private:
diff --git a/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp b/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp
index 48ac4b3fe..94f02bc1e 100644
--- a/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp
+++ b/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp
@@ -30,11 +30,9 @@
#include <qbackendnodetester.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/abstractaxisinput_p.h>
#include <Qt3DInput/QAbstractAxisInput>
#include <Qt3DInput/private/qabstractaxisinput_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "testdevice.h"
class DummyAxisInput : public Qt3DInput::QAbstractAxisInput
diff --git a/tests/auto/input/action/tst_action.cpp b/tests/auto/input/action/tst_action.cpp
index 6b8b11b80..cc40cef2f 100644
--- a/tests/auto/input/action/tst_action.cpp
+++ b/tests/auto/input/action/tst_action.cpp
@@ -30,7 +30,6 @@
#include <qbackendnodetester.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DInput/private/action_p.h>
diff --git a/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp b/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp
index 0bdaadc46..6f91ce337 100644
--- a/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp
+++ b/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp
@@ -32,11 +32,9 @@
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/analogaxisinput_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/QAnalogAxisInput>
-#include <Qt3DCore/qpropertyupdatedchange.h>
class tst_AnalogAxisInput: public Qt3DCore::QBackendNodeTester
{
diff --git a/tests/auto/input/axis/tst_axis.cpp b/tests/auto/input/axis/tst_axis.cpp
index de9d5c553..ddd59b395 100644
--- a/tests/auto/input/axis/tst_axis.cpp
+++ b/tests/auto/input/axis/tst_axis.cpp
@@ -30,7 +30,6 @@
#include <qbackendnodetester.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DInput/private/axis_p.h>
diff --git a/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp b/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp
index f7d7d32f1..f8d4adcd2 100644
--- a/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp
+++ b/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp
@@ -28,7 +28,6 @@
#include <QtTest/QTest>
#include <qbackendnodetester.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DInput/private/axis_p.h>
diff --git a/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp b/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp
index 5debe4d99..e315ed1dc 100644
--- a/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp
+++ b/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp
@@ -32,11 +32,9 @@
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/buttonaxisinput_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/QButtonAxisInput>
-#include <Qt3DCore/qpropertyupdatedchange.h>
class tst_ButtonAxisInput: public Qt3DCore::QBackendNodeTester
{
diff --git a/tests/auto/input/input.pro b/tests/auto/input/input.pro
index 6169d3f7c..7799c2b89 100644
--- a/tests/auto/input/input.pro
+++ b/tests/auto/input/input.pro
@@ -29,5 +29,6 @@ qtConfig(private_tests) {
mousedevice \
utils \
axisaccumulator \
- axisaccumulatorjob
+ axisaccumulatorjob \
+ qmouseevent
}
diff --git a/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp b/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp
index 985ee1955..c5322eda6 100644
--- a/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp
+++ b/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp
@@ -33,7 +33,6 @@
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/physicaldeviceproxy_p.h>
#include <Qt3DInput/private/qinputdeviceintegration_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include "qbackendnodetester.h"
#include "testdeviceproxy.h"
diff --git a/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp b/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp
index aaf46a54b..bd5da8e3f 100644
--- a/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp
+++ b/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp
@@ -32,9 +32,7 @@
#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p_p.h>
#include <Qt3DInput/private/physicaldeviceproxy_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include "qbackendnodetester.h"
#include "testdeviceproxy.h"
#include "testpostmanarbiter.h"
diff --git a/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp b/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp
index aef76cc0d..bbe184e0e 100644
--- a/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp
+++ b/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp
@@ -29,7 +29,6 @@
#include <QtTest/QTest>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testdeviceproxy.h"
diff --git a/tests/auto/input/qaction/tst_qaction.cpp b/tests/auto/input/qaction/tst_qaction.cpp
index 8d097978f..13c4a2d83 100644
--- a/tests/auto/input/qaction/tst_qaction.cpp
+++ b/tests/auto/input/qaction/tst_qaction.cpp
@@ -27,7 +27,6 @@
****************************************************************************/
#include <QtTest/QTest>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
diff --git a/tests/auto/input/qaxis/tst_qaxis.cpp b/tests/auto/input/qaxis/tst_qaxis.cpp
index 36d434c6a..9b3068442 100644
--- a/tests/auto/input/qaxis/tst_qaxis.cpp
+++ b/tests/auto/input/qaxis/tst_qaxis.cpp
@@ -27,7 +27,6 @@
****************************************************************************/
#include <QtTest/QTest>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
diff --git a/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp b/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp
index e4145ab7a..9f96cd845 100644
--- a/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp
+++ b/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp
@@ -27,7 +27,6 @@
****************************************************************************/
#include <QtTest/QTest>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
diff --git a/tests/auto/input/qmouseevent/qmouseevent.pro b/tests/auto/input/qmouseevent/qmouseevent.pro
new file mode 100644
index 000000000..70f4c6eda
--- /dev/null
+++ b/tests/auto/input/qmouseevent/qmouseevent.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+TARGET = tst_qmouseevent
+
+QT += 3dcore 3dcore-private 3dinput 3dinput-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_qmouseevent.cpp
+
+include(../commons/commons.pri)
diff --git a/tests/auto/input/qmouseevent/tst_qmouseevent.cpp b/tests/auto/input/qmouseevent/tst_qmouseevent.cpp
new file mode 100644
index 000000000..b48afb99d
--- /dev/null
+++ b/tests/auto/input/qmouseevent/tst_qmouseevent.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QTest>
+#include <Qt3DInput/qmouseevent.h>
+#include <QtGui/QMouseEvent>
+#include <QObject>
+#include <QSignalSpy>
+
+class tst_QMouseEvent : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void checkModifiers()
+ {
+ {
+ // GIVEN
+ QT_PREPEND_NAMESPACE(QMouseEvent) event(QEvent::MouseButtonPress,
+ QPointF(500, 500),
+ QPointF(500, 500),
+ Qt::LeftButton,
+ Qt::LeftButton,
+ Qt::NoModifier);
+
+ // WHEN
+ Qt3DInput::QMouseEvent event3D(event);
+
+ // THEN
+ QCOMPARE(event3D.modifiers(), Qt3DInput::QMouseEvent::NoModifier);
+ }
+ {
+ // GIVEN
+ QT_PREPEND_NAMESPACE(QMouseEvent) event(QEvent::MouseButtonPress,
+ QPointF(500, 500),
+ QPointF(500, 500),
+ Qt::LeftButton,
+ Qt::LeftButton,
+ Qt::ShiftModifier);
+
+ // WHEN
+ Qt3DInput::QMouseEvent event3D(event);
+
+ // THEN
+ QCOMPARE(event3D.modifiers(), Qt3DInput::QMouseEvent::ShiftModifier);
+ }
+ {
+ // GIVEN
+ QT_PREPEND_NAMESPACE(QMouseEvent) event(QEvent::MouseButtonPress,
+ QPointF(500, 500),
+ QPointF(500, 500),
+ Qt::LeftButton,
+ Qt::LeftButton,
+ Qt::ShiftModifier|Qt::ControlModifier);
+
+ // WHEN
+ Qt3DInput::QMouseEvent event3D(event);
+
+ // THEN
+ QCOMPARE(int(event3D.modifiers()), int(Qt3DInput::QMouseEvent::ShiftModifier|Qt3DInput::QMouseEvent::ControlModifier));
+ }
+ }
+};
+
+QTEST_MAIN(tst_QMouseEvent)
+
+#include "tst_qmouseevent.moc"
diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp
index 48215bea5..fa1491914 100644
--- a/tests/auto/render/buffer/tst_buffer.cpp
+++ b/tests/auto/render/buffer/tst_buffer.cpp
@@ -157,6 +157,61 @@ private Q_SLOTS:
QVERIFY(backendBuffer.pendingBufferUpdates().empty());
}
+
+ void checkForceFullUploadOnFirstTime()
+ {
+ // GIVEN
+ Qt3DRender::Render::Buffer backendBuffer;
+ Qt3DRender::Render::BufferManager bufferManager;
+ TestRenderer renderer;
+ Qt3DRender::QBuffer frontendBuffer;
+
+ QByteArray data("111456789\0");
+
+ frontendBuffer.setData(data);
+ frontendBuffer.updateData(1, QByteArray("23\0"));
+
+ // THEN
+ QCOMPARE(frontendBuffer.data(), QByteArray("123456789\0"));
+
+ // WHEN
+ backendBuffer.setManager(&bufferManager);
+ backendBuffer.setRenderer(&renderer);
+ simulateInitializationSync(&frontendBuffer, &backendBuffer);
+
+ // THEN
+ QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1);
+ Qt3DRender::QBufferUpdate fullUpdate = backendBuffer.pendingBufferUpdates().first();
+ QCOMPARE(fullUpdate.offset, -1);
+ QVERIFY(fullUpdate.data.isEmpty());
+ QCOMPARE(frontendBuffer.data(), backendBuffer.data());
+
+ backendBuffer.pendingBufferUpdates().clear();
+
+ // WHEN
+ frontendBuffer.updateData(1, QByteArray("00\0"));
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
+
+ // THEN
+ QCOMPARE(frontendBuffer.data(), QByteArray("100456789\0"));
+ QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1);
+ fullUpdate = backendBuffer.pendingBufferUpdates().first();
+ QCOMPARE(fullUpdate.offset, 1);
+ QCOMPARE(fullUpdate.data, QByteArray("00\0"));
+ QCOMPARE(frontendBuffer.data(), backendBuffer.data());
+
+ // WHEN
+ frontendBuffer.updateData(1, QByteArray("22\0"));
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, true);
+
+ // THEN
+ QCOMPARE(frontendBuffer.data(), QByteArray("122456789\0"));
+ fullUpdate = backendBuffer.pendingBufferUpdates().first();
+ QCOMPARE(fullUpdate.offset, -1);
+ QVERIFY(fullUpdate.data.isEmpty());
+ QCOMPARE(frontendBuffer.data(), backendBuffer.data());
+ }
+
void checkPropertyChanges()
{
// GIVEN
@@ -237,10 +292,7 @@ private Q_SLOTS:
backendBuffer.executeFunctor();
// THEN
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "data");
- QCOMPARE(change->value().toByteArray(), QByteArrayLiteral("454"));
+ QCOMPARE(arbiter.events.count(), 0);
QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1);
QCOMPARE(backendBuffer.pendingBufferUpdates().first().offset, -1);
diff --git a/tests/auto/render/commons/testrenderer.cpp b/tests/auto/render/commons/testrenderer.cpp
index 277b2b99b..5a36fecf2 100644
--- a/tests/auto/render/commons/testrenderer.cpp
+++ b/tests/auto/render/commons/testrenderer.cpp
@@ -30,11 +30,7 @@
QT_BEGIN_NAMESPACE
-TestRenderer::TestRenderer()
- : m_changes(0)
- , m_managers(nullptr)
-{
-}
+TestRenderer::TestRenderer() = default;
TestRenderer::~TestRenderer()
{
@@ -60,7 +56,7 @@ void TestRenderer::clearDirtyBits(Qt3DRender::Render::AbstractRenderer::BackendN
void TestRenderer::resetDirty()
{
- m_changes = 0;
+ m_changes = {};
}
QVariant TestRenderer::executeCommand(const QStringList &args)
diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h
index 8d27998a0..05ef4c130 100644
--- a/tests/auto/render/commons/testrenderer.h
+++ b/tests/auto/render/commons/testrenderer.h
@@ -42,33 +42,34 @@ public:
void dumpInfo() const override {}
API api() const override { return AbstractRenderer::OpenGL; }
qint64 time() const override { return 0; }
- void setTime(qint64 time) override { Q_UNUSED(time); }
+ void setTime(qint64 time) override { Q_UNUSED(time) }
void setNodeManagers(Qt3DRender::Render::NodeManagers *m) override { m_managers = m; }
- void setServices(Qt3DCore::QServiceLocator *services) override { Q_UNUSED(services); }
- void setSurfaceExposed(bool exposed) override { Q_UNUSED(exposed); }
+ void setServices(Qt3DCore::QServiceLocator *services) override { Q_UNUSED(services) }
+ void setSurfaceExposed(bool exposed) override { Q_UNUSED(exposed) }
Qt3DRender::Render::NodeManagers *nodeManagers() const override { return m_managers; }
Qt3DCore::QServiceLocator *services() const override { return nullptr; }
void initialize() override {}
void shutdown() override {}
void releaseGraphicsResources() override {}
void render() override {}
- void doRender(bool swapBuffers) override { Q_UNUSED(swapBuffers); }
+ void doRender(bool swapBuffers) override { Q_UNUSED(swapBuffers) }
void cleanGraphicsResources() override {}
bool isRunning() const override { return true; }
- bool shouldRender() override { return true; }
+ bool shouldRender() const override { return true; }
void skipNextFrame() override {}
+ void jobsDone(Qt3DCore::QAspectManager *manager) override { Q_UNUSED(manager) }
QVector<Qt3DCore::QAspectJobPtr> preRenderingJobs() override { return QVector<Qt3DCore::QAspectJobPtr>(); }
QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override { return QVector<Qt3DCore::QAspectJobPtr>(); }
Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override { return Qt3DCore::QAspectJobPtr(); }
Qt3DCore::QAspectJobPtr rayCastingJob() override { return Qt3DCore::QAspectJobPtr(); }
Qt3DCore::QAspectJobPtr syncLoadingJobs() override { return Qt3DCore::QAspectJobPtr(); }
Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override { return Qt3DCore::QAspectJobPtr(); }
- void setSceneRoot(Qt3DRender::Render::Entity *root) override { Q_UNUSED(root); }
+ void setSceneRoot(Qt3DRender::Render::Entity *root) override { Q_UNUSED(root) }
Qt3DRender::Render::Entity *sceneRoot() const override { return nullptr; }
Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const override { return nullptr; }
Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override { return nullptr; }
- void registerEventFilter(Qt3DCore::QEventFilterService *service) override { Q_UNUSED(service); }
- void setSettings(Qt3DRender::Render::RenderSettings *settings) override { Q_UNUSED(settings); }
+ void registerEventFilter(Qt3DCore::QEventFilterService *service) override { Q_UNUSED(service) }
+ void setSettings(Qt3DRender::Render::RenderSettings *settings) override { Q_UNUSED(settings) }
Qt3DRender::Render::RenderSettings *settings() const override { return nullptr; }
void markDirty(Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet changes, Qt3DRender::Render::BackendNode *node) override;
@@ -90,7 +91,7 @@ public:
protected:
Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet m_changes;
- Qt3DRender::Render::NodeManagers *m_managers;
+ Qt3DRender::Render::NodeManagers *m_managers = nullptr;
};
QT_END_NAMESPACE
diff --git a/tests/auto/render/computecommand/tst_computecommand.cpp b/tests/auto/render/computecommand/tst_computecommand.cpp
index 990c0cd98..4dc6b4436 100644
--- a/tests/auto/render/computecommand/tst_computecommand.cpp
+++ b/tests/auto/render/computecommand/tst_computecommand.cpp
@@ -31,12 +31,32 @@
#include <Qt3DRender/qcomputecommand.h>
#include <Qt3DRender/private/qcomputecommand_p.h>
#include <Qt3DRender/private/computecommand_p.h>
+#include <Qt3DRender/private/renderer_p.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DRender/private/managers_p.h>
#include <Qt3DCore/private/qbackendnode_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
#include "testpostmanarbiter.h"
+
+// tst_Renderer is a friend class of Renderer
+class tst_Renderer : public Qt3DRender::Render::Renderer
+{
+public:
+ tst_Renderer()
+ : Qt3DRender::Render::Renderer(Qt3DRender::QRenderAspect::Synchronous)
+ {}
+
+ ~tst_Renderer() {
+ shutdown();
+ }
+};
+
+
class tst_ComputeCommand : public Qt3DCore::QBackendNodeTester
{
Q_OBJECT
@@ -54,6 +74,7 @@ private Q_SLOTS:
QCOMPARE(backendComputeCommand.x(), 1);
QCOMPARE(backendComputeCommand.y(), 1);
QCOMPARE(backendComputeCommand.z(), 1);
+ QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false);
QCOMPARE(backendComputeCommand.runType(), Qt3DRender::QComputeCommand::Continuous);
QCOMPARE(backendComputeCommand.frameCount(), 0);
}
@@ -61,15 +82,27 @@ private Q_SLOTS:
void checkCleanupState()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::ComputeCommand backendComputeCommand;
+ Qt3DRender::QComputeCommand computeCommand;
+ computeCommand.setWorkGroupX(256);
+ computeCommand.setWorkGroupY(512);
+ computeCommand.setWorkGroupZ(128);
+ computeCommand.setRunType(Qt3DRender::QComputeCommand::Manual);
+ computeCommand.trigger(1);
// WHEN
+ backendComputeCommand.setRenderer(&renderer);
+ simulateInitializationSync(&computeCommand, &backendComputeCommand);
+
backendComputeCommand.setEnabled(true);
+ backendComputeCommand.hasReachedFrameCount();
backendComputeCommand.cleanup();
// THEN
QCOMPARE(backendComputeCommand.isEnabled(), false);
+ QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false);
}
void checkInitializeFromPeer()
@@ -207,6 +240,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(backendComputeCommand.frameCount(), 6 - (i + 1));
QCOMPARE(backendComputeCommand.isEnabled(), true);
+ QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false);
QCOMPARE(arbiter.events.size(), 0);
}
@@ -214,15 +248,102 @@ private Q_SLOTS:
backendComputeCommand.updateFrameCount();
// THEN
- QCOMPARE(backendComputeCommand.frameCount(), false);
+ QCOMPARE(backendComputeCommand.hasReachedFrameCount(), true);
+ QCOMPARE(backendComputeCommand.frameCount(), 0);
+ // Backend stays with enabled == true, frontend will be updated
+ // to be disabled and backend should be disabled on the next sync
+
+ // WHEN
+ computeCommand.setEnabled(false);
+ backendComputeCommand.syncFromFrontEnd(&computeCommand, false);
+
+ // THEN
QCOMPARE(backendComputeCommand.isEnabled(), false);
- QCOMPARE(arbiter.events.size(), 1);
- {
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "enabled");
- QCOMPARE(change->value().value<int>(), false);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- }
+ QCOMPARE(backendComputeCommand.frameCount(), 0);
+
+ // WHEN
+ computeCommand.trigger(1);
+ backendComputeCommand.syncFromFrontEnd(&computeCommand, false);
+
+ // THEN
+ QCOMPARE(computeCommand.isEnabled(), true);
+ QCOMPARE(backendComputeCommand.isEnabled(), true);
+ QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false);
+ QCOMPARE(backendComputeCommand.frameCount(), 1);
+ }
+
+ void checkDisablesFrontend()
+ {
+ // GIVEN
+ Qt3DRender::Render::NodeManagers nodeManager;
+ tst_Renderer renderer;
+ TestArbiter arbiter;
+
+ Qt3DCore::QAspectManager manager;
+ Qt3DCore::QScene scene;
+
+ Qt3DCore::QEntity rootEntity;
+ Qt3DCore::QNodePrivate::get(&rootEntity)->setScene(&scene);
+
+ Qt3DRender::QComputeCommand computeCommand;
+ Qt3DRender::Render::ComputeCommand *backendComputeCommand = nullptr;
+
+ renderer.setNodeManagers(&nodeManager);
+
+ // WHEN
+ computeCommand.setParent(&rootEntity);
+ // RootEntity is the entry point to retrieve the scene instance for lookups
+ manager.setRootEntity(&rootEntity, {});
+
+ // THEN
+ QVERIFY(scene.lookupNode(computeCommand.id()) != nullptr);
+
+ // WHEN
+ auto handle = nodeManager.computeJobManager()->getOrAcquireHandle(computeCommand.id());
+ backendComputeCommand = nodeManager.computeJobManager()->data(handle);
+
+ // WHEN
+ computeCommand.setWorkGroupX(256);
+ computeCommand.setWorkGroupY(512);
+ computeCommand.setWorkGroupZ(128);
+ computeCommand.setRunType(Qt3DRender::QComputeCommand::Manual);
+ computeCommand.trigger(1);
+
+ Qt3DCore::QBackendNodePrivate::get(backendComputeCommand)->setArbiter(&arbiter);
+ backendComputeCommand->setRenderer(&renderer);
+ simulateInitializationSync(&computeCommand, backendComputeCommand);
+
+ // THEN
+ QCOMPARE(backendComputeCommand->frameCount(),1);
+ QCOMPARE(backendComputeCommand->isEnabled(), true);
+ QCOMPARE(computeCommand.isEnabled(), true);
+ QCOMPARE(backendComputeCommand->hasReachedFrameCount(), false);
+
+ // WHEN
+ backendComputeCommand->updateFrameCount();
+
+ // THEN
+ QCOMPARE(backendComputeCommand->frameCount(), 0);
+ QCOMPARE(backendComputeCommand->hasReachedFrameCount(), true);
+
+
+ // Still enabled as we have yet to notify the fronted
+ QCOMPARE(backendComputeCommand->isEnabled(), true);
+ QCOMPARE(computeCommand.isEnabled(), true);
+
+ // WHEN
+ renderer.jobsDone(&manager); // so Renderer::sendDisablesToFrontend gets called
+
+ // THEN
+ QCOMPARE(computeCommand.isEnabled(), false);
+ QCOMPARE(backendComputeCommand->hasReachedFrameCount(), false);
+
+ // WHEN
+ backendComputeCommand->syncFromFrontEnd(&computeCommand, false);
+
+ // THEN
+ QCOMPARE(backendComputeCommand->frameCount(), 0);
+ QCOMPARE(backendComputeCommand->isEnabled(), false);
}
};
diff --git a/tests/auto/render/entity/tst_entity.cpp b/tests/auto/render/entity/tst_entity.cpp
index e3b8e756e..93f2614b8 100644
--- a/tests/auto/render/entity/tst_entity.cpp
+++ b/tests/auto/render/entity/tst_entity.cpp
@@ -35,7 +35,6 @@
#include <Qt3DRender/private/entityaccumulator_p.h>
#include <Qt3DRender/QCameraLens>
-#include <Qt3DCore/QPropertyNodeAddedChange>
#include <Qt3DCore/QTransform>
#include <Qt3DRender/QEnvironmentLight>
@@ -151,11 +150,6 @@ private slots:
nodeManagers.renderNodesManager()->getOrCreateResource(dummyFrontendEntity.id());
nodeManagers.renderNodesManager()->getOrCreateResource(dummyFrontendEntityChild.id());
-// TODOSYNC clean up
-// // Send children added event to entity
-// const auto addEntityChange = QPropertyNodeAddedChangePtr::create(dummyFrontendEntity.id(), &dummyFrontendEntityChild);
-// entity.sceneChangeEvent(addEntityChange);
-
// THEN
QVERIFY(!entity.componentUuid<Transform>().isNull());
QVERIFY(!entity.componentUuid<CameraLens>().isNull());
diff --git a/tests/auto/render/objectpicker/tst_objectpicker.cpp b/tests/auto/render/objectpicker/tst_objectpicker.cpp
index 5fc988d47..24fa2159d 100644
--- a/tests/auto/render/objectpicker/tst_objectpicker.cpp
+++ b/tests/auto/render/objectpicker/tst_objectpicker.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/qpickevent.h>
#include <Qt3DRender/qobjectpicker.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "testpostmanarbiter.h"
#include "testrenderer.h"
diff --git a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
index 1bed9fc44..1b65388af 100644
--- a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
+++ b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
@@ -50,7 +50,7 @@ Qt3DCore::QEntity *buildEntityAtDistance(float distance, Qt3DCore::QEntity *pare
// create geometry with a valid bounding volume - a single point is sufficient
auto geometry = new Qt3DRender::QGeometry;
- auto vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, geometry);
+ auto vertexBuffer = new Qt3DRender::QBuffer(geometry);
auto positionAttribute = new Qt3DRender::QAttribute;
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -117,14 +117,20 @@ private Q_SLOTS:
{
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
- Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity);
- Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity);
- Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *targetEntity = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity1 = buildEntityAtDistance(50.0f, rootEntity);
+ Qt3DCore::QEntity *childEntity2 = buildEntityAtDistance(25.0f, rootEntity);
+ Qt3DCore::QEntity *childEntity3 = buildEntityAtDistance(75.0f, rootEntity);
+
+ Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity);
+ proximityFilter->setDistanceThreshold(200.0f);
+ proximityFilter->setEntity(targetEntity);
QTest::newRow("ShouldSelectAll") << rootEntity
- << Qt3DCore::QNodeIdVector()
+ << (Qt3DCore::QNodeIdVector() << proximityFilter->id())
<< (Qt3DCore::QNodeIdVector()
<< rootEntity->id()
+ << targetEntity->id()
<< childEntity1->id()
<< childEntity2->id()
<< childEntity3->id()
diff --git a/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp b/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp
index 24febdac4..6116e031e 100644
--- a/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp
+++ b/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp
@@ -94,7 +94,7 @@ private Q_SLOTS:
{
Qt3DRender::QFrameGraphNode *nodeWithNestedChildren = new MyFrameGraphNode();
Qt3DRender::QFrameGraphNode *child = new MyFrameGraphNode(nodeWithNestedChildren);
- Qt3DCore::QNode *dummy = new Qt3DCore::QNode(nodeWithNestedChildren);
+ new Qt3DCore::QNode(nodeWithNestedChildren);
Qt3DRender::QFrameGraphNode *grandChild = new MyFrameGraphNode(nodeWithNestedChildren);
QVector<Qt3DCore::QNodeId> childIds = {child->id(), grandChild->id()};
QTest::newRow("nodeWithNestedChildren") << nodeWithNestedChildren << childIds << true << 4;
diff --git a/tests/auto/render/raycaster/tst_raycaster.cpp b/tests/auto/render/raycaster/tst_raycaster.cpp
index 72ef396d7..57a1bcf47 100644
--- a/tests/auto/render/raycaster/tst_raycaster.cpp
+++ b/tests/auto/render/raycaster/tst_raycaster.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/qpickevent.h>
#include <Qt3DRender/qraycaster.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "testpostmanarbiter.h"
#include "testrenderer.h"
diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro
index 180ff7ac1..908426570 100644
--- a/tests/auto/render/render.pro
+++ b/tests/auto/render/render.pro
@@ -137,7 +137,6 @@ qtConfig(qt3d-opengl-renderer):qtConfig(private_tests) {
renderviews \
renderqueue \
renderviewbuilder \
- sendrendercapturejob \
gltexture
qtConfig(qt3d-extras) {
diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp
index e1bf8dfd9..0cbc1aefc 100644
--- a/tests/auto/render/renderer/tst_renderer.cpp
+++ b/tests/auto/render/renderer/tst_renderer.cpp
@@ -78,17 +78,7 @@ private Q_SLOTS:
1); // RayCastingJob
// WHEN
- renderer.addRenderCaptureSendRequest(Qt3DCore::QNodeId::createId());
- jobs = renderer.preRenderingJobs();
-
- // THEN
- QCOMPARE(jobs.size(),
- 1 + // PickBoundingVolumeJob
- 1 + // RayCastingJob
- 1); // SendRenderCaptureJob
-
- // WHEN
- renderer.m_sendBufferCaptureJob->addRequest({nullptr, {}});
+ renderer.m_sendBufferCaptureJob->addRequest({Qt3DCore::QNodeId(), {}});
jobs = renderer.preRenderingJobs();
// THEN
@@ -110,20 +100,6 @@ private Q_SLOTS:
1); // SendSetFenceHandlesJob
// Note: pending set fence handles are only cleared when the job is run
- // WHEN
- renderer.m_updatedTextureProperties.push_back({{}, {}});
- jobs = renderer.preRenderingJobs();
-
- // THEN
- QCOMPARE(jobs.size(),
- 1 + // PickBoundingVolumeJob
- 1 + // RayCastingJob
- 1 + // SendBufferCaptureJob
- 1 + // SendSetFenceHandlesJob
- 1); // SendTextureChangesToFrontend
-
- // Note: pending texture changes are only cleared when the job is run
-
// Properly shutdown command thread
renderer.shutdown();
}
@@ -160,6 +136,9 @@ private Q_SLOTS:
const int layerCacheJobCount = 2;
// filterEntityByLayerJob,
// syncFilterEntityByLayerJob
+
+ const int singleRenderViewCommandRebuildJobCount = 1 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount();
+
const int singleRenderViewJobCount = 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount();
// RenderViewBuilder renderViewJob,
// syncRenderViewInitializationJob,
@@ -167,26 +146,68 @@ private Q_SLOTS:
// filterProximityJob,
// setClearDrawBufferIndexJob,
// frustumCullingJob,
- // syncRenderCommandBuldingJob,
- // syncRenderViewCommandBuilderJob
+ // syncRenderCommandUpdateJob,
+ // syncRenderViewCommandPostUpdateJob
// n * (RenderViewCommandBuildJobs)
// WHEN
QVector<Qt3DCore::QAspectJobPtr> jobs = renderer.renderBinJobs();
- // THEN
+ // THEN -> AllDirty
+ // (Renderer is not initialized so FilterCompatibleTechniqueJob
+ // and ShaderGathererJob are not added here)
+ QCOMPARE(jobs.size(),
+ 1 + // EntityEnabledDirty
+ 1 + // WorldTransformJob
+ 1 + // UpdateWorldBoundingVolume
+ 1 + // UpdateShaderDataTransform
+ 1 + // ExpandBoundingVolumeJob
+ 1 + // CalculateBoundingVolumeJob
+ 1 + // UpdateMeshTriangleListJob
+ 1 + // updateSkinningPaletteJob
+ 1 + // SyncLoadingJobs
+ 1 + // updateLevelOfDetailJob
+ 1 + // cleanupJob
+ 1 + // VAOGatherer
+ 1 + // BufferGathererJob
+ 1 + // TexturesGathererJob
+ 1 + // UpdateEntityLayersJob
+ 1 + // LightGathererJob
+ 1 + // CacheLightJob
+ 1 + // RenderableEntityFilterJob
+ 1 + // CacheRenderableEntitiesJob
+ 1 + // ComputableEntityFilterJob
+ 1 + // CacheComputableEntitiesJob
+ singleRenderViewJobCount +
+ singleRenderViewCommandRebuildJobCount +
+ layerCacheJobCount +
+ renderViewBuilderMaterialCacheJobCount);
+
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderQueue->reset();
+
+ // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (Nothing in cache)
+ renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr);
+ jobs = renderer.renderBinJobs();
+
+ // THEN (level
QCOMPARE(jobs.size(),
1 + // updateLevelOfDetailJob
1 + // cleanupJob
1 + // VAOGatherer
1 + // updateSkinningPaletteJob
- 1); // SyncLoadingJobs
+ 1 + // SyncLoadingJobs
+ singleRenderViewJobCount +
+ singleRenderViewCommandRebuildJobCount +
+ renderViewBuilderMaterialCacheJobCount +
+ layerCacheJobCount);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
renderQueue->reset();
- // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt)
+ // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (RV leaf in cache)
renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr);
+ renderer.cache()->leafNodeCache[renderer.m_frameGraphLeaves.first()] = {};
jobs = renderer.renderBinJobs();
// THEN (level
@@ -197,6 +218,7 @@ private Q_SLOTS:
1 + // updateSkinningPaletteJob
1 + // SyncLoadingJobs
singleRenderViewJobCount +
+ singleRenderViewCommandRebuildJobCount +
renderViewBuilderMaterialCacheJobCount +
layerCacheJobCount);
@@ -253,6 +275,7 @@ private Q_SLOTS:
1 + // updateSkinningPaletteJob
1 + // SyncLoadingJobs
singleRenderViewJobCount +
+ singleRenderViewCommandRebuildJobCount +
renderViewBuilderMaterialCacheJobCount);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
@@ -274,6 +297,7 @@ private Q_SLOTS:
1 + // ExpandBoundingVolumeJob
1 + // RenderableEntityFilterPtr
1 + // SyncRenderableEntities
+ singleRenderViewCommandRebuildJobCount +
singleRenderViewJobCount);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
@@ -315,41 +339,6 @@ private Q_SLOTS:
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
renderQueue->reset();
- // WHEN
- renderer.markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr);
- jobs = renderer.renderBinJobs();
-
- // THEN (Renderer is not initialized so FilterCompatibleTechniqueJob
- // and ShaderGathererJob are not added here)
- QCOMPARE(jobs.size(),
- 1 + // EntityEnabledDirty
- 1 + // WorldTransformJob
- 1 + // UpdateWorldBoundingVolume
- 1 + // UpdateShaderDataTransform
- 1 + // ExpandBoundingVolumeJob
- 1 + // CalculateBoundingVolumeJob
- 1 + // UpdateMeshTriangleListJob
- 1 + // updateSkinningPaletteJob
- 1 + // SyncLoadingJobs
- 1 + // updateLevelOfDetailJob
- 1 + // cleanupJob
- 1 + // VAOGatherer
- 1 + // BufferGathererJob
- 1 + // TexturesGathererJob
- 1 + // UpdateEntityLayersJob
- 1 + // LightGathererJob
- 1 + // CacheLightJob
- 1 + // RenderableEntityFilterJob
- 1 + // CacheRenderableEntitiesJob
- 1 + // ComputableEntityFilterJob
- 1 + // CacheComputableEntitiesJob
- singleRenderViewJobCount +
- layerCacheJobCount +
- renderViewBuilderMaterialCacheJobCount);
-
- renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderQueue->reset();
-
// Properly shutdown command thread
renderer.shutdown();
}
diff --git a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
index 96d51a3a9..6024084bd 100644
--- a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
+++ b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
@@ -52,6 +52,7 @@
#include <Qt3DRender/private/qrenderaspect_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
+#include <Qt3DRender/private/filterentitybycomponentjob_p.h>
QT_BEGIN_NAMESPACE
@@ -224,29 +225,29 @@ private Q_SLOTS:
QCOMPARE(renderViewBuilder.materialGathererCacheNeedsToBeRebuilt(), false);
QVERIFY(!renderViewBuilder.renderViewJob().isNull());
QVERIFY(!renderViewBuilder.frustumCullingJob().isNull());
- QVERIFY(!renderViewBuilder.syncFrustumCullingJob().isNull());
+ QVERIFY(!renderViewBuilder.syncPreFrustumCullingJob().isNull());
QVERIFY(!renderViewBuilder.setClearDrawBufferIndexJob().isNull());
QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull());
QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull());
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob().isNull());
- QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob().isNull());
- QVERIFY(renderViewBuilder.syncRenderViewInitializationJob().isNull());
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob().isNull());
+ QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob().isNull());
+ QVERIFY(renderViewBuilder.syncRenderViewPostInitializationJob().isNull());
- QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), 0);
+ QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), 0);
QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0);
// WHEN
renderViewBuilder.prepareJobs();
// THEN
- QVERIFY(!renderViewBuilder.syncRenderCommandBuildingJob().isNull());
- QVERIFY(!renderViewBuilder.syncRenderViewCommandBuildersJob().isNull());
- QVERIFY(!renderViewBuilder.syncRenderViewInitializationJob().isNull());
+ QVERIFY(!renderViewBuilder.syncRenderViewPreCommandUpdateJob().isNull());
+ QVERIFY(!renderViewBuilder.syncRenderViewPostCommandUpdateJob().isNull());
+ QVERIFY(!renderViewBuilder.syncRenderViewPostInitializationJob().isNull());
QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull());
QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull());
- QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
+ QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0);
QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
}
@@ -280,39 +281,6 @@ private Q_SLOTS:
// mark jobs dirty and recheck
QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 9 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
}
-
- {
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setLightGathererCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
-
- // THEN
- QCOMPARE(renderViewBuilder.lightGathererCacheNeedsToBeRebuilt(), true);
- QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
- }
-
- {
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
-
- // THEN
- QCOMPARE(renderViewBuilder.renderableCacheNeedsToBeRebuilt(), true);
- QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
- }
-
- {
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setComputableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
-
- // THEN
- QCOMPARE(renderViewBuilder.computableCacheNeedsToBeRebuilt(), true);
- QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
- }
}
void checkCheckJobDependencies()
@@ -338,8 +306,8 @@ private Q_SLOTS:
// Step 2
- QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1);
- QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().constFirst().toStrongRef().data(),
+ QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().size(), 1);
+ QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().constFirst().toStrongRef().data(),
renderViewBuilder.renderViewJob().data());
// Step 3
@@ -347,43 +315,44 @@ private Q_SLOTS:
QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull());
QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2);
- QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1);
QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(),
- renderViewBuilder.syncRenderViewInitializationJob().data());
+ renderViewBuilder.syncRenderViewPostInitializationJob().data());
- QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3);
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob()));
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
+ QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3);
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob()));
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
// Step 4
QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2);
- QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob()));
+ QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob()));
QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
- QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6);
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->textureGathererJob()));
+ QCOMPARE(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7);
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->cacheLightJob()));
// Step 5
- for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
+ for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) {
QCOMPARE(renderViewBuilderJob->dependencies().size(), 1);
QCOMPARE(renderViewBuilderJob->dependencies().constFirst().toStrongRef().data(),
- renderViewBuilder.syncRenderCommandBuildingJob().data());
+ renderViewBuilder.syncRenderViewPreCommandUpdateJob().data());
}
// Step 6
- QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size());
- for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
- QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob));
+ QCOMPARE(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().size(), renderViewBuilder.renderViewCommandUpdaterJobs().size());
+ for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) {
+ QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().contains(renderViewBuilderJob));
}
}
{
@@ -399,63 +368,63 @@ private Q_SLOTS:
QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update
// Step 2
- QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1);
- QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().constFirst().toStrongRef().data(),
+ QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().size(), 1);
+ QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().constFirst().toStrongRef().data(),
renderViewBuilder.renderViewJob().data());
// Step 3
QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 3);
QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateEntityLayersJob()));
- QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob()));
QCOMPARE(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().size(), 1);
QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob()));
QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2);
- QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1);
QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(),
- renderViewBuilder.syncRenderViewInitializationJob().data());
+ renderViewBuilder.syncRenderViewPostInitializationJob().data());
- QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3);
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob()));
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
+ QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3);
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob()));
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) {
QCOMPARE(materialGatherer->dependencies().size(), 3);
- QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob()));
}
// Step 4
QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2);
- QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob()));
+ QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob()));
QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->textureGathererJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob()));
// Step 5
- for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
+ for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) {
QCOMPARE(renderViewBuilderJob->dependencies().size(), 1);
QCOMPARE(renderViewBuilderJob->dependencies().constFirst().toStrongRef().data(),
- renderViewBuilder.syncRenderCommandBuildingJob().data());
+ renderViewBuilder.syncRenderViewPreCommandUpdateJob().data());
}
// Step 6
- QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size());
- for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
- QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob));
+ QCOMPARE(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().size(), renderViewBuilder.renderViewCommandUpdaterJobs().size());
+ for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) {
+ QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().contains(renderViewBuilderJob));
}
}
}
@@ -487,21 +456,18 @@ private Q_SLOTS:
Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport();
Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport);
Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id());
QVERIFY(leafNode != nullptr);
// WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setLightGathererCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
- renderViewBuilder.buildJobHierachy();
- renderViewBuilder.lightGathererJob()->run();
+ renderer->lightGathererJob()->run();
// THEN
- QCOMPARE(renderViewBuilder.lightGathererJob()->lights().size(), 2);
- QVERIFY(renderViewBuilder.lightGathererJob()->takeEnvironmentLight() != nullptr);
+ QCOMPARE(renderer->lightGathererJob()->lights().size(), 2);
+ QVERIFY(renderer->lightGathererJob()->takeEnvironmentLight() != nullptr);
}
void checkRenderableEntitiesFilteringExecution()
@@ -510,20 +476,17 @@ private Q_SLOTS:
Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport();
Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport);
Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id());
QVERIFY(leafNode != nullptr);
// WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
- renderViewBuilder.buildJobHierachy();
- renderViewBuilder.renderableEntityFilterJob()->run();
+ renderer->renderableEntityFilterJob()->run();
// THEN
- QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->filteredEntities().size(), 1);
+ QCOMPARE(renderer->renderableEntityFilterJob()->filteredEntities().size(), 1);
}
void checkComputableEntitiesFilteringExecution()
@@ -532,20 +495,17 @@ private Q_SLOTS:
Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport();
Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport);
Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id());
QVERIFY(leafNode != nullptr);
// WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setComputableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
- renderViewBuilder.buildJobHierachy();
- renderViewBuilder.computableEntityFilterJob()->run();
+ renderer->computableEntityFilterJob()->run();
// THEN
- QCOMPARE(renderViewBuilder.computableEntityFilterJob()->filteredEntities().size(), 1);
+ QCOMPARE(renderer->computableEntityFilterJob()->filteredEntities().size(), 1);
}
void checkSyncRenderViewInitializationExecution()
@@ -581,7 +541,7 @@ private Q_SLOTS:
// WHEN
renderViewBuilder.renderViewJob()->run();
- renderViewBuilder.syncRenderViewInitializationJob()->run();
+ renderViewBuilder.syncRenderViewPostInitializationJob()->run();
// THEN
QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true);
@@ -608,7 +568,7 @@ private Q_SLOTS:
// WHEN
renderViewBuilder.renderViewJob()->run();
- renderViewBuilder.syncRenderViewInitializationJob()->run();
+ renderViewBuilder.syncRenderViewPostInitializationJob()->run();
// THEN
QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true);
@@ -647,7 +607,7 @@ private Q_SLOTS:
// WHEN
renderViewBuilder.renderViewJob()->run();
- renderViewBuilder.syncFrustumCullingJob()->run();
+ renderViewBuilder.syncPreFrustumCullingJob()->run();
// THEN
QCOMPARE(convertToQMatrix4x4(renderViewBuilder.frustumCullingJob()->viewProjection()), camera->projectionMatrix() * camera->viewMatrix());
@@ -662,24 +622,28 @@ private Q_SLOTS:
Qt3DRender::QLayer *layer = new Qt3DRender::QLayer();
layerFilter->addLayer(layer);
Qt3DRender::TestAspect testAspect(buildEntityFilterTestScene(viewport, layer));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(layerFilter->id());
QVERIFY(leafNode != nullptr);
// WHEN
+ renderer->markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr);
+
Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true);
- renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true);
renderViewBuilder.prepareJobs();
renderViewBuilder.buildJobHierachy();
+ renderer->renderableEntityFilterJob()->run();
+ renderer->cacheRenderableEntitiesJob()->run();
+
renderViewBuilder.renderViewJob()->run();
- renderViewBuilder.renderableEntityFilterJob()->run();
- renderViewBuilder.syncRenderViewInitializationJob()->run();
+ renderViewBuilder.syncRenderViewPostInitializationJob()->run();
renderViewBuilder.filterEntityByLayerJob()->run();
- QVector<Qt3DRender::Render::Entity *> renderableEntity = renderViewBuilder.renderableEntityFilterJob()->filteredEntities();
+ QVector<Qt3DRender::Render::Entity *> renderableEntity = renderer->renderableEntityFilterJob()->filteredEntities();
QVector<Qt3DRender::Render::Entity *> filteredEntity = renderViewBuilder.filterEntityByLayerJob()->filteredEntities();
// THEN
diff --git a/tests/auto/render/renderviews/tst_renderviews.cpp b/tests/auto/render/renderviews/tst_renderviews.cpp
index f38915bf8..1558b68c9 100644
--- a/tests/auto/render/renderviews/tst_renderviews.cpp
+++ b/tests/auto/render/renderviews/tst_renderviews.cpp
@@ -51,16 +51,11 @@ void compareShaderParameterPacks(const ShaderParameterPack &t1,
const PackUniformHash hash1 = t1.uniforms();
const PackUniformHash hash2 = t2.uniforms();
- QCOMPARE(hash1.size(), hash2.size());
+ QCOMPARE(hash1.keys.size(), hash2.keys.size());
- auto it = hash1.constBegin();
- const auto end = hash1.constEnd();
-
- while (it != end) {
- const auto h2It = hash2.find(it.key());
- QVERIFY(h2It != hash2.cend());
- QCOMPARE(it.value(), h2It.value());
- ++it;
+ for (int i = 0, m = hash1.keys.size(); i < m; ++i) {
+ const int key = hash1.keys.at(i);
+ QCOMPARE(hash1.value(key), hash2.value(key));
}
}
@@ -138,14 +133,14 @@ private Q_SLOTS:
{
// GIVEN
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
QVector<QSortPolicy::SortType> sortTypes;
sortTypes.push_back(QSortPolicy::BackToFront);
for (int i = 0; i < 200; ++i) {
- RenderCommand *c = new RenderCommand();
- c->m_depth = float(i);
+ RenderCommand c;
+ c.m_depth = float(i);
rawCommands.push_back(c);
}
@@ -155,10 +150,10 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands.size(), sortedCommands.size());
for (int j = 1; j < sortedCommands.size(); ++j)
- QVERIFY(sortedCommands.at(j - 1)->m_depth > sortedCommands.at(j)->m_depth);
+ QVERIFY(sortedCommands.at(j - 1).m_depth > sortedCommands.at(j).m_depth);
// RenderCommands are deleted by RenderView dtor
}
@@ -167,7 +162,7 @@ private Q_SLOTS:
{
// GIVEN
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
QVector<QSortPolicy::SortType> sortTypes;
sortTypes.push_back(QSortPolicy::Material);
@@ -181,8 +176,8 @@ private Q_SLOTS:
};
for (int i = 0; i < 20; ++i) {
- RenderCommand *c = new RenderCommand();
- c->m_shaderDna = dnas[i % 5];
+ RenderCommand c;
+ c.m_shaderDna = dnas[i % 5];
rawCommands.push_back(c);
}
@@ -192,18 +187,18 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands.size(), sortedCommands.size());
ProgramDNA targetDNA;
for (int j = 0; j < sortedCommands.size(); ++j) {
if (j % 4 == 0) {
- targetDNA = sortedCommands.at(j)->m_shaderDna;
+ targetDNA = sortedCommands.at(j).m_shaderDna;
if (j > 0)
- QVERIFY(targetDNA != sortedCommands.at(j - 1)->m_shaderDna);
+ QVERIFY(targetDNA != sortedCommands.at(j - 1).m_shaderDna);
}
- QCOMPARE(targetDNA, sortedCommands.at(j)->m_shaderDna);
+ QCOMPARE(targetDNA, sortedCommands.at(j).m_shaderDna);
}
// RenderCommands are deleted by RenderView dtor
@@ -247,12 +242,12 @@ private Q_SLOTS:
QFETCH(QVector<ShaderParameterPack>, expectedMinimizedParameters);
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
for (int i = 0, m = programDNAs.size(); i < m; ++i) {
- RenderCommand *c = new RenderCommand();
- c->m_shaderDna = programDNAs.at(i);
- c->m_parameterPack = rawParameters.at(i);
+ RenderCommand c;
+ c.m_shaderDna = programDNAs.at(i);
+ c.m_parameterPack = rawParameters.at(i);
rawCommands.push_back(c);
}
@@ -261,13 +256,13 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands, sortedCommands);
for (int i = 0, m = programDNAs.size(); i < m; ++i) {
- const RenderCommand *c = sortedCommands.at(i);
- QCOMPARE(c->m_shaderDna, programDNAs.at(i));
- compareShaderParameterPacks(c->m_parameterPack, expectedMinimizedParameters.at(i));
+ const RenderCommand c = sortedCommands.at(i);
+ QCOMPARE(c.m_shaderDna, programDNAs.at(i));
+ compareShaderParameterPacks(c.m_parameterPack, expectedMinimizedParameters.at(i));
}
}
@@ -276,14 +271,14 @@ private Q_SLOTS:
{
// GIVEN
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
QVector<QSortPolicy::SortType> sortTypes;
sortTypes.push_back(QSortPolicy::FrontToBack);
for (int i = 0; i < 200; ++i) {
- RenderCommand *c = new RenderCommand();
- c->m_depth = float(i);
+ RenderCommand c;
+ c.m_depth = float(i);
rawCommands.push_back(c);
}
@@ -293,10 +288,10 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands.size(), sortedCommands.size());
for (int j = 1; j < sortedCommands.size(); ++j)
- QVERIFY(sortedCommands.at(j - 1)->m_depth < sortedCommands.at(j)->m_depth);
+ QVERIFY(sortedCommands.at(j - 1).m_depth < sortedCommands.at(j).m_depth);
// RenderCommands are deleted by RenderView dtor
}
@@ -305,14 +300,14 @@ private Q_SLOTS:
{
// GIVEN
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
QVector<QSortPolicy::SortType> sortTypes;
sortTypes.push_back(QSortPolicy::StateChangeCost);
for (int i = 0; i < 200; ++i) {
- RenderCommand *c = new RenderCommand();
- c->m_changeCost = i;
+ RenderCommand c;
+ c.m_changeCost = i;
rawCommands.push_back(c);
}
@@ -322,10 +317,10 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands.size(), sortedCommands.size());
for (int j = 1; j < sortedCommands.size(); ++j)
- QVERIFY(sortedCommands.at(j - 1)->m_changeCost > sortedCommands.at(j)->m_changeCost);
+ QVERIFY(sortedCommands.at(j - 1).m_changeCost > sortedCommands.at(j).m_changeCost);
// RenderCommands are deleted by RenderView dtor
}
@@ -334,7 +329,7 @@ private Q_SLOTS:
{
// GIVEN
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
QVector<QSortPolicy::SortType> sortTypes;
sortTypes.push_back(QSortPolicy::StateChangeCost);
@@ -360,24 +355,24 @@ private Q_SLOTS:
};
auto buildRC = [] (ProgramDNA dna, float depth, int changeCost) {
- RenderCommand *c = new RenderCommand();
- c->m_shaderDna = dna;
- c->m_depth = depth;
- c->m_changeCost = changeCost;
+ RenderCommand c;
+ c.m_shaderDna = dna;
+ c.m_depth = depth;
+ c.m_changeCost = changeCost;
return c;
};
- RenderCommand *c5 = buildRC(dna[3], depth[1], stateChangeCost[1]);
- RenderCommand *c3 = buildRC(dna[3], depth[0], stateChangeCost[1]);
- RenderCommand *c4 = buildRC(dna[2], depth[1], stateChangeCost[1]);
- RenderCommand *c8 = buildRC(dna[1], depth[1], stateChangeCost[1]);
- RenderCommand *c0 = buildRC(dna[0], depth[2], stateChangeCost[1]);
+ RenderCommand c5 = buildRC(dna[3], depth[1], stateChangeCost[1]);
+ RenderCommand c3 = buildRC(dna[3], depth[0], stateChangeCost[1]);
+ RenderCommand c4 = buildRC(dna[2], depth[1], stateChangeCost[1]);
+ RenderCommand c8 = buildRC(dna[1], depth[1], stateChangeCost[1]);
+ RenderCommand c0 = buildRC(dna[0], depth[2], stateChangeCost[1]);
- RenderCommand *c2 = buildRC(dna[2], depth[2], stateChangeCost[0]);
- RenderCommand *c9 = buildRC(dna[2], depth[0], stateChangeCost[0]);
- RenderCommand *c1 = buildRC(dna[1], depth[0], stateChangeCost[0]);
- RenderCommand *c7 = buildRC(dna[0], depth[2], stateChangeCost[0]);
- RenderCommand *c6 = buildRC(dna[0], depth[1], stateChangeCost[0]);
+ RenderCommand c2 = buildRC(dna[2], depth[2], stateChangeCost[0]);
+ RenderCommand c9 = buildRC(dna[2], depth[0], stateChangeCost[0]);
+ RenderCommand c1 = buildRC(dna[1], depth[0], stateChangeCost[0]);
+ RenderCommand c7 = buildRC(dna[0], depth[2], stateChangeCost[0]);
+ RenderCommand c6 = buildRC(dna[0], depth[1], stateChangeCost[0]);
rawCommands << c0 << c1 << c2 << c3 << c4 << c5 << c6 << c7 << c8 << c9;
@@ -387,12 +382,9 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands.size(), sortedCommands.size());
- for (RenderCommand *rc : sortedCommands)
- qDebug() << rc->m_changeCost << rc->m_shaderDna << rc->m_depth;
-
// Ordered by higher state, higher shaderDNA and higher depth
QCOMPARE(c0, sortedCommands.at(4));
QCOMPARE(c3, sortedCommands.at(1));
@@ -423,61 +415,60 @@ private Q_SLOTS:
Qt3DCore::QNodeId tex3 = Qt3DCore::QNodeId::createId();
Qt3DCore::QNodeId tex4 = Qt3DCore::QNodeId::createId();
- RenderCommand *a = new RenderCommand();
+ RenderCommand a;
{
ShaderParameterPack pack;
pack.setTexture(0, 0, tex1);
pack.setTexture(1, 0, tex3);
pack.setTexture(2, 0, tex4);
pack.setTexture(3, 0, tex2);
- a->m_parameterPack = pack;
+ a.m_parameterPack = pack;
}
- RenderCommand *b = new RenderCommand();
- RenderCommand *c = new RenderCommand();
+ RenderCommand b;
+ RenderCommand c;
{
ShaderParameterPack pack;
pack.setTexture(0, 0, tex1);
pack.setTexture(3, 0, tex2);
- c->m_parameterPack = pack;
+ c.m_parameterPack = pack;
}
- RenderCommand *d = new RenderCommand();
+ RenderCommand d;
{
ShaderParameterPack pack;
pack.setTexture(1, 0, tex3);
pack.setTexture(2, 0, tex4);
- d->m_parameterPack = pack;
+ d.m_parameterPack = pack;
}
- RenderCommand *e = new RenderCommand();
+ RenderCommand e;
{
ShaderParameterPack pack;
pack.setTexture(3, 0, tex2);
- e->m_parameterPack = pack;
+ e.m_parameterPack = pack;
}
- RenderCommand *f = new RenderCommand();
+ RenderCommand f;
{
ShaderParameterPack pack;
pack.setTexture(3, 0, tex2);
- f->m_parameterPack = pack;
+ f.m_parameterPack = pack;
}
- RenderCommand *g = new RenderCommand();
+ RenderCommand g;
{
ShaderParameterPack pack;
pack.setTexture(0, 0, tex1);
pack.setTexture(1, 0, tex3);
pack.setTexture(2, 0, tex4);
pack.setTexture(3, 0, tex2);
- g->m_parameterPack = pack;
+ g.m_parameterPack = pack;
}
// WHEN
- QVector<RenderCommand *> rawCommands = {a, b, c, d, e, f, g};
+ QVector<RenderCommand> rawCommands = {a, b, c, d, e, f, g};
renderView.addSortType(sortTypes);
renderView.setCommands(rawCommands);
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
- qDebug() << rawCommands << sortedCommands;
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands.size(), sortedCommands.size());
QCOMPARE(sortedCommands.at(0), a);
QCOMPARE(sortedCommands.at(1), g);
diff --git a/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp
index 4db12136a..fc65d0854 100644
--- a/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp
+++ b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp
@@ -426,12 +426,15 @@ private Q_SLOTS:
simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
- indexData.resize(sizeof(uint) * 2 * 4);
+ indexData.resize(sizeof(uint) * 7);
uint *iDataPtr = reinterpret_cast<uint *>(indexData.data());
iDataPtr[0] = 0;
iDataPtr[1] = 1;
iDataPtr[2] = 2;
iDataPtr[3] = 3;
+ iDataPtr[4] = static_cast<uint>(-1);
+ iDataPtr[5] = 0;
+ iDataPtr[6] = 1;
indexDataBuffer->setData(indexData);
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
@@ -450,7 +453,7 @@ private Q_SLOTS:
indexAttribute->setBuffer(indexDataBuffer.data());
indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt);
- indexAttribute->setCount(4);
+ indexAttribute->setCount(7);
indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
geometry->addAttribute(positionAttribute.data());
@@ -458,6 +461,8 @@ private Q_SLOTS:
geometryRenderer->setGeometry(geometry);
geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineStrip);
+ geometryRenderer->setPrimitiveRestartEnabled(true);
+ geometryRenderer->setRestartIndexValue(-1);
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
@@ -480,10 +485,11 @@ private Q_SLOTS:
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
// THEN
- QCOMPARE(visitor.segmentCount(), uint(3));
+ QCOMPARE(visitor.segmentCount(), uint(4));
QVERIFY(visitor.verifySegment(0, 0,1, Vector3D(0,0,0), Vector3D(1,0,0)));
QVERIFY(visitor.verifySegment(1, 1,2, Vector3D(1,0,0), Vector3D(1,1,0)));
QVERIFY(visitor.verifySegment(2, 2,3, Vector3D(1,1,0), Vector3D(0,1,0)));
+ QVERIFY(visitor.verifySegment(3, 0,1, Vector3D(0,0,0), Vector3D(1,0,0)));
}
void testVisitLineLoop()
@@ -588,12 +594,16 @@ private Q_SLOTS:
simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
- indexData.resize(sizeof(uint) * 2 * 4);
+ indexData.resize(sizeof(uint) * 8);
uint *iDataPtr = reinterpret_cast<uint *>(indexData.data());
iDataPtr[0] = 0;
iDataPtr[1] = 1;
iDataPtr[2] = 2;
iDataPtr[3] = 3;
+ iDataPtr[4] = static_cast<uint>(-1);
+ iDataPtr[5] = 0;
+ iDataPtr[6] = 1;
+ iDataPtr[7] = 2;
indexDataBuffer->setData(indexData);
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
@@ -612,7 +622,7 @@ private Q_SLOTS:
indexAttribute->setBuffer(indexDataBuffer.data());
indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt);
- indexAttribute->setCount(4);
+ indexAttribute->setCount(8);
indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
geometry->addAttribute(positionAttribute.data());
@@ -620,6 +630,8 @@ private Q_SLOTS:
geometryRenderer->setGeometry(geometry);
geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineLoop);
+ geometryRenderer->setPrimitiveRestartEnabled(true);
+ geometryRenderer->setRestartIndexValue(-1);
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
@@ -642,11 +654,14 @@ private Q_SLOTS:
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
// THEN
- QCOMPARE(visitor.segmentCount(), uint(4));
+ QCOMPARE(visitor.segmentCount(), uint(7));
QVERIFY(visitor.verifySegment(0, 0,1, Vector3D(0,0,0), Vector3D(1,0,0)));
QVERIFY(visitor.verifySegment(1, 1,2, Vector3D(1,0,0), Vector3D(1,1,0)));
QVERIFY(visitor.verifySegment(2, 2,3, Vector3D(1,1,0), Vector3D(0,1,0)));
QVERIFY(visitor.verifySegment(3, 3,0, Vector3D(0,1,0), Vector3D(0,0,0)));
+ QVERIFY(visitor.verifySegment(4, 0,1, Vector3D(0,0,0), Vector3D(1,0,0)));
+ QVERIFY(visitor.verifySegment(5, 1,2, Vector3D(1,0,0), Vector3D(1,1,0)));
+ QVERIFY(visitor.verifySegment(6, 2,0, Vector3D(1,1,0), Vector3D(0,0,0)));
}
void testVisitLineAdjacency()
diff --git a/tests/auto/render/sendrendercapturejob/sendrendercapturejob.pro b/tests/auto/render/sendrendercapturejob/sendrendercapturejob.pro
deleted file mode 100644
index 6aff0bebd..000000000
--- a/tests/auto/render/sendrendercapturejob/sendrendercapturejob.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-TEMPLATE = app
-
-TARGET = tst_sendrendercapturejob
-
-QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib
-
-CONFIG += testcase
-
-SOURCES += tst_sendrendercapturejob.cpp
-
-include(../commons/commons.pri)
-include(../../core/common/common.pri)
diff --git a/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp b/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp
deleted file mode 100644
index 53a646ccd..000000000
--- a/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QTest>
-#include "Qt3DRender/QRenderAspect"
-#include "Qt3DRender/private/renderer_p.h"
-#include "Qt3DRender/private/nodemanagers_p.h"
-#include "Qt3DRender/private/rendercapture_p.h"
-#include <Qt3DRender/private/sendrendercapturejob_p.h>
-#include "testpostmanarbiter.h"
-
-class tst_SendRenderCaptureJob : public QObject
-{
- Q_OBJECT
-private Q_SLOTS:
- void testSendRenderCaptureRequest()
- {
- // GIVEN
- TestArbiter arbiter;
- Qt3DRender::Render::RenderCapture *renderCapture = new Qt3DRender::Render::RenderCapture;
- Qt3DCore::QBackendNodePrivate::get(renderCapture)->setArbiter(&arbiter);
-
- QImage image(10, 10, QImage::Format_ARGB32);
-
- Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
- Qt3DRender::Render::SendRenderCaptureJob job;
-
- Qt3DRender::Render::NodeManagers nodeManagers;
- nodeManagers.frameGraphManager()->appendNode(renderCapture->peerId(), renderCapture);
- renderer.setNodeManagers(&nodeManagers);
- job.setManagers(&nodeManagers);
-
- renderCapture->requestCapture({ 42, QRect() });
- auto request = renderCapture->takeCaptureRequest();
- renderCapture->addRenderCapture(request.captureId, image);
- renderer.addRenderCaptureSendRequest(renderCapture->peerId());
- job.setPendingCaptureRequests(renderer.takePendingRenderCaptureSendRequests());
-
- //WHEN
- job.run();
-
- //THEN
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), renderCapture->peerId());
- QCOMPARE(change->propertyName(), "renderCaptureData");
- auto data = change->value().value<Qt3DRender::RenderCaptureDataPtr>();
- QCOMPARE(data.data()->captureId, 42);
- QCOMPARE(data.data()->image.width(), 10);
- QCOMPARE(data.data()->image.height(), 10);
- QCOMPARE(data.data()->image.format(), QImage::Format_ARGB32);
-
- // renderCapture will be deallocated by the nodeManagers destructor
- renderer.shutdown();
- }
-};
-
-QTEST_APPLESS_MAIN(tst_SendRenderCaptureJob)
-
-#include "tst_sendrendercapturejob.moc"
diff --git a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
index 7a08fe018..24dbe514a 100644
--- a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
+++ b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
@@ -560,6 +560,7 @@ private slots:
QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty());
QFETCH(Qt3DRender::QShaderProgram::ShaderType, type);
QFETCH(Qt3DRender::QShaderProgram::ShaderType, notificationType);
+ Q_UNUSED(notificationType)
const auto gl3Api = []{
auto api = Qt3DRender::GraphicsApiFilterData();
diff --git a/tests/auto/render/skeleton/tst_skeleton.cpp b/tests/auto/render/skeleton/tst_skeleton.cpp
index 6af055fb0..63ed51058 100644
--- a/tests/auto/render/skeleton/tst_skeleton.cpp
+++ b/tests/auto/render/skeleton/tst_skeleton.cpp
@@ -34,9 +34,7 @@
#include <Qt3DCore/qskeletonloader.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
#include <testrenderer.h>
@@ -49,24 +47,6 @@ Q_DECLARE_METATYPE(Qt3DRender::Render::JointInfo)
Q_DECLARE_METATYPE(Qt3DRender::Render::SkeletonData)
Q_DECLARE_METATYPE(Qt3DCore::Sqt)
-namespace {
-
-void linearizeTreeHelper(QJoint *joint, QVector<QJoint *> &joints)
-{
- joints.push_back(joint);
- for (const auto child : joint->childJoints())
- linearizeTreeHelper(child, joints);
-}
-
-QVector<QJoint *> linearizeTree(QJoint *rootJoint)
-{
- QVector<QJoint *> joints;
- linearizeTreeHelper(rootJoint, joints);
- return joints;
-}
-
-}
-
class tst_Skeleton : public Qt3DCore::QBackendNodeTester
{
Q_OBJECT
@@ -155,7 +135,6 @@ private Q_SLOTS:
backendSkeleton.setRenderer(&renderer);
backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager());
backendSkeleton.setDataType(Skeleton::File);
- Qt3DCore::QPropertyUpdatedChangePtr updateChange;
// Initialize to ensure skeleton manager is set
QSkeletonLoader skeleton;
@@ -219,70 +198,6 @@ private Q_SLOTS:
joint->setName(name);
QTest::newRow("inverseBind") << m << localPose << name << joint;
}
-
- void checkCreateFrontendJoints_data()
- {
- QTest::addColumn<SkeletonData>("skeletonData");
- QTest::addColumn<QJoint *>("expectedRootJoint");
-
- QTest::newRow("empty") << SkeletonData() << (QJoint*)nullptr;
-
- SkeletonData skeletonData;
- JointInfo rootJointInfo;
- skeletonData.joints.push_back(rootJointInfo);
- skeletonData.jointNames.push_back(QLatin1String("rootJoint"));
- skeletonData.localPoses.push_back(Qt3DCore::Sqt());
- const int childCount = 10;
- for (int i = 0; i < childCount; ++i) {
- JointInfo childJointInfo;
- childJointInfo.parentIndex = 0;
- skeletonData.joints.push_back(childJointInfo);
-
- const float x = static_cast<float>(i);
- Qt3DCore::Sqt localPose;
- localPose.translation = QVector3D(x, x, x);
- skeletonData.localPoses.push_back(localPose);
-
- skeletonData.jointNames.push_back(QString("Child-%1").arg(i));
- }
-
- QJoint *rootJoint = new QJoint();
- for (int i = 0; i < childCount; ++i) {
- QJoint *childJoint = new QJoint();
- const float x = static_cast<float>(i);
- childJoint->setTranslation(QVector3D(x, x, x));
- rootJoint->addChildJoint(childJoint);
- }
-
- QTest::newRow("wide") << skeletonData << rootJoint;
-
- skeletonData.joints.clear();
- skeletonData.joints.push_back(rootJointInfo);
- for (int i = 0; i < childCount; ++i) {
- JointInfo childJointInfo;
- childJointInfo.parentIndex = i;
- skeletonData.joints.push_back(childJointInfo);
-
- const float x = static_cast<float>(i);
- Qt3DCore::Sqt localPose;
- localPose.translation = QVector3D(x, x, x);
- skeletonData.localPoses.push_back(localPose);
-
- skeletonData.jointNames.push_back(QString("Child-%1").arg(i));
- }
-
- rootJoint = new QJoint();
- QJoint *previousJoint = rootJoint;
- for (int i = 0; i < childCount; ++i) {
- QJoint *childJoint = new QJoint();
- const float x = static_cast<float>(i);
- childJoint->setTranslation(QVector3D(x, x, x));
- previousJoint->addChildJoint(childJoint);
- previousJoint = childJoint;
- }
-
- QTest::newRow("deep") << skeletonData << rootJoint;
- }
};
QTEST_APPLESS_MAIN(tst_Skeleton)
diff --git a/tests/auto/render/transform/tst_transform.cpp b/tests/auto/render/transform/tst_transform.cpp
index 476c47393..a3fcdb9c8 100644
--- a/tests/auto/render/transform/tst_transform.cpp
+++ b/tests/auto/render/transform/tst_transform.cpp
@@ -32,7 +32,6 @@
#include <Qt3DCore/private/qtransform_p.h>
#include <Qt3DRender/private/transform_p.h>
#include <Qt3DRender/private/updateworldtransformjob_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <private/qbackendnode_p.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
diff --git a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp
index 8dfda0eea..66f67e08a 100644
--- a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp
+++ b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp
@@ -454,7 +454,7 @@ private Q_SLOTS:
simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
- indexData.resize(sizeof(uint) * 3 * 4);
+ indexData.resize(sizeof(uint) * 4 * 4);
uint *iDataPtr = reinterpret_cast<uint *>(indexData.data());
iDataPtr[0] = 0;
iDataPtr[1] = 1;
@@ -468,6 +468,10 @@ private Q_SLOTS:
iDataPtr[9] = 4;
iDataPtr[10] = 3;
iDataPtr[11] = 2;
+ iDataPtr[12] = static_cast<uint>(-1);
+ iDataPtr[13] = 0;
+ iDataPtr[14] = 1;
+ iDataPtr[15] = 2;
indexDataBuffer->setData(indexData);
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
@@ -486,7 +490,7 @@ private Q_SLOTS:
indexAttribute->setBuffer(indexDataBuffer.data());
indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt);
- indexAttribute->setCount(3*4);
+ indexAttribute->setCount(4*4);
indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
geometry->addAttribute(positionAttribute.data());
@@ -494,6 +498,8 @@ private Q_SLOTS:
geometryRenderer->setGeometry(geometry);
geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::TriangleStrip);
+ geometryRenderer->setPrimitiveRestartEnabled(true);
+ geometryRenderer->setRestartIndexValue(-1);
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
@@ -516,7 +522,7 @@ private Q_SLOTS:
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
// THEN
- QVERIFY(visitor.triangleCount() == 8);
+ QCOMPARE(visitor.triangleCount(), 9U);
QVERIFY(visitor.verifyTriangle(0, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1)));
QVERIFY(visitor.verifyTriangle(1, 3,2,1, Vector3D(0,0,1), Vector3D(0,1,0), Vector3D(1,0,0)));
QVERIFY(visitor.verifyTriangle(2, 4,3,2, Vector3D(1,0,0), Vector3D(0,0,1), Vector3D(0,1,0)));
@@ -525,6 +531,7 @@ private Q_SLOTS:
QVERIFY(visitor.verifyTriangle(5, 4,0,1, Vector3D(1,0,0), Vector3D(0,0,1), Vector3D(1,0,0)));
QVERIFY(visitor.verifyTriangle(6, 3,4,0, Vector3D(0,0,1), Vector3D(1,0,0), Vector3D(0,0,1)));
QVERIFY(visitor.verifyTriangle(7, 2,3,4, Vector3D(0,1,0), Vector3D(0,0,1), Vector3D(1,0,0)));
+ QVERIFY(visitor.verifyTriangle(8, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1)));
}
void testVisitTriangleFan()
@@ -643,7 +650,7 @@ private Q_SLOTS:
simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
- indexData.resize(sizeof(uint) * 3 * 2);
+ indexData.resize(sizeof(uint) * 10);
uint *iDataPtr = reinterpret_cast<uint *>(indexData.data());
iDataPtr[0] = 0;
iDataPtr[1] = 1;
@@ -651,6 +658,10 @@ private Q_SLOTS:
iDataPtr[3] = 3;
iDataPtr[4] = 4;
iDataPtr[5] = 5;
+ iDataPtr[6] = static_cast<uint>(-1);
+ iDataPtr[7] = 0;
+ iDataPtr[8] = 1;
+ iDataPtr[9] = 2;
indexDataBuffer->setData(indexData);
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
@@ -669,7 +680,7 @@ private Q_SLOTS:
indexAttribute->setBuffer(indexDataBuffer.data());
indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt);
- indexAttribute->setCount(3*2);
+ indexAttribute->setCount(10);
indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
geometry->addAttribute(positionAttribute.data());
@@ -677,6 +688,8 @@ private Q_SLOTS:
geometryRenderer->setGeometry(geometry);
geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::TriangleFan);
+ geometryRenderer->setPrimitiveRestartEnabled(true);
+ geometryRenderer->setRestartIndexValue(-1);
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
@@ -699,11 +712,12 @@ private Q_SLOTS:
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
// THEN
- QVERIFY(visitor.triangleCount() == 4);
+ QCOMPARE(visitor.triangleCount(), 5U);
QVERIFY(visitor.verifyTriangle(0, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1)));
QVERIFY(visitor.verifyTriangle(1, 3,2,0, Vector3D(0,0,1), Vector3D(0,1,0), Vector3D(0,0,1)));
QVERIFY(visitor.verifyTriangle(2, 4,3,0, Vector3D(1,0,0), Vector3D(0,0,1), Vector3D(0,0,1)));
QVERIFY(visitor.verifyTriangle(3, 5,4,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1)));
+ QVERIFY(visitor.verifyTriangle(4, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1)));
}
void testVisitTrianglesAdjacency()
diff --git a/tests/auto/render/uniform/tst_uniform.cpp b/tests/auto/render/uniform/tst_uniform.cpp
index 5f946afa3..d7775eb62 100644
--- a/tests/auto/render/uniform/tst_uniform.cpp
+++ b/tests/auto/render/uniform/tst_uniform.cpp
@@ -112,7 +112,7 @@ private Q_SLOTS:
QCOMPARE(v.constData<float>()[0], 572.0f);
QCOMPARE(v.constData<float>()[1], 355.0f);
QCOMPARE(v.constData<float>()[2], 383.0f);
- QCOMPARE(v.constData<float>()[4], 0.0f);
+ QCOMPARE(v.constData<float>()[3], 0.0f);
}
{
// GIVEN
diff --git a/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp b/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp
index 1238f1800..aafdb36f7 100644
--- a/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp
+++ b/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp
@@ -71,7 +71,7 @@ private:
bool isReadyToSubmit()
{
m_submitSemaphore.acquire(1);
- return m_running.load() == 1;
+ return m_running.loadRelaxed() == 1;
}
Qt3DRender::Render::VSyncFrameAdvanceService *m_tickService;
diff --git a/tests/manual/compute-manual/ComputeFrameGraph.qml b/tests/manual/compute-manual/ComputeFrameGraph.qml
new file mode 100644
index 000000000..47d57161c
--- /dev/null
+++ b/tests/manual/compute-manual/ComputeFrameGraph.qml
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+
+Viewport {
+ property alias camera: selector.camera
+
+ RenderSurfaceSelector {
+ id: surfaceSelector
+
+ // Clear Buffer
+ ClearBuffers {
+ buffers: ClearBuffers.ColorDepthBuffer
+ NoDraw {}
+ }
+
+ // Compute Pass
+ DispatchCompute {
+ // 1024 x 1024 particles
+ // We will launch 1024 local workgroup that will work
+ // on 1024 particles each
+ workGroupX: 1024; workGroupY: 1; workGroupZ: 1
+ TechniqueFilter {
+ matchAll: [
+ FilterKey { name: "type"; value: "compute"}
+ ]
+ }
+ }
+
+ // Draw particles from buffer computed in the Compute Pass
+ CameraSelector {
+ id: selector
+ TechniqueFilter {
+ MemoryBarrier { waitFor: MemoryBarrier.VertexAttributeArray }
+ matchAll: [
+ FilterKey { name: "type"; value: "draw"}
+ ]
+ }
+ }
+ }
+}
+
diff --git a/tests/manual/compute-manual/ComputeMaterial.qml b/tests/manual/compute-manual/ComputeMaterial.qml
new file mode 100644
index 000000000..9116a8b66
--- /dev/null
+++ b/tests/manual/compute-manual/ComputeMaterial.qml
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+
+Material {
+ property Buffer dataBuffer;
+ property real particleStep: 0.4
+ property real finalCollisionFactor: 0.2
+
+ parameters: [
+ Parameter { name: "particleStep"; value: particleStep },
+ Parameter { name: "finalCollisionFactor"; value: finalCollisionFactor }
+ ]
+
+ ShaderProgram {
+ id: computeShader
+ computeShaderCode: loadSource("qrc:/particles.comp")
+ }
+
+ ShaderProgram {
+ id: drawShader
+ vertexShaderCode: loadSource("qrc:/particles.vert")
+ fragmentShaderCode: loadSource("qrc:/particles.frag")
+ }
+
+ effect: Effect {
+ techniques: [
+ Technique {
+ renderPasses: [
+ RenderPass {
+ shaderProgram: computeShader
+ // We set the buffer as the parameter data
+ parameters: [
+ Parameter { name: "Particles"; value: dataBuffer }
+ ]
+ }
+ ]
+ filterKeys: [
+ FilterKey { name: "type"; value: "compute" }
+ ]
+ graphicsApiFilter {
+ api: GraphicsApiFilter.OpenGL
+ profile: GraphicsApiFilter.CoreProfile
+ majorVersion: 4
+ minorVersion: 3
+ }
+ },
+ Technique {
+ renderPasses: [
+ RenderPass {
+ shaderProgram: drawShader
+ // We assume the mesh to be drawn will also receive
+ // Vertex buffers attributes that will be used to position and color
+ }
+ ]
+ filterKeys: [
+ FilterKey { name: "type"; value: "draw" }
+ ]
+ graphicsApiFilter {
+ api: GraphicsApiFilter.OpenGL
+ profile: GraphicsApiFilter.CoreProfile
+ majorVersion: 4
+ minorVersion: 3
+ }
+ }
+ ] // techniques
+ }
+}
+
diff --git a/tests/manual/compute-manual/ParticlesScene.qml b/tests/manual/compute-manual/ParticlesScene.qml
new file mode 100644
index 000000000..68572f6b4
--- /dev/null
+++ b/tests/manual/compute-manual/ParticlesScene.qml
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Extras 2.14
+import Qt3D.Input 2.14
+
+Entity {
+
+ property alias computeMode: particlesComputeJob.runType
+
+ function triggerCompute(frames) {
+ particlesComputeJob.trigger(frames)
+ }
+
+ components: [
+ RenderSettings {
+ ComputeFrameGraph {
+ camera: sceneCamera
+ }
+ // explicitly set RenderingPolicy to AlwaysRender, as changes in the
+ // scene won't be reflected in actual Qt scene-graph changes (due to
+ // GPU compute calls)
+ renderPolicy: RenderSettings.Always
+ },
+ InputSettings {}
+ ]
+
+ FirstPersonCameraController { camera: sceneCamera }
+
+ Camera {
+ id: sceneCamera
+ projectionType: CameraLens.PerspectiveProjection
+ viewCenter: Qt.vector3d(0, 0, 0)
+ position: Qt.vector3d(0, 20, -800)
+ nearPlane: 0.1
+ farPlane: 1000
+ fieldOfView: 60
+ }
+
+ property int particlesCount: 1024 * 1024
+ readonly property int floatSize: 4
+
+ function buildParticlesBuffer() {
+ var byteSizeOfParticleData = 8;
+ var bufferData = new Float32Array(particlesCount * byteSizeOfParticleData);
+ for (var x = 0; x < 1024; ++x) {
+ for (var z = 0; z < 1024; ++z) {
+ var i = x * 1024 + z;
+ var positionIdx = i * byteSizeOfParticleData;
+ var colorIdx = i * byteSizeOfParticleData + 8;
+
+ bufferData[positionIdx] = -1024 + x * 2;
+ bufferData[positionIdx + 1] = 0;
+ bufferData[positionIdx + 2] = -1024 + z * 2;
+ bufferData[positionIdx + 3] = 1.0;
+
+ bufferData[colorIdx] = 0.25 + Math.sin(x / 1024) * 0.75;
+ bufferData[colorIdx + 1] = 0.25 + Math.sin(z / 1024) * 0.75;
+ bufferData[colorIdx + 2] = 0.25 + Math.sin(x / 1024) * 0.75;
+ bufferData[colorIdx + 3] = 1.0;
+ }
+ }
+ return bufferData
+ }
+
+ Buffer {
+ id: particleBuffer
+ type: Buffer.VertexBuffer
+ // struct ParticleData
+ // {
+ // vec3 position; // Aligned to 4 floats
+ // vec3 color; // Aligned to 4 floats
+ // };
+ data: buildParticlesBuffer()
+ }
+
+ Attribute {
+ id: particlePositionDataAttribute
+ name: "particlePosition"
+ attributeType: Attribute.VertexAttribute
+ vertexBaseType: Attribute.Float
+ vertexSize: 3
+ divisor: 1
+ byteStride: 8 * floatSize
+ buffer: particleBuffer
+ }
+
+ Attribute {
+ id: particleColorDataAttribute
+ name: "particleColor"
+ attributeType: Attribute.VertexAttribute
+ vertexBaseType: Attribute.Float
+ vertexSize: 3
+ divisor: 1
+ byteOffset: 4 * floatSize
+ byteStride: 8 * floatSize
+ buffer: particleBuffer
+ }
+
+ ComputeMaterial {
+ id: computeMaterial
+ dataBuffer: particleBuffer
+ }
+
+ ComputeCommand {
+ id: particlesComputeJob
+ onRunTypeChanged: {
+ // Don't forget to re-enable the command
+ // when switching back to continuous
+ if (runType === ComputeCommand.Continuous)
+ enabled = true
+ }
+ }
+
+ Entity {
+ id: particleComputeEntity
+ components: [
+ particlesComputeJob,
+ computeMaterial
+ ]
+ }
+
+ SphereGeometry {
+ id: sphereGeometry
+ rings: 10
+ slices: 10
+ radius: 1
+ // Additional Attributes
+ attributes: [
+ particlePositionDataAttribute,
+ particleColorDataAttribute
+ ]
+ }
+
+ Entity {
+ id: particleRenderEntity
+ readonly property GeometryRenderer particlesRenderer: GeometryRenderer {
+ instanceCount: particlesCount
+ indexOffset: 0
+ firstInstance: 0
+ primitiveType: GeometryRenderer.Triangles
+ geometry: sphereGeometry
+ }
+
+ components: [
+ particlesRenderer,
+ computeMaterial
+ ]
+ }
+}
+
diff --git a/tests/manual/compute-manual/compute-manual.pro b/tests/manual/compute-manual/compute-manual.pro
new file mode 100644
index 000000000..e2a9116db
--- /dev/null
+++ b/tests/manual/compute-manual/compute-manual.pro
@@ -0,0 +1,14 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3dquick 3dinput quick qml
+
+HEADERS += \
+
+
+RESOURCES += \
+ compute-manual.qrc
+
+SOURCES += \
+ main.cpp
diff --git a/tests/manual/compute-manual/compute-manual.qrc b/tests/manual/compute-manual/compute-manual.qrc
new file mode 100644
index 000000000..0f94fddd5
--- /dev/null
+++ b/tests/manual/compute-manual/compute-manual.qrc
@@ -0,0 +1,11 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>ComputeFrameGraph.qml</file>
+ <file>ComputeMaterial.qml</file>
+ <file>particles.frag</file>
+ <file>particles.vert</file>
+ <file>ParticlesScene.qml</file>
+ <file>particles.comp</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/compute-manual/main.cpp b/tests/manual/compute-manual/main.cpp
new file mode 100644
index 000000000..afc9df36a
--- /dev/null
+++ b/tests/manual/compute-manual/main.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQuickView>
+
+int main(int argc, char* argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QQuickView view;
+
+ view.resize(1024, 1024);
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/compute-manual/main.qml b/tests/manual/compute-manual/main.qml
new file mode 100644
index 000000000..a76c8ae0c
--- /dev/null
+++ b/tests/manual/compute-manual/main.qml
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import QtQuick.Scene3D 2.14
+import QtQuick.Controls 2.14
+import QtQuick.Layouts 1.1
+import Qt3D.Render 2.14
+
+Item {
+
+ Scene3D {
+ anchors.fill: parent
+ aspects: ["input", "logic"]
+ focus: true
+ ParticlesScene {
+ id: scene
+ computeMode: runModeCombo.currentIndex === 0 ? ComputeCommand.Continuous : ComputeCommand.Manual
+ }
+ }
+
+ RowLayout {
+ id: colorLayout
+ anchors.left: parent.left
+ anchors.leftMargin: 35
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 35
+ spacing: 15
+
+ RowLayout {
+ Text {
+ text: "Run Mode:"
+ color: "white"
+ }
+ ComboBox {
+ id: runModeCombo
+ model: ["Continuous", "Manual"]
+ }
+ }
+ RowLayout {
+ visible: runModeCombo.currentIndex === 1
+ Text {
+ color: "white"
+ text: "Frames"
+ }
+ SpinBox {
+ id: frameCountSpinBox
+ value: 5
+ from: 1
+ to: 10
+ stepSize: 1
+ }
+ Button {
+ text: "Trigger"
+ onClicked: {
+ // Trigger Compute Manual
+ scene.triggerCompute(frameCountSpinBox.value)
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/compute-manual/particles.comp b/tests/manual/compute-manual/particles.comp
new file mode 100644
index 000000000..b05e49c1d
--- /dev/null
+++ b/tests/manual/compute-manual/particles.comp
@@ -0,0 +1,31 @@
+#version 430 core
+
+uniform float time;
+
+layout (local_size_x = 1024) in;
+
+struct ParticleData
+{
+ vec4 position;
+ vec4 color;
+};
+
+// Particles from previouse frame
+layout (std430, binding = 0) coherent buffer Particles
+{
+ ParticleData particles[];
+} data;
+
+void main(void)
+{
+ uint globalId = gl_GlobalInvocationID.x;
+
+ // Retrieve current particle from previous frame
+ ParticleData currentParticle = data.particles[globalId];
+
+ // New position = old position + sin(time)
+ currentParticle.position = currentParticle.position + vec4(0.0, 1.0, 0.0, 0.0) * sin(time * globalId);
+
+ // Save updated particle
+ data.particles[globalId] = currentParticle;
+}
diff --git a/tests/manual/compute-manual/particles.frag b/tests/manual/compute-manual/particles.frag
new file mode 100644
index 000000000..3f11b9868
--- /dev/null
+++ b/tests/manual/compute-manual/particles.frag
@@ -0,0 +1,33 @@
+#version 430 core
+
+out vec4 color;
+
+in VertexBlock
+{
+ flat vec3 color;
+ vec3 pos;
+ vec3 normal;
+} frag_in;
+
+const vec4 lightPosition = vec4(0.0, 0.0, 0.0, 0.0);
+const vec3 lightIntensity = vec3(1.0, 1.0, 1.0);
+const vec3 ka = vec3(0.1, 0.1, 0.1);
+const vec3 ks = vec3(0.8, 0.8, 0.8);
+const float shininess = 50.0;
+
+vec3 ads()
+{
+ vec3 n = normalize( frag_in.normal);
+ vec3 s = normalize( vec3(lightPosition) - frag_in.pos );
+ vec3 v = normalize( -frag_in.pos );
+ vec3 h = normalize( v + s );
+ return lightIntensity * (ka +
+ frag_in.color * max( dot(s, frag_in.normal ), 0.0 ) +
+ ks * pow( max( dot( h, n ), 0.0 ), shininess ) );
+}
+
+
+void main(void)
+{
+ color = vec4(ads(), 1.0);
+}
diff --git a/tests/manual/compute-manual/particles.vert b/tests/manual/compute-manual/particles.vert
new file mode 100644
index 000000000..5f2da2a00
--- /dev/null
+++ b/tests/manual/compute-manual/particles.vert
@@ -0,0 +1,27 @@
+#version 430 core
+
+in vec3 vertexPosition;
+in vec3 vertexNormal;
+
+in vec3 particlePosition;
+in vec3 particleColor;
+
+out VertexBlock
+{
+ flat vec3 color;
+ vec3 pos;
+ vec3 normal;
+} v_out;
+
+uniform mat4 mvp;
+uniform mat3 modelViewNormal;
+uniform mat4 modelView;
+
+void main(void)
+{
+ vec4 pos = vec4(vertexPosition.xyz, 1.0) + vec4(particlePosition, 0.0);
+ gl_Position = mvp * pos;
+ v_out.pos = vec4(modelView * pos).xyz;
+ v_out.normal = normalize(modelViewNormal * vertexNormal);
+ v_out.color = mix(particleColor * 0.2, particleColor, smoothstep(0.5, 0.8, abs(v_out.normal).z));
+}
diff --git a/tests/manual/manual-renderloop/main.cpp b/tests/manual/manual-renderloop/main.cpp
new file mode 100644
index 000000000..f2a49cb86
--- /dev/null
+++ b/tests/manual/manual-renderloop/main.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QTimer>
+#include <QOpenGLContext>
+#include <QWindow>
+#include <qmath.h>
+
+#include <Qt3DCore/QNode>
+#include <Qt3DCore/QEntity>
+#include <Qt3DCore/QTransform>
+#include <Qt3DCore/QAspectEngine>
+
+#include <Qt3DExtras/QTorusMesh>
+#include <Qt3DExtras/QForwardRenderer>
+#include <Qt3DExtras/QPhongMaterial>
+
+#include <Qt3DRender/QCamera>
+#include <Qt3DRender/QCameraLens>
+#include <Qt3DRender/QCameraSelector>
+#include <Qt3DRender/QMesh>
+#include <Qt3DRender/QPointLight>
+#include <Qt3DRender/QRenderAspect>
+#include <Qt3DRender/QRenderSettings>
+#include <Qt3DRender/QRenderSurfaceSelector>
+#include <Qt3DRender/private/qrenderaspect_p.h>
+
+
+class ManualRenderer
+{
+public:
+ ManualRenderer()
+ : m_aspectEngine(new Qt3DCore::QAspectEngine())
+ , m_renderAspect(new Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous))
+ {
+ }
+
+ ~ManualRenderer() {
+ m_aspectEngine->setRootEntity(Qt3DCore::QEntityPtr());
+ m_aspectEngine->unregisterAspect(m_renderAspect);
+ delete m_renderAspect;
+ delete m_aspectEngine;
+ }
+
+ void initialize(QWindow *window, QOpenGLContext *glCtx)
+ {
+ m_aspectEngine->registerAspect(m_renderAspect);
+ m_aspectEngine->setRunMode(Qt3DCore::QAspectEngine::Manual);
+
+ Qt3DRender::QRenderAspectPrivate *dRenderAspect = static_cast<decltype(dRenderAspect)>
+ (Qt3DRender::QRenderAspectPrivate::get(m_renderAspect));
+ dRenderAspect->renderInitialize(glCtx);
+
+ m_rootEntity.reset(createSceneTree(window));
+ m_aspectEngine->setRootEntity(m_rootEntity);
+ }
+
+ void render() {
+ qDebug() << Q_FUNC_INFO << "Updating Scene";
+ updateScene();
+ qDebug() << Q_FUNC_INFO << "Processing Frame";
+ // Launch jobs to process the frame
+ m_aspectEngine->processFrame();
+ qDebug() << Q_FUNC_INFO << "Rendering Frame";
+ // Submit Render Queues
+ Qt3DRender::QRenderAspectPrivate *dRenderAspect = static_cast<decltype(dRenderAspect)>
+ (Qt3DRender::QRenderAspectPrivate::get(m_renderAspect));
+ dRenderAspect->renderSynchronous(true);
+ }
+
+private:
+ Qt3DCore::QEntity *createSceneTree(QWindow *surface) {
+ // Root entity in the 3D scene.
+ Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
+ auto camera = new Qt3DRender::QCamera(rootEntity);
+ camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
+ camera->setPosition(QVector3D(0, 0, 40.0f));
+ camera->setViewCenter(QVector3D(0, 0, 0));
+
+ // Torus
+ Qt3DCore::QEntity *torusEntity = new Qt3DCore::QEntity(rootEntity);
+ auto material = new Qt3DExtras::QPhongMaterial(rootEntity);
+ auto torusTransform = new Qt3DCore::QTransform;
+ auto torusMesh = new Qt3DExtras::QTorusMesh;
+
+ torusMesh->setRadius(5);
+ torusMesh->setMinorRadius(1);
+ torusMesh->setRings(100);
+ torusMesh->setSlices(20);
+
+ torusTransform->setScale3D(QVector3D(1.5, 1, 0.5));
+ torusTransform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 45.0f));
+
+ torusEntity->addComponent(torusMesh);
+ torusEntity->addComponent(material);
+ torusEntity->addComponent(torusTransform);
+
+ // FrameGraph
+ auto forwardRenderer = new Qt3DExtras::QForwardRenderer();
+ forwardRenderer->setSurface(surface);
+ forwardRenderer->setCamera(camera);
+ forwardRenderer->setClearColor(QColor(Qt::black));
+
+ auto renderSettings = new Qt3DRender::QRenderSettings();
+ renderSettings->setActiveFrameGraph(forwardRenderer);
+ rootEntity->addComponent(renderSettings);
+
+ return rootEntity;
+ }
+
+ void updateScene()
+ {
+ static int angle = 0;
+ // Update camera position
+ auto camera = m_rootEntity->findChild<Qt3DRender::QCamera *>();
+ Q_ASSERT(camera);
+
+ const double angleRad = qDegreesToRadians(double(angle));
+ const QVector3D newPos(qSin(angleRad), 0.0, qCos(angleRad));
+ camera->setPosition(newPos * 40.0f);
+
+ qDebug() << Q_FUNC_INFO << "Camera Transform Matrix" << camera->transform()->matrix();
+ qDebug() << Q_FUNC_INFO << "Camera ViewMatrix" << camera->viewMatrix();
+
+ angle = (angle + 1) % 360;
+ }
+
+ Qt3DCore::QEntityPtr m_rootEntity;
+ Qt3DCore::QAspectEngine *m_aspectEngine;
+ Qt3DRender::QRenderAspect *m_renderAspect;
+};
+
+int main(int ac, char **av)
+{
+ QSurfaceFormat format = QSurfaceFormat::defaultFormat();
+#ifdef QT_OPENGL_ES_2
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+#else
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
+ format.setVersion(4, 3);
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ }
+#endif
+ format.setDepthBufferSize(24);
+ format.setSamples(4);
+ format.setStencilBufferSize(8);
+ QSurfaceFormat::setDefaultFormat(format);
+
+ QGuiApplication app(ac, av);
+
+ QWindow win;
+ win.setSurfaceType(QSurface::OpenGLSurface);
+ win.resize(1024, 768);
+ win.setFormat(format);
+ win.show();
+
+ QOpenGLContext ctx;
+ ctx.setFormat(format);
+ const bool ctxCreated = ctx.create();
+
+ if (!ctxCreated) {
+ qWarning() << "Failed to create GL context";
+ return -1;
+ }
+
+ ManualRenderer renderer;
+ renderer.initialize(&win, &ctx);
+
+ QTimer t;
+ QObject::connect(&t, &QTimer::timeout, [&] { renderer.render(); });
+ t.start(16);
+
+ return app.exec();
+}
diff --git a/tests/manual/manual-renderloop/manual-renderloop.pro b/tests/manual/manual-renderloop/manual-renderloop.pro
new file mode 100644
index 000000000..d126a48c5
--- /dev/null
+++ b/tests/manual/manual-renderloop/manual-renderloop.pro
@@ -0,0 +1,8 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3drender-private 3dinput 3dextras
+
+SOURCES += \
+ main.cpp
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index 1182886d3..2f630e0d9 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -67,7 +67,13 @@ SUBDIRS += \
qtbug-76766 \
shader-image-qml \
scene3d-in-sync \
- compressed_textures
+ compressed_textures \
+ subtree-enabler-qml \
+ scene3d-visibility \
+ manual-renderloop
+
+!macos:!uikit: SUBDIRS += compute-manual
+
qtHaveModule(multimedia): {
SUBDIRS += \
diff --git a/tests/manual/rendercapture-qml/main.qml b/tests/manual/rendercapture-qml/main.qml
index 9aff1fefe..98b24e251 100644
--- a/tests/manual/rendercapture-qml/main.qml
+++ b/tests/manual/rendercapture-qml/main.qml
@@ -50,7 +50,7 @@
import QtQuick 2.2
import QtQuick.Layouts 1.3
-import QtQuick.Controls 1.4
+import QtQuick.Controls 2.12
import Qt3D.Render 2.9
import QtQuick.Scene3D 2.0
diff --git a/tests/manual/scene3d-visibility/main.cpp b/tests/manual/scene3d-visibility/main.cpp
new file mode 100644
index 000000000..8886263f4
--- /dev/null
+++ b/tests/manual/scene3d-visibility/main.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQuickView>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ QQuickView view;
+
+ view.resize(500, 500);
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/scene3d-visibility/main.qml b/tests/manual/scene3d-visibility/main.qml
new file mode 100644
index 000000000..ccfa3227f
--- /dev/null
+++ b/tests/manual/scene3d-visibility/main.qml
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Input 2.14
+import Qt3D.Extras 2.14
+import QtQuick.Scene3D 2.14
+
+Item {
+ id: root
+
+ Timer {
+ running: true
+ repeat: true
+ interval: 2000
+ onTriggered: scene3d.visible = !scene3d.visible
+ }
+
+ // Scene3D
+ Scene3D {
+ id: scene3d
+ visible: false
+ readonly property double halfWidth: width * 0.5
+
+ focus: true
+ anchors.fill: parent
+ // Make sure to define the input aspect if we want to handle inputs
+ aspects: ["render", "input"]
+ multisample: false
+
+ Entity { // Root
+ id: sceneRoot
+ components: [
+ RenderSettings {
+ activeFrameGraph: ForwardRenderer {
+ id: forwardRenderer
+ camera: mainCamera
+ clearColor: "yellow"
+ }
+ },
+ // Event Source is the Scene3D in that case
+ InputSettings { }
+ ]
+
+ Camera {
+ id: mainCamera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d( 0.0, 0.0, -40.0 )
+ upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
+ viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
+ }
+
+ PhongMaterial {
+ id: material
+ }
+
+ TorusMesh {
+ id: torusMesh
+ radius: 5
+ minorRadius: 1
+ rings: 100
+ slices: 20
+ }
+
+ SphereMesh {
+ id: sphereMesh
+ radius: 3
+ }
+
+ Transform {
+ id: torusTransform
+ scale3D: Qt.vector3d(1.5, 1, 0.5)
+ rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45)
+ }
+
+ Transform {
+ id: sphereTransform
+ property real userAngle: 0.0
+ matrix: {
+ var m = Qt.matrix4x4();
+ m.rotate(userAngle, Qt.vector3d(0, 1, 0));
+ m.translate(Qt.vector3d(20, 0, 0));
+ return m;
+ }
+
+ onWorldMatrixChanged: console.log("Sphere WorldMatrix " + worldMatrix)
+ }
+
+ NumberAnimation {
+ target: sphereTransform
+ property: "userAngle"
+ duration: 1000
+ from: 0
+ to: 360
+ loops: Animation.Infinite
+ running: true
+ }
+
+ Entity {
+ id: torusEntity
+ components: [ torusMesh, material, torusTransform ]
+ }
+ Entity {
+ id: sphereEntity
+ components: [ sphereMesh, material, sphereTransform ]
+ }
+ }
+ }
+}
diff --git a/tests/manual/scene3d-visibility/scene3d-visibility.pro b/tests/manual/scene3d-visibility/scene3d-visibility.pro
new file mode 100644
index 000000000..a1c20a502
--- /dev/null
+++ b/tests/manual/scene3d-visibility/scene3d-visibility.pro
@@ -0,0 +1,10 @@
+QT += qml quick 3dinput
+
+SOURCES += \
+ main.cpp
+
+OTHER_FILES += \
+ main.qml
+
+RESOURCES += \
+ scene3d-visibility.qrc
diff --git a/tests/manual/scene3d-visibility/scene3d-visibility.qrc b/tests/manual/scene3d-visibility/scene3d-visibility.qrc
new file mode 100644
index 000000000..5f6483ac3
--- /dev/null
+++ b/tests/manual/scene3d-visibility/scene3d-visibility.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/sharedtexture/main.cpp b/tests/manual/sharedtexture/main.cpp
index a85f90ee6..6f2ef42f2 100644
--- a/tests/manual/sharedtexture/main.cpp
+++ b/tests/manual/sharedtexture/main.cpp
@@ -137,8 +137,7 @@ int main(int argc, char* argv[])
// Multimedia player
TextureWidget textureWidget;
- VideoPlayerThread *videoPlayer = new VideoPlayerThread(&textureWidget);
- videoPlayer->start();
+ VideoPlayer *videoPlayer = new VideoPlayer(&textureWidget);
textureWidget.resize(800, 600);
textureWidget.show();
diff --git a/tests/manual/sharedtexture/videoplayer.cpp b/tests/manual/sharedtexture/videoplayer.cpp
index f970116b5..2e52b85e0 100644
--- a/tests/manual/sharedtexture/videoplayer.cpp
+++ b/tests/manual/sharedtexture/videoplayer.cpp
@@ -57,8 +57,6 @@ TextureWidget::TextureWidget(QWidget *parent)
: QOpenGLWidget(parent)
, m_texture(QOpenGLTexture::Target2D)
{
- // Lock mutex so that we never process a frame until we have been initialized
- m_mutex.lock();
}
// Main thread
@@ -104,14 +102,11 @@ void TextureWidget::initializeGL()
qDebug() << Q_FUNC_INFO << context()->shareContext();
m_vao.create();
- // Allow rendering/frame acquisition to go on
- m_mutex.unlock();
}
// Main thread
void TextureWidget::paintGL()
{
- QMutexLocker lock(&m_mutex);
glViewport(0, 0, width(), height());
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
@@ -131,12 +126,8 @@ void TextureWidget::paintGL()
m_shader.release();
}
-// Video Player thread
void TextureWidget::setVideoFrame(const QVideoFrame &frame)
{
- // Ensure we won't be rendering while we are processing the frame
- QMutexLocker lock(&m_mutex);
-
QVideoFrame f = frame;
// Map frame
@@ -194,16 +185,14 @@ bool GLVideoSurface::present(const QVideoFrame &frame)
return true;
}
-VideoPlayerThread::VideoPlayerThread(TextureWidget *textureWidget)
- : QThread(textureWidget)
+VideoPlayer::VideoPlayer(TextureWidget *textureWidget)
+ : QObject(textureWidget)
, m_player(new QMediaPlayer(nullptr, QMediaPlayer::VideoSurface))
, m_surface(new GLVideoSurface())
{
- m_player->moveToThread(this);
- m_player->setMedia(QUrl("https://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"));
+ m_player->setMedia(QUrl("https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4"));
// Tell player to render on GLVideoSurface
- m_surface->moveToThread(this);
m_player->setVideoOutput(m_surface.get());
// Display errors
@@ -218,16 +207,13 @@ VideoPlayerThread::VideoPlayerThread(TextureWidget *textureWidget)
m_player->play();
});
- // Start playing when thread starts
- QObject::connect(this, &QThread::started, this, [this] { m_player->play(); });
-
- // Direct connection between 2 objects living in different threads
QObject::connect(m_surface.get(), &GLVideoSurface::onNewFrame,
textureWidget, &TextureWidget::setVideoFrame, Qt::DirectConnection);
+
+ // Start playing
+ m_player->play();
}
-VideoPlayerThread::~VideoPlayerThread()
+VideoPlayer::~VideoPlayer()
{
- exit(0);
- wait();
}
diff --git a/tests/manual/sharedtexture/videoplayer.h b/tests/manual/sharedtexture/videoplayer.h
index 377ea57fe..a96cb16b1 100644
--- a/tests/manual/sharedtexture/videoplayer.h
+++ b/tests/manual/sharedtexture/videoplayer.h
@@ -48,9 +48,6 @@
**
****************************************************************************/
-#include <QThread>
-#include <QMutex>
-
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLVertexArrayObject>
@@ -90,7 +87,6 @@ private:
QOpenGLVertexArrayObject m_vao;
QOpenGLShaderProgram m_shader;
QOpenGLTexture m_texture;
- QMutex m_mutex;
};
@@ -108,12 +104,12 @@ Q_SIGNALS:
};
-class VideoPlayerThread : public QThread
+class VideoPlayer : public QObject
{
Q_OBJECT
public:
- VideoPlayerThread(TextureWidget *textureWidget);
- ~VideoPlayerThread();
+ VideoPlayer(TextureWidget *textureWidget);
+ ~VideoPlayer();
private:
TextureWidget *m_textureWidget;
diff --git a/tests/manual/sharedtextureqml/main.cpp b/tests/manual/sharedtextureqml/main.cpp
index 5c7ae9cff..c0a79e6f8 100644
--- a/tests/manual/sharedtextureqml/main.cpp
+++ b/tests/manual/sharedtextureqml/main.cpp
@@ -108,8 +108,7 @@ int main(int argc, char* argv[])
// Multimedia player
TextureWidget textureWidget;
- VideoPlayerThread *videoPlayer = new VideoPlayerThread(&textureWidget);
- videoPlayer->start();
+ VideoPlayer *videoPlayer = new VideoPlayer(&textureWidget);
textureWidget.resize(800, 600);
textureWidget.show();
diff --git a/tests/manual/subtree-enabler-qml/FrameGraph.qml b/tests/manual/subtree-enabler-qml/FrameGraph.qml
new file mode 100644
index 000000000..b9cdce9ea
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/FrameGraph.qml
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import QtQuick 2.14 as QQ2
+
+RenderSettings {
+ id: frameGraph
+
+ property alias leftCamera: cameraSelectorLeftViewport.camera;
+ property alias rightCamera: cameraSelectorRightViewport.camera;
+ property alias window: surfaceSelector.surface
+
+ activeFrameGraph: RenderSurfaceSelector {
+ id: surfaceSelector
+
+ Viewport {
+ id: mainViewport
+ normalizedRect: Qt.rect(0, 0, 1, 1)
+
+ ClearBuffers {
+ buffers: ClearBuffers.ColorDepthBuffer
+ clearColor: Qt.rgba(0.6, 0.6, 0.6, 1.0)
+ NoDraw {}
+ }
+
+ Viewport {
+ id: leftViewport
+ normalizedRect: Qt.rect(0, 0, 0.5, 0.5)
+ CameraSelector { id: cameraSelectorLeftViewport }
+ }
+
+ SubtreeEnabler {
+ id: enabler
+ enabled: true
+
+ QQ2.Timer {
+ running: true
+ repeat: true
+ interval: 1000
+ onTriggered: enabler.enabled = !enabler.enabled
+ }
+
+ Viewport {
+ id: rightViewport
+ normalizedRect: Qt.rect(0.5, 0.5, 0.5, 0.5)
+ CameraSelector { id: cameraSelectorRightViewport }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/subtree-enabler-qml/SimpleCamera.qml b/tests/manual/subtree-enabler-qml/SimpleCamera.qml
new file mode 100644
index 000000000..a1ef6d01c
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/SimpleCamera.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+
+Entity {
+ id: root
+
+ property vector3d position: Qt.vector3d(0.0, 0.0, 10.0)
+ property vector3d viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
+ property vector3d upVector: Qt.vector3d(0.0, 1.0, 0.0)
+ property CameraLens lens: null
+
+ components: [lens, transform]
+
+ Transform {
+ id: transform
+ matrix: {
+ var m = Qt.matrix4x4();
+ m.translate(root.position)
+ var zAxis = root.position.minus(root.viewCenter).normalized()
+ var xAxis = root.upVector.crossProduct(zAxis).normalized();
+ var yAxis = zAxis.crossProduct(xAxis);
+ var r = Qt.matrix4x4(xAxis.x, yAxis.x, zAxis.x, 0,
+ xAxis.y, yAxis.y, zAxis.y, 0,
+ xAxis.z, yAxis.z, zAxis.z, 0,
+ 0, 0, 0, 1)
+ return m.times(r);
+ }
+ }
+}
diff --git a/tests/manual/subtree-enabler-qml/main.cpp b/tests/manual/subtree-enabler-qml/main.cpp
new file mode 100644
index 000000000..ce5b883bd
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DQuickExtras/qt3dquickwindow.h>
+#include <QGuiApplication>
+
+int main(int ac, char **av)
+{
+ QGuiApplication app(ac, av);
+ Qt3DExtras::Quick::Qt3DQuickWindow view;
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
+
+
diff --git a/tests/manual/subtree-enabler-qml/main.qml b/tests/manual/subtree-enabler-qml/main.qml
new file mode 100644
index 000000000..c2e530893
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/main.qml
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Input 2.14
+import Qt3D.Extras 2.14
+
+Entity {
+ id: rootNode
+ components: [frameGraph]
+
+ FrameGraph {
+ id: frameGraph
+ leftCamera: camera1
+ rightCamera: camera2
+ }
+
+ CameraLens {
+ id: cameraLens
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ aspectRatio: 16/9
+ nearPlane: 0.01
+ farPlane: 1000.0
+ }
+
+ SimpleCamera {
+ id: camera1
+ lens: cameraLens
+ position: Qt.vector3d(10.0, 1.0, 10.0)
+ viewCenter: Qt.vector3d(0.0, 1.0, 0.0)
+ }
+
+ SimpleCamera {
+ id: camera2
+ lens: cameraLens
+ position: Qt.vector3d(0.0, 0.0, 5.0)
+ viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
+ }
+
+ Entity {
+ id: sceneRoot
+ property real rotationAngle: 0
+
+ SequentialAnimation {
+ running: true
+ loops: Animation.Infinite
+ NumberAnimation { target: sceneRoot; property: "rotationAngle"; to: 360; duration: 4000; }
+ }
+
+ Entity {
+ components: [
+ Transform {
+ rotation: fromAxisAndAngle(Qt.vector3d(0, 0, 1), -sceneRoot.rotationAngle)
+ },
+ CylinderMesh {},
+ MetalRoughMaterial {}
+ ]
+ }
+ } // sceneRoot
+} // rootNode
diff --git a/tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro
new file mode 100644
index 000000000..ddd0ae561
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro
@@ -0,0 +1,17 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras
+
+HEADERS += \
+
+SOURCES += \
+ main.cpp
+
+OTHER_FILES += \
+ main.qml
+
+RESOURCES += \
+ subtree-enabler-qml.qrc \
+
diff --git a/tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc
new file mode 100644
index 000000000..e565b719f
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>FrameGraph.qml</file>
+ <file>SimpleCamera.qml</file>
+ </qresource>
+</RCC>
diff --git a/tools/qgltf/qgltf.cpp b/tools/qgltf/qgltf.cpp
index 562e50911..91ecd5ba2 100644
--- a/tools/qgltf/qgltf.cpp
+++ b/tools/qgltf/qgltf.cpp
@@ -216,7 +216,9 @@ static inline QVector<float> ai2qt(const aiMatrix4x4 &matrix)
struct Options {
QString outDir;
+#ifndef QT_BOOTSTRAPPED
bool genBin;
+#endif
bool compact;
bool compress;
bool genTangents;
@@ -2450,23 +2452,31 @@ void GltfExporter::save(const QString &inputFilename)
QString gltfName = opts.outDir + basename + QStringLiteral(".qgltf");
f.setFileName(gltfName);
+
+#ifndef QT_BOOTSTRAPPED
if (opts.showLog)
qDebug().noquote() << (opts.genBin ? "Writing (binary JSON)" : "Writing") << gltfName;
- if (opts.genBin) {
- if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- m_files.insert(QFileInfo(f.fileName()).fileName());
- QByteArray json = m_doc.toBinaryData();
- f.write(json);
- f.close();
- }
- } else {
- if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
- m_files.insert(QFileInfo(f.fileName()).fileName());
- QByteArray json = m_doc.toJson(opts.compact ? QJsonDocument::Compact : QJsonDocument::Indented);
- f.write(json);
- f.close();
- }
+ const QIODevice::OpenMode openMode = opts.genBin
+ ? (QIODevice::WriteOnly | QIODevice::Truncate)
+ : (QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
+ const QByteArray json = opts.genBin
+ ? m_doc.toBinaryData()
+ : m_doc.toJson(opts.compact ? QJsonDocument::Compact : QJsonDocument::Indented);
+#else
+ if (opts.showLog)
+ qDebug().noquote() << "Writing" << gltfName;
+
+ const QIODevice::OpenMode openMode
+ = QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text;
+ const QByteArray json
+ = m_doc.toJson(opts.compact ? QJsonDocument::Compact : QJsonDocument::Indented);
+#endif
+
+ if (f.open(openMode)) {
+ m_files.insert(QFileInfo(f.fileName()).fileName());
+ f.write(json);
+ f.close();
}
QString qrcName = opts.outDir + basename + QStringLiteral(".qrc");
@@ -2509,8 +2519,10 @@ int main(int argc, char **argv)
cmdLine.setApplicationDescription(QString::fromUtf8(description));
QCommandLineOption outDirOpt(QStringLiteral("d"), QStringLiteral("Place all output data into <dir>"), QStringLiteral("dir"));
cmdLine.addOption(outDirOpt);
+#ifndef QT_BOOTSTRAPPED
QCommandLineOption binOpt(QStringLiteral("b"), QStringLiteral("Store binary JSON data in the .qgltf file"));
cmdLine.addOption(binOpt);
+#endif
QCommandLineOption compactOpt(QStringLiteral("m"), QStringLiteral("Store compact JSON in the .qgltf file"));
cmdLine.addOption(compactOpt);
QCommandLineOption compOpt(QStringLiteral("c"), QStringLiteral("qCompress() vertex/index data in the .bin file"));
@@ -2533,7 +2545,9 @@ int main(int argc, char **argv)
cmdLine.addOption(silentOpt);
cmdLine.process(app);
opts.outDir = cmdLine.value(outDirOpt);
+#ifndef QT_BOOTSTRAPPED
opts.genBin = cmdLine.isSet(binOpt);
+#endif
opts.compact = cmdLine.isSet(compactOpt);
opts.compress = cmdLine.isSet(compOpt);
opts.genTangents = cmdLine.isSet(tangentOpt);