Panda3D
shaderPool.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file shaderPool.cxx
10  * @author aignacio
11  * @date 2006-03
12  */
13 
14 #include "shaderPool.h"
15 #include "config_putil.h"
16 #include "config_express.h"
17 #include "virtualFileSystem.h"
18 #include "loader.h"
19 #include "shader.h"
20 #include "string_utils.h"
21 
22 ShaderPool *ShaderPool::_global_ptr = nullptr;
23 
24 /**
25  * Lists the contents of the shader pool to the indicated output stream.
26  */
27 void ShaderPool::
28 write(std::ostream &out) {
29  get_ptr()->ns_list_contents(out);
30 }
31 
32 /**
33  * The nonstatic implementation of has_shader().
34  */
35 bool ShaderPool::
36 ns_has_shader(const Filename &orig_filename) {
37  Filename filename;
38  resolve_filename(filename, orig_filename);
39 
40  LightMutexHolder holder(_lock);
41  Shaders::const_iterator ti;
42  ti = _shaders.find(filename);
43  if (ti != _shaders.end()) {
44  // This shader was previously loaded.
45  return true;
46  }
47 
48  return false;
49 }
50 
51 /**
52  * The nonstatic implementation of load_shader().
53  */
54 CPT(Shader) ShaderPool::
55 ns_load_shader(const Filename &orig_filename) {
56  Filename filename;
57  resolve_filename(filename, orig_filename);
58 
59  {
60  LightMutexHolder holder(_lock);
61 
62  Shaders::const_iterator ti;
63  ti = _shaders.find(filename);
64  if (ti != _shaders.end()) {
65  // This shader was previously loaded.
66  return (*ti).second;
67  }
68  }
69 
70  // The shader was not found in the pool.
71  gobj_cat.info()
72  << "Loading shader " << filename << "\n";
73 
74  Shader::ShaderLanguage lang = Shader::SL_none;
75 
76  // Do some guesswork to see if we can figure out the shader language from
77  // the file extension. This is really just guesswork - there are no
78  // standardized extensions for shaders, especially for GLSL. These are the
79  // ones that appear to be closest to "standard".
80  std::string ext = downcase(filename.get_extension());
81  if (ext == "cg" || ext == "sha") {
82  // "sha" is for historical reasons.
83  lang = Shader::SL_Cg;
84 
85  } else if (ext == "glsl" || ext == "vert" || ext == "frag" ||
86  ext == "geom" || ext == "tesc" || ext == "tese" ||
87  ext == "comp") {
88  lang = Shader::SL_GLSL;
89  }
90 
91  PT(Shader) shader = Shader::load(filename, lang);
92  if (shader == nullptr) {
93  // This shader was not found or could not be read.
94  return nullptr;
95  }
96 
97  {
98  LightMutexHolder holder(_lock);
99 
100  // Now try again. Someone may have loaded the shader in another thread.
101  Shaders::const_iterator ti;
102  ti = _shaders.find(filename);
103  if (ti != _shaders.end()) {
104  // This shader was previously loaded.
105  return (*ti).second;
106  }
107 
108  _shaders[filename] = shader;
109  }
110 
111  return shader;
112 }
113 
114 /**
115  * The nonstatic implementation of add_shader().
116  */
117 void ShaderPool::
118 ns_add_shader(const Filename &orig_filename, Shader *shader) {
119  Filename filename;
120  resolve_filename(filename, orig_filename);
121 
122  LightMutexHolder holder(_lock);
123  // We blow away whatever shader was there previously, if any.
124  _shaders[filename] = shader;
125 }
126 
127 /**
128  * The nonstatic implementation of release_shader().
129  */
130 void ShaderPool::
131 ns_release_shader(const Filename &filename) {
132  LightMutexHolder holder(_lock);
133 
134  Shaders::iterator ti;
135  ti = _shaders.find(filename);
136  if (ti != _shaders.end()) {
137  _shaders.erase(ti);
138  }
139 }
140 
141 /**
142  * The nonstatic implementation of release_all_shaders().
143  */
144 void ShaderPool::
145 ns_release_all_shaders() {
146  LightMutexHolder holder(_lock);
147 
148  _shaders.clear();
149 }
150 
151 /**
152  * The nonstatic implementation of garbage_collect().
153  */
154 int ShaderPool::
155 ns_garbage_collect() {
156  LightMutexHolder holder(_lock);
157 
158  int num_released = 0;
159  Shaders new_set;
160 
161  Shaders::iterator ti;
162  for (ti = _shaders.begin(); ti != _shaders.end(); ++ti) {
163  CPT(Shader) shader = (*ti).second;
164  if (shader->get_ref_count() == 1) {
165 /*
166  if (shader_cat.is_debug()) {
167  shader_cat.debug()
168  << "Releasing " << (*ti).first << "\n";
169  }
170 */
171  num_released++;
172  } else {
173  new_set.insert(new_set.end(), *ti);
174  }
175  }
176 
177  _shaders.swap(new_set);
178  return num_released;
179 }
180 
181 /**
182  * The nonstatic implementation of list_contents().
183  */
184 void ShaderPool::
185 ns_list_contents(std::ostream &out) const {
186  LightMutexHolder holder(_lock);
187 
188  out << _shaders.size() << " shaders:\n";
189  Shaders::const_iterator ti;
190  for (ti = _shaders.begin(); ti != _shaders.end(); ++ti) {
191  CPT(Shader) shader = (*ti).second;
192  out << " " << (*ti).first
193  << " (count = " << shader->get_ref_count() << ")\n";
194  }
195 }
196 
197 
198 /**
199  * Searches for the indicated filename along the model path.
200  */
201 void ShaderPool::
202 resolve_filename(Filename &new_filename, const Filename &orig_filename) {
203  new_filename = orig_filename;
205  vfs->resolve_filename(new_filename, get_model_path());
206 }
207 
208 /**
209  * Initializes and/or returns the global pointer to the one ShaderPool object
210  * in the system.
211  */
212 ShaderPool *ShaderPool::
213 get_ptr() {
214  if (_global_ptr == nullptr) {
215  _global_ptr = new ShaderPool;
216  }
217  return _global_ptr;
218 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A hierarchy of directories and files that appears to be one continuous file system,...
Definition: shader.h:49
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
static void write(std::ostream &out)
Lists the contents of the shader pool to the indicated output stream.
Definition: shaderPool.cxx:28
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const std::string &default_extension=std::string()) const
Searches the given search path for the filename.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the preferred interface for loading shaders for the TextNode system.
Definition: shaderPool.h:28
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
Similar to MutexHolder, but for a light mutex.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CPT(Shader) ShaderPool
The nonstatic implementation of load_shader().
Definition: shaderPool.cxx:54