More work on partial VBO updates still not working 100% correctly

This commit is contained in:
ZappoMan 2013-05-09 14:04:08 -07:00
parent a08d89a074
commit f490f3ed53
3 changed files with 165 additions and 8 deletions

View file

@ -422,22 +422,29 @@ void VoxelSystem::updateFullVBOs() {
GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
// consider the _voxelDirtyArray[] clean!
memset(_voxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool));
}
void VoxelSystem::updatePartialVBOs() {
int segmentCount = 0;
glBufferIndex segmentStart = 0;
glBufferIndex segmentEnd = 0;
bool inSegment = false;
for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {
bool thisVoxelDirty = _voxelDirtyArray[i];
if (!inSegment) {
if (_voxelDirtyArray[i]) {
if (thisVoxelDirty) {
segmentStart = i;
inSegment = true;
_voxelDirtyArray[i] = false; // consider us clean!
}
} else {
if (!_voxelDirtyArray[i] || (i == (_voxelsInWriteArrays - 1)) ) {
segmentEnd = i;
if (!thisVoxelDirty) {
// If we got here because because this voxel is NOT dirty, so the last dirty voxel was the one before
// this one and so that's where the "segment" ends
segmentEnd = i - 1;
inSegment = false;
int segmentLength = (segmentEnd - segmentStart) + 1;
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
@ -450,9 +457,113 @@ void VoxelSystem::updatePartialVBOs() {
GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
// debug
segmentCount++;
printLog("updatePartialVBOs() start=%ld, end=%ld, length=%ld, segmentCount=%d \n",
segmentStart, segmentEnd, segmentLength, segmentCount);
}
_voxelDirtyArray[i] = false; // consider us clean!
}
}
// if we got to the end of the array, and we're in an active dirty segment...
if (inSegment) {
segmentEnd = _voxelsInWriteArrays - 1;
inSegment = false;
int segmentLength = (segmentEnd - segmentStart) + 1;
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);
segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
// debug
segmentCount++;
printLog("updatePartialVBOs() start=%ld, end=%ld, length=%ld, segmentCount=%d \n",
segmentStart, segmentEnd, segmentLength, segmentCount);
}
}
void debugOpenGLError(const char* label) {
GLenum error = glGetError();
const char* errorMessage;
switch (error) {
case GL_NO_ERROR:
return;
case GL_INVALID_ENUM:
errorMessage = "GL_INVALID_ENUM";
break;
case GL_INVALID_VALUE:
errorMessage = "GL_INVALID_VALUE";
break;
case GL_INVALID_OPERATION:
errorMessage = "GL_INVALID_OPERATION";
break;
case GL_STACK_OVERFLOW:
errorMessage = "GL_STACK_OVERFLOW";
break;
case GL_STACK_UNDERFLOW:
errorMessage = "GL_STACK_UNDERFLOW";
break;
case GL_OUT_OF_MEMORY:
errorMessage = "GL_OUT_OF_MEMORY";
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
errorMessage = "GL_INVALID_FRAMEBUFFER_OPERATION";
break;
}
printLog("%s generated %s", label, errorMessage);
}
void VoxelSystem::updateJustEnoughVBOs() {
bool somethingDirty = false;
glBufferIndex minDirty = GLBUFFER_INDEX_UNKNOWN;
glBufferIndex maxDirty = 0;
for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {
if (_voxelDirtyArray[i]) {
somethingDirty = true;
minDirty = std::min(minDirty,i);
maxDirty = std::max(maxDirty,i);
_voxelDirtyArray[i] = false;
}
}
if (somethingDirty) {
glBufferIndex segmentStart = minDirty;
glBufferIndex segmentEnd = maxDirty;
glGetError(); // clear errors
int segmentLength = (segmentEnd - segmentStart) + 1;
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
debugOpenGLError("glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID)");
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);
debugOpenGLError("glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom)");
segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
debugOpenGLError("glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID)");
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
debugOpenGLError("glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom)");
// debug
printLog("updateJustEnoughVBOs() start=%ld, end=%ld, length=%ld, \n", segmentStart, segmentEnd, segmentLength);
}
}
void VoxelSystem::updateVBOs() {
@ -463,10 +574,12 @@ void VoxelSystem::updateVBOs() {
PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays
if (_voxelsDirty) {
// updatePartialVBOs() is not yet working. For now, ALWAYS call updateFullVBOs()
if (true || _renderFullVBO) {
bool alwaysRenderFullVBO = true;
if (alwaysRenderFullVBO || _renderFullVBO) {
updateFullVBOs();
} else {
updatePartialVBOs();
updateJustEnoughVBOs();
//updatePartialVBOs(); // too many small segments?
}
_voxelsDirty = false;
}
@ -726,3 +839,34 @@ void VoxelSystem::removeOutOfView() {
);
}
}
class falseColorizeRandomEveryOtherArgs {
public:
falseColorizeRandomEveryOtherArgs() : totalNodes(0), colorableNodes(0), coloredNodes(0), colorThis(true) {};
unsigned long totalNodes;
unsigned long colorableNodes;
unsigned long coloredNodes;
bool colorThis;
};
bool VoxelSystem::falseColorizeRandomEveryOtherOperation(VoxelNode* node, void* extraData) {
falseColorizeRandomEveryOtherArgs* args = (falseColorizeRandomEveryOtherArgs*)extraData;
args->totalNodes++;
if (node->isColored()) {
args->colorableNodes++;
if (args->colorThis) {
args->coloredNodes++;
node->setFalseColor(255, randomColorValue(150), randomColorValue(150));
}
args->colorThis = !args->colorThis;
}
return true; // keep going!
}
void VoxelSystem::falseColorizeRandomEveryOther() {
falseColorizeRandomEveryOtherArgs args;
_tree->recurseTreeWithOperation(falseColorizeRandomEveryOtherOperation,&args);
printLog("randomized false color for every other node: total %ld, colorable %ld, colored %ld\n",
args.totalNodes, args.colorableNodes, args.coloredNodes);
setupNewVoxelsForDrawing();
}

View file

@ -56,6 +56,7 @@ public:
void trueColorize();
void falseColorizeInView(ViewFrustum* viewFrustum);
void falseColorizeDistanceFromView(ViewFrustum* viewFrustum);
void falseColorizeRandomEveryOther();
void killLocalVoxels();
void setRenderPipelineWarnings(bool on) { _renderWarningsOn = on; };
@ -78,6 +79,7 @@ private:
static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData);
static bool getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData);
static bool removeOutOfViewOperation(VoxelNode* node, void* extraData);
static bool falseColorizeRandomEveryOtherOperation(VoxelNode* node, void* extraData);
int updateNodeInArraysAsFullVBO(VoxelNode* node);
int updateNodeInArraysAsPartialVBO(VoxelNode* node);
@ -116,12 +118,15 @@ private:
ViewFrustum _lastKnowViewFrustum;
int newTreeToArrays(VoxelNode *currentNode);
void cleanupRemovedVoxels();
void setupNewVoxelsForDrawing();
void copyWrittenDataToReadArrays();
void updateVBOs();
void updateFullVBOs();
void updatePartialVBOs();
void cleanupRemovedVoxels();
void updateFullVBOs(); // all voxels in the VBO
void updatePartialVBOs(); // multiple segments, only dirty voxels
void updateJustEnoughVBOs(); // single segment from first dirty, to last dirty, may include clean voxels
bool _voxelsDirty;
};

View file

@ -1331,6 +1331,13 @@ int doRandomizeVoxelColors(int state) {
return state;
}
int doFalseRandomizeEveryOtherVoxelColors(int state) {
if (state == MENU_ROW_PICKED) {
::voxels.falseColorizeRandomEveryOther();
}
return state;
}
int doFalseRandomizeVoxelColors(int state) {
if (state == MENU_ROW_PICKED) {
::voxels.falseColorizeRandom();
@ -1427,6 +1434,7 @@ void initMenu() {
menuColumnDebug->addRow("Kill Local Voxels", doKillLocalVoxels);
menuColumnDebug->addRow("Randomize Voxel TRUE Colors", doRandomizeVoxelColors);
menuColumnDebug->addRow("FALSE Color Voxels Randomly", doFalseRandomizeVoxelColors);
menuColumnDebug->addRow("FALSE Color Voxel Every Other Randomly", doFalseRandomizeEveryOtherVoxelColors);
menuColumnDebug->addRow("FALSE Color Voxels by Distance", doFalseColorizeByDistance);
menuColumnDebug->addRow("FALSE Color Voxel Out of View", doFalseColorizeInView);
menuColumnDebug->addRow("Show TRUE Colors", doTrueVoxelColors);