Skip to content

Commit

Permalink
use global buffer index
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas Märki <maerki@ubique.ch>
  • Loading branch information
maerki committed Nov 4, 2024
1 parent 5381563 commit e9a09ff
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 51 deletions.
22 changes: 7 additions & 15 deletions ios/graphics/Model/MultiBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@
import Metal
import simd

private let bufferCount = 3 // Triple buffering

public struct MultiBuffer<DataType> {
// Warning: Seems like suited to be generic
// But makeBuffer &reference does not like generic data
var buffers: [MTLBuffer]
var currentBufferIndex = 0
var currentFrameId = -1

fileprivate init(buffers: [MTLBuffer]) {
self.buffers = buffers
Expand All @@ -24,21 +20,15 @@ public struct MultiBuffer<DataType> {
public mutating func getNextBuffer(_ context: RenderingContext)
-> MTLBuffer?
{
if context.frameId != currentFrameId {
currentBufferIndex = (currentBufferIndex + 1) % bufferCount
currentFrameId = context.frameId
}
guard currentBufferIndex < buffers.count else {
return nil
}
return buffers[currentBufferIndex]
return buffers[context.currentBufferIndex]
}
}

extension MultiBuffer<simd_float1> {
public init(device: MTLDevice) {
var initialMutable = simd_float1(1.0)
let buffers: [MTLBuffer] = (0..<bufferCount).compactMap { _ in
let buffers: [MTLBuffer] = (0..<RenderingContext.bufferCount).compactMap
{ _ in
device
.makeBuffer(
bytes: &initialMutable,
Expand All @@ -52,7 +42,8 @@ extension MultiBuffer<simd_float1> {
extension MultiBuffer<simd_float4> {
public init(device: MTLDevice) {
var initialMutable = simd_float4(0.0, 0.0, 0.0, 0.0)
let buffers: [MTLBuffer] = (0..<bufferCount).compactMap { _ in
let buffers: [MTLBuffer] = (0..<RenderingContext.bufferCount).compactMap
{ _ in
device
.makeBuffer(
bytes: &initialMutable,
Expand All @@ -66,7 +57,8 @@ extension MultiBuffer<simd_float4> {
extension MultiBuffer<simd_float4x4> {
public init(device: MTLDevice) {
var initialMutable = simd_float4x4(1.0)
let buffers: [MTLBuffer] = (0..<bufferCount).compactMap { _ in
let buffers: [MTLBuffer] = (0..<RenderingContext.bufferCount).compactMap
{ _ in
device
.makeBuffer(
bytes: &initialMutable,
Expand Down
91 changes: 55 additions & 36 deletions ios/graphics/RenderingContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ public class RenderingContext: NSObject, @unchecked Sendable {
public weak var encoder: MTLRenderCommandEncoder?
public weak var computeEncoder: MTLComputeCommandEncoder?
public weak var sceneView: MCMapView?
private(set) var frameId: Int = 0

public static let bufferCount = 3 // Triple buffering
private(set) var currentBufferIndex = 0

public func beginFrame() {
frameId = (frameId + 1) % 1000
currentBufferIndex =
(currentBufferIndex + 1) % RenderingContext.bufferCount
}

public var cullMode: MCRenderingCullMode?
Expand All @@ -36,7 +39,8 @@ public class RenderingContext: NSObject, @unchecked Sendable {
let depthStencilDescriptor = MTLDepthStencilDescriptor()
depthStencilDescriptor.frontFaceStencil = descriptor
depthStencilDescriptor.backFaceStencil = descriptor
return MetalContext.current.device.makeDepthStencilState(descriptor: depthStencilDescriptor)
return MetalContext.current.device.makeDepthStencilState(
descriptor: depthStencilDescriptor)
}()

public lazy var polygonMask: MTLDepthStencilState? = {
Expand All @@ -49,7 +53,8 @@ public class RenderingContext: NSObject, @unchecked Sendable {
let depthStencilDescriptor = MTLDepthStencilDescriptor()
depthStencilDescriptor.frontFaceStencil = descriptor
depthStencilDescriptor.backFaceStencil = descriptor
return MetalContext.current.device.makeDepthStencilState(descriptor: depthStencilDescriptor)
return MetalContext.current.device.makeDepthStencilState(
descriptor: depthStencilDescriptor)
}()

public lazy var defaultMask: MTLDepthStencilState? = {
Expand All @@ -59,7 +64,8 @@ public class RenderingContext: NSObject, @unchecked Sendable {
let depthStencilDescriptor = MTLDepthStencilDescriptor()
depthStencilDescriptor.frontFaceStencil = descriptor
depthStencilDescriptor.backFaceStencil = descriptor
return MetalContext.current.device.makeDepthStencilState(descriptor: depthStencilDescriptor)
return MetalContext.current.device.makeDepthStencilState(
descriptor: depthStencilDescriptor)
}()

public var aspectRatio: Float {
Expand All @@ -72,7 +78,9 @@ public class RenderingContext: NSObject, @unchecked Sendable {

var currentPipeline: MTLRenderPipelineState?

open func setRenderPipelineStateIfNeeded(_ pipelineState: MTLRenderPipelineState) {
open func setRenderPipelineStateIfNeeded(
_ pipelineState: MTLRenderPipelineState
) {
guard currentPipeline?.hash != pipelineState.hash else {
return
}
Expand All @@ -83,34 +91,40 @@ public class RenderingContext: NSObject, @unchecked Sendable {
/// a Quad that fills the whole viewport
/// this is needed to clear the stencilbuffer
lazy var stencilClearQuad: Quad2d = {
let quad = Quad2d(shader: ClearStencilShader(), metalContext: .current, label: "ClearStencil")
quad.setFrame(.init(topLeft: .init(x: 1, y: -1, z: 0),
topRight: .init(x: -1, y: -1, z: 0),
bottomRight: .init(x: -1, y: 1, z: 0),
bottomLeft: .init(x: 1, y: 1, z: 0)),
textureCoordinates: .init(x: 0, y: 0, width: 0, height: 0), origin: .init(x: 0, y: 0, z: 0), is3d: false)
let quad = Quad2d(
shader: ClearStencilShader(), metalContext: .current,
label: "ClearStencil")
quad.setFrame(
.init(
topLeft: .init(x: 1, y: -1, z: 0),
topRight: .init(x: -1, y: -1, z: 0),
bottomRight: .init(x: -1, y: 1, z: 0),
bottomLeft: .init(x: 1, y: 1, z: 0)),
textureCoordinates: .init(x: 0, y: 0, width: 0, height: 0),
origin: .init(x: 0, y: 0, z: 0), is3d: false)
quad.setup(self)
return quad
}()

public func clearStencilBuffer() {
guard let encoder else { return }
stencilClearQuad.render(encoder: encoder,
context: self,
renderPass: .init(renderPass: 0, isPassMasked: false),
vpMatrix: 0,
mMatrix: 0,
origin: .init(x: 0, y: 0, z: 0),
isMasked: false,
screenPixelAsRealMeterFactor: 1)
stencilClearQuad.render(
encoder: encoder,
context: self,
renderPass: .init(renderPass: 0, isPassMasked: false),
vpMatrix: 0,
mMatrix: 0,
origin: .init(x: 0, y: 0, z: 0),
isMasked: false,
screenPixelAsRealMeterFactor: 1)
}
}

extension RenderingContext: MCRenderingContextInterface {
public func setCulling(_ mode: MCRenderingCullMode) {
self.cullMode = mode
}

public func preRenderStencilMask() {
}

Expand All @@ -125,14 +139,14 @@ extension RenderingContext: MCRenderingContextInterface {
Set the cullMode inverse in order to be consistent with opengl
*/
switch cullMode {
case .BACK:
encoder?.setCullMode(.front)
case .FRONT:
encoder?.setCullMode(.back)
case .NONE:
encoder?.setCullMode(.none)
@unknown default:
assertionFailure()
case .BACK:
encoder?.setCullMode(.front)
case .FRONT:
encoder?.setCullMode(.back)
case .NONE:
encoder?.setCullMode(.none)
@unknown default:
assertionFailure()
}
}
}
Expand Down Expand Up @@ -160,13 +174,17 @@ extension RenderingContext: MCRenderingContextInterface {
var s = CGSize(width: 1.0, height: 1.0)
if Thread.isMainThread {
MainActor.assumeIsolated {
s = self.sceneView?.frame.size ?? CGSize(width: 1.0, height: 1.0)
s =
self.sceneView?.frame.size
?? CGSize(width: 1.0, height: 1.0)
s.width = UIScreen.main.nativeScale * s.width
s.height = UIScreen.main.nativeScale * s.height
}
} else {
DispatchQueue.main.sync {
s = self.sceneView?.frame.size ?? CGSize(width: 1.0, height: 1.0)
s =
self.sceneView?.frame.size
?? CGSize(width: 1.0, height: 1.0)
s.width = UIScreen.main.nativeScale * s.width
s.height = UIScreen.main.nativeScale * s.height
}
Expand All @@ -182,14 +200,15 @@ extension RenderingContext: MCRenderingContextInterface {
}
}

private extension MCRectI {
var scissorRect: MTLScissorRect {
MTLScissorRect(x: Int(x), y: Int(y), width: Int(width), height: Int(height))
extension MCRectI {
fileprivate var scissorRect: MTLScissorRect {
MTLScissorRect(
x: Int(x), y: Int(y), width: Int(width), height: Int(height))
}
}

private extension MCVec2I {
var scissorRect: MTLScissorRect {
extension MCVec2I {
fileprivate var scissorRect: MTLScissorRect {
MTLScissorRect(x: 0, y: 0, width: Int(x), height: Int(y))
}
}

0 comments on commit e9a09ff

Please sign in to comment.