From cb4597ebb84fe7228c7039e2f54c545b63d60046 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 17 Sep 2023 19:12:33 +0200 Subject: [PATCH] shader: Pass built-in array shader input in one go This applies to `p3d_TextureMatrix[]` and `p3d_ClipPlane[]` This is more efficient and also works around Apple driver bugs (like #846) Fixes #883 --- panda/src/glstuff/glCgShaderContext_src.cxx | 2 + panda/src/glstuff/glShaderContext_src.cxx | 44 +++++++-------------- panda/src/gobj/shader.cxx | 4 +- panda/src/gobj/shader.h | 3 ++ 4 files changed, 21 insertions(+), 32 deletions(-) diff --git a/panda/src/glstuff/glCgShaderContext_src.cxx b/panda/src/glstuff/glCgShaderContext_src.cxx index daf671ce04..3f42461c3d 100644 --- a/panda/src/glstuff/glCgShaderContext_src.cxx +++ b/panda/src/glstuff/glCgShaderContext_src.cxx @@ -710,7 +710,9 @@ issue_parameters(int altered) { case Shader::SMP_vec2: cgGLSetParameter2fv(p, data); continue; case Shader::SMP_vec3: cgGLSetParameter3fv(p, data); continue; case Shader::SMP_vec4: cgGLSetParameter4fv(p, data); continue; + case Shader::SMP_vec4_array: cgGLSetParameterArray4f(p, 0, spec._array_count, data); continue; case Shader::SMP_mat4_whole: cgGLSetMatrixParameterfc(p, data); continue; + case Shader::SMP_mat4_array: cgGLSetMatrixParameterArrayfc(p, 0, spec._array_count, data); continue; case Shader::SMP_mat4_transpose: cgGLSetMatrixParameterfr(p, data); continue; case Shader::SMP_mat4_column: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); continue; case Shader::SMP_mat4_upper3x3: diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 1d74f61c25..c45ab59972 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -937,27 +937,12 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { return; } + bind._piece = Shader::SMP_mat4_array; bind._func = Shader::SMF_first; bind._part[0] = inverse ? Shader::SMO_inv_texmat_i : Shader::SMO_texmat_i; bind._part[1] = Shader::SMO_identity; - - // Add it once for each index. - for (bind._index = 0; bind._index < param_size; ++bind._index) { - // It was discovered in #846, that GLSL 4.10 and lower don't seem to - // guarantee that matrices occupy successive locations, and on macOS - // they indeed occupy four locations per element. - // As a big fat hack, we multiply by four on macOS, because this is - // hard to fix on the 1.10 branch. We'll have a proper fix on the - // master branch. -#ifdef __APPLE__ - bind._id._seqno = p + bind._index * 4; -#else - bind._id._seqno = p + bind._index; -#endif - _shader->cp_add_mat_spec(bind); - } - return; + bind._array_count = param_size; } else if (matrix_name.size() > 15 && matrix_name.substr(0, 12) == "LightSource[" && @@ -1222,19 +1207,16 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { << "p3d_ClipPlane should be vec4 or vec4[]\n"; return; } - for (int i = 0; i < param_size; ++i) { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._id._seqno = p + i; - bind._piece = Shader::SMP_vec4; - bind._func = Shader::SMF_first; - bind._index = i; - bind._part[0] = Shader::SMO_apiview_clipplane_i; - bind._arg[0] = nullptr; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = nullptr; - _shader->cp_add_mat_spec(bind); - } + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._piece = Shader::SMP_vec4_array; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_apiview_clipplane_i; + bind._arg[0] = nullptr; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = nullptr; + bind._array_count = param_size; + _shader->cp_add_mat_spec(bind); return; } if (size > 4 && noprefix.substr(0, 4) == "Fog.") { @@ -2310,7 +2292,9 @@ issue_parameters(int altered) { case Shader::SMP_vec2: _glgsg->_glUniform2fv(p, 1, data); continue; case Shader::SMP_vec3: _glgsg->_glUniform3fv(p, 1, data); continue; case Shader::SMP_vec4: _glgsg->_glUniform4fv(p, 1, data); continue; + case Shader::SMP_vec4_array: _glgsg->_glUniform4fv(p, spec._array_count, data); continue; case Shader::SMP_mat4_whole: _glgsg->_glUniformMatrix4fv(p, 1, GL_FALSE, data); continue; + case Shader::SMP_mat4_array: _glgsg->_glUniformMatrix4fv(p, spec._array_count, GL_FALSE, data); continue; case Shader::SMP_mat4_transpose: _glgsg->_glUniformMatrix4fv(p, 1, GL_TRUE, data); continue; case Shader::SMP_mat4_column: _glgsg->_glUniform4f(p, data[0], data[4], data[8], data[12]); continue; case Shader::SMP_mat4_upper3x3: diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 628445e4dc..55fec70437 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -577,7 +577,7 @@ cp_add_mat_spec(ShaderMatSpec &spec) { // index refer to. (It can't be the case that both parts are arrays.) int begin[2] = {0, 0}; int end[2] = {1, 1}; - if (spec._index > 0) { + if (spec._index > 0 || spec._array_count > 1) { for (int i = 0; i < 2; ++i) { if (spec._part[i] == SMO_texmat_i || spec._part[i] == SMO_inv_texmat_i || @@ -592,7 +592,7 @@ cp_add_mat_spec(ShaderMatSpec &spec) { spec._part[i] == SMO_texscale_i || spec._part[i] == SMO_texcolor_i) { begin[i] = spec._index; - end[i] = spec._index + 1; + end[i] = spec._index + spec._array_count; } } nassertv(end[0] == 1 || end[1] == 1); diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index fc7e49ae55..1b87d51c31 100644 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -296,7 +296,9 @@ public: SMP_vec2, SMP_vec3, SMP_vec4, + SMP_vec4_array, SMP_mat4_whole, + SMP_mat4_array, SMP_mat4_transpose, SMP_mat4_column, SMP_mat4_upper3x3, @@ -441,6 +443,7 @@ public: int _index = 0; ShaderMatPiece _piece; int _offset = 0; + int _array_count = 1; }; struct ShaderTexSpec {