Skip to content

Commit

Permalink
update renderers
Browse files Browse the repository at this point in the history
  • Loading branch information
eugenebokhan committed Apr 1, 2020
1 parent 9152f99 commit b9a06cd
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 158 deletions.
2 changes: 1 addition & 1 deletion Alloy.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Alloy'
s.version = '0.13.4'
s.version = '0.14.0'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.summary = 'Nano helpers for Metal framework'
s.homepage = 'https://github.com/s1ddok/Alloy'
Expand Down
35 changes: 14 additions & 21 deletions Alloy/Renderers/BoundingBoxesRenderer.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
//
// BoundingBoxesRenderer.swift
// Alloy
//
// Created by Eugene Bokhan on 22/04/2019.
//

import Metal

final public class BoundingBoxesRenderer {
Expand Down Expand Up @@ -64,21 +57,21 @@ final public class BoundingBoxesRenderer {
let verticalWidth = Float(self.lineWidth) / textureWidth

let startPoints: [SIMD2<Float>] = [.init(Float(bboxRect.minX),
Float(bboxRect.minY) - horizontalWidth / 2),
.init(Float(bboxRect.minX) + verticalWidth / 2,
Float(bboxRect.maxY)),
.init(Float(bboxRect.maxX),
Float(bboxRect.maxY) + horizontalWidth / 2),
.init(Float(bboxRect.maxX) - verticalWidth / 2,
Float(bboxRect.minY))]
Float(bboxRect.minY) - horizontalWidth / 2),
.init(Float(bboxRect.minX) + verticalWidth / 2,
Float(bboxRect.maxY)),
.init(Float(bboxRect.maxX),
Float(bboxRect.maxY) + horizontalWidth / 2),
.init(Float(bboxRect.maxX) - verticalWidth / 2,
Float(bboxRect.minY))]
let endPoints: [SIMD2<Float>] = [.init(Float(bboxRect.minX),
Float(bboxRect.maxY) + horizontalWidth / 2),
.init(Float(bboxRect.maxX) - verticalWidth / 2,
Float(bboxRect.maxY)),
.init(Float(bboxRect.maxX),
Float(bboxRect.minY) - horizontalWidth / 2),
.init(Float(bboxRect.minX) + verticalWidth / 2,
Float(bboxRect.minY))]
Float(bboxRect.maxY) + horizontalWidth / 2),
.init(Float(bboxRect.maxX) - verticalWidth / 2,
Float(bboxRect.maxY)),
.init(Float(bboxRect.maxX),
Float(bboxRect.minY) - horizontalWidth / 2),
.init(Float(bboxRect.minX) + verticalWidth / 2,
Float(bboxRect.minY))]
let widths: [Float] = [Float(verticalWidth),
Float(horizontalWidth),
Float(verticalWidth),
Expand Down
33 changes: 13 additions & 20 deletions Alloy/Renderers/LinesRenderer.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
//
// LinesRenderer.swift
// Alloy
//
// Created by Eugene Bokhan on 25/04/2019.
//

import Metal

final public class LinesRenderer {
Expand All @@ -15,7 +8,8 @@ final public class LinesRenderer {
public var lines: [Line] {
set {
self.linesCount = newValue.count
self.linesBuffer = try? self.vertexFunction
self.linesBuffer = try? self.renderPipelineDescriptor
.vertexFunction?
.device
.buffer(with: newValue,
options: .storageModeShared)
Expand All @@ -37,8 +31,7 @@ final public class LinesRenderer {
private var linesBuffer: MTLBuffer?
private var linesCount: Int = 0

private let vertexFunction: MTLFunction
private let fragmentFunction: MTLFunction
private let renderPipelineDescriptor: MTLRenderPipelineDescriptor
private var renderPipelineStates: [MTLPixelFormat: MTLRenderPipelineState] = [:]

// MARK: - Life Cycle
Expand Down Expand Up @@ -66,8 +59,13 @@ final public class LinesRenderer {
guard let vertexFunction = library.makeFunction(name: Self.vertexFunctionName),
let fragmentFunction = library.makeFunction(name: Self.fragmentFunctionName)
else { throw MetalError.MTLLibraryError.functionCreationFailed }
self.vertexFunction = vertexFunction
self.fragmentFunction = fragmentFunction

self.renderPipelineDescriptor = MTLRenderPipelineDescriptor()
self.renderPipelineDescriptor.vertexFunction = vertexFunction
self.renderPipelineDescriptor.fragmentFunction = fragmentFunction
self.renderPipelineDescriptor.colorAttachments[0].pixelFormat = pixelFormat
self.renderPipelineDescriptor.colorAttachments[0].setup(blending: .alpha)

try self.renderPipelineState(for: pixelFormat)
}

Expand All @@ -76,15 +74,10 @@ final public class LinesRenderer {
guard pixelFormat.isRenderable
else { return nil }
if self.renderPipelineStates[pixelFormat] == nil {
let renderPipelineDescriptor = MTLRenderPipelineDescriptor()
renderPipelineDescriptor.vertexFunction = self.vertexFunction
renderPipelineDescriptor.fragmentFunction = self.fragmentFunction
renderPipelineDescriptor.colorAttachments[0].pixelFormat = pixelFormat
renderPipelineDescriptor.colorAttachments[0].setup(blending: .alpha)

self.renderPipelineStates[pixelFormat] = try? self.vertexFunction
self.renderPipelineStates[pixelFormat] = try? self.renderPipelineDescriptor
.vertexFunction?
.device
.makeRenderPipelineState(descriptor: renderPipelineDescriptor)
.makeRenderPipelineState(descriptor: self.renderPipelineDescriptor)
}
return self.renderPipelineStates[pixelFormat]
}
Expand Down
71 changes: 20 additions & 51 deletions Alloy/Renderers/MaskRenderer.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
//
// MaskRenderer.swift
// Alloy
//
// Created by Eugene Bokhan on 28/04/2019.
//

import Metal
import simd

Expand All @@ -19,10 +12,8 @@ public class MaskRenderer {
/// Rectrangle described in a normalized coodrinate system.
public var normalizedRect: CGRect = .zero

private let vertexFunction: MTLFunction
private let fragmentFunction: MTLFunction
private let inversedFragmentFunction: MTLFunction
private var renderPipelineStates: [MTLPixelFormat: [Bool: MTLRenderPipelineState]] = [:]
private let renderPipelineDescriptor: MTLRenderPipelineDescriptor
private var renderPipelineStates: [MTLPixelFormat: MTLRenderPipelineState] = [:]

// MARK: - Life Cycle

Expand All @@ -46,56 +37,32 @@ public class MaskRenderer {
/// - Throws: Function creation error.
public init(library: MTLLibrary,
pixelFormat: MTLPixelFormat = .bgra8Unorm) throws {
guard let vertexFunction = library.makeFunction(name: Self.vertexFunctionName)
guard let vertexFunction = library.makeFunction(name: Self.vertexFunctionName),
let fragmentFunction = library.makeFunction(name: Self.fragmentFunctionName)
else { throw MetalError.MTLLibraryError.functionCreationFailed }
self.vertexFunction = vertexFunction
let constantValues = MTLFunctionConstantValues()
constantValues.set(false, at: 2)
self.fragmentFunction = try library.makeFunction(name: Self.fragmentFunctionName,
constantValues: constantValues)
let inversedConstantValues = MTLFunctionConstantValues()
inversedConstantValues.set(true, at: 2)
self.inversedFragmentFunction = try library.makeFunction(name: Self.fragmentFunctionName,
constantValues: inversedConstantValues)
try self.renderPipelineStatePair(for: pixelFormat)

self.renderPipelineDescriptor = MTLRenderPipelineDescriptor()
self.renderPipelineDescriptor.vertexFunction = vertexFunction
self.renderPipelineDescriptor.fragmentFunction = fragmentFunction
self.renderPipelineDescriptor.colorAttachments[0].pixelFormat = pixelFormat
self.renderPipelineDescriptor.colorAttachments[0].setup(blending: .alpha)

try self.renderPipelineState(for: pixelFormat)
}

@discardableResult
private func renderPipelineStatePair(for pixelFormat: MTLPixelFormat) -> [Bool: MTLRenderPipelineState]? {
private func renderPipelineState(for pixelFormat: MTLPixelFormat) -> MTLRenderPipelineState? {
guard pixelFormat.isRenderable
else { return nil }
if self.renderPipelineStates[pixelFormat] == nil {
let pipelineDescriptor = self.renderPipelineDescriptor(pixelFormat: pixelFormat,
isInversed: false)
let inversedPipelineDescriptor = self.renderPipelineDescriptor(pixelFormat: pixelFormat,
isInversed: true)
guard let pipelineState = try? self.vertexFunction
.device
.makeRenderPipelineState(descriptor: pipelineDescriptor),
let inversedPipelineState = try? self.vertexFunction
.device
.makeRenderPipelineState(descriptor: inversedPipelineDescriptor)
else { return nil }
self.renderPipelineStates[pixelFormat] = [
false: pipelineState,
true: inversedPipelineState
]
self.renderPipelineStates[pixelFormat] = try? self.renderPipelineDescriptor
.vertexFunction?
.device
.makeRenderPipelineState(descriptor: self.renderPipelineDescriptor)
}
return self.renderPipelineStates[pixelFormat]
}

private func renderPipelineDescriptor(pixelFormat: MTLPixelFormat,
isInversed: Bool) -> MTLRenderPipelineDescriptor {
let renderPipelineDescriptor = MTLRenderPipelineDescriptor()
renderPipelineDescriptor.vertexFunction = self.vertexFunction
renderPipelineDescriptor.fragmentFunction = isInversed
? self.inversedFragmentFunction
: self.fragmentFunction
renderPipelineDescriptor.colorAttachments[0].pixelFormat = pixelFormat
renderPipelineDescriptor.colorAttachments[0].setup(blending: .alpha)
return renderPipelineDescriptor
}

// MARK: - Helpers

private func constructRectangle() -> Rectangle {
Expand Down Expand Up @@ -141,7 +108,7 @@ public class MaskRenderer {
isInversed: Bool,
renderEncoder: MTLRenderCommandEncoder) {
guard self.normalizedRect != .zero,
let renderPipelineState = self.renderPipelineStatePair(for: pixelFormat)?[isInversed]
let renderPipelineState = self.renderPipelineState(for: pixelFormat)
else { return }

// Push a debug group allowing us to identify render commands in the GPU Frame Capture tool.
Expand All @@ -156,6 +123,8 @@ public class MaskRenderer {
index: 0)
renderEncoder.set(fragmentValue: self.color,
at: 0)
renderEncoder.set(fragmentValue: isInversed,
at: 1)
// Draw.
renderEncoder.drawPrimitives(type: .triangleStrip,
vertexStart: 0,
Expand Down
37 changes: 15 additions & 22 deletions Alloy/Renderers/PointsRenderer.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
//
// PointsRenderer.swift
// Alloy
//
// Created by Eugene Bokhan on 26/04/2019.
//

import Metal

final public class PointsRenderer {
Expand All @@ -15,7 +8,8 @@ final public class PointsRenderer {
public var pointsPositions: [SIMD2<Float>] {
set {
self.pointCount = newValue.count
self.pointsPositionsBuffer = try? self.vertexFunction
self.pointsPositionsBuffer = try? self.renderPipelineDescriptor
.vertexFunction?
.device
.buffer(with: newValue,
options: .storageModeShared)
Expand All @@ -38,8 +32,7 @@ final public class PointsRenderer {
private var pointsPositionsBuffer: MTLBuffer?
private var pointCount: Int = 0

private let vertexFunction: MTLFunction
private let fragmentFunction: MTLFunction
private let renderPipelineDescriptor: MTLRenderPipelineDescriptor
private var renderPipelineStates: [MTLPixelFormat: MTLRenderPipelineState] = [:]

// MARK: - Life Cycle
Expand Down Expand Up @@ -67,8 +60,13 @@ final public class PointsRenderer {
guard let vertexFunction = library.makeFunction(name: Self.vertexFunctionName),
let fragmentFunction = library.makeFunction(name: Self.fragmentFunctionName)
else { throw MetalError.MTLLibraryError.functionCreationFailed }
self.vertexFunction = vertexFunction
self.fragmentFunction = fragmentFunction

self.renderPipelineDescriptor = MTLRenderPipelineDescriptor()
self.renderPipelineDescriptor.vertexFunction = vertexFunction
self.renderPipelineDescriptor.fragmentFunction = fragmentFunction
self.renderPipelineDescriptor.colorAttachments[0].pixelFormat = pixelFormat
self.renderPipelineDescriptor.colorAttachments[0].setup(blending: .alpha)

try self.renderPipelineState(for: pixelFormat)
}

Expand All @@ -77,15 +75,10 @@ final public class PointsRenderer {
guard pixelFormat.isRenderable
else { return nil }
if self.renderPipelineStates[pixelFormat] == nil {
let renderPipelineDescriptor = MTLRenderPipelineDescriptor()
renderPipelineDescriptor.vertexFunction = self.vertexFunction
renderPipelineDescriptor.fragmentFunction = self.fragmentFunction
renderPipelineDescriptor.colorAttachments[0].pixelFormat = pixelFormat
renderPipelineDescriptor.colorAttachments[0].setup(blending: .alpha)

self.renderPipelineStates[pixelFormat] = try? self.vertexFunction
self.renderPipelineStates[pixelFormat] = try? self.renderPipelineDescriptor
.vertexFunction?
.device
.makeRenderPipelineState(descriptor: renderPipelineDescriptor)
.makeRenderPipelineState(descriptor: self.renderPipelineDescriptor)
}
return self.renderPipelineStates[pixelFormat]
}
Expand All @@ -101,10 +94,10 @@ final public class PointsRenderer {
commandBuffer: MTLCommandBuffer) throws {
guard let renderTarget = renderPassDescriptor.colorAttachments[0].texture
else { return }
commandBuffer.render(descriptor: renderPassDescriptor, { renderEncoder in
commandBuffer.render(descriptor: renderPassDescriptor) { renderEncoder in
self.render(pixelFormat: renderTarget.pixelFormat,
renderEncoder: renderEncoder)
})
}
}

/// Render points in a target texture.
Expand Down
30 changes: 11 additions & 19 deletions Alloy/Renderers/RectangleRenderer.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
//
// RectangleRenderer.swift
// Alloy
//
// Created by Eugene Bokhan on 23/04/2019.
//

import Metal

final public class RectangleRenderer {
Expand All @@ -16,8 +9,7 @@ final public class RectangleRenderer {
/// Rectrangle described in a normalized coodrinate system.
public var normalizedRect: CGRect = .zero

private let vertexFunction: MTLFunction
private let fragmentFunction: MTLFunction
private let renderPipelineDescriptor: MTLRenderPipelineDescriptor
private var renderPipelineStates: [MTLPixelFormat: MTLRenderPipelineState] = [:]


Expand Down Expand Up @@ -46,8 +38,13 @@ final public class RectangleRenderer {
guard let vertexFunction = library.makeFunction(name: Self.vertexFunctionName),
let fragmentFunction = library.makeFunction(name: Self.fragmentFunctionName)
else { throw MetalError.MTLLibraryError.functionCreationFailed }
self.vertexFunction = vertexFunction
self.fragmentFunction = fragmentFunction

self.renderPipelineDescriptor = MTLRenderPipelineDescriptor()
self.renderPipelineDescriptor.vertexFunction = vertexFunction
self.renderPipelineDescriptor.fragmentFunction = fragmentFunction
self.renderPipelineDescriptor.colorAttachments[0].pixelFormat = pixelFormat
self.renderPipelineDescriptor.colorAttachments[0].setup(blending: .alpha)

try self.renderPipelineState(for: pixelFormat)
}

Expand All @@ -56,15 +53,10 @@ final public class RectangleRenderer {
guard pixelFormat.isRenderable
else { return nil }
if self.renderPipelineStates[pixelFormat] == nil {
let renderPipelineDescriptor = MTLRenderPipelineDescriptor()
renderPipelineDescriptor.vertexFunction = self.vertexFunction
renderPipelineDescriptor.fragmentFunction = self.fragmentFunction
renderPipelineDescriptor.colorAttachments[0].pixelFormat = pixelFormat
renderPipelineDescriptor.colorAttachments[0].setup(blending: .alpha)

self.renderPipelineStates[pixelFormat] = try? self.vertexFunction
self.renderPipelineStates[pixelFormat] = try? self.renderPipelineDescriptor
.vertexFunction?
.device
.makeRenderPipelineState(descriptor: renderPipelineDescriptor)
.makeRenderPipelineState(descriptor: self.renderPipelineDescriptor)
}
return self.renderPipelineStates[pixelFormat]
}
Expand Down
Loading

0 comments on commit b9a06cd

Please sign in to comment.