Browse Source

Initial version of shader pool (this was ported from the font pool code).

aignacio_sf 20 years ago
parent
commit
ce55dd4956

+ 3 - 0
panda/src/pgraph/Sources.pp

@@ -98,6 +98,7 @@
     shader.I shader.h \
     shaderAttrib.I shaderAttrib.h \
     shaderInput.I shaderInput.h \
+    shaderPool.I shaderPool.h \
     showBoundsEffect.I showBoundsEffect.h \
     spotlight.I spotlight.h \
     stateMunger.I stateMunger.h \
@@ -205,6 +206,7 @@
     shader.cxx \
     shaderAttrib.cxx \
     shaderInput.cxx \
+    shaderPool.cxx \
     showBoundsEffect.cxx \
     spotlight.cxx \
     stateMunger.cxx \
@@ -308,6 +310,7 @@
     shader.I shader.h \
     shaderAttrib.I shaderAttrib.h \
     shaderInput.I shaderInput.h \
+    shaderPool.I shaderPool.h \
     showBoundsEffect.I showBoundsEffect.h \
     spotlight.I spotlight.h \
     stateMunger.I stateMunger.h \

+ 1 - 0
panda/src/pgraph/pgraph_composite4.cxx

@@ -12,6 +12,7 @@
 #include "shader.cxx"
 #include "shaderInput.cxx"
 #include "shaderAttrib.cxx"
+#include "shaderPool.cxx"
 #include "showBoundsEffect.cxx"
 #include "spotlight.cxx"
 #include "stateMunger.cxx"

+ 131 - 0
panda/src/pgraph/shaderPool.I

@@ -0,0 +1,131 @@
+// Filename: shaderPool.I
+// Created by:  aignacio (Mar06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::has_shader
+//       Access: Public, Static
+//  Description: Returns true if the shader has ever been loaded,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool ShaderPool::
+has_shader(const string &filename) {
+  return get_ptr()->ns_has_shader(filename);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::verify_shader
+//       Access: Public, Static
+//  Description: Loads the given filename up into a shader, if it has
+//               not already been loaded, and returns true to indicate
+//               success, or false to indicate failure.  If this
+//               returns true, it is guaranteed that a subsequent call
+//               to load_shader() with the same shader name will
+//               return a valid Shader pointer.
+////////////////////////////////////////////////////////////////////
+INLINE bool ShaderPool::
+verify_shader(const string &filename) {
+  return load_shader(filename) != (Shader *)NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::load_shader
+//       Access: Public, Static
+//  Description: Loads the given filename up into a shader, if it has
+//               not already been loaded, and returns the new shader.
+//               If a shader with the same filename was previously
+//               loaded, returns that one instead.  If the shader
+//               file cannot be found, returns NULL.
+////////////////////////////////////////////////////////////////////
+INLINE CPT(Shader) ShaderPool::
+load_shader(const string &filename) {
+  return get_ptr()->ns_load_shader(filename);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::add_shader
+//       Access: Public, Static
+//  Description: Adds the indicated already-loaded shader to the
+//               pool.  The shader will always replace any
+//               previously-loaded shader in the pool that had the
+//               same filename.
+////////////////////////////////////////////////////////////////////
+INLINE void ShaderPool::
+add_shader(const string &filename, Shader *shader) {
+  get_ptr()->ns_add_shader(filename, shader);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::release_shader
+//       Access: Public, Static
+//  Description: Removes the indicated shader from the pool,
+//               indicating it will never be loaded again; the shader
+//               may then be freed.  If this function is never called,
+//               a reference count will be maintained on every shader
+//               every loaded, and shaders will never be freed.
+////////////////////////////////////////////////////////////////////
+INLINE void ShaderPool::
+release_shader(const string &filename) {
+  get_ptr()->ns_release_shader(filename);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::release_all_shaders
+//       Access: Public, Static
+//  Description: Releases all shaders in the pool and restores the
+//               pool to the empty state.
+////////////////////////////////////////////////////////////////////
+INLINE void ShaderPool::
+release_all_shaders() {
+  get_ptr()->ns_release_all_shaders();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::garbage_collect
+//       Access: Public, Static
+//  Description: Releases only those shaders in the pool that have a
+//               reference count of exactly 1; i.e. only those
+//               shaders that are not being used outside of the pool.
+//               Returns the number of shaders released.
+////////////////////////////////////////////////////////////////////
+INLINE int ShaderPool::
+garbage_collect() {
+  return get_ptr()->ns_garbage_collect();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::list_contents
+//       Access: Public, Static
+//  Description: Lists the contents of the shader pool to the
+//               indicated output stream.
+////////////////////////////////////////////////////////////////////
+INLINE void ShaderPool::
+list_contents(ostream &out) {
+  get_ptr()->ns_list_contents(out);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::Constructor
+//       Access: Private
+//  Description: The constructor is not intended to be called
+//               directly; there's only supposed to be one ShaderPool
+//               in the universe and it constructs itself.
+////////////////////////////////////////////////////////////////////
+INLINE ShaderPool::
+ShaderPool() {
+}

+ 258 - 0
panda/src/pgraph/shaderPool.cxx

@@ -0,0 +1,258 @@
+// Filename: shaderPool.cxx
+// Created by:  aignacio (Mar06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2006, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "shaderPool.h"
+#include "config_util.h"
+#include "config_express.h"
+#include "virtualFileSystem.h"
+#include "loader.h"
+#include "shader.h"
+
+ShaderPool *ShaderPool::_global_ptr = (ShaderPool *)NULL;
+
+// ??? Is this needed ???
+static Loader model_loader;
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::write
+//       Access: Published, Static
+//  Description: Lists the contents of the shader pool to the
+//               indicated output stream.
+////////////////////////////////////////////////////////////////////
+void ShaderPool::
+write(ostream &out) {
+  get_ptr()->ns_list_contents(out);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::ns_has_shader
+//       Access: Private
+//  Description: The nonstatic implementation of has_shader().
+////////////////////////////////////////////////////////////////////
+bool ShaderPool::
+ns_has_shader(const string &str) {
+  string index_str;
+  Filename filename;
+  int face_index;
+  lookup_filename(str, index_str, filename, face_index);
+
+  Shaders::const_iterator ti;
+  ti = _shaders.find(index_str);
+  if (ti != _shaders.end()) {
+    // This shader was previously loaded.
+    return true;
+  }
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::ns_load_shader
+//       Access: Private
+//  Description: The nonstatic implementation of load_shader().
+////////////////////////////////////////////////////////////////////
+CPT(Shader) ShaderPool::
+ns_load_shader(const string &str) {
+  string index_str;
+  Filename filename;
+  int face_index;
+  lookup_filename(str, index_str, filename, face_index);
+
+  Shaders::const_iterator ti;
+  ti = _shaders.find(index_str);
+  if (ti != _shaders.end()) {
+    // This shader was previously loaded.
+    return (*ti).second;
+  }
+
+/*
+  shader_cat.info()
+    << "Loading shader " << filename << "\n";
+*/
+
+  CPT(Shader) shader;
+
+  shader = (CPT(Shader)) NULL;
+  string extension = filename.get_extension();
+
+  if (extension.empty() || extension == "cg" || extension == "hlsl") {
+    // this does nothing for now
+  }
+
+// ***** face_index ???
+
+  if (shader == (CPT(Shader)) NULL) {
+    int preprocessor;
+
+    preprocessor = 0;
+    shader = Shader::load (filename, preprocessor);
+    if (shader) {
+      if (shader -> get_load_error ( )) {
+//        delete shader;
+        shader = (CPT(Shader)) NULL;
+      }
+    }
+  }
+
+  if (shader == (CPT(Shader)) NULL) {
+    // This shader was not found or could not be read.
+    return NULL;
+  }
+
+  _shaders[index_str] = shader;
+  return shader;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::ns_add_shader
+//       Access: Private
+//  Description: The nonstatic implementation of add_shader().
+////////////////////////////////////////////////////////////////////
+void ShaderPool::
+ns_add_shader(const string &str, Shader *shader) {
+  string index_str;
+  Filename filename;
+  int face_index;
+  lookup_filename(str, index_str, filename, face_index);
+
+  // We blow away whatever shader was there previously, if any.
+  _shaders[index_str] = shader;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::ns_release_shader
+//       Access: Private
+//  Description: The nonstatic implementation of release_shader().
+////////////////////////////////////////////////////////////////////
+void ShaderPool::
+ns_release_shader(const string &filename) {
+  Shaders::iterator ti;
+  ti = _shaders.find(filename);
+  if (ti != _shaders.end()) {
+    _shaders.erase(ti);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::ns_release_all_shaders
+//       Access: Private
+//  Description: The nonstatic implementation of release_all_shaders().
+////////////////////////////////////////////////////////////////////
+void ShaderPool::
+ns_release_all_shaders() {
+  _shaders.clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::ns_garbage_collect
+//       Access: Private
+//  Description: The nonstatic implementation of garbage_collect().
+////////////////////////////////////////////////////////////////////
+int ShaderPool::
+ns_garbage_collect() {
+  int num_released = 0;
+  Shaders new_set;
+
+  Shaders::iterator ti;
+  for (ti = _shaders.begin(); ti != _shaders.end(); ++ti) {
+    CPT(Shader) shader = (*ti).second;
+    if (shader->get_ref_count() == 1) {
+/*
+      if (shader_cat.is_debug()) {
+        shader_cat.debug()
+          << "Releasing " << (*ti).first << "\n";
+      }
+*/
+      num_released++;
+    } else {
+      new_set.insert(new_set.end(), *ti);
+    }
+  }
+
+  _shaders.swap(new_set);
+  return num_released;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::ns_list_contents
+//       Access: Private
+//  Description: The nonstatic implementation of list_contents().
+////////////////////////////////////////////////////////////////////
+void ShaderPool::
+ns_list_contents(ostream &out) const {
+  out << _shaders.size() << " shaders:\n";
+  Shaders::const_iterator ti;
+  for (ti = _shaders.begin(); ti != _shaders.end(); ++ti) {
+    CPT(Shader) shader = (*ti).second;
+    out << "  " << (*ti).first
+        << " (count = " << shader->get_ref_count() << ")\n";
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::lookup_filename
+//       Access: Private, Static
+//  Description: Accepts a shader "filename", which might consist of a
+//               filename followed by an optional colon and a face
+//               index, and splits it out into its two components.
+//               Then it looks up the filename on the model path.
+//               Sets the filename and face index accordingly.  Also
+//               sets index_str to be the concatenation of the
+//               found filename with the face index, thus restoring
+//               the original input (but normalized to contain the
+//               full path.)
+////////////////////////////////////////////////////////////////////
+void ShaderPool::
+lookup_filename(const string &str, string &index_str,
+                Filename &filename, int &face_index) {
+  int colon = (int)str.length() - 1;
+  // Scan backwards over digits for a colon.
+  while (colon >= 0 && isdigit(str[colon])) {
+    --colon;
+  }
+  if (colon >= 0 && str[colon] == ':') {
+    string digits = str.substr(colon + 1);
+    filename = str.substr(0, colon);
+    face_index = atoi(digits.c_str());
+  } else {
+    filename = str;
+    face_index = 0;
+  }
+
+  // Now look up the filename on the model path.
+  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
+  vfs->resolve_filename(filename, get_model_path());
+
+  ostringstream strm;
+  strm << filename << ":" << face_index;
+  index_str = strm.str();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderPool::get_ptr
+//       Access: Private, Static
+//  Description: Initializes and/or returns the global pointer to the
+//               one ShaderPool object in the system.
+////////////////////////////////////////////////////////////////////
+ShaderPool *ShaderPool::
+get_ptr() {
+  if (_global_ptr == (ShaderPool *)NULL) {
+    _global_ptr = new ShaderPool;
+  }
+  return _global_ptr;
+}

+ 76 - 0
panda/src/pgraph/shaderPool.h

@@ -0,0 +1,76 @@
+// Filename: shaderPool.h
+// Created by:  aignacio (Mar06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2006, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef SHADERPOOL_H
+#define SHADERPOOL_H
+
+#include "pandabase.h"
+
+#include "shader.h"
+
+#include "filename.h"
+#include "pmap.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : ShaderPool
+// Description : This is the preferred interface for loading shaders for
+//               the TextNode system.  It is similar to ModelPool and
+//               TexturePool in that it unifies references to the same
+//               filename.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA ShaderPool {
+PUBLISHED:
+  // These functions take string parameters instead of Filenames
+  // because that's somewhat more convenient to the scripting
+  // language.
+  INLINE static bool has_shader(const string &filename);
+  INLINE static bool verify_shader(const string &filename);
+  INLINE static CPT(Shader) load_shader(const string &filename);
+  INLINE static void add_shader(const string &filename, Shader *shader);
+  INLINE static void release_shader(const string &filename);
+  INLINE static void release_all_shaders();
+
+  INLINE static int garbage_collect();
+
+  INLINE static void list_contents(ostream &out);
+  static void write(ostream &out);
+
+private:
+  INLINE ShaderPool();
+
+  bool ns_has_shader(const string &str);
+  CPT(Shader) ns_load_shader(const string &str);
+  void ns_add_shader(const string &str, Shader *shader);
+  void ns_release_shader(const string &filename);
+  void ns_release_all_shaders();
+  int ns_garbage_collect();
+  void ns_list_contents(ostream &out) const;
+
+  static void lookup_filename(const string &str, string &index_str,
+                              Filename &filename, int &face_index);
+
+  static ShaderPool *get_ptr();
+
+  static ShaderPool *_global_ptr;
+  typedef pmap<string,  CPT(Shader) > Shaders;
+  Shaders _shaders;
+};
+
+#include "shaderPool.I"
+
+#endif