Index: trunk/src/gfx/keyframed_mesh.cc
===================================================================
--- trunk/src/gfx/keyframed_mesh.cc	(revision 406)
+++ trunk/src/gfx/keyframed_mesh.cc	(revision 410)
@@ -192,5 +192,5 @@
 	buffer  ib = m_context->get_device()->create_buffer( INDEX_BUFFER, STATIC_DRAW, m_mesh_data->get_index_channel()->size(), m_mesh_data->get_index_channel()->data );
 
-	m_context->set_index_buffer( m_va, ib, m_mesh_data->get_index_channel()->desc.slots[0].etype, true );
+	m_context->set_index_buffer( m_va, ib, m_mesh_data->get_index_channel()->desc[0].etype, true );
 
 	m_data = new uint8[ m_vertex_count * m_vsize ];
Index: trunk/src/gfx/mesh_creator.cc
===================================================================
--- trunk/src/gfx/mesh_creator.cc	(revision 406)
+++ trunk/src/gfx/mesh_creator.cc	(revision 410)
@@ -57,6 +57,6 @@
 			size_t chan_count = old_keys->get_channel_count();
 			if ( chan_count == 1 
-				&& old_keys->get_channel(0)->desc.count == 1 
-				&& old_keys->get_channel(0)->desc.slots[0].etype == TRANSFORM ) continue;
+				&& old_keys->get_channel(0)->desc.slot_count() == 1 
+				&& old_keys->get_channel(0)->desc[0].etype == TRANSFORM ) continue;
 
 			size_t max_keys = 0;
@@ -70,5 +70,5 @@
 			new_keys->add_channel( raw_channel );
 			nv_key_transform* channel = reinterpret_cast<nv_key_transform*>(raw_channel->data);
-			key_descriptor final_key = old_keys->get_final_key();
+			data_descriptor final_key = old_keys->get_final_key();
 
 			for ( unsigned n = 0; n < max_keys; ++n )
@@ -107,5 +107,5 @@
 			{
 				const key_raw_channel* channel = kdata->get_channel(c);
-				size_t key_size = channel->desc.size;
+				size_t key_size = channel->desc.element_size();
 				for ( size_t n = 0; n < channel->count; ++n )
 				{
@@ -126,16 +126,16 @@
 	{
 		const mesh_raw_channel* channel = m_data->get_channel(c);
-		const vertex_descriptor& desc   = channel->desc;
+		const data_descriptor&  desc    = channel->desc;
 		uint8* raw_data = channel->data;
-		uint32 vtx_size = desc.size;
+		uint32 vtx_size = desc.element_size();
 		int p_offset = -1;
 		int n_offset = -1;
 		int t_offset = -1;
-		for ( uint32 i = 0; i < desc.count; ++i )
-			switch ( desc.slots[i].vslot )
-			{
-				case slot::POSITION : if ( desc.slots[i].etype == FLOAT_VECTOR_3 ) p_offset = int(desc.slots[i].offset); break;
-				case slot::NORMAL   : if ( desc.slots[i].etype == FLOAT_VECTOR_3 ) n_offset = int(desc.slots[i].offset); break;
-				case slot::TANGENT  : if ( desc.slots[i].etype == FLOAT_VECTOR_4 ) t_offset = int(desc.slots[i].offset); break;
+		for ( const auto& cslot : desc  )
+			switch ( cslot.vslot )
+			{
+				case slot::POSITION : if ( cslot.etype == FLOAT_VECTOR_3 ) p_offset = int( cslot.offset ); break;
+				case slot::NORMAL   : if ( cslot.etype == FLOAT_VECTOR_3 ) n_offset = int( cslot.offset ); break;
+				case slot::TANGENT  : if ( cslot.etype == FLOAT_VECTOR_4 ) t_offset = int( cslot.offset ); break;
 				default             : break;
 			}
@@ -174,13 +174,13 @@
 	if ( ch_n == -1 ) return;
 	mesh_raw_channel* channel = m_data->m_channels[ unsigned( ch_n ) ];
-	for ( uint32 i = 0; i < channel->desc.count; ++i )
-		if ( channel->desc.slots[i].vslot == slot::NORMAL )
-		{
-			n_offset  = channel->desc.slots[i].offset; 
+	for ( const auto& cslot : channel->desc )
+		if ( cslot.vslot == slot::NORMAL )
+		{
+			n_offset  = cslot.offset;
 		}
 
 	for ( uint32 i = 0; i < channel->count; ++i )
 	{
-		vec3& normal = *reinterpret_cast<vec3*>( channel->data + channel->desc.size * i + n_offset );
+		vec3& normal = *reinterpret_cast<vec3*>( channel->data + channel->desc.element_size() * i + n_offset );
 		normal = -normal;
 	}
@@ -204,25 +204,27 @@
 	{
 		const mesh_raw_channel* channel = m_data->get_channel(c);
-		const vertex_descriptor& desc   = channel->desc;
-		for ( uint32 i = 0; i < desc.count; ++i )
-			switch ( desc.slots[i].vslot )
+
+		for ( const auto& cslot : channel->desc )
+		switch ( cslot.vslot )
 		{
 			case slot::POSITION : 
-				if ( desc.slots[i].etype == FLOAT_VECTOR_3 ) 
-				{
-					p_offset  = int( desc.slots[i].offset );
+				if ( cslot.etype == FLOAT_VECTOR_3 )
+				{
+					p_offset  = int( cslot.offset );
 					p_channel = channel;
 				}
 				break;
-			case slot::NORMAL   : if ( desc.slots[i].etype == FLOAT_VECTOR_3 ) 
-				{
-					n_offset  = int( desc.slots[i].offset );
+			case slot::NORMAL   : 
+				if ( cslot.etype == FLOAT_VECTOR_3 )
+				{
+					n_offset  = int( cslot.offset );
 					n_channel = m_data->m_channels[ c ];
 					n_channel_index = c;
 				}
 				break;
-			case slot::TEXCOORD : if ( desc.slots[i].etype == FLOAT_VECTOR_2 ) 
-				{
-					t_offset  = int( desc.slots[i].offset );
+			case slot::TEXCOORD : 
+				if ( cslot.etype == FLOAT_VECTOR_2 )
+				{
+					t_offset  = int( cslot.offset );
 					t_channel = channel;
 				}
@@ -230,5 +232,5 @@
 			case slot::INDEX    : 
 				{
-					i_type    = desc.slots[i].etype;
+					i_type    = cslot.etype;
 					i_channel = channel;
 				}
@@ -278,7 +280,7 @@
 		}
 
-		const vec2& w1 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->desc.size*ti0 + t_offset );
-		const vec2& w2 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->desc.size*ti1 + t_offset );
-		const vec2& w3 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->desc.size*ti2 + t_offset );
+		const vec2& w1 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->desc.element_size()*ti0 + t_offset );
+		const vec2& w2 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->desc.element_size()*ti1 + t_offset );
+		const vec2& w3 = *reinterpret_cast<vec2*>(t_channel->data + t_channel->desc.element_size()*ti2 + t_offset );
 		vec2 st1 = w3 - w1;
 		vec2 st2 = w2 - w1;
@@ -291,7 +293,7 @@
 			uint32 nti1 = t_channel->count * set + ti1;
 			uint32 nti2 = t_channel->count * set + ti2;
-			vec3 v1 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->desc.size*nti0 + p_offset );
-			vec3 v2 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->desc.size*nti1 + p_offset );
-			vec3 v3 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->desc.size*nti2 + p_offset );
+			vec3 v1 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->desc.element_size()*nti0 + p_offset );
+			vec3 v2 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->desc.element_size()*nti1 + p_offset );
+			vec3 v3 = *reinterpret_cast<vec3*>(p_channel->data + p_channel->desc.element_size()*nti2 + p_offset );
 			vec3 xyz1 = v3 - v1;
 			vec3 xyz2 = v2 - v1;
@@ -317,5 +319,5 @@
 	for ( unsigned int i = 0; i < vtx_count; ++i )
 	{
-		const vec3 n = *reinterpret_cast<vec3*>( n_channel->data + n_channel->desc.size*i + n_offset );
+		const vec3 n = *reinterpret_cast<vec3*>( n_channel->data + n_channel->desc.element_size()*i + n_offset );
 		const vec3 t = vec3(tangents[i]);
 		if ( ! ( t.x == 0.0f && t.y == 0.0f && t.z == 0.0f ) )
@@ -335,21 +337,18 @@
 {
 	NV_ASSERT( a->count == b->count, "merge_channel - bad channels!" );
-	vertex_descriptor adesc = a->desc;
-	vertex_descriptor bdesc = b->desc;
-	uint32            count = a->count;
-
-	vertex_descriptor desc  = a->desc;
-	for ( uint32 i = 0; i < bdesc.count; i++ )
-	{
-		desc.slots[desc.count+i] = bdesc.slots[i];
-		desc.slots[desc.count+i].offset += desc.size;
-	}
-	desc.size  += bdesc.size;
-	desc.count += bdesc.count;
-	uint8* data = new uint8[ count * desc.size ];
+	data_descriptor adesc = a->desc;
+	data_descriptor bdesc = b->desc;
+	uint32          count = a->count;
+
+	data_descriptor desc  = a->desc;
+	for ( auto bslot : bdesc )
+	{
+		desc.push_slot( bslot.etype, bslot.vslot );
+	}
+	uint8* data = new uint8[ count * desc.element_size() ];
 	for ( uint32 i = 0; i < count; ++i )
 	{
-		raw_copy_n( a->data + i * adesc.size, adesc.size, data + i*desc.size );
-		raw_copy_n( b->data + i * bdesc.size, bdesc.size, data + i*desc.size + adesc.size );
+		raw_copy_n( a->data + i * adesc.element_size(), adesc.element_size(), data + i*desc.element_size() );
+		raw_copy_n( b->data + i * bdesc.element_size(), bdesc.element_size(), data + i*desc.element_size() + adesc.element_size() );
 	}
 	mesh_raw_channel* result = new mesh_raw_channel;
@@ -365,5 +364,5 @@
 	if ( a->count % frame_count != 0 ) return nullptr;
 	if ( b->count % frame_count != 0 ) return nullptr;
-	size_t vtx_size = a->desc.size;
+	size_t vtx_size = a->desc.element_size();
 
 	uint8* data = new uint8[ ( a->count + b->count ) * vtx_size ];
@@ -435,5 +434,5 @@
 		if ( old->get_buffer_type() == INDEX_BUFFER )
 		{
-			switch ( old->desc.slots[0].etype )
+			switch ( old->desc[0].etype )
 			{
 			case USHORT : 
