Radium Engine  1.5.0
ShaderProgramManager.cpp
1 #include <Engine/Data/ShaderConfiguration.hpp>
2 #include <Engine/Data/ShaderProgram.hpp>
3 #include <Engine/Data/ShaderProgramManager.hpp>
4 
5 #include <Core/Containers/MakeShared.hpp>
6 #include <Core/Utils/Log.hpp>
7 
8 #include <globjects/NamedString.h>
9 #include <globjects/Shader.h>
10 #include <globjects/base/File.h>
11 
12 namespace Ra {
13 namespace Engine {
14 namespace Data {
15 
16 using namespace Core::Utils; // log
17 using ShaderProgramPtr = std::shared_ptr<Data::ShaderProgram>;
18 
20 
21 ShaderProgramManager::~ShaderProgramManager() {
22  m_shaderPrograms.clear();
23 }
24 
25 bool ShaderProgramManager::addNamedString( const std::string& includepath,
26  const std::string& realfile ) {
27  auto el = m_namedStrings.find( includepath );
28  if ( el != m_namedStrings.end() ) {
29  if ( el->second.first->filePath() != realfile ) {
30  LOG( logWARNING )
31  << "[ShaderProgramManager] A named string already exists with this key: "
32  << includepath << " --> " << el->second.first->filePath();
33  }
34  else {
35  LOG( logINFO ) << "[ShaderProgramManager] Named string already inserted, skipping: "
36  << includepath << " --> " << realfile;
37  }
38 
39  return false;
40  }
41 
42  auto file = globjects::File::create( realfile );
43  m_namedStrings[includepath] = std::make_pair(
44  std::move( file ), globjects::NamedString::create( includepath, file.get() ) );
45 
46  return true;
47 }
48 
50  for ( auto& el : m_namedStrings ) {
51  el.second.first->reload();
52  el.second.second.reset( nullptr );
53  el.second.second = globjects::NamedString::create( el.first, el.second.first.get() );
54  }
55 }
56 
57 Core::Utils::optional<const Data::ShaderProgram*>
59  auto found = m_shaderPrograms.find( config );
60 
61  if ( found != m_shaderPrograms.end() ) { return found->second.get(); }
62 
63  // add named strings
64  for ( const auto& p : config.getNamedStrings() ) {
65  addNamedString( p.first, p.second );
66  }
67 
68  // Try to load the shader
69  auto prog = Core::make_shared<Data::ShaderProgram>( config );
70 
71  if ( prog->getProgramObject()->isLinked() ) {
72  insertShader( config, prog );
73  return prog.get();
74  }
75  else {
76 
77  LOG( logERROR ) << "Error occurred while loading shader program "
78  << config.getName().c_str() << ":\nDefault shader program used instead.";
79 
80  for ( const auto& strings : config.getNamedStrings() ) {
81  auto el = m_namedStrings.find( strings.first );
82  if ( el != m_namedStrings.end() ) {
83  if ( el->second.first->filePath() == strings.second ) {
84  LOG( logINFO ) << "[ShaderProgramManager] Removing named string "
85  << strings.first << " --> " << strings.second;
86  }
87  }
88  }
89 
90  // insert in the failed shaders list
91  m_shaderFailedConfs.push_back( config );
92 
93  return {};
94  }
95 }
96 
98  auto found = m_shaderProgramIds.find( id );
99 
100  if ( found != m_shaderProgramIds.end() ) { return getShaderProgram( found->second ); }
101  return nullptr;
102 }
103 
104 const Data::ShaderProgram*
106  auto res = addShaderProgram( config );
107  return bool( res ) ? *res : nullptr;
108 }
109 
111  // update the include registry
112  reloadNamedString();
113 
114  // For each shader in the map
115  for ( auto& shader : m_shaderPrograms ) {
116  shader.second->reload();
117  }
118 
119  // and also try the failed ones
120  reloadNotCompiledShaderPrograms();
121 }
122 
124  // for each shader in the failed map, try to reload
125  for ( const auto& conf : m_shaderFailedConfs ) {
126  auto prog = Core::make_shared<Data::ShaderProgram>( conf );
127 
128  if ( prog->getProgramObject()->isValid() ) {
129  insertShader( conf, prog );
130  // m_shaderFailedConfs.erase(conf);
131  }
132  }
133 }
134 
135 void ShaderProgramManager::insertShader( const Data::ShaderConfiguration& config,
136  const ShaderProgramPtr& shader ) {
137  m_shaderProgramIds.insert( { config.getName(), config } );
138  m_shaderPrograms.insert( { config, shader } );
139 }
140 
141 } // namespace Data
142 } // namespace Engine
143 } // namespace Ra
Core::Utils::optional< const Data::ShaderProgram * > addShaderProgram(const Data::ShaderConfiguration &config)
ShaderProgramManager()
Rule of three needed here to prevent copy on this manager (only movable)
const Data::ShaderProgram * getShaderProgram(const std::string &id)
bool addNamedString(const std::string &includepath, const std::string &realfile)
Definition: Cage.cpp:3