From 6b663f92e87365b080af230b44b5e1e718f52490 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 18 Aug 2017 09:03:01 -0700 Subject: [PATCH] [kit] Shuffle things around so delegate doesn't have to be given in init() Classes that use the Renderer might not be ready to assign themselves as delegate when the Renderer is initialized --- MetaballsKit/Renderer.swift | 88 ++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/MetaballsKit/Renderer.swift b/MetaballsKit/Renderer.swift index edc7684..3c5214a 100644 --- a/MetaballsKit/Renderer.swift +++ b/MetaballsKit/Renderer.swift @@ -25,59 +25,75 @@ struct Vertex { } public class Renderer: NSObject, MTKViewDelegate { - var delegate: RendererDelegate + public var delegate: RendererDelegate? = nil { + didSet { + guard let delegate = delegate else { + return + } + + let view = delegate.metalView + view.device = device + + do { + let library = try device.makeDefaultLibrary(bundle: Bundle.main) + let vertexShader = library.makeFunction(name: "passthroughVertexShader") + let fragmentShader = library.makeFunction(name: "sampleToColorShader") + + let pipelineStateDescriptor = MTLRenderPipelineDescriptor() + pipelineStateDescriptor.label = "Render Pipeline" + pipelineStateDescriptor.vertexFunction = vertexShader + pipelineStateDescriptor.fragmentFunction = fragmentShader + if let renderAttachment = pipelineStateDescriptor.colorAttachments[0] { + renderAttachment.pixelFormat = view.colorPixelFormat + // Pulled all this from SO. I don't know what all this does... + // https://stackoverflow.com/q/43727335/1174185 + renderAttachment.isBlendingEnabled = true + renderAttachment.alphaBlendOperation = .add + renderAttachment.rgbBlendOperation = .add + renderAttachment.sourceRGBBlendFactor = .sourceAlpha + renderAttachment.sourceAlphaBlendFactor = .sourceAlpha + renderAttachment.destinationRGBBlendFactor = .oneMinusSourceAlpha + renderAttachment.destinationAlphaBlendFactor = .oneMinusSourceAlpha + } + renderPipelineState = try device.makeRenderPipelineState(descriptor: pipelineStateDescriptor) + + try delegate.field.setupMetal(withDevice: device) + } catch let e { + fatalError("\(e)") + } + } + } private var device: MTLDevice private var commandQueue: MTLCommandQueue - private var renderPipelineState: MTLRenderPipelineState - - public init(delegate: RendererDelegate) throws { - self.delegate = delegate + private var renderPipelineState: MTLRenderPipelineState? = nil + override public init() { guard let device = MTLCreateSystemDefaultDevice() else { - throw RendererError.MetalError("Unable to create Metal system device") + fatalError("Unable to create Metal system device") } - let view = delegate.metalView self.device = device - view.device = device - - try delegate.field.setupMetal(withDevice: device) - - let library = try device.makeDefaultLibrary(bundle: Bundle.main) - let vertexShader = library.makeFunction(name: "passthroughVertexShader") - let fragmentShader = library.makeFunction(name: "sampleToColorShader") - - let pipelineStateDescriptor = MTLRenderPipelineDescriptor() - pipelineStateDescriptor.label = "Render Pipeline" - pipelineStateDescriptor.vertexFunction = vertexShader - pipelineStateDescriptor.fragmentFunction = fragmentShader - if let renderAttachment = pipelineStateDescriptor.colorAttachments[0] { - renderAttachment.pixelFormat = view.colorPixelFormat - // Pulled all this from SO. I don't know what all this does... - // https://stackoverflow.com/q/43727335/1174185 - renderAttachment.isBlendingEnabled = true - renderAttachment.alphaBlendOperation = .add - renderAttachment.rgbBlendOperation = .add - renderAttachment.sourceRGBBlendFactor = .sourceAlpha - renderAttachment.sourceAlphaBlendFactor = .sourceAlpha - renderAttachment.destinationRGBBlendFactor = .oneMinusSourceAlpha - renderAttachment.destinationAlphaBlendFactor = .oneMinusSourceAlpha - } - renderPipelineState = try device.makeRenderPipelineState(descriptor: pipelineStateDescriptor) - commandQueue = device.makeCommandQueue() + super.init() } + public convenience init(delegate: RendererDelegate) throws { + self.init() + self.delegate = delegate + } + /// MARK: - MTKViewDelegate public func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { - delegate.renderSize = Size(size: size) + delegate?.renderSize = Size(size: size) } public func draw(in view: MTKView) { - let field = delegate.field + guard let field = delegate?.field else { + return + } // Two triangles, plus texture coordinates. let points: [Vertex] = [ @@ -95,7 +111,7 @@ public class Renderer: NSObject, MTKViewDelegate { let buffer = commandQueue.makeCommandBuffer() buffer.label = "Render" - if let renderPass = view.currentRenderPassDescriptor { + if let renderPass = view.currentRenderPassDescriptor, let renderPipelineState = renderPipelineState { let encoder = buffer.makeRenderCommandEncoder(descriptor: renderPass) encoder.label = "Render Pass" encoder.setViewport(MTLViewport(originX: 0.0, originY: 0.0, width: Double(view.drawableSize.width), height: Double(view.drawableSize.height), znear: -1.0, zfar: 1.0))