A86f6aa8d4278fcde199dae732e53598
GPUImage2之渲染管线Pipeline的实现

目标:理解渲染管线怎么管理滤镜链?

学习思路

  • 生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据。
  1. 生产者(ImageSource)、消费者(ImageConsumer)的抽象
  2. 生产者和消费者的“交易”方式
  3. 高级应用

1. 抽象

  • GPUImage2将Inputs抽象为内容生产的ImageSource,Outputs抽象为消费内容的ImageConsumer,ImageSource和ImageConsumer均为协议(充分利用Swift面向协议编程大法),因此可以有多种ImageSource和ImageConsumer。

1.1 生产者ImageSource

public protocol ImageSource {
    var targets:TargetContainer { get }
    func transmitPreviousImage(to target:ImageConsumer, atIndex:UInt)
}
  • targets:TargetContainer为集合,一个生产者可以有多个消费者,比如一个PictureInput生产的内容可以被渲染到RenderView上,也可以输出到PictureOutput上输出一张图片。
    注意:targets为WeakImageConsumer,为了避免循环引用使用了weak。
  • transmitPreviousImage:将ImageSource自己生产的内容传送到target上,可以理解为ImageSource的出口。

1.2 消费者ImageConsumer

public protocol ImageConsumer:AnyObject {
    var maximumInputs:UInt { get }
    var sources:SourceContainer { get }

    func newFramebufferAvailable(_ framebuffer:Framebuffer, fromSourceIndex:UInt)
}
  • maximumInputs为输入的数量,说明有些效果只要一个输入即可,而有些效果需要2个或以上输入,对多个输入处理后输出结果,比如2张图片的混合blend等操作。
  • sources:SourceContainer为输入源的实例,这里存放的主要目的用来ImageRelay这种类(自己生产自己消费)的输入源。
  • newFramebufferAvailable:内容流入消费者的口,如果协议方法约束所有输入和输出的接口。

2. 生产者与消费者的“交易”方式

2.1 操作流程

  • 交易中生产者扮演着主导地位,关心生产者的targets即可,我们来看看ImageSource的扩展extension。
public func addTarget(_ target:ImageConsumer, atTargetIndex:UInt? = nil) {
   if let targetIndex = atTargetIndex {
       target.setSource(self, atIndex:targetIndex)
       targets.append(target, indexAtTarget:targetIndex)
       transmitPreviousImage(to:target, atIndex:targetIndex)
   } else if let indexAtTarget = target.addSource(self) {
       targets.append(target, indexAtTarget:indexAtTarget)
       transmitPreviousImage(to:target, atIndex:indexAtTarget)
   } else {
       debugPrint("Warning: tried to add target beyond target's input capacity")
   }
}

public func removeAllTargets() { 
    for (target, index) in targets {
        target.removeSourceAtIndex(index)
    }
    targets.removeAll()
}
  • addTarget
top Created with Sketch.