History

first cut at new faster voxel pipeline

ZappoMan committed 13 years ago

Commit 793a14e1 parent 0f74d4b8 files · +214 −13Browse files

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

Unified · Split

interface/src/VoxelSystem.cpp+153−3
@@ -70,10 +70,12 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) · 69 unmodified lines
70 _writeRenderFullVBO = true;70 _writeRenderFullVBO = true;
71 _readRenderFullVBO = true;71 _readRenderFullVBO = true;
72 _tree = new VoxelTree();72 _tree = new VoxelTree();
73 _tree->rootNode->setVoxelSystem(this);
73 pthread_mutex_init(&_bufferWriteLock, NULL);74 pthread_mutex_init(&_bufferWriteLock, NULL);
74 pthread_mutex_init(&_treeLock, NULL);75 pthread_mutex_init(&_treeLock, NULL);
75 76
76 VoxelNode::addDeleteHook(this);77 VoxelNode::addDeleteHook(this);
78 VoxelNode::addUpdateHook(this);
77 _abandonedVBOSlots = 0;79 _abandonedVBOSlots = 0;
78 _falseColorizeBySource = false;80 _falseColorizeBySource = false;
79 _dataSourceID = UNKNOWN_NODE_ID;81 _dataSourceID = UNKNOWN_NODE_ID;
@@ -96,6 +98,8 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) · 16 unmodified lines
96 _writeVoxelDirtyArray = NULL;98 _writeVoxelDirtyArray = NULL;
97 _readVoxelDirtyArray = NULL;99 _readVoxelDirtyArray = NULL;
98 100
101 _inSetupNewVoxelsForDrawing = false;
102 _useFastVoxelPipeline = false;
99}103}
100 104
101void VoxelSystem::voxelDeleted(VoxelNode* node) {105void VoxelSystem::voxelDeleted(VoxelNode* node) {
@@ -104,6 +108,61 @@ void VoxelSystem::voxelDeleted(VoxelNode* node) { · 2 unmodified lines
104 }108 }
105}109}
106 110
111void VoxelSystem::setUseFastVoxelPipeline(bool useFastVoxelPipeline) {
112 _useFastVoxelPipeline = useFastVoxelPipeline;
113 printf("setUseFastVoxelPipeline() _useFastVoxelPipeline=%s\n", debug::valueOf(_useFastVoxelPipeline));
114}
115
116void VoxelSystem::voxelUpdated(VoxelNode* node) {
117
118 //printf("VoxelSystem::voxelUpdated() _useFastVoxelPipeline=%s\n", debug::valueOf(_useFastVoxelPipeline));
119
120 // If we're in SetupNewVoxelsForDrawing() or _writeRenderFullVBO then bail..
121 if (!_useFastVoxelPipeline || _inSetupNewVoxelsForDrawing || _writeRenderFullVBO) {
122 return;
123 }
124
125 if (node->getVoxelSystem() == this) {
126 //printf("VoxelSystem::voxelUpdated()... node->getVoxelSystem() == this\n");
127
128 bool shouldRender = false; // assume we don't need to render it
129 // if it's colored, we might need to render it!
130 shouldRender = node->calculateShouldRender(_viewFrustum);
131
132 node->setShouldRender(shouldRender);
133
134 //printf("VoxelSystem::voxelUpdated() shouldRender=%s\n", debug::valueOf(shouldRender));
135
136 if (!node->isLeaf()) {
137
138 // As we check our children, see if any of them went from shouldRender to NOT shouldRender
139 // then we probably dropped LOD and if we don't have color, we want to average our children
140 // for a new color.
141 int childrenGotHiddenCount = 0;
142 for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
143 VoxelNode* childNode = node->getChildAtIndex(i);
144 if (childNode) {
145 bool wasShouldRender = childNode->getShouldRender();
146 bool isShouldRender = childNode->calculateShouldRender(_viewFrustum);
147 if (wasShouldRender && !isShouldRender) {
148 childrenGotHiddenCount++;
149 }
150 }
151 }
152 if (childrenGotHiddenCount > 0) {
153 node->setColorFromAverageOfChildren();
154 }
155 }
156
157 updateNodeInArraysAsPartialVBO(node);
158 _voxelsUpdated++;
159
160 node->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.
161
162 setupNewVoxelsForDrawingSingleNode();
163 }
164}
165
107// returns an available index, starts by reusing a previously freed index, but if there isn't one available166// returns an available index, starts by reusing a previously freed index, but if there isn't one available
108// it will use the end of the VBO array and grow our accounting of that array.167// it will use the end of the VBO array and grow our accounting of that array.
109// and makes the index available for some other node to use168// and makes the index available for some other node to use
@@ -147,6 +206,7 @@ VoxelSystem::~VoxelSystem() { · 37 unmodified lines
147 pthread_mutex_destroy(&_treeLock);206 pthread_mutex_destroy(&_treeLock);
148 207
149 VoxelNode::removeDeleteHook(this);208 VoxelNode::removeDeleteHook(this);
209 VoxelNode::removeUpdateHook(this);
150}210}
151 211
152void VoxelSystem::setMaxVoxels(int maxVoxels) {212void VoxelSystem::setMaxVoxels(int maxVoxels) {
@@ -462,7 +522,11 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 309 unmodified lines
462 break;522 break;
463 }523 }
464 524
465 setupNewVoxelsForDrawing();525 //printf("VoxelSystem::parseData() _useFastVoxelPipeline=%s\n", debug::valueOf(_useFastVoxelPipeline));
526
527 if (!_useFastVoxelPipeline || _writeRenderFullVBO) {
528 setupNewVoxelsForDrawing();
529 }
466 530
467 pthread_mutex_unlock(&_treeLock);531 pthread_mutex_unlock(&_treeLock);
468 532
@@ -474,6 +538,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 5 unmodified lines
474void VoxelSystem::setupNewVoxelsForDrawing() {538void VoxelSystem::setupNewVoxelsForDrawing() {
475 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),539 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
476 "setupNewVoxelsForDrawing()"); // would like to include _voxelsInArrays, _voxelsUpdated540 "setupNewVoxelsForDrawing()"); // would like to include _voxelsInArrays, _voxelsUpdated
541 _inSetupNewVoxelsForDrawing = true;
477 uint64_t start = usecTimestampNow();542 uint64_t start = usecTimestampNow();
478 uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000;543 uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000;
479 544
@@ -547,12 +612,92 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 67 unmodified lines
547 int elapsedmsec = (end - start) / 1000;612 int elapsedmsec = (end - start) / 1000;
548 _setupNewVoxelsForDrawingLastFinished = end;613 _setupNewVoxelsForDrawingLastFinished = end;
549 _setupNewVoxelsForDrawingLastElapsed = elapsedmsec;614 _setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
615 _inSetupNewVoxelsForDrawing = false;
550}616}
551 617
618void VoxelSystem::setupNewVoxelsForDrawingSingleNode() {
619 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
620 "setupNewVoxelsForDrawingSingleNode()"); // would like to include _voxelsInArrays, _voxelsUpdated
621 uint64_t start = usecTimestampNow();
622 uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000;
623
624 // clear up the VBOs for any nodes that have been recently deleted.
625 clearFreeBufferIndexes();
626
627 bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging
628 if (!iAmDebugging && sinceLastTime <= std::max((float) _setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) {
629 return; // bail early, it hasn't been long enough since the last time we ran
630 }
631
632 uint64_t sinceLastViewCulling = (start - _lastViewCulling) / 1000;
633 // If the view frustum is no longer changing, but has changed, since last time, then remove nodes that are out of view
634 if ((sinceLastViewCulling >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS))
635 && !isViewChanging()) {
636 _lastViewCulling = start;
637
638 // When we call removeOutOfView() voxels, we don't actually remove the voxels from the VBOs, but we do remove
639 // them from tree, this makes our tree caclulations faster, but doesn't require us to fully rebuild the VBOs (which
640 // can be expensive).
641 removeOutOfView();
642
643 // Once we call cleanupRemovedVoxels() we do need to rebuild our VBOs (if anything was actually removed). So,
644 // we should consider putting this someplace else... as this might be able to occur less frequently, and save us on
645 // VBO reubuilding. Possibly we should do this only if our actual VBO usage crosses some lower boundary.
646 cleanupRemovedVoxels();
647
648 uint64_t endViewCulling = usecTimestampNow();
649 _lastViewCullingElapsed = (endViewCulling - start) / 1000;
650 }
651
652 bool didWriteFullVBO = _writeRenderFullVBO;
653
654 if (_tree->isDirty()) {
655 static char buffer[64] = { 0 };
656 if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) {
657 sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", debug::valueOf(_writeRenderFullVBO));
658 };
659 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer);
660 _callsToTreesToArrays++;
661 if (_writeRenderFullVBO) {
662 _voxelsInWriteArrays = 0; // reset our VBO
663 _freeIndexes.clear(); // reset our free indexes
664 _voxelsUpdated = newTreeToArrays(_tree->rootNode);
665 _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean
666 _abandonedVBOSlots = 0; // reset the count of our abandoned slots, why is this here and not earlier????
667 }
668
669 // since we called treeToArrays, we can assume that our VBO is in sync, and so partial updates to the VBOs are
670 // ok again, until/unless we call removeOutOfView()
671 _writeRenderFullVBO = false;
672 } else {
673 _voxelsUpdated = 0;
674 }
675
676 // lock on the buffer write lock so we can't modify the data when the GPU is reading it
677 pthread_mutex_lock(&_bufferWriteLock);
678
679 if (_voxelsUpdated) {
680 _voxelsDirty=true;
681 }
682
683 // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated
684 copyWrittenDataToReadArrays(didWriteFullVBO);
685
686 // after...
687 _voxelsUpdated = 0;
688
689 pthread_mutex_unlock(&_bufferWriteLock);
690
691 uint64_t end = usecTimestampNow();
692 int elapsedmsec = (end - start) / 1000;
693 _setupNewVoxelsForDrawingLastFinished = end;
694 _setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
695}
552void VoxelSystem::cleanupRemovedVoxels() {696void VoxelSystem::cleanupRemovedVoxels() {
553 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "cleanupRemovedVoxels()");697 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "cleanupRemovedVoxels()");
554 // This handles cleanup of voxels that were culled as part of our regular out of view culling operation698 // This handles cleanup of voxels that were culled as part of our regular out of view culling operation
555 if (!_removedVoxels.isEmpty()) {699 if (!_removedVoxels.isEmpty()) {
700 qDebug() << "cleanupRemovedVoxels().. _removedVoxels=" << _removedVoxels.count() << "\n";
556 while (!_removedVoxels.isEmpty()) {701 while (!_removedVoxels.isEmpty()) {
557 delete _removedVoxels.extract();702 delete _removedVoxels.extract();
558 }703 }
@@ -560,8 +705,9 @@ void VoxelSystem::cleanupRemovedVoxels() { · 1 unmodified line
560 }705 }
561 // we also might have VBO slots that have been abandoned, if too many of our VBO slots706 // we also might have VBO slots that have been abandoned, if too many of our VBO slots
562 // are abandonded we want to rerender our full VBOs707 // are abandonded we want to rerender our full VBOs
563 const float TOO_MANY_ABANDONED_RATIO = 0.25f;708 const float TOO_MANY_ABANDONED_RATIO = 0.5f;
564 if (!_writeRenderFullVBO && (_abandonedVBOSlots > (_voxelsInWriteArrays * TOO_MANY_ABANDONED_RATIO))) {709 if (!_writeRenderFullVBO && (_abandonedVBOSlots > (_voxelsInWriteArrays * TOO_MANY_ABANDONED_RATIO))) {
710 qDebug() << "cleanupRemovedVoxels().. _abandonedVBOSlots ["<< _abandonedVBOSlots << "] > TOO_MANY_ABANDONED_RATIO \n";
565 _writeRenderFullVBO = true;711 _writeRenderFullVBO = true;
566 }712 }
567}713}
@@ -704,7 +850,7 @@ int VoxelSystem::updateNodeInArraysAsFullVBO(VoxelNode* node) { · 136 unmodified lines
704 return 1; // rendered850 return 1; // rendered
705 } else {851 } else {
706 node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);852 node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
707 node->setVoxelSystem(NULL);853 //node->setVoxelSystem(NULL);
708 }854 }
709 855
710 return 0; // not-rendered856 return 0; // not-rendered
@@ -805,6 +951,9 @@ void VoxelSystem::init() { · 94 unmodified lines
805 // VBO for the verticesArray951 // VBO for the verticesArray
806 initVoxelMemory();952 initVoxelMemory();
807 _initialized = true;953 _initialized = true;
954
955 // our own _removedVoxels doesn't need to be notified of voxel deletes
956 VoxelNode::removeDeleteHook(&_removedVoxels);
808}957}
809 958
810void VoxelSystem::changeTree(VoxelTree* newTree) {959void VoxelSystem::changeTree(VoxelTree* newTree) {
@@ -812,6 +961,7 @@ void VoxelSystem::changeTree(VoxelTree* newTree) { · 1 unmodified line
812 961
813 _tree = newTree;962 _tree = newTree;
814 _tree->setDirtyBit();963 _tree->setDirtyBit();
964 _tree->rootNode->setVoxelSystem(this);
815 965
816 connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float)));966 connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float)));
817 connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int)));967 connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int)));

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t