root/OpenSceneGraph/trunk/src/osg/Program.cpp @ 13041

Revision 13041, 25.9 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 * Copyright (C) 2003-2005 3Dlabs Inc. Ltd.
3 * Copyright (C) 2004-2005 Nathan Cournia
4 * Copyright (C) 2008 Zebra Imaging
5 * Copyright (C) 2010 VIRES Simulationstechnologie GmbH
6 *
7 * This application is open source and may be redistributed and/or modified
8 * freely and without restriction, both in commercial and non commercial
9 * applications, as long as this copyright notice is maintained.
10 *
11 * This application is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 *
15*/
16
17/* file:        src/osg/Program.cpp
18 * author:      Mike Weiblen 2008-01-19
19 *              Holger Helmich 2010-10-21
20*/
21
22#include <list>
23#include <fstream>
24
25#include <osg/Notify>
26#include <osg/State>
27#include <osg/Timer>
28#include <osg/buffered_value>
29#include <osg/ref_ptr>
30#include <osg/Program>
31#include <osg/Shader>
32#include <osg/GL2Extensions>
33
34#include <OpenThreads/ScopedLock>
35#include <OpenThreads/Mutex>
36
37#include <string.h>
38
39using namespace osg;
40
41///////////////////////////////////////////////////////////////////////////
42// static cache of glPrograms flagged for deletion, which will actually
43// be deleted in the correct GL context.
44
45typedef std::list<GLuint> GlProgramHandleList;
46typedef osg::buffered_object<GlProgramHandleList> DeletedGlProgramCache;
47
48static OpenThreads::Mutex    s_mutex_deletedGlProgramCache;
49static DeletedGlProgramCache s_deletedGlProgramCache;
50
51void Program::deleteGlProgram(unsigned int contextID, GLuint program)
52{
53    if( program )
54    {
55        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGlProgramCache);
56
57        // add glProgram to the cache for the appropriate context.
58        s_deletedGlProgramCache[contextID].push_back(program);
59    }
60}
61
62void Program::flushDeletedGlPrograms(unsigned int contextID,double /*currentTime*/, double& availableTime)
63{
64    // if no time available don't try to flush objects.
65    if (availableTime<=0.0) return;
66
67    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGlProgramCache);
68    const GL2Extensions* extensions = GL2Extensions::Get(contextID,true);
69    if( ! extensions->isGlslSupported() ) return;
70
71    const osg::Timer& timer = *osg::Timer::instance();
72    osg::Timer_t start_tick = timer.tick();
73    double elapsedTime = 0.0;
74
75    {
76
77        GlProgramHandleList& pList = s_deletedGlProgramCache[contextID];
78        for(GlProgramHandleList::iterator titr=pList.begin();
79            titr!=pList.end() && elapsedTime<availableTime;
80            )
81        {
82            extensions->glDeleteProgram( *titr );
83            titr = pList.erase( titr );
84            elapsedTime = timer.delta_s(start_tick,timer.tick());
85        }
86    }
87
88    availableTime -= elapsedTime;
89}
90
91void Program::discardDeletedGlPrograms(unsigned int contextID)
92{
93    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGlProgramCache);
94    GlProgramHandleList& pList = s_deletedGlProgramCache[contextID];
95    pList.clear();
96}
97
98
99///////////////////////////////////////////////////////////////////////////
100// osg::Program::ProgramBinary
101///////////////////////////////////////////////////////////////////////////
102
103Program::ProgramBinary::ProgramBinary() : _format(0)
104{
105}
106
107Program::ProgramBinary::ProgramBinary(const ProgramBinary& rhs, const osg::CopyOp&) :
108    _data(rhs._data), _format(rhs._format)
109{
110}
111
112void Program::ProgramBinary::allocate(unsigned int size)
113{
114    _data.clear();
115    _data.resize(size);
116}
117
118void Program::ProgramBinary::assign(unsigned int size, const unsigned char* data)
119{
120    allocate(size);
121    if (data)
122    {
123        for(unsigned int i=0; i<size; ++i)
124        {
125            _data[i] = data[i];
126        }
127    }
128}
129
130
131///////////////////////////////////////////////////////////////////////////
132// osg::Program
133///////////////////////////////////////////////////////////////////////////
134
135Program::Program() :
136    _geometryVerticesOut(1), _geometryInputType(GL_TRIANGLES),
137    _geometryOutputType(GL_TRIANGLE_STRIP),
138    _patchVertices(3)
139{
140}
141
142
143Program::Program(const Program& rhs, const osg::CopyOp& copyop):
144    osg::StateAttribute(rhs, copyop)
145{
146    for( unsigned int shaderIndex=0; shaderIndex < rhs.getNumShaders(); ++shaderIndex )
147    {
148        addShader( new osg::Shader( *rhs.getShader( shaderIndex ), copyop ) );
149    }
150
151    const osg::Program::AttribBindingList &abl = rhs.getAttribBindingList();
152    for( osg::Program::AttribBindingList::const_iterator attribute = abl.begin(); attribute != abl.end(); ++attribute )
153    {
154        addBindAttribLocation( attribute->first, attribute->second );
155    }
156
157    const osg::Program::FragDataBindingList &fdl = rhs.getFragDataBindingList();
158    for( osg::Program::FragDataBindingList::const_iterator fragdata = fdl.begin(); fragdata != fdl.end(); ++fragdata )
159    {
160        addBindFragDataLocation( fragdata->first, fragdata->second );
161    }
162
163    _geometryVerticesOut = rhs._geometryVerticesOut;
164    _geometryInputType = rhs._geometryInputType;
165    _geometryOutputType = rhs._geometryOutputType;
166
167    _patchVertices = rhs._patchVertices;
168}
169
170
171Program::~Program()
172{
173    // inform any attached Shaders that we're going away
174    for( unsigned int i=0; i < _shaderList.size(); ++i )
175    {
176        _shaderList[i]->removeProgramRef( this );
177    }
178}
179
180
181int Program::compare(const osg::StateAttribute& sa) const
182{
183    // check the types are equal and then create the rhs variable
184    // used by the COMPARE_StateAttribute_Parameter macros below.
185    COMPARE_StateAttribute_Types(Program,sa)
186
187    if( _shaderList.size() < rhs._shaderList.size() ) return -1;
188    if( rhs._shaderList.size() < _shaderList.size() ) return 1;
189
190    if( getName() < rhs.getName() ) return -1;
191    if( rhs.getName() < getName() ) return 1;
192
193    if( _geometryVerticesOut < rhs._geometryVerticesOut ) return -1;
194    if( rhs._geometryVerticesOut < _geometryVerticesOut ) return 1;
195
196    if( _geometryInputType < rhs._geometryInputType ) return -1;
197    if( rhs._geometryInputType < _geometryInputType ) return 1;
198
199    if( _geometryOutputType < rhs._geometryOutputType ) return -1;
200    if( rhs._geometryOutputType < _geometryOutputType ) return 1;
201
202    if( _patchVertices < rhs._patchVertices ) return -1;
203    if( rhs._patchVertices < _patchVertices ) return 1;
204
205    ShaderList::const_iterator litr=_shaderList.begin();
206    ShaderList::const_iterator ritr=rhs._shaderList.begin();
207    for(;
208        litr!=_shaderList.end();
209        ++litr,++ritr)
210    {
211        int result = (*litr)->compare(*(*ritr));
212        if (result!=0) return result;
213    }
214
215    return 0; // passed all the above comparison macros, must be equal.
216}
217
218
219void Program::compileGLObjects( osg::State& state ) const
220{
221    if( isFixedFunction() ) return;
222
223    const unsigned int contextID = state.getContextID();
224
225    for( unsigned int i=0; i < _shaderList.size(); ++i )
226    {
227        _shaderList[i]->compileShader( state );
228    }
229
230    getPCP( contextID )->linkProgram(state);
231}
232
233void Program::setThreadSafeRefUnref(bool threadSafe)
234{
235    StateAttribute::setThreadSafeRefUnref(threadSafe);
236
237    for( unsigned int i=0; i < _shaderList.size(); ++i )
238    {
239        if (_shaderList[i].valid()) _shaderList[i]->setThreadSafeRefUnref(threadSafe);
240    }
241}
242
243void Program::dirtyProgram()
244{
245    // mark our PCPs as needing relink
246    for( unsigned int cxt=0; cxt < _pcpList.size(); ++cxt )
247    {
248        if( _pcpList[cxt].valid() ) _pcpList[cxt]->requestLink();
249    }
250}
251
252
253void Program::resizeGLObjectBuffers(unsigned int maxSize)
254{
255    for( unsigned int i=0; i < _shaderList.size(); ++i )
256    {
257        if (_shaderList[i].valid()) _shaderList[i]->resizeGLObjectBuffers(maxSize);
258    }
259
260    _pcpList.resize(maxSize);
261}
262
263void Program::releaseGLObjects(osg::State* state) const
264{
265    for( unsigned int i=0; i < _shaderList.size(); ++i )
266    {
267        if (_shaderList[i].valid()) _shaderList[i]->releaseGLObjects(state);
268    }
269
270    if (!state) _pcpList.setAllElementsTo(0);
271    else
272    {
273        unsigned int contextID = state->getContextID();
274        _pcpList[contextID] = 0;
275    }
276}
277
278bool Program::addShader( Shader* shader )
279{
280    if( !shader ) return false;
281
282    // Shader can only be added once to a Program
283    for( unsigned int i=0; i < _shaderList.size(); ++i )
284    {
285        if( shader == _shaderList[i].get() ) return false;
286    }
287
288    // Add shader to PCPs
289    for( unsigned int cxt=0; cxt < _pcpList.size(); ++cxt )
290    {
291        if( _pcpList[cxt].valid() ) _pcpList[cxt]->addShaderToAttach( shader );
292    }
293
294    shader->addProgramRef( this );
295    _shaderList.push_back( shader );
296    dirtyProgram();
297    return true;
298}
299
300
301bool Program::removeShader( Shader* shader )
302{
303    if( !shader ) return false;
304
305    // Shader must exist to be removed.
306    for( ShaderList::iterator itr = _shaderList.begin();
307         itr != _shaderList.end();
308         ++itr)
309    {
310        if( shader == itr->get() )
311        {
312            // Remove shader from PCPs
313            for( unsigned int cxt=0; cxt < _pcpList.size(); ++cxt )
314            {
315                if( _pcpList[cxt].valid() ) _pcpList[cxt]->addShaderToDetach( shader );
316            }
317
318            shader->removeProgramRef( this );
319            _shaderList.erase(itr);
320
321            dirtyProgram();
322            return true;
323        }
324    }
325
326    return false;
327}
328
329
330void Program::setParameter( GLenum pname, GLint value )
331{
332    switch( pname )
333    {
334        case GL_GEOMETRY_VERTICES_OUT_EXT:
335            _geometryVerticesOut = value;
336            dirtyProgram();
337            break;
338        case GL_GEOMETRY_INPUT_TYPE_EXT:
339            _geometryInputType = value;
340            dirtyProgram();    // needed?
341            break;
342        case GL_GEOMETRY_OUTPUT_TYPE_EXT:
343            _geometryOutputType = value;
344            //dirtyProgram();    // needed?
345            break;
346        case GL_PATCH_VERTICES:
347            _patchVertices = value;
348            dirtyProgram();
349            break;
350        default:
351            OSG_WARN << "setParameter invalid param " << pname << std::endl;
352            break;
353    }
354}
355
356void Program::setParameterfv( GLenum pname, const GLfloat* value )
357{
358    switch( pname )
359    {
360      // todo tessellation default level
361        case GL_PATCH_DEFAULT_INNER_LEVEL:
362            break;
363        case GL_PATCH_DEFAULT_OUTER_LEVEL:
364            break;
365        default:
366            OSG_WARN << "setParameter invalid param " << pname << std::endl;
367            break;
368    }
369}
370
371const GLfloat* Program::getParameterfv( GLenum pname ) const
372{
373    /*switch( pname )
374    {
375      ;
376      // todo tessellation default level
377      //        case GL_PATCH_DEFAULT_INNER_LEVEL: return _patchDefaultInnerLevel;
378      //        case GL_PATCH_DEFAULT_OUTER_LEVEL: return _patchDefaultOuterLevel;
379
380    }*/
381    OSG_WARN << "getParameter invalid param " << pname << std::endl;
382    return 0;
383}
384
385GLint Program::getParameter( GLenum pname ) const
386{
387    switch( pname )
388    {
389        case GL_GEOMETRY_VERTICES_OUT_EXT: return _geometryVerticesOut;
390        case GL_GEOMETRY_INPUT_TYPE_EXT:   return _geometryInputType;
391        case GL_GEOMETRY_OUTPUT_TYPE_EXTreturn _geometryOutputType;
392        case GL_PATCH_VERTICES:            return _patchVertices;
393    }
394    OSG_WARN << "getParameter invalid param " << pname << std::endl;
395    return 0;
396}
397
398
399void Program::addBindAttribLocation( const std::string& name, GLuint index )
400{
401    _attribBindingList[name] = index;
402    dirtyProgram();
403}
404
405void Program::removeBindAttribLocation( const std::string& name )
406{
407    _attribBindingList.erase(name);
408    dirtyProgram();
409}
410
411void Program::addBindFragDataLocation( const std::string& name, GLuint index )
412{
413    _fragDataBindingList[name] = index;
414    dirtyProgram();
415}
416
417void Program::removeBindFragDataLocation( const std::string& name )
418{
419    _fragDataBindingList.erase(name);
420    dirtyProgram();
421}
422
423void Program::addBindUniformBlock(const std::string& name, GLuint index)
424{
425    _uniformBlockBindingList[name] = index;
426    dirtyProgram(); // XXX
427}
428
429void Program::removeBindUniformBlock(const std::string& name)
430{
431    _uniformBlockBindingList.erase(name);
432    dirtyProgram(); // XXX
433}
434
435
436
437
438void Program::apply( osg::State& state ) const
439{
440    const unsigned int contextID = state.getContextID();
441    const GL2Extensions* extensions = GL2Extensions::Get(contextID,true);
442    if( ! extensions->isGlslSupported() ) return;
443
444    if( isFixedFunction() )
445    {
446        extensions->glUseProgram( 0 );
447        state.setLastAppliedProgramObject(0);
448        return;
449    }
450
451    PerContextProgram* pcp = getPCP( contextID );
452    if( pcp->needsLink() ) compileGLObjects( state );
453    if( pcp->isLinked() )
454    {
455        // for shader debugging: to minimize performance impact,
456        // optionally validate based on notify level.
457        // TODO: enable this using notify level, or perhaps its own getenv()?
458        if( osg::isNotifyEnabled(osg::INFO) )
459            pcp->validateProgram();
460
461        pcp->useProgram();
462        state.setLastAppliedProgramObject(pcp);
463    }
464    else
465    {
466        // program not usable, fallback to fixed function.
467        extensions->glUseProgram( 0 );
468        state.setLastAppliedProgramObject(0);
469    }
470}
471
472
473Program::PerContextProgram* Program::getPCP(unsigned int contextID) const
474{
475    if( ! _pcpList[contextID].valid() )
476    {
477        _pcpList[contextID] = new PerContextProgram( this, contextID );
478
479        // attach all PCSs to this new PCP
480        for( unsigned int i=0; i < _shaderList.size(); ++i )
481        {
482            _pcpList[contextID]->addShaderToAttach( _shaderList[i].get() );
483        }
484    }
485
486    return _pcpList[contextID].get();
487}
488
489
490bool Program::isFixedFunction() const
491{
492    // A Program object having no attached Shaders is a special case:
493    // it indicates that programmable shading is to be disabled,
494    // and thus use GL 1.x "fixed functionality" rendering.
495    return _shaderList.empty();
496}
497
498
499bool Program::getGlProgramInfoLog(unsigned int contextID, std::string& log) const
500{
501    return getPCP( contextID )->getInfoLog( log );
502}
503
504const Program::ActiveUniformMap& Program::getActiveUniforms(unsigned int contextID) const
505{
506    return getPCP( contextID )->getActiveUniforms();
507}
508
509const Program::ActiveVarInfoMap& Program::getActiveAttribs(unsigned int contextID) const
510{
511    return getPCP( contextID )->getActiveAttribs();
512}
513
514///////////////////////////////////////////////////////////////////////////
515// osg::Program::PerContextProgram
516// PCP is an OSG abstraction of the per-context glProgram
517///////////////////////////////////////////////////////////////////////////
518
519Program::PerContextProgram::PerContextProgram(const Program* program, unsigned int contextID ) :
520        osg::Referenced(),
521        _loadedBinary(false),
522        _contextID( contextID )
523{
524    _program = program;
525    _extensions = GL2Extensions::Get( _contextID, true );
526    _glProgramHandle = _extensions->glCreateProgram();
527    requestLink();
528}
529
530Program::PerContextProgram::~PerContextProgram()
531{
532    Program::deleteGlProgram( _contextID, _glProgramHandle );
533}
534
535
536void Program::PerContextProgram::requestLink()
537{
538    _needsLink = true;
539    _isLinked = false;
540}
541
542
543void Program::PerContextProgram::linkProgram(osg::State& state)
544{
545    if( ! _needsLink ) return;
546    _needsLink = false;
547
548    OSG_INFO << "Linking osg::Program \"" << _program->getName() << "\""
549             << " id=" << _glProgramHandle
550             << " contextID=" << _contextID
551             <<  std::endl;
552
553    const ProgramBinary* programBinary = _program->getProgramBinary();
554
555    _loadedBinary = false;
556    if (programBinary && programBinary->getSize())
557    {
558        GLint linked = GL_FALSE;
559        _extensions->glProgramBinary( _glProgramHandle, programBinary->getFormat(),
560            reinterpret_cast<const GLvoid*>(programBinary->getData()), programBinary->getSize() );
561        _extensions->glGetProgramiv( _glProgramHandle, GL_LINK_STATUS, &linked );
562        _loadedBinary = _isLinked = (linked == GL_TRUE);
563    }
564
565    if (!_loadedBinary)
566    {
567        if (_extensions->isGeometryShader4Supported())
568        {
569            _extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_VERTICES_OUT_EXT, _program->_geometryVerticesOut );
570            _extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_INPUT_TYPE_EXT, _program->_geometryInputType );
571            _extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_OUTPUT_TYPE_EXT, _program->_geometryOutputType );
572        }
573
574        if (_extensions->areTessellationShadersSupported() )
575        {
576            _extensions->glPatchParameteri( GL_PATCH_VERTICES, _program->_patchVertices );
577            // todo: add default tessellation level
578        }
579
580        // Detach removed shaders
581        for( unsigned int i=0; i < _shadersToDetach.size(); ++i )
582        {
583            _shadersToDetach[i]->detachShader( _contextID, _glProgramHandle );
584        }
585    }
586    _shadersToDetach.clear();
587
588    if (!_loadedBinary)
589    {
590        // Attach new shaders
591        for( unsigned int i=0; i < _shadersToAttach.size(); ++i )
592        {
593            _shadersToAttach[i]->attachShader( _contextID, _glProgramHandle );
594        }
595    }
596    _shadersToAttach.clear();
597
598    _uniformInfoMap.clear();
599    _attribInfoMap.clear();
600    _lastAppliedUniformList.clear();
601
602    if (!_loadedBinary)
603    {
604        // set any explicit vertex attribute bindings
605        const AttribBindingList& programBindlist = _program->getAttribBindingList();
606        for( AttribBindingList::const_iterator itr = programBindlist.begin();
607            itr != programBindlist.end(); ++itr )
608        {
609            OSG_INFO<<"Program's vertex attrib binding "<<itr->second<<", "<<itr->first<<std::endl;
610            _extensions->glBindAttribLocation( _glProgramHandle, itr->second, reinterpret_cast<const GLchar*>(itr->first.c_str()) );
611        }
612
613        // set any explicit vertex attribute bindings that are set up via osg::State, such as the vertex arrays
614        //  that have been aliase to vertex attrib arrays
615        if (state.getUseVertexAttributeAliasing())
616        {
617            const AttribBindingList& stateBindlist = state.getAttributeBindingList();
618            for( AttribBindingList::const_iterator itr = stateBindlist.begin();
619                itr != stateBindlist.end(); ++itr )
620            {
621                OSG_INFO<<"State's vertex attrib binding "<<itr->second<<", "<<itr->first<<std::endl;
622                _extensions->glBindAttribLocation( _glProgramHandle, itr->second, reinterpret_cast<const GLchar*>(itr->first.c_str()) );
623            }
624        }
625
626        // set any explicit frag data bindings
627        const FragDataBindingList& fdbindlist = _program->getFragDataBindingList();
628        for( FragDataBindingList::const_iterator itr = fdbindlist.begin();
629            itr != fdbindlist.end(); ++itr )
630        {
631            _extensions->glBindFragDataLocation( _glProgramHandle, itr->second, reinterpret_cast<const GLchar*>(itr->first.c_str()) );
632        }
633
634        // if any program binary has been set then assume we want to retrieve a binary later.
635        if (programBinary)
636        {
637            _extensions->glProgramParameteri( _glProgramHandle, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE );
638        }
639
640        // link the glProgram
641        GLint linked = GL_FALSE;
642        _extensions->glLinkProgram( _glProgramHandle );
643        _extensions->glGetProgramiv( _glProgramHandle, GL_LINK_STATUS, &linked );
644        _isLinked = (linked == GL_TRUE);
645    }
646
647    if( ! _isLinked )
648    {
649        OSG_WARN << "glLinkProgram \""<< _program->getName() << "\" FAILED" << std::endl;
650
651        std::string infoLog;
652        if( getInfoLog(infoLog) )
653        {
654            OSG_WARN << "Program \""<< _program->getName() << "\" "
655                                      "infolog:\n" << infoLog << std::endl;
656        }
657
658        return;
659    }
660    else
661    {
662        std::string infoLog;
663        if( getInfoLog(infoLog) )
664        {
665            OSG_INFO << "Program \""<< _program->getName() << "\" "<<
666                                      "link succeeded, infolog:\n" << infoLog << std::endl;
667        }
668    }
669
670    if (_extensions->isUniformBufferObjectSupported())
671    {
672        GLuint activeUniformBlocks = 0;
673        GLsizei maxBlockNameLen = 0;
674        _extensions->glGetProgramiv(_glProgramHandle, GL_ACTIVE_UNIFORM_BLOCKS,
675                                    reinterpret_cast<GLint*>(&activeUniformBlocks));
676        _extensions->glGetProgramiv(_glProgramHandle,
677                                    GL_ACTIVE_UNIFORM_MAX_LENGTH,
678                                    &maxBlockNameLen);
679        if (maxBlockNameLen > 0)
680        {
681            std::vector<GLchar> blockName(maxBlockNameLen);
682            for (GLuint i = 0; i < activeUniformBlocks; ++i)
683            {
684                GLsizei len = 0;
685                GLint blockSize = 0;
686                _extensions->glGetActiveUniformBlockName(_glProgramHandle, i,
687                                                         maxBlockNameLen, &len,
688                                                         &blockName[0]);
689                _extensions->glGetActiveUniformBlockiv(_glProgramHandle, i,
690                                                       GL_UNIFORM_BLOCK_DATA_SIZE,
691                                                       &blockSize);
692                _uniformBlockMap
693                    .insert(UniformBlockMap::value_type(&blockName[0],
694                                                        UniformBlockInfo(i, blockSize)));
695            }
696        }
697        // Bind any uniform blocks
698        const UniformBlockBindingList& bindingList = _program->getUniformBlockBindingList();
699        for (UniformBlockMap::iterator itr = _uniformBlockMap.begin(),
700                 end = _uniformBlockMap.end();
701             itr != end;
702            ++itr)
703        {
704            const std::string& blockName = itr->first;
705            UniformBlockBindingList::const_iterator bitr = bindingList.find(blockName);
706            if (bitr != bindingList.end())
707            {
708                _extensions->glUniformBlockBinding(_glProgramHandle, itr->second._index,
709                                                   bitr->second);
710                OSG_INFO << "uniform block " << blockName << ": " << itr->second._index
711                         << " binding: " << bitr->second << "\n";
712            }
713            else
714            {
715                OSG_WARN << "uniform block " << blockName << " has no binding.\n";
716            }
717
718        }
719
720    }
721
722    // build _uniformInfoMap
723    GLint numUniforms = 0;
724    GLsizei maxLen = 0;
725    _extensions->glGetProgramiv( _glProgramHandle, GL_ACTIVE_UNIFORMS, &numUniforms );
726    _extensions->glGetProgramiv( _glProgramHandle, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen );
727    if( (numUniforms > 0) && (maxLen > 1) )
728    {
729        GLint size = 0;
730        GLenum type = 0;
731        GLchar* name = new GLchar[maxLen];
732
733        for( GLint i = 0; i < numUniforms; ++i )
734        {
735            _extensions->glGetActiveUniform( _glProgramHandle,
736                    i, maxLen, 0, &size, &type, name );
737
738            int pos = strlen(name);
739            if (pos>0 && name[pos-1]==']')
740            {
741                // need to trim [..] from end of name as some drivers append this causing problems with look up.
742                --pos;
743                while(pos>0 && name[pos]!='[') { --pos; }
744                name[pos] = 0;
745            }
746
747            GLint loc = _extensions->glGetUniformLocation( _glProgramHandle, name );
748
749            if( loc != -1 )
750            {
751                _uniformInfoMap[Uniform::getNameID(reinterpret_cast<const char*>(name))] = ActiveVarInfo(loc,type,size);
752
753                OSG_INFO << "\tUniform \"" << name << "\""
754                    << " loc="<< loc
755                    << " size="<< size
756                    << " type=" << Uniform::getTypename((Uniform::Type)type)
757                    << std::endl;
758            }
759        }
760        delete [] name;
761    }
762
763    // build _attribInfoMap
764    GLint numAttrib = 0;
765    _extensions->glGetProgramiv( _glProgramHandle, GL_ACTIVE_ATTRIBUTES, &numAttrib );
766    _extensions->glGetProgramiv( _glProgramHandle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLen );
767    if( (numAttrib > 0) && (maxLen > 1) )
768    {
769        GLint size = 0;
770        GLenum type = 0;
771        GLchar* name = new GLchar[maxLen];
772
773        for( GLint i = 0; i < numAttrib; ++i )
774        {
775            _extensions->glGetActiveAttrib( _glProgramHandle,
776                    i, maxLen, 0, &size, &type, name );
777
778            GLint loc = _extensions->glGetAttribLocation( _glProgramHandle, name );
779
780            if( loc != -1 )
781            {
782                _attribInfoMap[reinterpret_cast<char*>(name)] = ActiveVarInfo(loc,type,size);
783
784                OSG_INFO << "\tAttrib \"" << name << "\""
785                         << " loc=" << loc
786                         << " size=" << size
787                         << std::endl;
788            }
789        }
790        delete [] name;
791    }
792    OSG_INFO << std::endl;
793}
794
795bool Program::PerContextProgram::validateProgram()
796{
797    GLint validated = GL_FALSE;
798    _extensions->glValidateProgram( _glProgramHandle );
799    _extensions->glGetProgramiv( _glProgramHandle, GL_VALIDATE_STATUS, &validated );
800    if( validated == GL_TRUE)
801        return true;
802
803    OSG_WARN << "glValidateProgram FAILED \"" << _program->getName() << "\""
804             << " id=" << _glProgramHandle
805             << " contextID=" << _contextID
806             <<  std::endl;
807
808    std::string infoLog;
809    if( getInfoLog(infoLog) )
810        OSG_WARN << "infolog:\n" << infoLog << std::endl;
811
812    OSG_WARN << std::endl;
813
814    return false;
815}
816
817bool Program::PerContextProgram::getInfoLog( std::string& infoLog ) const
818{
819    return _extensions->getProgramInfoLog( _glProgramHandle, infoLog );
820}
821
822Program::ProgramBinary* Program::PerContextProgram::compileProgramBinary(osg::State& state)
823{
824    linkProgram(state);
825    GLint binaryLength = 0;
826    _extensions->glGetProgramiv( _glProgramHandle, GL_PROGRAM_BINARY_LENGTH, &binaryLength );
827    if (binaryLength)
828    {
829        ProgramBinary* programBinary = new ProgramBinary;
830        programBinary->allocate(binaryLength);
831        GLenum binaryFormat = 0;
832        _extensions->glGetProgramBinary( _glProgramHandle, binaryLength, 0, &binaryFormat, reinterpret_cast<GLvoid*>(programBinary->getData()) );
833        programBinary->setFormat(binaryFormat);
834        return programBinary;
835    }
836    return 0;
837}
838
839void Program::PerContextProgram::useProgram() const
840{
841    _extensions->glUseProgram( _glProgramHandle  );
842}
Note: See TracBrowser for help on using the browser.