Further work to clean up UniformCache for Effects

This commit is contained in:
Stuart Buchanan 2014-09-27 22:05:30 +01:00
parent 2bf79a2fa1
commit 93a63a0678
4 changed files with 30 additions and 73 deletions

View File

@ -107,7 +107,6 @@ private:
typedef boost::tuple<std::string, Uniform::Type, std::string> UniformCacheKey; typedef boost::tuple<std::string, Uniform::Type, std::string> UniformCacheKey;
typedef boost::tuple<ref_ptr<Uniform>, SGPropertyChangeListener*> UniformCacheValue; typedef boost::tuple<ref_ptr<Uniform>, SGPropertyChangeListener*> UniformCacheValue;
//std::map<UniformCacheKey,UniformCacheValue > uniformCache;
std::map<UniformCacheKey,ref_ptr<Uniform> > uniformCache; std::map<UniformCacheKey,ref_ptr<Uniform> > uniformCache;
typedef std::queue<DeferredPropertyListener*> DeferredListenerList; typedef std::queue<DeferredPropertyListener*> DeferredListenerList;
@ -147,8 +146,6 @@ ref_ptr<Uniform> UniformFactoryImpl::getUniform( Effect * effect,
} }
UniformCacheKey key = boost::make_tuple(name, uniformType, val); UniformCacheKey key = boost::make_tuple(name, uniformType, val);
//UniformCacheValue value = uniformCache[key];
//ref_ptr<Uniform> uniform = value.get_head();
ref_ptr<Uniform> uniform = uniformCache[key]; ref_ptr<Uniform> uniform = uniformCache[key];
if (uniform.valid()) { if (uniform.valid()) {
@ -158,28 +155,27 @@ ref_ptr<Uniform> UniformFactoryImpl::getUniform( Effect * effect,
SG_LOG(SG_GL,SG_DEBUG,"new uniform " << name << " value " << uniformCache.size()); SG_LOG(SG_GL,SG_DEBUG,"new uniform " << name << " value " << uniformCache.size());
uniformCache[key] = uniform = new Uniform; uniformCache[key] = uniform = new Uniform;
DeferredPropertyListener* updater = 0;
uniform->setName(name); uniform->setName(name);
uniform->setType(uniformType); uniform->setType(uniformType);
switch (uniformType) { switch (uniformType) {
case Uniform::BOOL: case Uniform::BOOL:
updater = initFromParameters(effect, valProp, uniform.get(), initFromParameters(effect, valProp, uniform.get(),
static_cast<bool (Uniform::*)(bool)>(&Uniform::set), static_cast<bool (Uniform::*)(bool)>(&Uniform::set),
options); options);
break; break;
case Uniform::FLOAT: case Uniform::FLOAT:
updater = initFromParameters(effect, valProp, uniform.get(), initFromParameters(effect, valProp, uniform.get(),
static_cast<bool (Uniform::*)(float)>(&Uniform::set), static_cast<bool (Uniform::*)(float)>(&Uniform::set),
options); options);
break; break;
case Uniform::FLOAT_VEC3: case Uniform::FLOAT_VEC3:
updater = initFromParameters(effect, valProp, uniform.get(), initFromParameters(effect, valProp, uniform.get(),
static_cast<bool (Uniform::*)(const Vec3&)>(&Uniform::set), static_cast<bool (Uniform::*)(const Vec3&)>(&Uniform::set),
vec3Names, options); vec3Names, options);
break; break;
case Uniform::FLOAT_VEC4: case Uniform::FLOAT_VEC4:
updater = initFromParameters(effect, valProp, uniform.get(), initFromParameters(effect, valProp, uniform.get(),
static_cast<bool (Uniform::*)(const Vec4&)>(&Uniform::set), static_cast<bool (Uniform::*)(const Vec4&)>(&Uniform::set),
vec4Names, options); vec4Names, options);
break; break;
@ -190,7 +186,7 @@ ref_ptr<Uniform> UniformFactoryImpl::getUniform( Effect * effect,
case Uniform::SAMPLER_1D_SHADOW: case Uniform::SAMPLER_1D_SHADOW:
case Uniform::SAMPLER_2D_SHADOW: case Uniform::SAMPLER_2D_SHADOW:
case Uniform::SAMPLER_CUBE: case Uniform::SAMPLER_CUBE:
updater = initFromParameters(effect, valProp, uniform.get(), initFromParameters(effect, valProp, uniform.get(),
static_cast<bool (Uniform::*)(int)>(&Uniform::set), static_cast<bool (Uniform::*)(int)>(&Uniform::set),
options); options);
break; break;
@ -199,7 +195,6 @@ ref_ptr<Uniform> UniformFactoryImpl::getUniform( Effect * effect,
break; break;
} }
addListener(updater);
return uniform; return uniform;
} }
@ -1443,6 +1438,11 @@ bool Effect::realizeTechniques(const SGReaderWriterOptions* options)
return true; return true;
} }
void Effect::addDeferredPropertyListener(DeferredPropertyListener* listener)
{
UniformFactory::instance()->addListener(listener);
}
void Effect::InitializeCallback::doUpdate(osg::Node* node, osg::NodeVisitor* nv) void Effect::InitializeCallback::doUpdate(osg::Node* node, osg::NodeVisitor* nv)
{ {
EffectGeode* eg = dynamic_cast<EffectGeode*>(node); EffectGeode* eg = dynamic_cast<EffectGeode*>(node);
@ -1455,16 +1455,6 @@ void Effect::InitializeCallback::doUpdate(osg::Node* node, osg::NodeVisitor* nv)
// Initialize all queued listeners // Initialize all queued listeners
UniformFactory::instance()->updateListeners(root); UniformFactory::instance()->updateListeners(root);
for (vector<SGSharedPtr<Updater> >::iterator itr = effect->_extraData.begin(),
end = effect->_extraData.end();
itr != end;
++itr) {
InitializeWhenAdded* adder
= dynamic_cast<InitializeWhenAdded*>(itr->ptr());
if (adder)
adder->initOnAdd(effect, root);
}
} }
bool Effect::Key::EqualTo::operator()(const Effect::Key& lhs, bool Effect::Key::EqualTo::operator()(const Effect::Key& lhs,

View File

@ -54,32 +54,12 @@ class SGReaderWriterOptions;
* things, like manipulations of the global property tree, are are * things, like manipulations of the global property tree, are are
* only safe in the update process. * only safe in the update process.
*/ */
class InitializeWhenAdded
{
public:
InitializeWhenAdded() : _initialized(false) {};
virtual ~InitializeWhenAdded() {};
void initOnAdd(Effect* effect, SGPropertyNode* propRoot)
{
if (!_initialized) {
initOnAddImpl(effect, propRoot);
_initialized = true;
}
}
bool getInitialized() const { return _initialized; }
private:
virtual void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot) = 0;
bool _initialized;
};
class DeferredPropertyListener { class DeferredPropertyListener {
public: public:
virtual void activate(SGPropertyNode* propRoot) {}; virtual void activate(SGPropertyNode* propRoot) {};
virtual ~DeferredPropertyListener() {}; virtual ~DeferredPropertyListener() {};
}; };
class Effect : public osg::Object class Effect : public osg::Object
{ {
public: public:
@ -111,16 +91,7 @@ public:
* Build the techniques from the effect properties. * Build the techniques from the effect properties.
*/ */
bool realizeTechniques(const SGReaderWriterOptions* options = 0); bool realizeTechniques(const SGReaderWriterOptions* options = 0);
/** void addDeferredPropertyListener(DeferredPropertyListener* listener);
* Updaters that should be derefed when the effect is
* deleted. Updaters arrange to be run by listening on properties
* or something.
*/
struct Updater : public virtual SGReferenced
{
virtual ~Updater() {}
};
void addUpdater(Updater* data) { _extraData.push_back(data); }
// Callback that is added to the effect geode to initialize the // Callback that is added to the effect geode to initialize the
// effect. // effect.
friend struct InitializeCallback; friend struct InitializeCallback;
@ -129,7 +100,6 @@ public:
void doUpdate(osg::Node* node, osg::NodeVisitor* nv); void doUpdate(osg::Node* node, osg::NodeVisitor* nv);
}; };
protected: protected:
std::vector<SGSharedPtr<Updater> > _extraData;
~Effect(); ~Effect();
// Support for a cache of effects that inherit from this one, so // Support for a cache of effects that inherit from this one, so
// Effect objects with the same parameters and techniques can be // Effect objects with the same parameters and techniques can be

View File

@ -607,33 +607,33 @@ inline void setDynamicVariance(osg::Object* obj)
* used. * used.
*/ */
template<typename OSGParamType, typename ObjType, typename F> template<typename OSGParamType, typename ObjType, typename F>
DeferredPropertyListener* void
initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj, initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
const F& setter, const SGReaderWriterOptions* options) const F& setter, const SGReaderWriterOptions* options)
{ {
const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop); const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
ScalarChangeListener<OSGParamType, ObjType, F>* listener = 0;
if (!valProp) if (!valProp)
return listener; return;
if (valProp->nChildren() == 0) { if (valProp->nChildren() == 0) {
setter(obj, valProp->getValue<OSGParamType>()); setter(obj, valProp->getValue<OSGParamType>());
} else { } else {
setDynamicVariance(obj); setDynamicVariance(obj);
std::string propName = getGlobalProperty(valProp, options); std::string propName = getGlobalProperty(valProp, options);
listener ScalarChangeListener<OSGParamType, ObjType, F>* listener
= new ScalarChangeListener<OSGParamType, ObjType, F>(obj, setter, = new ScalarChangeListener<OSGParamType, ObjType, F>(obj, setter,
propName); propName);
effect->addDeferredPropertyListener(listener);
} }
return listener; return;
} }
template<typename OSGParamType, typename ObjType, typename SetterReturn> template<typename OSGParamType, typename ObjType, typename SetterReturn>
inline DeferredPropertyListener* inline void
initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj, initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
SetterReturn (ObjType::*setter)(const OSGParamType), SetterReturn (ObjType::*setter)(const OSGParamType),
const SGReaderWriterOptions* options) const SGReaderWriterOptions* options)
{ {
return initFromParameters<OSGParamType>(effect, prop, obj, initFromParameters<OSGParamType>(effect, prop, obj,
boost::bind(setter, _1, _2), options); boost::bind(setter, _1, _2), options);
} }
@ -658,17 +658,16 @@ initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
*/ */
template<typename OSGParamType, typename ObjType, typename NameItrType, template<typename OSGParamType, typename ObjType, typename NameItrType,
typename F> typename F>
DeferredPropertyListener* void
initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj, initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
const F& setter, const F& setter,
NameItrType nameItr, const SGReaderWriterOptions* options) NameItrType nameItr, const SGReaderWriterOptions* options)
{ {
typedef typename Bridge<OSGParamType>::sg_type sg_type; typedef typename Bridge<OSGParamType>::sg_type sg_type;
DeferredPropertyListener* listener = 0;
const int numComponents = props::NumComponents<sg_type>::num_components; const int numComponents = props::NumComponents<sg_type>::num_components;
const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop); const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
if (!valProp) if (!valProp)
return listener; return;
if (valProp->nChildren() == 0) { // Has <use>? if (valProp->nChildren() == 0) { // Has <use>?
setter(obj, Bridge<OSGParamType>::get(valProp->getValue<sg_type>())); setter(obj, Bridge<OSGParamType>::get(valProp->getValue<sg_type>()));
} else { } else {
@ -678,22 +677,23 @@ initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
if (paramNames.empty()) if (paramNames.empty())
throw BuilderException(); throw BuilderException();
std::vector<std::string>::const_iterator pitr = paramNames.begin(); std::vector<std::string>::const_iterator pitr = paramNames.begin();
listener DeferredPropertyListener* listener
= new_EEPropListener<sg_type>(make_OSGFunctor<OSGParamType> = new_EEPropListener<sg_type>(make_OSGFunctor<OSGParamType>
(obj, setter), (obj, setter),
0, pitr, pitr + numComponents); 0, pitr, pitr + numComponents);
effect->addDeferredPropertyListener(listener);
} }
return listener; return;
} }
template<typename OSGParamType, typename ObjType, typename NameItrType, template<typename OSGParamType, typename ObjType, typename NameItrType,
typename SetterReturn> typename SetterReturn>
inline DeferredPropertyListener* inline void
initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj, initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
SetterReturn (ObjType::*setter)(const OSGParamType&), SetterReturn (ObjType::*setter)(const OSGParamType&),
NameItrType nameItr, const SGReaderWriterOptions* options) NameItrType nameItr, const SGReaderWriterOptions* options)
{ {
return initFromParameters<OSGParamType>(effect, prop, obj, initFromParameters<OSGParamType>(effect, prop, obj,
boost::bind(setter, _1, _2), nameItr, boost::bind(setter, _1, _2), nameItr,
options); options);
} }

View File

@ -859,12 +859,9 @@ TexEnvCombine* buildTexEnvCombine(Effect* effect, const SGPropertyNode* envProp,
#endif #endif
const SGPropertyNode* colorNode = envProp->getChild("constant-color"); const SGPropertyNode* colorNode = envProp->getChild("constant-color");
if (colorNode) { if (colorNode) {
DeferredPropertyListener* listener = initFromParameters(effect, colorNode, result, initFromParameters(effect, colorNode, result,
&TexEnvCombine::setConstantColor, colorFields, &TexEnvCombine::setConstantColor, colorFields,
options); options);
if (listener != 0) {
SG_LOG(SG_ALL,SG_ALERT,"Texture with property defined parameter");
}
} }
return result; return result;
} }
@ -961,8 +958,8 @@ private:
string buffer; string buffer;
}; };
class BufferNameChangeListener : public SGPropertyChangeListener, public InitializeWhenAdded, class BufferNameChangeListener : public SGPropertyChangeListener,
public Effect::Updater { public DeferredPropertyListener {
public: public:
BufferNameChangeListener(Pass* p, int u, const std::string& pn) : pass(p), unit(u) BufferNameChangeListener(Pass* p, int u, const std::string& pn) : pass(p), unit(u)
{ {
@ -978,7 +975,7 @@ public:
const char* buffer = node->getStringValue(); const char* buffer = node->getStringValue();
pass->setBufferUnit(unit, buffer); pass->setBufferUnit(unit, buffer);
} }
void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot) void activate(SGPropertyNode* propRoot)
{ {
SGPropertyNode* listenProp = makeNode(propRoot, *propName); SGPropertyNode* listenProp = makeNode(propRoot, *propName);
delete propName; delete propName;
@ -1014,7 +1011,7 @@ Texture* GBufferBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode*
} else { } else {
std::string propName = getGlobalProperty(nameProp, options); std::string propName = getGlobalProperty(nameProp, options);
BufferNameChangeListener* listener = new BufferNameChangeListener(pass, unit, propName); BufferNameChangeListener* listener = new BufferNameChangeListener(pass, unit, propName);
effect->addUpdater(listener); effect->addDeferredPropertyListener(listener);
} }
// Return white for now. Would be overridden in Technique::ProcessDrawable // Return white for now. Would be overridden in Technique::ProcessDrawable