Index: /trunk/nv/gfx/debug_draw.hh
===================================================================
--- /trunk/nv/gfx/debug_draw.hh	(revision 468)
+++ /trunk/nv/gfx/debug_draw.hh	(revision 469)
@@ -41,4 +41,6 @@
 		program             m_program;
 		vertex_array        m_va;
+		buffer              m_vb;
+		uint32              m_buffer_size;
 		vector< debug_vtx > m_data;
 	};
Index: /trunk/nv/interface/context.hh
===================================================================
--- /trunk/nv/interface/context.hh	(revision 468)
+++ /trunk/nv/interface/context.hh	(revision 469)
@@ -125,32 +125,32 @@
 
 		template < typename VTX, slot SLOT >
-		void add_vertex_buffer_impl( vertex_array, buffer, const false_type& )
+		void add_vertex_buffer_impl( vertex_array, buffer, bool, const false_type& )
 		{
 		}
 
 		template < typename VTX, slot SLOT >
-		void add_vertex_buffer_impl( vertex_array va, buffer vb, const true_type& )
+		void add_vertex_buffer_impl( vertex_array va, buffer vb, bool owned, const true_type& )
 		{
 			typedef slot_info< VTX, SLOT > vinfo;
 			typedef datatype_traits< typename vinfo::value_type > dt_traits;
-			add_vertex_buffer( va, SLOT, vb, type_to_enum< typename dt_traits::base_type >::type, dt_traits::size, vinfo::offset, sizeof( VTX ), false );
+			add_vertex_buffer( va, SLOT, vb, type_to_enum< typename dt_traits::base_type >::type, dt_traits::size, vinfo::offset, sizeof( VTX ), owned );
 		}
 
 		template < typename VTX, slot SLOT >
-		void add_vertex_buffer( vertex_array va, buffer vb )
-		{
-			add_vertex_buffer_impl< VTX, SLOT >( va, vb, has_slot< VTX, SLOT >() );
+		void add_vertex_buffer( vertex_array va, buffer vb, bool owned )
+		{
+			add_vertex_buffer_impl< VTX, SLOT >( va, vb, owned, has_slot< VTX, SLOT >() );
 		}
 
 		template < typename VTX >
-		void add_vertex_buffers( vertex_array va, buffer vb )
-		{
-			add_vertex_buffer< VTX, slot::POSITION >  ( va, vb );
-			add_vertex_buffer< VTX, slot::TEXCOORD >  ( va, vb );
-			add_vertex_buffer< VTX, slot::NORMAL   >  ( va, vb );
-			add_vertex_buffer< VTX, slot::TANGENT >   ( va, vb );
-			add_vertex_buffer< VTX, slot::BONEINDEX > ( va, vb );
-			add_vertex_buffer< VTX, slot::BONEWEIGHT >( va, vb );
-			add_vertex_buffer< VTX, slot::COLOR >     ( va, vb );
+		void add_vertex_buffers( vertex_array va, buffer vb, bool owned )
+		{
+			add_vertex_buffer< VTX, slot::POSITION >  ( va, vb, owned );
+			add_vertex_buffer< VTX, slot::TEXCOORD >  ( va, vb, owned );
+			add_vertex_buffer< VTX, slot::NORMAL   >  ( va, vb, owned );
+			add_vertex_buffer< VTX, slot::TANGENT >   ( va, vb, owned );
+			add_vertex_buffer< VTX, slot::BONEINDEX > ( va, vb, owned );
+			add_vertex_buffer< VTX, slot::BONEWEIGHT >( va, vb, owned );
+			add_vertex_buffer< VTX, slot::COLOR >     ( va, vb, owned );
 		}
 
@@ -182,8 +182,7 @@
 		vertex_array create_vertex_array( const VTX* v, size_t count, buffer_hint hint )
 		{
-			// TODO: vb will not be owned or freed!
 			vertex_array va = create_vertex_array();
 			buffer       vb = m_device->create_buffer( VERTEX_BUFFER, hint, count * sizeof( VTX ), v );
-			add_vertex_buffers< VTX >( va, vb );
+			add_vertex_buffers< VTX >( va, vb, true );
 			return va;
 		}
Index: /trunk/nv/stl/math/geometric.hh
===================================================================
--- /trunk/nv/stl/math/geometric.hh	(revision 468)
+++ /trunk/nv/stl/math/geometric.hh	(revision 469)
@@ -70,4 +70,10 @@
 		{
 			return sqrt( dot( v, v ) );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline value_type_t<T> length_sq( const T& v )
+		{
+			return dot( v, v );
 		}
 
Index: /trunk/nv/stl/string/short_string.hh
===================================================================
--- /trunk/nv/stl/string/short_string.hh	(revision 468)
+++ /trunk/nv/stl/string/short_string.hh	(revision 469)
@@ -95,5 +95,5 @@
 			char buffer[8];
 			size_t result = sint32_to_buffer( array_ref< char >( buffer ), s );
-			return ( result > 0 ? append( buffer.data(), result ) : 0 );
+			return ( result > 0 ? append( buffer, result ) : 0 );
 		}
 
Index: /trunk/nv/stl/utility/common.hh
===================================================================
--- /trunk/nv/stl/utility/common.hh	(revision 468)
+++ /trunk/nv/stl/utility/common.hh	(revision 469)
@@ -34,8 +34,21 @@
 
 	template < typename T >
+	inline const T&	max( const T& a, const T& b, const T& c )
+	{
+		return a < b ? (c < b ? b : c) : a;
+	}
+
+	template < typename T >
 	inline const T&	min( const T& a, const T& b )
 	{
 		return a > b ? b : a;
 	}
+
+	template < typename T >
+	inline const T&	min( const T& a, const T& b, const T& c )
+	{
+		return a > b ? ( c > b ? b : c ) : a;
+	}
+
 }
 
Index: /trunk/src/gfx/debug_draw.cc
===================================================================
--- /trunk/src/gfx/debug_draw.cc	(revision 468)
+++ /trunk/src/gfx/debug_draw.cc	(revision 469)
@@ -8,4 +8,5 @@
 
 #include "nv/interface/device.hh"
+#include "nv/core/logging.hh"
 
 static const char *nv_debug_draw_vertex_shader = R"(
@@ -34,10 +35,21 @@
 {
 	m_program = m_context->get_device()->create_program( nv_debug_draw_vertex_shader, nv_debug_draw_fragment_shader );
+	m_buffer_size = 0;
 }
 
 void nv::debug_data::update()
 {
-	m_context->release( m_va );
-	m_va = m_context->create_vertex_array( m_data, nv::STATIC_DRAW );
+	if ( !m_va.is_valid() || m_data.size() > m_buffer_size )
+	{
+		if ( m_va.is_valid() ) m_context->release( m_va );
+		m_buffer_size = nv::max( m_data.size(), 4096U, m_buffer_size );
+		m_va = m_context->create_vertex_array();
+		m_vb = m_context->get_device()->create_buffer( VERTEX_BUFFER, nv::STREAM_DRAW, m_buffer_size * sizeof( debug_vtx ), m_data.data() );
+		m_context->add_vertex_buffers< debug_vtx >( m_va, m_vb, true );
+	}
+	else
+	{
+		m_context->update( m_vb, m_data.data(), 0, m_data.size()* sizeof( debug_vtx ) );
+	}
 }
 
Index: /trunk/src/gl/gl_context.cc
===================================================================
--- /trunk/src/gl/gl_context.cc	(revision 468)
+++ /trunk/src/gl/gl_context.cc	(revision 469)
@@ -48,5 +48,6 @@
 		for ( uint32 i = 0; i < info->count; ++i )
 		{
-			if ( info->attr[i].owner ) m_device->release( info->attr[i].vbuffer );
+			if ( info->attr[i].owner ) 
+				m_device->release( info->attr[i].vbuffer );
 		}
 		if ( info->index.is_valid() && info->index_owner) m_device->release( info->index );
Index: /trunk/src/gui/gui_gfx_renderer.cc
===================================================================
--- /trunk/src/gui/gui_gfx_renderer.cc	(revision 468)
+++ /trunk/src/gui/gui_gfx_renderer.cc	(revision 469)
@@ -160,5 +160,5 @@
 	sr->varray = m_window->get_context()->create_vertex_array();
 	buffer vb = sr->buffer.get_buffer();
-	m_window->get_context()->add_vertex_buffers< vertex >( sr->varray, vb );
+	m_window->get_context()->add_vertex_buffers< vertex >( sr->varray, vb, false );
 
 	nv::sampler sampler( nv::sampler::LINEAR, nv::sampler::CLAMP_TO_EDGE );
