Changed std::map to boost::unordered_map for storing memory chunks and groups information.

This commit is contained in:
Maciej Suminski 2013-07-01 13:20:48 +02:00
parent 00847a8aed
commit a73216fc95
4 changed files with 53 additions and 30 deletions

View File

@ -26,8 +26,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <cmath>
#include <gal/opengl/opengl_gal.h> #include <gal/opengl/opengl_gal.h>
#include <gal/opengl/vbo_container.h> #include <gal/opengl/vbo_container.h>
#include <gal/definitions.h> #include <gal/definitions.h>
@ -39,6 +37,7 @@
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
#include <limits> #include <limits>
#include <boost/foreach.hpp>
#ifndef CALLBACK #ifndef CALLBACK
#define CALLBACK #define CALLBACK
@ -82,7 +81,6 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
groupCounter = 0; groupCounter = 0;
transform = glm::mat4( 1.0f ); // Identity matrix transform = glm::mat4( 1.0f ); // Identity matrix
SetSize( parentSize ); SetSize( parentSize );
screenSize.x = parentSize.x; screenSize.x = parentSize.x;
@ -1606,10 +1604,9 @@ void OPENGL_GAL::EndGroup()
void OPENGL_GAL::ClearCache() void OPENGL_GAL::ClearCache()
{ {
std::map<unsigned int, VBO_ITEM*>::iterator it, end; BOOST_FOREACH( GroupsMap::value_type it, groups )
for( it = groups.begin(), end = groups.end(); it != end; it++ )
{ {
delete it->second; delete it.second;
} }
groups.clear(); groups.clear();

View File

@ -30,6 +30,7 @@
#include <gal/opengl/vbo_container.h> #include <gal/opengl/vbo_container.h>
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#include <boost/foreach.hpp>
#include <wx/log.h> #include <wx/log.h>
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
#include <profile.h> #include <profile.h>
@ -38,7 +39,8 @@
using namespace KiGfx; using namespace KiGfx;
VBO_CONTAINER::VBO_CONTAINER( int aSize ) : VBO_CONTAINER::VBO_CONTAINER( int aSize ) :
m_freeSpace( aSize ), m_currentSize( aSize ), itemStarted( false ), m_transform( NULL ) m_freeSpace( aSize ), m_currentSize( aSize ), itemStarted( false ), m_transform( NULL ),
m_failed( false )
{ {
// By default no shader is used // By default no shader is used
m_shader[0] = 0; m_shader[0] = 0;
@ -82,6 +84,7 @@ void VBO_CONTAINER::EndItem()
m_freeSpace += ( itemChunkSize - itemSize ); m_freeSpace += ( itemChunkSize - itemSize );
} }
item = NULL;
itemStarted = false; itemStarted = false;
} }
@ -91,6 +94,9 @@ void VBO_CONTAINER::Add( VBO_ITEM* aVboItem, const VBO_VERTEX* aVertex, unsigned
unsigned int offset; unsigned int offset;
VBO_VERTEX* vertexPtr; VBO_VERTEX* vertexPtr;
if( m_failed )
return;
if( itemStarted ) // There is an item being created with an unknown size.. if( itemStarted ) // There is an item being created with an unknown size..
{ {
unsigned int itemChunkOffset; unsigned int itemChunkOffset;
@ -98,27 +104,34 @@ void VBO_CONTAINER::Add( VBO_ITEM* aVboItem, const VBO_VERTEX* aVertex, unsigned
// ..and unfortunately does not fit into currently reserved chunk // ..and unfortunately does not fit into currently reserved chunk
if( itemSize + aSize > itemChunkSize ) if( itemSize + aSize > itemChunkSize )
{ {
// Find the previous chunk for the item, save it, so it can be removed later // Find the previous chunk for the item and change mark it as NULL
// so it will not be removed during a possible defragmentation
ReservedChunkMap::iterator it = m_reservedChunks.find( item ); ReservedChunkMap::iterator it = m_reservedChunks.find( item );
m_reservedChunks.insert( ReservedChunk( static_cast<VBO_ITEM*>( NULL ), it->second ) );
m_reservedChunks.erase( it );
// Reserve bigger memory for the current item // Reserve bigger memory fo r the current item
int newSize = ( 2 * itemSize ) + aSize; int newSize = ( 2 * itemSize ) + aSize;
itemChunkOffset = allocate( aVboItem, newSize ); itemChunkOffset = allocate( aVboItem, newSize );
aVboItem->SetOffset( itemChunkOffset );
// Check if there was no error // Check if there was no error
if( itemChunkOffset > m_currentSize ) if( itemChunkOffset > m_currentSize )
{
m_failed = true;
return; return;
}
// Save previous chunk's offset for copying data it = m_reservedChunks.find( static_cast<VBO_ITEM*>( NULL ) );
// Check if the chunk was not reallocated after defragmentation
int oldItemChunkOffset = getChunkOffset( *it ); int oldItemChunkOffset = getChunkOffset( *it );
// Free the space previously used by the chunk
freeChunk( it );
// Copy all the old data // Copy all the old data
memcpy( &m_vertices[itemChunkOffset], &m_vertices[oldItemChunkOffset], memcpy( &m_vertices[itemChunkOffset], &m_vertices[oldItemChunkOffset],
itemSize * VBO_ITEM::VertByteSize ); itemSize * VBO_ITEM::VertByteSize );
// Return memory used by the previous chunk
freeChunk( it );
itemChunkSize = newSize; itemChunkSize = newSize;
} }
else else
@ -310,7 +323,8 @@ bool VBO_CONTAINER::defragment( VBO_VERTEX* aTarget )
memcpy( &aTarget[newOffset], &m_vertices[itemOffset], itemSize * VBO_ITEM::VertByteSize ); memcpy( &aTarget[newOffset], &m_vertices[itemOffset], itemSize * VBO_ITEM::VertByteSize );
// Update new offset // Update new offset
vboItem->SetOffset( newOffset ); if( vboItem )
vboItem->SetOffset( newOffset );
setChunkOffset( *it, newOffset ); setChunkOffset( *it, newOffset );
// Move to the next free space // Move to the next free space
@ -349,26 +363,32 @@ void VBO_CONTAINER::resizeChunk( VBO_ITEM* aVboItem, int aNewSize )
bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize ) bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
{ {
unsigned int copySize; VBO_VERTEX* newContainer;
if( aNewSize < m_currentSize ) if( aNewSize < m_currentSize )
{ {
// Sanity check, no shrinking if we cannot fit all the data // Sanity check, no shrinking if we cannot fit all the data
if( ( m_currentSize - m_freeSpace ) > aNewSize ) if( ( m_currentSize - m_freeSpace ) > aNewSize )
return false; return false;
defragment(); newContainer = static_cast<VBO_VERTEX*>( malloc( aNewSize * sizeof( VBO_VERTEX ) ) );
copySize = ( m_currentSize - m_freeSpace ); if( newContainer == NULL )
{
wxLogError( wxT( "Run out of memory" ) );
return false;
}
// Defragment directly to the new, smaller container
defragment( newContainer );
} }
else else
{ {
copySize = m_currentSize; newContainer = static_cast<VBO_VERTEX*>( realloc( m_vertices, aNewSize * sizeof( VBO_VERTEX ) ) );
} if( newContainer == NULL )
{
VBO_VERTEX* newContainer = static_cast<VBO_VERTEX*>( realloc( m_vertices, aNewSize * sizeof( VBO_VERTEX ) ) ); wxLogError( wxT( "Run out of memory" ) );
if( newContainer == NULL ) return false;
{ }
wxLogError( wxT( "Run out of memory" ) );
return false;
} }
m_vertices = newContainer; m_vertices = newContainer;

View File

@ -49,6 +49,7 @@
#include <iterator> #include <iterator>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <boost/unordered_map.hpp>
#include <stdlib.h> #include <stdlib.h>
#include <iostream> #include <iostream>
@ -355,7 +356,8 @@ private:
GLuint displayListSemiCircle; ///< Semi circle display list GLuint displayListSemiCircle; ///< Semi circle display list
// Vertex buffer objects related fields // Vertex buffer objects related fields
std::map<unsigned int, VBO_ITEM*> groups; ///< Stores informations about VBO objects (groups) typedef boost::unordered_map<unsigned int, VBO_ITEM*> GroupsMap;
GroupsMap groups; ///< Stores informations about VBO objects (groups)
unsigned int groupCounter; ///< Counter used for generating keys for groups unsigned int groupCounter; ///< Counter used for generating keys for groups
VBO_ITEM* currentGroup; ///< Currently used VBO_ITEM (for grouping) VBO_ITEM* currentGroup; ///< Currently used VBO_ITEM (for grouping)
VBO_CONTAINER* vboContainer; ///< Container for storing VBO_ITEMs VBO_CONTAINER* vboContainer; ///< Container for storing VBO_ITEMs
@ -559,7 +561,7 @@ private:
if( isGrouping ) if( isGrouping )
{ {
// New vertex coordinates for VBO // New vertex coordinates for VBO
VBO_VERTEX vertex = { aX, aY, aZ }; const VBO_VERTEX vertex = { aX, aY, aZ };
currentGroup->PushVertex( &vertex ); currentGroup->PushVertex( &vertex );
} }
else else

View File

@ -35,6 +35,7 @@
#include <gal/opengl/vbo_item.h> #include <gal/opengl/vbo_item.h>
#include <gal/color4d.h> #include <gal/color4d.h>
#include <map> #include <map>
#include <boost/unordered_map.hpp>
#include <wx/log.h> #include <wx/log.h>
namespace KiGfx namespace KiGfx
@ -52,9 +53,9 @@ public:
typedef std::pair<const unsigned int, unsigned int> Chunk; typedef std::pair<const unsigned int, unsigned int> Chunk;
typedef std::multimap<const unsigned int, unsigned int> FreeChunkMap; typedef std::multimap<const unsigned int, unsigned int> FreeChunkMap;
///< Maps size of reserved memory chunks to their owners (VBO_ITEMs) ///< Maps VBO_ITEMs to reserved memory chunks offsets & sizes
typedef std::pair<VBO_ITEM* const, Chunk> ReservedChunk; typedef std::pair<VBO_ITEM* const, Chunk> ReservedChunk;
typedef std::multimap<VBO_ITEM* const, Chunk> ReservedChunkMap; typedef boost::unordered_map<VBO_ITEM* const, Chunk> ReservedChunkMap;
/** /**
* Function StartItem() * Function StartItem()
@ -115,7 +116,7 @@ public:
/** /**
* Function GetVertices() * Function GetVertices()
* Returns vertices stored at the specific offset. * Returns vertices stored at the specific offset.
* @aOffest is the specific offset. * @aOffset is the specific offset.
*/ */
inline VBO_VERTEX* GetVertices( unsigned int aOffset ) const inline VBO_VERTEX* GetVertices( unsigned int aOffset ) const
{ {
@ -326,6 +327,9 @@ private:
///< Current transform matrix applied for every new vertex pushed. ///< Current transform matrix applied for every new vertex pushed.
const glm::mat4* m_transform; const glm::mat4* m_transform;
///< Failure flag
bool m_failed;
/** /**
* Function getPowerOf2() * Function getPowerOf2()
* Returns the nearest power of 2, bigger than aNumber. * Returns the nearest power of 2, bigger than aNumber.