Index: trunk/src/gl/gl_device.cc
===================================================================
--- trunk/src/gl/gl_device.cc	(revision 505)
+++ trunk/src/gl/gl_device.cc	(revision 506)
@@ -22,20 +22,4 @@
 	for ( auto& i : get_link_uniform_factory() ) 
 		m_shader_header.append( "uniform sampler2D "+i.first +";\n" );
-}
-
-program gl_device::create_program( string_view vs_source, string_view fs_source )
-{
-	program result = m_programs.create();
-	gl_program_info* info = m_programs.get( result );
-
-	info->m_attribute_map   = new attribute_map;
-	info->m_engine_uniforms = new engine_uniform_list;
-	info->m_uniform_map     = new uniform_map;
-
-	info->glid = glCreateProgram();
-	info->validated = false;
-	compile( info, vs_source, fs_source );
-	prepare_program( result );
-	return result;
 }
 
@@ -92,4 +76,39 @@
 	while ( m_programs.size() > 0 )
 		release( m_programs.get_handle(0) );
+	while ( m_shaders.size() > 0 )
+		release( m_shaders.get_handle( 0 ) );
+}
+
+nv::shader nv::gl_device::create_shader( shader_type type, string_view sh_source )
+{
+	uint32 glid = 0;
+	if ( !compile( shader_type_to_enum( type ), sh_source, glid ) )
+		return shader();
+
+	shader result = m_shaders.create();
+	gl_shader_info* info = m_shaders.get( result );
+	info->type = type;
+	info->glid = glid;
+	info->ref  = 0;
+
+	return result;
+}
+
+nv::program nv::gl_device::create_program( shader vs, shader fs )
+{
+	program result = m_programs.create();
+	gl_program_info* info = m_programs.get( result );
+
+	info->m_attribute_map = new attribute_map;
+	info->m_engine_uniforms = new engine_uniform_list;
+	info->m_uniform_map = new uniform_map;
+
+	info->glid = glCreateProgram();
+	info->validated = false;
+
+	compile( result, vs, fs );
+	prepare_program( result );
+	return result;
+
 }
 
@@ -156,4 +175,27 @@
 }
 
+void nv::gl_device::attach( program p, shader s )
+{
+	gl_program_info* pinfo = m_programs.get( p );
+	gl_shader_info*  sinfo = m_shaders.get( s );
+
+	if ( sinfo && pinfo )
+	{
+		glAttachShader( pinfo->glid, sinfo->glid );
+		sinfo->ref++;
+	}
+
+}
+
+void nv::gl_device::detach( program p, shader s )
+{
+	gl_program_info* pinfo = m_programs.get( p );
+	gl_shader_info*  sinfo = m_shaders.get( s );
+	if ( sinfo && pinfo )
+	{
+		glDetachShader( pinfo->glid, sinfo->glid );
+		sinfo->ref--;
+	}
+}
 const buffer_info* nv::gl_device::get_buffer_info( buffer t ) const
 {
@@ -169,8 +211,6 @@
 			delete i.second;
 
-		glDetachShader( info->glid, info->glidv );
-		glDetachShader( info->glid, info->glidf );
-		glDeleteShader( info->glidv );
-		glDeleteShader( info->glidf );
+		detach( p, info->vertex );
+		detach( p, info->fragment );
 		glDeleteProgram( info->glid );
 
@@ -182,4 +222,15 @@
 	}
 }
+
+void nv::gl_device::release( shader s )
+{
+	gl_shader_info* info = m_shaders.get( s );
+	if ( info && info->ref == 0 )
+	{
+		glDeleteShader( info->glid );
+		m_shaders.destroy( s );
+	}
+}
+
 
 nv::gl_texture_info* nv::gl_device::get_full_texture_info( texture t )
@@ -285,8 +336,9 @@
 }
 
-bool nv::gl_device::compile( gl_program_info* p, string_view vertex_program, string_view fragment_program )
-{
-	if (!compile( GL_VERTEX_SHADER,   vertex_program, p->glidv ))   { return false; }
-	if (!compile( GL_FRAGMENT_SHADER, fragment_program, p->glidf )) { return false; }
+bool nv::gl_device::compile( program pp, shader vp, shader fp )
+{
+	gl_program_info* p = m_programs.get( pp );
+	p->vertex = vp;
+	p->fragment = fp;
 
 	glBindAttribLocation( p->glid, static_cast<GLuint>( slot::POSITION   ), "nv_position"  );
@@ -298,6 +350,6 @@
 	glBindAttribLocation( p->glid, static_cast<GLuint>( slot::BONEWEIGHT ), "nv_boneweight");
 
-	glAttachShader( p->glid, p->glidf );
-	glAttachShader( p->glid, p->glidv );
+	attach( pp, p->vertex );
+	attach( pp, p->fragment );
 	glLinkProgram( p->glid );
 
Index: trunk/src/gl/gl_enum.cc
===================================================================
--- trunk/src/gl/gl_enum.cc	(revision 505)
+++ trunk/src/gl/gl_enum.cc	(revision 506)
@@ -319,4 +319,14 @@
 }
 
+
+unsigned int nv::shader_type_to_enum( shader_type type )
+{
+	switch ( type )
+	{
+	case VERTEX_SHADER:   return GL_VERTEX_SHADER;
+	case FRAGMENT_SHADER: return GL_FRAGMENT_SHADER;
+		NV_RETURN_COVERED_DEFAULT( 0 );
+	}
+}
 
 unsigned int nv::buffer_access_to_bitfield( buffer_access type )
