Răsfoiți Sursa

Shader generation should be done in cull, not in draw

rdb 11 ani în urmă
părinte
comite
7ba0469148

+ 14 - 6
panda/src/display/graphicsEngine.cxx

@@ -1360,9 +1360,9 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist,
                        Thread *current_thread) {
   PStatTimer timer(_cull_pcollector, current_thread);
 
-  Windows::const_iterator wi;
-  for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
-    GraphicsOutput *win = (*wi);
+  size_t wlist_size = wlist.size();
+  for (size_t wi = 0; wi < wlist_size; ++wi) {
+    GraphicsOutput *win = wlist[wi];
     if (win->is_active() && win->get_gsg()->is_active()) {
       if (win->flip_ready()) {
         {
@@ -1486,9 +1486,9 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
   typedef pmap<NodePath, DisplayRegion *> AlreadyCulled;
   AlreadyCulled already_culled;
 
-  Windows::const_iterator wi;
-  for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
-    GraphicsOutput *win = (*wi);
+  size_t wlist_size = wlist.size();
+  for (size_t wi = 0; wi < wlist_size; ++wi) {
+    GraphicsOutput *win = wlist[wi];
     if (win->is_active() && win->get_gsg()->is_active()) {
       PStatTimer timer(win->get_cull_window_pcollector(), current_thread);
       int num_display_regions = win->get_num_active_display_regions();
@@ -1997,6 +1997,14 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
   CPT(TransformState) cs_world_transform = cs_transform->compose(world_transform);
   scene_setup->set_cs_world_transform(cs_world_transform);
 
+  // Make sure that the GSG has a ShaderGenerator for the munger
+  // to use.  We have to do this here because the ShaderGenerator
+  // needs a host window pointer.  Hopefully we'll be able to
+  // eliminate that requirement in the future.
+  if (gsg->get_shader_generator() == NULL) {
+    gsg->set_shader_generator(new ShaderGenerator(gsg, window));
+  }
+
   return scene_setup;
 }
 

+ 22 - 0
panda/src/display/graphicsStateGuardian.I

@@ -214,6 +214,28 @@ get_loader() const {
   return _loader;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::set_shader_generator
+//       Access: Public
+//  Description: Sets the ShaderGenerator object that will be used
+//               by this GSG to generate shaders when necessary.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsStateGuardian::
+set_shader_generator(ShaderGenerator *shader_generator) {
+  _shader_generator = shader_generator;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::get_shader_generator
+//       Access: Public
+//  Description: Returns the ShaderGenerator object that will be used
+//               by this GSG to generate shaders when necessary.
+////////////////////////////////////////////////////////////////////
+INLINE ShaderGenerator *GraphicsStateGuardian::
+get_shader_generator() const {
+  return _shader_generator;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_pipe
 //       Access: Published

+ 0 - 8
panda/src/display/graphicsStateGuardian.cxx

@@ -266,8 +266,6 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
 
   _gamma = 1.0f;
   _texture_quality_override = Texture::QL_default;
-
-  _shader_generator = NULL;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -278,12 +276,6 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
 GraphicsStateGuardian::
 ~GraphicsStateGuardian() {
   remove_gsg(this);
-
-  if (_shader_generator) {
-    delete _shader_generator;
-    _shader_generator = 0;
-  }
-
   GeomMunger::unregister_mungers_for_gsg(this);
 }
 

+ 5 - 2
panda/src/display/graphicsStateGuardian.h

@@ -49,10 +49,10 @@
 #include "shaderAttrib.h"
 #include "texGenAttrib.h"
 #include "textureAttrib.h"
+#include "shaderGenerator.h"
 
 class DrawableRegion;
 class GraphicsEngine;
-class ShaderGenerator;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : GraphicsStateGuardian
@@ -104,6 +104,9 @@ PUBLISHED:
   INLINE void set_loader(Loader *loader);
   INLINE Loader *get_loader() const;
 
+  INLINE void set_shader_generator(ShaderGenerator *shader_generator);
+  INLINE ShaderGenerator *get_shader_generator() const;
+
   INLINE GraphicsPipe *get_pipe() const;
   GraphicsEngine *get_engine() const;
   INLINE const GraphicsThreadingModel &get_threading_model() const;
@@ -546,7 +549,7 @@ protected:
   PN_stdfloat _gamma;
   Texture::QualityLevel _texture_quality_override;
 
-  ShaderGenerator* _shader_generator;
+  PT(ShaderGenerator) _shader_generator;
 
 #ifndef NDEBUG
   PT(Texture) _flash_texture;

+ 35 - 6
panda/src/display/standardMunger.cxx

@@ -43,15 +43,18 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
 
   _munge_color = false;
   _munge_color_scale = false;
+  _auto_shader = false;
 
   if (!get_gsg()->get_runtime_color_scale()) {
     // We might need to munge the colors.
-    CPT(ColorAttrib) color_attrib = DCAST(ColorAttrib, state->get_attrib(ColorAttrib::get_class_slot()));
-    CPT(ColorScaleAttrib) color_scale_attrib = DCAST(ColorScaleAttrib, state->get_attrib(ColorScaleAttrib::get_class_slot()));
+    const ColorAttrib *color_attrib = (const ColorAttrib *)
+      state->get_attrib(ColorAttrib::get_class_slot());
+    const ColorScaleAttrib *color_scale_attrib = (const ColorScaleAttrib *)
+      state->get_attrib(ColorScaleAttrib::get_class_slot());
 
     if (color_attrib != (ColorAttrib *)NULL && 
         color_attrib->get_color_type() == ColorAttrib::T_flat) {
-      
+
       if (!get_gsg()->get_color_scale_via_lighting()) {
         // We only need to munge the color directly if the GSG says it
         // can't cheat the color via lighting (presumably, in this case,
@@ -72,15 +75,16 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
                color_scale_attrib->has_scale()) {
       _color_scale = color_scale_attrib->get_scale();
       
-      CPT(TextureAttrib) tex_attrib = DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_slot()));
-      
+      const TextureAttrib *tex_attrib = (const TextureAttrib *)
+        state->get_attrib(TextureAttrib::get_class_slot());
+
       // If the GSG says it can't cheat this RGB or alpha scale, we have
       // to apply the color scale directly.
       if ((color_scale_attrib->has_rgb_scale() && !get_gsg()->get_color_scale_via_lighting()) ||
           (color_scale_attrib->has_alpha_scale() && !get_gsg()->get_alpha_scale_via_texture(tex_attrib))) {
         _munge_color_scale = true;
       }
-      
+
       // Known bug: if there is a material on an object that would
       // obscure the effect of color_scale, we scale the lighting
       // anyway, thus applying the effect even if it should be obscured.
@@ -88,6 +92,12 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
       // situation and handle it correctly.
     }
   }
+
+  const ShaderAttrib *shader_attrib = (const ShaderAttrib *)
+    state->get_attrib_def(ShaderAttrib::get_class_slot());
+  if (shader_attrib->auto_shader()) {
+    _auto_shader = true;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -297,6 +307,10 @@ compare_to_impl(const GeomMunger *other) const {
     }
   }
 
+  if (_auto_shader != om->_auto_shader) {
+    return (int)_auto_shader - (int)om->_auto_shader;
+  }
+
   return StateMunger::compare_to_impl(other);
 }
 
@@ -351,5 +365,20 @@ munge_state_impl(const RenderState *state) {
     munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot());
   }
 
+  if (_auto_shader) {
+    CPT(RenderState) shader_state = munged_state->get_auto_shader_state();
+    ShaderGenerator *shader_generator = get_gsg()->get_shader_generator();
+    if (shader_generator == NULL) {
+      pgraph_cat.error()
+        << "auto_shader enabled, but GSG has no shader generator assigned!\n";
+      return munged_state;
+    }
+    if (shader_state->_generated_shader == NULL) {
+      // Cache the generated ShaderAttrib on the shader state.
+      shader_state->_generated_shader = shader_generator->synthesize_shader(shader_state);
+    }
+    munged_state = munged_state->set_attrib(shader_state->_generated_shader);
+  }
+
   return munged_state;
 }

+ 1 - 0
panda/src/display/standardMunger.h

@@ -57,6 +57,7 @@ private:
 
   bool _munge_color;
   bool _munge_color_scale;
+  bool _auto_shader;
 
   LColor _color;
   LVecBase4 _color_scale;

+ 0 - 10
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -3194,16 +3194,6 @@ set_state_and_transform(const RenderState *target,
   _target_rs = target;
 
   _target_shader = DCAST(ShaderAttrib, _target_rs->get_attrib_def(ShaderAttrib::get_class_slot()));
-  if (_target_shader->auto_shader()) {
-    // If we don't have a generated shader, make sure we have a ShaderGenerator, then generate the shader.
-    if (_target_rs->_generated_shader == NULL) {
-      if (_shader_generator == NULL) {
-        _shader_generator = new ShaderGenerator(this, _scene_setup->get_display_region()->get_window());
-      }
-      const_cast<RenderState*>(_target_rs.p())->_generated_shader = DCAST(ShaderAttrib, _shader_generator->synthesize_shader(_target_rs));
-    }
-    _target_shader = DCAST(ShaderAttrib, _target_rs->_generated_shader);
-  }
 
   int alpha_test_slot = AlphaTestAttrib::get_class_slot();
   if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) ||

+ 1 - 1
panda/src/pgraph/renderState.h

@@ -215,7 +215,7 @@ public:
   // ShaderAttrib will be synthesized by the runtime and stored here.
   // I can't declare this as a ShaderAttrib because that would create
   // a circular include-file dependency problem.  Aaargh.
-  CPT(RenderAttrib) _generated_shader;
+  mutable CPT(RenderAttrib) _generated_shader;
 
 private:
   // This mutex protects _states.  It also protects any modification

+ 5 - 6
panda/src/pgraphnodes/shaderGenerator.cxx

@@ -53,8 +53,8 @@ TypeHandle ShaderGenerator::_type_handle;
 //               which the shader generator belongs.
 ////////////////////////////////////////////////////////////////////
 ShaderGenerator::
-ShaderGenerator(PT(GraphicsStateGuardianBase) gsg, PT(GraphicsOutputBase) host) :
-  _gsg (gsg), _host (host) {
+ShaderGenerator(GraphicsStateGuardianBase *gsg, GraphicsOutputBase *host) :
+  _gsg(gsg), _host(host) {
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -566,7 +566,7 @@ update_shadow_buffer(NodePath light_np) {
   }
 
   // See if we already have a buffer. If not, create one.
-  PT(Texture) tex;
+  Texture *tex;
   if (light->_sbuffers.count(_gsg) == 0) {
     // Nope, the light doesn't have a buffer for our GSG. Make one.
     tex = _gsg->make_shadow_buffer(light_np, _host);
@@ -612,7 +612,7 @@ update_shadow_buffer(NodePath light_np) {
 //               - omit attenuation calculations if attenuation off
 //
 ////////////////////////////////////////////////////////////////////
-CPT(RenderAttrib) ShaderGenerator::
+CPT(ShaderAttrib) ShaderGenerator::
 synthesize_shader(const RenderState *rs) {
   analyze_renderstate(rs);
   reset_register_allocator();
@@ -1462,7 +1462,7 @@ synthesize_shader(const RenderState *rs) {
   }
   clear_analysis();
   reset_register_allocator();
-  return shattr;
+  return DCAST(ShaderAttrib, shattr);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1636,4 +1636,3 @@ texture_type_as_string(Texture::TextureType ttype) {
       return "2D";
   }
 }
-

+ 6 - 8
panda/src/pgraphnodes/shaderGenerator.h

@@ -63,12 +63,11 @@ class LightAttrib;
 //               Thanks to them!
 //
 ////////////////////////////////////////////////////////////////////
-
-class EXPCL_PANDA_PGRAPHNODES ShaderGenerator : public TypedObject {
+class EXPCL_PANDA_PGRAPHNODES ShaderGenerator : public TypedReferenceCount {
 PUBLISHED:
-  ShaderGenerator(PT(GraphicsStateGuardianBase) gsg, PT(GraphicsOutputBase) host);
+  ShaderGenerator(GraphicsStateGuardianBase *gsg, GraphicsOutputBase *host);
   virtual ~ShaderGenerator();
-  virtual CPT(RenderAttrib) synthesize_shader(const RenderState *rs);
+  virtual CPT(ShaderAttrib) synthesize_shader(const RenderState *rs);
 
 protected:
   CPT(RenderAttrib) create_shader_attrib(const string &txt);
@@ -152,9 +151,9 @@ protected:
   void analyze_renderstate(const RenderState *rs);
   void clear_analysis();
 
-  PT(GraphicsStateGuardianBase) _gsg;
-  PT(GraphicsOutputBase) _host;
-  pmap<WCPT(RenderState), CPT(ShaderAttrib)> _generated_shaders;
+  // This is not a PT() to prevent a circular reference.
+  GraphicsStateGuardianBase *_gsg;
+  GraphicsOutputBase *_host;
 
 public:
   static TypeHandle get_class_type() {
@@ -177,4 +176,3 @@ public:
 #include "shaderGenerator.I"
 
 #endif  // SHADERGENERATOR_H
-