fix to runaway saving file and optimizations to general encoding paths

This commit is contained in:
ZappoMan 2014-09-03 10:55:56 -07:00
parent 0acbefb6a2
commit 66a2f58192
8 changed files with 96 additions and 15 deletions

View file

@ -349,6 +349,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
// track completed scenes and send out the stats packet accordingly
nodeData->stats.sceneCompleted();
nodeData->setLastRootTimestamp(_myServer->getOctree()->getRoot()->getLastChanged());
_myServer->getOctree()->releaseSceneEncodeData(&nodeData->extraEncodeData);
// TODO: add these to stats page
//::endSceneSleepTime = _usleepTime;

View file

@ -516,6 +516,14 @@ void EntityTree::removeNewlyCreatedHook(NewlyCreatedEntityHook* hook) {
}
void EntityTree::releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const {
foreach(void* extraData, *extraEncodeData) {
EntityTreeElementExtraEncodeData* thisExtraEncodeData = static_cast<EntityTreeElementExtraEncodeData*>(extraData);
delete thisExtraEncodeData;
}
extraEncodeData->clear();
}
void EntityTree::changeEntityState(EntityItem* const entity,
EntityItem::SimulationState oldState, EntityItem::SimulationState newState) {

View file

@ -66,6 +66,7 @@ public:
// the root at least needs to store the number of entities in the packet/buffer
virtual int minimumRequiredRootDataBytes() const { return sizeof(uint16_t); }
virtual bool suppressEmptySubtrees() const { return false; }
virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const;
virtual bool versionHasSVOfileBreaks(PacketVersion thisVersion) const
{ return thisVersion >= VERSION_ENTITIES_HAS_FILE_BREAKS; }

View file

@ -94,7 +94,7 @@ void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params)
}
}
bool EntityTreeElement::shouldIncludeChild(int childIndex, EncodeBitstreamParams& params) const {
bool EntityTreeElement::shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const {
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
@ -114,6 +114,30 @@ bool EntityTreeElement::shouldIncludeChild(int childIndex, EncodeBitstreamParams
return false;
}
bool EntityTreeElement::shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const {
EntityTreeElement* childElement = getChildAtIndex(childIndex);
if (childElement->alreadyFullyEncoded(params)) {
return false;
}
return true; // if we don't know otherwise than recurse!
}
bool EntityTreeElement::alreadyFullyEncoded(EncodeBitstreamParams& params) const {
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
if (extraEncodeData->contains(this)) {
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
// If we know that ALL subtrees below us have already been recursed, then we don't
// need to recurse this child.
return entityTreeElementExtraEncodeData->subtreeCompleted;
}
return false;
}
void EntityTreeElement::updateEncodedData(int childIndex, AppendState childAppendState, EncodeBitstreamParams& params) const {
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
@ -133,6 +157,12 @@ void EntityTreeElement::updateEncodedData(int childIndex, AppendState childAppen
void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params, OctreeElementBag* bag) const {
const bool wantDebug = false;
if (wantDebug) {
qDebug() << "EntityTreeElement::elementEncodeComplete() element:" << getAACube();
}
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
assert(extraEncodeData->contains(this));
@ -152,10 +182,10 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params, Oct
// 1) it's ok for our child trees to not yet be fully encoded/complete...
// SO LONG AS... the our child's node is in the bag ready for encoding
bool someChildTreeNotComplete = false;
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
EntityTreeElement* childElement = getChildAtIndex(i);
if (childElement) {
bool isThisChildReallyComplete = thisExtraEncodeData->childCompleted[i];
// why would this ever fail???
// If we've encoding this element before... but we're coming back a second time in an attempt to
@ -163,20 +193,44 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params, Oct
if (extraEncodeData->contains(childElement)) {
EntityTreeElementExtraEncodeData* childExtraEncodeData
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(childElement));
for (int ii = 0; ii < NUMBER_OF_CHILDREN; ii++) {
if (!childExtraEncodeData->childCompleted[ii]) {
isThisChildReallyComplete = false;
if (wantDebug) {
qDebug() << "checking child: " << childElement->getAACube();
qDebug() << " childElement->isLeaf():" << childElement->isLeaf();
qDebug() << " childExtraEncodeData->elementCompleted:" << childExtraEncodeData->elementCompleted;
qDebug() << " childExtraEncodeData->subtreeCompleted:" << childExtraEncodeData->subtreeCompleted;
}
if (childElement->isLeaf() && childExtraEncodeData->elementCompleted) {
if (wantDebug) {
qDebug() << " CHILD IS LEAF -- AND CHILD ELEMENT DATA COMPLETED!!!";
}
childExtraEncodeData->subtreeCompleted = true;
}
if (isThisChildReallyComplete) {
extraEncodeData->remove(childElement);
delete childExtraEncodeData;
if (!childExtraEncodeData->elementCompleted || !childExtraEncodeData->subtreeCompleted) {
someChildTreeNotComplete = true;
}
}
}
}
if (wantDebug) {
qDebug() << "for this element: " << getAACube();
qDebug() << " WAS elementCompleted:" << thisExtraEncodeData->elementCompleted;
qDebug() << " WAS subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted;
}
thisExtraEncodeData->subtreeCompleted = !someChildTreeNotComplete;
if (wantDebug) {
qDebug() << " NOW elementCompleted:" << thisExtraEncodeData->elementCompleted;
qDebug() << " NOW subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted;
if (thisExtraEncodeData->subtreeCompleted) {
qDebug() << " YEAH!!!!! >>>>>>>>>>>>>> NOW subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted;
}
}
}
OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData* packetData,

View file

@ -40,10 +40,12 @@ class EntityTreeElementExtraEncodeData {
public:
EntityTreeElementExtraEncodeData() :
elementCompleted(false),
subtreeCompleted(false),
entities() {
memset(childCompleted, 0, sizeof(childCompleted));
}
bool elementCompleted;
bool subtreeCompleted;
bool childCompleted[NUMBER_OF_CHILDREN];
QMap<EntityItemID, EntityPropertyFlags> entities;
};
@ -51,6 +53,7 @@ public:
inline QDebug operator<<(QDebug debug, const EntityTreeElementExtraEncodeData* data) {
debug << "{";
debug << " elementCompleted: " << data->elementCompleted << ", ";
debug << " subtreeCompleted: " << data->subtreeCompleted << ", ";
debug << " childCompleted[]: ";
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
debug << " " << i << ":" << data->childCompleted[i] << ", ";
@ -109,10 +112,13 @@ public:
virtual void debugExtraEncodeData(EncodeBitstreamParams& params) const;
virtual void initializeExtraEncodeData(EncodeBitstreamParams& params) const;
virtual bool shouldIncludeChild(int childIndex, EncodeBitstreamParams& params) const;
virtual bool shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const;
virtual bool shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const;
virtual void updateEncodedData(int childIndex, AppendState childAppendState, EncodeBitstreamParams& params) const;
virtual void elementEncodeComplete(EncodeBitstreamParams& params, OctreeElementBag* bag) const;
bool alreadyFullyEncoded(EncodeBitstreamParams& params) const;
/// Override to serialize the state of this element. This is used for persistance and for transmission across the network.
virtual OctreeElement::AppendState appendElementData(OctreePacketData* packetData, EncodeBitstreamParams& params) const;

View file

@ -1401,7 +1401,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
// the childrenDataBits were set up by the in view/LOD logic, it may contain children that we've already
// processed and sent the data bits for. Let our tree subclass determine if it really wants to send the
// data for this child at this point
if (childElement && element->shouldIncludeChild(i, params)) {
if (childElement && element->shouldIncludeChildData(i, params)) {
int bytesBeforeChild = packetData->getUncompressedSize();
@ -1553,8 +1553,15 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
// recursing, by returning TRUE in recurseChildrenWithData().
if (recurseChildrenWithData() || !params.viewFrustum || !oneAtBit(childrenDataBits, originalIndex)) {
childTreeBytesOut = encodeTreeBitstreamRecursion(childElement, packetData, bag, params,
thisLevel, nodeLocationThisView);
// Allow the datatype a chance to determine if it really wants to recurse this tree. Usually this
// will be true. But if the tree has already been encoded, we will skip this.
if (element->shouldRecurseChildTree(originalIndex, params)) {
childTreeBytesOut = encodeTreeBitstreamRecursion(childElement, packetData, bag, params,
thisLevel, nodeLocationThisView);
} else {
childTreeBytesOut = 0;
}
}
// remember this for reshuffling
@ -1964,6 +1971,8 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) {
}
file.write((const char*)packetData.getFinalizedData(), packetData.getFinalizedSize());
}
releaseSceneEncodeData(&extraEncodeData);
}
file.close();
}

View file

@ -235,6 +235,7 @@ public:
virtual bool rootElementHasData() const { return false; }
virtual int minimumRequiredRootDataBytes() const { return 0; }
virtual bool suppressEmptySubtrees() const { return true; }
virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const { }
/// some versions of the SVO file will include breaks with buffer lengths between each buffer chunk in the SVO
/// file. If the Octree subclass expects this for this particular version of the file, it should override this
@ -275,7 +276,7 @@ public:
int encodeTreeBitstream(OctreeElement* element, OctreePacketData* packetData, OctreeElementBag& bag,
EncodeBitstreamParams& params) ;
bool isDirty() const { return _isDirty; }
void clearDirtyBit() { _isDirty = false; }
void setDirtyBit() { _isDirty = true; }

View file

@ -93,7 +93,8 @@ public:
virtual void debugExtraEncodeData(EncodeBitstreamParams& params) const { }
virtual void initializeExtraEncodeData(EncodeBitstreamParams& params) const { }
virtual bool shouldIncludeChild(int childIndex, EncodeBitstreamParams& params) const { return true; }
virtual bool shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const { return true; }
virtual bool shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const { return true; }
virtual void updateEncodedData(int childIndex, AppendState childAppendState, EncodeBitstreamParams& params) const { }
virtual void elementEncodeComplete(EncodeBitstreamParams& params, OctreeElementBag* bag) const { }