From d8caeb4bbe91f950d645bd339c573ee9d0869737 Mon Sep 17 00:00:00 2001 From: Daniel Bulla Date: Mon, 1 May 2017 16:49:46 +0200 Subject: fixed graphicscontext applyUniform for uint uniform types. Change-Id: I20e4146ba004a9b7f0cd823aa5ceaf2ed4a7103a Reviewed-by: Paul Lemire --- src/render/graphicshelpers/graphicscontext.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index 6fa081552..6e585c0a2 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -1320,16 +1320,16 @@ void GraphicsContext::applyUniform(const ShaderUniform &description, const Unifo break; case UniformType::UInt: - applyUniformHelper(description.m_location, description.m_size, v); + applyUniformHelper(description.m_location, description.m_size, v); break; case UniformType::UIVec2: - applyUniformHelper(description.m_location, description.m_size, v); + applyUniformHelper(description.m_location, description.m_size, v); break; case UniformType::UIVec3: - applyUniformHelper(description.m_location, description.m_size, v); + applyUniformHelper(description.m_location, description.m_size, v); break; case UniformType::UIVec4: - applyUniformHelper(description.m_location, description.m_size, v); + applyUniformHelper(description.m_location, description.m_size, v); break; case UniformType::Bool: -- cgit v1.2.3 From 46e4a33fe90b7ff21baffcb08194ef4c7b346df7 Mon Sep 17 00:00:00 2001 From: Oleg Evseev Date: Wed, 26 Apr 2017 13:03:42 +0300 Subject: Optimize partial data update support for QBuffer Now both QBuffer setData/functor and partial data update can be called without unexpected behavior. Optimize applying sequential updates. Change-Id: I5d3a8bcb7eb6eeb3ae33f0fbedbb34acedd1c000 Reviewed-by: Oleg Evseev Reviewed-by: Dmitry Volosnykh Reviewed-by: Paul Lemire --- src/render/geometry/buffer.cpp | 9 ++++++- src/render/graphicshelpers/graphicscontext.cpp | 36 ++++++++++++++++++-------- 2 files changed, 33 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp index 1133b8e5e..ae5ede731 100644 --- a/src/render/geometry/buffer.cpp +++ b/src/render/geometry/buffer.cpp @@ -134,7 +134,14 @@ void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) QByteArray propertyName = propertyChange->propertyName(); if (propertyName == QByteArrayLiteral("data")) { QByteArray newData = propertyChange->value().value(); - m_bufferDirty |= m_data != newData; + bool dirty = m_data != newData; + m_bufferDirty |= dirty; + if (dirty) { + QBufferUpdate updateNewData; + updateNewData.offset = -1; + m_bufferUpdates.clear(); //previous updates are pointless + m_bufferUpdates.push_back(updateNewData); + } m_data = newData; } else if (propertyName == QByteArrayLiteral("updateData")) { Qt3DRender::QBufferUpdate updateData = propertyChange->value().value(); diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index 6e585c0a2..65414e220 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -1528,21 +1528,35 @@ void GraphicsContext::uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool rel // * setData was called changing the whole data or functor (or the usage pattern) // * partial buffer updates where received - // Note: we assume the case where both setData/functor and updates are called to be a misuse - // with unexpected behavior - const QVector updates = std::move(buffer->pendingBufferUpdates()); - if (!updates.empty()) { - for (const Qt3DRender::QBufferUpdate &update : updates) { + // TO DO: Handle usage pattern + QVector updates = std::move(buffer->pendingBufferUpdates()); + for (auto it = updates.begin(); it != updates.end(); ++it) { + auto update = it; + if (update->offset >= 0) { + //accumulate sequential updates as single one + int bufferSize = update->data.size(); + auto it2 = it + 1; + while ((it2 != updates.end()) + && (it2->offset - update->offset == bufferSize)) { + bufferSize += it2->data.size(); + ++it2; + } + update->data.resize(bufferSize); + while (it + 1 != it2) { + ++it; + update->data.replace(it->offset - update->offset, it->data.size(), it->data); + it->data.clear(); + } // TO DO: based on the number of updates .., it might make sense to // sometime use glMapBuffer rather than glBufferSubData - b->update(this, update.data.constData(), update.data.size(), update.offset); + b->update(this, update->data.constData(), update->data.size(), update->offset); + } else { + const int bufferSize = buffer->data().size(); + b->allocate(this, bufferSize, false); // orphan the buffer + b->allocate(this, buffer->data().constData(), bufferSize, false); } - } else { - const int bufferSize = buffer->data().size(); - // TO DO: Handle usage pattern - b->allocate(this, bufferSize, false); // orphan the buffer - b->allocate(this, buffer->data().constData(), bufferSize, false); } + if (releaseBuffer) { b->release(this); if (bufferTypeToGLBufferType(buffer->type()) == GLBuffer::ArrayBuffer) -- cgit v1.2.3 From 8b45682dfb5bff49c6a7e9ed7b1bbe56e5801585 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 5 May 2017 17:05:34 +0200 Subject: AssimpImporter: properly handle texture wrapping By default the wrap mode is Repeat. If specified it is changed to the appropriate value. Note: This changes also shows that each material could be definining the same texture with different wrap modes. Therefore we cannot store textures only based on their file path like we used to. Change-Id: Ic543c466d7c5cc7cd7e26d1738006952a8ce746b Task-number: QTBUG-59531 Reviewed-by: Sean Harmer --- src/plugins/sceneparsers/assimp/assimpimporter.cpp | 47 +++++++++++++++++----- src/plugins/sceneparsers/assimp/assimpimporter.h | 1 - 2 files changed, 36 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.cpp b/src/plugins/sceneparsers/assimp/assimpimporter.cpp index 5d5593585..196e1d22f 100644 --- a/src/plugins/sceneparsers/assimp/assimpimporter.cpp +++ b/src/plugins/sceneparsers/assimp/assimpimporter.cpp @@ -142,7 +142,7 @@ QMatrix4x4 aiMatrix4x4ToQMatrix4x4(const aiMatrix4x4 &matrix) Q_DECL_NOTHROW /*! * Returns a QString from \a str; */ -static inline QString aiStringToQString(const aiString &str) +inline QString aiStringToQString(const aiString &str) { return QString::fromUtf8(str.data, int(str.length)); } @@ -246,6 +246,21 @@ QAttribute *createAttribute(QBuffer *buffer, return attribute; } +QTextureWrapMode::WrapMode wrapModeFromaiTextureMapMode(int mode) +{ + switch (mode) { + case aiTextureMapMode_Wrap: + return QTextureWrapMode::Repeat; + case aiTextureMapMode_Mirror: + return QTextureWrapMode::MirroredRepeat; + case aiTextureMapMode_Decal: + return QTextureWrapMode::ClampToBorder; + case aiTextureMapMode_Clamp: + default: + return QTextureWrapMode::ClampToEdge; + } +} + } // anonymous QStringList AssimpImporter::assimpSupportedFormatsList = AssimpImporter::assimpSupportedFormats(); @@ -1237,18 +1252,28 @@ void AssimpImporter::copyMaterialTextures(QMaterial *material, aiMaterial *assim for (unsigned int i = 0; i < sizeof(textureType)/sizeof(textureType[0]); i++) { aiString path; if (assimpMaterial->GetTexture(textureType[i], 0, &path) == AI_SUCCESS) { - QString fullPath = m_sceneDir.absoluteFilePath(texturePath(path)); + const QString fullPath = m_sceneDir.absoluteFilePath(texturePath(path)); // Load texture if not already loaded - if (!m_scene->m_materialTextures.contains(fullPath)) { - QAbstractTexture *tex = QAbstractNodeFactory::createNode("QTexture2D"); - QTextureImage *texImage = QAbstractNodeFactory::createNode("QTextureImage"); - texImage->setSource(QUrl::fromLocalFile(fullPath)); - tex->addTextureImage(texImage); - m_scene->m_materialTextures.insert(fullPath, tex); - qCDebug(AssimpImporterLog) << Q_FUNC_INFO << " Loaded Texture " << fullPath; - } + QAbstractTexture *tex = QAbstractNodeFactory::createNode("QTexture2D"); + QTextureImage *texImage = QAbstractNodeFactory::createNode("QTextureImage"); + texImage->setSource(QUrl::fromLocalFile(fullPath)); + tex->addTextureImage(texImage); + + // Set proper wrapping mode + QTextureWrapMode wrapMode(QTextureWrapMode::Repeat); + int xMode = 0; + int yMode = 0; + + if (assimpMaterial->Get(AI_MATKEY_MAPPINGMODE_U(textureType[i], 0), xMode) == aiReturn_SUCCESS) + wrapMode.setX(wrapModeFromaiTextureMapMode(xMode)); + if (assimpMaterial->Get(AI_MATKEY_MAPPINGMODE_V(textureType[i], 0), yMode) == aiReturn_SUCCESS) + wrapMode.setY(wrapModeFromaiTextureMapMode(yMode)); + + tex->setWrapMode(wrapMode); + + qCDebug(AssimpImporterLog) << Q_FUNC_INFO << " Loaded Texture " << fullPath; setParameterValue(m_scene->m_textureToParameterName[textureType[i]], - material, QVariant::fromValue(m_scene->m_materialTextures[fullPath])); + material, QVariant::fromValue(tex)); } } } diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.h b/src/plugins/sceneparsers/assimp/assimpimporter.h index 7335830f5..e37950981 100644 --- a/src/plugins/sceneparsers/assimp/assimpimporter.h +++ b/src/plugins/sceneparsers/assimp/assimpimporter.h @@ -143,7 +143,6 @@ private: QMap m_materials; QMap m_effects; QMap m_embeddedTextures; - QMap m_materialTextures; QMap m_cameras; QHash m_textureToParameterName; QVector m_animations; -- cgit v1.2.3 From 20ac249e7b408d37f70d0a5455c38606546bb9c3 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 5 May 2017 12:07:15 +0200 Subject: Logic: only execute FrameActions which are enabled Change-Id: Ib89f6a4eae1b875a17c124337e0e4283d5d62b9e Task-number: QTBUG-60584 Reviewed-by: Sean Harmer --- src/logic/executor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/logic/executor.cpp b/src/logic/executor.cpp index ab4ac154d..6134e801e 100644 --- a/src/logic/executor.cpp +++ b/src/logic/executor.cpp @@ -96,7 +96,7 @@ void Executor::processLogicFrameUpdates(float dt) const QVector nodes = m_scene->lookupNodes(m_nodeIds); for (QNode *node : nodes) { QFrameAction *frameAction = qobject_cast(node); - if (frameAction) + if (frameAction && frameAction->isEnabled()) frameAction->onTriggered(dt); } -- cgit v1.2.3 From 4a2d8d6ee54976e3a8e2218bc8e97c857688cdfe Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Thu, 4 May 2017 13:13:23 +0200 Subject: Fix Buffer uploading We used to load buffer data when creating it. This led to cases where we would not take into account immediately buffer updates after creation. This would then results in artifacts that would pop up on screen as actual buffer data and count would be different Change-Id: I5a2fad4fb5d7c1e1542cd0bf87ded16a111bc613 Task-number: QTBUG-60429 Reviewed-by: Oleg Evseev Reviewed-by: Laszlo Agocs --- src/render/backend/renderer.cpp | 5 ++--- src/render/geometry/buffer.cpp | 26 ++++++++++++++++++++------ src/render/geometry/buffer_p.h | 1 + src/render/graphicshelpers/graphicscontext.cpp | 6 ++++-- 4 files changed, 27 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 4080a72eb..bd8687d5e 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -1013,12 +1013,11 @@ void Renderer::updateGLResources() const QVector dirtyBufferHandles = std::move(m_dirtyBuffers); for (HBuffer handle: dirtyBufferHandles) { Buffer *buffer = m_nodesManager->bufferManager()->data(handle); - // Perform data upload // Forces creation if it doesn't exit if (!m_graphicsContext->hasGLBufferForBuffer(buffer)) m_graphicsContext->glBufferForRenderBuffer(buffer); - else if (buffer->isDirty()) // Otherwise update the glBuffer - m_graphicsContext->updateBuffer(buffer); + // Update the glBuffer data + m_graphicsContext->updateBuffer(buffer); buffer->unsetDirty(); } } diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp index ae5ede731..82dbbcc1b 100644 --- a/src/render/geometry/buffer.cpp +++ b/src/render/geometry/buffer.cpp @@ -88,6 +88,9 @@ void Buffer::executeFunctor() { Q_ASSERT(m_functor); 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()); @@ -101,6 +104,8 @@ void Buffer::executeFunctor() //Called from th sendBufferJob 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()); @@ -121,12 +126,25 @@ void Buffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chang m_access = data.access; m_bufferDirty = true; + if (!m_data.isEmpty()) + forceDataUpload(); + m_functor = data.functor; Q_ASSERT(m_manager); if (m_functor) m_manager->addDirtyBuffer(peerId()); } +void Buffer::forceDataUpload() +{ + // We push back an update with offset = -1 + // As this is the way to force data to be loaded + QBufferUpdate updateNewData; + updateNewData.offset = -1; + m_bufferUpdates.clear(); //previous updates are pointless + m_bufferUpdates.push_back(updateNewData); +} + void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) { if (e->type() == PropertyUpdated) { @@ -136,13 +154,9 @@ void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) QByteArray newData = propertyChange->value().value(); bool dirty = m_data != newData; m_bufferDirty |= dirty; - if (dirty) { - QBufferUpdate updateNewData; - updateNewData.offset = -1; - m_bufferUpdates.clear(); //previous updates are pointless - m_bufferUpdates.push_back(updateNewData); - } m_data = newData; + if (dirty) + forceDataUpload(); } else if (propertyName == QByteArrayLiteral("updateData")) { Qt3DRender::QBufferUpdate updateData = propertyChange->value().value(); m_bufferUpdates.push_back(updateData); diff --git a/src/render/geometry/buffer_p.h b/src/render/geometry/buffer_p.h index 9d9606eb0..691d6cc60 100644 --- a/src/render/geometry/buffer_p.h +++ b/src/render/geometry/buffer_p.h @@ -90,6 +90,7 @@ public: private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL; + void forceDataUpload(); QBuffer::BufferType m_type; QBuffer::UsageType m_usage; diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index 65414e220..80e8267da 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -1501,8 +1501,6 @@ HGLBuffer GraphicsContext::createGLBufferFor(Buffer *buffer) if (!bindGLBuffer(b, bufferTypeToGLBufferType(buffer->type()))) qCWarning(Render::Io) << Q_FUNC_INFO << "buffer binding failed"; - // TO DO: Handle usage pattern - b->allocate(this, buffer->data().constData(), buffer->data().size(), false); return m_renderer->nodeManagers()->glBufferManager()->lookupHandle(buffer->peerId()); } @@ -1532,6 +1530,7 @@ void GraphicsContext::uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool rel QVector updates = std::move(buffer->pendingBufferUpdates()); for (auto it = updates.begin(); it != updates.end(); ++it) { auto update = it; + // We have a partial update if (update->offset >= 0) { //accumulate sequential updates as single one int bufferSize = update->data.size(); @@ -1551,6 +1550,9 @@ void GraphicsContext::uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool rel // sometime use glMapBuffer rather than glBufferSubData b->update(this, update->data.constData(), update->data.size(), update->offset); } else { + // We have an update that was done by calling QBuffer::setData + // which is used to resize or entirely clear the buffer + // Note: we use the buffer data directly in that case const int bufferSize = buffer->data().size(); b->allocate(this, bufferSize, false); // orphan the buffer b->allocate(this, buffer->data().constData(), bufferSize, false); -- cgit v1.2.3