History

Optimized performance of newTreeToArrays() by implementing blended VBO strategy - Introduced concept of sometimes only updating the new/changed part of the VBO while other times updating the full VBO. This allows us to get the speed advantage of only partial VBO updates when nodes haven't been removed - Some debugging output related to _alwaysRenderFullVBO - added cleanupRemovedVoxels() which actually deletes the nodes that were previously removed (fixes a memory leak!!)

ZappoMan committed 13 years ago

Commit bb651371 parent cadc07c2 files · +37 −4Browse files

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

Unified · Split

interface/src/VoxelSystem.cpp+36−4
@@ -147,19 +147,37 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 146 unmodified lines
147 // If the view frustum has changed, since last time, then remove nodes that are out of view147 // If the view frustum has changed, since last time, then remove nodes that are out of view
148 if ((sinceLastViewCulling >= std::max(_lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) && hasViewChanged()) {148 if ((sinceLastViewCulling >= std::max(_lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) && hasViewChanged()) {
149 _lastViewCulling = start;149 _lastViewCulling = start;
150
151 // When we call removeOutOfView() voxels, we don't actually remove the voxels from the VBOs, but we do remove
152 // them from tree, this makes our tree caclulations faster, but doesn't require us to fully rebuild the VBOs (which
153 // can be expensive).
150 removeOutOfView();154 removeOutOfView();
155
156 // Once we call cleanupRemovedVoxels() we do need to rebuild our VBOs (if anything was actually removed). So,
157 // we should consider putting this someplace else... as this might be able to occur less frequently, and save us on
158 // VBO reubuilding. Possibly we should do this only if our actual VBO usage crosses some lower boundary.
159 cleanupRemovedVoxels();
160
151 double endViewCulling = usecTimestampNow();161 double endViewCulling = usecTimestampNow();
152 _lastViewCullingElapsed = (endViewCulling - start) / 1000.0;162 _lastViewCullingElapsed = (endViewCulling - start) / 1000.0;
153 } 163 }
154 164
155 if (_tree->isDirty()) {165 if (_tree->isDirty()) {
156 PerformanceWarning warn(_renderWarningsOn, "calling... newTreeToArrays()");166 static char buffer[64] = { 0 };
167 if (_renderWarningsOn) {
168 sprintf(buffer, "newTreeToArrays() _alwaysRenderFullVBO=%s", (_alwaysRenderFullVBO ? "yes" : "no"));
169 };
170 PerformanceWarning warn(_renderWarningsOn, buffer);
157 _callsToTreesToArrays++;171 _callsToTreesToArrays++;
158 if (_alwaysRenderFullVBO) {172 if (_alwaysRenderFullVBO) {
159 _voxelsInWriteArrays = 0; // reset our VBO173 _voxelsInWriteArrays = 0; // reset our VBO
160 }174 }
161 _voxelsUpdated = newTreeToArrays(_tree->rootNode);175 _voxelsUpdated = newTreeToArrays(_tree->rootNode);
162 _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean176 _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean
177
178 // since we called treeToArrays, we can assume that our VBO is in sync, and so partial updates to the VBOs are
179 // ok again, until/unless we call removeOutOfView()
180 _alwaysRenderFullVBO = false;
163 } else {181 } else {
164 _voxelsUpdated = 0;182 _voxelsUpdated = 0;
165 }183 }
@@ -176,6 +194,16 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 10 unmodified lines
176 _setupNewVoxelsForDrawingLastElapsed = elapsedmsec;194 _setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
177}195}
178 196
197void VoxelSystem::cleanupRemovedVoxels() {
198 PerformanceWarning warn(_renderWarningsOn, "cleanupRemovedVoxels()");
199 if (!_removedVoxels.isEmpty()) {
200 while (!_removedVoxels.isEmpty()) {
201 delete _removedVoxels.extract();
202 }
203 _alwaysRenderFullVBO = true; // if we remove voxels, we must update our full VBOs
204 }
205}
206
179void VoxelSystem::copyWrittenDataToReadArrays() {207void VoxelSystem::copyWrittenDataToReadArrays() {
180 PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()"); // would like to include _voxelsInArrays, _voxelsUpdated208 PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()"); // would like to include _voxelsInArrays, _voxelsUpdated
181 if (_voxelsDirty && _voxelsUpdated) {209 if (_voxelsDirty && _voxelsUpdated) {
@@ -374,7 +402,11 @@ void VoxelSystem::init() { · 192 unmodified lines
374}402}
375 403
376void VoxelSystem::updateVBOs() {404void VoxelSystem::updateVBOs() {
377 PerformanceWarning warn(_renderWarningsOn, "updateVBOs()"); // would like to include _callsToTreesToArrays405 static char buffer[40] = { 0 };
406 if (_renderWarningsOn) {
407 sprintf(buffer, "updateVBOs() _alwaysRenderFullVBO=%s", (_alwaysRenderFullVBO ? "yes" : "no"));
408 };
409 PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays
378 if (_voxelsDirty) {410 if (_voxelsDirty) {
379 if (_alwaysRenderFullVBO) {411 if (_alwaysRenderFullVBO) {
380 glBufferIndex segmentStart = 0;412 glBufferIndex segmentStart = 0;
@@ -673,9 +705,9 @@ void VoxelSystem::removeOutOfView() { · 292 unmodified lines
673 _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args);705 _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args);
674 706
675 if (_renderWarningsOn) {707 if (_renderWarningsOn) {
676 printLog("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld bag.count()=%d \n", 708 printLog("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n",
677 args.nodesScanned, args.nodesRemoved, args.nodesInside, 709 args.nodesScanned, args.nodesRemoved, args.nodesInside,
678 args.nodesIntersect, args.nodesOutside, args.dontRecurseBag.count()710 args.nodesIntersect, args.nodesOutside, _removedVoxels.count()
679 );711 );
680 }712 }
681}713}