From a263091c94e9a02d4e252df318b514854bf4732e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 14 Apr 2016 13:48:24 -0700 Subject: [PATCH 01/22] fix entity-server crash for out of bounds --- libraries/entities/src/EntityItem.cpp | 11 ++++++----- libraries/entities/src/EntitySimulation.cpp | 3 +-- libraries/entities/src/EntitySimulation.h | 2 +- libraries/entities/src/SimpleEntitySimulation.cpp | 9 +++++++++ libraries/entities/src/SimpleEntitySimulation.h | 2 ++ libraries/shared/src/SpatiallyNestable.cpp | 4 ++-- libraries/shared/src/SpatiallyNestable.h | 2 +- 7 files changed, 22 insertions(+), 11 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1f5db65089..65811c5c57 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -926,7 +926,8 @@ void EntityItem::simulateKinematicMotion(float timeElapsed, bool setFlags) { glm::quat dQ = computeBulletRotationStep(localAngularVelocity, dt); rotation = glm::normalize(dQ * rotation); - setRotation(rotation); + bool success; + setOrientation(rotation, success, false); } setLocalAngularVelocity(localAngularVelocity); @@ -1983,10 +1984,10 @@ void EntityItem::locationChanged(bool tellPhysics) { requiresRecalcBoxes(); if (tellPhysics) { _dirtyFlags |= Simulation::DIRTY_TRANSFORM; - } - EntityTreePointer tree = getTree(); - if (tree) { - tree->entityChanged(getThisPointer()); + EntityTreePointer tree = getTree(); + if (tree) { + tree->entityChanged(getThisPointer()); + } } SpatiallyNestable::locationChanged(tellPhysics); // tell all the children, also } diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index 14bfc5ac7a..7eed6d1c1a 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -35,6 +35,7 @@ void EntitySimulation::updateEntities() { callUpdateOnEntitiesThatNeedIt(now); moveSimpleKinematics(now); updateEntitiesInternal(now); + PerformanceTimer perfTimer("sortingEntities"); sortEntitiesThatMoved(); } @@ -133,10 +134,8 @@ void EntitySimulation::callUpdateOnEntitiesThatNeedIt(const quint64& now) { // protected void EntitySimulation::sortEntitiesThatMoved() { - QMutexLocker lock(&_mutex); // NOTE: this is only for entities that have been moved by THIS EntitySimulation. // External changes to entity position/shape are expected to be sorted outside of the EntitySimulation. - PerformanceTimer perfTimer("sortingEntities"); MovingEntitiesOperator moveOperator(_entityTree); AACube domainBounds(glm::vec3((float)-HALF_TREE_SCALE), (float)TREE_SCALE); SetOfEntities::iterator itemItr = _entitiesToSort.begin(); diff --git a/libraries/entities/src/EntitySimulation.h b/libraries/entities/src/EntitySimulation.h index 442ff4a74b..cbedbbd868 100644 --- a/libraries/entities/src/EntitySimulation.h +++ b/libraries/entities/src/EntitySimulation.h @@ -92,7 +92,7 @@ protected: void expireMortalEntities(const quint64& now); void callUpdateOnEntitiesThatNeedIt(const quint64& now); - void sortEntitiesThatMoved(); + virtual void sortEntitiesThatMoved(); QMutex _mutex{ QMutex::Recursive }; diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index 6bf25f767d..e406926141 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -132,3 +132,12 @@ void SimpleEntitySimulation::clearEntitiesInternal() { _entitiesThatNeedSimulationOwner.clear(); } +void SimpleEntitySimulation::sortEntitiesThatMoved() { + SetOfEntities::iterator itemItr = _entitiesToSort.begin(); + while (itemItr != _entitiesToSort.end()) { + EntityItemPointer entity = *itemItr; + entity->computePuffedQueryAACube(); + ++itemItr; + } + EntitySimulation::sortEntitiesThatMoved(); +} diff --git a/libraries/entities/src/SimpleEntitySimulation.h b/libraries/entities/src/SimpleEntitySimulation.h index d9c04fdcf9..12ded8a30d 100644 --- a/libraries/entities/src/SimpleEntitySimulation.h +++ b/libraries/entities/src/SimpleEntitySimulation.h @@ -30,6 +30,8 @@ protected: virtual void changeEntityInternal(EntityItemPointer entity) override; virtual void clearEntitiesInternal() override; + virtual void sortEntitiesThatMoved() override; + SetOfEntities _entitiesWithSimulationOwner; SetOfEntities _entitiesThatNeedSimulationOwner; quint64 _nextOwnerlessExpiry { 0 }; diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index 11d0668001..c4cb4f94ba 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -620,7 +620,7 @@ glm::vec3 SpatiallyNestable::getLocalPosition() const { return result; } -void SpatiallyNestable::setLocalPosition(const glm::vec3& position) { +void SpatiallyNestable::setLocalPosition(const glm::vec3& position, bool tellPhysics) { // guard against introducing NaN into the transform if (isNaN(position)) { qDebug() << "SpatiallyNestable::setLocalPosition -- position contains NaN"; @@ -629,7 +629,7 @@ void SpatiallyNestable::setLocalPosition(const glm::vec3& position) { _transformLock.withWriteLock([&] { _transform.setTranslation(position); }); - locationChanged(); + locationChanged(tellPhysics); } glm::quat SpatiallyNestable::getLocalOrientation() const { diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index c120c1010c..6485c23b87 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -102,7 +102,7 @@ public: virtual void setLocalTransform(const Transform& transform); virtual glm::vec3 getLocalPosition() const; - virtual void setLocalPosition(const glm::vec3& position); + virtual void setLocalPosition(const glm::vec3& position, bool tellPhysics = true); virtual glm::quat getLocalOrientation() const; virtual void setLocalOrientation(const glm::quat& orientation); From a9fefcc8023cfd1aba024321958025c00cfd025f Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 14 Apr 2016 18:16:14 -0700 Subject: [PATCH 02/22] Trying ti debug the bad normal maps --- libraries/gpu/src/gpu/GLBackendTexelFormat.cpp | 2 -- .../src/model-networking/ModelCache.cpp | 3 ++- libraries/model/src/model/TextureMap.cpp | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendTexelFormat.cpp b/libraries/gpu/src/gpu/GLBackendTexelFormat.cpp index 1a7b969e13..00528d0030 100644 --- a/libraries/gpu/src/gpu/GLBackendTexelFormat.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexelFormat.cpp @@ -399,11 +399,9 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E } break; case gpu::SRGB: - texel.format = GL_RGB; texel.internalFormat = GL_SRGB8; break; case gpu::SRGBA: - texel.format = GL_RGBA; texel.internalFormat = GL_SRGB8_ALPHA8; // standard 2.2 gamma correction color break; case gpu::COMPRESSED_RGBA: diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index b8deef9f27..586f2423af 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -497,7 +497,8 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!normalName.isEmpty()) { auto url = textureMap.contains(normalName) ? textureMap[normalName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, NORMAL_TEXTURE, MapChannel::NORMAL_MAP); + // auto map = fetchTextureMap(url, NORMAL_TEXTURE, MapChannel::NORMAL_MAP); + auto map = fetchTextureMap(url, DEFAULT_TEXTURE, MapChannel::NORMAL_MAP); setTextureMap(MapChannel::NORMAL_MAP, map); } diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 014431619c..b50a35bb9d 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -198,8 +198,18 @@ gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImag gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) { QImage image = srcImage; - if (image.format() != QImage::Format_RGB888) { + /* if (image.format() != QImage::Format_RGB888) { image = image.convertToFormat(QImage::Format_RGB888); + }*/ + + if (!image.hasAlphaChannel()) { + if (image.format() != QImage::Format_RGB888) { + image = image.convertToFormat(QImage::Format_RGB888); + } + } else { + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } } gpu::Texture* theTexture = nullptr; @@ -208,6 +218,10 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); + if (image.hasAlphaChannel()) { + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::BGRA); + } theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); From 30d0bfcfd35659b04353143f73d9a081fb3593fe Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 15 Apr 2016 00:41:37 -0700 Subject: [PATCH 03/22] FIxing the bump map loading which got broken in the past PR, fixed a double call to the glTexSUbIMage function and fixed a texel.Format --- libraries/gpu/src/gpu/GLBackendTexture.cpp | 4 ++-- libraries/model/src/model/TextureMap.cpp | 25 ++++++---------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 8da6b6d300..3443bee611 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -214,8 +214,8 @@ bool GLBackend::GLTexture::isReady() const { // Move content bits from the CPU to the GPU for a given mip / face void GLBackend::GLTexture::transferMip(GLenum target, const Texture::PixelsPointer& mip) const { - GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuTexture.getTexelFormat(), mip->getFormat()); - glTexSubImage2D(target, 0, 0, 0, _gpuTexture.getWidth(), _gpuTexture.getHeight(), texelFormat.format, texelFormat.type, mip->readData()); glTexSubImage2D(target, 0, 0, 0, _gpuTexture.getWidth(), _gpuTexture.getHeight(), texelFormat.format, texelFormat.type, mip->readData()); + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuTexture.getTexelFormat(), mip->getFormat()); + glTexSubImage2D(target, 0, 0, 0, _gpuTexture.getWidth(), _gpuTexture.getHeight(), texelFormat.format, texelFormat.type, mip->readData()); (void)CHECK_GL_ERROR(); } diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index b50a35bb9d..a41e42f606 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -198,18 +198,8 @@ gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImag gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) { QImage image = srcImage; - /* if (image.format() != QImage::Format_RGB888) { + if (image.format() != QImage::Format_RGB888) { image = image.convertToFormat(QImage::Format_RGB888); - }*/ - - if (!image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - } else { - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } } gpu::Texture* theTexture = nullptr; @@ -218,11 +208,6 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); - if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::BGRA); - } - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); theTexture->autoGenerateMips(-1); @@ -246,10 +231,12 @@ double mapComponent(double sobelValue) { gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcImage, const std::string& srcImageName) { QImage image = srcImage; + if (image.format() != QImage::Format_RGB888) { + image = image.convertToFormat(QImage::Format_RGB888); + } - #if 0 - // PR 5540 by AlessandroSigna - // integrated here as a specialized TextureLoader for bumpmaps + #if 1 + // PR 5540 by AlessandroSigna integrated here as a specialized TextureLoader for bumpmaps // The conversion is done using the Sobel Filter to calculate the derivatives from the grayscale image const double pStrength = 2.0; int width = image.width(); From 920ab88ef373c836345f24dfdea1b40aae60c70a Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 15 Apr 2016 01:00:57 -0700 Subject: [PATCH 04/22] remove a debug code --- libraries/model-networking/src/model-networking/ModelCache.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index f71f37fac4..a565b249d8 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -506,8 +506,7 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!normalName.isEmpty()) { auto url = textureMap.contains(normalName) ? textureMap[normalName].toUrl() : QUrl(); - // auto map = fetchTextureMap(url, NORMAL_TEXTURE, MapChannel::NORMAL_MAP); - auto map = fetchTextureMap(url, DEFAULT_TEXTURE, MapChannel::NORMAL_MAP); + auto map = fetchTextureMap(url, NORMAL_TEXTURE, MapChannel::NORMAL_MAP); setTextureMap(MapChannel::NORMAL_MAP, map); } From fc29397d91d3839cc7c37705f5b5c11203af771a Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 15 Apr 2016 10:10:04 -0700 Subject: [PATCH 05/22] Clening up from review comments --- libraries/gpu/src/gpu/GLBackendTexture.cpp | 2 +- libraries/model/src/model/TextureMap.cpp | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 3443bee611..097d7f73cd 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -214,7 +214,7 @@ bool GLBackend::GLTexture::isReady() const { // Move content bits from the CPU to the GPU for a given mip / face void GLBackend::GLTexture::transferMip(GLenum target, const Texture::PixelsPointer& mip) const { - GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuTexture.getTexelFormat(), mip->getFormat()); + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuTexture.getTexelFormat(), mip->getFormat()); glTexSubImage2D(target, 0, 0, 0, _gpuTexture.getWidth(), _gpuTexture.getHeight(), texelFormat.format, texelFormat.type, mip->readData()); (void)CHECK_GL_ERROR(); } diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index a41e42f606..1ef8d57945 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -235,7 +235,6 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm image = image.convertToFormat(QImage::Format_RGB888); } - #if 1 // PR 5540 by AlessandroSigna integrated here as a specialized TextureLoader for bumpmaps // The conversion is done using the Sobel Filter to calculate the derivatives from the grayscale image const double pStrength = 2.0; @@ -285,8 +284,7 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm result.setPixel(i, j, qRgbValue); } } - #endif - + gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { From 5c004e2a5cf0e5aed584196d552f728aaf892a28 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Apr 2016 13:50:46 -0700 Subject: [PATCH 06/22] Add comment on storage texture ptr --- libraries/gpu/src/gpu/Texture.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 9dde359596..70b26e38a6 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -260,7 +260,7 @@ public: Stamp bumpStamp() { return ++_stamp; } protected: Stamp _stamp = 0; - Texture* _texture = nullptr; + Texture* _texture = nullptr; // Points to the parent texture (not owned) Texture::Type _type = Texture::TEX_2D; // The type of texture is needed to know the number of faces to expect std::vector> _mips; // an array of mips, each mip is an array of faces From f2b9acd84d98707ea78b94ca4fb1acd3259fa6e4 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Apr 2016 15:13:23 -0700 Subject: [PATCH 07/22] Rm Texture::createFromStorage --- libraries/gpu/src/gpu/Texture.cpp | 7 ------- libraries/gpu/src/gpu/Texture.h | 2 -- 2 files changed, 9 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 15ae609fb9..822c1392df 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -221,13 +221,6 @@ Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, ui return tex; } -Texture* Texture::createFromStorage(Storage* storage) { - Texture* tex = new Texture(); - tex->_storage.reset(storage); - storage->assignTexture(tex); - return tex; -} - Texture::Texture(): Resource() { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 70b26e38a6..9ef98098d3 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -280,8 +280,6 @@ public: static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, const Sampler& sampler = Sampler()); static Texture* createCube(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler()); - static Texture* createFromStorage(Storage* storage); - Texture(); Texture(const Texture& buf); // deep copy of the sysmem texture Texture& operator=(const Texture& buf); // deep copy of the sysmem texture From d2426f30c66618f94949ea349543a1b2f0af62ac Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Apr 2016 15:56:55 -0700 Subject: [PATCH 08/22] Mv ResourceCacheShared to top of impl --- libraries/networking/src/ResourceCache.cpp | 150 ++++++++++----------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 96e05c8d09..fcf0e833e1 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -28,6 +28,80 @@ (((x) > (max)) ? (max) :\ (x))) +void ResourceCacheSharedItems::appendActiveRequest(QWeakPointer resource) { + Lock lock(_mutex); + _loadingRequests.append(resource); +} + +void ResourceCacheSharedItems::appendPendingRequest(QWeakPointer resource) { + Lock lock(_mutex); + _pendingRequests.append(resource); +} + +QList> ResourceCacheSharedItems::getPendingRequests() { + QList> result; + + { + Lock lock(_mutex); + foreach(QSharedPointer resource, _pendingRequests) { + if (resource) { + result.append(resource); + } + } + } + return result; +} + +uint32_t ResourceCacheSharedItems::getPendingRequestsCount() const { + Lock lock(_mutex); + return _pendingRequests.size(); +} + +QList> ResourceCacheSharedItems::getLoadingRequests() { + QList> result; + + { + Lock lock(_mutex); + foreach(QSharedPointer resource, _loadingRequests) { + if (resource) { + result.append(resource); + } + } + } + return result; +} + +void ResourceCacheSharedItems::removeRequest(QWeakPointer resource) { + Lock lock(_mutex); + _loadingRequests.removeAll(resource); +} + +QSharedPointer ResourceCacheSharedItems::getHighestPendingRequest() { + Lock lock(_mutex); + // look for the highest priority pending request + int highestIndex = -1; + float highestPriority = -FLT_MAX; + QSharedPointer highestResource; + for (int i = 0; i < _pendingRequests.size();) { + auto resource = _pendingRequests.at(i).lock(); + if (!resource) { + _pendingRequests.removeAt(i); + continue; + } + float priority = resource->getLoadPriority(); + if (priority >= highestPriority) { + highestPriority = priority; + highestIndex = i; + highestResource = resource; + } + i++; + } + if (highestIndex >= 0) { + _pendingRequests.takeAt(highestIndex); + } + return highestResource; +} + ResourceCache::ResourceCache(QObject* parent) : QObject(parent) { auto& domainHandler = DependencyManager::get()->getDomainHandler(); connect(&domainHandler, &DomainHandler::disconnectedFromDomain, @@ -264,81 +338,7 @@ void ResourceCache::updateTotalSize(const qint64& oldSize, const qint64& newSize _totalResourcesSize += (newSize - oldSize); emit dirty(); } - -void ResourceCacheSharedItems::appendActiveRequest(QWeakPointer resource) { - Lock lock(_mutex); - _loadingRequests.append(resource); -} - -void ResourceCacheSharedItems::appendPendingRequest(QWeakPointer resource) { - Lock lock(_mutex); - _pendingRequests.append(resource); -} - -QList> ResourceCacheSharedItems::getPendingRequests() { - QList> result; - - { - Lock lock(_mutex); - foreach(QSharedPointer resource, _pendingRequests) { - if (resource) { - result.append(resource); - } - } - } - return result; -} - -uint32_t ResourceCacheSharedItems::getPendingRequestsCount() const { - Lock lock(_mutex); - return _pendingRequests.size(); -} - -QList> ResourceCacheSharedItems::getLoadingRequests() { - QList> result; - - { - Lock lock(_mutex); - foreach(QSharedPointer resource, _loadingRequests) { - if (resource) { - result.append(resource); - } - } - } - return result; -} - -void ResourceCacheSharedItems::removeRequest(QWeakPointer resource) { - Lock lock(_mutex); - _loadingRequests.removeAll(resource); -} - -QSharedPointer ResourceCacheSharedItems::getHighestPendingRequest() { - Lock lock(_mutex); - // look for the highest priority pending request - int highestIndex = -1; - float highestPriority = -FLT_MAX; - QSharedPointer highestResource; - for (int i = 0; i < _pendingRequests.size();) { - auto resource = _pendingRequests.at(i).lock(); - if (!resource) { - _pendingRequests.removeAt(i); - continue; - } - float priority = resource->getLoadPriority(); - if (priority >= highestPriority) { - highestPriority = priority; - highestIndex = i; - highestResource = resource; - } - i++; - } - if (highestIndex >= 0) { - _pendingRequests.takeAt(highestIndex); - } - return highestResource; -} - + QList> ResourceCache::getLoadingRequests() { return DependencyManager::get()->getLoadingRequests(); } From 0d06d8ea936660b7e6464ffc5ede1ba0da4d0821 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Apr 2016 16:22:56 -0700 Subject: [PATCH 09/22] Clear freed loading resources --- libraries/networking/src/ResourceCache.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index fcf0e833e1..8f2bbcbb85 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -73,7 +73,18 @@ QList> ResourceCacheSharedItems::getLoadingRequests() { void ResourceCacheSharedItems::removeRequest(QWeakPointer resource) { Lock lock(_mutex); - _loadingRequests.removeAll(resource); + // resource can only be removed if it still has a ref-count, as + // QWeakPointer has no operator== implementation for two weak ptrs, so + // manually loop in case resource has been freed. + for (int i = 0; i < _loadingRequests.size();) { + auto request = _loadingRequests.at(i); + // Clear our resource and any freed resources + if (!request || request.data() == resource.data()) { + _loadingRequests.removeAt(i); + continue; + } + i++; + } } QSharedPointer ResourceCacheSharedItems::getHighestPendingRequest() { @@ -82,12 +93,16 @@ QSharedPointer ResourceCacheSharedItems::getHighestPendingRequest() { int highestIndex = -1; float highestPriority = -FLT_MAX; QSharedPointer highestResource; + for (int i = 0; i < _pendingRequests.size();) { + // Clear any freed resources auto resource = _pendingRequests.at(i).lock(); if (!resource) { _pendingRequests.removeAt(i); continue; } + + // Check load priority float priority = resource->getLoadPriority(); if (priority >= highestPriority) { highestPriority = priority; @@ -96,9 +111,11 @@ QSharedPointer ResourceCacheSharedItems::getHighestPendingRequest() { } i++; } + if (highestIndex >= 0) { _pendingRequests.takeAt(highestIndex); } + return highestResource; } From 8f6cfb72ea70f8f46e912e363ef3e4999402f65b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 16 Apr 2016 15:23:41 +1200 Subject: [PATCH 10/22] Fix QML warnings at shutdown --- interface/resources/qml/AddressBarDialog.qml | 15 ++++++++++++++- interface/resources/qml/Stats.qml | 16 +++++++++++++++- interface/resources/qml/windows-uit/Window.qml | 12 +++++++++--- interface/resources/qml/windows/Window.qml | 11 ++++++++--- interface/src/Application.cpp | 3 +++ libraries/ui/src/OffscreenUi.cpp | 7 +++++++ libraries/ui/src/OffscreenUi.h | 1 + 7 files changed, 57 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index c3d795f0a3..c5712c11d2 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -17,7 +17,7 @@ import "windows" Window { id: root HifiConstants { id: hifi } - anchors.centerIn: parent + objectName: "AddressBarDialog" frame: HiddenFrame {} @@ -29,6 +29,19 @@ Window { width: addressBarDialog.implicitWidth height: addressBarDialog.implicitHeight + Component.onCompleted: { + root.parentChanged.connect(center); + center(); + } + Component.onDestruction: { + root.parentChanged.disconnect(center); + } + + function center() { + // Explicitly center in order to avoid warnings at shutdown + anchors.centerIn = parent; + } + AddressBarDialog { id: addressBarDialog implicitWidth: backgroundImage.width diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index e2dfae2a02..fe88899658 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -3,10 +3,24 @@ import QtQuick 2.3 import QtQuick.Controls 1.2 Item { - anchors.fill: parent + id: stats + anchors.leftMargin: 300 objectName: "StatsItem" + Component.onCompleted: { + stats.parentChanged.connect(fill); + fill(); + } + Component.onDestruction: { + stats.parentChanged.disconnect(fill); + } + + function fill() { + // Explicitly fill in order to avoid warnings at shutdown + anchors.fill = parent; + } + Hifi.Stats { id: root objectName: "Stats" diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml index 32fc816173..0437e63615 100644 --- a/interface/resources/qml/windows-uit/Window.qml +++ b/interface/resources/qml/windows-uit/Window.qml @@ -248,9 +248,15 @@ Fadable { children: [ swallower, frame, pane, activator ] - Component.onCompleted: { raise(); setDefaultFocus(); } - Component.onDestruction: windowDestroyed(); - onParentChanged: raise(); + Component.onCompleted: { + window.parentChanged.connect(raise); + raise(); + setDefaultFocus(); + } + Component.onDestruction: { + window.parentChanged.disconnect(raise); // Prevent warning on shutdown + windowDestroyed(); + } onVisibleChanged: { if (!visible && destroyOnInvisible) { diff --git a/interface/resources/qml/windows/Window.qml b/interface/resources/qml/windows/Window.qml index 6088a7a0aa..06be0cd9e7 100644 --- a/interface/resources/qml/windows/Window.qml +++ b/interface/resources/qml/windows/Window.qml @@ -114,9 +114,14 @@ Fadable { children: [ swallower, frame, content, activator ] - Component.onCompleted: raise(); - Component.onDestruction: windowDestroyed(); - onParentChanged: raise(); + Component.onCompleted: { + window.parentChanged.connect(raise); + raise(); + } + Component.onDestruction: { + window.parentChanged.disconnect(raise); // Prevent warning on shutdown + windowDestroyed(); + } onVisibleChanged: { if (!visible && destroyOnInvisible) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3a0b0998c5..dbb30a4582 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1150,6 +1150,9 @@ void Application::aboutToQuit() { getActiveDisplayPlugin()->deactivate(); + // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. + DependencyManager::get()->hide("RunningScripts"); + _aboutToQuit = true; cleanupBeforeQuit(); diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 45413b6c35..0c1ad69d72 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -143,6 +143,13 @@ void OffscreenUi::toggle(const QUrl& url, const QString& name, std::functionfindChild(name); + if (item) { + item->setVisible(false); + } +} + class ModalDialogListener : public QObject { Q_OBJECT friend class OffscreenUi; diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index 0e87018c5c..5a16b49491 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -37,6 +37,7 @@ public: virtual void create(QOpenGLContext* context) override; void createDesktop(const QUrl& url); void show(const QUrl& url, const QString& name, std::function f = [](QQmlContext*, QObject*) {}); + void hide(const QString& name); void toggle(const QUrl& url, const QString& name, std::function f = [](QQmlContext*, QObject*) {}); bool shouldSwallowShortcut(QEvent* event); bool navigationFocused(); From f3e5306f901cc392956e1465dfea15d63a693866 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 5 Apr 2016 13:25:00 -0700 Subject: [PATCH 11/22] Working on an automated performance test --- examples/tests/playaPerformanceTest.js | 11 + examples/tests/playaPerformanceTest.qml | 193 ++++++++++++++++++ interface/src/Application.cpp | 13 +- .../src/FrameTimingsScriptingInterface.cpp | 53 +++++ .../src/FrameTimingsScriptingInterface.h | 38 ++++ interface/src/avatar/MyAvatar.cpp | 9 + interface/src/avatar/MyAvatar.h | 4 + libraries/gpu/src/gpu/GLBackendTexture.cpp | 7 +- 8 files changed, 324 insertions(+), 4 deletions(-) create mode 100644 examples/tests/playaPerformanceTest.js create mode 100644 examples/tests/playaPerformanceTest.qml create mode 100644 interface/src/FrameTimingsScriptingInterface.cpp create mode 100644 interface/src/FrameTimingsScriptingInterface.h diff --git a/examples/tests/playaPerformanceTest.js b/examples/tests/playaPerformanceTest.js new file mode 100644 index 0000000000..4c8a728a15 --- /dev/null +++ b/examples/tests/playaPerformanceTest.js @@ -0,0 +1,11 @@ +var qml = Script.resolvePath('playaPerformanceTest.qml'); +qmlWindow = new OverlayWindow({ + title: 'Test Qml', + source: qml, + height: 320, + width: 640, + toolWindow: false, + visible: true +}); + + diff --git a/examples/tests/playaPerformanceTest.qml b/examples/tests/playaPerformanceTest.qml new file mode 100644 index 0000000000..f1382358ae --- /dev/null +++ b/examples/tests/playaPerformanceTest.qml @@ -0,0 +1,193 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Rectangle { + id: root + width: parent ? parent.width : 100 + height: parent ? parent.height : 100 + + signal sendToScript(var message); + property var values: []; + property var host: AddressManager.hostname + + + Component.onCompleted: { + Window.domainChanged.connect(function(newDomain){ + if (newDomain !== root.host) { + root.host = AddressManager.hostname; + } + }); + } + + onHostChanged: { + if (root.running) { + if (host !== "Dreaming" && host !== "Playa") { + return; + } + + console.log("PERF new domain " + host) + if (host === "Dreaming") { + AddressManager.handleLookupString("Playa"); + return; + } + + if (host === "Playa") { + console.log("PERF starting timers and frame timing"); + // If we've arrived, start running the test + FrameTimings.start(); + rotationTimer.start(); + stopTimer.start(); + } + } + } + + function startTest() { + console.log("PERF startTest()"); + root.running = true + console.log("PERF current host: " + AddressManager.hostname) + // If we're already in playa, we need to go somewhere else... + if ("Playa" === AddressManager.hostname) { + console.log("PERF Navigating to dreaming") + AddressManager.handleLookupString("Dreaming/0,0,0"); + } else { + console.log("PERF Navigating to playa") + AddressManager.handleLookupString("Playa"); + } + } + + function stopTest() { + console.log("PERF stopTest()"); + root.running = false; + stopTimer.stop(); + rotationTimer.stop(); + FrameTimings.finish(); + root.values = FrameTimings.getValues(); + AddressManager.handleLookupString("Dreaming/0,0,0"); + resultGraph.requestPaint(); + console.log("PERF Value Count: " + root.values.length); + console.log("PERF Max: " + FrameTimings.max); + console.log("PERF Min: " + FrameTimings.min); + console.log("PERF Avg: " + FrameTimings.mean); + console.log("PERF StdDev: " + FrameTimings.standardDeviation); + } + + function yaw(a) { + var y = -Math.sin( a / 2.0 ); + var w = Math.cos( a / 2.0 ); + var l = Math.sqrt((y * y) + (w * w)); + return Qt.quaternion(w / l, 0, y / l, 0); + } + + function rotate() { + MyAvatar.setOrientationVar(yaw(Date.now() / 1000)); + } + + property bool running: false + + Timer { + id: stopTimer + interval: 30 * 1000 + repeat: false + running: false + onTriggered: stopTest(); + } + + Timer { + id: rotationTimer + interval: 100 + repeat: true + running: false + onTriggered: rotate(); + } + + Row { + id: row + anchors { left: parent.left; right: parent.right; } + spacing: 8 + Button { + text: root.running ? "Stop" : "Run" + onClicked: root.running ? stopTest() : startTest(); + } + } + +// Rectangle { +// anchors { left: parent.left; right: parent.right; top: row.bottom; topMargin: 8; bottom: parent.bottom; } +// //anchors.fill: parent +// color: "#7fff0000" +// } + + // Return the maximum value from a set of values + function vv(i, max) { + var perValue = values.length / max; + var start = Math.floor(perValue * i); + var end = Math.min(values.length, Math.floor(start + perValue)); + var result = 0; + for (var j = start; j <= end; ++j) { + result = Math.max(result, values[j]); + } + return result; + } + + Canvas { + id: resultGraph + anchors { left: parent.left; right: parent.right; top: row.bottom; margins: 16; bottom: parent.bottom; } + property real maxValue: 200; + property real perFrame: 10000; + property real k1: (5 / maxValue) * height; + property real k2: (10 / maxValue) * height; + property real k3: (100 / maxValue) * height; + + onPaint: { + var ctx = getContext("2d"); + if (values.length === 0) { + ctx.fillStyle = Qt.rgba(1, 0, 0, 1); + ctx.fillRect(0, 0, width, height); + return; + } + + + //ctx.setTransform(1, 0, 0, -1, 0, 0); + ctx.fillStyle = Qt.rgba(0, 0, 0, 1); + ctx.fillRect(0, 0, width, height); + + ctx.strokeStyle= "gray"; + ctx.lineWidth="1"; + ctx.beginPath(); + for (var i = 0; i < width; ++i) { + var value = vv(i, width); //values[Math.min(i, values.length - 1)]; + value /= 10000; + value /= maxValue; + ctx.moveTo(i, height); + ctx.lineTo(i, height - (height * value)); + } + ctx.stroke(); + + ctx.strokeStyle= "green"; + ctx.lineWidth="2"; + ctx.beginPath(); + var lineHeight = height - k1; + ctx.moveTo(0, lineHeight); + ctx.lineTo(width, lineHeight); + ctx.stroke(); + + ctx.strokeStyle= "yellow"; + ctx.lineWidth="2"; + ctx.beginPath(); + lineHeight = height - k2; + ctx.moveTo(0, lineHeight); + ctx.lineTo(width, lineHeight); + ctx.stroke(); + + ctx.strokeStyle= "red"; + ctx.lineWidth="2"; + ctx.beginPath(); + lineHeight = height - k3; + ctx.moveTo(0, lineHeight); + ctx.lineTo(width, lineHeight); + ctx.stroke(); + + } + } +} + + diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3a0b0998c5..f8bfd8f3d4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -147,6 +147,8 @@ #include "Util.h" #include "InterfaceParentFinder.h" +#include "FrameTimingsScriptingInterface.h" + // On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // FIXME seems to be broken. #if defined(Q_OS_WIN) @@ -1334,6 +1336,8 @@ void Application::initializeGL() { InfoView::show(INFO_HELP_PATH, true); } +FrameTimingsScriptingInterface _frameTimingsScriptingInterface; + extern void setupPreferences(); void Application::initializeUi() { @@ -1378,6 +1382,8 @@ void Application::initializeUi() { rootContext->setContextProperty("Messages", DependencyManager::get().data()); rootContext->setContextProperty("Recording", DependencyManager::get().data()); rootContext->setContextProperty("Preferences", DependencyManager::get().data()); + rootContext->setContextProperty("AddressManager", DependencyManager::get().data()); + rootContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface); rootContext->setContextProperty("TREE_SCALE", TREE_SCALE); rootContext->setContextProperty("Quat", new Quat()); @@ -1421,6 +1427,7 @@ void Application::initializeUi() { rootContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface()); rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); + _glWidget->installEventFilter(offscreenUi.data()); offscreenUi->setMouseTranslator([=](const QPointF& pt) { @@ -1463,9 +1470,9 @@ void Application::initializeUi() { }); } + void Application::paintGL() { updateHeartbeat(); - // Some plugins process message events, potentially leading to // re-entering a paint event. don't allow further processing if this // happens @@ -1483,6 +1490,7 @@ void Application::paintGL() { _frameCount++; _frameCounter.increment(); + auto lastPaintBegin = usecTimestampNow(); PROFILE_RANGE_EX(__FUNCTION__, 0xff0000ff, (uint64_t)_frameCount); PerformanceTimer perfTimer("paintGL"); @@ -1735,6 +1743,9 @@ void Application::paintGL() { batch.resetStages(); }); } + + uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; + _frameTimingsScriptingInterface.addValue(lastPaintDuration); } void Application::runTests() { diff --git a/interface/src/FrameTimingsScriptingInterface.cpp b/interface/src/FrameTimingsScriptingInterface.cpp new file mode 100644 index 0000000000..6c8c164804 --- /dev/null +++ b/interface/src/FrameTimingsScriptingInterface.cpp @@ -0,0 +1,53 @@ +// +// Created by Bradley Austin Davis on 2016/04/04 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "FrameTimingsScriptingInterface.h" + +#include + +void FrameTimingsScriptingInterface::start() { + _values.clear(); + DependencyManager::get()->setUnusedResourceCacheSize(0); + _values.reserve(8192); + _active = true; +} + +void FrameTimingsScriptingInterface::addValue(uint64_t value) { + if (_active) { + _values.push_back(value); + } +} + +void FrameTimingsScriptingInterface::finish() { + _active = false; + uint64_t total = 0; + _min = std::numeric_limits::max(); + _max = std::numeric_limits::lowest(); + size_t count = _values.size(); + for (auto i = 0; i < count; ++i) { + const uint64_t& value = _values[i]; + _max = std::max(_max, value); + _min = std::min(_min, value); + total += value; + } + _mean = (float)total / (float)count; + float deviationTotal = 0; + for (auto i = 0; i < count; ++i) { + float deviation = _values[i] - _mean; + deviationTotal += deviation*deviation; + } + _stdDev = sqrt(deviationTotal / (float)count); +} + +QVariantList FrameTimingsScriptingInterface::getValues() const { + QVariantList result; + for (const auto& v : _values) { + result << v; + } + return result; +} diff --git a/interface/src/FrameTimingsScriptingInterface.h b/interface/src/FrameTimingsScriptingInterface.h new file mode 100644 index 0000000000..73eb1aec67 --- /dev/null +++ b/interface/src/FrameTimingsScriptingInterface.h @@ -0,0 +1,38 @@ +// +// Created by Bradley Austin Davis on 2016/04/04 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once +#include +#include + +class FrameTimingsScriptingInterface : public QObject { + Q_OBJECT + Q_PROPERTY(float mean READ getMean CONSTANT) + Q_PROPERTY(float max READ getMax CONSTANT) + Q_PROPERTY(float min READ getMin CONSTANT) + Q_PROPERTY(float standardDeviation READ getStandardDeviation CONSTANT) +public: + Q_INVOKABLE void start(); + Q_INVOKABLE void addValue(uint64_t value); + Q_INVOKABLE void finish(); + Q_INVOKABLE QVariantList getValues() const; + + + uint64_t getMax() const { return _max; } + uint64_t getMin() const { return _min; } + float getStandardDeviation() const { return _stdDev; } + float getMean() const { return _mean; } + +protected: + std::vector _values; + bool _active { false }; + uint64_t _max { 0 }; + uint64_t _min { 0 }; + float _stdDev { 0 }; + float _mean { 0 }; +}; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 906f7b4c9f..4472abe6c3 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -204,6 +204,15 @@ MyAvatar::~MyAvatar() { _lookAtTargetAvatar.reset(); } +void MyAvatar::setOrientationVar(const QVariant& newOrientationVar) { + Avatar::setOrientation(quatFromVariant(newOrientationVar)); +} + +QVariant MyAvatar::getOrientationVar() const { + return quatToVariant(Avatar::getOrientation()); +} + + // virtual void MyAvatar::simulateAttachments(float deltaTime) { // don't update attachments here, do it in harvestResultsFromPhysicsSimulation() diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 92bf9e7614..b15f812197 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -105,6 +105,10 @@ public: // thread safe Q_INVOKABLE glm::mat4 getSensorToWorldMatrix() const; + Q_INVOKABLE void setOrientationVar(const QVariant& newOrientationVar); + Q_INVOKABLE QVariant getOrientationVar() const; + + // Pass a recent sample of the HMD to the avatar. // This can also update the avatar's position to follow the HMD // as it moves through the world. diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 097d7f73cd..0514411d7f 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -52,7 +52,8 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) : _target(gpuToGLTextureType(texture)), _size(0), _virtualSize(0), - _numLevels(texture.maxMip() + 1), + _numLevels(1), + //_numLevels(texture.maxMip() + 1), _gpuTexture(texture) { Backend::incrementTextureGPUCount(); @@ -254,7 +255,7 @@ void GLBackend::GLTexture::transfer() const { } if (_gpuTexture.isAutogenerateMips()) { - glGenerateMipmap(_target); + //glGenerateMipmap(_target); (void)CHECK_GL_ERROR(); } } @@ -435,7 +436,7 @@ void GLBackend::do_generateTextureMips(Batch& batch, size_t paramOffset) { glActiveTexture(GL_TEXTURE0 + bindingSlot); glBindTexture(object->_target, object->_texture); - glGenerateMipmap(object->_target); + //glGenerateMipmap(object->_target); if (freeSlot < 0) { // If had to use slot 0 then restore state From 75c99fe416e816f5155bfee9f30605df68fb0d58 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 15 Apr 2016 00:45:51 -0700 Subject: [PATCH 12/22] Working on GPU library test code --- tests/gpu-test/src/main.cpp | 474 +++++++++++++++++++++++------------- 1 file changed, 307 insertions(+), 167 deletions(-) diff --git a/tests/gpu-test/src/main.cpp b/tests/gpu-test/src/main.cpp index d1cd4389a7..1bb02b8101 100644 --- a/tests/gpu-test/src/main.cpp +++ b/tests/gpu-test/src/main.cpp @@ -38,9 +38,11 @@ #include #include +#include + #include #include -#include +#include #include "unlit_frag.h" #include "unlit_vert.h" @@ -83,6 +85,93 @@ public: uint32_t toCompactColor(const glm::vec4& color); + +const char* VERTEX_SHADER = R"SHADER( +#version 450 core + +layout(location = 0) in vec4 inPosition; +layout(location = 3) in vec2 inTexCoord0; + +struct TransformObject { + mat4 _model; + mat4 _modelInverse; +}; + +layout(location=15) in ivec2 _drawCallInfo; + +uniform samplerBuffer transformObjectBuffer; + +TransformObject getTransformObject() { + int offset = 8 * _drawCallInfo.x; + TransformObject object; + object._model[0] = texelFetch(transformObjectBuffer, offset); + object._model[1] = texelFetch(transformObjectBuffer, offset + 1); + object._model[2] = texelFetch(transformObjectBuffer, offset + 2); + object._model[3] = texelFetch(transformObjectBuffer, offset + 3); + + object._modelInverse[0] = texelFetch(transformObjectBuffer, offset + 4); + object._modelInverse[1] = texelFetch(transformObjectBuffer, offset + 5); + object._modelInverse[2] = texelFetch(transformObjectBuffer, offset + 6); + object._modelInverse[3] = texelFetch(transformObjectBuffer, offset + 7); + + return object; +} + +struct TransformCamera { + mat4 _view; + mat4 _viewInverse; + mat4 _projectionViewUntranslated; + mat4 _projection; + mat4 _projectionInverse; + vec4 _viewport; +}; + +layout(std140) uniform transformCameraBuffer { + TransformCamera _camera; +}; + +TransformCamera getTransformCamera() { + return _camera; +} + +// the interpolated normal +out vec2 _texCoord0; + +void main(void) { + _texCoord0 = inTexCoord0.st; + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + { // transformModelToClipPos + vec4 eyeWAPos; + { // _transformModelToEyeWorldAlignedPos + highp mat4 _mv = obj._model; + _mv[3].xyz -= cam._viewInverse[3].xyz; + highp vec4 _eyeWApos = (_mv * inPosition); + eyeWAPos = _eyeWApos; + } + gl_Position = cam._projectionViewUntranslated * eyeWAPos; + } + +})SHADER"; + +const char* FRAGMENT_SHADER = R"SHADER( +#version 450 core + +uniform sampler2D originalTexture; + +in vec2 _texCoord0; + +layout(location = 0) out vec4 _fragColor0; + +void main(void) { + //_fragColor0 = vec4(_texCoord0, 0.0, 1.0); + _fragColor0 = texture(originalTexture, _texCoord0); +} +)SHADER"; + + gpu::ShaderPointer makeShader(const std::string & vertexShaderSrc, const std::string & fragmentShaderSrc, const gpu::Shader::BindingSet & bindings) { auto vs = gpu::Shader::createVertex(vertexShaderSrc); auto fs = gpu::Shader::createPixel(fragmentShaderSrc); @@ -125,6 +214,7 @@ class QTestWindow : public QWindow { glm::mat4 _projectionMatrix; RateCounter fps; QTime _time; + glm::mat4 _camera; protected: void renderText(); @@ -145,7 +235,7 @@ public: setGLFormatVersion(format); format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); format.setOption(QSurfaceFormat::DebugContext); - format.setSwapInterval(0); + //format.setSwapInterval(0); setFormat(format); @@ -158,19 +248,22 @@ public: gpu::Context::init(); _context = std::make_shared(); - + makeCurrent(); auto shader = makeShader(unlit_vert, unlit_frag, gpu::Shader::BindingSet{}); auto state = std::make_shared(); state->setMultisampleEnable(true); state->setDepthTest(gpu::State::DepthTest { true }); _pipeline = gpu::Pipeline::create(shader, state); + + // Clear screen gpu::Batch batch; batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 1.0, 0.0, 0.5, 1.0 }); _context->render(batch); DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(); resize(QSize(800, 600)); @@ -181,182 +274,229 @@ public: virtual ~QTestWindow() { } + void updateCamera() { + float t = _time.elapsed() * 1e-4f; + glm::vec3 unitscale { 1.0f }; + glm::vec3 up { 0.0f, 1.0f, 0.0f }; + + float distance = 3.0f; + glm::vec3 camera_position { distance * sinf(t), 0.5f, distance * cosf(t) }; + + static const vec3 camera_focus(0); + static const vec3 camera_up(0, 1, 0); + _camera = glm::inverse(glm::lookAt(camera_position, camera_focus, up)); + } + + + void drawFloorGrid(gpu::Batch& batch) { + auto geometryCache = DependencyManager::get(); + // Render grid on xz plane (not the optimal way to do things, but w/e) + // Note: GeometryCache::renderGrid will *not* work, as it is apparenly unaffected by batch rotations and renders xy only + static const std::string GRID_INSTANCE = "Grid"; + static auto compactColor1 = toCompactColor(vec4 { 0.35f, 0.25f, 0.15f, 1.0f }); + static auto compactColor2 = toCompactColor(vec4 { 0.15f, 0.25f, 0.35f, 1.0f }); + static std::vector transforms; + static gpu::BufferPointer colorBuffer; + if (!transforms.empty()) { + transforms.reserve(200); + colorBuffer = std::make_shared(); + for (int i = 0; i < 100; ++i) { + { + glm::mat4 transform = glm::translate(mat4(), vec3(0, -1, -50 + i)); + transform = glm::scale(transform, vec3(100, 1, 1)); + transforms.push_back(transform); + colorBuffer->append(compactColor1); + } + + { + glm::mat4 transform = glm::mat4_cast(quat(vec3(0, PI / 2.0f, 0))); + transform = glm::translate(transform, vec3(0, -1, -50 + i)); + transform = glm::scale(transform, vec3(100, 1, 1)); + transforms.push_back(transform); + colorBuffer->append(compactColor2); + } + } + } + auto pipeline = geometryCache->getSimplePipeline(); + for (auto& transform : transforms) { + batch.setModelTransform(transform); + batch.setupNamedCalls(GRID_INSTANCE, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { + batch.setViewTransform(_camera); + batch.setPipeline(_pipeline); + geometryCache->renderWireShapeInstances(batch, GeometryCache::Line, data.count(), colorBuffer); + }); + } + } + + void drawSimpleShapes(gpu::Batch& batch) { + auto geometryCache = DependencyManager::get(); + static const size_t ITEM_COUNT = 1000; + static const float SHAPE_INTERVAL = (PI * 2.0f) / ITEM_COUNT; + static const float ITEM_INTERVAL = SHAPE_INTERVAL / TYPE_COUNT; + + static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; + static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; + static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA }; + + static std::vector transforms; + static std::vector colors; + static gpu::BufferPointer colorBuffer; + static gpu::BufferView colorView; + static gpu::BufferView instanceXfmView; + if (!colorBuffer) { + colorBuffer = std::make_shared(); + + static const float ITEM_RADIUS = 20; + static const vec3 ITEM_TRANSLATION { 0, 0, -ITEM_RADIUS }; + for (size_t i = 0; i < TYPE_COUNT; ++i) { + GeometryCache::Shape shape = SHAPE[i]; + GeometryCache::ShapeData shapeData = geometryCache->_shapes[shape]; + //indirectCommand._count + float startingInterval = ITEM_INTERVAL * i; + for (size_t j = 0; j < ITEM_COUNT; ++j) { + float theta = j * SHAPE_INTERVAL + startingInterval; + auto transform = glm::rotate(mat4(), theta, Vectors::UP); + transform = glm::rotate(transform, (randFloat() - 0.5f) * PI / 4.0f, Vectors::UNIT_X); + transform = glm::translate(transform, ITEM_TRANSLATION); + transform = glm::scale(transform, vec3(randFloat() / 2.0f + 0.5f)); + transforms.push_back(transform); + auto color = vec4 { randomColorValue(64), randomColorValue(64), randomColorValue(64), 255 }; + color /= 255.0f; + colors.push_back(color); + colorBuffer->append(toCompactColor(color)); + } + } + colorView = gpu::BufferView(colorBuffer, COLOR_ELEMENT); + } + + batch.setViewTransform(_camera); + batch.setPipeline(_pipeline); + batch.setInputFormat(getInstancedSolidStreamFormat()); + for (size_t i = 0; i < TYPE_COUNT; ++i) { + GeometryCache::Shape shape = SHAPE[i]; + GeometryCache::ShapeData shapeData = geometryCache->_shapes[shape]; + batch.setInputBuffer(gpu::Stream::COLOR, colorView); + for (size_t j = 0; j < ITEM_COUNT; ++j) { + batch.setModelTransform(transforms[j]); + shapeData.draw(batch); + } + } + } + + void drawCenterShape(gpu::Batch& batch) { + // Render unlit cube + sphere + static auto startUsecs = usecTimestampNow(); + float seconds = getSeconds(startUsecs); + seconds /= 4.0f; + batch.setModelTransform(Transform()); + batch._glColor4f(0.8f, 0.25f, 0.25f, 1.0f); + + bool wire = (seconds - floorf(seconds) > 0.5f); + auto geometryCache = DependencyManager::get(); + int shapeIndex = ((int)seconds) % TYPE_COUNT; + if (wire) { + geometryCache->renderWireShape(batch, SHAPE[shapeIndex]); + } else { + geometryCache->renderShape(batch, SHAPE[shapeIndex]); + } + + batch.setModelTransform(Transform().setScale(2.05f)); + batch._glColor4f(1, 1, 1, 1); + geometryCache->renderWireCube(batch); + } + + void drawTerrain(gpu::Batch& batch) { + auto geometryCache = DependencyManager::get(); + static std::once_flag once; + static gpu::BufferPointer vertexBuffer { std::make_shared() }; + static gpu::BufferPointer indexBuffer { std::make_shared() }; + + static gpu::BufferView positionView; + static gpu::BufferView textureView; + static gpu::Stream::FormatPointer vertexFormat { std::make_shared() }; + + static gpu::TexturePointer texture; + static gpu::PipelinePointer pipeline; + std::call_once(once, [&] { + static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec4) * 2; // position, normals, textures + static const uint SHAPE_TEXTURES_OFFSET = sizeof(glm::vec4); + static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; + static const gpu::Element TEXTURE_ELEMENT { gpu::VEC2, gpu::FLOAT, gpu::UV }; + static const gpu::Type SHAPE_INDEX_TYPE = gpu::UINT16; + static const uint SHAPE_INDEX_SIZE = sizeof(gpu::uint16); + std::vector vertices; + const int MINX = -1000; + const int MAXX = 1000; + // top + vertices.push_back(vec4(MAXX, 0, MAXX, 1)); + vertices.push_back(vec4(MAXX, MAXX, 0, 0)); + + vertices.push_back(vec4(MAXX, 0, MINX, 1)); + vertices.push_back(vec4(MAXX, 0, 0, 0)); + + vertices.push_back(vec4(MINX, 0, MINX, 1)); + vertices.push_back(vec4(0, 0, 0, 0)); + + vertices.push_back(vec4(MINX, 0, MAXX, 1)); + vertices.push_back(vec4(0, MAXX, 0, 0)); + + vertexBuffer->append(vertices); + indexBuffer->append(std::vector({ 0, 1, 2, 2, 3, 0 })); + + positionView = gpu::BufferView(vertexBuffer, 0, vertexBuffer->getSize(), SHAPE_VERTEX_STRIDE, POSITION_ELEMENT); + textureView = gpu::BufferView(vertexBuffer, SHAPE_TEXTURES_OFFSET, vertexBuffer->getSize(), SHAPE_VERTEX_STRIDE, TEXTURE_ELEMENT); + texture = DependencyManager::get()->getImageTexture("C:/Users/bdavis/Git/openvr/samples/bin/cube_texture.png"); + //texture = DependencyManager::get()->getImageTexture("H:/test.png"); + //texture = DependencyManager::get()->getImageTexture("H:/crate_blue.fbm/lambert8SG_Normal_OpenGL.png"); + + auto shader = makeShader(VERTEX_SHADER, FRAGMENT_SHADER, gpu::Shader::BindingSet {}); + auto state = std::make_shared(); + state->setMultisampleEnable(false); + state->setDepthTest(gpu::State::DepthTest { true }); + pipeline = gpu::Pipeline::create(shader, state); + vertexFormat->setAttribute(gpu::Stream::POSITION); + vertexFormat->setAttribute(gpu::Stream::TEXCOORD); + + }); + batch.setPipeline(pipeline); + batch.setInputBuffer(gpu::Stream::POSITION, positionView); + batch.setInputBuffer(gpu::Stream::TEXCOORD, textureView); + batch.setIndexBuffer(gpu::UINT16, indexBuffer, 0); + batch.setInputFormat(vertexFormat); + + batch.setResourceTexture(0, texture); + batch.setModelTransform(glm::translate(glm::mat4(), vec3(0, -0.1, 0))); + batch.drawIndexed(gpu::TRIANGLES, 6, 0); + + batch.setResourceTexture(0, DependencyManager::get()->getBlueTexture()); + batch.setModelTransform(glm::translate(glm::mat4(), vec3(0, -0.2, 0))); + batch.drawIndexed(gpu::TRIANGLES, 6, 0); + } + void draw() { // Attempting to draw before we're visible and have a valid size will // produce GL errors. if (!isVisible() || _size.width() <= 0 || _size.height() <= 0) { return; } + updateCamera(); makeCurrent(); gpu::Batch batch; - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 0.0f, 0.0f, 0.0f, 1.0f }); + batch.resetStages(); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 0.0f, 0.1f, 0.2f, 1.0f }); batch.clearDepthFramebuffer(1e4); batch.setViewportTransform({ 0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio() }); batch.setProjectionTransform(_projectionMatrix); - float t = _time.elapsed() * 1e-3f; - glm::vec3 unitscale { 1.0f }; - glm::vec3 up { 0.0f, 1.0f, 0.0f }; - - float distance = 3.0f; - glm::vec3 camera_position{ distance * sinf(t), 0.0f, distance * cosf(t) }; - - static const vec3 camera_focus(0); - static const vec3 camera_up(0, 1, 0); - glm::mat4 camera = glm::inverse(glm::lookAt(camera_position, camera_focus, up)); - batch.setViewTransform(camera); + batch.setViewTransform(_camera); batch.setPipeline(_pipeline); batch.setModelTransform(Transform()); - auto geometryCache = DependencyManager::get(); - - // Render grid on xz plane (not the optimal way to do things, but w/e) - // Note: GeometryCache::renderGrid will *not* work, as it is apparenly unaffected by batch rotations and renders xy only - { - static const std::string GRID_INSTANCE = "Grid"; - static auto compactColor1 = toCompactColor(vec4{ 0.35f, 0.25f, 0.15f, 1.0f }); - static auto compactColor2 = toCompactColor(vec4{ 0.15f, 0.25f, 0.35f, 1.0f }); - static std::vector transforms; - static gpu::BufferPointer colorBuffer; - if (!transforms.empty()) { - transforms.reserve(200); - colorBuffer = std::make_shared(); - for (int i = 0; i < 100; ++i) { - { - glm::mat4 transform = glm::translate(mat4(), vec3(0, -1, -50 + i)); - transform = glm::scale(transform, vec3(100, 1, 1)); - transforms.push_back(transform); - colorBuffer->append(compactColor1); - } - - { - glm::mat4 transform = glm::mat4_cast(quat(vec3(0, PI / 2.0f, 0))); - transform = glm::translate(transform, vec3(0, -1, -50 + i)); - transform = glm::scale(transform, vec3(100, 1, 1)); - transforms.push_back(transform); - colorBuffer->append(compactColor2); - } - } - } - - auto pipeline = geometryCache->getSimplePipeline(); - for (auto& transform : transforms) { - batch.setModelTransform(transform); - batch.setupNamedCalls(GRID_INSTANCE, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { - batch.setViewTransform(camera); - batch.setPipeline(_pipeline); - geometryCache->renderWireShapeInstances(batch, GeometryCache::Line, data.count(), colorBuffer); - }); - } - } - - { - static const size_t ITEM_COUNT = 1000; - static const float SHAPE_INTERVAL = (PI * 2.0f) / ITEM_COUNT; - static const float ITEM_INTERVAL = SHAPE_INTERVAL / TYPE_COUNT; - - static const gpu::Element POSITION_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ }; - static const gpu::Element NORMAL_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ }; - static const gpu::Element COLOR_ELEMENT{ gpu::VEC4, gpu::NUINT8, gpu::RGBA }; - static const gpu::Element TRANSFORM_ELEMENT{ gpu::MAT4, gpu::FLOAT, gpu::XYZW }; - - - static std::vector transforms; - static std::vector colors; - static gpu::BufferPointer indirectBuffer; - static gpu::BufferPointer transformBuffer; - static gpu::BufferPointer colorBuffer; - static gpu::BufferView colorView; - static gpu::BufferView instanceXfmView; - - if (!transformBuffer) { - transformBuffer = std::make_shared(); - colorBuffer = std::make_shared(); - indirectBuffer = std::make_shared(); - - static const float ITEM_RADIUS = 20; - static const vec3 ITEM_TRANSLATION{ 0, 0, -ITEM_RADIUS }; - for (size_t i = 0; i < TYPE_COUNT; ++i) { - GeometryCache::Shape shape = SHAPE[i]; - GeometryCache::ShapeData shapeData = geometryCache->_shapes[shape]; - { - gpu::Batch::DrawIndexedIndirectCommand indirectCommand; - indirectCommand._count = (uint)shapeData._indexCount; - indirectCommand._instanceCount = ITEM_COUNT; - indirectCommand._baseInstance = (uint)(i * ITEM_COUNT); - indirectCommand._firstIndex = (uint)shapeData._indexOffset / 2; - indirectCommand._baseVertex = 0; - indirectBuffer->append(indirectCommand); - } - - //indirectCommand._count - float startingInterval = ITEM_INTERVAL * i; - for (size_t j = 0; j < ITEM_COUNT; ++j) { - float theta = j * SHAPE_INTERVAL + startingInterval; - auto transform = glm::rotate(mat4(), theta, Vectors::UP); - transform = glm::rotate(transform, (randFloat() - 0.5f) * PI / 4.0f, Vectors::UNIT_X); - transform = glm::translate(transform, ITEM_TRANSLATION); - transform = glm::scale(transform, vec3(randFloat() / 2.0f + 0.5f)); - transformBuffer->append(transform); - transforms.push_back(transform); - auto color = vec4{ randomColorValue(64), randomColorValue(64), randomColorValue(64), 255 }; - color /= 255.0f; - colors.push_back(color); - colorBuffer->append(toCompactColor(color)); - } - } - colorView = gpu::BufferView(colorBuffer, COLOR_ELEMENT); - instanceXfmView = gpu::BufferView(transformBuffer, TRANSFORM_ELEMENT); - } - -#if 1 - GeometryCache::ShapeData shapeData = geometryCache->_shapes[GeometryCache::Icosahedron]; - { - batch.setViewTransform(camera); - batch.setModelTransform(Transform()); - batch.setPipeline(_pipeline); - batch.setInputFormat(getInstancedSolidStreamFormat()); - batch.setInputBuffer(gpu::Stream::COLOR, colorView); - batch.setIndirectBuffer(indirectBuffer); - shapeData.setupBatch(batch); - batch.multiDrawIndexedIndirect(TYPE_COUNT, gpu::TRIANGLES); - } -#else - batch.setViewTransform(camera); - batch.setPipeline(_pipeline); - for (size_t i = 0; i < TYPE_COUNT; ++i) { - GeometryCache::Shape shape = SHAPE[i]; - for (size_t j = 0; j < ITEM_COUNT; ++j) { - int index = i * ITEM_COUNT + j; - batch.setModelTransform(transforms[index]); - const vec4& color = colors[index]; - batch._glColor4f(color.r, color.g, color.b, 1.0); - geometryCache->renderShape(batch, shape); - } - } -#endif - } - - // Render unlit cube + sphere - static auto startUsecs = usecTimestampNow(); - float seconds = getSeconds(startUsecs); - - seconds /= 4.0f; - int shapeIndex = ((int)seconds) % TYPE_COUNT; - bool wire = (seconds - floorf(seconds) > 0.5f); - batch.setModelTransform(Transform()); - batch._glColor4f(0.8f, 0.25f, 0.25f, 1.0f); - - if (wire) { - geometryCache->renderWireShape(batch, SHAPE[shapeIndex]); - } else { - geometryCache->renderShape(batch, SHAPE[shapeIndex]); - } - - batch.setModelTransform(Transform().setScale(2.05f)); - batch._glColor4f(1, 1, 1, 1); - geometryCache->renderWireCube(batch); + //drawFloorGrid(batch); + //drawSimpleShapes(batch); + drawCenterShape(batch); + drawTerrain(batch); _context->render(batch); _qGlContext.swapBuffers(this); @@ -387,12 +527,12 @@ protected: int main(int argc, char** argv) { QGuiApplication app(argc, argv); QTestWindow window; - QTimer timer; - timer.setInterval(0); - app.connect(&timer, &QTimer::timeout, &app, [&] { + auto timer = new QTimer(&app); + timer->setInterval(0); + app.connect(timer, &QTimer::timeout, &app, [&] { window.draw(); }); - timer.start(); + timer->start(); app.exec(); return 0; } From c35d81260d70d1545be168be27226a24b384b553 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 15 Apr 2016 00:49:45 -0700 Subject: [PATCH 13/22] Load local texture files through the same code as network --- .../src/model-networking/TextureCache.cpp | 119 +++++++++--------- .../src/model-networking/TextureCache.h | 2 +- 2 files changed, 60 insertions(+), 61 deletions(-) diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index e482c20b11..0e93119fe3 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -154,21 +154,63 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type return ResourceCache::getResource(url, QUrl(), content.isEmpty(), &extra).staticCast(); } -/// Returns a texture version of an image file -gpu::TexturePointer TextureCache::getImageTexture(const QString& path) { - QImage image = QImage(path).mirrored(false, true); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); - if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::BGRA); + +TextureCache::TextureLoaderFunc getTextureLoaderForType(TextureType type) { + switch (type) { + case ALBEDO_TEXTURE: { + return model::TextureUsage::createAlbedoTextureFromImage; + break; + } + case EMISSIVE_TEXTURE: { + return model::TextureUsage::createEmissiveTextureFromImage; + break; + } + case LIGHTMAP_TEXTURE: { + return model::TextureUsage::createLightmapTextureFromImage; + break; + } + case CUBE_TEXTURE: { + return model::TextureUsage::createCubeTextureFromImage; + break; + } + case BUMP_TEXTURE: { + return model::TextureUsage::createNormalTextureFromBumpImage; + break; + } + case NORMAL_TEXTURE: { + return model::TextureUsage::createNormalTextureFromNormalImage; + break; + } + case ROUGHNESS_TEXTURE: { + return model::TextureUsage::createRoughnessTextureFromImage; + break; + } + case GLOSS_TEXTURE: { + return model::TextureUsage::createRoughnessTextureFromGlossImage; + break; + } + case SPECULAR_TEXTURE: { + return model::TextureUsage::createMetallicTextureFromImage; + break; + } + case CUSTOM_TEXTURE: { + Q_ASSERT(false); + return TextureCache::TextureLoaderFunc(); + break; + } + case DEFAULT_TEXTURE: + default: { + return model::TextureUsage::create2DTextureFromImage; + break; + } } - gpu::TexturePointer texture = gpu::TexturePointer( - gpu::Texture::create2D(formatGPU, image.width(), image.height(), - gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - texture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); - texture->autoGenerateMips(-1); - return texture; +} + +/// Returns a texture version of an image file +gpu::TexturePointer TextureCache::getImageTexture(const QString& path, TextureType type) { + QImage image = QImage(path); + auto loader = getTextureLoaderForType(type); + return gpu::TexturePointer(loader(image, QUrl::fromLocalFile(path).fileName().toStdString())); } QSharedPointer TextureCache::createResource(const QUrl& url, @@ -203,53 +245,10 @@ NetworkTexture::NetworkTexture(const QUrl& url, const TextureLoaderFunc& texture } NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const { - switch (_type) { - case ALBEDO_TEXTURE: { - return TextureLoaderFunc(model::TextureUsage::createAlbedoTextureFromImage); - break; - } - case EMISSIVE_TEXTURE: { - return TextureLoaderFunc(model::TextureUsage::createEmissiveTextureFromImage); - break; - } - case LIGHTMAP_TEXTURE: { - return TextureLoaderFunc(model::TextureUsage::createLightmapTextureFromImage); - break; - } - case CUBE_TEXTURE: { - return TextureLoaderFunc(model::TextureUsage::createCubeTextureFromImage); - break; - } - case BUMP_TEXTURE: { - return TextureLoaderFunc(model::TextureUsage::createNormalTextureFromBumpImage); - break; - } - case NORMAL_TEXTURE: { - return TextureLoaderFunc(model::TextureUsage::createNormalTextureFromNormalImage); - break; - } - case ROUGHNESS_TEXTURE: { - return TextureLoaderFunc(model::TextureUsage::createRoughnessTextureFromImage); - break; - } - case GLOSS_TEXTURE: { - return TextureLoaderFunc(model::TextureUsage::createRoughnessTextureFromGlossImage); - break; - } - case SPECULAR_TEXTURE: { - return TextureLoaderFunc(model::TextureUsage::createMetallicTextureFromImage); - break; - } - case CUSTOM_TEXTURE: { - return _textureLoader; - break; - } - case DEFAULT_TEXTURE: - default: { - return TextureLoaderFunc(model::TextureUsage::create2DTextureFromImage); - break; - } + if (_type == CUSTOM_TEXTURE) { + return _textureLoader; } + return getTextureLoaderForType(_type); } diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 4fe9a89460..a392117958 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -72,7 +72,7 @@ public: const gpu::TexturePointer& getNormalFittingTexture(); /// Returns a texture version of an image file - static gpu::TexturePointer getImageTexture(const QString& path); + static gpu::TexturePointer getImageTexture(const QString& path, TextureType type = DEFAULT_TEXTURE); /// Loads a texture from the specified URL. NetworkTexturePointer getTexture(const QUrl& url, TextureType type = DEFAULT_TEXTURE, From ac3d6c77b9e2574d2d4265a4ba2a60351dc75166 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 15 Apr 2016 00:50:28 -0700 Subject: [PATCH 14/22] Add default parameter to mip loaded notifications --- libraries/gpu/src/gpu/Texture.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 9dde359596..49885f4f19 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -430,7 +430,7 @@ public: Stamp getSamplerStamp() const { return _samplerStamp; } // Only callable by the Backend - void notifyMipFaceGPULoaded(uint16 level, uint8 face) const { return _storage->notifyMipFaceGPULoaded(level, face); } + void notifyMipFaceGPULoaded(uint16 level, uint8 face = 0) const { return _storage->notifyMipFaceGPULoaded(level, face); } const GPUObjectPointer gpuObject {}; From 0d3bf366c1f8675976f945ef467a7ea23d1a5c23 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 15 Apr 2016 01:02:28 -0700 Subject: [PATCH 15/22] Support loading multiple mips in texture transfer --- libraries/gpu/src/gpu/GLBackend.h | 2 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 73 +++++++++++++--------- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index aabd84fbfb..9806c17db4 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -139,7 +139,7 @@ public: GLuint _virtualSize; // theorical size as expected GLuint _numLevels{ 0 }; - void transferMip(GLenum target, const Texture::PixelsPointer& mip) const; + void transferMip(uint16_t mipLevel, uint8_t face = 0) const; // The owning texture const Texture& _gpuTexture; diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 0514411d7f..dfb854143b 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -52,8 +52,7 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) : _target(gpuToGLTextureType(texture)), _size(0), _virtualSize(0), - _numLevels(1), - //_numLevels(texture.maxMip() + 1), + _numLevels(texture.maxMip() + 1), _gpuTexture(texture) { Backend::incrementTextureGPUCount(); @@ -94,25 +93,22 @@ void GLBackend::GLTexture::createTexture() { (void)CHECK_GL_ERROR(); // Fixme: this usage of TexStorage doesn;t work wtih compressed texture, altuogh it should. // GO through the process of allocating the correct storage - /* if (GLEW_VERSION_4_2 && !texture.getTexelFormat().isCompressed()) { - glTexStorage2D(_target, _numLevels, texelFormat.internalFormat, width, height); - (void)CHECK_GL_ERROR(); - } else*/ - { + if (GLEW_VERSION_4_2 && !_gpuTexture.getTexelFormat().isCompressed()) { + glTexStorage2D(_target, _numLevels, texelFormat.internalFormat, width, height); + (void)CHECK_GL_ERROR(); + } else { glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(_target, GL_TEXTURE_MAX_LEVEL, _numLevels - 1); - - // for (int l = 0; l < _numLevels; l++) { - { int l = 0; - if (_gpuTexture.getType() == gpu::Texture::TEX_CUBE) { - for (size_t face = 0; face < CUBE_NUM_FACES; face++) { - glTexImage2D(CUBE_FACE_LAYOUT[face], l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); + for (uint16_t l = 0; l < _numLevels; l++) { + if (_gpuTexture.getType() == gpu::Texture::TEX_CUBE) { + for (size_t face = 0; face < CUBE_NUM_FACES; face++) { + glTexImage2D(CUBE_FACE_LAYOUT[face], l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); + } + } else { + glTexImage2D(_target, l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); } - } else { - glTexImage2D(_target, l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); - } - width = std::max(1, (width / 2)); - height = std::max(1, (height / 2)); + width = std::max(1, (width / 2)); + height = std::max(1, (height / 2)); } (void)CHECK_GL_ERROR(); } @@ -214,9 +210,13 @@ bool GLBackend::GLTexture::isReady() const { } // Move content bits from the CPU to the GPU for a given mip / face -void GLBackend::GLTexture::transferMip(GLenum target, const Texture::PixelsPointer& mip) const { +void GLBackend::GLTexture::transferMip(uint16_t mipLevel, uint8_t face) const { + auto mip = _gpuTexture.accessStoredMipFace(mipLevel, face); GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuTexture.getTexelFormat(), mip->getFormat()); - glTexSubImage2D(target, 0, 0, 0, _gpuTexture.getWidth(), _gpuTexture.getHeight(), texelFormat.format, texelFormat.type, mip->readData()); + GLenum target = _target == GL_TEXTURE_2D ? GL_TEXTURE_2D : CUBE_FACE_LAYOUT[face]; + uvec2 size = uvec2(_gpuTexture.getWidth(), _gpuTexture.getHeight()); + size >>= mipLevel; + glTexSubImage2D(target, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData()); (void)CHECK_GL_ERROR(); } @@ -235,16 +235,20 @@ void GLBackend::GLTexture::transfer() const { // GO through the process of allocating the correct storage and/or update the content switch (_gpuTexture.getType()) { case Texture::TEX_2D: - if (_gpuTexture.isStoredMipFaceAvailable(0)) { - transferMip(GL_TEXTURE_2D, _gpuTexture.accessStoredMipFace(0)); + for (uint16_t i = 0; i < Sampler::MAX_MIP_LEVEL; ++i) { + if (_gpuTexture.isStoredMipFaceAvailable(i)) { + transferMip(i); + } } break; case Texture::TEX_CUBE: // transfer pixels from each faces for (uint8_t f = 0; f < CUBE_NUM_FACES; f++) { - if (_gpuTexture.isStoredMipFaceAvailable(0, f)) { - transferMip(CUBE_FACE_LAYOUT[f], _gpuTexture.accessStoredMipFace(0, f)); + for (uint16_t i = 0; i < Sampler::MAX_MIP_LEVEL; ++i) { + if (_gpuTexture.isStoredMipFaceAvailable(i, f)) { + transferMip(i, f); + } } } break; @@ -255,7 +259,7 @@ void GLBackend::GLTexture::transfer() const { } if (_gpuTexture.isAutogenerateMips()) { - //glGenerateMipmap(_target); + glGenerateMipmap(_target); (void)CHECK_GL_ERROR(); } } @@ -270,12 +274,21 @@ void GLBackend::GLTexture::postTransfer() { // At this point the mip pixels have been loaded, we can notify the gpu texture to abandon it's memory switch (_gpuTexture.getType()) { case Texture::TEX_2D: - _gpuTexture.notifyMipFaceGPULoaded(0, 0); + for (uint16_t i = 0; i < Sampler::MAX_MIP_LEVEL; ++i) { + if (_gpuTexture.isStoredMipFaceAvailable(i)) { + _gpuTexture.notifyMipFaceGPULoaded(i); + } + } break; case Texture::TEX_CUBE: - for (uint8_t f = 0; f < CUBE_NUM_FACES; ++f) { - _gpuTexture.notifyMipFaceGPULoaded(0, f); + // transfer pixels from each faces + for (uint8_t f = 0; f < CUBE_NUM_FACES; f++) { + for (uint16_t i = 0; i < Sampler::MAX_MIP_LEVEL; ++i) { + if (_gpuTexture.isStoredMipFaceAvailable(i, f)) { + _gpuTexture.notifyMipFaceGPULoaded(i, f); + } + } } break; @@ -346,7 +359,7 @@ GLuint GLBackend::getTextureID(const TexturePointer& texture, bool sync) { } else { object = Backend::getGPUObject(*texture); } - if (object) { + if (object && object->getSyncState() == GLTexture::Idle) { return object->_texture; } else { return 0; @@ -436,7 +449,7 @@ void GLBackend::do_generateTextureMips(Batch& batch, size_t paramOffset) { glActiveTexture(GL_TEXTURE0 + bindingSlot); glBindTexture(object->_target, object->_texture); - //glGenerateMipmap(object->_target); + glGenerateMipmap(object->_target); if (freeSlot < 0) { // If had to use slot 0 then restore state From 3a969eed476916a4ccd37bc4e81d0a9932801f2b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 15 Apr 2016 01:03:22 -0700 Subject: [PATCH 16/22] Manually generate image mip levels when loading textures --- libraries/model/src/model/TextureMap.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 1ef8d57945..7200793bed 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -150,8 +150,8 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag QImage image = process2DImageColor(srcImage, validAlpha, alphaAsMask); gpu::Texture* theTexture = nullptr; - if ((image.width() > 0) && (image.height() > 0)) { + if ((image.width() > 0) && (image.height() > 0)) { gpu::Element formatGPU; gpu::Element formatMip; defineColorTexelFormats(formatGPU, formatMip, image, isLinear, doCompress); @@ -171,6 +171,14 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag if (generateMips) { theTexture->autoGenerateMips(-1); + auto levels = theTexture->maxMip(); + uvec2 size(image.width(), image.height()); + for (uint8_t i = 1; i <= levels; ++i) { + size >>= 1; + size = glm::max(size, uvec2(1)); + image = image.scaled(size.x, size.y, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + theTexture->assignStoredMip(i, formatMip, image.byteCount(), image.constBits()); + } } } @@ -291,7 +299,6 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); theTexture->autoGenerateMips(-1); From b50f835d3515508af57927e2fe037a30d180e7ef Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 15 Apr 2016 01:43:09 -0700 Subject: [PATCH 17/22] Warning and error fixes --- interface/src/FrameTimingsScriptingInterface.cpp | 8 ++++---- libraries/gl/src/gl/OglplusHelpers.cpp | 2 +- tests/gpu-test/src/main.cpp | 4 +--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/interface/src/FrameTimingsScriptingInterface.cpp b/interface/src/FrameTimingsScriptingInterface.cpp index 6c8c164804..59b653105c 100644 --- a/interface/src/FrameTimingsScriptingInterface.cpp +++ b/interface/src/FrameTimingsScriptingInterface.cpp @@ -29,7 +29,7 @@ void FrameTimingsScriptingInterface::finish() { _min = std::numeric_limits::max(); _max = std::numeric_limits::lowest(); size_t count = _values.size(); - for (auto i = 0; i < count; ++i) { + for (size_t i = 0; i < count; ++i) { const uint64_t& value = _values[i]; _max = std::max(_max, value); _min = std::min(_min, value); @@ -37,7 +37,7 @@ void FrameTimingsScriptingInterface::finish() { } _mean = (float)total / (float)count; float deviationTotal = 0; - for (auto i = 0; i < count; ++i) { + for (size_t i = 0; i < count; ++i) { float deviation = _values[i] - _mean; deviationTotal += deviation*deviation; } @@ -46,8 +46,8 @@ void FrameTimingsScriptingInterface::finish() { QVariantList FrameTimingsScriptingInterface::getValues() const { QVariantList result; - for (const auto& v : _values) { - result << v; + for (quint64 v : _values) { + result << QVariant(v); } return result; } diff --git a/libraries/gl/src/gl/OglplusHelpers.cpp b/libraries/gl/src/gl/OglplusHelpers.cpp index 11c4f2fe3d..220ea86646 100644 --- a/libraries/gl/src/gl/OglplusHelpers.cpp +++ b/libraries/gl/src/gl/OglplusHelpers.cpp @@ -126,7 +126,7 @@ ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect) { } ShapeWrapperPtr loadSkybox(ProgramPtr program) { - return ShapeWrapperPtr(new shapes::ShapeWrapper({ { "Position" } }, shapes::SkyBox(), *program)); + return ShapeWrapperPtr(new shapes::ShapeWrapper(std::initializer_list{ "Position" }, shapes::SkyBox(), *program)); } // Return a point's cartesian coordinates on a sphere from pitch and yaw diff --git a/tests/gpu-test/src/main.cpp b/tests/gpu-test/src/main.cpp index 1bb02b8101..47852104a2 100644 --- a/tests/gpu-test/src/main.cpp +++ b/tests/gpu-test/src/main.cpp @@ -422,11 +422,10 @@ public: static const uint SHAPE_TEXTURES_OFFSET = sizeof(glm::vec4); static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; static const gpu::Element TEXTURE_ELEMENT { gpu::VEC2, gpu::FLOAT, gpu::UV }; - static const gpu::Type SHAPE_INDEX_TYPE = gpu::UINT16; - static const uint SHAPE_INDEX_SIZE = sizeof(gpu::uint16); std::vector vertices; const int MINX = -1000; const int MAXX = 1000; + // top vertices.push_back(vec4(MAXX, 0, MAXX, 1)); vertices.push_back(vec4(MAXX, MAXX, 0, 0)); @@ -456,7 +455,6 @@ public: pipeline = gpu::Pipeline::create(shader, state); vertexFormat->setAttribute(gpu::Stream::POSITION); vertexFormat->setAttribute(gpu::Stream::TEXCOORD); - }); batch.setPipeline(pipeline); batch.setInputBuffer(gpu::Stream::POSITION, positionView); From c9fa91936a96d3999186e2850599034a24b49814 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 18 Apr 2016 13:46:45 -0700 Subject: [PATCH 18/22] Cleanup disk cache io device --- libraries/networking/src/AssetUtils.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/AssetUtils.cpp b/libraries/networking/src/AssetUtils.cpp index e25f357fcc..c505d108e5 100644 --- a/libraries/networking/src/AssetUtils.cpp +++ b/libraries/networking/src/AssetUtils.cpp @@ -11,6 +11,8 @@ #include "AssetUtils.h" +#include + #include #include @@ -29,12 +31,15 @@ QByteArray hashData(const QByteArray& data) { QByteArray loadFromCache(const QUrl& url) { if (auto cache = NetworkAccessManager::getInstance().cache()) { - if (auto ioDevice = cache->data(url)) { + + // caller is responsible for the deletion of the ioDevice, hence the unique_ptr + if (auto ioDevice = std::unique_ptr(cache->data(url))) { qCDebug(asset_client) << url.toDisplayString() << "loaded from disk cache."; return ioDevice->readAll(); } else { qCDebug(asset_client) << url.toDisplayString() << "not in disk cache"; } + } else { qCWarning(asset_client) << "No disk cache to load assets from."; } @@ -49,7 +54,8 @@ bool saveToCache(const QUrl& url, const QByteArray& file) { metaData.setSaveToDisk(true); metaData.setLastModified(QDateTime::currentDateTime()); metaData.setExpirationDate(QDateTime()); // Never expires - + + // ioDevice is managed by the cache and should either be passed back to insert or remove! if (auto ioDevice = cache->prepare(metaData)) { ioDevice->write(file); cache->insert(ioDevice); From 790e3252488f9e65c9cf2e1cefe8c98765a0fa20 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 18 Apr 2016 14:31:16 -0700 Subject: [PATCH 19/22] Clear entities and avatars on exit --- interface/src/Application.cpp | 5 ++++- interface/src/avatar/AvatarManager.cpp | 11 +++++++++++ interface/src/avatar/AvatarManager.h | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dbb30a4582..5120bf13e9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1233,6 +1233,9 @@ void Application::cleanupBeforeQuit() { } Application::~Application() { + _entityClipboard->eraseAllOctreeElements(); + _entityClipboard.reset(); + EntityTreePointer tree = getEntities()->getTree(); tree->setSimulation(nullptr); @@ -1242,7 +1245,7 @@ Application::~Application() { _physicsEngine->setCharacterController(nullptr); // remove avatars from physics engine - DependencyManager::get()->clearOtherAvatars(); + DependencyManager::get()->clearAllAvatars(); VectorOfMotionStates motionStates; DependencyManager::get()->getObjectsToRemoveFromPhysics(motionStates); _physicsEngine->removeObjects(motionStates); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 9f3a0eb254..c1bf3b7f0b 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -250,6 +250,17 @@ void AvatarManager::clearOtherAvatars() { _myAvatar->clearLookAtTargetAvatar(); } +void AvatarManager::clearAllAvatars() { + clearOtherAvatars(); + + QWriteLocker (locker&_hashLock); + + _myAvatar->die(); + _myAvatar.reset(); + + _avatarHash.clear(); +} + void AvatarManager::setLocalLights(const QVector& localLights) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "setLocalLights", Q_ARG(const QVector&, localLights)); diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 57fc1022ea..576a17f080 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -45,6 +45,7 @@ public: void updateOtherAvatars(float deltaTime); void clearOtherAvatars(); + void clearAllAvatar(); bool shouldShowReceiveStats() const { return _shouldShowReceiveStats; } From c87eec41823415750fc495df0e35865a2326ac4d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 18 Apr 2016 14:45:33 -0700 Subject: [PATCH 20/22] Fix typo in AvatarManager::clearAllAvatars --- interface/src/avatar/AvatarManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 576a17f080..bedd089c93 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -45,7 +45,7 @@ public: void updateOtherAvatars(float deltaTime); void clearOtherAvatars(); - void clearAllAvatar(); + void clearAllAvatars(); bool shouldShowReceiveStats() const { return _shouldShowReceiveStats; } From c9dc642d76f00e04c42fe292abf816f62ae7e488 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 18 Apr 2016 14:48:24 -0700 Subject: [PATCH 21/22] Fix type in AvatarManager::clearAllAvatars --- interface/src/avatar/AvatarManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index c1bf3b7f0b..b8f121bcd9 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -253,7 +253,7 @@ void AvatarManager::clearOtherAvatars() { void AvatarManager::clearAllAvatars() { clearOtherAvatars(); - QWriteLocker (locker&_hashLock); + QWriteLocker locker(&_hashLock); _myAvatar->die(); _myAvatar.reset(); From 146ea066db1b31b6e95704a55bbbb830d16e01a3 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 18 Apr 2016 14:53:04 -0700 Subject: [PATCH 22/22] Update AvatarManager.cpp --- interface/src/avatar/AvatarManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index b8f121bcd9..efd1bede47 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -77,7 +77,6 @@ AvatarManager::AvatarManager(QObject* parent) : } AvatarManager::~AvatarManager() { - _myAvatar->die(); } void AvatarManager::init() {