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

Revision 13949, 30.2 kB (checked in by robert, 20 hours ago)

Created ui lua scripts in a way that makes them compatible with being used with lua require()

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