From 80170bd4c40c1548352c49e25dd02336c66de5fc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 29 Mar 2013 03:12:11 -0700 Subject: [PATCH] don't do gross things if data is being written while GPU is copying it --- interface/src/VoxelSystem.cpp | 99 ++++++++++++++++++++--------------- interface/src/VoxelSystem.h | 13 +++-- 2 files changed, 65 insertions(+), 47 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 14f75d7e0a..6d81207531 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -39,12 +39,16 @@ GLubyte identityIndices[] = { 0,1,2, 0,2,3, VoxelSystem::VoxelSystem() { voxelsRendered = 0; tree = new VoxelTree(); + pthread_mutex_init(&bufferWriteLock, NULL); } VoxelSystem::~VoxelSystem() { - delete[] verticesArray; - delete[] colorsArray; + delete[] readVerticesArray; + delete[] writeVerticesArray; + delete[] readColorsArray; + delete[] writeColorsArray; delete tree; + pthread_mutex_destroy(&bufferWriteLock); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -57,14 +61,8 @@ VoxelSystem::~VoxelSystem() { void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { tree->loadVoxelsFile(fileName,wantColorRandomizer); - - // reset the verticesEndPointer so we're writing to the beginning of the array - verticesEndPointer = verticesArray; - // call recursive function to populate in memory arrays - // it will return the number of voxels added - voxelsRendered = treeToArrays(tree->rootNode); - // set the boolean if there are any voxels to be rendered so we re-fill the VBOs - voxelsToRender = (voxelsRendered > 0); + + copyWrittenDataToReadArrays(); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -77,14 +75,7 @@ void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) { tree->createSphere(r,xc,yc,zc,s,solid,wantColorRandomizer); - - // reset the verticesEndPointer so we're writing to the beginning of the array - verticesEndPointer = verticesArray; - // call recursive function to populate in memory arrays - // it will return the number of voxels added - voxelsRendered = treeToArrays(tree->rootNode); - // set the boolean if there are any voxels to be rendered so we re-fill the VBOs - voxelsToRender = (voxelsRendered > 0); + setupNewVoxelsForDrawing(); } @@ -95,20 +86,32 @@ void VoxelSystem::parseData(void *data, int size) { // ask the VoxelTree to read the bitstream into the tree tree->readBitstreamToTree(voxelData, size - 1); + setupNewVoxelsForDrawing(); +} + +void VoxelSystem::setupNewVoxelsForDrawing() { // reset the verticesEndPointer so we're writing to the beginning of the array - verticesEndPointer = verticesArray; - + writeVerticesEndPointer = writeVerticesArray; // call recursive function to populate in memory arrays // it will return the number of voxels added - int newVoxels = treeToArrays(tree->rootNode); + voxelsRendered = treeToArrays(tree->rootNode); - if (newVoxels > voxelsRendered) { - - voxelsRendered = newVoxels; - - // set the boolean if there are any voxels to be rendered so we re-fill the VBOs - voxelsToRender = true; - } + // copy the newly written data to the arrays designated for reading + copyWrittenDataToReadArrays(); +} + +void VoxelSystem::copyWrittenDataToReadArrays() { + // lock on the buffer write lock so we can't modify the data when the GPU is reading it + pthread_mutex_lock(&bufferWriteLock); + // store a pointer to the current end so it doesn't change during copy + GLfloat *endOfCurrentVerticesData = writeVerticesEndPointer; + // copy the vertices and colors + memcpy(readVerticesArray, writeVerticesArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLfloat)); + memcpy(readColorsArray, writeColorsArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLubyte)); + + // set the read vertices end pointer to the correct spot so the GPU knows how much to pull + readVerticesEndPointer = readVerticesArray + (endOfCurrentVerticesData - writeVerticesArray); + pthread_mutex_unlock(&bufferWriteLock); } int VoxelSystem::treeToArrays(VoxelNode *currentNode) { @@ -130,10 +133,10 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode) { // populate the array with points for the 8 vertices // and RGB color for each added vertex for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { - *verticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); - *(colorsArray + (verticesEndPointer - verticesArray)) = currentNode->color[j % 3]; + *writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); + *(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->color[j % 3]; - verticesEndPointer++; + writeVerticesEndPointer++; } voxelsAdded++; @@ -151,8 +154,10 @@ VoxelSystem* VoxelSystem::clone() const { void VoxelSystem::init() { // prep the data structures for incoming voxel data - verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; - colorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; @@ -195,16 +200,24 @@ void VoxelSystem::render() { glPushMatrix(); - if (voxelsToRender) { - glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); - glBufferSubData(GL_ARRAY_BUFFER, 0, (verticesEndPointer - verticesArray) * sizeof(GLfloat), verticesArray); - - glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); - glBufferSubData(GL_ARRAY_BUFFER, 0, (verticesEndPointer - verticesArray) * sizeof(GLubyte), colorsArray); - - voxelsToRender = false; + + if (readVerticesEndPointer != readVerticesArray) { + // try to lock on the buffer write + // just avoid pulling new data if it is currently being written + if (pthread_mutex_trylock(&bufferWriteLock) == 0) { + + glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLfloat), readVerticesArray); + + glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLubyte), readColorsArray); + + readVerticesEndPointer = readVerticesArray; + + pthread_mutex_unlock(&bufferWriteLock); + } } // tell OpenGL where to find vertex and color information diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 1bfd4c185e..20f7965760 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -38,15 +38,20 @@ public: private: int voxelsRendered; VoxelTree *tree; - bool voxelsToRender; - GLfloat *verticesArray; - GLubyte *colorsArray; - GLfloat *verticesEndPointer; + GLfloat *readVerticesArray; + GLubyte *readColorsArray; + GLfloat *readVerticesEndPointer; + GLfloat *writeVerticesArray; + GLubyte *writeColorsArray; + GLfloat *writeVerticesEndPointer; GLuint vboVerticesID; GLuint vboColorsID; GLuint vboIndicesID; + pthread_mutex_t bufferWriteLock; int treeToArrays(VoxelNode *currentNode); + void setupNewVoxelsForDrawing(); + void copyWrittenDataToReadArrays(); }; #endif