message: Concatenate GL shader sources before attempting to separable-patch
  * Since we search for #version, if it appears in a separate source
  string from the rest of the shader, we fail to find the right place to
  insert the patch blocks. If we concatenate first, it makes it easier.
diff: @@ -238,9 +238,11 @@ GLuint MakeSeparableShaderProgram(WrappedOpenGL &gl, GLenum type, vector<string>
  // this will fail if e.g. a member of gl_PerVertex is declared at global scope
  // (this is probably most likely for clipdistance if it's redeclared with a size)
  - // these strings contain whichever source string we replaced, here to scope until
  - // the program has been created
  - string subStrings[2];
  + // we start by concatenating the source strings to make parsing easier.
  + std::string src;
  +
  + for(size_t i = 0; i < sources.size(); i++)
  + src += sources[i];
  for(int blocktype = 0; blocktype < 2; blocktype++)
  {
  @@ -248,32 +250,18 @@ GLuint MakeSeparableShaderProgram(WrappedOpenGL &gl, GLenum type, vector<string>
  if(type == eGL_VERTEX_SHADER && blocktype == 0)
  continue;
  - string &substituted = subStrings[blocktype];
  -
  string block = blocks[blocktype];
  const char *identifier = blockIdentifiers[blocktype];
  - bool already = false;
  -
  - for(size_t i = 0; i < sources.size(); i++)
  - {
  // if we find the 'identifier' (ie. the block name),
  - // assume this block is already present and stop
  - if(sources[i].find(identifier) != string::npos)
  - {
  - already = true;
  - break;
  - }
  - }
  -
  + // assume this block is already present and stop.
  // only try and insert this block if the shader doesn't already have it
  - if(already)
  + if(src.find(identifier) != string::npos)
  + {
  continue;
  + }
  - for(size_t i = 0; i < sources.size(); i++)
  {
  - string src = strings[i];
  -
  size_t len = src.length();
  // find if this source contains a #version, accounting for whitespace
  @@ -302,8 +290,12 @@ GLuint MakeSeparableShaderProgram(WrappedOpenGL &gl, GLenum type, vector<string>
  // no #version found
  if(it == string::npos)
  - continue;
  -
  + {
  + // insert at the start
  + it = 0;
  + }
  + else
  + {
  // it now points after the #version
  // skip whitespace
  @@ -425,8 +417,8 @@ GLuint MakeSeparableShaderProgram(WrappedOpenGL &gl, GLenum type, vector<string>
  bool precisionMatch =
  (pit + sizeof(lowp) < len && !strncmp(&src[pit], lowp, sizeof(lowp) - 1) &&
  isspacetab(src[pit + sizeof(lowp) - 1]));
  - precisionMatch |=
  - (pit + sizeof(mediump) < len && !strncmp(&src[pit], mediump, sizeof(mediump) - 1) &&
  + precisionMatch |= (pit + sizeof(mediump) < len &&
  + !strncmp(&src[pit], mediump, sizeof(mediump) - 1) &&
  isspacetab(src[pit + sizeof(mediump) - 1]));
  precisionMatch |=
  (pit + sizeof(highp) < len && !strncmp(&src[pit], highp, sizeof(highp) - 1) &&
  @@ -456,18 +448,16 @@ GLuint MakeSeparableShaderProgram(WrappedOpenGL &gl, GLenum type, vector<string>
  while(it < len && !isnewline(src[it]))
  ++it;
  }
  + }
  - substituted = src;
  -
  - substituted.insert(it, block);
  -
  - strings[i] = substituted.c_str();
  -
  - break;
  + if(it < src.length())
  + src.insert(it, block);
  }
  }
  - sepProg = CreateSepProgram(gl, type, (GLsizei)sources.size(), strings, numPaths, paths);
  + const char *c_src = src.c_str();
  +
  + sepProg = CreateSepProgram(gl, type, 1, &c_src, numPaths, paths);
  }
  gl.glGetProgramiv(sepProg, eGL_LINK_STATUS, &status);
  