_callGPU(x) {
    if (!this.axisNormalized) {
      if (x.is2DReshaped || x.is2DSquareReshaped) {
        this.inputShape = x.originalShape
      } else {
        this.inputShape = x.tensor.shape
      }
      this.axis = this.axis < 0 ? this.inputShape.length + this.axis : this.axis - 1
      this.axisNormalized = true
    }

    if (!x.glTexture && !x.glTextureFragments) {
      if (x.tensor.shape.length <= 2) {
        x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true })
      } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) {
        // defaults to square reshaped
        x.reshapeTo2DSquare()
        x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true })
      }
    }

    this._createIndexMap(x.glTextureShape, x.indicesForReshaped)

    // create output textures if doesn't already exist
    if (!this.output) {
      this.output = new Tensor([], x.glTextureShape)
      this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true })
      if (x.is1D) {
        this.output.is1D = x.is1D
      } else if (x.is2DReshaped || x.is2DSquareReshaped) {
        if (x.is2DReshaped) {
          this.output.is2DReshaped = x.is2DReshaped
        } else if (x.is2DSquareReshaped) {
          this.output.is2DSquareReshaped = x.is2DSquareReshaped
        }
        this.output.originalShape = x.originalShape
        this.output.indicesForReshaped = x.indicesForReshaped
      }
    }

    const programInputs = [{ input: x, name: 'X' }, { input: this.normAxisIndexMap, name: 'normAxisIndexMap' }]
    if (this.scale) {
      programInputs.push({ input: this.weights['gamma'], name: 'gamma' })
    }
    if (this.center) {
      programInputs.push({ input: this.weights['beta'], name: 'beta' })
    }
    programInputs.push({ input: this.weights['moving_mean'], name: 'mean' })
    programInputs.push({ input: this.weights['moving_variance'], name: 'std' })
    const programUniforms = [
      { value: this.epsilon, type: 'float', name: 'epsilon' },
      { value: +this.scale, type: 'bool', name: 'scale' },
      { value: +this.center, type: 'bool', name: 'center' }
    ]
    webgl2.runProgram({
      program: this.program,
      output: this.output,
      inputs: programInputs,
      uniforms: programUniforms,
      supportsTextureFragments: true
    })

    // GPU -> CPU data transfer
    if (this.outbound.length === 0) {
      this.output.transferFromGLTexture()
      if (this.output.is2DReshaped) {
        this.output.reshapeFrom2D()
      } else if (this.output.is2DSquareReshaped) {
        this.output.reshapeFrom2DSquare()
      }
    }
  }
GPU call
(will only work on the 2D-reshaped representation for post-convolutional BN)

@param {Tensor} x