         renderPassDescriptor.colorAttachments[0].storeAction = .store
         
         guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) else {return}
-
+        
         renderEncoder.setRenderPipelineState(renderPipeline)
         renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
         renderEncoder.setVertexBuffer(texCoordBuffer, offset: 0, index: 1)
-
+        
         renderEncoder.setFragmentTexture(texture, index: 0)
         var textureIndex = 1
         for additionalTex in additionalTextures {

            renderEncoder.setFragmentBuffer(additionalBuf, offset: 0, index: bufferIndex)
            bufferIndex += 1
        }

        renderEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
        renderEncoder.endEncoding()
    }


    // =========================================================================
    // MARK: - Initialization
    
    init(frame frameRect: CGRect) {
        guard let device = MTLCreateSystemDefaultDevice() else {fatalError()}
        super.init(frame: frameRect, device: device)
        commonInit()
    }
    
    required init(coder: NSCoder) {
        super.init(coder: coder)
        guard let device = MTLCreateSystemDefaultDevice() else {fatalError()}
        self.device = device
        commonInit()
    }
    
    private func commonInit() {
        guard let device = device else {fatalError()}
        commandQueue = device.makeCommandQueue()
        textureLoader = MTKTextureLoader(device: device)
        lanczos = MPSImageLanczosScale(device: device)
        
        framebufferOnly = false
        enableSetNeedsDisplay = true
        isPaused = true
        delegate = self
    }

    // =========================================================================
    // MARK: - Private
        
    private func transform(contentMode: UIViewContentMode) {
        guard let device = device else {fatalError()}
        guard let drawable = currentDrawable, let texture = texture else {return}
        guard texture.width != drawable.texture.width || texture.height != drawable.texture.height else {
            transformedTexture = texture
            return
        }
        
        var transform: MPSScaleTransform = contentMode.scaleTransform(
            from: texture,
            to: drawable.texture)
        
        // make dest texture
        transformedTexture = device.makeTexture(pixelFormat: texture.pixelFormat, width: drawable.texture.width, height: drawable.texture.height)
        guard let transformedTexture = transformedTexture else {fatalError()}
        
        // resize
        guard let commandBuffer = commandQueue.makeCommandBuffer() else {fatalError()}
        withUnsafePointer(to: &transform) { (transformPtr: UnsafePointer<MPSScaleTransform>) in
            lanczos.scaleTransform = transformPtr
            lanczos.encode(commandBuffer: commandBuffer, sourceTexture: texture, destinationTexture: transformedTexture)
        }
        commandBuffer.commit()
        commandBuffer.waitUntilCompleted()
    }
    
    // =========================================================================

    private var renderDescriptor: MTLRenderPipelineDescriptor?
    private var renderPipeline: MTLRenderPipelineState?

    // =========================================================================
    // MARK: - Initialization
    
    init(frame frameRect: CGRect) {
        guard let device = MTLCreateSystemDefaultDevice() else {fatalError()}
        super.init(frame: frameRect, device: device)
        commonInit()
    }
    
    required init(coder: NSCoder) {
        super.init(coder: coder)
        guard let device = MTLCreateSystemDefaultDevice() else {fatalError()}
        self.device = device
        commonInit()
    }
    
    private func commonInit() {
        guard let device = device else {fatalError()}
        commandQueue = device.makeCommandQueue()
        textureLoader = MTKTextureLoader(device: device)
        lanczos = MPSImageLanczosScale(device: device)
        
        framebufferOnly = false
        enableSetNeedsDisplay = true
        isPaused = true
        delegate = self
    }

    // =========================================================================
    // MARK: - Private
        
    private func transform(contentMode: UIViewContentMode) {
        guard let device = device else {fatalError()}
        guard let drawable = currentDrawable, let texture = texture else {return}
        guard texture.width != drawable.texture.width || texture.height != drawable.texture.height else {
            transformedTexture = texture
            return
        }
        
        var transform: MPSScaleTransform = contentMode.scaleTransform(
            from: texture,
            to: drawable.texture)
        
        // make dest texture
        transformedTexture = device.makeTexture(pixelFormat: texture.pixelFormat, width: drawable.texture.width, height: drawable.texture.height)
        guard let transformedTexture = transformedTexture else {fatalError()}
        
        // resize
        guard let commandBuffer = commandQueue.makeCommandBuffer() else {fatalError()}
        withUnsafePointer(to: &transform) { (transformPtr: UnsafePointer<MPSScaleTransform>) in
            lanczos.scaleTransform = transformPtr
            lanczos.encode(commandBuffer: commandBuffer, sourceTexture: texture, destinationTexture: transformedTexture)
        }
        commandBuffer.commit()
        commandBuffer.waitUntilCompleted()
    }
    
    func makeBuffer(bytes: UnsafeRawPointer, length: Int) -> MTLBuffer {
        guard let device = device else {fatalError()}
        return device.makeBuffer(bytes: bytes, length: length, options: [])!
    }
    
    func registerShaders(library: MTLLibrary, vertexFunctionName: String, fragmentFunctionName: String) {
        renderDescriptor = MTLRenderPipelineDescriptor()
        guard let descriptor = renderDescriptor else {return}
        descriptor.vertexFunction = library.makeFunction(name: vertexFunctionName)
        descriptor.fragmentFunction = library.makeFunction(name: fragmentFunctionName)
    }
    
    private func makePipelineIfNeeded() {
        guard let texture = texture else {return}
        guard let descriptor = renderDescriptor else {return}
