From 274690f79098763dcbb5a4849f8fefa269313327 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 6 Mar 2017 20:22:30 +0100 Subject: [PATCH] Refactor BufferCache to allow caching buffers of different sizes --- components/terrain/buffercache.cpp | 34 +++++++++++++++--------------- components/terrain/buffercache.hpp | 10 +++------ components/terrain/terraingrid.cpp | 7 +++--- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/components/terrain/buffercache.cpp b/components/terrain/buffercache.cpp index 3bf5d56516..4706555397 100644 --- a/components/terrain/buffercache.cpp +++ b/components/terrain/buffercache.cpp @@ -178,56 +178,56 @@ osg::ref_ptr createIndexBuffer(unsigned int flags, unsigned int namespace Terrain { - osg::ref_ptr BufferCache::getUVBuffer() + osg::ref_ptr BufferCache::getUVBuffer(unsigned int numVerts) { OpenThreads::ScopedLock lock(mUvBufferMutex); - if (mUvBufferMap.find(mNumVerts) != mUvBufferMap.end()) + if (mUvBufferMap.find(numVerts) != mUvBufferMap.end()) { - return mUvBufferMap[mNumVerts]; + return mUvBufferMap[numVerts]; } - int vertexCount = mNumVerts * mNumVerts; + int vertexCount = numVerts * numVerts; osg::ref_ptr uvs (new osg::Vec2Array); uvs->reserve(vertexCount); - for (unsigned int col = 0; col < mNumVerts; ++col) + for (unsigned int col = 0; col < numVerts; ++col) { - for (unsigned int row = 0; row < mNumVerts; ++row) + for (unsigned int row = 0; row < numVerts; ++row) { - uvs->push_back(osg::Vec2f(col / static_cast(mNumVerts-1), - ((mNumVerts-1) - row) / static_cast(mNumVerts-1))); + uvs->push_back(osg::Vec2f(col / static_cast(numVerts-1), + ((numVerts-1) - row) / static_cast(numVerts-1))); } } // Assign a VBO here to enable state sharing between different Geometries. uvs->setVertexBufferObject(new osg::VertexBufferObject); - mUvBufferMap[mNumVerts] = uvs; + mUvBufferMap[numVerts] = uvs; return uvs; } - osg::ref_ptr BufferCache::getIndexBuffer(unsigned int flags) + osg::ref_ptr BufferCache::getIndexBuffer(unsigned int numVerts, unsigned int flags) { + std::pair id = std::make_pair(numVerts, flags); OpenThreads::ScopedLock lock(mIndexBufferMutex); - unsigned int verts = mNumVerts; - if (mIndexBufferMap.find(flags) != mIndexBufferMap.end()) + if (mIndexBufferMap.find(id) != mIndexBufferMap.end()) { - return mIndexBufferMap[flags]; + return mIndexBufferMap[id]; } osg::ref_ptr buffer; - if (verts*verts <= (0xffffu)) - buffer = createIndexBuffer(flags, verts); + if (numVerts*numVerts <= (0xffffu)) + buffer = createIndexBuffer(flags, numVerts); else - buffer = createIndexBuffer(flags, verts); + buffer = createIndexBuffer(flags, numVerts); // Assign a EBO here to enable state sharing between different Geometries. buffer->setElementBufferObject(new osg::ElementBufferObject); - mIndexBufferMap[flags] = buffer; + mIndexBufferMap[id] = buffer; return buffer; } diff --git a/components/terrain/buffercache.hpp b/components/terrain/buffercache.hpp index 172b9d6724..e8963354ba 100644 --- a/components/terrain/buffercache.hpp +++ b/components/terrain/buffercache.hpp @@ -14,28 +14,24 @@ namespace Terrain class BufferCache { public: - BufferCache(unsigned int numVerts) : mNumVerts(numVerts) {} - /// @param flags first 4*4 bits are LOD deltas on each edge, respectively (4 bits each) /// next 4 bits are LOD level of the index buffer (LOD 0 = don't omit any vertices) /// @note Thread safe. - osg::ref_ptr getIndexBuffer (unsigned int flags); + osg::ref_ptr getIndexBuffer (unsigned int numVerts, unsigned int flags); /// @note Thread safe. - osg::ref_ptr getUVBuffer(); + osg::ref_ptr getUVBuffer(unsigned int numVerts); // TODO: add releaseGLObjects() for our vertex/element buffer objects private: // Index buffers are shared across terrain batches where possible. There is one index buffer for each // combination of LOD deltas and index buffer LOD we may need. - std::map > mIndexBufferMap; + std::map, osg::ref_ptr > mIndexBufferMap; OpenThreads::Mutex mIndexBufferMutex; std::map > mUvBufferMap; OpenThreads::Mutex mUvBufferMutex; - - unsigned int mNumVerts; }; } diff --git a/components/terrain/terraingrid.cpp b/components/terrain/terraingrid.cpp index ffb30c04ab..7a8307043d 100644 --- a/components/terrain/terraingrid.cpp +++ b/components/terrain/terraingrid.cpp @@ -51,7 +51,6 @@ namespace Terrain TerrainGrid::TerrainGrid(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUtil::IncrementalCompileOperation* ico, Storage* storage, int nodeMask, Shader::ShaderManager* shaderManager, SceneUtil::UnrefQueue* unrefQueue) : Terrain::World(parent, resourceSystem, ico, storage, nodeMask) , mNumSplits(4) - , mCache((storage->getCellVertices()-1)/static_cast(mNumSplits) + 1) , mUnrefQueue(unrefQueue) , mShaderManager(shaderManager) { @@ -130,7 +129,9 @@ osg::ref_ptr TerrainGrid::buildTerrain (osg::Group* parent, float chu geometry->setUseDisplayList(false); geometry->setUseVertexBufferObjects(true); - geometry->addPrimitiveSet(mCache.getIndexBuffer(0)); + unsigned int numVerts = (mStorage->getCellVertices()-1) * chunkSize + 1; + + geometry->addPrimitiveSet(mCache.getIndexBuffer(numVerts, 0)); // we already know the bounding box, so no need to let OSG compute it. osg::Vec3f min(-0.5f*mStorage->getCellWorldSize()*chunkSize, @@ -184,7 +185,7 @@ osg::ref_ptr TerrainGrid::buildTerrain (osg::Group* parent, float chu // use texture coordinates for both texture units, the layer texture and blend texture for (unsigned int i=0; i<2; ++i) - geometry->setTexCoordArray(i, mCache.getUVBuffer()); + geometry->setTexCoordArray(i, mCache.getUVBuffer(numVerts)); float blendmapScale = ESM::Land::LAND_TEXTURE_SIZE*chunkSize;