   getUniformLocations: (descriptor) ->
     {gl} = descriptor.context
     program = @getGLProgram descriptor.context
+    id = descriptor.context.id
     for name, variable of @variables.uniforms
-      variable.location = gl.getUniformLocation program, variable.name
-      if variable.location is null
+      variable.location or= {}
+      variable.location[id] = gl.getUniformLocation program, variable.name
+      if variable.location[id] is null
         # remove variables that were not used in the shader, to prevent
         # uselessly iterating through them later
         delete @variables.uniforms[name]

    true

  setAttribute: (context, variable, value) ->
    unless @isAttributeEnabled context, variable.location
      @enableAttribute context, variable.location, variable.name
    value.bind context
    context.gl.vertexAttribPointer variable.location, value.itemSize, value.dataType || GL_FLOAT, false, 0, value.offset || 0

  setUniform: (context, variable, value) ->
    {gl} = context
    switch variable.type
      when 'float'          then gl.uniform1f  variable.location, value
      when 'bool', 'int'    then gl.uniform1i  variable.location, value
      when 'vec2'           then gl.uniform2fv variable.location, value
      when 'vec3'           then gl.uniform3fv variable.location, value
      when 'vec4'           then gl.uniform4fv variable.location, value
      when 'bvec2', 'ivec2' then gl.uniform2iv variable.location, value
      when 'bvec3', 'ivec3' then gl.uniform3iv variable.location, value
      when 'bvec4', 'ivec4' then gl.uniform4iv variable.location, value
      when 'mat2' then gl.uniformMatrix2fv variable.location, false, value
      when 'mat3' then gl.uniformMatrix3fv variable.location, false, value
      when 'mat4' then gl.uniformMatrix4fv variable.location, false, value
      when 'sampler2D', 'samplerCube'
        if !(value instanceof Jax.Texture) or value.ready()
          gl.activeTexture GL_TEXTURE0 + @__textureIndex
          value.refresh context unless value.isValid context
          gl.bindTexture value.options.target, value.getHandle context
          gl.uniform1i variable.location, value = @__textureIndex++
      else throw new Error "Unexpected variable type: #{variable.type}"

  insert: (vsrc, fsrc, index) ->

      descriptor = @_contexts[context.id] =
        valid: false
        context: context
      # console.log @variables
      maxAttrs = @getShaderContext(descriptor, 'vertex').maxVertexAttribs
      context._enabledAttributes or= new Uint8Array maxAttrs
    descriptor
