Shader context input state tracking system, for more efficiently updating shader inputs

This commit is contained in:
rdb 2015-07-28 16:18:33 +02:00
parent 0cecab3124
commit e4c3301bd0
13 changed files with 519 additions and 242 deletions

View File

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

View File

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

View File

@ -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<CGparameter> _cg_parameter_map;
CPT(RenderState) _state_rs;
CPT(TransformState) _modelview_transform;
CPT(TransformState) _projection_transform;
GLint _frame_number;
CLP(GraphicsStateGuardian) *_glgsg;
bool _has_divisor;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<GLuint> GLSLShaders;
GLSLShaders _glsl_shaders;
CPT(RenderState) _state_rs;
CPT(TransformState) _modelview_transform;
CPT(TransformState) _projection_transform;
//struct ParamContext {
// CPT(InternalName) _name;
// GLint _location;

View File

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

View File

@ -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 <ShaderMatSpec> _mat_spec;
pvector <ShaderTexSpec> _tex_spec;
pvector <ShaderVarSpec> _var_spec;
int _mat_deps;
bool _error_flag;
ShaderFile _text;

View File

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

View File

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