Commit b7922209 authored by Christopher Tenter's avatar Christopher Tenter
Browse files

- remove shader modifier limit closes #2306

- instanced render objects

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@19916 383ad7c9-94d9-4d36-a494-682f7c89f535
parent d0db9b1a
......@@ -884,7 +884,10 @@ void IRenderer::drawObject(ACG::RenderObject* _obj)
glPolygonMode(GL_FRONT_AND_BACK, _obj->fillMode);
if (noIndices) {
glDrawArrays(_obj->primitiveMode, _obj->indexOffset, _obj->numIndices);
if (_obj->numInstances <= 0)
glDrawArrays(_obj->primitiveMode, _obj->indexOffset, _obj->numIndices);
else
glDrawArraysInstanced(_obj->primitiveMode, _obj->indexOffset, _obj->numIndices, _obj->numInstances);
}
else
{
......@@ -898,8 +901,12 @@ void IRenderer::drawObject(ACG::RenderObject* _obj)
default: indexSize = 1; break;
}
glDrawElements(_obj->primitiveMode, _obj->numIndices, _obj->indexType,
((const char*)_obj->sysmemIndexBuffer) + _obj->indexOffset * indexSize);
if (_obj->numInstances <= 0)
glDrawElements(_obj->primitiveMode, _obj->numIndices, _obj->indexType,
((const char*)_obj->sysmemIndexBuffer) + _obj->indexOffset * indexSize);
else
glDrawElementsInstanced(_obj->primitiveMode, _obj->numIndices, _obj->indexType,
((const char*)_obj->sysmemIndexBuffer) + _obj->indexOffset * indexSize, _obj->numInstances);
}
}
}
......@@ -907,7 +914,7 @@ void IRenderer::drawObject(ACG::RenderObject* _obj)
void IRenderer::renderObject(ACG::RenderObject* _obj,
GLSL::Program* _prog,
bool _constRenderStates,
unsigned int _shaderModifiers)
const std::vector<unsigned int>* _shaderModifiers)
{
// select shader from cache
GLSL::Program* prog = _prog ? _prog : ACG::ShaderCache::getInstance()->getProgram(&_obj->shaderDesc, _shaderModifiers);
......@@ -1059,11 +1066,7 @@ QString IRenderer::dumpCurrentRenderObjectsToString(ACG::RenderObject** _list, b
QTextStream outStrm(&objectString);
std::vector<ACG::ShaderModifier*>::iterator it;
unsigned int usage = 0;
if (_modifiers) {
for (it = _modifiers->begin(); it != _modifiers->end(); ++it)
usage |= (*it)->getID();
}
for (int i = 0; i < getNumRenderObjects(); ++i)
{
const RenderObject* obj = _list ? _list[i] : &renderObjects_[i];
......@@ -1077,10 +1080,7 @@ QString IRenderer::dumpCurrentRenderObjectsToString(ACG::RenderObject** _list, b
outStrm << obj->shaderDesc.toString();
ShaderProgGenerator progGen(&(obj->shaderDesc), usage);
if (!usage)
progGen.generateShaders();
ShaderProgGenerator progGen(&(obj->shaderDesc), _modifiers);
outStrm << "\n---------------------vertex-shader--------------------\n\n";
for (int i = 0; i < progGen.getVertexShaderCode().size(); ++i)
......
......@@ -200,7 +200,7 @@ protected:
*
* Shader modifiers can be combined and applied to this pass.
*/
virtual void renderObject(ACG::RenderObject* _obj, GLSL::Program* _prog = 0, bool _constRenderStates = false, unsigned int _shaderModifiers = 0);
virtual void renderObject(ACG::RenderObject* _obj, GLSL::Program* _prog = 0, bool _constRenderStates = false, const std::vector<unsigned int>* _shaderModifiers = 0);
/** \brief Binding VBOs (First state function)
*
......
......@@ -177,6 +177,7 @@ RenderObject::RenderObject()
vertexArrayObject(0),
vertexBuffer(0), indexBuffer(0), sysmemIndexBuffer(0),
primitiveMode(GL_TRIANGLES), numIndices(0), indexOffset(0), indexType(GL_UNSIGNED_INT),
numInstances(0),
vertexDecl(0),
culling(true), blending(false), alphaTest(false),
depthTest(true), depthWrite(true),
......
......@@ -193,6 +193,13 @@ struct ACGDLLEXPORT RenderObject
*/
GLenum indexType;
/**\ brief Instancing
*
* Number of instances to render.
* numinstances <= 0, disables instancing.
*/
GLsizei numInstances;
/// Defines the vertex buffer layout, ignored if VAO is provided
const VertexDeclaration* vertexDecl;
......@@ -336,7 +343,7 @@ public:
// opengl style helper function interface:
// provided for easier setup of RenderObjects,
// usage is not necessary
void glBindBuffer(GLenum target, GLuint buffer)
inline void glBindBuffer(GLenum target, GLuint buffer)
{
switch (target)
{
......@@ -345,19 +352,28 @@ public:
}
}
void glDrawArrays(GLenum mode, GLint first, GLsizei count)
inline void glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
this->glDrawArraysInstanced(mode, first, count, 0);
}
inline void glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
{
indexBuffer = 0;
sysmemIndexBuffer = 0;
primitiveMode = mode;
indexOffset = first;
numIndices = count;
numInstances = primcount;
}
inline void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
{
this->glDrawElementsInstanced(mode, count, type, indices, 0);
}
void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
inline void glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
{
primitiveMode = mode;
numIndices = count;
......@@ -366,12 +382,12 @@ public:
sysmemIndexBuffer = indices;
}
void glColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a)
inline void glColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a)
{
colorWriteMask[0] = r; colorWriteMask[1] = g; colorWriteMask[2] = b; colorWriteMask[3] = a;
}
void glAlphaFunc(GLenum func, float ref)
inline void glAlphaFunc(GLenum func, float ref)
{
alphaFunc = func;
alphaRef = ref;
......
......@@ -91,16 +91,22 @@ ShaderCache* ACG::ShaderCache::getInstance()
}
GLSL::Program* ACG::ShaderCache::getProgram( const ShaderGenDesc* _desc )
{
std::vector<unsigned int> dummy;
return getProgram(_desc, dummy);
}
//***********************************************************************
// TODO implement binary search eventually (if cache access is getting too slow)
// - modify compareShaderGenDescs s.t. it defines an order
// or generate a hash key from ShaderGenDesc
GLSL::Program* ACG::ShaderCache::getProgram( const ShaderGenDesc* _desc, unsigned int _usage )
GLSL::Program* ACG::ShaderCache::getProgram( const ShaderGenDesc* _desc, const std::vector<unsigned int>& _mods )
{
CacheEntry newEntry;
newEntry.desc = *_desc;
newEntry.usage = _usage;
newEntry.mods = _mods;
if (!_desc->fragmentTemplateFile.isEmpty())
{
......@@ -147,7 +153,7 @@ GLSL::Program* ACG::ShaderCache::getProgram( const ShaderGenDesc* _desc, unsigne
}
// glsl program not in cache, generate shaders
ShaderProgGenerator progGen(_desc, _usage);
ShaderProgGenerator progGen(_desc, _mods);
if (!dbgOutputDir_.isEmpty())
{
......@@ -163,7 +169,11 @@ GLSL::Program* ACG::ShaderCache::getProgram( const ShaderGenDesc* _desc, unsigne
QTextStream outStrm(&fileOut);
outStrm << _desc->toString();
outStrm << "\nusage: " << _usage << "\n";
outStrm << "\nmods: ";
for (size_t i = 0; i < _mods.size(); ++i)
outStrm << _mods[i] << (i+1 < _mods.size() ? ", " : "");
outStrm << "\n";
outStrm << "\n---------------------vertex-shader--------------------\n\n";
......@@ -280,7 +290,6 @@ GLSL::Program* ACG::ShaderCache::getProgram( const char* _vertexShaderFile,
QStringList* _macros, bool _verbose )
{
CacheEntry newEntry;
newEntry.usage = 0;
// store filenames and timestamps in new entry
......@@ -435,7 +444,6 @@ GLSL::Program* ACG::ShaderCache::getProgram( const char* _vertexShaderFile, cons
GLSL::Program* ACG::ShaderCache::getComputeProgram(const char* _computeShaderFile, QStringList* _macros /* = 0 */, bool _verbose /* = true */)
{
CacheEntry newEntry;
newEntry.usage = 0;
// store filenames and timestamps in new entry
// use vertex shader filename as compute shader
......@@ -560,7 +568,7 @@ bool ACG::ShaderCache::compareTimeStamp(const CacheEntry* _a, const CacheEntry*
int ACG::ShaderCache::compareShaderGenDescs( const CacheEntry* _a, const CacheEntry* _b)
{
if (_a->usage != _b->usage)
if (_a->mods != _b->mods)
return -1;
const ShaderGenDesc* a = &_a->desc;
......
......@@ -86,10 +86,30 @@ public:
/** \brief Query a dynamically generated program from cache
*
* @param _desc Shader description
* @param _usage Additional usage identifier (combination of shader modifier ids)
* @param _mods Combination of active shader modifier ids
* @return The program (Either from cache or newly compiled and linked)
*/
GLSL::Program* getProgram(const ShaderGenDesc* _desc, unsigned int _usage = 0);
GLSL::Program* getProgram(const ShaderGenDesc* _desc, const std::vector<unsigned int>& _mods);
/** \brief Query a dynamically generated program from cache
*
* @param _desc Shader description
* @param _mods Combination of active shader modifier ids
* @return The program (Either from cache or newly compiled and linked)
*/
GLSL::Program* getProgram(const ShaderGenDesc* _desc, const std::vector<unsigned int>* _mods)
{
return _mods ? getProgram(_desc, *_mods) : getProgram(_desc);
}
/** \brief Query a dynamically generated program from cache
*
* @param _desc Shader description
* @param _mods Combination of active shader modifier ids
* @return The program (Either from cache or newly compiled and linked)
*/
GLSL::Program* getProgram(const ShaderGenDesc* _desc);
/** \brief Query a static shader program from cache
*
......@@ -161,7 +181,7 @@ protected:
struct CacheEntry
{
ShaderGenDesc desc;
unsigned int usage;
std::vector<unsigned int> mods;
// string-pointer in ShaderGenDesc may not be permanent,
// so copy string data here
......
......@@ -93,8 +93,8 @@ namespace ACG
#define SG_OUTPUT_VERTEXCOLOR "SG_OUTPUT_VERTEXCOLOR"
int ShaderProgGenerator::numModifiers_ = 0;
ShaderModifier* ShaderProgGenerator::modifiers_[32] = {0};
int ShaderProgGenerator::numRegisteredModifiers_ = 0;
std::vector<ShaderModifier*> ShaderProgGenerator::registeredModifiers_;
......@@ -797,10 +797,74 @@ ShaderGenerator::DefaultIODesc::DefaultIODesc()
QString ShaderProgGenerator::shaderDir_;
QStringList ShaderProgGenerator::lightingCode_;
ShaderProgGenerator::ShaderProgGenerator(const ShaderGenDesc* _desc,
unsigned int _usage)
: vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), usage_(_usage), renormalizeLighting_(false)
ShaderProgGenerator::ShaderProgGenerator( const ShaderGenDesc* _desc )
: vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
{
init(_desc, (ShaderModifier**)0, 0);
}
ShaderProgGenerator::ShaderProgGenerator( const ShaderGenDesc* _desc, const unsigned int* _modifierIDs, unsigned int _numActiveMods )
: vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
{
init(_desc, _modifierIDs, _numActiveMods);
}
ShaderProgGenerator::ShaderProgGenerator(const ShaderGenDesc* _desc, const std::vector<unsigned int>& _modifierIDs)
: vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
{
init(_desc, _modifierIDs.empty() ? 0 : &_modifierIDs[0], (unsigned int)_modifierIDs.size());
}
ShaderProgGenerator::ShaderProgGenerator(const ShaderGenDesc* _desc, const std::vector<unsigned int>* _modifierIDs)
: vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
{
init(_desc, !_modifierIDs || _modifierIDs->empty() ? 0 : &((*_modifierIDs)[0]), (unsigned int)_modifierIDs->size());
}
ShaderProgGenerator::ShaderProgGenerator(const ShaderGenDesc* _desc, ShaderModifier* const* _modifiers, unsigned int _numActiveMods)
: vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
{
init(_desc, _modifiers, _numActiveMods);
}
ShaderProgGenerator::ShaderProgGenerator(const ShaderGenDesc* _desc, const std::vector<ShaderModifier*>& _modifierIDs)
: vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
{
init(_desc, _modifierIDs.empty() ? 0 : &(_modifierIDs[0]), (unsigned int)_modifierIDs.size());
}
ShaderProgGenerator::ShaderProgGenerator(const ShaderGenDesc* _desc, const std::vector<ShaderModifier*>* _modifierIDs)
: vertex_(0), tessControl_(0), tessEval_(0), geometry_(0), fragment_(0), renormalizeLighting_(false)
{
init(_desc, !_modifierIDs || _modifierIDs->empty() ? 0 : &((*_modifierIDs)[0]), (unsigned int)_modifierIDs->size());
}
void ShaderProgGenerator::init( const ShaderGenDesc* _desc, const unsigned int* _modifierIDs, unsigned int _numActiveMods )
{
if (_modifierIDs && _numActiveMods)
{
activeMods_.resize(_numActiveMods);
for (unsigned int i = 0; i < _numActiveMods; ++i)
activeMods_[i] = registeredModifiers_[ _modifierIDs[i] ];
}
init(_desc, (ShaderModifier**)0, 0);
}
void ShaderProgGenerator::init( const ShaderGenDesc* _desc, ShaderModifier* const* _modifiers, unsigned int _numActiveMods )
{
if (_modifiers && _numActiveMods)
{
activeMods_.resize(_numActiveMods);
for (unsigned int i = 0; i < _numActiveMods; ++i)
activeMods_[i] = _modifiers[i];
}
if (shaderDir_.isEmpty())
std::cout << "error: call ShaderProgGenerator::setShaderDir() first!" << std::endl;
else
......@@ -841,6 +905,7 @@ ShaderProgGenerator::ShaderProgGenerator(const ShaderGenDesc* _desc,
}
}
ShaderProgGenerator::~ShaderProgGenerator(void)
{
delete vertex_;
......@@ -973,11 +1038,8 @@ void ShaderProgGenerator::buildVertexShader()
// apply i/o modifiers
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
modifiers_[i]->modifyVertexIO(vertex_);
}
for (size_t i = 0; i < activeMods_.size(); ++i)
activeMods_[i]->modifyVertexIO(vertex_);
initGenDefines(vertex_);
......@@ -1086,11 +1148,8 @@ void ShaderProgGenerator::addVertexBeginCode(QStringList* _code)
// apply modifiers
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
modifiers_[i]->modifyVertexBeginCode(_code);
}
for (size_t i = 0; i < activeMods_.size(); ++i)
activeMods_[i]->modifyVertexBeginCode(_code);
}
......@@ -1120,11 +1179,8 @@ void ShaderProgGenerator::addVertexEndCode(QStringList* _code)
// apply modifiers
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
modifiers_[i]->modifyVertexEndCode(_code);
}
for (size_t i = 0; i < activeMods_.size(); ++i)
activeMods_[i]->modifyVertexEndCode(_code);
}
......@@ -1206,11 +1262,8 @@ void ShaderProgGenerator::buildTessControlShader()
// apply i/o modifiers
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
modifiers_[i]->modifyTessControlIO(tessControl_);
}
for (size_t i = 0; i < activeMods_.size(); ++i)
activeMods_[i]->modifyTessControlIO(tessControl_);
initGenDefines(tessControl_);
......@@ -1292,11 +1345,8 @@ void ShaderProgGenerator::buildTessEvalShader()
tessEval_->addLayout(itLayout);
// apply i/o modifiers
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
modifiers_[i]->modifyTessControlIO(tessEval_);
}
for (size_t i = 0; i < activeMods_.size(); ++i)
activeMods_[i]->modifyTessControlIO(tessEval_);
initGenDefines(tessEval_);
......@@ -1483,11 +1533,8 @@ void ShaderProgGenerator::buildGeometryShader()
// apply i/o modifiers
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
modifiers_[i]->modifyGeometryIO(geometry_);
}
for (size_t i = 0; i < activeMods_.size(); ++i)
activeMods_[i]->modifyGeometryIO(geometry_);
initGenDefines(geometry_);
......@@ -1601,11 +1648,8 @@ void ShaderProgGenerator::buildFragmentShader()
}
// apply i/o modifiers
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
modifiers_[i]->modifyFragmentIO(fragment_);
}
for (size_t i = 0; i < activeMods_.size(); ++i)
activeMods_[i]->modifyFragmentIO(fragment_);
initGenDefines(fragment_);
......@@ -1725,11 +1769,8 @@ void ShaderProgGenerator::addFragmentBeginCode(QStringList* _code)
// apply modifiers
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
modifiers_[i]->modifyFragmentBeginCode(_code);
}
for (size_t i = 0; i < activeMods_.size(); ++i)
activeMods_[i]->modifyFragmentBeginCode(_code);
}
void ShaderProgGenerator::addFragmentEndCode(QStringList* _code)
......@@ -1737,11 +1778,8 @@ void ShaderProgGenerator::addFragmentEndCode(QStringList* _code)
_code->push_back("outFragment = sg_cColor;");
// apply modifiers
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
modifiers_[i]->modifyFragmentEndCode(_code);
}
for (size_t i = 0; i < activeMods_.size(); ++i)
activeMods_[i]->modifyFragmentEndCode(_code);
}
......@@ -1752,11 +1790,10 @@ void ShaderProgGenerator::addLightingCode(QStringList* _code)
ShaderModifier* lightingModifier = 0;
// check if any modifier replaces the default lighting function
for (int i = 0; i < numModifiers_ && !lightingModifier; ++i)
for (size_t i = 0; i < activeMods_.size() && !lightingModifier; ++i)
{
if (usage_ & (1 << i))
if (modifiers_[i]->replaceDefaultLightingCode())
lightingModifier = modifiers_[i];
if (activeMods_[i]->replaceDefaultLightingCode())
lightingModifier = activeMods_[i];
}
if (!lightingModifier)
......@@ -1791,11 +1828,8 @@ void ShaderProgGenerator::addLightingCode(QStringList* _code)
// modify lighting color afterwards
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
modifyLightingCode(_code, modifiers_[i]);
}
for (size_t i = 0; i < activeMods_.size(); ++i)
modifyLightingCode(_code, activeMods_[i]);
}
else
{
......@@ -1805,10 +1839,10 @@ void ShaderProgGenerator::addLightingCode(QStringList* _code)
// apply remaining modifiers that do not replace the complete lighting code
for (int i = 0; i < numModifiers_; ++i)
for (size_t i = 0; i < activeMods_.size(); ++i)
{
if (usage_ & (1 << i) && lightingModifier != modifiers_[i])
modifyLightingCode(_code, modifiers_[i]);
if (lightingModifier != activeMods_[i])
modifyLightingCode(_code, activeMods_[i]);
}
}
......@@ -1867,18 +1901,15 @@ void ShaderProgGenerator::generateShaders()
// done by adding modifier io to an empty dummy
ShaderGenerator dummy;
for (int i = 0; i < numModifiers_; ++i)
for (size_t i = 0; i < activeMods_.size(); ++i)
{
if (usage_ & (1 << i))
{
ShaderModifier* mod = modifiers_[i];
ShaderModifier* mod = activeMods_[i];
mod->modifyVertexIO(&dummy);
mod->modifyTessControlIO(&dummy);
mod->modifyTessEvalIO(&dummy);
mod->modifyGeometryIO(&dummy);
mod->modifyFragmentIO(&dummy);
}
mod->modifyVertexIO(&dummy);
mod->modifyTessControlIO(&dummy);
mod->modifyTessEvalIO(&dummy);
mod->modifyGeometryIO(&dummy);
mod->modifyFragmentIO(&dummy);
}
// scan requested inputs from modifiers
......@@ -2137,36 +2168,25 @@ unsigned int ShaderProgGenerator::registerModifier( ShaderModifier* _modifier )
if (!_modifier) return 0;
// redundancy check
for (unsigned int i = 0; i < 32; ++i)
{
if (modifiers_[i] == _modifier)
return i;
}
if (numModifiers_ == 32)
for (int i = 0; i < numRegisteredModifiers_; ++i)
{
std::cout << "warning: exceeded maximal ShaderModifier count!" << std::endl;
return 0;
if (registeredModifiers_[i] == _modifier)
{
// std::cout << "warning: trying to re-register shader modifier " << _modifier->getID() << std::endl;
return registeredModifiers_[i]->getID();
}
}
_modifier->modifierID_ = (unsigned int)(1 << numModifiers_);
_modifier->modifierID_ = (unsigned int)(numRegisteredModifiers_++);
modifiers_[numModifiers_++] = _modifier;
registeredModifiers_.push_back(_modifier);
return _modifier->modifierID_;
}
ShaderModifier* ShaderProgGenerator::getActiveModifier( int _i )
{
// search active modifiers
int counter = 0;
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
{
if (counter++ == _i)
return modifiers_[i];
}
}
if (_i >= 0 && _i <= int(activeMods_.size()))
return activeMods_[_i];
// invalid _i
return 0;
......@@ -2174,14 +2194,7 @@ ShaderModifier* ShaderProgGenerator::getActiveModifier( int _i )
int ShaderProgGenerator::getNumActiveModifiers() const
{
// count modifiers
int numActive = 0;
for (int i = 0; i < numModifiers_; ++i)
{
if (usage_ & (1 << i))
++numActive;
}
return numActive;
return int(activeMods_.size());
}
......
......@@ -47,6 +47,7 @@
#include <string>
#include <list>