diff --git a/simgear/scene/material/Effect.cxx b/simgear/scene/material/Effect.cxx index 65e8364d..d32654d5 100644 --- a/simgear/scene/material/Effect.cxx +++ b/simgear/scene/material/Effect.cxx @@ -227,8 +227,9 @@ Effect::Effect() } Effect::Effect(const Effect& rhs, const CopyOp& copyop) - : osg::Object(rhs,copyop), root(rhs.root), parametersProp(rhs.parametersProp), _cache(0), - _isRealized(rhs._isRealized) + : osg::Object(rhs, copyop), root(rhs.root), parametersProp(rhs.parametersProp), _cache(0), + _isRealized(rhs._isRealized), + _effectFilePath(rhs._effectFilePath) { typedef vector > TechniqueList; for (TechniqueList::const_iterator itr = rhs.techniques.begin(), @@ -961,7 +962,11 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass, pass->setAttributeAndModes(program); return; } - program = new SGProgram; + + auto sgprogram = new SGProgram; + program = sgprogram; + sgprogram->setEffectFilePath(effect->filePath()); + for (const auto& skey : resolvedKey.shaders) { const string& fileName = skey.first; Shader::Type stype = (Shader::Type)skey.second; @@ -1654,3 +1659,15 @@ expression::ExpParserRegistrar propvalueRegistrar("float-property", propertyExpressionParser); } + +using namespace simgear; + +void Effect::setFilePath(const SGPath& path) +{ + _effectFilePath = path; +} + +SGPath Effect::filePath() const +{ + return _effectFilePath; +} diff --git a/simgear/scene/material/Effect.hxx b/simgear/scene/material/Effect.hxx index c6afd738..438533a3 100644 --- a/simgear/scene/material/Effect.hxx +++ b/simgear/scene/material/Effect.hxx @@ -29,10 +29,11 @@ #include #include +#include #include #include -#include #include +#include namespace osg { @@ -106,6 +107,10 @@ public: std::string getName(){return _name;} void setName(std::string name){_name = name;} + + void setFilePath(const SGPath& path); + SGPath filePath() const; + protected: ~Effect(); // Support for a cache of effects that inherit from this one, so @@ -142,10 +147,13 @@ protected: Cache* _cache; friend size_t hash_value(const Key& key); friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques, - const SGReaderWriterOptions* options); + const SGReaderWriterOptions* options, + const SGPath& path); bool _isRealized; std::string _name; + SGPath _effectFilePath; }; + // Automatic support for boost hash function size_t hash_value(const Effect::Key&); @@ -156,7 +164,8 @@ Effect* makeEffect(const std::string& name, Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques, - const SGReaderWriterOptions* options); + const SGReaderWriterOptions* options, + const SGPath& path = SGPath{}); bool makeParametersFromStateSet(SGPropertyNode* paramRoot, const osg::StateSet* ss); diff --git a/simgear/scene/material/makeEffect.cxx b/simgear/scene/material/makeEffect.cxx index b006990e..0f3b06e6 100644 --- a/simgear/scene/material/makeEffect.cxx +++ b/simgear/scene/material/makeEffect.cxx @@ -26,8 +26,9 @@ #include #include -#include +#include #include +#include #include #include #include @@ -139,7 +140,7 @@ Effect* makeEffect(const string& name, return 0; } ref_ptr result = makeEffect(effectProps.ptr(), realizeTechniques, - options); + options, SGPath::fromUtf8(absFileName)); if (result.valid()) { OpenThreads::ScopedLock lock(effectMutex); pair irslt @@ -156,7 +157,8 @@ Effect* makeEffect(const string& name, Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques, - const SGReaderWriterOptions* options) + const SGReaderWriterOptions* options, + const SGPath& filePath) { // Give default names to techniques and passes vector techniques = prop->getChildren("technique"); @@ -217,6 +219,7 @@ Effect* makeEffect(SGPropertyNode* prop, if (!effect.valid()) { effect = new Effect; effect->setName(nameProp->getStringValue()); + effect->setFilePath(filePath.isNull() ? parent->filePath() : filePath); effect->root = new SGPropertyNode; mergePropertyTrees(effect->root, prop, parent->root); effect->parametersProp = effect->root->getChild("parameters"); @@ -240,6 +243,7 @@ Effect* makeEffect(SGPropertyNode* prop, } } else { effect = new Effect; + effect->setFilePath(filePath); effect->setName(nameProp->getStringValue()); effect->root = prop; effect->parametersProp = effect->root->getChild("parameters"); diff --git a/simgear/scene/util/SGProgram.cxx b/simgear/scene/util/SGProgram.cxx index 6034cf28..419493c6 100644 --- a/simgear/scene/util/SGProgram.cxx +++ b/simgear/scene/util/SGProgram.cxx @@ -20,13 +20,25 @@ #include "SGProgram.hxx" #include +#include #include +#include -SGProgram::SGProgram(const SGProgram& rhs, const osg::CopyOp& copyop) : osg::Program(rhs, copyop) +SGProgram::SGProgram() { } +SGProgram::SGProgram(const SGProgram& rhs, const osg::CopyOp& copyop) : osg::Program(rhs, copyop), + _effectFilePath(rhs._effectFilePath) +{ +} + +void SGProgram::setEffectFilePath(const SGPath& p) +{ + _effectFilePath = p; +} + void SGProgram::apply(osg::State& state) const { osg::Program::apply(state); @@ -41,8 +53,17 @@ void SGProgram::apply(osg::State& state) const _checkState = FailedToApply; getPCP(state)->getInfoLog(infoLog); + // log all the shader source file names, to help in debugging link errors + std::ostringstream os; + for (int i = 0; i < getNumShaders(); ++i) { + const auto shader = getShader(i); + os << "\t" << shader->getFileName() << "\n"; + } + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadEffectsShaders, - "Shader program errors: " + infoLog, sg_location()); + "Shader program errors: " + infoLog + + "\n\nShader sources:\n" + os.str(), + _effectFilePath); for (int i = 0; i < getNumShaders(); ++i) { const auto shader = getShader(i); diff --git a/simgear/scene/util/SGProgram.hxx b/simgear/scene/util/SGProgram.hxx index 2d66df6f..7af8bfa0 100644 --- a/simgear/scene/util/SGProgram.hxx +++ b/simgear/scene/util/SGProgram.hxx @@ -18,6 +18,8 @@ #include +#include + /** * @brief wrapper around osg::Program to allow detecting shader/link * errors in the GLSL code at runtime, and reporting of them @@ -26,7 +28,7 @@ class SGProgram : public osg::Program { public: - SGProgram() = default; + SGProgram(); SGProgram(const SGProgram& rhs, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY); @@ -40,6 +42,9 @@ public: FailedToApply }; + void setEffectFilePath(const SGPath& p); + private: + SGPath _effectFilePath; mutable ErrorCheckState _checkState = NotApplied; };