diff --git a/panda/src/glstuff/glCgShaderContext_src.I b/panda/src/glstuff/glCgShaderContext_src.I index 243ed4c758..376347a96e 100644 --- a/panda/src/glstuff/glCgShaderContext_src.I +++ b/panda/src/glstuff/glCgShaderContext_src.I @@ -52,15 +52,5 @@ uses_custom_vertex_arrays() { return true; } -//////////////////////////////////////////////////////////////////// -// Function: GLCgShaderContext::uses_custom_texture_bindings -// Access: Public -// Description: Always true, for now. -//////////////////////////////////////////////////////////////////// -INLINE bool CLP(CgShaderContext):: -uses_custom_texture_bindings() { - return true; -} - #endif // OPENGLES_1 diff --git a/panda/src/glstuff/glCgShaderContext_src.cxx b/panda/src/glstuff/glCgShaderContext_src.cxx index a2301e74a7..1a4589e854 100644 --- a/panda/src/glstuff/glCgShaderContext_src.cxx +++ b/panda/src/glstuff/glCgShaderContext_src.cxx @@ -46,6 +46,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte _color_attrib_index = CA_color; _transform_table_param = 0; _slider_table_param = 0; + _frame_number = -1; nassertv(s->get_language() == Shader::SL_Cg); @@ -361,13 +362,8 @@ release_resources() { // input parameters. //////////////////////////////////////////////////////////////////// void CLP(CgShaderContext):: -bind(bool reissue_parameters) { +bind() { if (_cg_program != 0) { - if (reissue_parameters) { - // Pass in k-parameters and transform-parameters - issue_parameters(Shader::SSD_general); - } - // Bind the shaders. cgGLEnableProgramProfiles(_cg_program); cgGLBindProgram(_cg_program); @@ -397,6 +393,88 @@ unbind() { } } +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::set_state_and_transform +// Access: Public +// Description: This function gets called whenever the RenderState +// or TransformState has changed, but the Shader +// itself has not changed. It loads new values into the +// shader's parameters. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +set_state_and_transform(const RenderState *target_rs, + const TransformState *modelview_transform, + const TransformState *projection_transform) { + + if (!valid()) { + return; + } + + // Find out which state properties have changed. + int altered = 0; + + if (_modelview_transform != modelview_transform) { + _modelview_transform = modelview_transform; + altered |= Shader::SSD_transform; + } + if (_projection_transform != projection_transform) { + _projection_transform = projection_transform; + altered |= Shader::SSD_projection; + } + + if (_state_rs != target_rs) { + if (_state_rs == NULL) { + // We haven't set any state yet. + altered |= Shader::SSD_general; + } else { + if (_state_rs->get_attrib(ColorAttrib::get_class_slot()) != + target_rs->get_attrib(ColorAttrib::get_class_slot())) { + altered |= Shader::SSD_color; + } + if (_state_rs->get_attrib(ColorScaleAttrib::get_class_slot()) != + target_rs->get_attrib(ColorScaleAttrib::get_class_slot())) { + altered |= Shader::SSD_colorscale; + } + if (_state_rs->get_attrib(MaterialAttrib::get_class_slot()) != + target_rs->get_attrib(MaterialAttrib::get_class_slot())) { + altered |= Shader::SSD_material; + } + if (_state_rs->get_attrib(ShaderAttrib::get_class_slot()) != + target_rs->get_attrib(ShaderAttrib::get_class_slot())) { + altered |= Shader::SSD_shaderinputs; + } + if (_state_rs->get_attrib(FogAttrib::get_class_slot()) != + target_rs->get_attrib(FogAttrib::get_class_slot())) { + altered |= Shader::SSD_fog; + } + if (_state_rs->get_attrib(LightAttrib::get_class_slot()) != + target_rs->get_attrib(LightAttrib::get_class_slot())) { + altered |= Shader::SSD_light; + } + if (_state_rs->get_attrib(ClipPlaneAttrib::get_class_slot()) != + target_rs->get_attrib(ClipPlaneAttrib::get_class_slot())) { + altered |= Shader::SSD_clip_planes; + } + if (_state_rs->get_attrib(TexMatrixAttrib::get_class_slot()) != + target_rs->get_attrib(TexMatrixAttrib::get_class_slot())) { + altered |= Shader::SSD_tex_matrix; + } + } + _state_rs = target_rs; + } + + // Is this the first time this shader is used this frame? + int frame_number = ClockObject::get_global_clock()->get_frame_count(); + if (frame_number != _frame_number) { + altered |= Shader::SSD_frame; + _frame_number = frame_number; + } + + if (altered != 0) { + issue_parameters(altered); + } +} + //////////////////////////////////////////////////////////////////// // Function: GLCgShaderContext::issue_parameters // Access: Public @@ -414,49 +492,48 @@ unbind() { //////////////////////////////////////////////////////////////////// void CLP(CgShaderContext):: issue_parameters(int altered) { - //PStatGPUTimer timer(_glgsg, _glgsg->_draw_set_state_shader_parameters_pcollector); + PStatGPUTimer timer(_glgsg, _glgsg->_draw_set_state_shader_parameters_pcollector); - if (!valid()) { - return; + if (GLCAT.is_spam()) { + GLCAT.spam() + << "Setting uniforms for " << _shader->get_filename() + << " (altered 0x" << hex << altered << dec << ")\n"; } - // Iterate through _ptr parameters - for (int i=0; i<(int)_shader->_ptr_spec.size(); i++) { - if (altered & (_shader->_ptr_spec[i]._dep[0] | _shader->_ptr_spec[i]._dep[1])) { - const Shader::ShaderPtrSpec& _ptr = _shader->_ptr_spec[i]; - Shader::ShaderPtrData* ptr_data = - const_cast< Shader::ShaderPtrData*>(_glgsg->fetch_ptr_parameter(_ptr)); + // We have no way to track modifications to PTAs, so we assume that + // they are modified every frame and when we switch ShaderAttribs. + if (altered & (Shader::SSD_shaderinputs | Shader::SSD_frame)) { + // Iterate through _ptr parameters + for (int i = 0; i < (int)_shader->_ptr_spec.size(); ++i) { + Shader::ShaderPtrSpec &spec = _shader->_ptr_spec[i]; + const Shader::ShaderPtrData *ptr_data =_glgsg->fetch_ptr_parameter(spec); if (ptr_data == NULL){ //the input is not contained in ShaderPtrData release_resources(); return; } - //check if the data must be shipped to the GPU - /*if (!ptr_data->_updated) - continue; - ptr_data->_updated = false;*/ //Check if the size of the shader input and ptr_data match - int input_size = _ptr._dim[0] * _ptr._dim[1] * _ptr._dim[2]; + int input_size = spec._dim[0] * spec._dim[1] * spec._dim[2]; // dimension is negative only if the parameter had the (deprecated)k_ prefix. - if ((input_size > ptr_data->_size) && (_ptr._dim[0] > 0)) { - GLCAT.error() << _ptr._id._name << ": incorrect number of elements, expected " + if ((input_size > ptr_data->_size) && (spec._dim[0] > 0)) { + GLCAT.error() << spec._id._name << ": incorrect number of elements, expected " << input_size <<" got " << ptr_data->_size << "\n"; release_resources(); return; } - CGparameter p = _cg_parameter_map[_ptr._id._seqno]; + CGparameter p = _cg_parameter_map[spec._id._seqno]; switch (ptr_data->_type) { case Shader::SPT_float: - switch(_ptr._info._class) { + switch (spec._info._class) { case Shader::SAC_scalar: cgSetParameter1fv(p, (float*)ptr_data->_ptr); continue; case Shader::SAC_vector: - switch (_ptr._info._type) { + switch (spec._info._type) { case Shader::SAT_vec1: cgSetParameter1fv(p, (float*)ptr_data->_ptr); continue; @@ -479,22 +556,22 @@ issue_parameters(int altered) { continue; case Shader::SAC_array: - switch (_ptr._info._subclass) { + switch (spec._info._subclass) { case Shader::SAC_scalar: - cgGLSetParameterArray1f(p, 0, _ptr._dim[0], (float*)ptr_data->_ptr); + cgGLSetParameterArray1f(p, 0, spec._dim[0], (float*)ptr_data->_ptr); continue; case Shader::SAC_vector: - switch (_ptr._dim[2]) { - case 1: cgGLSetParameterArray1f(p, 0, _ptr._dim[0], (float*)ptr_data->_ptr); continue; - case 2: cgGLSetParameterArray2f(p, 0, _ptr._dim[0], (float*)ptr_data->_ptr); continue; - case 3: cgGLSetParameterArray3f(p, 0, _ptr._dim[0], (float*)ptr_data->_ptr); continue; - case 4: cgGLSetParameterArray4f(p, 0, _ptr._dim[0], (float*)ptr_data->_ptr); continue; + switch (spec._dim[2]) { + case 1: cgGLSetParameterArray1f(p, 0, spec._dim[0], (float*)ptr_data->_ptr); continue; + case 2: cgGLSetParameterArray2f(p, 0, spec._dim[0], (float*)ptr_data->_ptr); continue; + case 3: cgGLSetParameterArray3f(p, 0, spec._dim[0], (float*)ptr_data->_ptr); continue; + case 4: cgGLSetParameterArray4f(p, 0, spec._dim[0], (float*)ptr_data->_ptr); continue; default: - nassertd(_ptr._dim[2] > 0 && _ptr._dim[2] <= 4) continue; + nassertd(spec._dim[2] > 0 && spec._dim[2] <= 4) continue; } continue; case Shader::SAC_matrix: - cgGLSetMatrixParameterArrayfc(p, 0, _ptr._dim[0], (float*)ptr_data->_ptr); + cgGLSetMatrixParameterArrayfc(p, 0, spec._dim[0], (float*)ptr_data->_ptr); continue; default: nassertd(false) continue; @@ -504,13 +581,13 @@ issue_parameters(int altered) { } case Shader::SPT_double: - switch(_ptr._info._class) { + switch (spec._info._class) { case Shader::SAC_scalar: cgSetParameter1dv(p, (double*)ptr_data->_ptr); continue; case Shader::SAC_vector: - switch (_ptr._info._type) { + switch (spec._info._type) { case Shader::SAT_vec1: cgSetParameter1dv(p, (double*)ptr_data->_ptr); continue; @@ -533,22 +610,22 @@ issue_parameters(int altered) { continue; case Shader::SAC_array: - switch (_ptr._info._subclass) { + switch (spec._info._subclass) { case Shader::SAC_scalar: - cgGLSetParameterArray1d(p, 0, _ptr._dim[0], (double*)ptr_data->_ptr); + cgGLSetParameterArray1d(p, 0, spec._dim[0], (double*)ptr_data->_ptr); continue; case Shader::SAC_vector: - switch (_ptr._dim[2]) { - case 1: cgGLSetParameterArray1d(p, 0, _ptr._dim[0], (double*)ptr_data->_ptr); continue; - case 2: cgGLSetParameterArray2d(p, 0, _ptr._dim[0], (double*)ptr_data->_ptr); continue; - case 3: cgGLSetParameterArray3d(p, 0, _ptr._dim[0], (double*)ptr_data->_ptr); continue; - case 4: cgGLSetParameterArray4d(p, 0, _ptr._dim[0], (double*)ptr_data->_ptr); continue; + switch (spec._dim[2]) { + case 1: cgGLSetParameterArray1d(p, 0, spec._dim[0], (double*)ptr_data->_ptr); continue; + case 2: cgGLSetParameterArray2d(p, 0, spec._dim[0], (double*)ptr_data->_ptr); continue; + case 3: cgGLSetParameterArray3d(p, 0, spec._dim[0], (double*)ptr_data->_ptr); continue; + case 4: cgGLSetParameterArray4d(p, 0, spec._dim[0], (double*)ptr_data->_ptr); continue; default: - nassertd(_ptr._dim[2] > 0 && _ptr._dim[2] <= 4) continue; + nassertd(spec._dim[2] > 0 && spec._dim[2] <= 4) continue; } continue; case Shader::SAC_matrix: - cgGLSetMatrixParameterArraydc(p, 0, _ptr._dim[0], (double*)ptr_data->_ptr); + cgGLSetMatrixParameterArraydc(p, 0, spec._dim[0], (double*)ptr_data->_ptr); continue; default: nassertd(false) continue; @@ -559,12 +636,12 @@ issue_parameters(int altered) { continue; case Shader::SPT_int: - switch(_ptr._info._class) { + switch (spec._info._class) { case Shader::SAC_scalar: cgSetParameter1iv(p, (int*)ptr_data->_ptr); continue; case Shader::SAC_vector: - switch(_ptr._info._type) { + switch (spec._info._type) { case Shader::SAT_vec1: cgSetParameter1iv(p, (int*)ptr_data->_ptr); continue; case Shader::SAT_vec2: cgSetParameter2iv(p, (int*)ptr_data->_ptr); continue; case Shader::SAT_vec3: cgSetParameter3iv(p, (int*)ptr_data->_ptr); continue; @@ -576,21 +653,27 @@ issue_parameters(int altered) { nassertd(false) continue; } default: - GLCAT.error() << _ptr._id._name << ":" << "unrecognized parameter type\n"; + GLCAT.error() << spec._id._name << ":" << "unrecognized parameter type\n"; release_resources(); return; } } } - for (int i=0; i<(int)_shader->_mat_spec.size(); i++) { - if (altered & (_shader->_mat_spec[i]._dep[0] | _shader->_mat_spec[i]._dep[1])) { - const LMatrix4 *val = _glgsg->fetch_specified_value(_shader->_mat_spec[i], altered); + if (altered & _shader->_mat_deps) { + for (int i = 0; i < (int)_shader->_mat_spec.size(); ++i) { + Shader::ShaderMatSpec &spec = _shader->_mat_spec[i]; + + if ((altered & (spec._dep[0] | spec._dep[1])) == 0) { + continue; + } + + const LMatrix4 *val = _glgsg->fetch_specified_value(spec, altered); if (!val) continue; const PN_stdfloat *data = val->get_data(); - CGparameter p = _cg_parameter_map[_shader->_mat_spec[i]._id._seqno]; - switch (_shader->_mat_spec[i]._piece) { + CGparameter p = _cg_parameter_map[spec._id._seqno]; + switch (spec._piece) { case Shader::SMP_whole: GLfc(cgGLSetMatrixParameter)(p, data); continue; case Shader::SMP_transpose: GLfr(cgGLSetMatrixParameter)(p, data); continue; case Shader::SMP_col0: GLf(cgGLSetParameter4)(p, data[0], data[4], data[ 8], data[12]); continue; @@ -981,9 +1064,9 @@ disable_shader_texture_bindings() { //////////////////////////////////////////////////////////////////// void CLP(CgShaderContext):: update_shader_texture_bindings(ShaderContext *prev) { - if (prev) { - prev->disable_shader_texture_bindings(); - } + //if (prev) { + // prev->disable_shader_texture_bindings(); + //} if (!valid()) { return; diff --git a/panda/src/glstuff/glCgShaderContext_src.h b/panda/src/glstuff/glCgShaderContext_src.h index da1f0bea78..fb64d37bac 100644 --- a/panda/src/glstuff/glCgShaderContext_src.h +++ b/panda/src/glstuff/glCgShaderContext_src.h @@ -38,19 +38,23 @@ public: ALLOC_DELETED_CHAIN(CLP(CgShaderContext)); INLINE bool valid(void); - void bind(bool reissue_parameters = true); - void unbind(); - void issue_parameters(int altered); + void bind() OVERRIDE; + void unbind() OVERRIDE; + + void set_state_and_transform(const RenderState *state, + const TransformState *modelview_transform, + const TransformState *projection_transform); + + void issue_parameters(int altered) OVERRIDE; void update_transform_table(const TransformTable *table); void update_slider_table(const SliderTable *table); - void disable_shader_vertex_arrays(); - bool update_shader_vertex_arrays(ShaderContext *prev, bool force); - void disable_shader_texture_bindings(); - void update_shader_texture_bindings(ShaderContext *prev); + void disable_shader_vertex_arrays() OVERRIDE; + bool update_shader_vertex_arrays(ShaderContext *prev, bool force) OVERRIDE; + void disable_shader_texture_bindings() OVERRIDE; + void update_shader_texture_bindings(ShaderContext *prev) OVERRIDE; INLINE bool uses_standard_vertex_arrays(void); INLINE bool uses_custom_vertex_arrays(void); - INLINE bool uses_custom_texture_bindings(void); // Special values for location to indicate conventional attrib slots. enum ConventionalAttrib { @@ -74,6 +78,11 @@ private: pvector _cg_parameter_map; + CPT(RenderState) _state_rs; + CPT(TransformState) _modelview_transform; + CPT(TransformState) _projection_transform; + GLint _frame_number; + CLP(GraphicsStateGuardian) *_glgsg; bool _has_divisor; diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index e440ecb988..78ecf91bb1 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -307,7 +307,7 @@ rebuild_bitplanes() { RenderTexturePlane plane = rt._plane; Texture *tex = rt._texture; - if (rtm_mode == RTM_bind_layered) { + if (rtm_mode == RTM_bind_layered && glgsg->_supports_geometry_shaders) { if (tex->get_z_size() != _rb_size_z) { GLCAT.warning() << "All textures attached to layered FBO should have the same layer count!\n"; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index bfc5914b03..5fc640cce7 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1527,11 +1527,15 @@ reset() { _glVertexAttribLPointer = NULL; #endif -#ifndef OPENGLES_1 // We need to have a default shader to apply in case // something didn't happen to have a shader applied, or // if it failed to compile. This default shader just outputs // a red color, indicating that something went wrong. +#ifndef SUPPORT_FIXED_FUNCTION + if (_default_shader == NULL) { + _default_shader = Shader::make(Shader::SL_GLSL, default_vshader, default_fshader); + } +#elif !defined(OPENGLES) if (_default_shader == NULL && core_profile) { _default_shader = Shader::make(Shader::SL_GLSL, default_vshader, default_fshader); } @@ -2926,6 +2930,11 @@ clear_before_callback() { #ifndef OPENGLES if (_supports_sampler_objects) { _glBindSampler(0, 0); + + if (GLCAT.is_spam()) { + GLCAT.spam() + << "glBindSampler(0, 0)\n"; + } } #endif } @@ -5548,6 +5557,11 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z, if (new_image && gtc->_immutable) { gtc->reset_data(); glBindTexture(target, gtc->_index); + + if (GLCAT.is_spam()) { + GLCAT.spam() + << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n"; + } } #ifndef OPENGLES @@ -5844,12 +5858,6 @@ do_issue_transform() { #endif _transform_stale = false; -#ifndef OPENGLES_1 - if (_current_shader_context) { - _current_shader_context->issue_parameters(Shader::SSD_transform); - } -#endif - report_my_gl_errors(); } @@ -5885,9 +5893,9 @@ do_issue_shade_model() { // Description: //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: -do_issue_shader(bool state_has_changed) { +do_issue_shader() { ShaderContext *context = 0; - Shader *shader = (Shader *)(_target_shader->get_shader()); + Shader *shader = (Shader *)_target_shader->get_shader(); #ifndef SUPPORT_FIXED_FUNCTION // If we don't have a shader, apply the default shader. @@ -5919,18 +5927,13 @@ do_issue_shader(bool state_has_changed) { if (context != _current_shader_context) { // Use a completely different shader than before. // Unbind old shader, bind the new one. - if (_current_shader_context != 0) { + if (_current_shader_context != NULL && + _current_shader->get_language() != shader->get_language()) { _current_shader_context->unbind(); } context->bind(); _current_shader = shader; _current_shader_context = context; - context->issue_parameters(Shader::SSD_shaderinputs); - } else { - if (state_has_changed) { - // Use the same shader as before, but with new input arguments. - context->issue_parameters(Shader::SSD_shaderinputs); - } } } @@ -6410,6 +6413,11 @@ do_issue_blending() { _glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_ZERO, GL_ONE); } + + if (GLCAT.is_spam()) { + GLCAT.spam() << "glBlendEquation(GL_FUNC_ADD)\n"; + GLCAT.spam() << "glBlendFunc(GL_ZERO, GL_ONE)\n"; + } return; } else { set_color_write_mask(color_channels); @@ -6433,16 +6441,23 @@ do_issue_blending() { enable_blend(true); _glBlendEquation(get_blend_equation_type(color_blend_mode)); glBlendFunc(get_blend_func(color_blend->get_operand_a()), - get_blend_func(color_blend->get_operand_b())); + get_blend_func(color_blend->get_operand_b())); + LColor c; if (_color_blend_involves_color_scale) { // Apply the current color scale to the blend mode. - _glBlendColor(_current_color_scale[0], _current_color_scale[1], - _current_color_scale[2], _current_color_scale[3]); - + c = _current_color_scale; } else { - LColor c = color_blend->get_color(); - _glBlendColor(c[0], c[1], c[2], c[3]); + c = color_blend->get_color(); + } + + _glBlendColor(c[0], c[1], c[2], c[3]); + + if (GLCAT.is_spam()) { + GLCAT.spam() << "glBlendEquation(" << color_blend_mode << ")\n"; + GLCAT.spam() << "glBlendFunc(" << color_blend->get_operand_a() + << color_blend->get_operand_b() << ")\n"; + GLCAT.spam() << "glBlendColor(" << c << ")\n"; } return; } @@ -6460,6 +6475,11 @@ do_issue_blending() { enable_blend(true); _glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if (GLCAT.is_spam()) { + GLCAT.spam() << "glBlendEquation(GL_FUNC_ADD)\n"; + GLCAT.spam() << "glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)\n"; + } return; case TransparencyAttrib::M_multisample: @@ -6489,6 +6509,11 @@ do_issue_blending() { enable_blend(true); _glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if (GLCAT.is_spam()) { + GLCAT.spam() << "glBlendEquation(GL_FUNC_ADD)\n"; + GLCAT.spam() << "glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)\n"; + } return; } @@ -9224,10 +9249,27 @@ set_state_and_transform(const RenderState *target, } _target_rs = target; +#ifndef OPENGLES_1 _target_shader = (const ShaderAttrib *) _target_rs->get_attrib_def(ShaderAttrib::get_class_slot()); -#ifndef OPENGLES_1 _instance_count = _target_shader->get_instance_count(); + + if (_target_shader != _state_shader) { + //PStatGPUTimer timer(this, _draw_set_state_shader_pcollector); + do_issue_shader(); + _state_shader = _target_shader; + _state_mask.clear_bit(TextureAttrib::get_class_slot()); + } +#ifndef SUPPORT_FIXED_FUNCTION + else { // In the case of OpenGL ES 2.x, we need to glUseShader before we draw anything. + do_issue_shader(); + _state_mask.clear_bit(TextureAttrib::get_class_slot()); + } +#endif + + if (_current_shader_context != NULL) { + _current_shader_context->set_state_and_transform(target, transform, _projection_mat); + } #endif #ifdef SUPPORT_FIXED_FUNCTION @@ -9256,11 +9298,6 @@ set_state_and_transform(const RenderState *target, //PStatGPUTimer timer(this, _draw_set_state_clip_plane_pcollector); do_issue_clip_plane(); _state_mask.set_bit(clip_plane_slot); -#ifndef OPENGLES_1 - if (_current_shader_context) { - _current_shader_context->issue_parameters(Shader::SSD_clip_planes); - } -#endif } int color_slot = ColorAttrib::get_class_slot(); @@ -9274,12 +9311,6 @@ set_state_and_transform(const RenderState *target, do_issue_color_scale(); _state_mask.set_bit(color_slot); _state_mask.set_bit(color_scale_slot); -#ifndef OPENGLES_1 - if (_current_shader_context) { - _current_shader_context->issue_parameters(Shader::SSD_color); - _current_shader_context->issue_parameters(Shader::SSD_colorscale); - } -#endif } int cull_face_slot = CullFaceAttrib::get_class_slot(); @@ -9360,20 +9391,6 @@ set_state_and_transform(const RenderState *target, _state_mask.set_bit(color_blend_slot); } - if (_target_shader != _state_shader) { - //PStatGPUTimer timer(this, _draw_set_state_shader_pcollector); -#ifndef OPENGLES_1 - do_issue_shader(true); -#endif - _state_shader = _target_shader; - _state_mask.clear_bit(TextureAttrib::get_class_slot()); - } -#ifndef SUPPORT_FIXED_FUNCTION - else { // In the case of OpenGL ES 2.x, we need to glUseShader before we draw anything. - do_issue_shader(false); - } -#endif - int texture_slot = TextureAttrib::get_class_slot(); if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) || !_state_mask.get_bit(texture_slot)) { @@ -9441,11 +9458,6 @@ set_state_and_transform(const RenderState *target, do_issue_material(); #endif _state_mask.set_bit(material_slot); -#ifndef OPENGLES_1 - if (_current_shader_context) { - _current_shader_context->issue_parameters(Shader::SSD_material); - } -#endif } int light_slot = LightAttrib::get_class_slot(); @@ -9456,11 +9468,6 @@ set_state_and_transform(const RenderState *target, do_issue_light(); #endif _state_mask.set_bit(light_slot); -#ifndef OPENGLES_1 - if (_current_shader_context) { - _current_shader_context->issue_parameters(Shader::SSD_light); - } -#endif } int stencil_slot = StencilAttrib::get_class_slot(); @@ -9479,11 +9486,6 @@ set_state_and_transform(const RenderState *target, do_issue_fog(); #endif _state_mask.set_bit(fog_slot); -#ifndef OPENGLES_1 - if (_current_shader_context) { - _current_shader_context->issue_parameters(Shader::SSD_fog); - } -#endif } int scissor_slot = ScissorAttrib::get_class_slot(); @@ -9528,7 +9530,7 @@ do_issue_texture() { #ifdef OPENGLES_1 update_standard_texture_bindings(); #else - if (_current_shader_context == 0 || !_current_shader_context->uses_custom_texture_bindings()) { + if (_current_shader_context == 0) { // No shader, or a non-Cg shader. if (_texture_binding_shader_context != 0) { _texture_binding_shader_context->disable_shader_texture_bindings(); @@ -9909,9 +9911,9 @@ update_show_usage_texture_bindings(int show_stage_index) { UsageTextureKey key(texture->get_x_size(), texture->get_y_size()); UsageTextures::iterator ui = _usage_textures.find(key); + GLuint index; if (ui == _usage_textures.end()) { // Need to create a new texture for this size. - GLuint index; glGenTextures(1, &index); glBindTexture(GL_TEXTURE_2D, index); //TODO: this could be a lot simpler with glTexStorage2D @@ -9921,10 +9923,15 @@ update_show_usage_texture_bindings(int show_stage_index) { } else { // Just bind the previously-created texture. - GLuint index = (*ui).second; + index = (*ui).second; glBindTexture(GL_TEXTURE_2D, index); } + if (GLCAT.is_spam()) { + GLCAT.spam() + << "glBindTexture(GL_TEXTURE_2D, " << index << ")\n"; + } + //TODO: glBindSampler(0) ? } @@ -10468,9 +10475,14 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) { #endif #ifndef OPENGLES - glTexParameterf(target, GL_TEXTURE_MIN_LOD, sampler.get_min_lod()); - glTexParameterf(target, GL_TEXTURE_MAX_LOD, sampler.get_max_lod()); - glTexParameterf(target, GL_TEXTURE_LOD_BIAS, sampler.get_lod_bias()); + if (is_at_least_gl_version(1, 2)) { + glTexParameterf(target, GL_TEXTURE_MIN_LOD, sampler.get_min_lod()); + glTexParameterf(target, GL_TEXTURE_MAX_LOD, sampler.get_max_lod()); + + if (is_at_least_gl_version(1, 4)) { + glTexParameterf(target, GL_TEXTURE_LOD_BIAS, sampler.get_lod_bias()); + } + } #endif report_my_gl_errors(); @@ -10505,7 +10517,12 @@ apply_texture(CLP(TextureContext) *gtc) { gtc->reset_data(); gtc->_target = target; } + glBindTexture(target, gtc->_index); + if (GLCAT.is_spam()) { + GLCAT.spam() + << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n"; + } report_my_gl_errors(); return true; @@ -10537,8 +10554,8 @@ apply_sampler(GLuint unit, const SamplerState &sampler, CLP(TextureContext) *gtc _glBindSampler(unit, gsc->_index); if (GLCAT.is_spam()) { - GLCAT.spam() - << "bind " << unit << " " << sampler << "\n"; + GLCAT.spam() << "glBindSampler(" << unit << ", " + << gsc->_index << "): " << sampler << "\n"; } } else @@ -10791,6 +10808,11 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { GLCAT.warning() << "Attempt to modify texture with immutable storage, recreating texture.\n"; gtc->reset_data(); glBindTexture(target, gtc->_index); + + if (GLCAT.is_spam()) { + GLCAT.spam() + << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n"; + } } #ifndef OPENGLES @@ -11045,6 +11067,8 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { gtc->update_data_size_bytes(get_texture_memory_size(tex)); } + nassertr(gtc->_has_storage, false); + if (tex->get_post_load_store_cache()) { tex->set_post_load_store_cache(false); // OK, get the RAM image, and save it in a BamCache record. @@ -11752,6 +11776,10 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { #endif glBindTexture(target, gtc->_index); + if (GLCAT.is_spam()) { + GLCAT.spam() + << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n"; + } Texture *tex = gtc->get_texture(); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index f38dd5326c..52845621a6 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -399,7 +399,7 @@ protected: void do_issue_depth_offset(); void do_issue_shade_model(); #ifndef OPENGLES_1 - void do_issue_shader(bool state_has_changed = false); + void do_issue_shader(); #endif #ifdef SUPPORT_FIXED_FUNCTION void do_issue_material(); @@ -462,8 +462,10 @@ protected: INLINE void enable_stencil_test(bool val); INLINE void enable_blend(bool val); INLINE void enable_depth_test(bool val); +#ifdef SUPPORT_FIXED_FUNCTION INLINE void enable_fog(bool val); INLINE void enable_alpha_test(bool val); +#endif INLINE void enable_polygon_offset(bool val); INLINE void set_color_write_mask(int mask); diff --git a/panda/src/glstuff/glShaderContext_src.I b/panda/src/glstuff/glShaderContext_src.I index c3424b8cca..d95671510f 100644 --- a/panda/src/glstuff/glShaderContext_src.I +++ b/panda/src/glstuff/glShaderContext_src.I @@ -55,13 +55,3 @@ INLINE bool CLP(ShaderContext):: uses_custom_vertex_arrays() { return true; } - -//////////////////////////////////////////////////////////////////// -// Function: GLShaderContext::uses_custom_texture_bindings -// Access: Public -// Description: Always true, for now. -//////////////////////////////////////////////////////////////////// -INLINE bool CLP(ShaderContext):: -uses_custom_texture_bindings() { - return true; -} diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 4602f60e7a..49eb12221a 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -18,17 +18,15 @@ #include "pStatGPUTimer.h" -TypeHandle CLP(ShaderContext)::_type_handle; +#include "colorAttrib.h" +#include "colorScaleAttrib.h" +#include "materialAttrib.h" +#include "shaderAttrib.h" +#include "fogAttrib.h" +#include "lightAttrib.h" +#include "clipPlaneAttrib.h" -#ifndef GL_GEOMETRY_SHADER_EXT -#define GL_GEOMETRY_SHADER_EXT 0x8DD9 -#endif -#ifndef GL_GEOMETRY_VERTICES_OUT_EXT -#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA -#endif -#ifndef GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT -#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 -#endif +TypeHandle CLP(ShaderContext)::_type_handle; //////////////////////////////////////////////////////////////////// // Function: GLShaderContext::ParseAndSetShaderUniformVars @@ -228,6 +226,7 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, GLenum param_t objShader->cp_optimize_mat_spec(bind); objShader->_mat_spec.push_back(bind); + objShader->_mat_deps |= bind._dep[0] | bind._dep[1]; if (param_size > 1) { // We support arrays of rows and arrays of columns, so we can @@ -338,8 +337,14 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext reflect_attribute(i, name_buffer, name_buflen); } - _glgsg->_glUseProgram(0); _glgsg->report_my_gl_errors(); + + // Restore the active shader. + if (_glgsg->_current_shader_context == NULL) { + _glgsg->_glUseProgram(0); + } else { + _glgsg->_current_shader_context->bind(); + } } //////////////////////////////////////////////////////////////////// @@ -715,8 +720,6 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { } bind._arg[0] = NULL; bind._arg[1] = NULL; - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; if (matrix_name == "ModelViewProjectionMatrix") { if (inverse) { @@ -802,7 +805,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n"; return; } + _shader->cp_optimize_mat_spec(bind); _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0] | bind._dep[1]; return; } if (size > 7 && noprefix.substr(0, 7) == "Texture") { @@ -846,6 +851,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { } bind._piece = Shader::SMP_row0; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; return; } else if (noprefix == "Material.diffuse") { @@ -855,6 +861,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { } bind._piece = Shader::SMP_row1; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; return; } else if (noprefix == "Material.emission") { @@ -864,6 +871,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { } bind._piece = Shader::SMP_row2; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; return; } else if (noprefix == "Material.specular") { @@ -873,6 +881,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { } bind._piece = Shader::SMP_row3x3; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; return; } else if (noprefix == "Material.shininess") { @@ -882,6 +891,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { } bind._piece = Shader::SMP_cell15; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; return; } } @@ -906,6 +916,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { return; } _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; return; } if (noprefix == "Color") { @@ -929,6 +940,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { return; } _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; return; } if (noprefix == "ClipPlane") { @@ -951,6 +963,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._arg[1] = NULL; bind._dep[1] = Shader::SSD_NONE; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; } return; } @@ -975,6 +988,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { return; } _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; return; } if (noprefix == "TransformTable") { @@ -1016,8 +1030,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._part[0] = Shader::SMO_world_to_view; bind._part[1] = Shader::SMO_view_to_apiview; bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_general; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0] | bind._dep[1]; return; } else if (noprefix == "InverseViewMatrix" || noprefix == "ViewMatrixInverse") { @@ -1025,9 +1040,10 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._func = Shader::SMF_compose; bind._part[0] = Shader::SMO_apiview_to_view; bind._part[1] = Shader::SMO_view_to_world; - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[0] = Shader::SSD_general; bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0] | bind._dep[1]; return; } else if (noprefix == "FrameTime") { @@ -1035,9 +1051,10 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._func = Shader::SMF_first; bind._part[0] = Shader::SMO_frame_time; bind._part[1] = Shader::SMO_identity; - bind._dep[0] = Shader::SSD_general; + bind._dep[0] = Shader::SSD_general | Shader::SSD_frame; bind._dep[1] = Shader::SSD_NONE; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0] | bind._dep[1]; return; } else if (noprefix == "DeltaFrameTime") { @@ -1045,9 +1062,10 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._func = Shader::SMF_first; bind._part[0] = Shader::SMO_frame_delta; bind._part[1] = Shader::SMO_identity; - bind._dep[0] = Shader::SSD_general; + bind._dep[0] = Shader::SSD_general | Shader::SSD_frame; bind._dep[1] = Shader::SSD_NONE; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0] | bind._dep[1]; return; } else if (noprefix == "FrameNumber") { @@ -1124,11 +1142,12 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._func = Shader::SMF_first; bind._part[0] = Shader::SMO_mat_constant_x; bind._arg[0] = InternalName::make(param_name); - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame; bind._part[1] = Shader::SMO_identity; bind._arg[1] = NULL; bind._dep[1] = Shader::SSD_NONE; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; return; } case GL_FLOAT_MAT4: { @@ -1138,11 +1157,12 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._func = Shader::SMF_first; bind._part[0] = Shader::SMO_mat_constant_x; bind._arg[0] = InternalName::make(param_name); - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame; bind._part[1] = Shader::SMO_identity; bind._arg[1] = NULL; bind._dep[1] = Shader::SSD_NONE; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; return; } case GL_FLOAT: @@ -1172,11 +1192,12 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._func = Shader::SMF_first; bind._part[0] = Shader::SMO_vec_constant_x_attrib; bind._arg[0] = iname; - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame; bind._part[1] = Shader::SMO_identity; bind._arg[1] = NULL; bind._dep[1] = Shader::SSD_NONE; _shader->_mat_spec.push_back(bind); + _shader->_mat_deps |= bind._dep[0]; return; } // else fall through } @@ -1228,7 +1249,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { } bind._arg = InternalName::make(param_name); bind._dim[0] = 1; - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame; bind._dep[1] = Shader::SSD_NONE; _shader->_ptr_spec.push_back(bind); return; @@ -1335,7 +1356,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { } bind._arg = InternalName::make(param_name); bind._dim[0] = param_size; - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame; bind._dep[1] = Shader::SSD_NONE; _shader->_ptr_spec.push_back(bind); return; @@ -1507,23 +1528,22 @@ release_resources() { // input parameters. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -bind(bool reissue_parameters) { - // GLSL shaders need to be bound before passing parameters. - if (!_shader->get_error_flag()) { - _glgsg->_glUseProgram(_glsl_program); - } - - if (reissue_parameters) { - // Pass in k-parameters and transform-parameters - issue_parameters(Shader::SSD_general); - } - +bind() { if (!_validated) { _glgsg->_glValidateProgram(_glsl_program); glsl_report_program_errors(_glsl_program, false); _validated = true; } + if (!_shader->get_error_flag()) { + _glgsg->_glUseProgram(_glsl_program); + } + + if (GLCAT.is_spam()) { + GLCAT.spam() << "glUseProgram(" << _glsl_program << "): " + << _shader->get_filename() << "\n"; + } + _glgsg->report_my_gl_errors(); } @@ -1534,10 +1554,92 @@ bind(bool reissue_parameters) { //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: unbind() { + if (GLCAT.is_spam()) { + GLCAT.spam() << "glUseProgram(0)\n"; + } + _glgsg->_glUseProgram(0); _glgsg->report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: GLShaderContext::set_state_and_transform +// Access: Public +// Description: This function gets called whenever the RenderState +// or TransformState has changed, but the Shader +// itself has not changed. It loads new values into the +// shader's parameters. +//////////////////////////////////////////////////////////////////// +void CLP(ShaderContext):: +set_state_and_transform(const RenderState *target_rs, + const TransformState *modelview_transform, + const TransformState *projection_transform) { + + // Find out which state properties have changed. + int altered = 0; + + if (_modelview_transform != modelview_transform) { + _modelview_transform = modelview_transform; + altered |= Shader::SSD_transform; + } + if (_projection_transform != projection_transform) { + _projection_transform = projection_transform; + altered |= Shader::SSD_projection; + } + + if (_state_rs != target_rs) { + if (_state_rs == NULL) { + // We haven't set any state yet. + altered |= Shader::SSD_general; + } else { + if (_state_rs->get_attrib(ColorAttrib::get_class_slot()) != + target_rs->get_attrib(ColorAttrib::get_class_slot())) { + altered |= Shader::SSD_color; + } + if (_state_rs->get_attrib(ColorScaleAttrib::get_class_slot()) != + target_rs->get_attrib(ColorScaleAttrib::get_class_slot())) { + altered |= Shader::SSD_colorscale; + } + if (_state_rs->get_attrib(MaterialAttrib::get_class_slot()) != + target_rs->get_attrib(MaterialAttrib::get_class_slot())) { + altered |= Shader::SSD_material; + } + if (_state_rs->get_attrib(ShaderAttrib::get_class_slot()) != + target_rs->get_attrib(ShaderAttrib::get_class_slot())) { + altered |= Shader::SSD_shaderinputs; + } + if (_state_rs->get_attrib(FogAttrib::get_class_slot()) != + target_rs->get_attrib(FogAttrib::get_class_slot())) { + altered |= Shader::SSD_fog; + } + if (_state_rs->get_attrib(LightAttrib::get_class_slot()) != + target_rs->get_attrib(LightAttrib::get_class_slot())) { + altered |= Shader::SSD_light; + } + if (_state_rs->get_attrib(ClipPlaneAttrib::get_class_slot()) != + target_rs->get_attrib(ClipPlaneAttrib::get_class_slot())) { + altered |= Shader::SSD_clip_planes; + } + if (_state_rs->get_attrib(TexMatrixAttrib::get_class_slot()) != + target_rs->get_attrib(TexMatrixAttrib::get_class_slot())) { + altered |= Shader::SSD_tex_matrix; + } + } + _state_rs = target_rs; + } + + // Is this the first time this shader is used this frame? + int frame_number = ClockObject::get_global_clock()->get_frame_count(); + if (frame_number != _frame_number) { + altered |= Shader::SSD_frame; + _frame_number = frame_number; + } + + if (altered != 0) { + issue_parameters(altered); + } +} + //////////////////////////////////////////////////////////////////// // Function: GLShaderContext::issue_parameters // Access: Public @@ -1545,35 +1647,30 @@ unbind() { // or TransformState has changed, but the Shader // itself has not changed. It loads new values into the // shader's parameters. -// -// If "altered" is false, that means you promise that -// the parameters for this shader context have already -// been issued once, and that since the last time the -// parameters were issued, no part of the render -// state has changed except the external and internal -// transforms. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: issue_parameters(int altered) { - //PStatGPUTimer timer(_glgsg, _glgsg->_draw_set_state_shader_parameters_pcollector); + PStatGPUTimer timer(_glgsg, _glgsg->_draw_set_state_shader_parameters_pcollector); - if (!valid()) { - return; + if (GLCAT.is_spam()) { + GLCAT.spam() + << "Setting uniforms for " << _shader->get_filename() + << " (altered 0x" << hex << altered << dec << ")\n"; } - if (_frame_number_loc != -1) { - int current_frame = ClockObject::get_global_clock()->get_frame_count(); - if (current_frame != _frame_number) { - _glgsg->_glUniform1i(_frame_number_loc, current_frame); - _frame_number = current_frame; + // We have no way to track modifications to PTAs, so we assume that + // they are modified every frame and when we switch ShaderAttribs. + if (altered & (Shader::SSD_shaderinputs | Shader::SSD_frame)) { + + // If we have an osg_FrameNumber input, set it now. + if ((altered | Shader::SSD_frame) != 0 && _frame_number_loc >= 0) { + _glgsg->_glUniform1i(_frame_number_loc, _frame_number); } - } - // Iterate through _ptr parameters - for (int i = 0; i < (int)_shader->_ptr_spec.size(); ++i) { - Shader::ShaderPtrSpec &spec = _shader->_ptr_spec[i]; + // Iterate through _ptr parameters + for (int i = 0; i < (int)_shader->_ptr_spec.size(); ++i) { + Shader::ShaderPtrSpec &spec = _shader->_ptr_spec[i]; - if (altered & (spec._dep[0] | spec._dep[1])) { const Shader::ShaderPtrData* ptr_data = _glgsg->fetch_ptr_parameter(spec); if (ptr_data == NULL) { //the input is not contained in ShaderPtrData release_resources(); @@ -1657,10 +1754,14 @@ issue_parameters(int altered) { } } - for (int i = 0; i < (int)_shader->_mat_spec.size(); ++i) { - Shader::ShaderMatSpec &spec = _shader->_mat_spec[i]; + if (altered & _shader->_mat_deps) { + for (int i = 0; i < (int)_shader->_mat_spec.size(); ++i) { + Shader::ShaderMatSpec &spec = _shader->_mat_spec[i]; + + if ((altered & (spec._dep[0] | spec._dep[1])) == 0) { + continue; + } - if (altered & (spec._dep[0] | spec._dep[1])) { const LMatrix4 *val = _glgsg->fetch_specified_value(spec, altered); if (!val) continue; #ifndef STDFLOAT_DOUBLE @@ -1814,12 +1915,12 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { return true; } -#ifdef SUPPORT_IMMEDIATE_MODE - if (_glgsg->_use_sender) { - GLCAT.error() << "immediate mode shaders not implemented yet\n"; - } else -#endif // SUPPORT_IMMEDIATE_MODE - { + if (valid()) { + // Get the active ColorAttrib. We'll need it to determine how to + // apply vertex colors. + const ColorAttrib *color_attrib; + _state_rs->get_attrib_def(color_attrib); + const GeomVertexArrayDataHandle *array_reader; Geom::NumericType numeric_type; int start, stride, num_values; @@ -1845,7 +1946,7 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { // Don't apply vertex colors if they are disabled with a ColorAttrib. int num_elements, element_stride, divisor; bool normalized; - if ((p != _color_attrib_index || _glgsg->_vertex_colors_enabled) && + if ((p != _color_attrib_index || color_attrib->get_type() == ColorAttrib::T_vertex) && _glgsg->_data_reader->get_array_info(name, array_reader, num_values, numeric_type, normalized, start, stride, divisor, @@ -1891,9 +1992,9 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { if (p == _color_attrib_index) { // Vertex colors are disabled or not present. Apply flat color. #if defined(STDFLOAT_DOUBLE) && !defined(OPENGLES) - _glgsg->_glVertexAttrib4dv(p, _glgsg->_scene_graph_color.get_data()); + _glgsg->_glVertexAttrib4dv(p, color_attrib->get_color().get_data()); #else - _glgsg->_glVertexAttrib4fv(p, _glgsg->_scene_graph_color.get_data()); + _glgsg->_glVertexAttrib4fv(p, color_attrib->get_color().get_data()); #endif } } @@ -1926,6 +2027,8 @@ disable_shader_texture_bindings() { return; } + DO_PSTATS_STUFF(_glgsg->_texture_state_pcollector.add_level(1)); + for (int i = 0; i < _shader->_tex_spec.size(); ++i) { #ifndef OPENGLES // Check if bindless was used, if so, there's nothing to unbind. @@ -1960,9 +2063,7 @@ disable_shader_texture_bindings() { break; case Texture::TT_3d_texture: -#ifndef OPENGLES_1 glBindTexture(GL_TEXTURE_3D, 0); -#endif break; case Texture::TT_2d_texture_array: @@ -2026,9 +2127,9 @@ disable_shader_texture_bindings() { //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: update_shader_texture_bindings(ShaderContext *prev) { - if (prev) { - prev->disable_shader_texture_bindings(); - } + //if (prev) { + // prev->disable_shader_texture_bindings(); + //} if (!valid()) { return; @@ -2134,8 +2235,10 @@ update_shader_texture_bindings(ShaderContext *prev) { // We get the TextureAttrib directly from the _target_rs, not the // filtered TextureAttrib in _target_texture. - const TextureAttrib *texattrib = DCAST(TextureAttrib, _glgsg->_target_rs->get_attrib_def(TextureAttrib::get_class_slot())); - nassertv(texattrib != (TextureAttrib *)NULL); + const TextureAttrib *texattrib; + _glgsg->_target_rs->get_attrib_def(texattrib); + //const TextureAttrib *texattrib; + //_state_rs->get_attrib_def(TextureAttrib::get_class_slot()); for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) { Shader::ShaderTexSpec &spec = _shader->_tex_spec[i]; diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index cc04500c9d..f6231b8481 100644 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -45,19 +45,23 @@ public: bool get_sampler_texture_type(int &out, GLenum param_type); INLINE bool valid(void); - void bind(bool reissue_parameters = true); + void bind(); void unbind(); + + void set_state_and_transform(const RenderState *state, + const TransformState *modelview_transform, + const TransformState *projection_transform); + void issue_parameters(int altered); void update_transform_table(const TransformTable *table); void update_slider_table(const SliderTable *table); void disable_shader_vertex_arrays(); bool update_shader_vertex_arrays(ShaderContext *prev, bool force); - void disable_shader_texture_bindings(); - void update_shader_texture_bindings(ShaderContext *prev); + void disable_shader_texture_bindings() OVERRIDE; + void update_shader_texture_bindings(ShaderContext *prev) OVERRIDE; INLINE bool uses_standard_vertex_arrays(void); INLINE bool uses_custom_vertex_arrays(void); - INLINE bool uses_custom_texture_bindings(void); private: bool _validated; @@ -65,6 +69,10 @@ private: typedef pvector GLSLShaders; GLSLShaders _glsl_shaders; + CPT(RenderState) _state_rs; + CPT(TransformState) _modelview_transform; + CPT(TransformState) _projection_transform; + //struct ParamContext { // CPT(InternalName) _name; // GLint _location; diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index b20ac8e1b2..57b5882ea7 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -416,7 +416,17 @@ cp_dependency(ShaderMatInput inp) { if ((inp == SMO_model_to_view) || (inp == SMO_view_to_model) || (inp == SMO_model_to_apiview) || - (inp == SMO_apiview_to_model)) { + (inp == SMO_apiview_to_model) || + (inp == SMO_view_to_world) || + (inp == SMO_world_to_view) || + (inp == SMO_view_x_to_view) || + (inp == SMO_view_to_view_x) || + (inp == SMO_apiview_x_to_view) || + (inp == SMO_view_to_apiview_x) || + (inp == SMO_clip_x_to_view) || + (inp == SMO_view_to_clip_x) || + (inp == SMO_apiclip_x_to_view) || + (inp == SMO_view_to_apiclip_x)) { dep |= SSD_transform; } if ((inp == SMO_texpad_x) || @@ -438,6 +448,25 @@ cp_dependency(ShaderMatInput inp) { (inp == SMO_apiclip_x_to_view) || (inp == SMO_view_to_apiclip_x)) { dep |= SSD_shaderinputs; + + if ((inp == SMO_alight_x) || + (inp == SMO_dlight_x) || + (inp == SMO_plight_x) || + (inp == SMO_slight_x) || + (inp == SMO_satten_x) || + (inp == SMO_vec_constant_x_attrib) || + (inp == SMO_view_x_to_view) || + (inp == SMO_view_to_view_x) || + (inp == SMO_apiview_x_to_view) || + (inp == SMO_view_to_apiview_x) || + (inp == SMO_clip_x_to_view) || + (inp == SMO_view_to_clip_x) || + (inp == SMO_apiclip_x_to_view) || + (inp == SMO_view_to_apiclip_x)) { + // We can't track changes to these yet, so we have to assume that + // they are modified every frame. + dep |= SSD_frame; + } } if ((inp == SMO_light_ambient) || (inp == SMO_light_source_i_attrib)) { @@ -455,6 +484,21 @@ cp_dependency(ShaderMatInput inp) { if (inp == SMO_texmat_i || inp == SMO_inv_texmat_i) { dep |= SSD_tex_matrix; } + if ((inp == SMO_window_size) || + (inp == SMO_pixel_size) || + (inp == SMO_frame_number) || + (inp == SMO_frame_time) || + (inp == SMO_frame_delta)) { + dep |= SSD_frame; + } + if ((inp == SMO_clip_to_view) || + (inp == SMO_view_to_clip) || + (inp == SMO_apiclip_to_view) || + (inp == SMO_view_to_apiclip) || + (inp == SMO_apiview_to_apiclip) || + (inp == SMO_apiclip_to_apiview)) { + dep |= SSD_projection; + } return dep; } @@ -857,6 +901,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { } cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -931,6 +976,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -944,6 +990,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -967,6 +1014,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -988,6 +1036,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -1029,6 +1078,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { } cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -1051,6 +1101,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -1072,6 +1123,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -1093,6 +1145,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -1139,6 +1192,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -1195,6 +1249,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { bind._arg[1] = NULL; cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -1215,6 +1270,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { bind._arg[1] = NULL; cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); + _mat_deps |= bind._dep[0] | bind._dep[1]; return true; } @@ -1261,8 +1317,12 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { bind._id = p._id; bind._arg = kinputname; bind._info = p; - bind._dep[0] = SSD_general | SSD_shaderinputs; - bind._dep[1] = SSD_general | SSD_NONE; + + // We specify SSD_frame because a PTA may be modified by the app + // from frame to frame, and we have no way to know. So, we must + // respecify a PTA at least once every frame. + bind._dep[0] = SSD_general | SSD_shaderinputs | SSD_frame; + bind._dep[1] = SSD_NONE; memcpy(bind._dim,arg_dim,sizeof(int)*3); @@ -2050,7 +2110,8 @@ Shader(ShaderLanguage lang) : _parse(0), _loaded(false), _language(lang), - _last_modified(0) + _last_modified(0), + _mat_deps(0) { #ifdef HAVE_CG _cg_vprogram = 0; diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index 33fe43b799..0c2fb79401 100644 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -273,6 +273,8 @@ public: SSD_light = 0x080, SSD_clip_planes = 0x100, SSD_tex_matrix = 0x200, + SSD_frame = 0x400, + SSD_projection = 0x800, }; enum ShaderBug { @@ -529,6 +531,7 @@ public: epvector _mat_spec; pvector _tex_spec; pvector _var_spec; + int _mat_deps; bool _error_flag; ShaderFile _text; diff --git a/panda/src/gobj/shaderContext.h b/panda/src/gobj/shaderContext.h index 5785b155c9..8531966a10 100644 --- a/panda/src/gobj/shaderContext.h +++ b/panda/src/gobj/shaderContext.h @@ -36,8 +36,10 @@ class EXPCL_PANDA_GOBJ ShaderContext: public SavedContext { public: INLINE ShaderContext(Shader *se); + INLINE virtual void set_state_and_transform(const RenderState *, const TransformState *, const TransformState*) {}; + INLINE virtual bool valid() { return false; } - INLINE virtual void bind(bool reissue_parameters = true) {}; + INLINE virtual void bind() {}; INLINE virtual void unbind() {}; INLINE virtual void issue_parameters(int altered) {}; INLINE virtual void disable_shader_vertex_arrays() {}; @@ -47,7 +49,6 @@ public: INLINE virtual bool uses_standard_vertex_arrays(void) { return true; }; INLINE virtual bool uses_custom_vertex_arrays(void) { return false; }; - INLINE virtual bool uses_custom_texture_bindings(void) { return false; }; PUBLISHED: INLINE Shader *get_shader() const; diff --git a/panda/src/pgraph/colorBlendAttrib.h b/panda/src/pgraph/colorBlendAttrib.h index dc2975985f..0de99e04e5 100644 --- a/panda/src/pgraph/colorBlendAttrib.h +++ b/panda/src/pgraph/colorBlendAttrib.h @@ -141,10 +141,9 @@ private: static int _attrib_slot; }; -ostream &operator << (ostream &out, ColorBlendAttrib::Mode mode); -ostream &operator << (ostream &out, ColorBlendAttrib::Operand operand); +EXPCL_PANDA_PGRAPH ostream &operator << (ostream &out, ColorBlendAttrib::Mode mode); +EXPCL_PANDA_PGRAPH ostream &operator << (ostream &out, ColorBlendAttrib::Operand operand); #include "colorBlendAttrib.I" #endif -