title: How to improve texture access performance in OpenGL shaders?
body: <h1>Conditions</h1>
  
  <p>I use <code>OpenGL 3</code> and <code>PyOpenGL</code>.</p>
  
  <p>I have ~50 thousand (53'490) vertices and each of them has 199 <code>vec3</code> attributes which determine their displacement. It's impossible to store this data as regular vertices attributes, so I use texture.</p>
  
  <p>The problem is: non-parallelized <code>C</code> function calculates displacement of vertices as fast as <code>GLSL</code> and even faster in some cases. I've checked: the issue is texture read and I don't understand how to optimize it.</p>
  
  <p>I've written two different shaders. One calculates new model in ~0.09s and another one in ~0.12s (including attributes assignment, which is equal for both cases).</p>
  
  <h1>Code</h1>
  
  <p>Both shaders start with</p>
  
  <pre><code>#version 300 es
  
  in vec3 vin_position;
  
  out vec4 vin_pos;
  
  uniform mat4 rotation_matrix;
  
  uniform float coefficients[199];
  
  uniform sampler2D principal_components;
  </code></pre>
  
  <p>The faster one is</p>
  
  <pre><code>void main(void) {
      int c_pos = gl_VertexID;
      int texture_size = 8192;
      ivec2 texPos = ivec2(c_pos % texture_size, c_pos / texture_size);
      vec4 tmp = vec4(0.0);
      for (int i = 0; i &lt; 199; i++) {
          tmp += texelFetch(principal_components, texPos, 0) * coefficients[i];
          c_pos += 53490;
          texPos = ivec2(c_pos % texture_size, c_pos / texture_size);
      }
      gl_Position = rotation_matrix
          * vec4(vin_position + tmp.xyz, 246006.0);
      vin_pos = gl_Position;
  }
  </code></pre>
  
  <p>The slower one</p>
  
  <pre><code>void main(void) {
      int texture_size = 8192;
      int columns = texture_size - texture_size % 199;
      int c_pos = gl_VertexID * 199;
      ivec2 texPos = ivec2(c_pos % columns, c_pos / columns);
      vec4 tmp = vec3(0.0);
      for (int i = 0; i &lt; 199; i++) {
          tmp += texelFetch(principal_components, texPos, 0) * coefficients[i];
          texPos.x++;
      }
      gl_Position = rotation_matrix
          * vec4(vin_position + tmp.xyz, 246006.0);
      vin_pos = gl_Position;
  }
  </code></pre>
  
  <p>The main idea of difference between them:</p>
  
  <ul>
  <li>in the first case attributes of vertices are stored in following way:
  
  <ul>
  <li>first attributes of all vertices</li>
  <li>second attributes of all vertices</li>
  <li>...</li>
  <li>last attributes of all vertices</li>
  </ul></li>
  <li>in the second case attributes of vertices are stored in another way:
  
  <ul>
  <li>all attributes of the first vertex</li>
  <li>all attributes of the second vertex</li>
  <li>...</li>
  <li>all attributes of the last vertex</li>
  </ul></li>
  <li>also in the second example data is aligned so that all attributes of each vertex stored only in one row. This means that if I know the row and column of the first attribute of some vertex, I need only to increment <code>x</code> component of texture coordinate</li>
  </ul>
  
  <p>I thought, that aligned data will be accessed faster.</p>
  
  <h1>Questions</h1>
  
  <ul>
  <li>Why is data not accessed faster?</li>
  <li>How can I increase performance of it?</li>
  <li>Is there ability to link texture chunk with vertex?</li>
  <li>Are there recommendations for data alignment, good related article about caching in GPUs (Intel HD, nVidia GeForce)?</li>
  </ul>
  
  <h1>Notes</h1>
  
  <ul>
  <li><code>coefficients</code> array changed from frame to frame, otherwise there's no problem: I could precalculate the model and be happy</li>
  </ul>