diff --git a/shaders.cc b/shaders.cc
index 19fa6a6..1e73ebf 100644
--- a/shaders.cc
+++ b/shaders.cc
@@ -186,7 +186,7 @@ void T_InputReader_::parseInputDirective(
 
 	// Name
 	std::string const& name{ tokens[ 2 ] };
-	if ( input.uniforms.find( name ) != input.uniforms.end( ) ) {
+	if ( input.uniforms.contains( name.c_str( ) ) ) {
 		error( "duplicate uniform" );
 		return;
 	}
@@ -202,8 +202,8 @@ void T_InputReader_::parseInputDirective(
 		return;
 	}
 
-	input.uniforms.emplace( tokens[ 2 ] , T_ShaderUniform{
-			tokens[ 2 ] , global , tPos->second } );
+	input.uniforms.add( T_ShaderUniform{
+			tokens[ 2 ].c_str( ) , global , tPos->second } );
 }
 
 /*----------------------------------------------------------------------------*/
@@ -237,13 +237,13 @@ void T_InputReader_::addAccumulated( )
 /*= T_ShaderInput ============================================================*/
 
 bool T_ShaderInput::load(
-		std::string const& path )
+		T_String const& path )
 {
 	type = E_ShaderInput::CHUNK;
 	chunks.clear( );
 	errors.clear( );
 
-	FILE* const file{ fopen( path.c_str( ) , "r" ) };
+	FILE* const file{ fopen( (char const*) path.toOSString( ).data( ) , "r" ) };
 	if ( !file ) {
 		return false;
 	}
@@ -708,17 +708,19 @@ bool T_ShaderManager::useExistingProgram(
 T_ShaderInput const* T_ShaderManager::getInput(
 		T_String const& name )
 {
-	std::string fakename( (char const*) name.toOSString( ).data( ) );
-	auto pos( inputs_.find( fakename ) );
-	if ( pos != inputs_.end( ) ) {
-		return pos->second.get( );
+	auto const* const existing( inputs_.get( name ) );
+	if ( existing ) {
+		return existing->get( );
 	}
+
 	T_ShaderInput ni;
-	if ( !ni.load( "shaders/" + fakename ) ) {
+	T_StringBuilder sb;
+	sb << "shaders/" << name;
+	if ( !ni.load( sb ) ) {
 		return nullptr;
 	}
-	inputs_.emplace( fakename , std::make_unique< T_ShaderInput >( std::move( ni ) ) );
-	return inputs_.find( fakename )->second.get( );
+	inputs_.add( name , NewOwned< T_ShaderInput >( std::move( ni ) ) );
+	return inputs_.get( name )->get( );
 }
 
 
diff --git a/shaders.hh b/shaders.hh
index 471ac7f..25357e8 100644
--- a/shaders.hh
+++ b/shaders.hh
@@ -61,7 +61,7 @@ enum class E_UniformType {
 // Uniform declarations
 struct T_ShaderUniform
 {
-	std::string name;
+	T_String name;
 	bool global;
 	E_UniformType type;
 };
@@ -72,11 +72,15 @@ struct T_ShaderInput
 	E_ShaderInput type = E_ShaderInput::CHUNK;
 	T_Array< T_ShaderInputChunk > chunks;
 	T_Array< T_ShaderInputError > errors;
-	std::unordered_map< std::string , T_ShaderUniform > uniforms;
+	T_ObjectTable< T_String , T_ShaderUniform > uniforms{
+		[]( T_ShaderUniform const& su ) -> T_String {
+			return su.name;
+		}
+	};
 
-	bool load( std::string const& path );
+	bool load( T_String const& path );
 };
-using P_ShaderInput = std::unique_ptr< T_ShaderInput >;
+using P_ShaderInput = T_OwnPtr< T_ShaderInput >;
 
 
 // Type of shader
@@ -192,7 +196,7 @@ struct T_ShaderManager
 	T_Array< T_Program_ > programs_;
 	T_KeyValueTable< T_String , uint32_t > programIndex_;
 
-	std::map< std::string , P_ShaderInput > inputs_;
+	T_KeyValueTable< T_String , P_ShaderInput > inputs_;
 
 	std::map< std::string , std::set< std::string > > missing_;
 	std::set< std::string > updates_;
@@ -209,24 +213,18 @@ struct T_ShaderManager
 	T_ShaderInput const* getInput(
 			T_String const& name );
 
-	void dereferencePipeline(
-			T_String const& id );
+	void dereferencePipeline( T_String const& id );
 	void dereferenceProgram(
 			const uint32_t index ,
 			T_String const& pipeline );
 
-	void initPipeline(
-			T_Pipeline_& pipeline ) const;
-	void initProgram(
-			T_Program_& program );
+	void initPipeline( T_Pipeline_& pipeline ) const;
+	void initProgram( T_Program_& program );
 
 	void parseGLSLError(
 			T_ShaderCode& code ,
 			char const* errorLine );
 
-	void programUpdated(
-			std::string const& name );
-
-	void resetProgram(
-			T_Program_& program );
+	void programUpdated( std::string const& name );
+	void resetProgram( T_Program_& program );
 };