anchor.diff:      }
     }
   
  -  bool _AllUniformsInitialized() {
  +  bool AllUniformsInitialized() {
       //LogInfo("program ${program.name}");
       //     LogInfo("want: ${program.uniformLocations}");
       //     LogInfo("have: ${program._uniformInitialized}");
       return _uniformInitialized.length == _uniformLocations.length;
     }
  -
  -  void Begin(gl, bool debug) {
  + 
  +    List<String> UniformsUninitialized() {
  +      List<String> out = [];
  +      for (String u in _uniformLocations.keys) {
  +        if (!_uniformInitialized.contains(u)) out.add(u); 
  +      }
  +      return out;
  +    }
  +
  +  void Begin(bool debug) {
       if (debug) print("[${name} setting attributes");
  -    gl.useProgram(_program);
  +    _gl.useProgram(_program);
       for (String a in _attributeLocations.keys) {
         if (debug) print("[${name}] $a");
         final index = _attributeLocations[a];
  -      gl.enableVertexAttribArray(index);
  +      _gl.enableVertexAttribArray(index);
         if (a.startsWith("ia")) {
           _extInstancedArrays.vertexAttribDivisorAngle(index, 1);
         }
       }
     }
   
  -  void Draw(gl, bool debug, int numInstances, int numItems, bool drawPoints,
  +  void Draw(bool debug, int numInstances, int numItems, bool drawPoints,
         bool useArrayBuffer) {
       if (debug) print(
           "[${name}] draw points: ${drawPoints} instances${numInstances}");
  -    if (!_AllUniformsInitialized()) {
  -      assert(false);
  +    if (!AllUniformsInitialized()) {
  +      throw "uninitialized uniforms: ${UniformsUninitialized()}";
       }
       if (numInstances > 0) {
         if (drawPoints) {
  
positive.code:                 : WEBGL.UNSIGNED_SHORT,
              0);
        } else {
          gl.drawArrays(WEBGL.TRIANGLES, 0, numItems);
        }
      }
      if (debug) print(gl.getProgramInfoLog(_program));
    }
  
    void End(gl, bool debug) {
      if (debug) print("[${name} unsetting attributes");
      for (String canonical in _attributeLocations.keys) {
        int index = _attributeLocations[canonical];
        if (canonical.startsWith("ia")) {
          _extInstancedArrays.vertexAttribDivisorAngle(index, 0);
        }
        gl.disableVertexAttribArray(index);
      }
    }
  }
  
negative.code:     WEBGL.UniformLocation l = _uniformLocations[canonical];
      switch (desc.type) {
        case "float":
          _gl.uniform1f(l, val);
          break;
        case "mat4":
          _gl.uniformMatrix4fv(l, false, val.array);
          break;
        case "vec4":
          assert(val.array.length == 4);
          _gl.uniform4fv(l, val.array);
          break;
        case "vec3":
          assert(val.array.length == 3);
          _gl.uniform3fv(l, val.array);
          break;
        case "vec2":
          assert(val.array.length == 2);
          _gl.uniform2fv(l, val.array);
          break;
        case "sampler2D":
          int n;
  