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
57 57
58VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)58VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
59 : NodeData(),59 : NodeData(),
60 _treeScale(treeScale),60 _treeScale(treeScale),
61 _maxVoxels(maxVoxels),61 _maxVoxels(maxVoxels),
62 _initialized(false) {62 _initialized(false),
63 _writeArraysLock(QReadWriteLock::Recursive),
64 _readArraysLock(QReadWriteLock::Recursive)
65 {
63 66
64 _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0;67 _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0;
65 _writeRenderFullVBO = true;68 _writeRenderFullVBO = true;
@@ -124,8 +127,16 @@ void VoxelSystem::setDisableFastVoxelPipeline(bool disableFastVoxelPipeline) { · 58 unmodified lines
124 127
125void VoxelSystem::elementUpdated(OctreeElement* element) {128void VoxelSystem::elementUpdated(OctreeElement* element) {
126 VoxelTreeElement* voxel = (VoxelTreeElement*)element;129 VoxelTreeElement* voxel = (VoxelTreeElement*)element;
130//qDebug() << "VoxelSystem::elementUpdated()...";
131
127 // If we're in SetupNewVoxelsForDrawing() or _writeRenderFullVBO then bail..132 // If we're in SetupNewVoxelsForDrawing() or _writeRenderFullVBO then bail..
128 if (!_useFastVoxelPipeline || _inSetupNewVoxelsForDrawing || _writeRenderFullVBO) {133 if (!_useFastVoxelPipeline || _inSetupNewVoxelsForDrawing || _writeRenderFullVBO) {
134/*
135qDebug() << "VoxelSystem::elementUpdated()... BAILING!!! "
136 << "_writeRenderFullVBO="<< _writeRenderFullVBO
137 << "_inSetupNewVoxelsForDrawing="<< _inSetupNewVoxelsForDrawing
138 << "_useFastVoxelPipeline="<< _useFastVoxelPipeline;
139*/
129 return;140 return;
130 }141 }
131 142
@@ -136,6 +147,8 @@ void VoxelSystem::elementUpdated(OctreeElement* element) { · 4 unmodified lines
136 int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();147 int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
137 shouldRender = voxel->calculateShouldRender(_viewFrustum, voxelSizeScale, boundaryLevelAdjust);148 shouldRender = voxel->calculateShouldRender(_viewFrustum, voxelSizeScale, boundaryLevelAdjust);
138 149
150//qDebug() << "VoxelSystem::elementUpdated()... recalcing should render!!";
151
139 if (voxel->getShouldRender() != shouldRender) {152 if (voxel->getShouldRender() != shouldRender) {
140 voxel->setShouldRender(shouldRender);153 voxel->setShouldRender(shouldRender);
141 }154 }
@@ -163,11 +176,13 @@ void VoxelSystem::elementUpdated(OctreeElement* element) { · 21 unmodified lines
163 176
164 const bool REUSE_INDEX = true;177 const bool REUSE_INDEX = true;
165 const bool DONT_FORCE_REDRAW = false;178 const bool DONT_FORCE_REDRAW = false;
179//qDebug() << "VoxelSystem::elementUpdated()... calling updateNodeInArrays()!!!";
166 updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW);180 updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW);
167 _voxelsUpdated++;181 _voxelsUpdated++;
168 182
169 voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.183 voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.
170 184
185//qDebug() << "VoxelSystem::elementUpdated()... calling setupNewVoxelsForDrawingSingleNode()!!!";
171 setupNewVoxelsForDrawingSingleNode();186 setupNewVoxelsForDrawingSingleNode();
172 }187 }
173}188}
@@ -409,7 +424,8 @@ void VoxelSystem::setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndice · 235 unmodified lines
409}424}
410 425
411void VoxelSystem::initVoxelMemory() {426void VoxelSystem::initVoxelMemory() {
412 _readArraysLock.lockForWrite();427 //_readArraysLock.lockForWrite();
428 //_writeArraysLock.lockForWrite();
413 429
414 _memoryUsageRAM = 0;430 _memoryUsageRAM = 0;
415 _memoryUsageVBO = 0; // our VBO allocations as we know them431 _memoryUsageVBO = 0; // our VBO allocations as we know them
@@ -524,7 +540,8 @@ void VoxelSystem::initVoxelMemory() { · 108 unmodified lines
524 540
525 _initialized = true;541 _initialized = true;
526 542
527 _readArraysLock.unlock();543 //_writeArraysLock.unlock();
544 //_readArraysLock.unlock();
528}545}
529 546
530void VoxelSystem::writeToSVOFile(const char* filename, VoxelTreeElement* element) const {547void VoxelSystem::writeToSVOFile(const char* filename, VoxelTreeElement* element) const {
@@ -741,9 +758,90 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { · 210 unmodified lines
741 _setupNewVoxelsForDrawingLastElapsed = elapsedmsec;758 _setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
742}759}
743 760
761
762
763class recreateVoxelGeometryInViewArgs {
764public:
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.
783bool 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???
744void VoxelSystem::recreateVoxelGeometryInView() {815void VoxelSystem::recreateVoxelGeometryInView() {
745 // this is a temporary solution... we need a full implementation that actually does a full redraw into clean VBOs816
746 hideOutOfView(true);817qDebug() << "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();
747}845}
748 846
749void VoxelSystem::checkForCulling() {847void VoxelSystem::checkForCulling() {
@@ -784,7 +882,8 @@ void VoxelSystem::checkForCulling() { · 34 unmodified lines
784 882
785 if (fullRedraw) {883 if (fullRedraw) {
786 // this will remove all old geometry and recreate the correct geometry for all in view voxels884 // this will remove all old geometry and recreate the correct geometry for all in view voxels
787 recreateVoxelGeometryInView();885 //recreateVoxelGeometryInView();
886 hideOutOfView(forceFullFrustum);
788 } else {887 } else {
789 hideOutOfView(forceFullFrustum);888 hideOutOfView(forceFullFrustum);
790 }889 }
@@ -905,12 +1004,26 @@ void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) { · 114 unmodified lines
905 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),1004 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
906 "copyWrittenDataToReadArrays()");1005 "copyWrittenDataToReadArrays()");
907 1006
908 if (_voxelsDirty && _voxelsUpdated) {1007 // attempt to get the writeArraysLock for reading and the readArraysLock for writing
909 if (fullVBOs) {1008 // so we can copy from the write to the read... if we fail, that's ok, we'll get it the next
910 copyWrittenDataToReadArraysFullVBOs();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();
911 } else {1021 } else {
912 copyWrittenDataToReadArraysPartialVBOs();1022 qDebug() << "couldn't get _writeArraysLock.LockForRead()...";
913 }1023 }
1024 _readArraysLock.unlock();
1025 } else {
1026 qDebug() << "couldn't get _readArraysLock.LockForWrite()...";
914 }1027 }
915}1028}
916 1029
@@ -1105,7 +1218,8 @@ void VoxelSystem::changeTree(VoxelTree* newTree) { · 188 unmodified lines
1105 connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float)));1218 connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float)));
1106 connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int)));1219 connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int)));
1107 1220
1108 setupNewVoxelsForDrawing();1221 // TODO: hmmmmm?????
1222 //setupNewVoxelsForDrawing();
1109}1223}
1110 1224
1111void VoxelSystem::updateFullVBOs() {1225void VoxelSystem::updateFullVBOs() {
@@ -1166,17 +1280,27 @@ void VoxelSystem::updateVBOs() { · 54 unmodified lines
1166 // would like to include _callsToTreesToArrays1280 // would like to include _callsToTreesToArrays
1167 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer);1281 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer);
1168 if (_voxelsDirty) {1282 if (_voxelsDirty) {
1169 if (_readRenderFullVBO) {1283
1170 updateFullVBOs();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();
1171 } else {1296 } else {
1172 updatePartialVBOs();1297 qDebug() << "updateVBOs().... couldn't get _readArraysLock.tryLockForRead()";
1173 }1298 }
1174 _voxelsDirty = false;
1175 _readRenderFullVBO = false;
1176 }1299 }
1177 _callsToTreesToArrays = 0; // clear it1300 _callsToTreesToArrays = 0; // clear it
1178}1301}
1179 1302
1303// this should only be called on the main application thread during render
1180void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) {1304void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) {
1181 bool showWarning = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);1305 bool showWarning = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1182 PerformanceWarning warn(showWarning, "updateVBOSegment()");1306 PerformanceWarning warn(showWarning, "updateVBOSegment()");