diff --git a/glslang/MachineIndependent/iomapper.cpp b/glslang/MachineIndependent/iomapper.cpp index 8b80cbed1..e68e0f8ac 100644 --- a/glslang/MachineIndependent/iomapper.cpp +++ b/glslang/MachineIndependent/iomapper.cpp @@ -201,6 +201,36 @@ public: const TVarLiveMap& uniformList; }; +struct TNotifyUniformAdaptor +{ + EShLanguage stage; + TIoMapResolver& resolver; + inline TNotifyUniformAdaptor(EShLanguage s, TIoMapResolver& r) + : stage(s) + , resolver(r) + { + } + inline void operator()(TVarEntryInfo& ent) + { + resolver.notifyBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live); + } +}; + +struct TNotifyInOutAdaptor +{ + EShLanguage stage; + TIoMapResolver& resolver; + inline TNotifyInOutAdaptor(EShLanguage s, TIoMapResolver& r) + : stage(s) + , resolver(r) + { + } + inline void operator()(TVarEntryInfo& ent) + { + resolver.notifyInOut(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live); + } +}; + struct TResolverUniformAdaptor { TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e, TIntermediate& interm) @@ -383,6 +413,10 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver return -1; } + void notifyBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) override {} + void notifyInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) override {} + void endNotifications() override {} + protected: static int getLayoutSet(const glslang::TType& type) { if (type.getQualifier().hasSet()) @@ -674,8 +708,14 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi std::sort(uniformVarMap.begin(), uniformVarMap.end(), TVarEntryInfo::TOrderByPriority()); bool hadError = false; + TNotifyInOutAdaptor inOutNotify(stage, *resolver); + TNotifyUniformAdaptor uniformNotify(stage, *resolver); TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError, intermediate); TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError, intermediate); + std::for_each(inVarMap.begin(), inVarMap.end(), inOutNotify); + std::for_each(outVarMap.begin(), outVarMap.end(), inOutNotify); + std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformNotify); + resolver->endNotifications(); std::for_each(inVarMap.begin(), inVarMap.end(), inOutResolve); std::for_each(outVarMap.begin(), outVarMap.end(), inOutResolve); std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformResolve); diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 432329ce0..c2aa1ad29 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -463,6 +463,13 @@ class TIoMapper; // 5) all uniforms with set but no binding defined // 6) all uniforms with no binding and no set defined // +// mapIO will use this resolver in two phases. The first +// phase is a notification phase, calling the corresponging +// notifiy callbacks, this phase ends with a call to endNotifications. +// Phase two starts directly after the call to endNotifications +// and calls all other callbacks to validate and to get the +// bindings, sets, locations, component and color indices. +// // NOTE: that still limit checks are applied to bindings and sets // and may result in an error. class TIoMapResolver @@ -491,6 +498,12 @@ public: // Should return a value >= 0 if the current color index should be overridden. // Return -1 if the current color index (including no index) should be kept. virtual int resolveInOutIndex(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; + // Notification of a uniform variable + virtual void notifyBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; + // Notification of a in or out variable + virtual void notifyInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0; + // Called by mapIO when it has finished the notify pass + virtual void endNotifications() = 0; }; // Make one TProgram per set of shaders that will get linked together. Add all