diff --git a/simgear/scene/material/Effect.cxx b/simgear/scene/material/Effect.cxx index cd32ff89..65e8364d 100644 --- a/simgear/scene/material/Effect.cxx +++ b/simgear/scene/material/Effect.cxx @@ -73,6 +73,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,7 @@ bool loadShaderFromUTF8File(osg::Shader* shader, const std::string& fileName) if (!inStream.is_open()) return false; + shader->setFileName(fileName); shader->setShaderSource(inStream.read_all()); return true; } @@ -959,7 +961,7 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass, pass->setAttributeAndModes(program); return; } - program = new Program; + program = new SGProgram; for (const auto& skey : resolvedKey.shaders) { const string& fileName = skey.first; Shader::Type stype = (Shader::Type)skey.second; diff --git a/simgear/scene/util/CMakeLists.txt b/simgear/scene/util/CMakeLists.txt index 7177f87e..dae7c008 100644 --- a/simgear/scene/util/CMakeLists.txt +++ b/simgear/scene/util/CMakeLists.txt @@ -31,6 +31,7 @@ set(HEADERS UpdateOnceCallback.hxx VectorArrayAdapter.hxx project.hxx + SGProgram.hxx ) set(SOURCES @@ -55,6 +56,7 @@ set(SOURCES StateAttributeFactory.cxx UpdateOnceCallback.cxx project.cxx + SGProgram.cxx ) simgear_scene_component(util scene/util "${SOURCES}" "${HEADERS}") diff --git a/simgear/scene/util/SGProgram.cxx b/simgear/scene/util/SGProgram.cxx new file mode 100644 index 00000000..6034cf28 --- /dev/null +++ b/simgear/scene/util/SGProgram.cxx @@ -0,0 +1,61 @@ +//// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301, USA. + + +#include "simgear_config.h" + +#include "SGProgram.hxx" + +#include + +#include + +SGProgram::SGProgram(const SGProgram& rhs, const osg::CopyOp& copyop) : osg::Program(rhs, copyop) +{ +} + +void SGProgram::apply(osg::State& state) const +{ + osg::Program::apply(state); + + if (_checkState != NotApplied) { + return; // already done + } + + auto pcp = state.getLastAppliedProgramObject(); + if (!pcp) { + std::string infoLog; + _checkState = FailedToApply; + getPCP(state)->getInfoLog(infoLog); + + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadEffectsShaders, + "Shader program errors: " + infoLog, sg_location()); + + for (int i = 0; i < getNumShaders(); ++i) { + const auto shader = getShader(i); + auto pcs = shader->getPCS(state); + + std::string shaderLog; + pcs->getInfoLog(shaderLog); + if (!shaderLog.empty()) { + simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadEffectsShaders, + "Shader source errors: " + shaderLog, sg_location(shader->getFileName())); + } + } + } else { + _checkState = AppliedOk; + } +} diff --git a/simgear/scene/util/SGProgram.hxx b/simgear/scene/util/SGProgram.hxx new file mode 100644 index 00000000..2d66df6f --- /dev/null +++ b/simgear/scene/util/SGProgram.hxx @@ -0,0 +1,45 @@ +//// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#pragma once + +#include + +/** + * @brief wrapper around osg::Program to allow detecting shader/link + * errors in the GLSL code at runtime, and reporting of them + * + */ +class SGProgram : public osg::Program +{ +public: + SGProgram() = default; + + SGProgram(const SGProgram& rhs, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY); + + META_StateAttribute(simgear, SGProgram, PROGRAM); + + void apply(osg::State& state) const override; + + enum ErrorCheckState { + NotApplied, + AppliedOk, + FailedToApply + }; + +private: + mutable ErrorCheckState _checkState = NotApplied; +};