فهرست منبع

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
rdb 2 سال پیش
والد
کامیت
cb4597ebb8
4فایلهای تغییر یافته به همراه21 افزوده شده و 32 حذف شده
  1. 2 0
      panda/src/glstuff/glCgShaderContext_src.cxx
  2. 14 30
      panda/src/glstuff/glShaderContext_src.cxx
  3. 2 2
      panda/src/gobj/shader.cxx
  4. 3 0
      panda/src/gobj/shader.h

+ 2 - 0
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_vec2: cgGLSetParameter2fv(p, data); continue;
       case Shader::SMP_vec3: cgGLSetParameter3fv(p, data); continue;
       case Shader::SMP_vec3: cgGLSetParameter3fv(p, data); continue;
       case Shader::SMP_vec4: cgGLSetParameter4fv(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_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_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_column: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); continue;
       case Shader::SMP_mat4_upper3x3:
       case Shader::SMP_mat4_upper3x3:

+ 14 - 30
panda/src/glstuff/glShaderContext_src.cxx

@@ -937,27 +937,12 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
           return;
           return;
         }
         }
 
 
+        bind._piece = Shader::SMP_mat4_array;
         bind._func = Shader::SMF_first;
         bind._func = Shader::SMF_first;
         bind._part[0] = inverse ? Shader::SMO_inv_texmat_i
         bind._part[0] = inverse ? Shader::SMO_inv_texmat_i
                                 : Shader::SMO_texmat_i;
                                 : Shader::SMO_texmat_i;
         bind._part[1] = Shader::SMO_identity;
         bind._part[1] = Shader::SMO_identity;
-
-        // 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 &&
       } else if (matrix_name.size() > 15 &&
                  matrix_name.substr(0, 12) == "LightSource[" &&
                  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";
           << "p3d_ClipPlane should be vec4 or vec4[]\n";
         return;
         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;
       return;
     }
     }
     if (size > 4 && noprefix.substr(0, 4) == "Fog.") {
     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_vec2: _glgsg->_glUniform2fv(p, 1, data); continue;
       case Shader::SMP_vec3: _glgsg->_glUniform3fv(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: _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_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_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_column: _glgsg->_glUniform4f(p, data[0], data[4], data[8], data[12]); continue;
       case Shader::SMP_mat4_upper3x3:
       case Shader::SMP_mat4_upper3x3:

+ 2 - 2
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.)
   // index refer to.  (It can't be the case that both parts are arrays.)
   int begin[2] = {0, 0};
   int begin[2] = {0, 0};
   int end[2] = {1, 1};
   int end[2] = {1, 1};
-  if (spec._index > 0) {
+  if (spec._index > 0 || spec._array_count > 1) {
     for (int i = 0; i < 2; ++i) {
     for (int i = 0; i < 2; ++i) {
       if (spec._part[i] == SMO_texmat_i ||
       if (spec._part[i] == SMO_texmat_i ||
           spec._part[i] == SMO_inv_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_texscale_i ||
           spec._part[i] == SMO_texcolor_i) {
           spec._part[i] == SMO_texcolor_i) {
         begin[i] = spec._index;
         begin[i] = spec._index;
-        end[i] = spec._index + 1;
+        end[i] = spec._index + spec._array_count;
       }
       }
     }
     }
     nassertv(end[0] == 1 || end[1] == 1);
     nassertv(end[0] == 1 || end[1] == 1);

+ 3 - 0
panda/src/gobj/shader.h

@@ -296,7 +296,9 @@ public:
     SMP_vec2,
     SMP_vec2,
     SMP_vec3,
     SMP_vec3,
     SMP_vec4,
     SMP_vec4,
+    SMP_vec4_array,
     SMP_mat4_whole,
     SMP_mat4_whole,
+    SMP_mat4_array,
     SMP_mat4_transpose,
     SMP_mat4_transpose,
     SMP_mat4_column,
     SMP_mat4_column,
     SMP_mat4_upper3x3,
     SMP_mat4_upper3x3,
@@ -441,6 +443,7 @@ public:
     int               _index = 0;
     int               _index = 0;
     ShaderMatPiece    _piece;
     ShaderMatPiece    _piece;
     int               _offset = 0;
     int               _offset = 0;
+    int               _array_count = 1;
   };
   };
 
 
   struct ShaderTexSpec {
   struct ShaderTexSpec {