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) {
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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

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

View File

@ -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) ||

View File

@ -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

View File

@ -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";
}
}

View File

@ -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