Shaders - Made it possible to load programs separately
This commit is contained in:
parent
71f6fed1ee
commit
96d821828f
2 changed files with 237 additions and 45 deletions
243
shaders.cc
243
shaders.cc
|
@ -257,6 +257,114 @@ bool T_ShaderInput::load(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_ShaderPogram ===========================================================*/
|
||||||
|
|
||||||
|
T_ShaderProgram::T_ShaderProgram( )
|
||||||
|
: T_ShaderProgram( 0 )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
T_ShaderProgram::T_ShaderProgram(
|
||||||
|
T_ShaderProgram const& other )
|
||||||
|
: T_ShaderProgram( other.id_ )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
T_ShaderProgram::T_ShaderProgram(
|
||||||
|
T_ShaderProgram&& other ) noexcept
|
||||||
|
: T_ShaderProgram( )
|
||||||
|
{
|
||||||
|
swap( other.id_ , id_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
T_ShaderProgram::T_ShaderProgram(
|
||||||
|
const uint32_t id ) noexcept
|
||||||
|
: id_( id )
|
||||||
|
{
|
||||||
|
if ( id_ ) {
|
||||||
|
Globals::Shaders( ).programs_[ id_ - 1 ].saReferences ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T_ShaderProgram::~T_ShaderProgram( )
|
||||||
|
{
|
||||||
|
if ( id_ ) {
|
||||||
|
Globals::Shaders( ).dereferenceProgram( id_ );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T_ShaderProgram& T_ShaderProgram::operator=(
|
||||||
|
T_ShaderProgram const& other )
|
||||||
|
{
|
||||||
|
if ( this != &other ) {
|
||||||
|
if ( id_ ) {
|
||||||
|
Globals::Shaders( ).dereferenceProgram( id_ );
|
||||||
|
}
|
||||||
|
id_ = other.id_;
|
||||||
|
if ( id_ ) {
|
||||||
|
Globals::Shaders( ).programs_[ id_ - 1 ].saReferences ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T_ShaderProgram& T_ShaderProgram::operator=(
|
||||||
|
T_ShaderProgram&& other ) noexcept
|
||||||
|
{
|
||||||
|
if ( this != &other ) {
|
||||||
|
if ( id_ ) {
|
||||||
|
Globals::Shaders( ).dereferenceProgram( id_ );
|
||||||
|
}
|
||||||
|
id_ = other.id_;
|
||||||
|
other.id_ = T_String{};
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_ShaderProgram::valid( ) const noexcept
|
||||||
|
{
|
||||||
|
return id_ && Globals::Shaders( ).programs_[ id_ - 1 ].id != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_ShaderProgram::enable( ) const
|
||||||
|
{
|
||||||
|
if ( !id_ ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const& p( Globals::Shaders( ).programs_[ id_ - 1 ] );
|
||||||
|
if ( p.id ) {
|
||||||
|
glBindProgramPipeline( 0 );
|
||||||
|
glUseProgram( p.id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint T_ShaderProgram::id( ) const
|
||||||
|
{
|
||||||
|
if ( id_ ) {
|
||||||
|
return Globals::Shaders( ).programs_[ id_ - 1 ].id;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T_Optional< E_ShaderType > T_ShaderProgram::type( ) const
|
||||||
|
{
|
||||||
|
if ( id_ ) {
|
||||||
|
return Globals::Shaders( ).programs_[ id_ - 1 ].code.type;
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T_String T_ShaderProgram::name( ) const
|
||||||
|
{
|
||||||
|
if ( id_ ) {
|
||||||
|
return Globals::Shaders( ).programs_[ id_ - 1 ].name;
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*= T_ShaderPipeline =========================================================*/
|
/*= T_ShaderPipeline =========================================================*/
|
||||||
|
|
||||||
T_ShaderPipeline::T_ShaderPipeline( )
|
T_ShaderPipeline::T_ShaderPipeline( )
|
||||||
|
@ -332,6 +440,7 @@ void T_ShaderPipeline::enable( ) const
|
||||||
|
|
||||||
auto const* pl( Globals::Shaders( ).pipelines_.get( id_ ) );
|
auto const* pl( Globals::Shaders( ).pipelines_.get( id_ ) );
|
||||||
if ( pl && pl->id ) {
|
if ( pl && pl->id ) {
|
||||||
|
glUseProgram( 0 );
|
||||||
glBindProgramPipeline( pl->id );
|
glBindProgramPipeline( pl->id );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -552,6 +661,14 @@ T_ShaderManager::T_ShaderManager( ) noexcept
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
T_ShaderProgram T_ShaderManager::program(
|
||||||
|
T_String const& name )
|
||||||
|
{
|
||||||
|
loadProgram( name );
|
||||||
|
assert( programIndex_.contains( name ) );
|
||||||
|
return T_ShaderProgram( *programIndex_.get( name ) );
|
||||||
|
}
|
||||||
|
|
||||||
T_ShaderPipeline T_ShaderManager::pipeline(
|
T_ShaderPipeline T_ShaderManager::pipeline(
|
||||||
std::initializer_list< T_String > shaders )
|
std::initializer_list< T_String > shaders )
|
||||||
{
|
{
|
||||||
|
@ -576,7 +693,7 @@ T_ShaderPipeline T_ShaderManager::pipeline(
|
||||||
pipelines_.add( T_Pipeline_{ id , shaders } );
|
pipelines_.add( T_Pipeline_{ id , shaders } );
|
||||||
auto& p( *pipelines_.get( id ) );
|
auto& p( *pipelines_.get( id ) );
|
||||||
for ( auto const& pName : shaders ) {
|
for ( auto const& pName : shaders ) {
|
||||||
loadProgram( p.idString , (char*)( pName.toOSString( ).data( ) ) );
|
loadProgram( p.idString , pName );
|
||||||
}
|
}
|
||||||
initPipeline( p );
|
initPipeline( p );
|
||||||
|
|
||||||
|
@ -623,7 +740,7 @@ void T_ShaderManager::update( )
|
||||||
auto const* p( programIndex_.get( *it ) );
|
auto const* p( programIndex_.get( *it ) );
|
||||||
if ( p ) {
|
if ( p ) {
|
||||||
auto& pr( programs_[ *p ] );
|
auto& pr( programs_[ *p ] );
|
||||||
for ( auto const& ref : pr.references ) {
|
for ( auto const& ref : pr.plReferences ) {
|
||||||
if ( !temp.contains( ref ) ) {
|
if ( !temp.contains( ref ) ) {
|
||||||
temp.add( ref );
|
temp.add( ref );
|
||||||
}
|
}
|
||||||
|
@ -669,43 +786,13 @@ void T_ShaderManager::update( )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t T_ShaderManager::newProgramRecord( )
|
|
||||||
{
|
|
||||||
uint32_t i = 0;
|
|
||||||
while ( i < programs_.size( ) ) {
|
|
||||||
if ( programs_[ i ].references.empty( ) ) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
i ++;
|
|
||||||
}
|
|
||||||
programs_.addNew( );
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void T_ShaderManager::loadProgram(
|
void T_ShaderManager::loadProgram(
|
||||||
T_String const& pipeline ,
|
T_String const& pipeline ,
|
||||||
T_String const& name )
|
T_String const& name )
|
||||||
{
|
{
|
||||||
if ( useExistingProgram( pipeline , name ) ) {
|
if ( !useExistingProgram( pipeline , name ) ) {
|
||||||
return;
|
initProgramRecord( name ).plReferences.add( pipeline );
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t index( newProgramRecord( ) );
|
|
||||||
auto& program( programs_[ index ] );
|
|
||||||
programIndex_.add( name , index );
|
|
||||||
program.name = name;
|
|
||||||
program.references.add( pipeline );
|
|
||||||
program.id = 0;
|
|
||||||
initProgram( program );
|
|
||||||
|
|
||||||
T_StringBuilder sb;
|
|
||||||
for ( auto const& e : program.code.errors ) {
|
|
||||||
sb << e.source << ':' << e.line << ": "
|
|
||||||
<< e.error << '\n';
|
|
||||||
}
|
|
||||||
sb << '\0';
|
|
||||||
printf( "%s" , sb.data( ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool T_ShaderManager::useExistingProgram(
|
bool T_ShaderManager::useExistingProgram(
|
||||||
|
@ -716,12 +803,67 @@ bool T_ShaderManager::useExistingProgram(
|
||||||
if ( !pos ) {
|
if ( !pos ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto& refs( programs_[ *pos ].references );
|
auto& refs( programs_[ *pos ].plReferences );
|
||||||
assert( !refs.contains( pipeline ) );
|
assert( !refs.contains( pipeline ) );
|
||||||
refs.add( pipeline );
|
refs.add( pipeline );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void T_ShaderManager::loadProgram(
|
||||||
|
T_String const& name )
|
||||||
|
{
|
||||||
|
if ( useExistingProgram( name ) ) {
|
||||||
|
initProgramRecord( name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_ShaderManager::useExistingProgram(
|
||||||
|
T_String const& name )
|
||||||
|
{
|
||||||
|
auto const* pos( programIndex_.get( name ) );
|
||||||
|
if ( !pos ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
programs_[ *pos ].saReferences ++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t T_ShaderManager::newProgramRecord( )
|
||||||
|
{
|
||||||
|
uint32_t i = 0;
|
||||||
|
while ( i < programs_.size( ) ) {
|
||||||
|
if ( programs_[ i ].plReferences.empty( )
|
||||||
|
&& !programs_[ i ].saReferences ) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
i ++;
|
||||||
|
}
|
||||||
|
programs_.addNew( );
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
T_ShaderManager::T_Program_& T_ShaderManager::initProgramRecord(
|
||||||
|
T_String const& name )
|
||||||
|
{
|
||||||
|
const uint32_t index( newProgramRecord( ) );
|
||||||
|
auto& program( programs_[ index ] );
|
||||||
|
programIndex_.add( name , index );
|
||||||
|
program.name = name;
|
||||||
|
program.id = 0;
|
||||||
|
initProgram( program );
|
||||||
|
|
||||||
|
T_StringBuilder sb;
|
||||||
|
for ( auto const& e : program.code.errors ) {
|
||||||
|
sb << e.source << ':' << e.line << ": "
|
||||||
|
<< e.error << '\n';
|
||||||
|
}
|
||||||
|
sb << '\0';
|
||||||
|
printf( "%s" , sb.data( ) );
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
T_ShaderInput const* T_ShaderManager::getInput(
|
T_ShaderInput const* T_ShaderManager::getInput(
|
||||||
T_String const& name )
|
T_String const& name )
|
||||||
|
@ -772,11 +914,25 @@ void T_ShaderManager::dereferenceProgram(
|
||||||
T_String const& pipeline )
|
T_String const& pipeline )
|
||||||
{
|
{
|
||||||
auto& program( programs_[ index ] );
|
auto& program( programs_[ index ] );
|
||||||
auto& refs( program.references );
|
auto& refs( program.plReferences );
|
||||||
const auto plidx( refs.indexOf( pipeline ) );
|
const auto plidx( refs.indexOf( pipeline ) );
|
||||||
assert( plidx >= 0 );
|
assert( plidx >= 0 );
|
||||||
refs.remove( plidx );
|
refs.remove( plidx );
|
||||||
if ( refs.size( ) != 0 ) {
|
if ( !refs.empty( ) || program.saReferences ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resetProgram( program );
|
||||||
|
programIndex_.remove( program.name );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void T_ShaderManager::dereferenceProgram(
|
||||||
|
const uint32_t index )
|
||||||
|
{
|
||||||
|
auto& program( programs_[ index ] );
|
||||||
|
assert( program.saReferences > 0 );
|
||||||
|
program.saReferences --;
|
||||||
|
if ( program.saReferences || !program.plReferences.empty( ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resetProgram( program );
|
resetProgram( program );
|
||||||
|
@ -997,12 +1153,15 @@ void T_ShaderManager::makeUI( )
|
||||||
ImGui::Begin( "Shaders" );
|
ImGui::Begin( "Shaders" );
|
||||||
|
|
||||||
const auto n( std::count_if( programs_.begin( ) , programs_.end( ) ,
|
const auto n( std::count_if( programs_.begin( ) , programs_.end( ) ,
|
||||||
[]( auto const& p ) { return !p.references.empty( ); } ) );
|
[]( auto const& p ) {
|
||||||
|
return !p.plReferences.empty( ) || p.saReferences != 0;
|
||||||
|
} ) );
|
||||||
|
|
||||||
std::vector< size_t > indices;
|
std::vector< size_t > indices;
|
||||||
const auto rn = programs_.size( );
|
const auto rn = programs_.size( );
|
||||||
for ( auto i = 0u ; i < rn ; i ++ ) {
|
for ( auto i = 0u ; i < rn ; i ++ ) {
|
||||||
if ( !programs_[ i ].references.empty( ) ) {
|
auto const& p( programs_[ i ] );
|
||||||
|
if ( !p.plReferences.empty( ) || p.saReferences ) {
|
||||||
indices.push_back( i );
|
indices.push_back( i );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1013,8 +1172,8 @@ void T_ShaderManager::makeUI( )
|
||||||
if ( pa.code.errors.size( ) != pb.code.errors.size( ) ) {
|
if ( pa.code.errors.size( ) != pb.code.errors.size( ) ) {
|
||||||
return pa.code.errors.size( ) > pb.code.errors.size( );
|
return pa.code.errors.size( ) > pb.code.errors.size( );
|
||||||
}
|
}
|
||||||
if ( pa.references.size( ) != pb.references.size( ) ) {
|
if ( pa.plReferences.size( ) != pb.plReferences.size( ) ) {
|
||||||
return pa.references.size( ) > pb.references.size( );
|
return pa.plReferences.size( ) > pb.plReferences.size( );
|
||||||
}
|
}
|
||||||
return programs_[ a ].name < programs_[ b ].name;
|
return programs_[ a ].name < programs_[ b ].name;
|
||||||
} );
|
} );
|
||||||
|
@ -1034,7 +1193,7 @@ void T_ShaderManager::makeUI( )
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine( 400 );
|
ImGui::SameLine( 400 );
|
||||||
ImGui::Text( "Usage: %u" , program.references.size( ) );
|
ImGui::Text( "Usage: %u" , program.plReferences.size( ) + program.saReferences );
|
||||||
ImGui::SameLine( 550 );
|
ImGui::SameLine( 550 );
|
||||||
if ( program.code.errors.empty( ) ) {
|
if ( program.code.errors.empty( ) ) {
|
||||||
ImGui::PushStyleColor( ImGuiCol_Text , ImVec4( .6 , 1 , .6 , 1 ) );
|
ImGui::PushStyleColor( ImGuiCol_Text , ImVec4( .6 , 1 , .6 , 1 ) );
|
||||||
|
|
39
shaders.hh
39
shaders.hh
|
@ -119,6 +119,26 @@ struct T_ShaderError
|
||||||
|
|
||||||
struct T_ShaderManager;
|
struct T_ShaderManager;
|
||||||
|
|
||||||
|
struct T_ShaderProgram
|
||||||
|
{
|
||||||
|
friend struct T_ShaderManager;
|
||||||
|
|
||||||
|
T_ShaderProgram( );
|
||||||
|
COPY( T_ShaderProgram );
|
||||||
|
MOVE( T_ShaderProgram );
|
||||||
|
~T_ShaderProgram( );
|
||||||
|
|
||||||
|
bool valid( ) const noexcept;
|
||||||
|
void enable( ) const;
|
||||||
|
GLuint id( ) const;
|
||||||
|
T_Optional< E_ShaderType > type( ) const;
|
||||||
|
T_String name( ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit T_ShaderProgram( uint32_t id ) noexcept;
|
||||||
|
uint32_t id_;
|
||||||
|
};
|
||||||
|
|
||||||
struct T_ShaderPipeline
|
struct T_ShaderPipeline
|
||||||
{
|
{
|
||||||
friend struct T_ShaderManager;
|
friend struct T_ShaderManager;
|
||||||
|
@ -143,6 +163,7 @@ struct T_ShaderPipeline
|
||||||
struct T_ShaderManager
|
struct T_ShaderManager
|
||||||
{
|
{
|
||||||
friend struct T_ShaderPipeline;
|
friend struct T_ShaderPipeline;
|
||||||
|
friend struct T_ShaderProgram;
|
||||||
|
|
||||||
struct T_ShaderCode
|
struct T_ShaderCode
|
||||||
{
|
{
|
||||||
|
@ -157,6 +178,7 @@ struct T_ShaderManager
|
||||||
|
|
||||||
T_ShaderManager( ) noexcept;
|
T_ShaderManager( ) noexcept;
|
||||||
|
|
||||||
|
T_ShaderProgram program( T_String const& name );
|
||||||
T_ShaderPipeline pipeline(
|
T_ShaderPipeline pipeline(
|
||||||
std::initializer_list< T_String > shaders );
|
std::initializer_list< T_String > shaders );
|
||||||
|
|
||||||
|
@ -183,7 +205,8 @@ struct T_ShaderManager
|
||||||
struct T_Program_
|
struct T_Program_
|
||||||
{
|
{
|
||||||
T_String name;
|
T_String name;
|
||||||
T_Array< T_String > references;
|
T_Array< T_String > plReferences;
|
||||||
|
uint32_t saReferences{ 0 };
|
||||||
T_ShaderCode code;
|
T_ShaderCode code;
|
||||||
GLuint id;
|
GLuint id;
|
||||||
T_Optional< T_WatchedFiles > watch;
|
T_Optional< T_WatchedFiles > watch;
|
||||||
|
@ -201,8 +224,7 @@ struct T_ShaderManager
|
||||||
T_KeyValueTable< T_String , T_Array< T_String > > missing_;
|
T_KeyValueTable< T_String , T_Array< T_String > > missing_;
|
||||||
T_Array< T_String > updates_;
|
T_Array< T_String > updates_;
|
||||||
|
|
||||||
uint32_t newProgramRecord( );
|
// Load/use existing program for use with pipelines
|
||||||
|
|
||||||
void loadProgram(
|
void loadProgram(
|
||||||
T_String const& pipeline ,
|
T_String const& pipeline ,
|
||||||
T_String const& name );
|
T_String const& name );
|
||||||
|
@ -210,6 +232,15 @@ struct T_ShaderManager
|
||||||
T_String const& pipeline ,
|
T_String const& pipeline ,
|
||||||
T_String const& name );
|
T_String const& name );
|
||||||
|
|
||||||
|
// Load/use existing program for standalone use
|
||||||
|
void loadProgram( T_String const& name );
|
||||||
|
bool useExistingProgram( T_String const& name );
|
||||||
|
|
||||||
|
// Program management
|
||||||
|
T_Program_& initProgramRecord( // Init management data
|
||||||
|
T_String const& record );
|
||||||
|
uint32_t newProgramRecord( ); // Allocate entry in index
|
||||||
|
|
||||||
T_ShaderInput const* getInput(
|
T_ShaderInput const* getInput(
|
||||||
T_String const& name );
|
T_String const& name );
|
||||||
|
|
||||||
|
@ -217,6 +248,8 @@ struct T_ShaderManager
|
||||||
void dereferenceProgram(
|
void dereferenceProgram(
|
||||||
const uint32_t index ,
|
const uint32_t index ,
|
||||||
T_String const& pipeline );
|
T_String const& pipeline );
|
||||||
|
void dereferenceProgram(
|
||||||
|
const uint32_t index );
|
||||||
|
|
||||||
void initPipeline( T_Pipeline_& pipeline ) const;
|
void initPipeline( T_Pipeline_& pipeline ) const;
|
||||||
void initProgram( T_Program_& program );
|
void initProgram( T_Program_& program );
|
||||||
|
|
Loading…
Reference in a new issue