     }
 }
 
-@available(macOS 10.12, iOS 10.0, tvOS 10.0, *)
 private class TiledCacheKernel: CIImageProcessorKernel {
     
     fileprivate struct Info {
         
-        var image: CIImage
+        let image: CIImage
         let blockSize: Int
         let maxBlockSize: Int
         
         let colorSpace: ColorSpace<RGBColorModel>?
         
         let cache = Cache()
+        let pool = CIContextPool()
     }
     
     override class func process(with inputs: [CIImageProcessorInput]?, arguments: [String : Any]?, output: CIImageProcessorOutput) throws {
-        
-        guard let commandBuffer = output.metalCommandBuffer else { return }
-        guard let texture = output.metalTexture else { return }
-        guard var info = arguments?["info"] as? Info else { return }
-        
-        let region = output.region
-        let bounds = Rect(x: region.minX, y: -region.minY, width: region.width, height: -region.height)
-        
-        info.image = info.image.transformed(by: SDTransform.reflectY())
-        info.render(to: texture, commandBuffer: commandBuffer, bounds: bounds)
+        guard let info = arguments?["info"] as? Info else { return }
+        info.render(to: output.surface, bounds: Rect(output.region))
     }
 }
 
-@available(macOS 10.12, iOS 10.0, tvOS 10.0, *)
 extension TiledCacheKernel.Info {
     
     struct Block: Hashable {

        }
    }
    
    func make_context(commandQueue: MTLCommandQueue, outputPremultiplied: Bool) -> CIContext? {
        
        cache.lck.lock()
        defer { cache.lck.unlock() }
        
        if cache.pool[commandQueue] == nil {
            cache.pool[commandQueue] = CIContextPool(commandQueue: commandQueue)
        }
        
        return cache.pool[commandQueue]?.makeContext(colorSpace: colorSpace, outputPremultiplied: outputPremultiplied)
    }
    
    func render(to texture: MTLTexture, commandBuffer: MTLCommandBuffer, bounds: Rect) {
        
        guard let renderer = self.make_context(commandQueue: commandBuffer.commandQueue, outputPremultiplied: colorSpace == nil) else { return }
        guard let texture_renderer = colorSpace == nil ? renderer : self.make_context(commandQueue: commandBuffer.commandQueue, outputPremultiplied: true) else { return }
        let workingColorSpace = texture_renderer.workingColorSpace ?? CGColorSpaceCreateDeviceRGB()
        
        guard let minX = Int(exactly: floor(bounds.minX)) else { return }

            
            guard let image = _image else { continue }
            
            blocks.append((block, CIImage(cgImage: image)))
            
            for y in stride(from: block.minY, to: block.maxY, by: blockSize) {
                for x in stride(from: block.minX, to: block.maxX, by: blockSize) {
