function createUniformBlockInfoFromProgram(gl, program, uniformBlockSpec, blockName) {
  var blockSpecs = uniformBlockSpec.blockSpecs;
  var uniformData = uniformBlockSpec.uniformData;
  var blockSpec = blockSpecs[blockName];

  if (!blockSpec) {
    warn("no uniform block object named:", blockName);
    return {
      name: blockName,
      uniforms: {}
    };
  }

  var array = new ArrayBuffer(blockSpec.size);
  var buffer = gl.createBuffer();
  var uniformBufferIndex = blockSpec.index;
  gl.bindBuffer(UNIFORM_BUFFER, buffer);
  gl.uniformBlockBinding(program, blockSpec.index, uniformBufferIndex);
  var prefix = blockName + ".";

  if (arraySuffixRE.test(prefix)) {
    prefix = prefix.replace(arraySuffixRE, ".");
  }

  var uniforms = {};
  var setters = {};
  var setterTree = {};
  blockSpec.uniformIndices.forEach(function (uniformNdx) {
    var data = uniformData[uniformNdx];
    var name = data.name;

    if (name.startsWith(prefix)) {
      name = name.substr(prefix.length);
    }

    var isArray = name.endsWith('[0]');

    if (isArray) {
      name = name.substr(0, name.length - 3);
    }

    var typeInfo = typeMap[data.type];
    var Type = typeInfo.Type;
    var byteLength = isArray ? pad(typeInfo.size, 16) * data.size : typeInfo.size * data.size;
    var uniformView = new Type(array, data.offset, byteLength / Type.BYTES_PER_ELEMENT);
    uniforms[name] = uniformView; // Note: I'm not sure what to do here. The original
    // idea was to create TypedArray views into each part
    // of the block. This is useful, for example if you have
    // a block with { mat4: model; mat4 view; mat4 projection; }
    // you'll get a Float32Array for each one suitable for
    // passing to most JS math libraries including twgl's and glMatrix.js.
    //
    // But, if you have a an array of structures, especially if that
    // array is large, you get a whole bunch of TypedArray views.
    // Every one of them has overhead and switching between them all
    // is probably a cache miss. In that case it would really be better
    // to just have one view (asFloat) and have all the setters
    // just reference the correct portion. But, then you can't easily
    // treat a matrix, or a vec4, as a standalone thing like you can
    // with all the views.
    //
    // Another problem with the views is they are not shared. With
    // uniforms you have one set of setters. With UniformBlockInfo
    // you have a set of setters *pre block instance*. That's because
    // TypedArray views can't be mapped to different buffers.
    //
    // My gut right now is if you really want the speed and compactness
    // then you should probably roll your own solution. TWGL's goal
    // here is ease of use as AFAICT there is no simple generic efficient
    // solution.

    var setter = createUniformBlockUniformSetter(uniformView, isArray, typeInfo.rows, typeInfo.cols);
    setters[name] = setter;
    addSetterToUniformTree(name, setter, setterTree, setters);
  });
  return {
    name: blockName,
    array: array,
    asFloat: new Float32Array(array),
    // for debugging
    buffer: buffer,
    uniforms: uniforms,
    setters: setters
  };
}
Creates a `UniformBlockInfo` for the specified block

Note: **If the blockName matches no existing blocks a warning is printed to the console and a dummy
`UniformBlockInfo` is returned**. This is because when debugging GLSL
it is common to comment out large portions of a shader or for example set
the final output to a constant. When that happens blocks get optimized out.
If this function did not create dummy blocks your code would crash when debugging.

@param {WebGL2RenderingContext} gl A WebGL2RenderingContext
@param {WebGLProgram} program A WebGLProgram
@param {module:twgl.UniformBlockSpec} uniformBlockSpec. A UniformBlockSpec as returned
    from {@link module:twgl.createUniformBlockSpecFromProgram}.
@param {string} blockName The name of the block.
@return {module:twgl.UniformBlockInfo} The created UniformBlockInfo
@memberOf module:twgl/programs