diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index c73e8e1d34..7750c0a105 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -13,7 +13,7 @@ setup_memory_debugger() link_hifi_libraries( audio avatars octree gpu graphics fbx entities networking animation recording shared script-engine embedded-webserver - controllers physics plugins midi image + controllers physics plugins midi image workload ) add_dependencies(${TARGET_NAME} oven) diff --git a/libraries/avatars-renderer/CMakeLists.txt b/libraries/avatars-renderer/CMakeLists.txt index 40e1607b2a..d3d61ea3fa 100644 --- a/libraries/avatars-renderer/CMakeLists.txt +++ b/libraries/avatars-renderer/CMakeLists.txt @@ -14,5 +14,6 @@ include_hifi_library_headers(audio) include_hifi_library_headers(entities) include_hifi_library_headers(octree) include_hifi_library_headers(task) +include_hifi_library_headers(workload) target_bullet() diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 0f33a73e40..92f78e357e 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -14,6 +14,7 @@ include_hifi_library_headers(entities) include_hifi_library_headers(avatars) include_hifi_library_headers(controllers) include_hifi_library_headers(task) +include_hifi_library_headers(workload) target_bullet() target_polyvox() diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index d6d9058e44..3d43330ebc 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") -link_hifi_libraries(shared networking octree avatars graphics) +link_hifi_libraries(shared workload networking octree avatars graphics) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ed13a46414..503f55e072 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2365,12 +2365,14 @@ QList EntityItem::getActionsOfType(EntityDynamicType typeT void EntityItem::locationChanged(bool tellPhysics) { requiresRecalcBoxes(); - if (tellPhysics) { - _flags |= Simulation::DIRTY_TRANSFORM; - EntityTreePointer tree = getTree(); - if (tree) { + EntityTreePointer tree = getTree(); + if (tree) { + if (tellPhysics) { + _flags |= Simulation::DIRTY_TRANSFORM; tree->entityChanged(getThisPointer()); } + glm::vec4 sphere(getWorldPosition(), 0.5f * glm::length(getScaledDimensions())); + tree->queueUpdateSpaceProxy(_spaceIndex, sphere); } SpatiallyNestable::locationChanged(tellPhysics); // tell all the children, also somethingChangedNotification(); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5f84bcc311..97ba8b493f 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -477,6 +477,8 @@ public: void setCauterized(bool value) { _cauterized = value; } bool getCauterized() const { return _cauterized; } + void setSpaceIndex(int32_t index) { assert(_spaceIndex == -1); _spaceIndex = index; } + int32_t getSpaceIndex() const { return _spaceIndex; } signals: void requestRenderUpdate(); @@ -630,6 +632,7 @@ protected: quint64 _lastUpdatedAccelerationTimestamp { 0 }; quint64 _lastUpdatedQueryAACubeTimestamp { 0 }; + int32_t _spaceIndex { -1 }; // index to proxy in workload::Space bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera }; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 60bcc85575..5854357661 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -560,37 +560,49 @@ void EntityTree::setSimulation(EntitySimulationPointer simulation) { } void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ignoreWarnings) { - EntityTreeElementPointer containingElement = getContainingElement(entityID); - if (!containingElement) { + EntityItemPointer entity; + { + QReadLocker locker(&_entityMapLock); + entity = _entityMap.value(entityID); + } + if (!entity) { if (!ignoreWarnings) { - qCWarning(entities) << "EntityTree::deleteEntity() on non-existent entityID=" << entityID; + qCWarning(entities) << "EntityTree::deleteEntity() on unknown entityID=" << entityID; } return; } - - EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID); - if (!existingEntity) { - if (!ignoreWarnings) { - qCWarning(entities) << "EntityTree::deleteEntity() on non-existant entity item with entityID=" << entityID; - } - return; - } - - if (existingEntity->getLocked() && !force) { + if (entity->getLocked() && !force) { if (!ignoreWarnings) { qCDebug(entities) << "ERROR! EntityTree::deleteEntity() trying to delete locked entity. entityID=" << entityID; } return; } + if (!ignoreWarnings) { + if (!entity->getElement()) { + qCWarning(entities) << "EntityTree::deleteEntity() found entity with entityID=" << entityID + << " in map but it doesn't know its containing element"; + } else { + // check for element mismatch + EntityItemPointer otherEntity = entity->getElement()->getEntityWithEntityItemID(entityID); + if (!otherEntity) { + qCWarning(entities) << "EntityTree::deleteEntity() on entity with entityID=" << entityID + << " but the containing element of record cannot find it"; + } else if (otherEntity != entity) { + qCWarning(entities) << "EntityTree::deleteEntity() on entity with entityID=" << entityID + << " but the containing element of record found a different entity"; + } + } + } + unhookChildAvatar(entityID); emit deletingEntity(entityID); - emit deletingEntityPointer(existingEntity.get()); + emit deletingEntityPointer(entity.get()); // NOTE: callers must lock the tree before using this method DeleteEntityOperator theOperator(getThisPointer(), entityID); - existingEntity->forEachDescendant([&](SpatiallyNestablePointer descendant) { + entity->forEachDescendant([&](SpatiallyNestablePointer descendant) { auto descendantID = descendant->getID(); theOperator.addEntityIDToDeleteList(descendantID); emit deletingEntity(descendantID); @@ -620,34 +632,46 @@ void EntityTree::deleteEntities(QSet entityIDs, bool force, bool i // NOTE: callers must lock the tree before using this method DeleteEntityOperator theOperator(getThisPointer()); foreach(const EntityItemID& entityID, entityIDs) { - EntityTreeElementPointer containingElement = getContainingElement(entityID); - if (!containingElement) { + EntityItemPointer entity; + { + QReadLocker locker(&_entityMapLock); + entity = _entityMap.value(entityID); + } + if (!entity) { if (!ignoreWarnings) { - qCWarning(entities) << "EntityTree::deleteEntities() on non-existent entityID=" << entityID; + qCWarning(entities) << "EntityTree::deleteEntities() on unknown entityID=" << entityID; } continue; } - - EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID); - if (!existingEntity) { - if (!ignoreWarnings) { - qCWarning(entities) << "EntityTree::deleteEntities() on non-existent entity item with entityID=" << entityID; - } - continue; - } - - if (existingEntity->getLocked() && !force) { + if (entity->getLocked() && !force) { if (!ignoreWarnings) { qCDebug(entities) << "ERROR! EntityTree::deleteEntities() trying to delete locked entity. entityID=" << entityID; } continue; } + if (!ignoreWarnings) { + if (!entity->getElement()) { + qCWarning(entities) << "EntityTree::deleteEntities() found entity with entityID=" << entityID + << " in map but it doesn't know its containing element"; + } else { + // check for element mismatch + EntityItemPointer otherEntity = entity->getElement()->getEntityWithEntityItemID(entityID); + if (!otherEntity) { + qCWarning(entities) << "EntityTree::deleteEntities() on entity with entityID=" << entityID + << " but the containing element of record cannot find it"; + } else if (otherEntity != entity) { + qCWarning(entities) << "EntityTree::deleteEntities() on entity with entityID=" << entityID + << " but the containing element of record found a different entity"; + } + } + } + // tell our delete operator about this entityID unhookChildAvatar(entityID); theOperator.addEntityIDToDeleteList(entityID); emit deletingEntity(entityID); - emit deletingEntityPointer(existingEntity.get()); + emit deletingEntityPointer(entity.get()); } if (theOperator.getEntities().size() > 0) { @@ -1209,6 +1233,10 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, Entity return verificationSuccess; } +void EntityTree::queueUpdateSpaceProxy(int32_t index, const glm::vec4& sphere) { + _spaceUpdates.push_back(std::pair(index, sphere)); +} + void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { int certIDByteArraySize; int textByteArraySize; @@ -1810,6 +1838,12 @@ void EntityTree::update(bool simulate) { } }); } + + // process Space queues + _space.deleteProxies(_spaceDeletes); + _spaceDeletes.clear(); + _space.updateProxies(_spaceUpdates); + _spaceUpdates.clear(); } quint64 EntityTree::getAdjustedConsiderSince(quint64 sinceTime) { @@ -1979,11 +2013,25 @@ void EntityTree::addEntityMapEntry(EntityItemPointer entity) { return; } _entityMap.insert(id, entity); + + // create a proxy for the entity in the workload/Space container + glm::vec4 sphere(entity->getWorldPosition(), 0.5f * glm::length(entity->getScaledDimensions())); + int32_t spaceIndex = _space.createProxy(sphere); + entity->setSpaceIndex(spaceIndex); } void EntityTree::clearEntityMapEntry(const EntityItemID& id) { + // this method only called by DeleteEntityOperator QWriteLocker locker(&_entityMapLock); - _entityMap.remove(id); + QHash::iterator itr = _entityMap.find(id); + if (itr != _entityMap.end()) { + // queue delete from _space BEFORE removing from map + int32_t spaceIndex = itr.value()->getSpaceIndex(); + assert(spaceIndex != -1); + _spaceDeletes.push_back(spaceIndex); + + _entityMap.erase(itr); + } } void EntityTree::debugDumpMap() { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 90fe342f57..c2d0b229b6 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -17,6 +17,7 @@ #include #include +#include class EntityTree; using EntityTreePointer = std::shared_ptr; @@ -280,6 +281,8 @@ public: void setMyAvatar(std::shared_ptr myAvatar) { _myAvatar = myAvatar; } + void queueUpdateSpaceProxy(int32_t index, const glm::vec4& sphere); + signals: void deletingEntity(const EntityItemID& entityID); void deletingEntityPointer(EntityItem* entityID); @@ -387,6 +390,9 @@ private: void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); std::shared_ptr _myAvatar{ nullptr }; + workload::Space _space; + std::vector< std::pair > _spaceUpdates; + std::vector< int32_t > _spaceDeletes; }; #endif // hifi_EntityTree_h diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index ad082c1a6e..c9df2dfc77 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -7,5 +7,6 @@ include_hifi_library_headers(avatars) include_hifi_library_headers(audio) include_hifi_library_headers(octree) include_hifi_library_headers(animation) +include_hifi_library_headers(workload) target_bullet() diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 31436bbf8b..6ef8438bf5 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -20,3 +20,4 @@ endif () link_hifi_libraries(shared networking octree gpu procedural graphics model-networking ktx recording avatars fbx entities controllers animation audio physics image midi) # ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit include_hifi_library_headers(gl) +include_hifi_library_headers(workload) diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 0e3c15b965..77264a017c 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -27,6 +27,7 @@ #include "VrMenu.h" #include "ui/Logging.h" +#include // adebug #include @@ -619,7 +620,13 @@ class KeyboardFocusHack : public QObject { public: KeyboardFocusHack() { Q_ASSERT(_mainWindow); + std::cout << "adebug _mainWindow = " << (void*)(_mainWindow) << std::endl; // adebug QTimer::singleShot(200, [=] { + _mainWindow = findMainWindow(); + std::cout << "adebug again _mainWindow = " << (void*)(_mainWindow) << std::endl; // adebug + std::cout << "adebug _mainWindow->x() = " << _mainWindow->x() << std::endl; + std::cout << " adebug _mainWindow->y() = " << _mainWindow->y() << std::endl; + std::cout << std::endl; // adebug _hackWindow = new QWindow(); _hackWindow->setFlags(Qt::FramelessWindowHint); _hackWindow->setGeometry(_mainWindow->x(), _mainWindow->y(), 10, 10); @@ -647,10 +654,11 @@ private: break; } } + std::cout << "adebug findMainWindow() result = " << (void*)(result) << std::endl; // adebug return result; } - QWindow* const _mainWindow { findMainWindow() }; + QWindow* _mainWindow { findMainWindow() }; QWindow* _hackWindow { nullptr }; }; diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 1e2bfb228a..2c38ec9f8b 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -34,38 +34,26 @@ int32_t Space::createProxy(const Space::Sphere& newSphere) { } } -void Space::deleteProxy(int32_t proxyId) { - if (proxyId >= (int32_t)_proxies.size() || _proxies.empty()) { - return; - } - if (proxyId == (int32_t)_proxies.size() - 1) { - // remove proxy on back - _proxies.pop_back(); - if (!_freeIndices.empty()) { - // remove any freeIndices on back - std::sort(_freeIndices.begin(), _freeIndices.end()); - while(!_freeIndices.empty() && _freeIndices.back() == (int32_t)_proxies.size() - 1) { - _freeIndices.pop_back(); - _proxies.pop_back(); - } - } - } else { - _proxies[proxyId].region = Space::REGION_INVALID; - _freeIndices.push_back(proxyId); +void Space::deleteProxies(const std::vector& deadIndices) { + for (uint32_t i = 0; i < deadIndices.size(); ++i) { + deleteProxy(deadIndices[i]); } } -void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) { - if (proxyId >= (int32_t)_proxies.size()) { - return; +void Space::updateProxies(const std::vector >& changedProxies) { + for (uint32_t i = 0; i < changedProxies.size(); ++i) { + int32_t proxyId = changedProxies[i].first; + if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { + updateProxy(changedProxies[i].first, changedProxies[i].second); + } } - _proxies[proxyId].sphere = newSphere; } void Space::setViews(const std::vector& views) { _views = views; } +// TODO?: move this to an algorithm/job? void Space::categorizeAndGetChanges(std::vector& changes) { uint32_t numProxies = (uint32_t)_proxies.size(); uint32_t numViews = (uint32_t)_views.size(); @@ -92,3 +80,31 @@ void Space::categorizeAndGetChanges(std::vector& changes) { } } +// private +void Space::deleteProxy(int32_t proxyId) { + if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { + if (proxyId == (int32_t)_proxies.size() - 1) { + // remove proxy on back + _proxies.pop_back(); + if (!_freeIndices.empty()) { + // remove any freeIndices on back + std::sort(_freeIndices.begin(), _freeIndices.end()); + while(!_freeIndices.empty() && _freeIndices.back() == (int32_t)_proxies.size() - 1) { + _freeIndices.pop_back(); + _proxies.pop_back(); + } + } + } else { + _proxies[proxyId].region = Space::REGION_INVALID; + _freeIndices.push_back(proxyId); + } + } +} + +// private +void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) { + if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { + _proxies[proxyId].sphere = newSphere; + } +} + diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index be47cddc4e..3a8dd3c488 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -60,8 +60,8 @@ public: Space() {} int32_t createProxy(const Sphere& sphere); - void deleteProxy(int32_t proxyId); - void updateProxy(int32_t proxyId, const Sphere& sphere); + void deleteProxies(const std::vector& deadIndices); + void updateProxies(const std::vector >& changedProxies); void setViews(const std::vector& views); uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); } @@ -69,6 +69,9 @@ public: void categorizeAndGetChanges(std::vector& changes); private: + void deleteProxy(int32_t proxyId); + void updateProxy(int32_t proxyId, const Sphere& sphere); + std::vector _proxies; std::vector _views; std::vector _freeIndices; diff --git a/tests/entities/CMakeLists.txt b/tests/entities/CMakeLists.txt index 6d0bf9f149..b1bfcfd8a5 100644 --- a/tests/entities/CMakeLists.txt +++ b/tests/entities/CMakeLists.txt @@ -7,7 +7,7 @@ setup_memory_debugger() set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") # link in the shared libraries -link_hifi_libraries(entities avatars shared octree gpu graphics fbx networking animation audio gl) +link_hifi_libraries(entities avatars shared workload octree gpu graphics fbx networking animation audio gl) if (WIN32) add_dependency_external_projects(wasapi) diff --git a/tests/render-perf/CMakeLists.txt b/tests/render-perf/CMakeLists.txt index 7e61d9550c..ed13aadfa3 100644 --- a/tests/render-perf/CMakeLists.txt +++ b/tests/render-perf/CMakeLists.txt @@ -18,7 +18,7 @@ link_hifi_libraries( render render-utils graphics fbx model-networking entities entities-renderer audio avatars script-engine - physics procedural midi qml ui + physics procedural midi qml ui workload ${PLATFORM_GL_BACKEND} )