我觉得我必须在这里丢失一些东西。我已经分类NSOpenGLView
,我试图在drawRect:
调用中画一个CIImage
。将CIImage绘制成NSOpenGLView(没有碰到主内存)
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
let start = CFAbsoluteTimeGetCurrent()
openGLContext!.makeCurrentContext()
let cglContext = openGLContext!.CGLContextObj
let pixelFormat = openGLContext!.pixelFormat.CGLPixelFormatObj
let colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB)!
let options: [String: AnyObject] = [kCIContextOutputColorSpace: colorSpace]
let context = CIContext(CGLContext: cglContext, pixelFormat: pixelFormat, colorSpace: colorSpace, options: options)
context.drawImage(inputImage, inRect: self.bounds, fromRect: input.extent)
openGLContext!.flushBuffer()
let end = CFAbsoluteTimeGetCurrent()
Swift.print("updated view in \(end - start)")
}
我显然是错误的印象是,NSOpenGLContext
(和它的底层CGLContext
)可被包裹在一个CIContext
下除去,并且渲染到将产生在该视图的图像。但是,在上面的代码中正在完成工作时,我不知道实际像素的结束位置(因为视图最终为空)。
如果我只是抓住当前NSGraphicsContext
和渲染成,然后我得到的NSOpenGLView
的图像,但渲染似乎需要大约10倍,只要(通过改变CIContext
声明此IE):
// Works, but is slow
let context = NSGraphicsContext.currentContext()!.CIContext!
也试过这个,这既是慢,实际上不显示图像,使之成为一个双重失败:
// Doesn't work. AND it's slow.
input.drawInRect(bounds, fromRect: input.extent, operation: .CompositeDestinationAtop, fraction: 1.0)
简单的解决办法就是要渲染到CGImage
,和TH en弹出到屏幕上(通过CGImage -> NSImage
,然后NSImageView
,或支持CALayer
)。但是这对我的情况来说不够高效。在我的应用程序中,我正在寻找渲染几十个缩略图大小的图像,每个图像都有自己的不同链CIFilters
,并随着底层基础图像的更改而实时刷新它们。虽然它们每个都在几毫秒内呈现(使用我当前的路径),但视图更新仍然是每秒几帧的数量级。
我目前有一个类似于CGImageRef -> CIImage -> Bunch of CIFilters -> CGImage -> assign to CALayer for display
的路径。但似乎在渲染链的两端有CGImages
正在查杀性能。
分析后,似乎大部分时间都花在了复制内存的周围,我认为这是预期的,但效率不高。支持CGImage需要穿梭到GPU,然后过滤,然后返回主存储器作为CGImage
,然后(大概)直接返回到GPU以缩放并显示CALayer
。理想情况下,根图像(在过滤之前)只能放在GPU上,结果会直接呈现给视频内存,但我不知道如何完成此操作。我目前的渲染路径是在GPU上进行像素粉碎(这真是太棒了!),但是通过穿梭存储器来实际显示所摧毁的东西而淹没了它。
因此,任何人都可以启发我如何做核心图像过滤与保持在GPU端到端的事情的途径? (或者至少只需要将数据交换一次?)如果我有一个IOSurface支持的CIImage,那么如何直接将UI绘制到UI而不碰到主内存?任何提示?
这将有助于解释的原代码所做的任何更改,以及他们为什么被做了。 – miken32