Răsfoiți Sursa

New shader system

Josh Yelon 20 ani în urmă
părinte
comite
f7ee3b5729

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

@@ -44,6 +44,7 @@
     preparedGraphicsObjects.I preparedGraphicsObjects.h \
     preparedGraphicsObjects.I preparedGraphicsObjects.h \
     lens.h lens.I \
     lens.h lens.I \
     savedContext.I savedContext.h \
     savedContext.I savedContext.h \
+    shader.I shader.h \
     sliderTable.I sliderTable.h \
     sliderTable.I sliderTable.h \
     texture.I texture.h \
     texture.I texture.h \
     textureContext.I textureContext.h \
     textureContext.I textureContext.h \
@@ -92,6 +93,7 @@
     preparedGraphicsObjects.cxx \
     preparedGraphicsObjects.cxx \
     lens.cxx  \
     lens.cxx  \
     savedContext.cxx \
     savedContext.cxx \
+    shader.cxx \
     sliderTable.cxx \
     sliderTable.cxx \
     texture.cxx textureContext.cxx texturePool.cxx \
     texture.cxx textureContext.cxx texturePool.cxx \
     textureStage.cxx \
     textureStage.cxx \
@@ -140,6 +142,7 @@
     preparedGraphicsObjects.I preparedGraphicsObjects.h \
     preparedGraphicsObjects.I preparedGraphicsObjects.h \
     lens.h lens.I \
     lens.h lens.I \
     savedContext.I savedContext.h \
     savedContext.I savedContext.h \
+    shader.h shaderContext.h \
     sliderTable.I sliderTable.h \
     sliderTable.I sliderTable.h \
     texture.I texture.h \
     texture.I texture.h \
     textureContext.I textureContext.h \
     textureContext.I textureContext.h \

+ 5 - 0
panda/src/gobj/config_gobj.cxx

@@ -42,6 +42,8 @@
 #include "texture.h"
 #include "texture.h"
 #include "textureStage.h"
 #include "textureStage.h"
 #include "textureContext.h"
 #include "textureContext.h"
+#include "shader.h"
+#include "shaderContext.h"
 #include "transformBlendTable.h"
 #include "transformBlendTable.h"
 #include "transformTable.h"
 #include "transformTable.h"
 #include "userVertexSlider.h"
 #include "userVertexSlider.h"
@@ -254,6 +256,8 @@ ConfigureFn(config_gobj) {
   Texture::init_type();
   Texture::init_type();
   dDrawable::init_type();
   dDrawable::init_type();
   TextureStage::init_type();
   TextureStage::init_type();
+  Shader::init_type();
+  ShaderContext::init_type();
   TransformBlendTable::init_type();
   TransformBlendTable::init_type();
   TransformTable::init_type();
   TransformTable::init_type();
   UserVertexSlider::init_type();
   UserVertexSlider::init_type();
@@ -280,6 +284,7 @@ ConfigureFn(config_gobj) {
   MatrixLens::register_with_read_factory();
   MatrixLens::register_with_read_factory();
   PerspectiveLens::register_with_read_factory();
   PerspectiveLens::register_with_read_factory();
   SliderTable::register_with_read_factory();
   SliderTable::register_with_read_factory();
+  Shader::register_with_read_factory();
   Texture::register_with_read_factory();
   Texture::register_with_read_factory();
   TextureStage::register_with_read_factory();
   TextureStage::register_with_read_factory();
   TransformBlendTable::register_with_read_factory();
   TransformBlendTable::register_with_read_factory();

+ 2 - 0
panda/src/gobj/gobj_composite2.cxx

@@ -16,6 +16,8 @@
 #include "textureContext.cxx"
 #include "textureContext.cxx"
 #include "texturePool.cxx"
 #include "texturePool.cxx"
 #include "textureStage.cxx"
 #include "textureStage.cxx"
+#include "shader.cxx"
+#include "shaderContext.cxx"
 #include "transformBlend.cxx"
 #include "transformBlend.cxx"
 #include "transformBlendTable.cxx"
 #include "transformBlendTable.cxx"
 #include "transformTable.cxx"
 #include "transformTable.cxx"

+ 1 - 0
panda/src/gobj/preparedGraphicsObjects.I

@@ -26,6 +26,7 @@ INLINE void PreparedGraphicsObjects::
 release_all() {
 release_all() {
   release_all_textures();
   release_all_textures();
   release_all_geoms();
   release_all_geoms();
+  release_all_shaders();
   release_all_vertex_buffers();
   release_all_vertex_buffers();
   release_all_index_buffers();
   release_all_index_buffers();
 }
 }

+ 173 - 1
panda/src/gobj/preparedGraphicsObjects.cxx

@@ -24,6 +24,7 @@
 #include "geom.h"
 #include "geom.h"
 #include "geomVertexArrayData.h"
 #include "geomVertexArrayData.h"
 #include "geomPrimitive.h"
 #include "geomPrimitive.h"
+#include "shader.h"
 #include "mutexHolder.h"
 #include "mutexHolder.h"
 
 
 PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage");
 PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage");
@@ -77,6 +78,18 @@ PreparedGraphicsObjects::
   _released_geoms.clear();
   _released_geoms.clear();
   _enqueued_geoms.clear();
   _enqueued_geoms.clear();
 
 
+  Shaders::iterator sci;
+  for (sci = _prepared_shaders.begin();
+       sci != _prepared_shaders.end();
+       ++sci) {
+    ShaderContext *sc = (*sci);
+    sc->_shader->clear_prepared(this);
+  }
+
+  _prepared_shaders.clear();
+  _released_shaders.clear();
+  _enqueued_shaders.clear();
+
   VertexBuffers::iterator vbci;
   VertexBuffers::iterator vbci;
   for (vbci = _prepared_vertex_buffers.begin();
   for (vbci = _prepared_vertex_buffers.begin();
        vbci != _prepared_vertex_buffers.end();
        vbci != _prepared_vertex_buffers.end();
@@ -249,7 +262,6 @@ prepare_texture_now(Texture *tex, GraphicsStateGuardianBase *gsg) {
   return tc;
   return tc;
 }
 }
 
 
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PreparedGraphicsObjects::enqueue_geom
 //     Function: PreparedGraphicsObjects::enqueue_geom
 //       Access: Public
 //       Access: Public
@@ -390,6 +402,146 @@ prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg) {
   return gc;
   return gc;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PreparedGraphicsObjects::enqueue_shader
+//       Access: Public
+//  Description: Indicates that a shader would like to be put on the
+//               list to be prepared when the GSG is next ready to
+//               do this (presumably at the next frame).
+////////////////////////////////////////////////////////////////////
+void PreparedGraphicsObjects::
+enqueue_shader(Shader *shader) {
+  MutexHolder holder(_lock);
+
+  _enqueued_shaders.insert(shader);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PreparedGraphicsObjects::dequeue_shader
+//       Access: Public
+//  Description: Removes a shader from the queued list of shaders to
+//               be prepared.  Normally it is not necessary to call
+//               this, unless you change your mind about preparing it
+//               at the last minute, since the shader will
+//               automatically be dequeued and prepared at the next
+//               frame.
+//
+//               The return value is true if the shader is
+//               successfully dequeued, false if it had not been
+//               queued.
+////////////////////////////////////////////////////////////////////
+bool PreparedGraphicsObjects::
+dequeue_shader(Shader *shader) {
+  MutexHolder holder(_lock);
+
+  EnqueuedShaders::iterator qi = _enqueued_shaders.find(shader);
+  if (qi != _enqueued_shaders.end()) {
+    _enqueued_shaders.erase(qi);
+    return true;
+  }
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PreparedGraphicsObjects::release_shader
+//       Access: Public
+//  Description: Indicates that a shader context, created by a
+//               previous call to prepare_shader(), is no longer
+//               needed.  The driver resources will not be freed until
+//               some GSG calls update(), indicating it is at a
+//               stage where it is ready to release shaders--this
+//               prevents conflicts from threading or multiple GSG's
+//               sharing shaders (we have no way of knowing which
+//               graphics context is currently active, or what state
+//               it's in, at the time release_shader is called).
+////////////////////////////////////////////////////////////////////
+void PreparedGraphicsObjects::
+release_shader(ShaderContext *sc) {
+  MutexHolder holder(_lock);
+
+  sc->_shader->clear_prepared(this);
+
+  // We have to set the Shader pointer to NULL at this point, since
+  // the Shader itself might destruct at any time after it has been
+  // released.
+  sc->_shader = (Shader *)NULL;
+
+  bool removed = (_prepared_shaders.erase(sc) != 0);
+  nassertv(removed);
+
+  _released_shaders.insert(sc);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PreparedGraphicsObjects::release_all_shaders
+//       Access: Public
+//  Description: Releases all shaders at once.  This will force them
+//               to be reloaded into shader memory for all GSG's that
+//               share this object.  Returns the number of shaders
+//               released.
+////////////////////////////////////////////////////////////////////
+int PreparedGraphicsObjects::
+release_all_shaders() {
+  MutexHolder holder(_lock);
+
+  int num_shaders = (int)_prepared_shaders.size();
+
+  Shaders::iterator sci;
+  for (sci = _prepared_shaders.begin();
+       sci != _prepared_shaders.end();
+       ++sci) {
+    ShaderContext *sc = (*sci);
+    sc->_shader->clear_prepared(this);
+    sc->_shader = (Shader *)NULL;
+
+    _released_shaders.insert(sc);
+  }
+
+  _prepared_shaders.clear();
+
+  return num_shaders;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PreparedGraphicsObjects::prepare_shader_now
+//       Access: Public
+//  Description: Immediately creates a new ShaderContext for the
+//               indicated shader and returns it.  This assumes that
+//               the GraphicsStateGuardian is the currently active
+//               rendering context and that it is ready to accept new
+//               shaders.  If this is not necessarily the case, you
+//               should use enqueue_shader() instead.
+//
+//               Normally, this function is not called directly.  Call
+//               Shader::prepare_now() instead.
+//
+//               The ShaderContext contains all of the pertinent
+//               information needed by the GSG to keep track of this
+//               one particular shader, and will exist as long as the
+//               shader is ready to be rendered.
+//
+//               When either the Shader or the
+//               PreparedGraphicsObjects object destructs, the
+//               ShaderContext will be deleted.
+////////////////////////////////////////////////////////////////////
+ShaderContext *PreparedGraphicsObjects::
+prepare_shader_now(Shader *shader, GraphicsStateGuardianBase *gsg) {
+  MutexHolder holder(_lock);
+
+  // Ask the GSG to create a brand new ShaderContext.  There might
+  // be several GSG's sharing the same set of shaders; if so, it
+  // doesn't matter which of them creates the context (since they're
+  // all shared anyway).
+  ShaderContext *sc = gsg->prepare_shader(shader);
+
+  if (sc != (ShaderContext *)NULL) {
+    bool prepared = _prepared_shaders.insert(sc).second;
+    nassertr(prepared, sc);
+  }
+
+  return sc;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PreparedGraphicsObjects::enqueue_vertex_buffer
 //     Function: PreparedGraphicsObjects::enqueue_vertex_buffer
 //       Access: Public
 //       Access: Public
@@ -722,6 +874,16 @@ update(GraphicsStateGuardianBase *gsg) {
 
 
   _released_geoms.clear();
   _released_geoms.clear();
 
 
+  Shaders::iterator sci;
+  for (sci = _released_shaders.begin();
+       sci != _released_shaders.end();
+       ++sci) {
+    ShaderContext *sc = (*sci);
+    gsg->release_shader(sc);
+  }
+
+  _released_shaders.clear();
+
   VertexBuffers::iterator vbci;
   VertexBuffers::iterator vbci;
   for (vbci = _released_vertex_buffers.begin();
   for (vbci = _released_vertex_buffers.begin();
        vbci != _released_vertex_buffers.end();
        vbci != _released_vertex_buffers.end();
@@ -764,6 +926,16 @@ update(GraphicsStateGuardianBase *gsg) {
 
 
   _enqueued_geoms.clear();
   _enqueued_geoms.clear();
 
 
+  EnqueuedShaders::iterator qsi;
+  for (qsi = _enqueued_shaders.begin();
+       qsi != _enqueued_shaders.end();
+       ++qsi) {
+    Shader *shader = (*qsi);
+    shader->prepare_now(this, gsg);
+  }
+
+  _enqueued_shaders.clear();
+
   EnqueuedVertexBuffers::iterator qvbi;
   EnqueuedVertexBuffers::iterator qvbi;
   for (qvbi = _enqueued_vertex_buffers.begin();
   for (qvbi = _enqueued_vertex_buffers.begin();
        qvbi != _enqueued_vertex_buffers.end();
        qvbi != _enqueued_vertex_buffers.end();

+ 13 - 0
panda/src/gobj/preparedGraphicsObjects.h

@@ -25,6 +25,7 @@
 #include "geom.h"
 #include "geom.h"
 #include "geomVertexArrayData.h"
 #include "geomVertexArrayData.h"
 #include "geomPrimitive.h"
 #include "geomPrimitive.h"
+#include "shader.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "pStatCollector.h"
 #include "pStatCollector.h"
 #include "pset.h"
 #include "pset.h"
@@ -32,6 +33,7 @@
 
 
 class TextureContext;
 class TextureContext;
 class GeomContext;
 class GeomContext;
+class ShaderContext;
 class VertexBufferContext;
 class VertexBufferContext;
 class IndexBufferContext;
 class IndexBufferContext;
 class GraphicsStateGuardianBase;
 class GraphicsStateGuardianBase;
@@ -76,6 +78,13 @@ public:
 
 
   GeomContext *prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg);
   GeomContext *prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg);
 
 
+  void enqueue_shader(Shader *shader);
+  bool dequeue_shader(Shader *shader);
+  void release_shader(ShaderContext *sc);
+  int release_all_shaders();
+
+  ShaderContext *prepare_shader_now(Shader *shader, GraphicsStateGuardianBase *gsg);
+
   void enqueue_vertex_buffer(GeomVertexArrayData *data);
   void enqueue_vertex_buffer(GeomVertexArrayData *data);
   bool dequeue_vertex_buffer(GeomVertexArrayData *data);
   bool dequeue_vertex_buffer(GeomVertexArrayData *data);
   void release_vertex_buffer(VertexBufferContext *vbc);
   void release_vertex_buffer(VertexBufferContext *vbc);
@@ -101,6 +110,8 @@ private:
   typedef phash_set< PT(Texture) > EnqueuedTextures;
   typedef phash_set< PT(Texture) > EnqueuedTextures;
   typedef phash_set<GeomContext *, pointer_hash> Geoms;
   typedef phash_set<GeomContext *, pointer_hash> Geoms;
   typedef phash_set< PT(Geom) > EnqueuedGeoms;
   typedef phash_set< PT(Geom) > EnqueuedGeoms;
+  typedef phash_set<ShaderContext *, pointer_hash> Shaders;
+  typedef phash_set< PT(Shader) > EnqueuedShaders;
   typedef phash_set<VertexBufferContext *, pointer_hash> VertexBuffers;
   typedef phash_set<VertexBufferContext *, pointer_hash> VertexBuffers;
   typedef phash_set< PT(GeomVertexArrayData) > EnqueuedVertexBuffers;
   typedef phash_set< PT(GeomVertexArrayData) > EnqueuedVertexBuffers;
   typedef phash_set<IndexBufferContext *, pointer_hash> IndexBuffers;
   typedef phash_set<IndexBufferContext *, pointer_hash> IndexBuffers;
@@ -111,6 +122,8 @@ private:
   EnqueuedTextures _enqueued_textures;
   EnqueuedTextures _enqueued_textures;
   Geoms _prepared_geoms, _released_geoms;  
   Geoms _prepared_geoms, _released_geoms;  
   EnqueuedGeoms _enqueued_geoms;
   EnqueuedGeoms _enqueued_geoms;
+  Shaders _prepared_shaders, _released_shaders;
+  EnqueuedShaders _enqueued_shaders;
   VertexBuffers _prepared_vertex_buffers, _released_vertex_buffers;  
   VertexBuffers _prepared_vertex_buffers, _released_vertex_buffers;  
   EnqueuedVertexBuffers _enqueued_vertex_buffers;
   EnqueuedVertexBuffers _enqueued_vertex_buffers;
   IndexBuffers _prepared_index_buffers, _released_index_buffers;  
   IndexBuffers _prepared_index_buffers, _released_index_buffers;  

+ 38 - 0
panda/src/gobj/shader.I

@@ -0,0 +1,38 @@
+// Filename: shader.I
+// Heavily Modified:  jyelon (Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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: Shader::get_text
+//  Access: Public
+//  Description: Return the shader's text.
+////////////////////////////////////////////////////////////////////
+INLINE const string &Shader::
+get_text(void) {
+  return _text;
+}
+
+////////////////////////////////////////////////////////////////////
+//  Function: Shader::get_file
+//  Access: Public
+//  Description: Return the shader's filename, or null string.
+////////////////////////////////////////////////////////////////////
+INLINE const Filename &Shader::
+get_file(void) {
+  return _file;
+}
+

+ 196 - 0
panda/src/gobj/shader.cxx

@@ -0,0 +1,196 @@
+// Filename: shader.cxx
+// Created by: jyelon (Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pandabase.h"
+#include "shader.h"
+
+TypeHandle Shader::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//  Function: Shader::Constructor
+//  Access: Public
+//  Description: Construct a Shader.
+////////////////////////////////////////////////////////////////////
+Shader::
+Shader(const string &text, const string &file) {
+  _text = text;
+  _file = file;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::Destructor
+//       Access: Public
+//  Description: Delete the compiled code, if it exists.
+////////////////////////////////////////////////////////////////////
+Shader::
+~Shader() {
+  release_all();
+}
+
+////////////////////////////////////////////////////////////////////
+//  Function: Shader::arg_index
+//  Access: Public
+//  Description: Allocates an integer index to the given
+//               shader parameter name.
+////////////////////////////////////////////////////////////////////
+INLINE int Shader::
+arg_index(const string &id) {
+  for (int i=0; i<(int)(_args.size()); i++)
+    if (_args[i] == id)
+      return i;
+  _args.push_back(id);
+  return _args.size() - 1;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::prepare
+//       Access: Published
+//  Description: Indicates that the shader should be enqueued to be
+//               prepared in the indicated prepared_objects at the
+//               beginning of the next frame.  This will ensure the
+//               texture is already loaded into texture memory if it
+//               is expected to be rendered soon.
+//
+//               Use this function instead of prepare_now() to preload
+//               textures from a user interface standpoint.
+////////////////////////////////////////////////////////////////////
+void Shader::
+prepare(PreparedGraphicsObjects *prepared_objects) {
+  prepared_objects->enqueue_shader(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::release
+//       Access: Published
+//  Description: Frees the texture context only on the indicated object,
+//               if it exists there.  Returns true if it was released,
+//               false if it had not been prepared.
+////////////////////////////////////////////////////////////////////
+bool Shader::
+release(PreparedGraphicsObjects *prepared_objects) {
+  Contexts::iterator ci;
+  ci = _contexts.find(prepared_objects);
+  if (ci != _contexts.end()) {
+    ShaderContext *sc = (*ci).second;
+    if (sc != (ShaderContext *)NULL) {
+      prepared_objects->release_shader(sc);
+    } else {
+      _contexts.erase(ci);
+    }
+    return true;
+  }
+
+  // Maybe it wasn't prepared yet, but it's about to be.
+  return prepared_objects->dequeue_shader(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::prepare_now
+//       Access: Public
+//  Description: Creates a context for the texture on the particular
+//               GSG, if it does not already exist.  Returns the new
+//               (or old) ShaderContext.  This assumes that the
+//               GraphicsStateGuardian is the currently active
+//               rendering context and that it is ready to accept new
+//               textures.  If this is not necessarily the case, you
+//               should use prepare() instead.
+//
+//               Normally, this is not called directly except by the
+//               GraphicsStateGuardian; a texture does not need to be
+//               explicitly prepared by the user before it may be
+//               rendered.
+////////////////////////////////////////////////////////////////////
+ShaderContext *Shader::
+prepare_now(PreparedGraphicsObjects *prepared_objects, 
+            GraphicsStateGuardianBase *gsg) {
+  Contexts::const_iterator ci;
+  ci = _contexts.find(prepared_objects);
+  if (ci != _contexts.end()) {
+    return (*ci).second;
+  }
+
+  ShaderContext *tc = prepared_objects->prepare_shader_now(this, gsg);
+  _contexts[prepared_objects] = tc;
+
+  return tc;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::clear_prepared
+//       Access: Private
+//  Description: Removes the indicated PreparedGraphicsObjects table
+//               from the Shader's table, without actually releasing
+//               the texture.  This is intended to be called only from
+//               PreparedGraphicsObjects::release_texture(); it should
+//               never be called by user code.
+////////////////////////////////////////////////////////////////////
+void Shader::
+clear_prepared(PreparedGraphicsObjects *prepared_objects) {
+  Contexts::iterator ci;
+  ci = _contexts.find(prepared_objects);
+  if (ci != _contexts.end()) {
+    _contexts.erase(ci);
+  } else {
+    // If this assertion fails, clear_prepared() was given a
+    // prepared_objects which the texture didn't know about.
+    nassertv(false);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::release_all
+//       Access: Published
+//  Description: Frees the context allocated on all objects for which
+//               the texture has been declared.  Returns the number of
+//               contexts which have been freed.
+////////////////////////////////////////////////////////////////////
+int Shader::
+release_all() {
+  // We have to traverse a copy of the _contexts list, because the
+  // PreparedGraphicsObjects object will call clear_prepared() in response
+  // to each release_texture(), and we don't want to be modifying the
+  // _contexts list while we're traversing it.
+  Contexts temp = _contexts;
+  int num_freed = (int)_contexts.size();
+
+  Contexts::const_iterator ci;
+  for (ci = temp.begin(); ci != temp.end(); ++ci) {
+    PreparedGraphicsObjects *prepared_objects = (*ci).first;
+    ShaderContext *sc = (*ci).second;
+    if (sc != (ShaderContext *)NULL) {
+      prepared_objects->release_shader(sc);
+    }
+  }
+  
+  // There might still be some outstanding contexts in the map, if
+  // there were any NULL pointers there.  Eliminate them.
+  _contexts.clear();
+
+  return num_freed;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::register_with_read_factory
+//       Access: Public, Static
+//  Description: Factory method to generate a Shader object
+////////////////////////////////////////////////////////////////////
+void Shader::
+register_with_read_factory() {
+  // IMPLEMENT ME
+}
+

+ 105 - 0
panda/src/gobj/shader.h

@@ -0,0 +1,105 @@
+// Filename: shader.h
+// Created by:  jyelon (01Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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] .
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//
+// Current Loose Ends:
+//   - BAM reading/writing not implemented on most classes.
+//   - ShaderPool not implemented.
+//   - compilation of shaders for OpenGL not implemented.
+//   - compilation of shaders for DirectX8 not implemented.
+//   - compilation of shaders for DirectX9 not implemented.
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef SHADER_H
+#define SHADER_H
+
+#include "pandabase.h"
+#include "typedWritableReferenceCount.h"
+#include "internalName.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Shader
+//      Summary: The Shader object contains the string which 
+//               is the shader's text, a filename that indicates
+//               where the shader came from (optional), and an
+//               argument-name to argument-index allocator.  The
+//               allocator is there so that all the Shader and
+//               ShaderContext objects associated with this Shader
+//               can refer to arguments by index instead of by name,
+//               which could make the bind process significantly
+//               faster.
+////////////////////////////////////////////////////////////////////
+
+class EXPCL_PANDA Shader: public TypedWritableReferenceCount {
+
+PUBLISHED:
+  Shader(const string &text, const string &file);
+  ~Shader(void);
+
+  INLINE const string   &get_text(void);
+  INLINE const Filename &get_file(void);
+
+  void prepare(PreparedGraphicsObjects *prepared_objects);
+  bool release(PreparedGraphicsObjects *prepared_objects);
+  int release_all();
+
+public:
+  INLINE int arg_count(void);
+  int        arg_index(const string &id);
+
+  string         _text;
+  Filename       _file;
+  vector<string> _args;
+  
+  typedef pmap<PreparedGraphicsObjects *, ShaderContext *> Contexts;
+  Contexts _contexts;
+
+  static void register_with_read_factory(void);
+
+  friend class ShaderContext;
+  friend class PreparedGraphicsObjects;
+
+  ShaderContext *prepare_now(PreparedGraphicsObjects *prepared_objects, 
+                             GraphicsStateGuardianBase *gsg);
+
+private:  
+  void clear_prepared(PreparedGraphicsObjects *prepared_objects);
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    TypedWritableReferenceCount::init_type();
+    register_type(_type_handle, "Shader",
+                  TypedWritableReferenceCount::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "shader.I"
+
+#endif

+ 30 - 0
panda/src/gobj/shaderContext.I

@@ -0,0 +1,30 @@
+// Filename: shaderContext.I
+// Created by: jyelon (01Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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: ShaderContext::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE ShaderContext::
+ShaderContext(Shader *s) :
+  _shader(s)
+{
+}
+
+

+ 20 - 0
panda/src/gobj/shaderContext.cxx

@@ -0,0 +1,20 @@
+// Filename: shaderContext.cxx
+// Created by: jyelon (01Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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] .
+//
+////////////////////////////////////////////////////////////////////
+
+TypeHandle ShaderContext::_type_handle;
+

+ 65 - 0
panda/src/gobj/shaderContext.h

@@ -0,0 +1,65 @@
+// Filename: shaderContext.h
+// Created by: jyelon (01Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef SHADERCONTEXT_H
+#define SHADERCONTEXT_H
+
+#include "pandabase.h"
+#include "internalName.h"
+#include "savedContext.h"
+#include "shader.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : ShaderContext
+// Description : The ShaderContext is meant to contain the compiled
+//               version of a shader string.  ShaderContext is an
+//               abstract base class, there will be a subclass of it
+//               for each shader language and graphics API.
+//               Since the languages are so different and the
+//               graphics APIs have so little in common, the base
+//               class contains almost nothing.  All the implementation
+//               details are in the subclasses.
+////////////////////////////////////////////////////////////////////
+
+class EXPCL_PANDA ShaderContext: public SavedContext {
+public:
+  INLINE ShaderContext(Shader *shader);
+  
+  Shader *_shader;
+  
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    TypedObject::init_type();
+    register_type(_type_handle, "ShaderContext",
+                  TypedObject::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "shaderContext.I"
+
+#endif