commit 80961fc18d0118b46afe57270b1c4f682c00f2ea
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Feb 25 00:12:41 2021 +0100

    Make the 'Component Associations' UBO (on most devices) twice smaller -
    use the 'packed' layout and 'ivec2' in place of 'ivec4'.
    
    This forces us to dynamically probe the 'Stride' - number of 4-byte entities that the UBO's 'ivec4' takes - and correct the already-constructed UniformBlockAssociation objects in case this turns out to be different than the expected 2, i.e. tightly-packed.
    
    The point: this saves a lot of uniform space in th vertex shader, which lets us declare larger MAX_NUM_COMPONENTS - needed for the Gigaminx.
    
    (and no, we cannot assume an UBO can hold at least 16KB since this is not the case on Samsung Galaxy J4+)

diff --git a/src/main/java/org/distorted/library/mesh/MeshBase.java b/src/main/java/org/distorted/library/mesh/MeshBase.java
index dcf28eb..894bd22 100644
--- a/src/main/java/org/distorted/library/mesh/MeshBase.java
+++ b/src/main/java/org/distorted/library/mesh/MeshBase.java
@@ -51,7 +51,7 @@ public abstract class MeshBase
    {
    private static final int ASSOC_UBO_BINDING  = 3;
    private static final int CENTER_UBO_BINDING = 4;
-   public  static final int MAX_EFFECT_COMPONENTS= 98;
+   public  static final int MAX_EFFECT_COMPONENTS= 242;
 
    // sizes of attributes of an individual vertex.
    private static final int POS_DATA_SIZE= 3; // vertex coordinates: x,y,z
@@ -94,6 +94,8 @@ public abstract class MeshBase
    private float mInflate;
    private final UniformBlockAssociation mUBA;
    private UniformBlockCenter mUBC;
+   private boolean mStrideCorrected;
+   private static int mStride;
 
    DeferredJobs.JobNode[] mJobNode;
 
@@ -577,6 +579,18 @@ public abstract class MeshBase
      {
      mCenterBlockIndex[variant]= GLES30.glGetUniformBlockIndex(programH, "componentCenter");
      mAssocBlockIndex[variant] = GLES30.glGetUniformBlockIndex(programH, "componentAssociation");
+
+     if( mStride==0 )
+       {
+       String[] uniformNames = { "vComAssoc" };
+       int[] indices = new int[1];
+       int[] params  = new int[1];
+
+       GLES30.glGetUniformIndices(programH, uniformNames, indices, 0);
+       GLES30.glGetActiveUniformsiv( programH, 1, indices, 0, GLES30.GL_UNIFORM_ARRAY_STRIDE, params,0 );
+
+       mStride = params[0]/4;
+       }
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -726,6 +740,12 @@ public abstract class MeshBase
  */
    public void send(int programH, int variant)
      {
+     if( !mStrideCorrected )
+       {
+       mStrideCorrected = true;
+       mUBA.correctStride(mStride);
+       }
+
      int indexA = mUBA.getIndex();
      GLES30.glBindBufferBase(GLES30.GL_UNIFORM_BUFFER, ASSOC_UBO_BINDING, indexA);
      GLES30.glUniformBlockBinding(programH, mAssocBlockIndex[variant], ASSOC_UBO_BINDING);
diff --git a/src/main/java/org/distorted/library/uniformblock/UniformBlockAssociation.java b/src/main/java/org/distorted/library/uniformblock/UniformBlockAssociation.java
index 507baa4..019ede5 100644
--- a/src/main/java/org/distorted/library/uniformblock/UniformBlockAssociation.java
+++ b/src/main/java/org/distorted/library/uniformblock/UniformBlockAssociation.java
@@ -33,22 +33,26 @@ import static org.distorted.library.mesh.MeshBase.MAX_EFFECT_COMPONENTS;
  */
 public class UniformBlockAssociation
   {
-  private static final int BLOCK_SIZE = 16*MAX_EFFECT_COMPONENTS;
   private static final int DEFAULT_ASSOCIATION = 0xffffffff;
+  private static final int DEFAULT_STRIDE = 2;
+  private static final int LOC_AND = 0;
+  private static final int LOC_EQU = 1;
 
   private final InternalBuffer mUBO;
-  private final int[] mAssociations;
+  private int[] mAssociations;
+  private int mStride;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public UniformBlockAssociation()
     {
-    mAssociations= new int[BLOCK_SIZE/4];
+    mStride = DEFAULT_STRIDE;
+    mAssociations= new int[mStride*MAX_EFFECT_COMPONENTS];
 
     for(int i=0; i<MAX_EFFECT_COMPONENTS; i++)
       {
-      mAssociations[4*i  ] = DEFAULT_ASSOCIATION;
-      mAssociations[4*i+2] = i;
+      mAssociations[mStride*i+LOC_AND] = DEFAULT_ASSOCIATION;
+      mAssociations[mStride*i+LOC_EQU] = i;
       }
 
     mUBO = new InternalBuffer(GLES30.GL_UNIFORM_BUFFER, GLES30.GL_STATIC_READ);
@@ -58,6 +62,7 @@ public class UniformBlockAssociation
 
   public UniformBlockAssociation(UniformBlockAssociation original)
     {
+    mStride = original.mStride;
     int size = original.mAssociations.length;
     mAssociations= new int[size];
     System.arraycopy(original.mAssociations, 0, mAssociations, 0, size);
@@ -65,19 +70,38 @@ public class UniformBlockAssociation
     mUBO = new InternalBuffer(GLES30.GL_UNIFORM_BUFFER, GLES30.GL_STATIC_READ);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void correctStride(int stride)
+    {
+    if( mStride != stride )
+      {
+      int[] tmp = new int[stride*MAX_EFFECT_COMPONENTS];
+
+      for(int i=0; i<MAX_EFFECT_COMPONENTS; i++)
+        {
+        tmp[stride*i+LOC_AND] = mAssociations[mStride*i+LOC_AND];
+        tmp[stride*i+LOC_EQU] = mAssociations[mStride*i+LOC_EQU];
+        }
+
+      mAssociations = tmp;
+      mStride = stride;
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public boolean matchesAssociation( int comp, int andAssoc, int equAssoc)
     {
-    return (andAssoc & mAssociations[4*comp]) != 0 || (equAssoc == mAssociations[4*comp+2]);
+    return (andAssoc & mAssociations[mStride*comp+LOC_AND]) != 0 || (equAssoc == mAssociations[mStride*comp+LOC_EQU]);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void setEffectAssociationNow(int comp, int andAssociation, int equAssociation)
     {
-    mAssociations[4*comp  ] = andAssociation;
-    mAssociations[4*comp+2] = equAssociation;
+    mAssociations[mStride*comp+LOC_AND] = andAssociation;
+    mAssociations[mStride*comp+LOC_EQU] = equAssociation;
 
     mUBO.invalidate();
     }
@@ -86,15 +110,15 @@ public class UniformBlockAssociation
 
   public int getIndex()
     {
-    return mUBO.createImmediatelyInt( BLOCK_SIZE, mAssociations);
+    return mUBO.createImmediatelyInt( 4*mStride*MAX_EFFECT_COMPONENTS, mAssociations);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void copy(int compTo, UniformBlockAssociation assocFrom, int compFrom)
     {
-    mAssociations[4*compTo  ] = assocFrom.mAssociations[4*compFrom  ];
-    mAssociations[4*compTo+2] = assocFrom.mAssociations[4*compFrom+2];
+    mAssociations[mStride*compTo+LOC_AND] = assocFrom.mAssociations[mStride*compFrom+LOC_AND];
+    mAssociations[mStride*compTo+LOC_EQU] = assocFrom.mAssociations[mStride*compFrom+LOC_EQU];
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -115,9 +139,9 @@ public class UniformBlockAssociation
 
     for(int i=0; i<8; i++)
       {
-      builder.append(mAssociations[4*i]);
+      builder.append(mAssociations[mStride*i+LOC_AND]);
       builder.append(' ');
-      builder.append(mAssociations[4*i+2]);
+      builder.append(mAssociations[mStride*i+LOC_EQU]);
       builder.append(' ');
       }
 
diff --git a/src/main/res/raw/main_vertex_shader.glsl b/src/main/res/raw/main_vertex_shader.glsl
index 28c4d6d..2b2f093 100644
--- a/src/main/res/raw/main_vertex_shader.glsl
+++ b/src/main/res/raw/main_vertex_shader.glsl
@@ -65,13 +65,9 @@ layout (std140) uniform vUniformFloats
                                       // second vec4: first float - cache, next 3: Center, the third -  the Region.
   };
 
-layout (std140) uniform componentAssociation
+layout (packed) uniform componentAssociation
   {
-  ivec4 vComAssoc[MAX_COMPON];        // component Associations, 4 ints:
-                                      // 1: component's AND association
-                                      // 2: reserved. Probably another AND assoc in the future.
-                                      // 3: component's EQU association
-                                      // 4: reserved
+  ivec2 vComAssoc[MAX_COMPON];        // component 'AND' and 'EQU' Associations
   };
 
 //////////////////////////////////////////////////////////////////////////////////////////////
@@ -131,7 +127,7 @@ void main()
 
   for(int i=0; i<vNumEffects; i++)
     {
-    if( ((vComAssoc[component].x & vProperties[i].y) != 0) || (vComAssoc[component].z == vProperties[i].w) )
+    if( ((vComAssoc[component].x & vProperties[i].y) != 0) || (vComAssoc[component].y == vProperties[i].w) )
       {
       // ENABLED EFFECTS WILL BE INSERTED HERE
 
