Ignore:
Timestamp:
08/08/14 13:18:41 (11 years ago)
Author:
epyon
Message:
  • program is now handle-based
  • all device constructs are now handle-based and do not dynamically allocate
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gl/gl_device.cc

    r302 r303  
    66
    77#include "nv/gl/gl_window.hh"
    8 #include "nv/gl/gl_program.hh"
    98#include "nv/logging.hh"
    109#include "nv/lib/sdl.hh"
     
    5049}
    5150
    52 program* gl_device::create_program( const string& vs_source, const string& fs_source )
    53 {
    54         return new gl_program( vs_source, fs_source );
     51program gl_device::create_program( const string& vs_source, const string& fs_source )
     52{
     53        program result = m_programs.create();
     54        gl_program_info* info = m_programs.get( result );
     55
     56        info->glid = glCreateProgram();
     57        compile( info, vs_source, fs_source );
     58        prepare_program( result );
     59        return result;
    5560}
    5661
     
    8590gl_device::~gl_device()
    8691{
     92        while ( m_vertex_arrays.size() > 0 )
     93                release( m_vertex_arrays.get_handle(0) );
    8794        while ( m_textures.size() > 0 )
    8895                release( m_textures.get_handle(0) );
    8996        while ( m_buffers.size() > 0 )
    9097                release( m_buffers.get_handle(0) );
     98        while ( m_programs.size() > 0 )
     99                release( m_programs.get_handle(0) );
    91100
    92101        SDL_Quit();
     
    154163}
    155164
    156 const texture_info* nv::gl_device::get_texture_info( texture t )
     165const texture_info* nv::gl_device::get_texture_info( texture t ) const
    157166{
    158167        return m_textures.get( t );
     
    178187}
    179188
    180 const buffer_info* nv::gl_device::get_buffer_info( buffer t )
     189const buffer_info* nv::gl_device::get_buffer_info( buffer t ) const
    181190{
    182191        return m_buffers.get( t );
    183192}
     193
     194nv::vertex_array nv::gl_device::create_vertex_array()
     195{
     196        vertex_array result = m_vertex_arrays.create();
     197        vertex_array_info* info = m_vertex_arrays.get( result );
     198        info->count       = 0;
     199        info->index       = buffer();
     200        info->index_owner = false;
     201        info->index_type  = USHORT;
     202        return result;
     203}
     204
     205void nv::gl_device::release( vertex_array va )
     206{
     207        vertex_array_info* info = m_vertex_arrays.get( va );
     208        if ( info )
     209        {
     210                for ( uint32 i = 0; i < info->count; ++i )
     211                {
     212                        if ( info->attr[i].owner ) release( info->attr[i].vbuffer );
     213                }
     214                if ( info->index.is_valid() && info->index_owner) release( info->index );
     215                m_vertex_arrays.destroy( va );
     216        }
     217}
     218
     219void nv::gl_device::release( program p )
     220{
     221        gl_program_info* info = m_programs.get( p );
     222        if ( info )
     223        {
     224                for ( auto& i : info->m_uniform_map )
     225                        delete i.second;
     226
     227                glDetachShader( info->glid, info->glidv );
     228                glDetachShader( info->glid, info->glidf );
     229                glDeleteShader( info->glidv );
     230                glDeleteShader( info->glidf );
     231                glDeleteProgram( info->glid );
     232
     233                m_programs.destroy( p );
     234        }
     235}
     236
     237const vertex_array_info* nv::gl_device::get_vertex_array_info( vertex_array va ) const
     238{
     239        return m_vertex_arrays.get( va );
     240}
     241
     242vertex_array_info* nv::gl_device::get_vertex_array_info_mutable( vertex_array va )
     243{
     244        return m_vertex_arrays.get( va );
     245}
     246
     247void nv::gl_device::prepare_program( program p )
     248{
     249        gl_program_info* info = m_programs.get( p );
     250        if ( info )
     251        {
     252                auto& map  = get_uniform_factory();
     253                auto& lmap = get_link_uniform_factory();
     254
     255                for ( auto& i : info->m_uniform_map )
     256                {
     257                        auto j = lmap.find( i.first );
     258                        if ( j != lmap.end() )
     259                        {
     260                                j->second->set( i.second );
     261                        }                       
     262
     263                        auto k = map.find( i.first );
     264                        if ( k != map.end() )
     265                        {
     266                                info->m_engine_uniforms.push_back( k->second->create( i.second ) );
     267                        }                               
     268                }
     269        }
     270}
     271
     272uniform_base* nv::gl_device::get_uniform( program p, const string& name, bool fatal /*= true */ ) const
     273{
     274        const gl_program_info* info = m_programs.get( p );
     275        {
     276                uniform_map::const_iterator i = info->m_uniform_map.find( name );
     277                if ( i != info->m_uniform_map.end() )
     278                {
     279                        return i->second;
     280                }
     281                if ( fatal )
     282                {
     283                        NV_LOG( LOG_ERROR, "Uniform '" << name << "' not found in program!" );
     284                        NV_THROW( runtime_error, ( "Uniform '"+name+"' not found!" ) );
     285                }
     286        }
     287        return nullptr;
     288}
     289
     290int nv::gl_device::get_attribute_location( program p, const string& name, bool fatal /*= true */ ) const
     291{
     292        const gl_program_info* info = m_programs.get( p );
     293        if ( info )
     294        {
     295                attribute_map::const_iterator i = info->m_attribute_map.find( name );
     296                if ( i != info->m_attribute_map.end() )
     297                {
     298                        return i->second.location;
     299                }
     300                if ( fatal )
     301                {
     302                        NV_LOG( LOG_ERROR, "Attribute '" << name << "' not found in program!" );
     303                        NV_THROW( runtime_error, ( "Attribute '"+name+"' not found!" ) );
     304                }
     305        }
     306        return -1;
     307}
     308
     309bool nv::gl_device::compile( gl_program_info* p, const string& vertex_program, const string& fragment_program )
     310{
     311        if (!compile( GL_VERTEX_SHADER,   vertex_program, p->glidv ))   { return false; }
     312        if (!compile( GL_FRAGMENT_SHADER, fragment_program, p->glidf )) { return false; }
     313
     314        glBindAttribLocation( p->glid, static_cast<GLuint>( slot::POSITION   ), "nv_position"  );
     315        glBindAttribLocation( p->glid, static_cast<GLuint>( slot::TEXCOORD   ), "nv_texcoord"  );
     316        glBindAttribLocation( p->glid, static_cast<GLuint>( slot::NORMAL     ), "nv_normal"    );
     317        glBindAttribLocation( p->glid, static_cast<GLuint>( slot::COLOR      ), "nv_color"     );
     318        glBindAttribLocation( p->glid, static_cast<GLuint>( slot::TANGENT    ), "nv_tangent"   );
     319        glBindAttribLocation( p->glid, static_cast<GLuint>( slot::BONEINDEX  ), "nv_boneindex" );
     320        glBindAttribLocation( p->glid, static_cast<GLuint>( slot::BONEWEIGHT ), "nv_boneweight");
     321
     322        glAttachShader( p->glid, p->glidf );
     323        glAttachShader( p->glid, p->glidv );
     324        glLinkProgram( p->glid );
     325
     326        const uint32 buffer_size = 2048;
     327        char buffer[ buffer_size ] = { 0 };
     328        int length;
     329        int status;
     330
     331        glGetProgramiv( p->glid, GL_LINK_STATUS, &status );
     332        glGetProgramInfoLog( p->glid, buffer_size, &length, buffer );
     333
     334        NV_LOG( LOG_INFO, "Program #" << p->glid << (status == GL_FALSE ? " failed to compile!" : " compiled successfully.") );
     335
     336        if ( length > 0 )
     337        {
     338                NV_LOG( LOG_INFO, "Program #" << p->glid << " log: " << buffer );
     339        }
     340
     341        if ( status == GL_FALSE )
     342        {
     343                return false;
     344        }
     345
     346        glValidateProgram( p->glid );
     347        glGetProgramiv( p->glid, GL_VALIDATE_STATUS, &status );
     348
     349        if ( status == GL_FALSE )
     350        {
     351                glGetProgramInfoLog( p->glid, buffer_size, &length, buffer );
     352                NV_LOG( LOG_ERROR, "Program #" << p->glid << " validation error : " << buffer );
     353                return false;
     354        }
     355        load_attributes( p );
     356        load_uniforms( p );
     357        return true;
     358}
     359
     360void nv::gl_device::update_uniforms( gl_program_info* p )
     361{
     362        for ( uniform_map::iterator i = p->m_uniform_map.begin();       i != p->m_uniform_map.end(); ++i )
     363        {
     364                uniform_base* ubase = i->second;
     365                if ( ubase->is_dirty() )
     366                {
     367                        int uloc = ubase->get_location();
     368                        switch( ubase->get_type() )
     369                        {
     370                        case FLOAT          : glUniform1fv( uloc, ubase->get_length(), ((uniform< enum_to_type< FLOAT >::type >*)( ubase ))->get_value() ); break;
     371                        case INT            : glUniform1iv( uloc, ubase->get_length(), ((uniform< enum_to_type< INT >::type >*)( ubase ))->get_value() ); break;
     372                        case FLOAT_VECTOR_2 : glUniform2fv( uloc, ubase->get_length(), (GLfloat*)((uniform< enum_to_type< FLOAT_VECTOR_2 >::type >*)( ubase ))->get_value()); break;
     373                        case FLOAT_VECTOR_3 : glUniform3fv( uloc, ubase->get_length(), (GLfloat*)((uniform< enum_to_type< FLOAT_VECTOR_3 >::type >*)( ubase ))->get_value()); break;
     374                        case FLOAT_VECTOR_4 : glUniform4fv( uloc, ubase->get_length(), (GLfloat*)((uniform< enum_to_type< FLOAT_VECTOR_4 >::type >*)( ubase ))->get_value()); break;
     375                        case INT_VECTOR_2   : glUniform2iv( uloc, ubase->get_length(), (GLint*)((uniform< enum_to_type< INT_VECTOR_2 >::type >*)( ubase ))->get_value()); break;
     376                        case INT_VECTOR_3   : glUniform3iv( uloc, ubase->get_length(), (GLint*)((uniform< enum_to_type< INT_VECTOR_3 >::type >*)( ubase ))->get_value()); break;
     377                        case INT_VECTOR_4   : glUniform4iv( uloc, ubase->get_length(), (GLint*)((uniform< enum_to_type< INT_VECTOR_4 >::type >*)( ubase ))->get_value()); break;
     378                        case FLOAT_MATRIX_2 : glUniformMatrix2fv( uloc, ubase->get_length(), GL_FALSE, (GLfloat*)((uniform< enum_to_type< FLOAT_MATRIX_2 >::type >*)( ubase ))->get_value()); break;
     379                        case FLOAT_MATRIX_3 : glUniformMatrix3fv( uloc, ubase->get_length(), GL_FALSE, (GLfloat*)((uniform< enum_to_type< FLOAT_MATRIX_3 >::type >*)( ubase ))->get_value()); break;
     380                        case FLOAT_MATRIX_4 : glUniformMatrix4fv( uloc, ubase->get_length(), GL_FALSE, (GLfloat*)((uniform< enum_to_type< FLOAT_MATRIX_4 >::type >*)( ubase ))->get_value()); break;
     381                        default : break; // error?
     382                        }
     383                        ubase->clean();
     384                }
     385        }
     386}
     387
     388void nv::gl_device::load_attributes( gl_program_info* p )
     389{
     390        int params;
     391        glGetProgramiv( p->glid, GL_ACTIVE_ATTRIBUTES, &params );
     392
     393        for ( unsigned i = 0; i < (unsigned)params; ++i )
     394        {
     395                int attr_nlen;
     396                int attr_len;
     397                unsigned attr_type;
     398                char name_buffer[128];
     399
     400                glGetActiveAttrib( p->glid, i, 128, &attr_nlen, &attr_len, &attr_type, name_buffer );
     401
     402                string name( name_buffer, size_t(attr_nlen) );
     403
     404                // skip built-ins
     405                if ( name.substr(0,3) == "gl_" ) continue;
     406
     407                int attr_loc = glGetAttribLocation( p->glid, name.c_str() );
     408
     409                attribute& attr = p->m_attribute_map[ name ];
     410                attr.name     = name;
     411                attr.location = attr_loc;
     412                attr.type     = gl_enum_to_datatype( attr_type );
     413                attr.length   = attr_len;
     414        }
     415}
     416
     417void nv::gl_device::load_uniforms( gl_program_info* p )
     418{
     419        int params;
     420        glGetProgramiv( p->glid, GL_ACTIVE_UNIFORMS, &params );
     421
     422        for ( unsigned i = 0; i < size_t(params); ++i )
     423        {
     424                int uni_nlen;
     425                int uni_len;
     426                unsigned uni_type;
     427                char name_buffer[128];
     428
     429                glGetActiveUniform( p->glid, i, 128, &uni_nlen, &uni_len, &uni_type, name_buffer );
     430
     431                string name( name_buffer, size_t(uni_nlen) );
     432
     433                // skip built-ins
     434                if ( name.substr(0,3) == "gl_" ) continue;
     435
     436                int uni_loc = glGetUniformLocation( p->glid, name.c_str() );
     437                datatype utype = gl_enum_to_datatype( uni_type );
     438
     439                // check for array
     440                string::size_type arrchar = name.find('[');
     441                if ( arrchar != string::npos )
     442                {
     443                        name = name.substr( 0, arrchar );
     444                }
     445
     446                uniform_base* u = uniform_base::create( utype, name, uni_loc, uni_len );
     447                NV_ASSERT( u, "Unknown uniform type!" );
     448                p->m_uniform_map[ name ] = u;
     449        }
     450}
     451
     452bool nv::gl_device::compile( uint32 sh_type, const std::string& shader_code, unsigned& glid )
     453{
     454        glid = glCreateShader( sh_type );
     455
     456        const char* pc = shader_code.c_str();
     457
     458        glShaderSource( glid,   1, &pc, 0 );
     459        glCompileShader( glid );
     460
     461        const uint32 buffer_size = 1024;
     462        char buffer[ buffer_size ] = { 0 };
     463        int length;
     464        int compile_ok = GL_FALSE;
     465        glGetShaderiv(glid, GL_COMPILE_STATUS, &compile_ok);
     466        glGetShaderInfoLog( glid, buffer_size, &length, buffer );
     467
     468        if ( length > 0 )
     469        {
     470                if ( compile_ok == 0 )
     471                {
     472                        NV_LOG( LOG_ERROR, "Shader #" << glid << " error: " << buffer );
     473                }
     474                else
     475                {
     476                        NV_LOG( LOG_INFO, "Shader #" << glid << " compiled successfully: " << buffer );
     477                }
     478        }
     479        else
     480        {
     481                NV_LOG( LOG_INFO, "Shader #" << glid << " compiled successfully." );
     482        }
     483        return compile_ok != 0;
     484
     485}
     486
     487
Note: See TracChangeset for help on using the changeset viewer.