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 }
LightMutexHolder
Similar to MutexHolder, but for a light mutex.
Definition: lightMutexHolder.h:25
ShaderPool::write
static void write(std::ostream &out)
Lists the contents of the shader pool to the indicated output stream.
Definition: shaderPool.cxx:28
config_putil.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Shader
Definition: shader.h:49
string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CPT
CPT(Shader) ShaderPool
The nonstatic implementation of load_shader().
Definition: shaderPool.cxx:54
downcase
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
Definition: string_utils.cxx:71
VirtualFileSystem
A hierarchy of directories and files that appears to be one continuous file system,...
Definition: virtualFileSystem.h:40
shaderPool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VirtualFileSystem::get_global_ptr
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
Definition: virtualFileSystem.cxx:742
virtualFileSystem.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
shader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
loader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VirtualFileSystem::resolve_filename
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const std::string &default_extension=std::string()) const
Searches the given search path for the filename.
Definition: virtualFileSystem.cxx:641
ShaderPool
This is the preferred interface for loading shaders for the TextNode system.
Definition: shaderPool.h:28
config_express.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Filename::get_extension
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39