History

add proper readWriteLocks around the VBO arrays to preven random triangles

ZappoMan committed 12 years ago

Commit cac67d71 parent e9259db2 files · +144 −18Browse files

Showing the changes to interface/src/VoxelSystem.cpp (1 of 2 files). Show all

Unified · Split

interface/src/VoxelSystem.cpp+142−18
@@ -57,9 +57,12 @@ GLubyte identityIndicesBack[] = { 4, 5, 6, 4, 6, 7 }; · 56 unmodified lines
5757
5858 VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
5959 : NodeData(),
60− _treeScale(treeScale),
61− _maxVoxels(maxVoxels),
62− _initialized(false) {
60+ _treeScale(treeScale),
61+ _maxVoxels(maxVoxels),
62+ _initialized(false),
63+ _writeArraysLock(QReadWriteLock::Recursive),
64+ _readArraysLock(QReadWriteLock::Recursive)
65+ {
6366
6467 _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0;
6568 _writeRenderFullVBO = true;
@@ -124,8 +127,16 @@ void VoxelSystem::setDisableFastVoxelPipeline(bool disableFastVoxelPipeline) { · 58 unmodified lines
124127
125128 void VoxelSystem::elementUpdated(OctreeElement* element) {
126129 VoxelTreeElement* voxel = (VoxelTreeElement*)element;
130+//qDebug() << "VoxelSystem::elementUpdated()...";
131+
127132 // If we're in SetupNewVoxelsForDrawing() or _writeRenderFullVBO then bail..
128133 if (!_useFastVoxelPipeline || _inSetupNewVoxelsForDrawing || _writeRenderFullVBO) {
134+/*
135+qDebug() << "VoxelSystem::elementUpdated()... BAILING!!! "
136+ << "_writeRenderFullVBO="<< _writeRenderFullVBO
137+ << "_inSetupNewVoxelsForDrawing="<< _inSetupNewVoxelsForDrawing
138+ << "_useFastVoxelPipeline="<< _useFastVoxelPipeline;
139+*/
129140 return;
130141 }
131142
@@ -136,6 +147,8 @@ void VoxelSystem::elementUpdated(OctreeElement* element) { · 4 unmodified lines
136147 int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
137148 shouldRender = voxel->calculateShouldRender(_viewFrustum, voxelSizeScale, boundaryLevelAdjust);
138149
150+//qDebug() << "VoxelSystem::elementUpdated()... recalcing should render!!";
151+
139152 if (voxel->getShouldRender() != shouldRender) {
140153 voxel->setShouldRender(shouldRender);
141154 }
@@ -163,11 +176,13 @@ void VoxelSystem::elementUpdated(OctreeElement* element) { · 21 unmodified lines
163176
164177 const bool REUSE_INDEX = true;
165178 const bool DONT_FORCE_REDRAW = false;
179+//qDebug() << "VoxelSystem::elementUpdated()... calling updateNodeInArrays()!!!";
166180 updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW);
167181 _voxelsUpdated++;
168182
169183 voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.
170184
185+//qDebug() << "VoxelSystem::elementUpdated()... calling setupNewVoxelsForDrawingSingleNode()!!!";
171186 setupNewVoxelsForDrawingSingleNode();
172187 }
173188 }
@@ -409,7 +424,8 @@ void VoxelSystem::setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndice · 235 unmodified lines
409424 }
410425
411426 void VoxelSystem::initVoxelMemory() {
412− _readArraysLock.lockForWrite();
427+ //_readArraysLock.lockForWrite();
428+ //_writeArraysLock.lockForWrite();
413429
414430 _memoryUsageRAM = 0;
415431 _memoryUsageVBO = 0; // our VBO allocations as we know them
@@ -524,7 +540,8 @@ void VoxelSystem::initVoxelMemory() { · 108 unmodified lines
524540
525541 _initialized = true;
526542
527− _readArraysLock.unlock();
543+ //_writeArraysLock.unlock();
544+ //_readArraysLock.unlock();
528545 }
529546
530547 void VoxelSystem::writeToSVOFile(const char* filename, VoxelTreeElement* element) const {
@@ -741,9 +758,90 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { · 210 unmodified lines
741758 _setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
742759 }
743760
761+
762+
763+class recreateVoxelGeometryInViewArgs {
764+public:
765+ VoxelSystem* thisVoxelSystem;
766+ ViewFrustum thisViewFrustum;
767+ unsigned long nodesScanned;
768+ float voxelSizeScale;
769+ int boundaryLevelAdjust;
770+
771+ recreateVoxelGeometryInViewArgs(VoxelSystem* voxelSystem) :
772+ thisVoxelSystem(voxelSystem),
773+ thisViewFrustum(*voxelSystem->getViewFrustum()),
774+ nodesScanned(0),
775+ voxelSizeScale(Menu::getInstance()->getVoxelSizeScale()),
776+ boundaryLevelAdjust(Menu::getInstance()->getBoundaryLevelAdjust())
777+ {
778+ }
779+};
780+
781+// The goal of this operation is to remove any old references to old geometry, and if the voxel
782+// should be visible, create new geometry for it.
783+bool VoxelSystem::recreateVoxelGeometryInViewOperation(OctreeElement* element, void* extraData) {
784+ VoxelTreeElement* voxel = (VoxelTreeElement*)element;
785+ recreateVoxelGeometryInViewArgs* args = (recreateVoxelGeometryInViewArgs*)extraData;
786+
787+ args->nodesScanned++;
788+
789+ // reset the old geometry...
790+ // note: this doesn't "mark the voxel as changed", so it only releases the old buffer index thereby forgetting the
791+ // old geometry
792+ voxel->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
793+
794+ bool shouldRender = voxel->calculateShouldRender(&args->thisViewFrustum, args->voxelSizeScale, args->boundaryLevelAdjust);
795+ bool inView = voxel->isInView(args->thisViewFrustum);
796+ voxel->setShouldRender(inView && shouldRender);
797+
798+ if (shouldRender) {
799+ bool falseColorize = false;
800+ if (falseColorize) {
801+ voxel->setFalseColor(0,0,255); // false colorize
802+ }
803+ // These are both needed to force redraw...
804+ voxel->setDirtyBit();
805+ qDebug() << "recreateVoxelGeometryInViewOperation()... calling voxel->markWithChangedTime()";
806+ voxel->markWithChangedTime(); // this will notifyUpdateHooks, which will result in our geometry being created
807+ }
808+
809+ return true; // keep recursing!
810+}
811+
812+
813+// TODO: does cleanupRemovedVoxels() ever get called?
814+// TODO: other than cleanupRemovedVoxels() is there anyplace we attempt to detect too many abandoned slots???
744815 void VoxelSystem::recreateVoxelGeometryInView() {
745− // this is a temporary solution... we need a full implementation that actually does a full redraw into clean VBOs
746− hideOutOfView(true);
816+
817+qDebug() << "recreateVoxelGeometryInView()...";
818+
819+ recreateVoxelGeometryInViewArgs args(this);
820+ _writeArraysLock.lockForWrite(); // don't let anyone read or write our write arrays until we're done
821+ _tree->lockForRead(); // don't let anyone change our tree structure until we're run
822+
823+ // reset our write arrays bookkeeping to think we've got no voxels in it
824+ clearFreeBufferIndexes(); // does this do everything we need?
825+ /**
826+ // clear out all our abandoned indexes - they are all available
827+ // TODO: is it possible freeBufferIndex() will get called???
828+ _voxelsInWriteArrays = 0;
829+ _freeIndexLock.lock();
830+ _freeIndexes.clear();
831+ _freeIndexLock.unlock();
832+ **/
833+
834+ //_voxelsUpdated = 0; // ????
835+ //_writeRenderFullVBO = true;
836+
837+ // do we need to reset out _writeVoxelDirtyArray arrays??
838+ memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
839+
840+
841+
842+ _tree->recurseTreeWithOperation(recreateVoxelGeometryInViewOperation,(void*)&args);
843+ _tree->unlock();
844+ _writeArraysLock.unlock();
747845 }
748846
749847 void VoxelSystem::checkForCulling() {
@@ -784,7 +882,8 @@ void VoxelSystem::checkForCulling() { · 34 unmodified lines
784882
785883 if (fullRedraw) {
786884 // this will remove all old geometry and recreate the correct geometry for all in view voxels
787− recreateVoxelGeometryInView();
885+ //recreateVoxelGeometryInView();
886+ hideOutOfView(forceFullFrustum);
788887 } else {
789888 hideOutOfView(forceFullFrustum);
790889 }
@@ -905,12 +1004,26 @@ void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) { · 114 unmodified lines
9051004 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
9061005 "copyWrittenDataToReadArrays()");
9071006
908− if (_voxelsDirty && _voxelsUpdated) {
909− if (fullVBOs) {
910− copyWrittenDataToReadArraysFullVBOs();
1007+ // attempt to get the writeArraysLock for reading and the readArraysLock for writing
1008+ // so we can copy from the write to the read... if we fail, that's ok, we'll get it the next
1009+ // time around, the only side effect is the VBOs won't be updated this frame
1010+ const int WAIT_FOR_LOCK_IN_MS = 5;
1011+ if (_readArraysLock.tryLockForWrite(WAIT_FOR_LOCK_IN_MS)) {
1012+ if (_writeArraysLock.tryLockForRead(WAIT_FOR_LOCK_IN_MS)) {
1013+ if (_voxelsDirty && _voxelsUpdated) {
1014+ if (fullVBOs) {
1015+ copyWrittenDataToReadArraysFullVBOs();
1016+ } else {
1017+ copyWrittenDataToReadArraysPartialVBOs();
1018+ }
1019+ }
1020+ _writeArraysLock.unlock();
9111021 } else {
912− copyWrittenDataToReadArraysPartialVBOs();
1022+ qDebug() << "couldn't get _writeArraysLock.LockForRead()...";
9131023 }
1024+ _readArraysLock.unlock();
1025+ } else {
1026+ qDebug() << "couldn't get _readArraysLock.LockForWrite()...";
9141027 }
9151028 }
9161029
@@ -1105,7 +1218,8 @@ void VoxelSystem::changeTree(VoxelTree* newTree) { · 188 unmodified lines
11051218 connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float)));
11061219 connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int)));
11071220
1108− setupNewVoxelsForDrawing();
1221+ // TODO: hmmmmm?????
1222+ //setupNewVoxelsForDrawing();
11091223 }
11101224
11111225 void VoxelSystem::updateFullVBOs() {
@@ -1166,17 +1280,27 @@ void VoxelSystem::updateVBOs() { · 54 unmodified lines
11661280 // would like to include _callsToTreesToArrays
11671281 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer);
11681282 if (_voxelsDirty) {
1169− if (_readRenderFullVBO) {
1170− updateFullVBOs();
1283+
1284+ // attempt to lock the read arrays, to for copying from them to the actual GPU VBOs.
1285+ // if we fail to get the lock, that's ok, our VBOs will update on the next frame...
1286+ const int WAIT_FOR_LOCK_IN_MS = 5;
1287+ if (_readArraysLock.tryLockForRead(WAIT_FOR_LOCK_IN_MS)) {
1288+ if (_readRenderFullVBO) {
1289+ updateFullVBOs();
1290+ } else {
1291+ updatePartialVBOs();
1292+ }
1293+ _voxelsDirty = false;
1294+ _readRenderFullVBO = false;
1295+ _readArraysLock.unlock();
11711296 } else {
1172− updatePartialVBOs();
1297+ qDebug() << "updateVBOs().... couldn't get _readArraysLock.tryLockForRead()";
11731298 }
1174− _voxelsDirty = false;
1175− _readRenderFullVBO = false;
11761299 }
11771300 _callsToTreesToArrays = 0; // clear it
11781301 }
11791302
1303+// this should only be called on the main application thread during render
11801304 void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) {
11811305 bool showWarning = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
11821306 PerformanceWarning warn(showWarning, "updateVBOSegment()");