separate elementBag logic from EntityTreeSendThread

This commit is contained in:
SamGondelman 2017-09-11 10:26:27 -07:00 committed by Andrew Meadows
parent bf1065b56e
commit cbd20f89dd
3 changed files with 38 additions and 26 deletions

View file

@ -30,7 +30,6 @@ public:
EntityTreeSendThread(OctreeServer* myServer, const SharedNodePointer& node); EntityTreeSendThread(OctreeServer* myServer, const SharedNodePointer& node);
protected: protected:
void preDistributionProcessing() override;
void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
bool viewFrustumChanged, bool isFullScene) override; bool viewFrustumChanged, bool isFullScene) override;
@ -42,6 +41,12 @@ private:
void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum); void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum);
bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override; bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override;
void preDistributionProcessing() override;
bool hasSomethingToSend(OctreeQueryNode* nodeData) override { return !_sendQueue.empty(); }
bool shouldStartNewTraversal(OctreeQueryNode* nodeData, bool viewFrustumChanged) override { return viewFrustumChanged || _traversal.finished(); }
void preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene) override {};
bool shouldTraverseAndSend(OctreeQueryNode* nodeData) override { return true; }
DiffTraversal _traversal; DiffTraversal _traversal;
EntityPriorityQueue _sendQueue; EntityPriorityQueue _sendQueue;
std::unordered_set<EntityItem*> _entitiesInQueue; std::unordered_set<EntityItem*> _entitiesInQueue;

View file

@ -17,7 +17,6 @@
#include <udt/PacketHeaders.h> #include <udt/PacketHeaders.h>
#include <PerfStat.h> #include <PerfStat.h>
#include "OctreeQueryNode.h"
#include "OctreeSendThread.h" #include "OctreeSendThread.h"
#include "OctreeServer.h" #include "OctreeServer.h"
#include "OctreeServerConsts.h" #include "OctreeServerConsts.h"
@ -301,9 +300,25 @@ int OctreeSendThread::handlePacketSend(SharedNodePointer node, OctreeQueryNode*
return numPackets; return numPackets;
} }
void OctreeSendThread::preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene) {
// If we're starting a full scene, then definitely we want to empty the elementBag
if (isFullScene) {
nodeData->elementBag.deleteAll();
}
// This is the start of "resending" the scene.
bool dontRestartSceneOnMove = false; // this is experimental
if (dontRestartSceneOnMove) {
if (nodeData->elementBag.isEmpty()) {
nodeData->elementBag.insert(_myServer->getOctree()->getRoot());
}
} else {
nodeData->elementBag.insert(_myServer->getOctree()->getRoot());
}
}
/// Version of octree element distributor that sends the deepest LOD level at once /// Version of octree element distributor that sends the deepest LOD level at once
int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged) { int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged) {
OctreeServer::didPacketDistributor(this); OctreeServer::didPacketDistributor(this);
// if shutting down, exit early // if shutting down, exit early
@ -311,7 +326,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
return 0; return 0;
} }
if (nodeData->elementBag.isEmpty()) { if (shouldStartNewTraversal(nodeData, viewFrustumChanged)) {
// if we're about to do a fresh pass, // if we're about to do a fresh pass,
// give our pre-distribution processing a chance to do what it needs // give our pre-distribution processing a chance to do what it needs
preDistributionProcessing(); preDistributionProcessing();
@ -345,7 +360,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
// If the current view frustum has changed OR we have nothing to send, then search against // If the current view frustum has changed OR we have nothing to send, then search against
// the current view frustum for things to send. // the current view frustum for things to send.
if (viewFrustumChanged || nodeData->elementBag.isEmpty()) { if (shouldStartNewTraversal(nodeData, viewFrustumChanged)) {
// if our view has changed, we need to reset these things... // if our view has changed, we need to reset these things...
if (viewFrustumChanged) { if (viewFrustumChanged) {
@ -367,11 +382,6 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
_packetsSentThisInterval += handlePacketSend(node, nodeData, isFullScene); _packetsSentThisInterval += handlePacketSend(node, nodeData, isFullScene);
// If we're starting a full scene, then definitely we want to empty the elementBag
if (isFullScene) {
nodeData->elementBag.deleteAll();
}
// TODO: add these to stats page // TODO: add these to stats page
//::startSceneSleepTime = _usleepTime; //::startSceneSleepTime = _usleepTime;
@ -380,19 +390,11 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged,
_myServer->getOctree()->getRoot(), _myServer->getJurisdiction()); _myServer->getOctree()->getRoot(), _myServer->getJurisdiction());
// This is the start of "resending" the scene. preStartNewScene(nodeData, isFullScene);
bool dontRestartSceneOnMove = false; // this is experimental
if (dontRestartSceneOnMove) {
if (nodeData->elementBag.isEmpty()) {
nodeData->elementBag.insert(_myServer->getOctree()->getRoot());
}
} else {
nodeData->elementBag.insert(_myServer->getOctree()->getRoot());
}
} }
// If we have something in our elementBag, then turn them into packets and send them out... // If we have something in our elementBag, then turn them into packets and send them out...
if (!nodeData->elementBag.isEmpty()) { if (shouldTraverseAndSend(nodeData)) {
quint64 start = usecTimestampNow(); quint64 start = usecTimestampNow();
traverseTreeAndSendContents(node, nodeData, viewFrustumChanged, isFullScene); traverseTreeAndSendContents(node, nodeData, viewFrustumChanged, isFullScene);
@ -441,7 +443,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
// if after sending packets we've emptied our bag, then we want to remember that we've sent all // if after sending packets we've emptied our bag, then we want to remember that we've sent all
// the octree elements from the current view frustum // the octree elements from the current view frustum
if (nodeData->elementBag.isEmpty()) { if (!hasSomethingToSend(nodeData)) {
nodeData->updateLastKnownViewFrustum(); nodeData->updateLastKnownViewFrustum();
nodeData->setViewSent(true); nodeData->setViewSent(true);
@ -502,8 +504,7 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre
EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP, EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale, viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale,
isFullScene, _myServer->getJurisdiction(), nodeData); isFullScene, _myServer->getJurisdiction(), nodeData);
// Our trackSend() function is implemented by the server subclass, and will be called back // Our trackSend() function is implemented by the server subclass, and will be called back as new entities/data elements are sent
// during the encodeTreeBitstream() as new entities/data elements are sent
params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) { params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) {
_myServer->trackSend(dataID, dataEdited, _nodeUuid); _myServer->trackSend(dataID, dataEdited, _nodeUuid);
}; };
@ -513,7 +514,7 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre
} }
bool somethingToSend = true; // assume we have something bool somethingToSend = true; // assume we have something
bool bagHadSomething = !nodeData->elementBag.isEmpty(); bool bagHadSomething = hasSomethingToSend(nodeData);
while (somethingToSend && _packetsSentThisInterval < maxPacketsPerInterval && !nodeData->isShuttingDown()) { while (somethingToSend && _packetsSentThisInterval < maxPacketsPerInterval && !nodeData->isShuttingDown()) {
float compressAndWriteElapsedUsec = OctreeServer::SKIP_TIME; float compressAndWriteElapsedUsec = OctreeServer::SKIP_TIME;
float packetSendingElapsedUsec = OctreeServer::SKIP_TIME; float packetSendingElapsedUsec = OctreeServer::SKIP_TIME;

View file

@ -19,6 +19,7 @@
#include <GenericThread.h> #include <GenericThread.h>
#include <Node.h> #include <Node.h>
#include <OctreePacketData.h> #include <OctreePacketData.h>
#include "OctreeQueryNode.h"
class OctreeQueryNode; class OctreeQueryNode;
class OctreeServer; class OctreeServer;
@ -51,8 +52,6 @@ protected:
/// Implements generic processing behavior for this thread. /// Implements generic processing behavior for this thread.
virtual bool process() override; virtual bool process() override;
/// Called before a packetDistributor pass to allow for pre-distribution processing
virtual void preDistributionProcessing() {};
virtual void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, virtual void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
bool viewFrustumChanged, bool isFullScene); bool viewFrustumChanged, bool isFullScene);
virtual bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters); virtual bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters);
@ -62,9 +61,16 @@ protected:
OctreeServer* _myServer { nullptr }; OctreeServer* _myServer { nullptr };
private: private:
/// Called before a packetDistributor pass to allow for pre-distribution processing
virtual void preDistributionProcessing() {};
int handlePacketSend(SharedNodePointer node, OctreeQueryNode* nodeData, bool dontSuppressDuplicate = false); int handlePacketSend(SharedNodePointer node, OctreeQueryNode* nodeData, bool dontSuppressDuplicate = false);
int packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged); int packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged);
virtual bool hasSomethingToSend(OctreeQueryNode* nodeData) { return !nodeData->elementBag.isEmpty(); }
virtual bool shouldStartNewTraversal(OctreeQueryNode* nodeData, bool viewFrustumChanged) { return viewFrustumChanged || !hasSomethingToSend(nodeData); }
virtual void preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene);
virtual bool shouldTraverseAndSend(OctreeQueryNode* nodeData) { return hasSomethingToSend(nodeData); }
QUuid _nodeUuid; QUuid _nodeUuid;
int _truePacketsSent { 0 }; // available for debug stats int _truePacketsSent { 0 }; // available for debug stats