Jelajahi Sumber

shaderpipeline: Start stubbing things out

  * Add base class for ShaderCompiler and ShaderModule
  * Stub out ShaderCompilerGlslPreProc and ShaderModuleGlsl
  * Implement a ShaderCompilerRegistry
Mitchell Stokes 6 tahun lalu
induk
melakukan
2b8e0e2c68

+ 16 - 0
makepanda/makepanda.py

@@ -3266,6 +3266,7 @@ CopyAllHeaders('panda/src/movies')
 CopyAllHeaders('panda/src/pgraphnodes')
 CopyAllHeaders('panda/src/pgraphnodes')
 CopyAllHeaders('panda/src/pgraph')
 CopyAllHeaders('panda/src/pgraph')
 CopyAllHeaders('panda/src/cull')
 CopyAllHeaders('panda/src/cull')
+CopyAllHeaders('panda/src/shaderpipeline')
 CopyAllHeaders('panda/src/display')
 CopyAllHeaders('panda/src/display')
 CopyAllHeaders('panda/src/chan')
 CopyAllHeaders('panda/src/chan')
 CopyAllHeaders('panda/src/char')
 CopyAllHeaders('panda/src/char')
@@ -4000,6 +4001,18 @@ if (not RUNTIME):
     OPTS=['DIR:panda/src/display']
     OPTS=['DIR:panda/src/display']
     TargetAdd('subprocessWindowBuffer.obj', opts=OPTS, input='subprocessWindowBuffer.cxx')
     TargetAdd('subprocessWindowBuffer.obj', opts=OPTS, input='subprocessWindowBuffer.cxx')
     TargetAdd('libp3subprocbuffer.ilb', input='subprocessWindowBuffer.obj')
     TargetAdd('libp3subprocbuffer.ilb', input='subprocessWindowBuffer.obj')
+#
+# DIRECTORY: panda/src/shaderpipeline/
+#
+
+if (not RUNTIME):
+  OPTS=['DIR:panda/src/shaderpipeline', 'BUILDING:PANDA']
+  TargetAdd('p3shaderpipeline_composite1.obj', opts=OPTS, input='p3shaderpipeline_composite1.cxx')
+
+  OPTS=['DIR:panda/src/shaderpipeline']
+  IGATEFILES=GetDirectoryContents('panda/src/shaderpipeline', ["*.h", "*_composite*.cxx"])
+  TargetAdd('libp3shaderpipeline.in', opts=OPTS, input=IGATEFILES)
+  TargetAdd('libp3shaderpipeline.in', opts=['IMOD:panda3d.core', 'ILIB:libp3shaderpipeline', 'SRCDIR:panda/src/shaderpipeline'])
 
 
 #
 #
 # DIRECTORY: panda/src/chan/
 # DIRECTORY: panda/src/chan/
@@ -4212,6 +4225,7 @@ if (not RUNTIME):
   TargetAdd('libpanda.dll', input='p3pgraph_composite4.obj')
   TargetAdd('libpanda.dll', input='p3pgraph_composite4.obj')
   TargetAdd('libpanda.dll', input='p3cull_composite1.obj')
   TargetAdd('libpanda.dll', input='p3cull_composite1.obj')
   TargetAdd('libpanda.dll', input='p3cull_composite2.obj')
   TargetAdd('libpanda.dll', input='p3cull_composite2.obj')
+  TargetAdd('libpanda.dll', input='p3shaderpipeline_composite1.obj')
   TargetAdd('libpanda.dll', input='p3movies_composite1.obj')
   TargetAdd('libpanda.dll', input='p3movies_composite1.obj')
   TargetAdd('libpanda.dll', input='p3grutil_multitexReducer.obj')
   TargetAdd('libpanda.dll', input='p3grutil_multitexReducer.obj')
   TargetAdd('libpanda.dll', input='p3grutil_composite1.obj')
   TargetAdd('libpanda.dll', input='p3grutil_composite1.obj')
@@ -4285,6 +4299,7 @@ if (not RUNTIME):
   PyTargetAdd('core_module.obj', input='libp3pgraphnodes.in')
   PyTargetAdd('core_module.obj', input='libp3pgraphnodes.in')
   PyTargetAdd('core_module.obj', input='libp3pgraph.in')
   PyTargetAdd('core_module.obj', input='libp3pgraph.in')
   PyTargetAdd('core_module.obj', input='libp3cull.in')
   PyTargetAdd('core_module.obj', input='libp3cull.in')
+  PyTargetAdd('core_module.obj', input='libp3shaderpipeline.in')
   PyTargetAdd('core_module.obj', input='libp3grutil.in')
   PyTargetAdd('core_module.obj', input='libp3grutil.in')
   PyTargetAdd('core_module.obj', input='libp3chan.in')
   PyTargetAdd('core_module.obj', input='libp3chan.in')
   PyTargetAdd('core_module.obj', input='libp3pstatclient.in')
   PyTargetAdd('core_module.obj', input='libp3pstatclient.in')
@@ -4343,6 +4358,7 @@ if (not RUNTIME):
   PyTargetAdd('core.pyd', input='libp3pipeline_igate.obj')
   PyTargetAdd('core.pyd', input='libp3pipeline_igate.obj')
   PyTargetAdd('core.pyd', input='libp3event_igate.obj')
   PyTargetAdd('core.pyd', input='libp3event_igate.obj')
   PyTargetAdd('core.pyd', input='libp3gobj_igate.obj')
   PyTargetAdd('core.pyd', input='libp3gobj_igate.obj')
+  PyTargetAdd('core.pyd', input='libp3shaderpipeline_igate.obj')
   PyTargetAdd('core.pyd', input='libp3gsgbase_igate.obj')
   PyTargetAdd('core.pyd', input='libp3gsgbase_igate.obj')
   PyTargetAdd('core.pyd', input='libp3linmath_igate.obj')
   PyTargetAdd('core.pyd', input='libp3linmath_igate.obj')
   PyTargetAdd('core.pyd', input='libp3mathutil_igate.obj')
   PyTargetAdd('core.pyd', input='libp3mathutil_igate.obj')

+ 9 - 0
panda/src/pandabase/pandasymbols.h

@@ -103,6 +103,7 @@
   #define BUILDING_PANDA_RECORDER
   #define BUILDING_PANDA_RECORDER
   #define BUILDING_PANDA_TEXT
   #define BUILDING_PANDA_TEXT
   #define BUILDING_PANDA_TFORM
   #define BUILDING_PANDA_TFORM
+  #define BUILDING_PANDA_SHADERPIPELINE
 #endif
 #endif
 
 
 /* BUILDING_PANDAEGG for these: */
 /* BUILDING_PANDAEGG for these: */
@@ -443,6 +444,14 @@
   #define EXPTP_PANDA_RECORDER IMPORT_TEMPL
   #define EXPTP_PANDA_RECORDER IMPORT_TEMPL
 #endif
 #endif
 
 
+#ifdef BUILDING_PANDA_SHADERPIPELINE
+  #define EXPCL_PANDA_SHADERPIPELINE EXPORT_CLASS
+  #define EXPTP_PANDA_SHADERPIPELINE EXPORT_TEMPL
+#else
+  #define EXPCL_PANDA_SHADERPIPELINE IMPORT_CLASS
+  #define EXPTP_PANDA_SHADERPIPELINE IMPORT_TEMPL
+#endif
+
 #ifdef BUILDING_PANDA_TEXT
 #ifdef BUILDING_PANDA_TEXT
   #define EXPCL_PANDA_TEXT EXPORT_CLASS
   #define EXPCL_PANDA_TEXT EXPORT_CLASS
   #define EXPTP_PANDA_TEXT EXPORT_TEMPL
   #define EXPTP_PANDA_TEXT EXPORT_TEMPL

+ 45 - 0
panda/src/shaderpipeline/config_shaderpipeline.cxx

@@ -0,0 +1,45 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file config_shaderpipeline.cxx
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#include "config_shaderpipeline.h"
+
+#include "shaderCompilerRegistry.h"
+#include "shaderCompilerGlslPreProc.h"
+
+#include "dconfig.h"
+
+
+ConfigureDef(config_shaderpipeline);
+NotifyCategoryDef(shaderpipeline, "");
+
+ConfigureFn(config_shaderpipeline) {
+  init_libshaderpipeline();
+}
+
+/**
+ * Initializes the library.  This must be called at least once before any of
+ * the functions or classes in this library can be used.  Normally it will be
+ * called by the static initializers and need not be called explicitly, but
+ * special cases exist.
+ */
+void
+init_libshaderpipeline() {
+  static bool initialized = false;
+  if (initialized) {
+    return;
+  }
+  initialized = true;
+
+  ShaderCompilerRegistry *reg = ShaderCompilerRegistry::get_global_ptr();
+  reg->register_compiler(new ShaderCompilerGlslPreProc());
+}

+ 26 - 0
panda/src/shaderpipeline/config_shaderpipeline.h

@@ -0,0 +1,26 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file config_shaderpipeline.h
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#ifndef CONFIG_SHADERPIPELINE_H
+#define CONFIG_SHADERPIPELINE_H
+
+#include "pandabase.h"
+#include "notifyCategoryProxy.h"
+#include "dconfig.h"
+
+ConfigureDecl(config_shaderpipeline, EXPCL_PANDA_SHADERPIPELINE, EXPTP_PANDA_SHADERPIPELINE);
+NotifyCategoryDecl(shaderpipeline, EXPCL_PANDA_SHADERPIPELINE, EXPTP_PANDA_SHADERPIPELINE);
+
+extern EXPCL_PANDA_PGRAPH void init_libshaderpipeline();
+
+#endif

+ 6 - 0
panda/src/shaderpipeline/p3shaderpipeline_composite1.cxx

@@ -0,0 +1,6 @@
+#include "config_shaderpipeline.cxx"
+#include "shaderModule.cxx"
+#include "shaderModuleGlsl.cxx"
+#include "shaderCompiler.cxx"
+#include "shaderCompilerGlslPreProc.cxx"
+#include "shaderCompilerRegistry.cxx"

+ 31 - 0
panda/src/shaderpipeline/shaderCompiler.cxx

@@ -0,0 +1,31 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderCompiler.cxx
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#include "shaderCompiler.h"
+
+
+TypeHandle ShaderCompiler::_type_handle;
+
+/**
+ *
+ */
+ShaderCompiler::
+ShaderCompiler() {
+}
+
+/**
+ *
+ */
+ShaderCompiler::
+~ShaderCompiler() {
+}

+ 59 - 0
panda/src/shaderpipeline/shaderCompiler.h

@@ -0,0 +1,59 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderCompiler.h
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#ifndef SHADERCOMPILER_H
+#define SHADERCOMPILER_H
+
+#include "pandabase.h"
+
+#include "pvector.h"
+#include "typedObject.h"
+#include "shader.h"
+#include "shaderModule.h"
+
+typedef pvector<Shader::Shader::ShaderLanguage> ShaderLanguages;
+
+/**
+ * This is the base class for objects to compile various types of shader code.
+ */
+class EXPCL_PANDA_SHADERPIPELINE ShaderCompiler : public TypedObject {
+protected:
+  ShaderCompiler();
+
+public:
+  virtual ~ShaderCompiler();
+
+PUBLISHED:
+  virtual std::string get_name() const=0;
+  virtual ShaderLanguages get_languages() const=0;
+  virtual PT(ShaderModule) compile_now(Shader::ShaderType shader_type, std::string source) const=0;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    TypedObject::init_type();
+    register_type(_type_handle, "ShaderCompiler",
+                  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;
+};
+
+#endif

+ 50 - 0
panda/src/shaderpipeline/shaderCompilerGlslPreProc.cxx

@@ -0,0 +1,50 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderCompilerGlslPreProc.cxx
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#include "shaderCompilerGlslPreProc.h"
+#include "shaderModuleGlsl.h"
+#include "config_shaderpipeline.h"
+
+#include "dcast.h"
+
+TypeHandle ShaderCompilerGlslPreProc::_type_handle;
+
+/**
+ *
+ */
+ShaderCompilerGlslPreProc::
+ShaderCompilerGlslPreProc() {
+}
+
+/**
+ *
+ */
+std::string ShaderCompilerGlslPreProc::
+get_name() const {
+  return "GLSL Pre-Processing Compiler";
+}
+
+/**
+ *
+ */
+ShaderLanguages ShaderCompilerGlslPreProc::
+get_languages() const {
+  return {
+    Shader::SL_GLSL
+  };
+}
+
+PT(ShaderModule) ShaderCompilerGlslPreProc::
+compile_now(Shader::ShaderType shader_type, std::string source) const {
+  return new ShaderModuleGlsl(shader_type, source);
+}

+ 51 - 0
panda/src/shaderpipeline/shaderCompilerGlslPreProc.h

@@ -0,0 +1,51 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderCompilerGlslPreProc.h
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#ifndef SHADERCOMPILERGLSLPREPROC_H
+#define SHADERCOMPILERGLSLPREPROC_H
+
+#include "pandabase.h"
+
+#include "shaderCompiler.h"
+
+/**
+ * This defines the compiler interface to read GLSL files and pre-process them
+ */
+class EXPCL_PANDA_SHADERPIPELINE ShaderCompilerGlslPreProc : public ShaderCompiler {
+public:
+  ShaderCompilerGlslPreProc();
+
+PUBLISHED:
+  virtual std::string get_name() const;
+  virtual ShaderLanguages get_languages() const;
+  virtual PT(ShaderModule) compile_now(Shader::ShaderType shader_type, std::string source) const;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    ShaderCompiler::init_type();
+    register_type(_type_handle, "ShaderCompilerGlslPreProc",
+                  ShaderCompiler::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;
+};
+
+#endif

+ 244 - 0
panda/src/shaderpipeline/shaderCompilerRegistry.cxx

@@ -0,0 +1,244 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderCompilerRegistry.cxx
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#include "shaderCompilerRegistry.h"
+#include "shaderCompiler.h"
+#include "config_shaderpipeline.h"
+#include "config_putil.h"
+
+#include "load_dso.h"
+#include "string_utils.h"
+#include "indent.h"
+
+#include <algorithm>
+
+using std::string;
+
+ShaderCompilerRegistry *ShaderCompilerRegistry::_global_ptr;
+
+/**
+ *
+ */
+ShaderCompilerRegistry::
+ShaderCompilerRegistry() {
+}
+
+/**
+ *
+ */
+ShaderCompilerRegistry::
+~ShaderCompilerRegistry() {
+}
+
+/**
+ * Defines a new ShaderCompiler in the universe.
+ */
+void ShaderCompilerRegistry::
+register_compiler(ShaderCompiler *compiler) {
+  // Make sure we haven't already registered this compiler.
+  if (find(_compilers.begin(), _compilers.end(), compiler) != _compilers.end()) {
+    if (shaderpipeline_cat->is_debug()) {
+      shaderpipeline_cat->debug()
+        << "Attempt to register ShaderCompiler " << compiler->get_name()
+        << " (" << compiler->get_type() << ") more than once.\n";
+    }
+    return;
+  }
+
+  _compilers.push_back(compiler);
+
+  ShaderLanguages langs = compiler->get_languages();
+  for (auto langit = langs.begin(); langit != langs.end(); ++langit) {
+    record_language(*langit, compiler);
+  }
+}
+
+/**
+ * Records a compiler associated with a particular language to be loaded in the
+ * future.  The named library will be dynamically loaded the first time files
+ * of this language are loaded; presumably this library will call
+ * register_compiler() when it initializes, thus making the language loadable.
+ */
+void ShaderCompilerRegistry::
+register_deferred_compiler(Shader::ShaderLanguage language, const string &library) {
+  Languages::const_iterator li;
+  li = _languages.find(language);
+  if (li != _languages.end()) {
+    // We already have a loader for this compiler; no need to register another
+    // one.
+    if (shaderpipeline_cat->is_debug()) {
+      shaderpipeline_cat->debug()
+        << "Attempt to register loader library " << library
+        << " (" << language << ") when language is already known.\n";
+    }
+    return;
+  }
+
+  DeferredCompilers::const_iterator di;
+  di = _deferred_compilers.find(language);
+  if (di != _deferred_compilers.end()) {
+    if ((*di).second == library) {
+      if (shaderpipeline_cat->is_debug()) {
+        shaderpipeline_cat->debug()
+          << "Attempt to register loader library " << library
+          << " (" << language << ") more than once.\n";
+      }
+      return;
+    } else {
+      if (shaderpipeline_cat->is_debug()) {
+        shaderpipeline_cat->debug()
+          << "Multiple libraries registered that use the language "
+          << language << "\n";
+      }
+    }
+  }
+
+  _deferred_compilers[language] = library;
+}
+
+/**
+ * Returns the total number of compilers registered.
+ */
+int ShaderCompilerRegistry::
+get_num_compilers() const {
+  return _compilers.size();
+}
+
+/**
+ * Returns the nth compiler registered.
+ */
+ShaderCompiler *ShaderCompilerRegistry::
+get_compiler(int n) const {
+  nassertr(n >= 0 && n < (int)_compilers.size(), nullptr);
+  return _compilers[n];
+}
+
+/**
+ * Determines the compiler of the file based on the indicated language (without a
+ * leading dot).  Returns NULL if the language matches no known file compilers.
+ */
+ShaderCompiler *ShaderCompilerRegistry::
+get_compiler_from_language(Shader::ShaderLanguage language) {
+  Languages::const_iterator li;
+  li = _languages.find(language);
+  if (li == _languages.end()) {
+    // Nothing matches that language.  Do we have a deferred compiler?
+
+    DeferredCompilers::iterator di;
+    di = _deferred_compilers.find(language);
+    if (di != _deferred_compilers.end()) {
+      // We do!  Try to load the deferred library on-the-fly.  Note that this
+      // is a race condition if we support threaded loading; this whole
+      // function needs to be protected from multiple entry.
+      string name = (*di).second;
+      Filename dlname = Filename::dso_filename("lib" + name + ".so");
+      _deferred_compilers.erase(di);
+
+      shaderpipeline_cat->info()
+        << "loading file compiler module: " << name << std::endl;
+      void *tmp = load_dso(get_plugin_path().get_value(), dlname);
+      if (tmp == nullptr) {
+        shaderpipeline_cat->warning()
+          << "Unable to load " << dlname.to_os_specific() << ": "
+          << load_dso_error() << std::endl;
+        return nullptr;
+      } else if (shaderpipeline_cat.is_debug()) {
+        shaderpipeline_cat.debug()
+          << "done loading file compiler module: " << name << std::endl;
+      }
+
+      // Now try again to find the ShaderCompiler.
+      li = _languages.find(language);
+    }
+  }
+
+  if (li == _languages.end()) {
+    // Nothing matches that language, even after we've checked for a deferred
+    // compiler description.
+    return nullptr;
+  }
+
+  return (*li).second;
+}
+
+/**
+ * Writes a list of supported file compilers to the indicated output stream, one
+ * per line.
+ */
+void ShaderCompilerRegistry::
+write(std::ostream &out, int indent_level) const {
+  if (_compilers.empty()) {
+    indent(out, indent_level) << "(No file compilers are known).\n";
+  } else {
+    Compilers::const_iterator ti;
+    for (ti = _compilers.begin(); ti != _compilers.end(); ++ti) {
+      ShaderCompiler *compiler = (*ti);
+      string name = compiler->get_name();
+      indent(out, indent_level) << name;
+      indent(out, std::max(30 - (int)name.length(), 0)) << " ";
+
+      bool comma = false;
+      ShaderLanguages langs = compiler->get_languages();
+      for (auto li = langs.begin(); li != langs.end(); ++li) {
+        if (comma) {
+          out << ",";
+        } else {
+          comma = true;
+        }
+        out << " ." << *li;
+      }
+      out << "\n";
+    }
+  }
+
+  if (!_deferred_compilers.empty()) {
+    indent(out, indent_level) << "Also available:";
+    DeferredCompilers::const_iterator di;
+    for (di = _deferred_compilers.begin(); di != _deferred_compilers.end(); ++di) {
+        Shader::ShaderLanguage language = (*di).first;
+      out << " ." << language;
+    }
+    out << "\n";
+  }
+}
+
+/**
+ * Returns a pointer to the global ShaderCompilerRegistry object.
+ */
+ShaderCompilerRegistry *ShaderCompilerRegistry::
+get_global_ptr() {
+  if (_global_ptr == nullptr) {
+    _global_ptr = new ShaderCompilerRegistry;
+  }
+  return _global_ptr;
+}
+
+/**
+ * Records a Shader::ShaderLanguage recognized by a shader compiler.
+ */
+void ShaderCompilerRegistry::
+record_language(Shader::ShaderLanguage language, ShaderCompiler *compiler) {
+  Languages::const_iterator li;
+  li = _languages.find(language);
+  if (li != _languages.end()) {
+    if (shaderpipeline_cat->is_debug()) {
+      shaderpipeline_cat->debug()
+        << "Multiple ShaderCompilers registered that use the language "
+        << language << "\n";
+    }
+  } else {
+    _languages.insert(Languages::value_type(language, compiler));
+  }
+
+  _deferred_compilers.erase(language);
+}

+ 65 - 0
panda/src/shaderpipeline/shaderCompilerRegistry.h

@@ -0,0 +1,65 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderCompilerRegistry.h
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#ifndef SHADERCOMPILERREGISTRY_H
+#define SHADERCOMPILERREGISTRY_H
+
+#include "pandabase.h"
+
+#include "pvector.h"
+#include "pmap.h"
+#include "shader.h"
+
+class ShaderCompiler;
+
+/**
+ * This class maintains the set of all known ShaderCompilers in the universe.
+ */
+class EXPCL_PANDA_SHADERPIPELINE ShaderCompilerRegistry {
+protected:
+  ShaderCompilerRegistry();
+
+public:
+  ~ShaderCompilerRegistry();
+
+  void register_compiler(ShaderCompiler *compiler);
+  void register_deferred_compiler(Shader::ShaderLanguage language, const std::string &library);
+
+PUBLISHED:
+  int get_num_compilers() const;
+  ShaderCompiler *get_compiler(int n) const;
+  MAKE_SEQ(get_compilers, get_num_compilers, get_compiler);
+  MAKE_SEQ_PROPERTY(compilers, get_num_compilers, get_compiler);
+  ShaderCompiler *get_compiler_from_language(Shader::ShaderLanguage language);
+
+  void write(std::ostream &out, int indent_level = 0) const;
+
+  static ShaderCompilerRegistry *get_global_ptr();
+
+private:
+  void record_language(Shader::ShaderLanguage language, ShaderCompiler *compiler);
+
+private:
+  typedef pvector<ShaderCompiler *> Compilers;
+  Compilers _compilers;
+
+  typedef pmap<Shader::ShaderLanguage, ShaderCompiler *> Languages;
+  Languages _languages;
+
+  typedef pmap<Shader::ShaderLanguage, std::string> DeferredCompilers;
+  DeferredCompilers _deferred_compilers;
+
+  static ShaderCompilerRegistry *_global_ptr;
+};
+
+#endif

+ 22 - 0
panda/src/shaderpipeline/shaderModule.cxx

@@ -0,0 +1,22 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderModule.cxx
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#include "shaderModule.h"
+
+ShaderModule::
+ShaderModule() {
+}
+
+ShaderModule::
+~ShaderModule() {
+}

+ 29 - 0
panda/src/shaderpipeline/shaderModule.h

@@ -0,0 +1,29 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderModule.h
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#ifndef SHADERMODULE_H
+#define SHADERMODULE_H
+
+/**
+ * This is the base class for the outputs of shaderCompilers
+ */
+class EXPCL_PANDA_SHADERPIPELINE ShaderModule : public TypedReferenceCount {
+public:
+  ShaderModule();
+  virtual ~ShaderModule();
+
+PUBLISHED:
+  virtual std::string get_ir() const=0;
+  virtual Shader::ShaderType get_shader_type() const=0;
+};
+#endif

+ 35 - 0
panda/src/shaderpipeline/shaderModuleGlsl.cxx

@@ -0,0 +1,35 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderModuleGlsl.cxx
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#include "shaderModuleGlsl.h"
+
+ShaderModuleGlsl::
+ShaderModuleGlsl(Shader::ShaderType shader_type, std::string source) :
+  _shader_type(shader_type),
+  _raw_source(source)
+{
+}
+
+ShaderModuleGlsl::
+~ShaderModuleGlsl() {
+}
+
+std::string ShaderModuleGlsl::
+get_ir() const {
+  return this->_raw_source;
+}
+
+Shader::ShaderType ShaderModuleGlsl::
+get_shader_type() const {
+  return this->_shader_type;
+}

+ 35 - 0
panda/src/shaderpipeline/shaderModuleGlsl.h

@@ -0,0 +1,35 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderModuleGlsl.h
+ * @author Mitchell Stokes
+ * @date 2019-02-16
+ */
+
+#ifndef SHADERMODULEGLSL_H
+#define SHADERMODULEGLSL_H
+
+#include "shader.h"
+
+/**
+ * ShaderModule that contains raw GLSL code
+ */
+class EXPCL_PANDA_SHADERPIPELINE ShaderModuleGlsl : public ShaderModule {
+public:
+  ShaderModuleGlsl(Shader::ShaderType shader_type, std::string source);
+  virtual ~ShaderModuleGlsl();
+
+protected:
+  Shader::ShaderType _shader_type;
+  std::string _raw_source;
+
+PUBLISHED:
+  virtual std::string get_ir() const;
+  virtual Shader::ShaderType get_shader_type() const;
+};
+#endif

+ 7 - 0
tests/shaderpipeline/conftest.py

@@ -0,0 +1,7 @@
+import pytest
+
[email protected]
+def registry():
+    from panda3d.core import ShaderCompilerRegistry
+    return ShaderCompilerRegistry.get_global_ptr()
+

+ 10 - 0
tests/shaderpipeline/test_shadercompiler.py

@@ -0,0 +1,10 @@
+from panda3d import core
+
+GLSL_VERT_SHADER = """
+"""
+
+def test_shadercompiler_glsl(registry):
+    compiler = registry.get_compiler_from_language(core.Shader.SL_GLSL)
+    module = compiler.compile_now(core.Shader.ST_vertex, GLSL_VERT_SHADER)
+    assert module.get_shader_type() == core.Shader.ST_vertex
+    assert module.get_ir() == GLSL_VERT_SHADER

+ 14 - 0
tests/shaderpipeline/test_shadercompilerregistry.py

@@ -0,0 +1,14 @@
+from panda3d import core
+
+
+def test_shadercompilerregistry_exists(registry):
+    assert registry is not None
+
+
+def test_shadercompilerregistry_glslpreproc_loaded(registry):
+    assert core.ShaderCompilerGlslPreProc in [type(i) for i in registry.compilers]
+    assert registry.get_compiler_from_language(core.Shader.SL_GLSL) is not None
+
+def test_shadercompilerregistry_missing_lang(registry):
+    assert core.ShaderCompilerGlslPreProc in [type(i) for i in registry.compilers]
+    assert registry.get_compiler_from_language(core.Shader.SL_Cg) is None