import Foundation import MetalKit final class Renderer: NSObject { private let queue: MTLCommandQueue? private var time: Float = 0 private var animatedBy: Float = 0 private var constants = Constants() private let triangleModel: TriangleModel? private let rectangleModel: RectangleModel? private let textureModel: TextureModel? init?(device: MTLDevice, pixelFormat: MTLPixelFormat) { queue = device.makeCommandQueue() guard let library = device.makeDefaultLibrary() else { return nil } triangleModel = TriangleModel(device: device, library: library, pixelFormat: pixelFormat) rectangleModel = RectangleModel(device: device, library: library, pixelFormat: pixelFormat) textureModel = TextureModel(device: device, library: library, pixelFormat: pixelFormat) super.init() } func showTexture(_ texture: MTLTexture) { textureModel?.updateTexture(texture) } } extension Renderer: MTKViewDelegate { func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { print(#function, size) } func draw(in view: MTKView) { time += 1 / Float(view.preferredFramesPerSecond) animatedBy = abs(sin(time) / 2 + 0.5) constants.animatedBy = animatedBy guard let drawable = view.currentDrawable, let descriptor = view.currentRenderPassDescriptor, let commandBuffer = queue?.makeCommandBuffer(), let parallelRenderCommandEncoder = commandBuffer.makeParallelRenderCommandEncoder(descriptor: descriptor) else { return } textureModel?.setupRenderCommandEncoder(parallelRenderCommandEncoder: parallelRenderCommandEncoder) rectangleModel?.setupRenderCommandEncoder(parallelRenderCommandEncoder: parallelRenderCommandEncoder, constants: constants, animatedBy: animatedBy) triangleModel?.setupRenderCommandEncoder(parallelRenderCommandEncoder: parallelRenderCommandEncoder, constants: constants) parallelRenderCommandEncoder.endEncoding() commandBuffer.present(drawable) commandBuffer.commit() } }