Shader generation should be done in cull, not in draw

This commit is contained in:
rdb 2015-01-23 15:03:50 +01:00
parent a56f722c09
commit 7ba0469148
10 changed files with 89 additions and 47 deletions

View File

@ -1360,9 +1360,9 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist,
Thread *current_thread) { Thread *current_thread) {
PStatTimer timer(_cull_pcollector, current_thread); PStatTimer timer(_cull_pcollector, current_thread);
Windows::const_iterator wi; size_t wlist_size = wlist.size();
for (wi = wlist.begin(); wi != wlist.end(); ++wi) { for (size_t wi = 0; wi < wlist_size; ++wi) {
GraphicsOutput *win = (*wi); GraphicsOutput *win = wlist[wi];
if (win->is_active() && win->get_gsg()->is_active()) { if (win->is_active() && win->get_gsg()->is_active()) {
if (win->flip_ready()) { if (win->flip_ready()) {
{ {
@ -1486,9 +1486,9 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
typedef pmap<NodePath, DisplayRegion *> AlreadyCulled; typedef pmap<NodePath, DisplayRegion *> AlreadyCulled;
AlreadyCulled already_culled; AlreadyCulled already_culled;
Windows::const_iterator wi; size_t wlist_size = wlist.size();
for (wi = wlist.begin(); wi != wlist.end(); ++wi) { for (size_t wi = 0; wi < wlist_size; ++wi) {
GraphicsOutput *win = (*wi); GraphicsOutput *win = wlist[wi];
if (win->is_active() && win->get_gsg()->is_active()) { if (win->is_active() && win->get_gsg()->is_active()) {
PStatTimer timer(win->get_cull_window_pcollector(), current_thread); PStatTimer timer(win->get_cull_window_pcollector(), current_thread);
int num_display_regions = win->get_num_active_display_regions(); 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); CPT(TransformState) cs_world_transform = cs_transform->compose(world_transform);
scene_setup->set_cs_world_transform(cs_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; return scene_setup;
} }

View File

@ -214,6 +214,28 @@ get_loader() const {
return _loader; 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 // Function: GraphicsStateGuardian::get_pipe
// Access: Published // Access: Published

View File

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

View File

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

View File

@ -43,11 +43,14 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
_munge_color = false; _munge_color = false;
_munge_color_scale = false; _munge_color_scale = false;
_auto_shader = false;
if (!get_gsg()->get_runtime_color_scale()) { if (!get_gsg()->get_runtime_color_scale()) {
// We might need to munge the colors. // We might need to munge the colors.
CPT(ColorAttrib) color_attrib = DCAST(ColorAttrib, state->get_attrib(ColorAttrib::get_class_slot())); const ColorAttrib *color_attrib = (const ColorAttrib *)
CPT(ColorScaleAttrib) color_scale_attrib = DCAST(ColorScaleAttrib, state->get_attrib(ColorScaleAttrib::get_class_slot())); 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 && if (color_attrib != (ColorAttrib *)NULL &&
color_attrib->get_color_type() == ColorAttrib::T_flat) { color_attrib->get_color_type() == ColorAttrib::T_flat) {
@ -72,7 +75,8 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
color_scale_attrib->has_scale()) { color_scale_attrib->has_scale()) {
_color_scale = color_scale_attrib->get_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 // If the GSG says it can't cheat this RGB or alpha scale, we have
// to apply the color scale directly. // to apply the color scale directly.
@ -88,6 +92,12 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
// situation and handle it correctly. // 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); 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()); 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; return munged_state;
} }

View File

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

View File

@ -3194,16 +3194,6 @@ set_state_and_transform(const RenderState *target,
_target_rs = target; _target_rs = target;
_target_shader = DCAST(ShaderAttrib, _target_rs->get_attrib_def(ShaderAttrib::get_class_slot())); _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(); int alpha_test_slot = AlphaTestAttrib::get_class_slot();
if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) || if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) ||

View File

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

View File

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

View File

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