diff --git a/shaders.cc b/shaders.cc index 772e135..19fa6a6 100644 --- a/shaders.cc +++ b/shaders.cc @@ -79,13 +79,10 @@ struct T_InputReader_ void read( ); - void handleDirective( - T_Tokens_ const& tokens ); - void parseInputDirective( - T_Tokens_ const& tokens ); + void handleDirective( T_Tokens_ const& tokens ); + void parseInputDirective( T_Tokens_ const& tokens ); - void error( - std::string const& err ); + void error( T_String const& err ); void nl( ); void addAccumulated( ); }; @@ -137,7 +134,7 @@ void T_InputReader_::handleDirective( } addAccumulated( ); auto& ck( input.chunks ); - ck.emplace_back( E_ShaderInputChunk::INCLUDE , tokens[ 1 ] , 1 ); + ck.addNew( E_ShaderInputChunk::INCLUDE , tokens[ 1 ].c_str( ) , 1 ); } else if ( directive == "type" ) { nl( ); @@ -164,7 +161,7 @@ void T_InputReader_::handleDirective( return; } } - input.chunks.emplace_back( E_ShaderInputChunk::UNIFORMS , "" , 1 ); + input.chunks.addNew( E_ShaderInputChunk::UNIFORMS , "" , 1 ); } else { nl( ); @@ -212,10 +209,9 @@ void T_InputReader_::parseInputDirective( /*----------------------------------------------------------------------------*/ void T_InputReader_::error( - std::string const& err ) + T_String const& err ) { - input.errors.push_back( T_ShaderInputError{ - line , err } ); + input.errors.addNew( line , err ); } void T_InputReader_::nl( ) @@ -228,8 +224,8 @@ void T_InputReader_::addAccumulated( ) { if ( accumLines ) { auto& ck( input.chunks ); - ck.emplace_back( E_ShaderInputChunk::CODE , - std::move( accumulator ) , accumLines ); + ck.addNew( E_ShaderInputChunk::CODE , + accumulator.c_str( ) , accumLines ); accumulator = {}; accumLines = 0; } @@ -262,34 +258,33 @@ bool T_ShaderInput::load( /*= T_ShaderPipeline =========================================================*/ T_ShaderPipeline::T_ShaderPipeline( ) - : T_ShaderPipeline( -1 ) + : T_ShaderPipeline( T_String{} ) { } T_ShaderPipeline::T_ShaderPipeline( T_ShaderPipeline const& other ) - : T_ShaderPipeline( other.smIndex_ ) + : T_ShaderPipeline( other.id_ ) { } T_ShaderPipeline::T_ShaderPipeline( T_ShaderPipeline&& other ) noexcept : T_ShaderPipeline( ) { - std::swap( other.smIndex_ , smIndex_ ); + swap( other.id_ , id_ ); } -T_ShaderPipeline::T_ShaderPipeline( - const int32_t index ) - : smIndex_( index ) +T_ShaderPipeline::T_ShaderPipeline( T_String id ) noexcept + : id_( std::move( id ) ) { - if ( smIndex_ >= 0 ) { - Globals::Shaders( ).pipelines_[ smIndex_ ].references ++; + if ( id_ ) { + Globals::Shaders( ).pipelines_.get( id_ )->references ++; } } T_ShaderPipeline::~T_ShaderPipeline( ) { - if ( smIndex_ >= 0 ) { - Globals::Shaders( ).dereferencePipeline( smIndex_ ); + if ( id_ ) { + Globals::Shaders( ).dereferencePipeline( id_ ); } } @@ -297,12 +292,12 @@ T_ShaderPipeline& T_ShaderPipeline::operator=( T_ShaderPipeline const& other ) { if ( this != &other ) { - if ( smIndex_ >= 0 ) { - Globals::Shaders( ).dereferencePipeline( smIndex_ ); + if ( id_ ) { + Globals::Shaders( ).dereferencePipeline( id_ ); } - smIndex_ = other.smIndex_; - if ( smIndex_ >= 0 ) { - Globals::Shaders( ).pipelines_[ smIndex_ ].references ++; + id_ = other.id_; + if ( id_ ) { + Globals::Shaders( ).pipelines_.get( id_ )->references ++; } } return *this; @@ -312,32 +307,37 @@ T_ShaderPipeline& T_ShaderPipeline::operator=( T_ShaderPipeline&& other ) noexcept { if ( this != &other ) { - if ( smIndex_ >= 0 ) { - Globals::Shaders( ).dereferencePipeline( smIndex_ ); + if ( id_ ) { + Globals::Shaders( ).dereferencePipeline( id_ ); } - smIndex_ = other.smIndex_; - other.smIndex_ = -1; + id_ = other.id_; + other.id_ = T_String{}; } return *this; } bool T_ShaderPipeline::valid( ) const noexcept { - return smIndex_ >= 0 - && Globals::Shaders( ).pipelines_[ smIndex_ ].id != 0; + return id_ + && Globals::Shaders( ).pipelines_.get( id_ )->id != 0; } void T_ShaderPipeline::enable( ) const { - if ( valid( ) ) { - glBindProgramPipeline( Globals::Shaders( ).pipelines_[ smIndex_ ].id ); + if ( !id_ ) { + return; + } + + auto const* pl( Globals::Shaders( ).pipelines_.get( id_ ) ); + if ( pl && pl->id ) { + glBindProgramPipeline( pl->id ); } } GLuint T_ShaderPipeline::id( ) const { - if ( smIndex_ >= 0 ) { - return Globals::Shaders( ).pipelines_[ smIndex_ ].id; + if ( id_ ) { + return Globals::Shaders( ).pipelines_.get( id_ )->id; } else { return 0; } @@ -351,13 +351,13 @@ GLuint T_ShaderPipeline::program( } auto const& sm( Globals::Shaders( ) ); - auto const& pl( sm.pipelines_[ smIndex_ ] ); + auto const& pl( *sm.pipelines_.get( id_ ) ); for ( auto const& pn : pl.programs ) { - auto pos( sm.programIndex_.find( pn ) ); - if ( pos == sm.programIndex_.end( ) ) { + auto const* pos( sm.programIndex_.get( pn ) ); + if ( !pos ) { continue; } - auto& p( sm.programs_[ pos->second ] ); + auto& p( sm.programs_[ *pos ] ); if ( p.code.type == program ) { return p.id; } @@ -370,32 +370,32 @@ GLuint T_ShaderPipeline::program( namespace { -using F_GetInput_ = std::function< T_ShaderInput const*( std::string const& ) >; +using F_GetInput_ = std::function< T_ShaderInput const*( T_String const& ) >; using T_Code_ = T_ShaderManager::T_ShaderCode; // Code builder, state and functions struct T_CodeBuilder_ { struct T_StackEntry_ { - std::string name; + T_String name; T_ShaderInput const* input; uint32_t pos; }; F_GetInput_ loader; - const std::string name; + const T_String name; T_Code_& code; T_ShaderInput const* main; - std::map< std::string , uint32_t > pos; + T_KeyValueTable< T_String , uint32_t > pos; std::vector< T_StackEntry_ > stack; - std::set< std::string > libraries; + T_Array< T_String > libraries; T_ShaderInput const* current; uint32_t cpos{ 0 }; - std::string cname; + T_String cname; T_CodeBuilder_( F_GetInput_ loader , - std::string const& name , + T_String const& name , T_Code_& code ) : loader( loader ) , name( name ) , code( code ) , main( loader( name ) ) @@ -403,13 +403,13 @@ struct T_CodeBuilder_ bool buildCode( ); void appendChunk( T_ShaderInputChunk const& chunk ); - void include( std::string const& name , + void include( T_String const& name , const uint32_t lines ); void next( ); void addInputLoaderErrors( T_ShaderInput const* input , - std::string const& name ); + T_String const& name ); }; /*----------------------------------------------------------------------------*/ @@ -417,14 +417,13 @@ struct T_CodeBuilder_ bool T_CodeBuilder_::buildCode( ) { code = T_Code_{ }; - code.files.emplace( name , main != nullptr ); + code.files.add( name , main != nullptr ); if ( !main ) { return false; } if ( main->type == E_ShaderInput::CHUNK || main->type == E_ShaderInput::LIBRARY ) { - code.errors.push_back( T_ShaderError{ - name , 0 , "invalid type" } ); + code.errors.addNew( name , 0 , "invalid type" ); } else { code.type = E_ShaderType( int( main->type ) - 2 ); } @@ -443,70 +442,77 @@ bool T_CodeBuilder_::buildCode( ) next( ); } + code.code << '\0'; return true; } void T_CodeBuilder_::appendChunk( T_ShaderInputChunk const& chunk ) { - code.sources.push_back( cname ); - code.counts.push_back( chunk.lines ); - code.starts.push_back( pos[ cname ] ); - code.code += chunk.text; - pos[ cname ] += chunk.lines; + auto* p( pos.get( cname ) ); + if ( !p ) { + pos.add( cname , 0u ); + p = pos.get( cname ); + } + code.sources.addNew( cname ); + code.counts.add( chunk.lines ); + code.starts.add( *p ); + code.code << chunk.text; + *p += chunk.lines; } void T_CodeBuilder_::include( - std::string const& nname , + T_String const& nname , const uint32_t lines ) { - const auto prevPos( pos[ cname ] ); - pos[ cname ] += lines; + auto* const p( pos.get( cname ) ); + const auto prevPos( *p ); + *p += lines; // Avoid recursion - if ( cname == nname || 0 != count_if( stack.begin( ) , stack.end( ) , + if ( nname == cname || 0 != count_if( stack.begin( ) , stack.end( ) , [nname] ( T_StackEntry_ const& e ) { return nname == e.name; } ) ) { - code.errors.push_back( T_ShaderError{ cname , prevPos , - "recursive inclusion of '" + nname + "'" } ); + T_StringBuilder sb; + code.errors.addNew( cname , prevPos , + sb << "recursive inclusion of '" + << nname << "'" ); return; } // Avoid including libraries more than once - if ( libraries.find( nname ) != libraries.end( ) ) { + if ( libraries.contains( nname ) ) { return; } T_ShaderInput const* const isi( loader( nname ) ); - code.files.emplace( nname , isi != nullptr ); + code.files.add( nname , isi != nullptr ); // Check for problems if ( !isi ) { // Not found - code.errors.push_back( T_ShaderError{ cname , prevPos , - "file not found" } ); + code.errors.addNew( cname , prevPos , "file not found" ); return; } if ( isi->type != E_ShaderInput::CHUNK && isi->type != E_ShaderInput::LIBRARY ) { // Trying to load a top-level shader - code.errors.push_back( T_ShaderError{ cname , prevPos , - "trying to include a top-level file" } ); + code.errors.addNew( cname , prevPos , "trying to include a top-level file" ); return; } // Add input loader errors - if ( libraries.find( nname ) == libraries.end( ) ) { + if ( !libraries.contains( nname ) ) { addInputLoaderErrors( isi , nname ); } - libraries.insert( nname ); + libraries.add( nname ); // Enter the new file stack.push_back( T_StackEntry_{ cname , current , cpos } ); cname = nname; current = isi; cpos = UINT32_MAX; - pos[ cname ] = 0; + pos.set( cname , 0u ); } void T_CodeBuilder_::next( ) @@ -514,7 +520,7 @@ void T_CodeBuilder_::next( ) cpos ++; while ( cpos == current->chunks.size( ) && !stack.empty( ) ) { T_StackEntry_ const& se( stack[ stack.size( ) - 1 ] ); - pos.erase( cname ); + pos.remove( cname ); cpos = se.pos + 1; current = se.input; cname = se.name; @@ -524,11 +530,10 @@ void T_CodeBuilder_::next( ) void T_CodeBuilder_::addInputLoaderErrors( T_ShaderInput const* input , - std::string const& name ) + T_String const& name ) { for ( auto const& errs : input->errors ) { - code.errors.push_back( T_ShaderError{ - name , errs.line , errs.error } ); + code.errors.addNew( name , errs.line , (char*) errs.error.toOSString( ).data( ) ); } } @@ -537,38 +542,43 @@ void T_CodeBuilder_::addInputLoaderErrors( /*============================================================================*/ +T_ShaderManager::T_ShaderManager( ) noexcept + : pipelines_( []( T_Pipeline_ const& p ) -> T_String { + return p.idString; + } ) +{ } + +/*----------------------------------------------------------------------------*/ T_ShaderPipeline T_ShaderManager::pipeline( - std::initializer_list< std::string > shaders ) + std::initializer_list< T_String > shaders ) { if ( shaders.size( ) < 1 || shaders.size( ) > 5 ) { return {}; } - const std::string id( ([&shaders] () { - std::ostringstream oss; - std::copy( shaders.begin( ) , shaders.end( ) , - std::ostream_iterator< std::string >( oss , "|" ) ); - return oss.str( ); + const T_String id( ([&shaders] () { + T_StringBuilder sb; + for ( auto const& s : shaders ) { + sb << s << '|'; + } + sb << '\0'; + return T_String{ std::move( sb.data( ) ) }; } )() ); - auto pos( pipelineIndex_.find( id ) ); - if ( pos != pipelineIndex_.end( ) ) { - return T_ShaderPipeline{ int32_t( pos->second ) }; + + auto const* existing( pipelines_.get( id ) ); + if ( existing ) { + return T_ShaderPipeline{ existing->idString }; } - const auto index( newPipelineRecord( ) ); - auto& p( pipelines_[ index ] ); - pipelineIndex_.emplace( id , index ); - p.idString = id; - p.id = 0; - p.references = 0; - p.programs = shaders; + pipelines_.add( T_Pipeline_{ id , shaders } ); + auto& p( *pipelines_.get( id ) ); for ( auto const& pName : shaders ) { - loadProgram( index , pName ); + loadProgram( p.idString , (char*)( pName.toOSString( ).data( ) ) ); } initPipeline( p ); - return T_ShaderPipeline{ int32_t( index ) }; + return T_ShaderPipeline{ p.idString }; } /*----------------------------------------------------------------------------*/ @@ -591,15 +601,19 @@ void T_ShaderManager::update( ) } // Reset programs that need to be updated - std::set< uint32_t > pipelines; + T_Array< T_String > pipelines; for ( auto const& name : updates_ ) { - auto p( programIndex_.find( name ) ); - if ( p == programIndex_.end( ) ) { - updates_.erase( name ); - } else { - auto& pr( programs_[ p->second ] ); - pipelines.insert( pr.references.begin( ) , pr.references.end( ) ); + auto const* p( programIndex_.get( name.c_str( ) ) ); + if ( p ) { + auto& pr( programs_[ *p ] ); + for ( auto const& ref : pr.references ) { + if ( !pipelines.contains( ref ) ) { + pipelines.add( ref ); + } + } resetProgram( pr ); + } else { + updates_.erase( name ); } } if ( updates_.empty( ) ) { @@ -607,8 +621,8 @@ void T_ShaderManager::update( ) } // Reset pipelines affected by the programs above - for ( auto plid : pipelines ) { - auto& pipeline( pipelines_[ plid ] ); + for ( auto const& pName : pipelines ) { + auto& pipeline( *pipelines_.get( pName ) ); if ( pipeline.id != 0 ) { glDeleteProgramPipelines( 1 , &pipeline.id ); pipeline.id = 0; @@ -617,36 +631,26 @@ void T_ShaderManager::update( ) // Try to load all updated programs for ( auto const& name : updates_ ) { - auto& pr( programs_[ programIndex_[ name ] ] ); + auto& pr( programs_[ *programIndex_.get( name.c_str( ) ) ] ); initProgram( pr ); + T_StringBuilder sb; for ( auto const& e : pr.code.errors ) { - printf( "%s:%d: %s\n" , e.source.c_str( ) , e.line , - e.error.c_str( ) ); + sb << e.source << ':' << e.line << ": " + << e.error << '\n'; } + sb << '\0'; + printf( "%s" , sb.data( ) ); } // Try to initialise all affected pipelines - for ( auto plid : pipelines ) { - initPipeline( pipelines_[ plid ] ); + for ( auto const& pName : pipelines ) { + initPipeline( *pipelines_.get( pName ) ); } updates_.clear( ); } -uint32_t T_ShaderManager::newPipelineRecord( ) -{ - uint32_t i = 0; - while ( i < pipelines_.size( ) ) { - if ( pipelines_[ i ].references == 0 ) { - return i; - } - i ++; - } - pipelines_.emplace_back( ); - return i; -} - uint32_t T_ShaderManager::newProgramRecord( ) { uint32_t i = 0; @@ -656,13 +660,13 @@ uint32_t T_ShaderManager::newProgramRecord( ) } i ++; } - programs_.emplace_back( ); + programs_.addNew( ); return i; } void T_ShaderManager::loadProgram( - const uint32_t pipeline , + T_String const& pipeline , std::string const& name ) { if ( useExistingProgram( pipeline , name ) ) { @@ -671,84 +675,92 @@ void T_ShaderManager::loadProgram( const uint32_t index( newProgramRecord( ) ); auto& program( programs_[ index ] ); - programIndex_.emplace( name , index ); - program.name = name; - program.references.insert( pipeline ); + programIndex_.add( T_String{ name.c_str( ) } , index ); + program.name = name.c_str( ); + program.references.add( pipeline ); program.id = 0; initProgram( program ); + + T_StringBuilder sb; for ( auto const& e : program.code.errors ) { - printf( "%s:%d: %s\n" , e.source.c_str( ) , e.line , e.error.c_str( ) ); + sb << e.source << ':' << e.line << ": " + << e.error << '\n'; } + sb << '\0'; + printf( "%s" , sb.data( ) ); } bool T_ShaderManager::useExistingProgram( - const uint32_t pipeline , + T_String const& pipeline , std::string const& name ) { - auto pos( programIndex_.find( name ) ); - if ( pos == programIndex_.end( ) ) { + auto const* pos( programIndex_.get( name.c_str( ) ) ); + if ( !pos ) { return false; } - auto& refs( programs_[ pos->second ].references ); - assert( refs.find( pipeline ) == refs.end( ) ); - refs.insert( pipeline ); + auto& refs( programs_[ *pos ].references ); + assert( !refs.contains( pipeline ) ); + refs.add( pipeline ); return true; } T_ShaderInput const* T_ShaderManager::getInput( - std::string const& name ) + T_String const& name ) { - auto pos( inputs_.find( name ) ); + std::string fakename( (char const*) name.toOSString( ).data( ) ); + auto pos( inputs_.find( fakename ) ); if ( pos != inputs_.end( ) ) { return pos->second.get( ); } T_ShaderInput ni; - if ( !ni.load( "shaders/" + name ) ) { + if ( !ni.load( "shaders/" + fakename ) ) { return nullptr; } - inputs_.emplace( name , std::make_unique< T_ShaderInput >( std::move( ni ) ) ); - return inputs_.find( name )->second.get( ); + inputs_.emplace( fakename , std::make_unique< T_ShaderInput >( std::move( ni ) ) ); + return inputs_.find( fakename )->second.get( ); } void T_ShaderManager::dereferencePipeline( - const uint32_t index ) + T_String const& id ) { - auto& pipeline( pipelines_[ index ] ); + auto& pipeline( *pipelines_.get( id ) ); assert( pipeline.references > 0 ); pipeline.references --; if ( pipeline.references > 0 ) { return; } - pipelineIndex_.erase( pipeline.idString ); if ( pipeline.id != 0 ) { glDeleteProgramPipelines( 1 , &pipeline.id ); pipeline.id = 0; } for ( auto const& pName : pipeline.programs ) { - auto pos( programIndex_.find( pName ) ); - assert( pos != programIndex_.end( ) ); - dereferenceProgram( pos->second , index ); + auto const* pos( programIndex_.get( pName ) ); + assert( pos ); + dereferenceProgram( *pos , id ); } + + pipelines_.remove( pipeline.idString ); } void T_ShaderManager::dereferenceProgram( const uint32_t index , - const uint32_t pipeline ) + T_String const& pipeline ) { auto& program( programs_[ index ] ); auto& refs( program.references ); - assert( refs.find( pipeline ) != refs.end( ) ); - refs.erase( pipeline ); + const auto plidx( refs.indexOf( pipeline ) ); + assert( plidx >= 0 ); + refs.remove( plidx ); if ( refs.size( ) != 0 ) { return; } resetProgram( program ); - programIndex_.erase( program.name ); + programIndex_.remove( program.name.c_str( ) ); } @@ -757,7 +769,7 @@ void T_ShaderManager::initPipeline( { assert( pipeline.id == 0 ); - printf( "init pipeline %s\n" , pipeline.idString.c_str( ) ); + printf( "init pipeline %s\n" , pipeline.idString.toOSString( ).data( ) ); constexpr auto nst{ size_t( E_ShaderType::__COUNT__ ) }; int32_t programs[ nst ]; for ( auto i = 0u ; i < nst ; i ++ ) { @@ -765,7 +777,7 @@ void T_ShaderManager::initPipeline( } for ( auto const& pName : pipeline.programs ) { - const uint32_t pid( programIndex_.find( pName )->second ); + const uint32_t pid( *programIndex_.get( pName ) ); auto const& program( programs_[ pid ] ); if ( programs[ int( program.code.type ) ] != -1 || program.id == 0 ) { @@ -808,26 +820,29 @@ void T_ShaderManager::initProgram( auto name( program.name ); printf( "init program %s\n" , program.name.c_str( ) ); auto& code( program.code ); - T_CodeBuilder_ cb( [this]( std::string const& n ) { return getInput( n ); } , - name , code ); + T_CodeBuilder_ cb( [this]( T_String const& n ) { return getInput( n ); } , + name.c_str( ) , code ); const bool built( T_CodeBuilder_{ - [this]( std::string const& n ) { return getInput( n ); } , - program.name , code + [this]( T_String const& n ) { return getInput( n ); } , + program.name.c_str( ) , code }.buildCode( ) ); // Initialise file watcher + missing files - program.watch = std::make_unique< T_WatchedFiles >( Globals::Watcher( ) , + program.watch = T_WatchedFiles{ Globals::Watcher( ) , [this,name]() { programUpdated( name ); - } ); - for ( auto entry : code.files ) { - if ( entry.second ) { - ebcl::T_StringBuilder sb( "shaders/" ); - sb << entry.first.c_str( ); - program.watch->watch( std::move( sb ) ); + } }; + const auto nf( code.files.size( ) ); + auto& w( *( program.watch.target( ) ) ); + for ( auto i = 0u ; i < nf ; i ++ ) { + T_String const& fn( code.files.keys( )[ i ] ); + if ( code.files.values( )[ i ] ) { + T_StringBuilder sb; + sb << "shaders/" << fn; + w.watch( std::move( sb ) ); } else { - missing_[ entry.first ].insert( name ); + missing_[ std::string{ (char*) fn.toOSString( ).data( ) } ].insert( name ); } } @@ -837,14 +852,14 @@ void T_ShaderManager::initProgram( // Try to compile the program char const* const list[] = { - program.code.code.c_str( ) + program.code.code.data( ) }; const GLenum sid = glCreateShaderProgramv( ProgramTypes_[ int( code.type ) ] , 1 , &list[ 0 ] ); if ( sid == 0 ) { - code.errors.push_back( T_ShaderError{ - name , 0 , "failed to create GL program" } ); + code.errors.addNew( name.c_str( ) , 0 , + "failed to create GL program" ); return; } @@ -898,10 +913,10 @@ void T_ShaderManager::parseGLSLError( pos ++; } - code.errors.push_back( T_ShaderError{ - pos == 0 ? "*unknown*" : code.sources[ pos - 1 ] , + code.errors.addNew( + pos == 0 ? "*unknown*" : ((char*)code.sources[ pos - 1 ].toOSString( ).data( ) ) , pos == 0 ? 0 : ( rawLine + code.counts[ pos - 1 ] - check + code.starts[ pos - 1 ] ) , - errorLine } ); + errorLine ); } void T_ShaderManager::programUpdated( @@ -913,8 +928,8 @@ void T_ShaderManager::programUpdated( void T_ShaderManager::resetProgram( T_Program_& program ) { - if ( program.watch ) { - program.watch.reset( ); + if ( program.watch.present( ) ) { + program.watch.clear( ); } if ( program.id != 0 ) { glDeleteProgram( program.id ); @@ -922,14 +937,19 @@ void T_ShaderManager::resetProgram( return; } - for ( auto entry : program.code.files ) { - if ( entry.second || missing_.find( entry.first ) == missing_.end( ) ) { + auto const& files( program.code.files ); + const auto nf( files.size( ) ); + for ( auto i = 0u ; i < nf ; i ++ ) { + T_String const& k{ files.keys( )[ i ] }; + bool v{ files[ i ] }; + std::string temp{ (char*) k.toOSString( ).data( ) }; + if ( v || missing_.find( temp ) == missing_.end( ) ) { continue; } - auto& set( missing_[ entry.first ] ); + auto& set( missing_[ temp ] ); set.erase( program.name ); if ( set.empty( ) ) { - missing_.erase( entry.first ); + missing_.erase( temp ); } } } @@ -987,14 +1007,14 @@ void T_ShaderManager::makeUI( ) } ImGui::SameLine( 400 ); - ImGui::Text( "Usage: %zu" , program.references.size( ) ); + ImGui::Text( "Usage: %u" , program.references.size( ) ); ImGui::SameLine( 550 ); if ( program.code.errors.empty( ) ) { ImGui::PushStyleColor( ImGuiCol_Text , ImVec4( .6 , 1 , .6 , 1 ) ); ImGui::Text( "No errors" ); } else { ImGui::PushStyleColor( ImGuiCol_Text , ImVec4( 1 , .6 , .6 , 1 ) ); - ImGui::Text( "%zu error%s" , nErrors , nErrors > 1 ? "s" : "" ); + ImGui::Text( "%u error%s" , nErrors , nErrors > 1 ? "s" : "" ); } ImGui::PopStyleColor( ); @@ -1002,11 +1022,11 @@ void T_ShaderManager::makeUI( ) for ( auto const& err : program.code.errors ) { ImGui::NewLine( ); ImGui::SameLine( 50 ); - ImGui::Text( "%s" , err.source.c_str( ) ); + ImGui::Text( "%s" , err.source.toOSString( ).data( ) ); ImGui::SameLine( 250 ); ImGui::Text( "line %d" , err.line ); ImGui::SameLine( 370 ); - ImGui::Text( "%s" , err.error.c_str( ) ); + ImGui::Text( "%s" , err.error.toOSString( ).data( ) ); } ImGui::TreePop( ); } diff --git a/shaders.hh b/shaders.hh index a3ac8cb..471ac7f 100644 --- a/shaders.hh +++ b/shaders.hh @@ -16,13 +16,13 @@ enum class E_ShaderInputChunk { struct T_ShaderInputChunk { E_ShaderInputChunk type; - std::string text; + T_String text; uint32_t lines; T_ShaderInputChunk( ) = default; T_ShaderInputChunk( const E_ShaderInputChunk type , - std::string text , + T_String text , const uint32_t lines ) : type( type ) , text( std::move( text ) ) , lines( lines ) { } @@ -42,7 +42,13 @@ enum class E_ShaderInput { struct T_ShaderInputError { uint32_t line; - std::string error; + T_String error; + + T_ShaderInputError( + const uint32_t line , + T_String error ) + : line( line ) , error( std::move( error ) ) + { } }; // Uniform types @@ -64,8 +70,8 @@ struct T_ShaderUniform struct T_ShaderInput { E_ShaderInput type = E_ShaderInput::CHUNK; - std::vector< T_ShaderInputChunk > chunks; - std::vector< T_ShaderInputError > errors; + T_Array< T_ShaderInputChunk > chunks; + T_Array< T_ShaderInputError > errors; std::unordered_map< std::string , T_ShaderUniform > uniforms; bool load( std::string const& path ); @@ -85,9 +91,25 @@ enum class E_ShaderType { // the input loader, the shader loader or the driver. struct T_ShaderError { - std::string source; + T_String source; uint32_t line; - std::string error; + T_String error; + + T_ShaderError( ) = default; + + T_ShaderError( T_String source , + const uint32_t line , + T_String error ) + : source( std::move( source ) ) , line( line ) , + error( std::move( error ) ) + { } + + T_ShaderError( T_String source , + const uint32_t line , + T_StringBuilder& error ) + : source( std::move( source ) ) , line( line ) , + error( std::move( error ) ) + { } }; @@ -109,9 +131,8 @@ struct T_ShaderPipeline GLuint program( const E_ShaderType program ) const; private: - explicit T_ShaderPipeline( - const int32_t index ); - int32_t smIndex_; + explicit T_ShaderPipeline( T_String id ) noexcept; + T_String id_; }; @@ -122,16 +143,18 @@ struct T_ShaderManager struct T_ShaderCode { E_ShaderType type; - std::vector< uint32_t > starts; // Position of chunk in source file - std::vector< uint32_t > counts; // Chunk lengths - std::vector< std::string > sources; // Chunk source files - std::string code; - std::vector< T_ShaderError > errors; - std::map< std::string , bool > files; + T_AutoArray< uint32_t , 8 > starts; // Position of chunk in source file + T_AutoArray< uint32_t , 8 > counts; // Chunk lengths + T_AutoArray< T_String , 8 > sources; // Chunk source files + T_StringBuilder code; + T_Array< T_ShaderError > errors; + T_KeyValueTable< T_String , bool > files; }; + T_ShaderManager( ) noexcept; + T_ShaderPipeline pipeline( - std::initializer_list< std::string > shaders ); + std::initializer_list< T_String > shaders ); void update( ); @@ -142,52 +165,55 @@ struct T_ShaderManager private: struct T_Pipeline_ { - uint32_t references; - std::string idString; - GLuint id; - std::vector< std::string > programs; + T_String idString; + uint32_t references = 0; + GLuint id = 0; + T_Array< T_String > programs{ 8 }; + + T_Pipeline_( T_String const& id , + std::initializer_list< T_String > shaders ) + : idString{ id } , programs{ shaders } + {} }; struct T_Program_ { std::string name; - std::set< uint32_t > references; + T_Array< T_String > references; T_ShaderCode code; GLuint id; - std::unique_ptr< T_WatchedFiles > watch; + T_Optional< T_WatchedFiles > watch; }; bool uiEnabled_ = false; - std::vector< T_Pipeline_ > pipelines_; - std::map< std::string , uint32_t > pipelineIndex_; + T_ObjectTable< T_String , T_Pipeline_ > pipelines_; - std::vector< T_Program_ > programs_; - std::map< std::string , uint32_t > programIndex_; + T_Array< T_Program_ > programs_; + T_KeyValueTable< T_String , uint32_t > programIndex_; std::map< std::string , P_ShaderInput > inputs_; std::map< std::string , std::set< std::string > > missing_; std::set< std::string > updates_; - uint32_t newPipelineRecord( ); uint32_t newProgramRecord( ); void loadProgram( - const uint32_t pipeline , + T_String const& pipeline , std::string const& name ); bool useExistingProgram( - const uint32_t pipeline , + T_String const& pipeline , std::string const& name ); T_ShaderInput const* getInput( - std::string const& name ); + T_String const& name ); void dereferencePipeline( - const uint32_t index ); + T_String const& id ); void dereferenceProgram( const uint32_t index , - const uint32_t pipeline ); + T_String const& pipeline ); void initPipeline( T_Pipeline_& pipeline ) const;