1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 #include "OSGConfig.h"
40 #include "OSGShaderCache.h"
41 #include "OSGShaderProgramVariableChunk.h"
43 #include "boost/bind.hpp"
48 /*-------------------------------------------------------------------------*/
51 ShaderCache::ShaderCache(void) :
52 #ifdef OSG_SHC_USE_REF
61 /*-------------------------------------------------------------------------*/
64 ShaderCache::~ShaderCache(void)
69 #if defined(OSG_SHC_USE_REF) && !defined(OSG_SHC_MODE_0)
70 bool operator < (const ShaderCache::StoreElement
&rhs
,
71 const ShaderCache::IdStore
&lhs
)
73 return rhs
.first
< lhs
;
76 bool operator < (const ShaderCache::StoreVarElement
&rhs
,
77 const ShaderCache::IdStore
&lhs
)
79 return rhs
.first
< lhs
;
83 ShaderExecutableChunk
*ShaderCache::findShader(const IdStore
&vIds
)
85 #ifdef OSG_SHC_USE_REF
86 ShaderStore::const_iterator sIt
= std::lower_bound(_vShaderStore
.begin(),
91 ShaderExecutableChunk
*returnValue
= _oExeTree
.find(vIds
);
93 #ifdef OSG_SHC_USE_REF
94 if(sIt
== _vShaderStore
.end())
96 #ifdef OSG_ASSERT_TREE
97 OSG_ASSERT(returnValue
== NULL
);
104 #ifdef OSG_SHC_USE_REF
105 if(sIt
->first
!= vIds
)
107 #ifdef OSG_ASSERT_TREE
108 OSG_ASSERT(returnValue
== NULL
);
115 #ifdef OSG_SHC_USE_REF
116 #ifdef OSG_ASSERT_TREE
117 OSG_ASSERT(returnValue
== sIt
->second
);
121 #ifdef OSG_SHC_USE_REF
128 ShaderExecutableVarChunk
*ShaderCache::findShaderVar(const IdStore
&vIds
)
130 #ifdef OSG_SHC_USE_REF
131 ShaderVarStore::const_iterator vIt
=
132 std::lower_bound(_vShaderVarStore
.begin(),
133 _vShaderVarStore
.end (),
137 ShaderExecutableVarChunk
*returnValue
= _oVarTree
.find(vIds
);
139 #ifdef OSG_SHC_USE_REF
140 if(vIt
== _vShaderVarStore
.end())
142 #ifdef OSG_ASSERT_TREE
143 OSG_ASSERT(returnValue
== NULL
);
150 #ifdef OSG_SHC_USE_REF
151 if(vIt
->first
!= vIds
)
153 #ifdef OSG_ASSERT_TREE
154 OSG_ASSERT(returnValue
== NULL
);
161 #ifdef OSG_SHC_USE_REF
162 #ifdef OSG_ASSERT_TREE
163 OSG_ASSERT(returnValue
== vIt
->second
);
167 #ifdef OSG_SHC_USE_REF
174 void ShaderCache::addShader (const IdStore
&vIds
,
175 ShaderExecutableChunk
*pShader
)
177 #ifdef OSG_SHC_USE_REF
178 ShaderStore::iterator sIt
= std::lower_bound(_vShaderStore
.begin(),
179 _vShaderStore
.end (),
182 #ifdef OSG_ASSERT_TREE
186 if(sIt
== _vShaderStore
.end())
188 _vShaderStore
.push_back(StoreElement(vIds
, pShader
));
190 #ifdef OSG_SHC_REF_CLEANUP
191 updateRemoveCallback(pShader
);
194 #ifdef OSG_ASSERT_TREE
198 else if(sIt
->first
!= vIds
)
200 _vShaderStore
.insert(sIt
, StoreElement(vIds
, pShader
));
202 #ifdef OSG_SHC_REF_CLEANUP
203 updateRemoveCallback(pShader
);
206 #ifdef OSG_ASSERT_TREE
210 #ifdef OSG_ASSERT_TREE
213 OSG_ASSERT(sIt
->second
== pShader
);
218 if(_oExeTree
.add(vIds
, pShader
) == true)
220 #ifdef OSG_SHC_USE_REF
221 #ifdef OSG_ASSERT_TREE
222 OSG_ASSERT(bAdded
== true);
226 #ifndef OSG_SHC_REF_CLEANUP
227 updateRemoveCallback(pShader
);
232 void ShaderCache::addShaderVar(const IdStore
&vIds
,
233 ShaderExecutableVarChunk
*pVar
)
235 #ifdef OSG_SHC_USE_REF
236 ShaderVarStore::iterator vIt
=
237 std::lower_bound(_vShaderVarStore
.begin(),
238 _vShaderVarStore
.end (),
241 #ifdef OSG_ASSERT_TREE
245 if(vIt
== _vShaderVarStore
.end())
247 _vShaderVarStore
.push_back(StoreVarElement(vIds
, pVar
));
249 #ifdef OSG_SHC_REF_CLEANUP
250 updateRemoveCallback(pVar
);
253 #ifdef OSG_ASSERT_TREE
257 else if(vIt
->first
!= vIds
)
259 _vShaderVarStore
.insert(vIt
, StoreVarElement(vIds
, pVar
));
261 #ifdef OSG_SHC_REF_CLEANUP
262 updateRemoveCallback(pVar
);
265 #ifdef OSG_ASSERT_TREE
269 #ifdef OSG_ASSERT_TREE
272 OSG_ASSERT(vIt
->second
== pVar
);
277 if(_oVarTree
.add(vIds
, pVar
) == true)
279 #ifdef OSG_SHC_USE_REF
280 #ifdef OSG_ASSERT_TREE
281 OSG_ASSERT(bAdded
== true);
285 #ifndef OSG_SHC_REF_CLEANUP
286 updateRemoveCallback(pVar
);
291 void ShaderCache::clear(void)
293 #ifdef OSG_SHC_USE_REF
294 ShaderStore::const_iterator sIt
= _vShaderStore
.begin();
295 ShaderStore::const_iterator sEnd
= _vShaderStore
.end ();
297 #ifdef OSG_SHC_REF_CLEANUP
298 for(; sIt
!= sEnd
; ++sIt
)
300 clearShRemoveCallback(sIt
->second
);
305 _oExeTree
.destroy(boost::bind(&ShaderCache::clearShRemoveCallback
,
309 #ifdef OSG_SHC_USE_REF
310 ShaderVarStore::const_iterator vIt
= _vShaderVarStore
.begin();
311 ShaderVarStore::const_iterator vEnd
= _vShaderVarStore
.end ();
313 #ifdef OSG_SHC_REF_CLEANUP
314 for(; vIt
!= vEnd
; ++vIt
)
316 clearVaRemoveCallback(vIt
->second
);
321 _oVarTree
.destroy(boost::bind(&ShaderCache::clearVaRemoveCallback
,
326 void ShaderCache::dump(void)
328 #ifdef OSG_SHC_USE_REF
329 fprintf(stderr
, "Dump shader cache \n");
331 ShaderStore::const_iterator sIt
= _vShaderStore
.begin();
332 ShaderStore::const_iterator sEnd
= _vShaderStore
.end ();
335 for(; sIt
!= sEnd
; ++sIt
)
337 IdStore::const_iterator idIt
= sIt
->first
.begin();
338 IdStore::const_iterator idEnd
= sIt
->first
.end ();
340 fprintf(stderr
, " ");
342 for(; idIt
!= idEnd
; ++idIt
)
344 fprintf(stderr
, "%d ", *idIt
);
347 fprintf(stderr
, ": %p\n", sIt
->second
.get());
351 ShaderVarStore::const_iterator vIt
= _vShaderVarStore
.begin();
352 ShaderVarStore::const_iterator vEnd
= _vShaderVarStore
.end ();
355 for(; vIt
!= vEnd
; ++vIt
)
357 IdStore::const_iterator idIt
= vIt
->first
.begin();
358 IdStore::const_iterator idEnd
= vIt
->first
.end ();
360 fprintf(stderr
, " ");
362 for(; idIt
!= idEnd
; ++idIt
)
364 fprintf(stderr
, "%d ", *idIt
);
367 fprintf(stderr
, ": %p\n", vIt
->second
.get());
371 _oExeTree
.dumpDot("/tmp/exetree.dot");
372 _oVarTree
.dumpDot("/tmp/vartree.dot");
375 void ShaderCache::updateRemoveCallback(ShaderExecutableChunk
*pShader
)
380 ShaderExecutableChunk::FragmentShaderIt fIt
=
381 pShader
->getMFFragmentShader()->begin();
382 ShaderExecutableChunk::FragmentShaderIt fEnd
=
383 pShader
->getMFFragmentShader()->end ();
385 for(; fIt
!= fEnd
; ++fIt
)
390 if((*fIt
)->hasDestroyedFunctor(
391 boost::bind(&ShaderCache::removeShaderProgram
,
396 (*fIt
)->addDestroyedFunctor(
397 boost::bind(&ShaderCache::removeShaderProgram
,
405 ShaderExecutableChunk::GeometryShaderIt gIt
=
406 pShader
->getMFGeometryShader()->begin();
407 ShaderExecutableChunk::GeometryShaderIt gEnd
=
408 pShader
->getMFGeometryShader()->end ();
410 for(; gIt
!= gEnd
; ++gIt
)
415 if((*gIt
)->hasDestroyedFunctor(
416 boost::bind(&ShaderCache::removeShaderProgram
,
421 (*gIt
)->addDestroyedFunctor(
422 boost::bind(&ShaderCache::removeShaderProgram
,
431 ShaderExecutableChunk::VertexShaderIt vIt
=
432 pShader
->getMFVertexShader()->begin();
433 ShaderExecutableChunk::VertexShaderIt vEnd
=
434 pShader
->getMFVertexShader()->end ();
436 for(; vIt
!= vEnd
; ++vIt
)
441 if((*vIt
)->hasDestroyedFunctor(
442 boost::bind(&ShaderCache::removeShaderProgram
,
447 (*vIt
)->addDestroyedFunctor(
448 boost::bind(&ShaderCache::removeShaderProgram
,
457 void ShaderCache::clearShRemoveCallback(ShaderExecutableChunk
*pShader
)
462 ShaderExecutableChunk::FragmentShaderIt fIt
=
463 pShader
->getMFFragmentShader()->begin();
464 ShaderExecutableChunk::FragmentShaderIt fEnd
=
465 pShader
->getMFFragmentShader()->end ();
467 for(; fIt
!= fEnd
; ++fIt
)
472 (*fIt
)->subDestroyedFunctor(
473 boost::bind(&ShaderCache::removeShaderProgram
,
479 ShaderExecutableChunk::GeometryShaderIt gIt
=
480 pShader
->getMFGeometryShader()->begin();
481 ShaderExecutableChunk::GeometryShaderIt gEnd
=
482 pShader
->getMFGeometryShader()->end ();
484 for(; gIt
!= gEnd
; ++gIt
)
489 (*gIt
)->subDestroyedFunctor(
490 boost::bind(&ShaderCache::removeShaderProgram
,
497 ShaderExecutableChunk::VertexShaderIt vIt
=
498 pShader
->getMFVertexShader()->begin();
499 ShaderExecutableChunk::VertexShaderIt vEnd
=
500 pShader
->getMFVertexShader()->end ();
502 for(; vIt
!= vEnd
; ++vIt
)
507 (*vIt
)->subDestroyedFunctor(
508 boost::bind(&ShaderCache::removeShaderProgram
,
517 void ShaderCache::updateRemoveCallback(ShaderExecutableVarChunk
*pVar
)
522 ShaderExecutableVarChunk::VarChunksIt vIt
=
523 pVar
->getMFProgramVarChunks()->begin();
524 ShaderExecutableVarChunk::VarChunksIt vEnd
=
525 pVar
->getMFProgramVarChunks()->end ();
527 for(; vIt
!= vEnd
; ++vIt
)
532 if((*vIt
)->hasDestroyedFunctor(
533 boost::bind(&ShaderCache::removeShaderVar
,
538 (*vIt
)->addDestroyedFunctor(
539 boost::bind(&ShaderCache::removeShaderVar
,
548 void ShaderCache::clearVaRemoveCallback(ShaderExecutableVarChunk
*pVar
)
553 ShaderExecutableVarChunk::VarChunksIt vIt
=
554 pVar
->getMFProgramVarChunks()->begin();
555 ShaderExecutableVarChunk::VarChunksIt vEnd
=
556 pVar
->getMFProgramVarChunks()->end ();
558 for(; vIt
!= vEnd
; ++vIt
)
563 (*vIt
)->subDestroyedFunctor(
564 boost::bind(&ShaderCache::removeShaderVar
,
572 void ShaderCache::removeShaderProgram(FieldContainer
*pContainer
,
573 ConstFieldMaskArg whichField
)
575 ShaderProgram
*pShaderProg
= dynamic_cast<ShaderProgram
*>(pContainer
);
577 if(pShaderProg
== NULL
)
580 UInt16 uiShaderId
= pShaderProg
->getProgramId();
582 #ifdef OSG_SHC_USE_REF
583 ShaderStore:: iterator sIt
= _vShaderStore
.begin();
584 ShaderStore::const_iterator sEnd
= _vShaderStore
.end ();
589 IdStore::const_iterator idIt
= std::find(sIt
->first
.begin(),
593 if(idIt
!= sIt
->first
.end())
595 sIt
= _vShaderStore
.erase(sIt
);
596 sEnd
= _vShaderStore
.end();
605 _oExeTree
.sub(uiShaderId
);
609 void ShaderCache::removeShaderVar(FieldContainer
*pContainer
,
610 ConstFieldMaskArg whichField
)
612 ShaderProgramVariableChunk
*pShaderVar
=
613 dynamic_cast<ShaderProgramVariableChunk
*>(pContainer
);
615 if(pShaderVar
== NULL
)
618 UInt16 uiVarId
= pShaderVar
->getVariableId();
620 #ifdef OSG_SHC_USE_REF
621 ShaderVarStore:: iterator vIt
= _vShaderVarStore
.begin();
622 ShaderVarStore::const_iterator vEnd
= _vShaderVarStore
.end ();
626 IdStore::const_iterator idIt
= std::find(vIt
->first
.begin(),
630 if(idIt
!= vIt
->first
.end())
632 vIt
= _vShaderVarStore
.erase(vIt
);
633 vEnd
= _vShaderVarStore
.end();
642 _oVarTree
.sub(uiVarId
);