Developer Documentation

ShaderCache.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42
43
44
45 #include "ShaderCache.hh"
46
47 #include <cstdio>
48 #include <iostream>
49 #include <fstream>
50
51
52 #include <QFile>
53 #include <QFileInfo>
54 #include <QDir>
55 #include <QTextStream>
56
57 #include <ACG/GL/GLError.hh>
58 #include <ACG/ShaderUtils/GLSLShader.hh>
59
60
61 namespace ACG
62 {
63
64 ShaderCache::ShaderCache():
65 cache_(),
66 cacheStatic_(),
67 timeCheck_(false)
68 {
69 }
70
71 ShaderCache::~ShaderCache()
72 {
73 // free all glsl programs in cache
74 for (CacheList::iterator it = cache_.begin(); it != cache_.end(); ++it)
75 delete it->second;
76
77 for (CacheList::iterator it = cacheStatic_.begin(); it != cacheStatic_.end(); ++it)
78 delete it->second;
79
80 for (CacheList::iterator it = cacheComputeShaders_.begin(); it != cacheComputeShaders_.end(); ++it)
81 delete it->second;
82 }
83
84 ShaderCache* ACG::ShaderCache::getInstance()
85 {
86 static ShaderCache singleton;
87 return &singleton;
88 }
89
90
91 GLSL::Program* ACG::ShaderCache::getProgram( const ShaderGenDesc* _desc )
92 {
93 std::vector<unsigned int> dummy;
94 return getProgram(_desc, dummy);
95 }
96
97 //***********************************************************************
98 // TODO implement binary search eventually (if cache access is getting too slow)
99 // - modify compareShaderGenDescs s.t. it defines an order
100 // or generate a hash key from ShaderGenDesc
101
102 GLSL::Program* ACG::ShaderCache::getProgram( const ShaderGenDesc* _desc, const std::vector<unsigned int>& _mods )
103 {
104 CacheEntry newEntry;
105 newEntry.desc = *_desc;
106 newEntry.mods = _mods;
107
108 if (!_desc->fragmentTemplateFile.isEmpty())
109 {
110 newEntry.strFragmentTemplate = _desc->fragmentTemplateFile;
111 newEntry.fragmentFileLastMod = QFileInfo(newEntry.strFragmentTemplate).lastModified();
112 }
113
114 if (!_desc->tessControlTemplateFile.isEmpty())
115 {
116 newEntry.strTessControlTemplate = _desc->tessControlTemplateFile;
117 newEntry.tessControlFileLastMod = QFileInfo(newEntry.strTessControlTemplate).lastModified();
118 }
119
120 if (!_desc->tessEvaluationTemplateFile.isEmpty())
121 {
122 newEntry.strTessEvaluationTemplate = _desc->tessEvaluationTemplateFile;
123 newEntry.tessEvaluationFileLastMod = QFileInfo(newEntry.strTessEvaluationTemplate).lastModified();
124 }
125
126 if (!_desc->geometryTemplateFile.isEmpty())
127 {
128 newEntry.strGeometryTemplate = _desc->geometryTemplateFile;
129 newEntry.geometryFileLastMod = QFileInfo(newEntry.strGeometryTemplate).lastModified();
130 }
131
132 if (!_desc->vertexTemplateFile.isEmpty())
133 {
134 newEntry.strVertexTemplate = _desc->vertexTemplateFile;
135 newEntry.vertexFileLastMod = QFileInfo(newEntry.strVertexTemplate).lastModified();
136 }
137
138 CacheList::iterator oldCache = cache_.end();
139
140 for (CacheList::iterator it = cache_.begin(); it != cache_.end(); ++it)
141 {
142 // If the shaders are equal, we return the cached entry
143 if (!compareShaderGenDescs(&it->first, &newEntry))
144 {
145 if ( timeCheck_ && !compareTimeStamp(&it->first, &newEntry))
146 oldCache = it;
147 else
148 return it->second;
149 }
150 }
151
152 // glsl program not in cache, generate shaders
153 ShaderProgGenerator progGen(_desc, _mods);
154
155 if (!dbgOutputDir_.isEmpty())
156 {
157 static int counter = 0;
158
159 QString fileName;
160 fileName.sprintf("shader_%02d.glsl", counter++);
161 fileName = dbgOutputDir_ + QDir::separator() + fileName;
162
163 QFile fileOut(fileName);
164 if (fileOut.open(QFile::WriteOnly | QFile::Truncate))
165 {
166 QTextStream outStrm(&fileOut);
167
168 outStrm << _desc->toString();
169 outStrm << "\nmods: ";
170
171 for (size_t i = 0; i < _mods.size(); ++i)
172 outStrm << _mods[i] << (i+1 < _mods.size() ? ", " : "");
173 outStrm << "\n";
174
175
176 outStrm << "\n---------------------vertex-shader--------------------\n\n";
177
178 for (int i = 0; i < progGen.getVertexShaderCode().size(); ++i)
179 outStrm << progGen.getVertexShaderCode()[i] << "\n";
180
181 if (progGen.hasTessControlShader())
182 {
183 outStrm << "\n---------------------tesscontrol-shader--------------------\n\n";
184
185 for (int i = 0; i < progGen.getTessControlShaderCode().size(); ++i)
186 outStrm << progGen.getTessControlShaderCode()[i] << "\n";
187 }
188
189 if (progGen.hasTessEvaluationShader())
190 {
191 outStrm << "\n---------------------tesseval-shader--------------------\n\n";
192
193 for (int i = 0; i < progGen.getTessEvaluationShaderCode().size(); ++i)
194 outStrm << progGen.getTessEvaluationShaderCode()[i] << "\n";
195 }
196
197 if (progGen.hasGeometryShader())
198 {
199 outStrm << "\n---------------------geometry-shader--------------------\n\n";
200
201 for (int i = 0; i < progGen.getGeometryShaderCode().size(); ++i)
202 outStrm << progGen.getGeometryShaderCode()[i] << "\n";
203 }
204
205 outStrm << "\n---------------------fragment-shader--------------------\n\n";
206
207 for (int i = 0; i < progGen.getFragmentShaderCode().size(); ++i)
208 outStrm << progGen.getFragmentShaderCode()[i] << "\n";
209
210
211 fileOut.close();
212 }
213 }
214
215 GLSL::FragmentShader* fragShader = new GLSL::FragmentShader();
216 GLSL::VertexShader* vertShader = new GLSL::VertexShader();
217
218 vertShader->setSource(progGen.getVertexShaderCode());
219 fragShader->setSource(progGen.getFragmentShaderCode());
220
221 vertShader->compile();
222 fragShader->compile();
223
224 GLSL::Program* prog = new GLSL::Program();
225 prog->attach(vertShader);
226 prog->attach(fragShader);
227
228 // Check if we have a geometry shader and if we have support for it, enable it here
229 if ( progGen.hasGeometryShader() ) {
230 GLSL::GeometryShader* geomShader = new GLSL::GeometryShader();
231 geomShader->setSource(progGen.getGeometryShaderCode());
232 geomShader->compile();
233 prog->attach(geomShader);
234 }
235
236 // Check if we have tessellation shaders and if we have support for it, enable it here
237 if ( progGen.hasTessControlShader() || progGen.hasTessEvaluationShader() ) {
238 GLSL::Shader* tessControlShader = 0, *tessEvalShader = 0;
239
240 #ifdef GL_ARB_tessellation_shader
241 tessControlShader = new GLSL::TessControlShader();
242 tessEvalShader = new GLSL::TessEvaluationShader();
243 #endif // GL_ARB_tessellation_shader
244
245 if (tessControlShader && progGen.hasTessControlShader())
246 {
247 tessControlShader->setSource(progGen.getTessControlShaderCode());
248 tessControlShader->compile();
249 prog->attach(tessControlShader);
250 }
251
252 if (tessEvalShader && progGen.hasTessEvaluationShader())
253 {
254 tessEvalShader->setSource(progGen.getTessEvaluationShaderCode());
255 tessEvalShader->compile();
256 prog->attach(tessEvalShader);
257 }
258
259 }
260
261 prog->link();
262 glCheckErrors();
263
264 if (oldCache != cache_.end())
265 {
266 if (!prog->isLinked())
267 {
268 delete prog;
269 return oldCache->second;
270 }
271 else
272 {
273 cache_.erase(oldCache);
274 }
275 }
276
277 cache_.push_back(std::pair<CacheEntry, GLSL::Program*>(newEntry, prog));
278
279 return prog;
280 }
281
282 GLSL::Program* ACG::ShaderCache::getProgram( const char* _vertexShaderFile,
283 const char* _tessControlShaderFile,
284 const char* _tessEvalShaderFile,
285 const char* _geometryShaderFile,
286 const char* _fragmentShaderFile,
287 QStringList* _macros, bool _verbose )
288 {
289 CacheEntry newEntry;
290
291
292 // store filenames and timestamps in new entry
293
294 // fragment shader
295 QFileInfo fileInfo(_fragmentShaderFile);
296 if (fileInfo.isRelative())
297 {
298 QString absFilename = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + QString(_fragmentShaderFile);
299 fileInfo = QFileInfo(absFilename);
300
301 newEntry.strFragmentTemplate = absFilename;
302 newEntry.fragmentFileLastMod = fileInfo.lastModified();
303 }
304 else
305 {
306 newEntry.strFragmentTemplate = _fragmentShaderFile;
307 newEntry.fragmentFileLastMod = fileInfo.lastModified();
308 }
309
310 // vertex shader
311 fileInfo = QFileInfo(_vertexShaderFile);
312 if (fileInfo.isRelative())
313 {
314 QString absFilename = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + QString(_vertexShaderFile);
315 fileInfo = QFileInfo(absFilename);
316
317 newEntry.strVertexTemplate = absFilename;
318 newEntry.vertexFileLastMod = fileInfo.lastModified();
319 }
320 else
321 {
322 newEntry.strVertexTemplate = _vertexShaderFile;
323 newEntry.vertexFileLastMod = fileInfo.lastModified();
324 }
325
326
327 // geometry shader
328 if (_geometryShaderFile)
329 {
330 fileInfo = QFileInfo(_geometryShaderFile);
331 if (fileInfo.isRelative())
332 {
333 QString absFilename = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + QString(_geometryShaderFile);
334 fileInfo = QFileInfo(absFilename);
335
336 newEntry.strGeometryTemplate = absFilename;
337 newEntry.geometryFileLastMod = fileInfo.lastModified();
338 }
339 else
340 {
341 newEntry.strGeometryTemplate = _geometryShaderFile;
342 newEntry.geometryFileLastMod = fileInfo.lastModified();
343 }
344 }
345
346 // tess-ctrl shader
347 if (_tessControlShaderFile)
348 {
349 fileInfo = QFileInfo(_tessControlShaderFile);
350 if (fileInfo.isRelative())
351 {
352 QString absFilename = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + QString(_tessControlShaderFile);
353 fileInfo = QFileInfo(absFilename);
354
355 newEntry.strTessControlTemplate = absFilename;
356 newEntry.tessControlFileLastMod = fileInfo.lastModified();
357 }
358 else
359 {
360 newEntry.strTessControlTemplate = _tessControlShaderFile;
361 newEntry.tessControlFileLastMod = fileInfo.lastModified();
362 }
363 }
364
365 // tess-eval shader
366 if (_tessEvalShaderFile)
367 {
368 fileInfo = QFileInfo(_tessEvalShaderFile);
369 if (fileInfo.isRelative())
370 {
371 QString absFilename = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + QString(_tessEvalShaderFile);
372 fileInfo = QFileInfo(absFilename);
373
374 newEntry.strTessEvaluationTemplate = absFilename;
375 newEntry.tessEvaluationFileLastMod = fileInfo.lastModified();
376 }
377 else
378 {
379 newEntry.strTessEvaluationTemplate = _tessEvalShaderFile;
380 newEntry.tessEvaluationFileLastMod = fileInfo.lastModified();
381 }
382 }
383
384
385
386 if (_macros)
387 newEntry.macros = *_macros;
388
389 CacheList::iterator oldCache = cacheStatic_.end();
390
391 for (CacheList::iterator it = cacheStatic_.begin(); it != cacheStatic_.end(); ++it)
392 {
393 // If the shaders are equal, we return the cached entry
394 if (!compareShaderGenDescs(&it->first, &newEntry))
395 {
396 if ( timeCheck_ && !compareTimeStamp(&it->first, &newEntry))
397 oldCache = it;
398 else
399 return it->second;
400 }
401 }
402
403
404 // convert QStringList to GLSL::StringList
405
406 GLSL::StringList glslMacros;
407
408 if (_macros)
409 {
410 for (QStringList::const_iterator it = _macros->constBegin(); it != _macros->constEnd(); ++it)
411 glslMacros.push_back(it->toStdString());
412 }
413
414
415 GLSL::Program* prog = GLSL::loadProgram(_vertexShaderFile, _tessControlShaderFile, _tessEvalShaderFile, _geometryShaderFile, _fragmentShaderFile, &glslMacros, _verbose);
416 glCheckErrors();
417
418 if (oldCache != cacheStatic_.end())
419 {
420 if (!prog || !prog->isLinked())
421 {
422 delete prog;
423 return oldCache->second;
424 }
425 else
426 {
427 cacheStatic_.erase(oldCache);
428 }
429 }
430
431 cacheStatic_.push_back(std::pair<CacheEntry, GLSL::Program*>(newEntry, prog));
432
433 return prog;
434 }
435
436 GLSL::Program* ACG::ShaderCache::getProgram( const char* _vertexShaderFile, const char* _fragmentShaderFile, QStringList* _macros, bool _verbose )
437 {
438 return getProgram(_vertexShaderFile, 0, 0, 0, _fragmentShaderFile, _macros, _verbose);
439 }
440
441 GLSL::Program* ACG::ShaderCache::getComputeProgram(const char* _computeShaderFile, QStringList* _macros /* = 0 */, bool _verbose /* = true */)
442 {
443 CacheEntry newEntry;
444
445 // store filenames and timestamps in new entry
446 // use vertex shader filename as compute shader
447 QFileInfo fileInfo(_computeShaderFile);
448 if (fileInfo.isRelative())
449 {
450 QString absFilename = ACG::ShaderProgGenerator::getShaderDir() + QDir::separator() + QString(_computeShaderFile);
451 fileInfo = QFileInfo(absFilename);
452
453 newEntry.strVertexTemplate = absFilename;
454 newEntry.vertexFileLastMod = fileInfo.lastModified();
455 }
456 else
457 {
458 newEntry.strVertexTemplate = _computeShaderFile;
459 newEntry.vertexFileLastMod = fileInfo.lastModified();
460 }
461
462 if (_macros)
463 newEntry.macros = *_macros;
464
465 CacheList::iterator oldCache = cacheComputeShaders_.end();
466
467 for (CacheList::iterator it = cacheComputeShaders_.begin(); it != cacheComputeShaders_.end(); ++it)
468 {
469 // If the shaders are equal, we return the cached entry
470 if (!compareShaderGenDescs(&it->first, &newEntry))
471 {
472 if ( ( timeCheck_ && !compareTimeStamp(&it->first, &newEntry)) || !it->second || !it->second->isLinked())
473 oldCache = it;
474 else
475 return it->second;
476 }
477 }
478
479
480 // convert QStringList to GLSL::StringList
481
482 GLSL::StringList glslMacros;
483
484 if (_macros)
485 {
486 for (QStringList::const_iterator it = _macros->constBegin(); it != _macros->constEnd(); ++it)
487 glslMacros.push_back(it->toStdString());
488 }
489
490
491 GLSL::Program* prog = GLSL::loadComputeProgram(newEntry.strVertexTemplate.toUtf8(), &glslMacros, _verbose);
492 glCheckErrors();
493
494 if (oldCache != cacheComputeShaders_.end())
495 {
496 if (!prog || !prog->isLinked())
497 {
498 delete prog;
499
500
501 // dump shader source including macros to debug output
502 if (!glslMacros.empty() && !dbgOutputDir_.isEmpty())
503 {
504 GLSL::StringList shaderSrc = GLSL::loadShader(newEntry.strVertexTemplate.toUtf8(), &glslMacros);
505
506 // compute FNV hash of macros
507
508 unsigned int fnv_prime = 16777619;
509 unsigned int fnv_hash = 2166136261;
510
511 for (GLSL::StringList::iterator it = shaderSrc.begin(); it != shaderSrc.end(); ++it)
512 {
513 for (size_t i = 0; i < it->length(); ++i)
514 {
515 fnv_hash *= fnv_prime;
516 fnv_hash ^= static_cast<unsigned char>((*it)[i]);
517 }
518 }
519
520 QString fnv_string;
521 fnv_string.sprintf("%X", fnv_hash);
522
523 std::string dumpFilename = QString(dbgOutputDir_ + QDir::separator() + fileInfo.fileName() + fnv_string).toStdString();
524
525 std::ofstream dumpStream(dumpFilename.c_str());
526 if (dumpStream.is_open())
527 {
528 for (GLSL::StringList::iterator it = shaderSrc.begin(); it != shaderSrc.end(); ++it)
529 dumpStream << it->c_str();
530 dumpStream.close();
531 }
532 }
533
534 return oldCache->second;
535 }
536 else
537 {
538 cacheComputeShaders_.erase(oldCache);
539 }
540 }
541
542 cacheComputeShaders_.push_back(std::pair<CacheEntry, GLSL::Program*>(newEntry, prog));
543
544 return prog;
545 }
546
547 bool ACG::ShaderCache::compareTimeStamp(const CacheEntry* _a, const CacheEntry* _b)
548 {
549 if (_a->vertexFileLastMod != _b->vertexFileLastMod)
550 return false;
551
552 if (_a->geometryFileLastMod != _b->geometryFileLastMod)
553 return false;
554
555 if (_a->fragmentFileLastMod != _b->fragmentFileLastMod)
556 return false;
557
558 if (_a->tessControlFileLastMod != _b->tessControlFileLastMod)
559 return false;
560
561 if (_a->tessEvaluationFileLastMod != _b->tessEvaluationFileLastMod)
562 return false;
563 return true;
564 }
565
566 int ACG::ShaderCache::compareShaderGenDescs( const CacheEntry* _a, const CacheEntry* _b)
567 {
568 if (_a->mods != _b->mods)
569 return -1;
570
571 const ShaderGenDesc* a = &_a->desc;
572 const ShaderGenDesc* b = &_b->desc;
573
574 if (_a->strFragmentTemplate != _b->strFragmentTemplate)
575 return -1;
576
577 if (_a->strGeometryTemplate != _b->strGeometryTemplate)
578 return -1;
579
580 if (_a->strVertexTemplate != _b->strVertexTemplate)
581 return -1;
582
583 if (_a->strTessControlTemplate != _b->strTessControlTemplate)
584 return -1;
585
586 if (_a->strTessEvaluationTemplate != _b->strTessEvaluationTemplate)
587 return -1;
588
589 if (_a->macros != _b->macros)
590 return -1;
591
592
593 return *a == *b ? 0 : -1;
594 }
595
596
597 void ACG::ShaderCache::clearCache()
598 {
599 cache_.clear();
600 cacheStatic_.clear();
601 cacheComputeShaders_.clear();
602 }
603
604 void ACG::ShaderCache::setDebugOutputDir(const char* _outputDir)
605 {
606 dbgOutputDir_ = _outputDir;
607 }
608
609 //=============================================================================
610 } // namespace ACG
611 //=============================================================================
ACG::ShaderProgGenerator::getShaderDir
static QString getShaderDir()
Definition: ShaderGenerator.cc:2451
ACG::ShaderCache::getComputeProgram
GLSL::Program * getComputeProgram(const char *_computeShaderFile, QStringList *_macros=0, bool _verbose=true)
Query a static compute shader program from cache.
Definition: ShaderCache.cc:441
GLSL::Shader::setSource
void setSource(const StringList &source)
Upload the source of the shader.
Definition: GLSLShader.cc:103
ACG::ShaderProgGenerator::getTessEvaluationShaderCode
const QStringList & getTessEvaluationShaderCode()
Returns generated tessellation control shader code.
Definition: ShaderGenerator.cc:2249
ACG::ShaderProgGenerator::hasTessControlShader
bool hasTessControlShader() const
check whether there is a tess-control shader present
Definition: ShaderGenerator.cc:2497
ACG::ShaderCache::setDebugOutputDir
void setDebugOutputDir(const char *_outputDir)
Enable debug output of generated shaders to specified directory.
Definition: ShaderCache.cc:604
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
GLSL::FragmentShader
GLSL fragment shader.
Definition: GLSLShader.hh:110
GLSL::Shader::compile
bool compile(bool verbose=true)
Compile the shader object.
Definition: GLSLShader.cc:146
ACG::ShaderProgGenerator::getTessControlShaderCode
const QStringList & getTessControlShaderCode()
Returns generated vertex shader code.
Definition: ShaderGenerator.cc:2244
GLSL::loadComputeProgram
GLSL::PtrProgram loadComputeProgram(const char *computeShaderFile, const GLSL::StringList *macros, bool verbose)
Definition: GLSLShader.cc:1154
ACG::ShaderProgGenerator::getFragmentShaderCode
const QStringList & getFragmentShaderCode()
Returns generated fragment shader code.
Definition: ShaderGenerator.cc:2259
ACG::ShaderProgGenerator::hasTessEvaluationShader
bool hasTessEvaluationShader() const
check whether there is a tess-evaluation shader present
Definition: ShaderGenerator.cc:2502
GLSL::loadShader
GLSL::StringList loadShader(const char *filename, const GLSL::StringList *macros, bool appendNewLineChar, GLSL::StringList *outIncludes)
Loads the shader source.
Definition: GLSLShader.cc:921
ACG::glCheckErrors
void glCheckErrors()
Definition: GLError.hh:96
GLSL::VertexShader
GLSL vertex shader.
Definition: GLSLShader.hh:95
GLSL::Program::isLinked
bool isLinked()
Returns if the program object has been succesfully linked.
Definition: GLSLShader.cc:370
GLSL::Program::attach
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
Definition: GLSLShader.cc:292
GLSL::loadProgram
GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *tessControlShaderFile, const char *tessEvaluationShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose)
Definition: GLSLShader.cc:1076
GLSL::Program
GLSL program class.
Definition: GLSLShader.hh:211
ACG::ShaderCache::getInstance
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
Definition: ShaderCache.cc:84
ACG::ShaderCache::~ShaderCache
virtual ~ShaderCache()
Destructor.
Definition: ShaderCache.cc:71
ACG::ShaderCache
Cache for shaders.
Definition: ShaderCache.hh:73
ACG::ShaderCache::CacheEntry
Definition: ShaderCache.hh:182
ACG::ShaderProgGenerator
Definition: ShaderGenerator.hh:1189
GLSL::GeometryShader
GLSL geometry shader.
Definition: GLSLShader.hh:124
ACG::ShaderCache::getProgram
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
Definition: ShaderCache.cc:102
ACG::ShaderCache::clearCache
void clearCache()
Delete all cached shaders.
Definition: ShaderCache.cc:597
ACG::ShaderProgGenerator::getGeometryShaderCode
const QStringList & getGeometryShaderCode()
Returns generated tessellation evaluation shader code.
Definition: ShaderGenerator.cc:2254
ACG::ShaderCache::compareShaderGenDescs
int compareShaderGenDescs(const CacheEntry *_a, const CacheEntry *_b)
Returns true, if the shaders are not equal.
Definition: ShaderCache.cc:566
ACG::ShaderGenDesc::toString
QString toString() const
convert ShaderGenDesc to string format for debugging
Definition: ShaderGenerator.cc:2733
GLSL::Shader
A generic shader base class.
Definition: GLSLShader.hh:71
ACG::ShaderProgGenerator::getVertexShaderCode
const QStringList & getVertexShaderCode()
Returns generated vertex shader code.
Definition: ShaderGenerator.cc:2239
ACG::ShaderProgGenerator::hasGeometryShader
bool hasGeometryShader() const
check whether there is a geometry shader present
Definition: ShaderGenerator.cc:2492
ACG::ShaderCache::compareTimeStamp
bool compareTimeStamp(const CacheEntry *_a, const CacheEntry *_b)
Returns true, if the shaders have the timestamp.
Definition: ShaderCache.cc:547
GLSL::Program::link
void link()
Links the shader objects to the program.
Definition: GLSLShader.cc:326
ACG::ShaderGenDesc
Definition: ShaderGenerator.hh:83