shader: separate shader matrix input cache from ShaderMatSpec

If multiple ShaderMatSpec entries use the same state matrix, this should result in a reduction in the number of times that state matrix is fetched.  This is especially so for arrays, which are now fetched once rather than once for every item.

This is the first step towards trying to solve #846.
This commit is contained in:
rdb 2020-01-25 17:05:36 +01:00
parent 6c66c8618d
commit 89f1a0e63c
11 changed files with 589 additions and 506 deletions

File diff suppressed because it is too large Load Diff

View File

@ -336,10 +336,12 @@ public:
virtual void clear(DrawableRegion *clearable); virtual void clear(DrawableRegion *clearable);
const LMatrix4 *fetch_specified_value(Shader::ShaderMatSpec &spec, int altered); void update_shader_matrix_cache(Shader *shader, LMatrix4 *cache, int altered);
const LMatrix4 *fetch_specified_part(Shader::ShaderMatInput input, InternalName *name, const LMatrix4 *fetch_specified_value(Shader::ShaderMatSpec &spec, const LMatrix4 *cache, int altered);
LMatrix4 &t, int index); void fetch_specified_part(Shader::ShaderMatInput input, InternalName *name,
const LMatrix4 *fetch_specified_member(const NodePath &np, CPT_InternalName member, LMatrix4 &t); LMatrix4 *into, int count = 1);
void fetch_specified_member(const NodePath &np, CPT_InternalName member,
LMatrix4 &t);
PT(Texture) fetch_specified_texture(Shader::ShaderTexSpec &spec, PT(Texture) fetch_specified_texture(Shader::ShaderTexSpec &spec,
SamplerState &sampler, int &view); SamplerState &sampler, int &view);
const Shader::ShaderPtrData *fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec); const Shader::ShaderPtrData *fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec);

View File

@ -74,6 +74,8 @@ DXShaderContext9(Shader *s, GSG *gsg) : ShaderContext(s) {
} }
} }
#endif #endif
_mat_part_cache = new LMatrix4[s->cp_get_mat_cache_size()];
} }
/** /**
@ -92,6 +94,8 @@ DXShaderContext9::
delete _vertex_element_array; delete _vertex_element_array;
_vertex_element_array = nullptr; _vertex_element_array = nullptr;
} }
delete[] _mat_part_cache;
} }
/** /**
@ -232,15 +236,20 @@ issue_parameters(GSG *gsg, int altered) {
} }
} }
for (size_t i = 0; i < _shader->_mat_spec.size(); ++i) { if (altered & _shader->_mat_deps) {
Shader::ShaderMatSpec &spec = _shader->_mat_spec[i]; gsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered);
for (Shader::ShaderMatSpec &spec : _shader->_mat_spec) {
if ((altered & spec._dep) == 0) {
continue;
}
if (altered & (spec._dep[0] | spec._dep[1])) {
CGparameter p = _cg_parameter_map[spec._id._seqno]; CGparameter p = _cg_parameter_map[spec._id._seqno];
if (p == nullptr) { if (p == nullptr) {
continue; continue;
} }
const LMatrix4 *val = gsg->fetch_specified_value(spec, altered);
const LMatrix4 *val = gsg->fetch_specified_value(spec, _mat_part_cache, altered);
if (val) { if (val) {
HRESULT hr; HRESULT hr;
PN_stdfloat v [4]; PN_stdfloat v [4];

View File

@ -87,6 +87,8 @@ private:
pvector <CGparameter> _cg_parameter_map; pvector <CGparameter> _cg_parameter_map;
#endif #endif
LMatrix4 *_mat_part_cache = nullptr;
private: private:
void release_resources(void); void release_resources(void);

View File

@ -338,6 +338,8 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
} }
} }
_mat_part_cache = new LMatrix4[_shader->cp_get_mat_cache_size()];
_glgsg->report_my_gl_errors(); _glgsg->report_my_gl_errors();
} }
@ -347,6 +349,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
CLP(CgShaderContext):: CLP(CgShaderContext)::
~CLP(CgShaderContext)() { ~CLP(CgShaderContext)() {
// Don't call release_resources; we may not have an active context. // Don't call release_resources; we may not have an active context.
delete[] _mat_part_cache;
} }
/** /**
@ -690,14 +693,14 @@ issue_parameters(int altered) {
} }
if (altered & _shader->_mat_deps) { if (altered & _shader->_mat_deps) {
for (int i = 0; i < (int)_shader->_mat_spec.size(); ++i) { _glgsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered);
Shader::ShaderMatSpec &spec = _shader->_mat_spec[i];
if ((altered & (spec._dep[0] | spec._dep[1])) == 0) { for (Shader::ShaderMatSpec &spec : _shader->_mat_spec) {
if ((altered & spec._dep) == 0) {
continue; continue;
} }
const LMatrix4 *val = _glgsg->fetch_specified_value(spec, altered); const LMatrix4 *val = _glgsg->fetch_specified_value(spec, _mat_part_cache, altered);
if (!val) continue; if (!val) continue;
const PN_stdfloat *data = val->get_data(); const PN_stdfloat *data = val->get_data();

View File

@ -75,6 +75,7 @@ private:
long _transform_table_size; long _transform_table_size;
long _slider_table_size; long _slider_table_size;
LMatrix4 *_mat_part_cache = nullptr;
pvector<CGparameter> _cg_parameter_map; pvector<CGparameter> _cg_parameter_map;
WCPT(RenderState) _state_rs; WCPT(RenderState) _state_rs;

View File

@ -228,9 +228,7 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, GLenum param_t
bind._part[1] = Shader::SMO_apiclip_to_view; bind._part[1] = Shader::SMO_apiclip_to_view;
} }
objShader->cp_optimize_mat_spec(bind); objShader->cp_add_mat_spec(bind);
objShader->_mat_spec.push_back(bind);
objShader->_mat_deps |= bind._dep[0] | bind._dep[1];
if (param_size > 1) { if (param_size > 1) {
// We support arrays of rows and arrays of columns, so we can run the // We support arrays of rows and arrays of columns, so we can run the
@ -243,7 +241,7 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, GLenum param_t
for (int i = 1; i < param_size; ++i) { for (int i = 1; i < param_size; ++i) {
bind._id._seqno += 1; bind._id._seqno += 1;
bind._piece = (Shader::ShaderMatPiece)((int)bind._piece + 1); bind._piece = (Shader::ShaderMatPiece)((int)bind._piece + 1);
objShader->_mat_spec.push_back(bind); objShader->cp_add_mat_spec(bind);
} }
} else { } else {
GLCAT.warning() << basename << "[" << param_size << "] should not be an array, only the first element will be defined\n"; GLCAT.warning() << basename << "[" << param_size << "] should not be an array, only the first element will be defined\n";
@ -380,6 +378,8 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
} else { } else {
_glgsg->_current_shader_context->bind(); _glgsg->_current_shader_context->bind();
} }
_mat_part_cache = new LMatrix4[_shader->cp_get_mat_cache_size()];
} }
/** /**
@ -885,15 +885,12 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._part[0] = inverse ? Shader::SMO_inv_texmat_i bind._part[0] = inverse ? Shader::SMO_inv_texmat_i
: Shader::SMO_texmat_i; : Shader::SMO_texmat_i;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._dep[0] = Shader::SSD_general | Shader::SSD_tex_matrix;
bind._dep[1] = 0;
// Add it once for each index. // Add it once for each index.
for (bind._index = 0; bind._index < param_size; ++bind._index) { for (bind._index = 0; bind._index < param_size; ++bind._index) {
bind._id._seqno = p + bind._index; bind._id._seqno = p + bind._index;
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
} }
_shader->_mat_deps |= bind._dep[0];
return; return;
} else if (matrix_name.size() > 15 && } else if (matrix_name.size() > 15 &&
@ -938,9 +935,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n"; GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n";
return; return;
} }
_shader->cp_optimize_mat_spec(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0] | bind._dep[1];
return; return;
} }
if (size > 7 && noprefix.substr(0, 7) == "Texture") { if (size > 7 && noprefix.substr(0, 7) == "Texture") {
@ -973,10 +968,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_attr_material; bind._part[0] = Shader::SMO_attr_material;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._dep[0] = Shader::SSD_general | Shader::SSD_material | Shader::SSD_frame;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._dep[1] = Shader::SSD_NONE;
if (noprefix == "Material.baseColor") { if (noprefix == "Material.baseColor") {
if (param_type != GL_FLOAT_VEC4) { if (param_type != GL_FLOAT_VEC4) {
@ -985,9 +978,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
} }
bind._part[0] = Shader::SMO_attr_material2; bind._part[0] = Shader::SMO_attr_material2;
bind._piece = Shader::SMP_row0; bind._piece = Shader::SMP_row0;
bind._dep[0] |= Shader::SSD_color; _shader->cp_add_mat_spec(bind);
_shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} else if (noprefix == "Material.ambient") { } else if (noprefix == "Material.ambient") {
@ -996,8 +987,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_Material.ambient should be vec4\n"; << "p3d_Material.ambient should be vec4\n";
} }
bind._piece = Shader::SMP_row0; bind._piece = Shader::SMP_row0;
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} else if (noprefix == "Material.diffuse") { } else if (noprefix == "Material.diffuse") {
@ -1006,8 +996,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_Material.diffuse should be vec4\n"; << "p3d_Material.diffuse should be vec4\n";
} }
bind._piece = Shader::SMP_row1; bind._piece = Shader::SMP_row1;
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} else if (noprefix == "Material.emission") { } else if (noprefix == "Material.emission") {
@ -1016,8 +1005,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_Material.emission should be vec4\n"; << "p3d_Material.emission should be vec4\n";
} }
bind._piece = Shader::SMP_row2; bind._piece = Shader::SMP_row2;
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} else if (noprefix == "Material.specular") { } else if (noprefix == "Material.specular") {
@ -1026,8 +1014,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_Material.specular should be vec3\n"; << "p3d_Material.specular should be vec3\n";
} }
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_row3x3;
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} else if (noprefix == "Material.shininess") { } else if (noprefix == "Material.shininess") {
@ -1036,8 +1023,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_Material.shininess should be float\n"; << "p3d_Material.shininess should be float\n";
} }
bind._piece = Shader::SMP_cell15; bind._piece = Shader::SMP_cell15;
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} else if (noprefix == "Material.roughness") { } else if (noprefix == "Material.roughness") {
@ -1047,8 +1033,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
} }
bind._part[0] = Shader::SMO_attr_material2; bind._part[0] = Shader::SMO_attr_material2;
bind._piece = Shader::SMP_cell15; bind._piece = Shader::SMP_cell15;
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} else if (noprefix == "Material.metallic") { } else if (noprefix == "Material.metallic") {
@ -1058,8 +1043,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
} }
bind._part[0] = Shader::SMO_attr_material2; bind._part[0] = Shader::SMO_attr_material2;
bind._piece = Shader::SMP_row3x1; bind._piece = Shader::SMP_row3x1;
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} else if (noprefix == "Material.refractiveIndex") { } else if (noprefix == "Material.refractiveIndex") {
@ -1069,8 +1053,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
} }
bind._part[0] = Shader::SMO_attr_material2; bind._part[0] = Shader::SMO_attr_material2;
bind._piece = Shader::SMP_cell13; bind._piece = Shader::SMP_cell13;
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} }
} }
@ -1080,10 +1063,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_attr_colorscale; bind._part[0] = Shader::SMO_attr_colorscale;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._dep[0] = Shader::SSD_general | Shader::SSD_colorscale;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._dep[1] = Shader::SSD_NONE;
if (param_type == GL_FLOAT_VEC3) { if (param_type == GL_FLOAT_VEC3) {
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_row3x3;
@ -1094,8 +1075,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_ColorScale should be vec3 or vec4\n"; << "p3d_ColorScale should be vec3 or vec4\n";
return; return;
} }
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} }
if (noprefix == "Color") { if (noprefix == "Color") {
@ -1104,10 +1084,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_attr_color; bind._part[0] = Shader::SMO_attr_color;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._dep[0] = Shader::SSD_general | Shader::SSD_color;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._dep[1] = Shader::SSD_NONE;
if (param_type == GL_FLOAT_VEC3) { if (param_type == GL_FLOAT_VEC3) {
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_row3x3;
@ -1118,8 +1096,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_Color should be vec3 or vec4\n"; << "p3d_Color should be vec3 or vec4\n";
return; return;
} }
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} }
if (noprefix == "ClipPlane") { if (noprefix == "ClipPlane") {
@ -1137,12 +1114,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._index = i; bind._index = i;
bind._part[0] = Shader::SMO_apiview_clipplane_i; bind._part[0] = Shader::SMO_apiview_clipplane_i;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._dep[0] = Shader::SSD_general | Shader::SSD_clip_planes;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._dep[1] = Shader::SSD_NONE; _shader->cp_add_mat_spec(bind);
_shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0];
} }
return; return;
} }
@ -1151,10 +1125,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._id = arg_id; bind._id = arg_id;
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._dep[0] = Shader::SSD_general | Shader::SSD_fog;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._dep[1] = Shader::SSD_NONE;
if (noprefix == "Fog.color") { if (noprefix == "Fog.color") {
bind._part[0] = Shader::SMO_attr_fogcolor; bind._part[0] = Shader::SMO_attr_fogcolor;
@ -1214,8 +1186,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
} }
} }
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} }
if (noprefix == "LightModel.ambient") { if (noprefix == "LightModel.ambient") {
@ -1224,10 +1195,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_light_ambient; bind._part[0] = Shader::SMO_light_ambient;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._dep[0] = Shader::SSD_general | Shader::SSD_light;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._dep[1] = Shader::SSD_NONE;
if (param_type == GL_FLOAT_VEC3) { if (param_type == GL_FLOAT_VEC3) {
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_row3x3;
@ -1238,8 +1207,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_LightModel.ambient should be vec3 or vec4\n"; << "p3d_LightModel.ambient should be vec3 or vec4\n";
return; return;
} }
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} }
if (size > 15 && noprefix.substr(0, 12) == "LightSource[") { if (size > 15 && noprefix.substr(0, 12) == "LightSource[") {
@ -1279,15 +1247,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._index = index; bind._index = index;
bind._part[0] = Shader::SMO_light_source_i_attrib; bind._part[0] = Shader::SMO_light_source_i_attrib;
bind._arg[0] = InternalName::make(member_name); bind._arg[0] = InternalName::make(member_name);
bind._dep[0] = Shader::SSD_general | Shader::SSD_light | Shader::SSD_frame;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._dep[1] = Shader::SSD_NONE;
if (member_name == "position" || member_name == "halfVector" ||
member_name == "spotDirection") {
bind._dep[0] |= Shader::SSD_view_transform;
}
switch (param_type) { switch (param_type) {
case GL_FLOAT: case GL_FLOAT:
@ -1311,8 +1272,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_LightSource[]." << member_name << " should be float or vec\n"; << "p3d_LightSource[]." << member_name << " should be float or vec\n";
return; return;
} }
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0] | bind._dep[1];
return; return;
} }
} }
@ -1344,13 +1304,10 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._index = 0; bind._index = 0;
bind._part[0] = Shader::SMO_tex_is_alpha_i; bind._part[0] = Shader::SMO_tex_is_alpha_i;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._dep[0] = Shader::SSD_general | Shader::SSD_texture | Shader::SSD_frame;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._dep[1] = Shader::SSD_NONE;
bind._piece = Shader::SMP_row3; bind._piece = Shader::SMP_row3;
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0] | bind._dep[1];
return; return;
} }
GLCAT.error() << "Unrecognized uniform name '" << param_name << "'!\n"; GLCAT.error() << "Unrecognized uniform name '" << param_name << "'!\n";
@ -1371,10 +1328,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_compose; bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_world_to_view; bind._part[0] = Shader::SMO_world_to_view;
bind._part[1] = Shader::SMO_view_to_apiview; bind._part[1] = Shader::SMO_view_to_apiview;
bind._dep[0] = Shader::SSD_general | Shader::SSD_view_transform; _shader->cp_add_mat_spec(bind);
bind._dep[1] = Shader::SSD_general;
_shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0] | bind._dep[1];
return; return;
} else if (noprefix == "InverseViewMatrix" || noprefix == "ViewMatrixInverse") { } else if (noprefix == "InverseViewMatrix" || noprefix == "ViewMatrixInverse") {
@ -1382,10 +1336,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_compose; bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_apiview_to_view; bind._part[0] = Shader::SMO_apiview_to_view;
bind._part[1] = Shader::SMO_view_to_world; bind._part[1] = Shader::SMO_view_to_world;
bind._dep[0] = Shader::SSD_general; _shader->cp_add_mat_spec(bind);
bind._dep[1] = Shader::SSD_general | Shader::SSD_view_transform;
_shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0] | bind._dep[1];
return; return;
} else if (noprefix == "FrameTime") { } else if (noprefix == "FrameTime") {
@ -1393,10 +1344,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_frame_time; bind._part[0] = Shader::SMO_frame_time;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._dep[0] = Shader::SSD_general | Shader::SSD_frame; _shader->cp_add_mat_spec(bind);
bind._dep[1] = Shader::SSD_NONE;
_shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0] | bind._dep[1];
return; return;
} else if (noprefix == "DeltaFrameTime") { } else if (noprefix == "DeltaFrameTime") {
@ -1404,10 +1352,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_frame_delta; bind._part[0] = Shader::SMO_frame_delta;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._dep[0] = Shader::SSD_general | Shader::SSD_frame; _shader->cp_add_mat_spec(bind);
bind._dep[1] = Shader::SSD_NONE;
_shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0] | bind._dep[1];
return; return;
} else if (noprefix == "FrameNumber") { } else if (noprefix == "FrameNumber") {
@ -1491,12 +1436,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_mat_constant_x; bind._part[0] = Shader::SMO_mat_constant_x;
bind._arg[0] = InternalName::make(param_name); bind._arg[0] = InternalName::make(param_name);
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._dep[1] = Shader::SSD_NONE; _shader->cp_add_mat_spec(bind);
_shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} }
case GL_FLOAT_MAT4: { case GL_FLOAT_MAT4: {
@ -1506,7 +1448,6 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._dep[1] = Shader::SSD_NONE;
PT(InternalName) iname = InternalName::make(param_name); PT(InternalName) iname = InternalName::make(param_name);
if (iname->get_parent() != InternalName::get_root()) { if (iname->get_parent() != InternalName::get_root()) {
// It might be something like an attribute of a shader input, like a // It might be something like an attribute of a shader input, like a
@ -1527,22 +1468,17 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_compose; bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_model_to_apiview; bind._part[0] = Shader::SMO_model_to_apiview;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._dep[0] = Shader::SSD_general | Shader::SSD_transform;
bind._part[1] = Shader::SMO_mat_constant_x_attrib; bind._part[1] = Shader::SMO_mat_constant_x_attrib;
bind._arg[1] = iname->get_parent()->append("shadowViewMatrix"); bind._arg[1] = iname->get_parent()->append("shadowViewMatrix");
bind._dep[1] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame | Shader::SSD_view_transform;
} else { } else {
bind._part[0] = Shader::SMO_mat_constant_x_attrib; bind._part[0] = Shader::SMO_mat_constant_x_attrib;
bind._arg[0] = InternalName::make(param_name); bind._arg[0] = InternalName::make(param_name);
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame | Shader::SSD_view_transform;
} }
} else { } else {
bind._part[0] = Shader::SMO_mat_constant_x; bind._part[0] = Shader::SMO_mat_constant_x;
bind._arg[0] = InternalName::make(param_name); bind._arg[0] = InternalName::make(param_name);
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame;
} }
_shader->_mat_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} }
case GL_FLOAT: case GL_FLOAT:
@ -1572,14 +1508,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_vec_constant_x_attrib; bind._part[0] = Shader::SMO_vec_constant_x_attrib;
bind._arg[0] = iname; bind._arg[0] = iname;
// We need SSD_view_transform since some attributes (eg. light
// position) have to be transformed to view space.
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame | Shader::SSD_view_transform;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._dep[1] = Shader::SSD_NONE; _shader->cp_add_mat_spec(bind);
_shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0];
return; return;
} // else fall through } // else fall through
} }
@ -1913,6 +1844,7 @@ get_sampler_texture_type(int &out, GLenum param_type) {
CLP(ShaderContext):: CLP(ShaderContext)::
~CLP(ShaderContext)() { ~CLP(ShaderContext)() {
// Don't call release_resources; we may not have an active context. // Don't call release_resources; we may not have an active context.
delete[] _mat_part_cache;
} }
/** /**
@ -2230,14 +2162,14 @@ issue_parameters(int altered) {
} }
if (altered & _shader->_mat_deps) { if (altered & _shader->_mat_deps) {
for (int i = 0; i < (int)_shader->_mat_spec.size(); ++i) { _glgsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered);
Shader::ShaderMatSpec &spec = _shader->_mat_spec[i];
if ((altered & (spec._dep[0] | spec._dep[1])) == 0) { for (Shader::ShaderMatSpec &spec : _shader->_mat_spec) {
if ((altered & spec._dep) == 0) {
continue; continue;
} }
const LMatrix4 *val = _glgsg->fetch_specified_value(spec, altered); const LMatrix4 *val = _glgsg->fetch_specified_value(spec, _mat_part_cache, altered);
if (!val) continue; if (!val) continue;
#ifndef STDFLOAT_DOUBLE #ifndef STDFLOAT_DOUBLE
// In this case, the data is already single-precision. // In this case, the data is already single-precision.

View File

@ -114,6 +114,8 @@ private:
}; };
pvector<ImageInput> _glsl_img_inputs; pvector<ImageInput> _glsl_img_inputs;
LMatrix4 *_mat_part_cache = nullptr;
CLP(GraphicsStateGuardian) *_glgsg; CLP(GraphicsStateGuardian) *_glgsg;
bool _uses_standard_vertex_arrays; bool _uses_standard_vertex_arrays;

View File

@ -384,7 +384,7 @@ cp_dependency(ShaderMatInput inp) {
if (inp == SMO_attr_material || inp == SMO_attr_material2) { if (inp == SMO_attr_material || inp == SMO_attr_material2) {
dep |= SSD_material | SSD_frame; dep |= SSD_material | SSD_frame;
} }
if (inp == SMO_attr_color) { if (inp == SMO_attr_color || inp == SMO_attr_material2) {
dep |= SSD_color; dep |= SSD_color;
} }
if (inp == SMO_attr_colorscale) { if (inp == SMO_attr_colorscale) {
@ -422,6 +422,7 @@ cp_dependency(ShaderMatInput inp) {
(inp == SMO_slight_x) || (inp == SMO_slight_x) ||
(inp == SMO_satten_x) || (inp == SMO_satten_x) ||
(inp == SMO_mat_constant_x) || (inp == SMO_mat_constant_x) ||
(inp == SMO_mat_constant_x_attrib) ||
(inp == SMO_vec_constant_x) || (inp == SMO_vec_constant_x) ||
(inp == SMO_vec_constant_x_attrib) || (inp == SMO_vec_constant_x_attrib) ||
(inp == SMO_view_x_to_view) || (inp == SMO_view_x_to_view) ||
@ -441,6 +442,8 @@ cp_dependency(ShaderMatInput inp) {
(inp == SMO_plight_x) || (inp == SMO_plight_x) ||
(inp == SMO_slight_x) || (inp == SMO_slight_x) ||
(inp == SMO_satten_x) || (inp == SMO_satten_x) ||
(inp == SMO_mat_constant_x) ||
(inp == SMO_mat_constant_x_attrib) ||
(inp == SMO_vec_constant_x_attrib) || (inp == SMO_vec_constant_x_attrib) ||
(inp == SMO_view_x_to_view) || (inp == SMO_view_x_to_view) ||
(inp == SMO_view_to_view_x) || (inp == SMO_view_to_view_x) ||
@ -459,10 +462,13 @@ cp_dependency(ShaderMatInput inp) {
(inp == SMO_light_source_i_attrib) || (inp == SMO_light_source_i_attrib) ||
(inp == SMO_light_source_i_packed)) { (inp == SMO_light_source_i_packed)) {
dep |= SSD_light | SSD_frame; dep |= SSD_light | SSD_frame;
if (inp == SMO_light_source_i_attrib || }
inp == SMO_light_source_i_packed) { if (inp == SMO_light_source_i_attrib ||
dep |= SSD_view_transform; inp == SMO_light_source_i_packed ||
} inp == SMO_mat_constant_x_attrib ||
inp == SMO_vec_constant_x_attrib) {
// Some light attribs (eg. position) need to be transformed to view space.
dep |= SSD_view_transform;
} }
if ((inp == SMO_light_product_i_ambient) || if ((inp == SMO_light_product_i_ambient) ||
(inp == SMO_light_product_i_diffuse) || (inp == SMO_light_product_i_diffuse) ||
@ -499,14 +505,10 @@ cp_dependency(ShaderMatInput inp) {
} }
/** /**
* Analyzes a ShaderMatSpec and decides what it should use its cache for. It * Adds the given ShaderMatSpec to the shader's mat spec table.
* can cache the results of any one opcode, or, it can cache the entire
* result. This routine needs to be smart enough to know which data items can
* be correctly cached, and which cannot.
*/ */
void Shader:: void Shader::
cp_optimize_mat_spec(ShaderMatSpec &spec) { cp_add_mat_spec(ShaderMatSpec &spec) {
// If we're composing with identity, simplify. // If we're composing with identity, simplify.
if (spec._func == SMF_first) { if (spec._func == SMF_first) {
@ -563,10 +565,92 @@ cp_optimize_mat_spec(ShaderMatSpec &spec) {
} }
} }
// Calculate state and transform dependencies. // Determine which part is an array, for determining which one the count and
// index refer to. (It can't be the case that both parts are arrays.)
int begin[2] = {0, 0};
int end[2] = {1, 1};
if (spec._index > 0) {
for (int i = 0; i < 2; ++i) {
if (spec._part[i] == SMO_texmat_i ||
spec._part[i] == SMO_inv_texmat_i ||
spec._part[i] == SMO_light_source_i_attrib ||
spec._part[i] == SMO_light_product_i_ambient ||
spec._part[i] == SMO_light_product_i_diffuse ||
spec._part[i] == SMO_light_product_i_specular ||
spec._part[i] == SMO_apiview_clipplane_i ||
spec._part[i] == SMO_tex_is_alpha_i ||
spec._part[i] == SMO_transform_i ||
spec._part[i] == SMO_slider_i ||
spec._part[i] == SMO_light_source_i_packed ||
spec._part[i] == SMO_texscale_i ||
spec._part[i] == SMO_texcolor_i) {
begin[i] = spec._index;
end[i] = spec._index + 1;
}
}
nassertv(end[0] == 1 || end[1] == 1);
}
spec._dep[0] = cp_dependency(spec._part[0]); // Make sure that we have a place in the part cache for both parts.
spec._dep[1] = cp_dependency(spec._part[1]); int num_parts = (spec._func != SMF_first) ? 2 : 1;
for (int p = 0; p < num_parts; ++p) {
int dep = cp_dependency(spec._part[p]);
spec._dep |= dep;
// Do we already have a spot in the cache for this part?
size_t i;
size_t offset = 0;
for (i = 0; i < _mat_parts.size(); ++i) {
ShaderMatPart &part = _mat_parts[i];
if (part._part == spec._part[p] && part._arg == spec._arg[p]) {
int diff = end[p] - part._count;
if (diff <= 0) {
// The existing cache entry is big enough.
break;
} else {
// It's not big enough. Enlarge it, which means we have to change the
// offset of some of the other spec entries.
for (ShaderMatSpec &spec : _mat_spec) {
if (spec._cache_offset[0] >= offset + part._count) {
spec._cache_offset[0] += diff;
}
if (spec._cache_offset[1] >= offset + part._count) {
spec._cache_offset[1] += diff;
}
}
part._count = end[p];
break;
}
}
offset += part._count;
}
if (i == _mat_parts.size()) {
// Didn't find this part yet, create a new one.
ShaderMatPart part;
part._part = spec._part[p];
part._count = end[p];
part._arg = spec._arg[p];
part._dep = dep;
_mat_parts.push_back(std::move(part));
}
spec._cache_offset[p] = offset + begin[p];
}
_mat_spec.push_back(spec);
_mat_deps |= spec._dep;
}
/**
* Returns the total size of the matrix part cache.
*/
size_t Shader::
cp_get_mat_cache_size() const {
size_t size = 0;
for (const ShaderMatPart &part : _mat_parts) {
size += part._count;
}
return size;
} }
#ifdef HAVE_CG #ifdef HAVE_CG
@ -776,9 +860,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._index = atoi(pieces[2].c_str()); bind._index = atoi(pieces[2].c_str());
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -931,9 +1013,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
if (!cp_parse_eol(p, pieces, next)) { if (!cp_parse_eol(p, pieces, next)) {
return false; return false;
} }
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1041,9 +1121,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
return false; return false;
} }
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1055,9 +1133,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1079,9 +1155,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._part[1] = SMO_identity; bind._part[1] = SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1101,9 +1175,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._part[1] = SMO_identity; bind._part[1] = SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1143,9 +1215,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
if (!cp_parse_eol(p, pieces, next)) { if (!cp_parse_eol(p, pieces, next)) {
return false; return false;
} }
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1166,9 +1236,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._index = atoi(pieces[1].c_str()); bind._index = atoi(pieces[1].c_str());
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1189,9 +1257,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._index = atoi(pieces[1].c_str()); bind._index = atoi(pieces[1].c_str());
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1212,9 +1278,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._index = atoi(pieces[1].c_str()); bind._index = atoi(pieces[1].c_str());
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1234,9 +1298,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._part[1] = SMO_identity; bind._part[1] = SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1256,9 +1318,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._part[1] = SMO_identity; bind._part[1] = SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1303,9 +1363,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
return false; return false;
} }
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1388,9 +1446,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._arg[0] = InternalName::make(pieces[1]); bind._arg[0] = InternalName::make(pieces[1]);
bind._part[1] = SMO_identity; bind._part[1] = SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -1409,9 +1465,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._arg[0] = InternalName::make(pieces[1]); bind._arg[0] = InternalName::make(pieces[1]);
bind._part[1] = SMO_identity; bind._part[1] = SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
cp_optimize_mat_spec(bind); cp_add_mat_spec(bind);
_mat_spec.push_back(bind);
_mat_deps |= bind._dep[0] | bind._dep[1];
return true; return true;
} }
@ -2362,7 +2416,6 @@ Shader(ShaderLanguage lang) :
_loaded(false), _loaded(false),
_language(lang), _language(lang),
_last_modified(0), _last_modified(0),
_mat_deps(0),
_cache_compiled_shader(false) _cache_compiled_shader(false)
{ {
#ifdef HAVE_CG #ifdef HAVE_CG

View File

@ -402,15 +402,30 @@ public:
INLINE void read_datagram(DatagramIterator &source); INLINE void read_datagram(DatagramIterator &source);
}; };
/**
* Describes a matrix making up a single part of the ShaderMatInput cache.
* The cache is made up of a continuous array of matrices, as described by
* a successive list of ShaderMatPart (each of which takes up _count matrices)
*/
struct ShaderMatPart {
ShaderMatInput _part;
PT(InternalName) _arg;
int _count = 1;
int _dep = SSD_NONE;
};
/**
* Describes a shader input that is sourced from the render state.
*/
struct ShaderMatSpec { struct ShaderMatSpec {
LMatrix4 _cache[2]; size_t _cache_offset[2];
LMatrix4 _value;
ShaderArgId _id; ShaderArgId _id;
ShaderMatFunc _func; ShaderMatFunc _func;
ShaderMatInput _part[2]; ShaderMatInput _part[2];
PT(InternalName) _arg[2]; PT(InternalName) _arg[2];
int _dep[2]; LMatrix4 _value;
int _index; int _dep = SSD_NONE;
int _index = 0;
ShaderMatPiece _piece; ShaderMatPiece _piece;
}; };
@ -514,7 +529,8 @@ public:
vector_string &pieces, int &next, vector_string &pieces, int &next,
ShaderMatSpec &spec, bool fromflag); ShaderMatSpec &spec, bool fromflag);
int cp_dependency(ShaderMatInput inp); int cp_dependency(ShaderMatInput inp);
void cp_optimize_mat_spec(ShaderMatSpec &spec); void cp_add_mat_spec(ShaderMatSpec &spec);
size_t cp_get_mat_cache_size() const;
#ifdef HAVE_CG #ifdef HAVE_CG
void cg_recurse_parameters(CGparameter parameter, void cg_recurse_parameters(CGparameter parameter,
@ -578,7 +594,9 @@ public:
epvector<ShaderMatSpec> _mat_spec; epvector<ShaderMatSpec> _mat_spec;
pvector<ShaderTexSpec> _tex_spec; pvector<ShaderTexSpec> _tex_spec;
pvector<ShaderVarSpec> _var_spec; pvector<ShaderVarSpec> _var_spec;
int _mat_deps; pvector<ShaderMatPart> _mat_parts;
int _mat_deps = 0;
int _mat_cache_size = 0;
bool _error_flag; bool _error_flag;
ShaderFile _text; ShaderFile _text;

View File

@ -530,7 +530,8 @@ get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const {
if (p.get_value_type() == ShaderInput::M_nodepath) { if (p.get_value_type() == ShaderInput::M_nodepath) {
const NodePath &np = p.get_nodepath(); const NodePath &np = p.get_nodepath();
nassertr(!np.is_empty(), LMatrix4::ident_mat()); nassertr(!np.is_empty(), LMatrix4::ident_mat());
return np.get_transform()->get_mat(); matrix = np.get_transform()->get_mat();
return matrix;
} else if (p.get_value_type() == ShaderInput::M_numeric && } else if (p.get_value_type() == ShaderInput::M_numeric &&
p.get_ptr()._size >= 16 && (p.get_ptr()._size & 15) == 0) { p.get_ptr()._size >= 16 && (p.get_ptr()._size & 15) == 0) {