summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/jobs/qthreadpooler.cpp13
-rw-r--r--src/core/jobs/qthreadpooler_p.h2
-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/quick3d/imports/scene3d/scene3ditem.cpp4
-rw-r--r--src/quick3d/quick3d/qquaternionanimation.cpp2
-rw-r--r--src/quick3d/quick3dextras/qt3dquickwindow.cpp2
-rw-r--r--src/render/backend/bufferutils_p.h4
-rw-r--r--src/render/backend/segmentsvisitor.cpp52
-rw-r--r--src/render/backend/stringtoint.cpp39
-rw-r--r--src/render/backend/trianglesvisitor.cpp11
-rw-r--r--src/render/backend/visitorutils_p.h2
-rw-r--r--src/render/jobs/expandboundingvolumejob.cpp4
-rw-r--r--src/render/jobs/updateworldboundingvolumejob.cpp4
-rw-r--r--src/render/jobs/updateworldtransformjob.cpp3
-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/shader.cpp64
-rw-r--r--src/render/materialsystem/shader_p.h26
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp10
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp9
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h9
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp11
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h12
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp68
-rw-r--r--src/render/renderers/opengl/renderer/renderview.cpp161
-rw-r--r--src/render/renderers/opengl/renderer/renderview_p.h9
-rw-r--r--src/render/renderers/opengl/renderer/renderviewbuilder.cpp74
-rw-r--r--tests/auto/core/qaspectengine/tst_qaspectengine.cpp6
-rw-r--r--tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp27
-rw-r--r--tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp26
34 files changed, 516 insertions, 246 deletions
diff --git a/src/core/jobs/qthreadpooler.cpp b/src/core/jobs/qthreadpooler.cpp
index a9f4e7a31..3ab321542 100644
--- a/src/core/jobs/qthreadpooler.cpp
+++ b/src/core/jobs/qthreadpooler.cpp
@@ -66,16 +66,19 @@ QThreadPooler::QThreadPooler(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);
+ m_threadPool->setExpiryTimeout(-1);
#if QT_CONFIG(qt3d_profile_jobs)
QThreadPooler::m_jobsStatTimer.start();
#endif
@@ -105,7 +108,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 +128,7 @@ void QThreadPooler::taskFinished(RunnableInterface *task)
if (!aspectTask->reserved()) {
aspectTask->setReserved(true);
aspectTask->setPooler(this);
- m_threadPool.start(aspectTask);
+ m_threadPool->start(aspectTask);
}
}
}
@@ -188,7 +191,7 @@ int QThreadPooler::currentCount() const
int QThreadPooler::maxThreadCount() const
{
- return m_threadPool.maxThreadCount();
+ return m_threadPool->maxThreadCount();
}
#if QT_CONFIG(qt3d_profile_jobs)
diff --git a/src/core/jobs/qthreadpooler_p.h b/src/core/jobs/qthreadpooler_p.h
index 65459efba..3e17cbd6d 100644
--- a/src/core/jobs/qthreadpooler_p.h
+++ b/src/core/jobs/qthreadpooler_p.h
@@ -103,7 +103,7 @@ private:
QFutureInterface<void> *m_futureInterface;
QMutex m_mutex;
QAtomicInt m_taskCount;
- QThreadPool m_threadPool;
+ QThreadPool *m_threadPool;
};
} // namespace Qt3DCore
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/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp
index f0ebfbc38..f824d2c4e 100644
--- a/src/quick3d/imports/scene3d/scene3ditem.cpp
+++ b/src/quick3d/imports/scene3d/scene3ditem.cpp
@@ -474,10 +474,12 @@ bool Scene3DItem::needsRender()
// processFrame will block and wait for renderer to have been finished
void Scene3DItem::onBeforeSync()
{
+ 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())
+ if (!isVisible() && dontRenderWhenHidden)
return;
Q_ASSERT(QThread::currentThread() == thread());
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/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/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/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/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/jobs/expandboundingvolumejob.cpp b/src/render/jobs/expandboundingvolumejob.cpp
index d63934b54..641a5c272 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());
}
}
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 e3487e68b..ea9aa778c 100644
--- a/src/render/jobs/updateworldtransformjob.cpp
+++ b/src/render/jobs/updateworldtransformjob.cpp
@@ -67,6 +67,9 @@ struct TransformUpdate
void updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform, QVector<TransformUpdate> &updatedTransforms)
{
+ if (!node->isEnabled())
+ return;
+
Matrix4x4 worldTransform(parentTransform);
Transform *nodeTransform = node->renderComponent<Transform>();
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/shader.cpp b/src/render/materialsystem/shader.cpp
index 300a71b84..0d4b5edba 100644
--- a/src/render/materialsystem/shader.cpp
+++ b/src/render/materialsystem/shader.cpp
@@ -57,6 +57,29 @@ 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)
@@ -308,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]);
@@ -394,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 fe1a401d9..298b09c6c 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/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/jobs/renderviewcommandbuilderjob.cpp b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp
index c6bc20423..091d49ef5 100644
--- a/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp
@@ -53,6 +53,8 @@ int renderViewInstanceCounter = 0;
RenderViewCommandBuilderJob::RenderViewCommandBuilderJob()
: Qt3DCore::QAspectJob()
+ , m_offset(0)
+ , m_count(0)
, m_renderView(nullptr)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderViewCommandBuilder, renderViewInstanceCounter++)
@@ -61,11 +63,14 @@ RenderViewCommandBuilderJob::RenderViewCommandBuilderJob()
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_commandData = m_renderView->buildDrawRenderCommands(m_entities, m_offset, m_count);
else
- m_commandData = m_renderView->buildComputeRenderCommands(m_entities);
+ m_commandData = m_renderView->buildComputeRenderCommands(m_entities, m_offset, m_count);
}
}
diff --git a/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h
index 9f45a8005..556c7f241 100644
--- a/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h
+++ b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h
@@ -67,12 +67,19 @@ public:
RenderViewCommandBuilderJob();
inline void setRenderView(RenderView *rv) Q_DECL_NOTHROW { m_renderView = rv; }
- inline void setEntities(const QVector<Entity *> &entities) { m_entities = entities; }
+ 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;
QVector<Entity *> m_entities;
EntityRenderCommandData m_commandData;
diff --git a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
index af1d545ed..6d6ae7853 100644
--- a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
@@ -54,8 +54,11 @@ int renderViewInstanceCounter = 0;
RenderViewCommandUpdaterJob::RenderViewCommandUpdaterJob()
: Qt3DCore::QAspectJob()
+ , m_offset(0)
+ , m_count(0)
, m_renderView(nullptr)
, m_renderer(nullptr)
+ , m_renderables(nullptr)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderCommandUpdater, renderViewInstanceCounter++);
}
@@ -65,12 +68,10 @@ 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_count == 0)
+ return;
// Update Render Commands (Uniform Change, Depth Change)
- m_renderView->updateRenderCommand(m_renderables);
-
- // Copy commands out of cached -> ensures we can submit them for rendering
- // while cache is rebuilt or modified for next frame
- m_commands = m_renderables.commands;
+ m_renderView->updateRenderCommand(m_renderables, m_offset, m_count);
}
}
diff --git a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h
index 72caef6cf..e6df3f3b3 100644
--- a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h
+++ b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h
@@ -71,16 +71,24 @@ public:
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 EntityRenderCommandData &renderables) Q_DECL_NOTHROW { m_renderables = renderables; }
+ inline void setRenderables(EntityRenderCommandData *renderables, int offset, int count) Q_DECL_NOTHROW
+ {
+ m_offset = offset;
+ m_count = count;
+ m_renderables = renderables;
+ }
+ EntityRenderCommandData *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;
- EntityRenderCommandData m_renderables;
+ EntityRenderCommandData *m_renderables;
QVector<RenderCommand> m_commands;
};
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index bf9230079..d61d1d8ac 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -1019,74 +1019,6 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
// 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;
- }
- }
-
- 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);
Q_ASSERT(shader);
diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp
index 0ac4f876f..d7e34e16c 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:
@@ -621,13 +621,16 @@ void RenderView::addClearBuffers(const ClearBuffers *cb) {
}
// If we are there, we know that entity had a GeometryRenderer + Material
-EntityRenderCommandData RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities) const
+EntityRenderCommandData RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities,
+ int offset, int count) const
{
EntityRenderCommandData 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>();
@@ -640,12 +643,15 @@ EntityRenderCommandData RenderView::buildDrawRenderCommands(const QVector<Entity
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 = {};
command.m_geometryRenderer = geometryRendererHandle;
- command.m_geometry = m_manager->geometryManager()->lookupHandle(geometryRenderer->geometryId());
+ command.m_geometry = geometryHandle;
command.m_material = materialHandle;
// For RenderPass based states we use the globally set RenderState
@@ -662,6 +668,71 @@ EntityRenderCommandData RenderView::buildDrawRenderCommands(const QVector<Entity
}
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;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ 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));
@@ -672,7 +743,8 @@ EntityRenderCommandData RenderView::buildDrawRenderCommands(const QVector<Entity
return commands;
}
-EntityRenderCommandData RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities) const
+EntityRenderCommandData RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities,
+ int offset, int count) const
{
// If the RenderView contains only a ComputeDispatch then it cares about
// A ComputeDispatch is also implicitely a NoDraw operation
@@ -681,9 +753,11 @@ EntityRenderCommandData RenderView::buildComputeRenderCommands(const QVector<Ent
// material/effect/technique/parameters/filters/
EntityRenderCommandData 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);
ComputeCommand *computeJob = nullptr;
HComputeCommand computeCommandHandle = entity->componentHandle<ComputeCommand>();
if ((computeJob = nodeManagers()->computeJobManager()->data(computeCommandHandle)) != nullptr
@@ -725,7 +799,9 @@ EntityRenderCommandData RenderView::buildComputeRenderCommands(const QVector<Ent
return commands;
}
-void RenderView::updateRenderCommand(EntityRenderCommandData &renderCommandData)
+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
@@ -735,10 +811,11 @@ void RenderView::updateRenderCommand(EntityRenderCommandData &renderCommandData)
builder->textureManager = m_manager->textureManager();
m_localData.setLocalData(builder);
- for (int i = 0, m = renderCommandData.size(); i < m; ++i) {
- Entity *entity = renderCommandData.entities.at(i);
- const RenderPassParameterData passData = renderCommandData.passesData.at(i);
- RenderCommand &command = renderCommandData.commands[i];
+ 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.
@@ -944,6 +1021,7 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
// 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();
@@ -963,20 +1041,23 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
shader->setFragOutputs(fragOutputs);
}
- if (!uniformNamesIds.isEmpty() || !attributeNamesIds.isEmpty() ||
+ 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 : uniformNamesIds) {
- if (ms_standardUniformSetters.contains(uniformNameId))
+ 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
diff --git a/src/render/renderers/opengl/renderer/renderview_p.h b/src/render/renderers/opengl/renderer/renderview_p.h
index 1221e7a59..c7dc37a2c 100644
--- a/src/render/renderers/opengl/renderer/renderview_p.h
+++ b/src/render/renderers/opengl/renderer/renderview_p.h
@@ -227,11 +227,14 @@ public:
RenderPassList passesAndParameters(ParameterInfoList *parameter, Entity *node, bool useDefaultMaterials = true);
- EntityRenderCommandData buildDrawRenderCommands(const QVector<Entity *> &entities) const;
- EntityRenderCommandData buildComputeRenderCommands(const QVector<Entity *> &entities) const;
+ 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);
+ void updateRenderCommand(EntityRenderCommandData *renderCommandData,
+ int offset, int count);
void setCommands(const QVector<RenderCommand> &commands) Q_DECL_NOTHROW { m_commands = commands; }
diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
index 96fa55c47..9f7589ecc 100644
--- a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
+++ b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
@@ -50,10 +50,18 @@ 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 {
+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:
@@ -82,16 +90,16 @@ public:
lock.unlock();
- // Split among the number of command builders
- int i = 0;
- const int m = RenderViewBuilder::optimalJobCount() - 1;
- const int packetSize = entities.size() / RenderViewBuilder::optimalJobCount();
- while (i < m) {
+ // 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);
- renderViewCommandBuilder->setEntities(entities.mid(i * packetSize, packetSize));
- ++i;
+ const int count = (i == m - 1) ? entities.size() - (i * idealPacketSize) : idealPacketSize;
+ renderViewCommandBuilder->setEntities(entities, i * idealPacketSize, count);
}
- m_renderViewCommandBuilderJobs.at(i)->setEntities(entities.mid(i * packetSize, packetSize + entities.size() % (m + 1)));
}
private:
@@ -117,22 +125,20 @@ public:
// Append all the commands and sort them
RenderView *rv = m_renderViewJob->renderView();
- int totalCommandCount = 0;
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandUpdaterJobs))
- totalCommandCount += renderViewCommandBuilder->commands().size();
+ const EntityRenderCommandData *commandData = m_renderViewCommandUpdaterJobs.first()->renderables();
- QVector<RenderCommand> commands;
- commands.reserve(totalCommandCount);
+ if (commandData != nullptr) {
+ const QVector<RenderCommand> commands = std::move(commandData->commands);
- // Reduction
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandUpdaterJobs))
- commands += std::move(renderViewCommandBuilder->commands());
+ // TO DO: Cache the EntityRenderCommandData so that it can be reused if nothing in the scene has changed
+ delete commandData;
- rv->setCommands(commands);
+ rv->setCommands(commands);
- // TO DO: Find way to store commands once or at least only when required
- // 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());
@@ -279,12 +285,12 @@ public:
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;
@@ -316,8 +322,8 @@ public:
// Filter out Render commands for which the Entity wasn't selected because
// of frustum, proximity or layer filtering
- EntityRenderCommandData filteredCommandData;
- filteredCommandData.reserve(renderableEntities.size());
+ EntityRenderCommandData *filteredCommandData = new EntityRenderCommandData();
+ 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);
@@ -335,24 +341,24 @@ public:
// 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));
+ filteredCommandData->push_back(commandData.entities.at(cIt),
+ commandData.commands.at(cIt),
+ commandData.passesData.at(cIt));
++cIt;
}
++eIt;
}
// Split among the number of command builders
- int i = 0;
- const int m = RenderViewBuilder::optimalJobCount() - 1;
- const int packetSize = filteredCommandData.size() / RenderViewBuilder::optimalJobCount();
- while (i < m) {
+ // 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);
- renderViewCommandBuilder->setRenderables(filteredCommandData.mid(i * packetSize, packetSize));
- ++i;
+ const int count = (i == m - 1) ? filteredCommandData->size() - (i * idealPacketSize) : idealPacketSize;
+ renderViewCommandBuilder->setRenderables(filteredCommandData, i * idealPacketSize, count);
}
- m_renderViewCommandUpdaterJobs.at(i)->setRenderables(filteredCommandData.mid(i * packetSize, packetSize + filteredCommandData.size() % (m + 1)));
}
}
diff --git a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp
index eb20536e6..2f16bf7c6 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
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/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()