mirror of
				https://github.com/GayPizzaSpecifications/voxelotl-engine.git
				synced 2025-11-04 10:59:39 +00:00 
			
		
		
		
	allow for up to 3 frames to be processed at once
This commit is contained in:
		@ -40,9 +40,10 @@ fileprivate let cubeIndices: [UInt16] = [
 | 
				
			|||||||
  20, 21, 22, 22, 21, 23
 | 
					  20, 21, 22, 22, 21, 23
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Renderer {
 | 
					fileprivate let numFramesInFlight: Int = 3
 | 
				
			||||||
  private let depthFormat: MTLPixelFormat = .depth16Unorm
 | 
					fileprivate let depthFormat: MTLPixelFormat = .depth16Unorm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Renderer {
 | 
				
			||||||
  private var device: MTLDevice
 | 
					  private var device: MTLDevice
 | 
				
			||||||
  private var layer: CAMetalLayer
 | 
					  private var layer: CAMetalLayer
 | 
				
			||||||
  private var viewport: MTLViewport
 | 
					  private var viewport: MTLViewport
 | 
				
			||||||
@ -52,12 +53,15 @@ class Renderer {
 | 
				
			|||||||
  private let passDescription = MTLRenderPassDescriptor()
 | 
					  private let passDescription = MTLRenderPassDescriptor()
 | 
				
			||||||
  private var pso: MTLRenderPipelineState
 | 
					  private var pso: MTLRenderPipelineState
 | 
				
			||||||
  private var depthStencilState: MTLDepthStencilState
 | 
					  private var depthStencilState: MTLDepthStencilState
 | 
				
			||||||
  private var depthStencilTexture: MTLTexture
 | 
					  private var depthTextures: [MTLTexture]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private var vtxBuffer: MTLBuffer, idxBuffer: MTLBuffer
 | 
					  private var vtxBuffer: MTLBuffer, idxBuffer: MTLBuffer
 | 
				
			||||||
  private var defaultTexture: MTLTexture
 | 
					  private var defaultTexture: MTLTexture
 | 
				
			||||||
  private var cubeTexture: MTLTexture? = nil
 | 
					  private var cubeTexture: MTLTexture? = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private let inFlightSemaphore = DispatchSemaphore(value: numFramesInFlight)
 | 
				
			||||||
 | 
					  private var frame = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fileprivate static func createMetalDevice() -> MTLDevice? {
 | 
					  fileprivate static func createMetalDevice() -> MTLDevice? {
 | 
				
			||||||
    MTLCopyAllDevices().reduce(nil, { best, dev in
 | 
					    MTLCopyAllDevices().reduce(nil, { best, dev in
 | 
				
			||||||
      if best == nil { dev }
 | 
					      if best == nil { dev }
 | 
				
			||||||
@ -95,11 +99,12 @@ class Renderer {
 | 
				
			|||||||
    passDescription.depthAttachment.storeAction = .dontCare
 | 
					    passDescription.depthAttachment.storeAction = .dontCare
 | 
				
			||||||
    passDescription.depthAttachment.clearDepth  = 1.0
 | 
					    passDescription.depthAttachment.clearDepth  = 1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    guard let depthStencilTexture = Self.createDepthTexture(device, size, format: depthFormat) else {
 | 
					    self.depthTextures = try (0..<numFramesInFlight).map { _ in
 | 
				
			||||||
      throw RendererError.initFailure("Failed to create depth buffer")
 | 
					      guard let depthStencilTexture = Self.createDepthTexture(device, size, format: depthFormat) else {
 | 
				
			||||||
 | 
					        throw RendererError.initFailure("Failed to create depth buffer")
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return depthStencilTexture
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    self.depthStencilTexture = depthStencilTexture
 | 
					 | 
				
			||||||
    passDescription.depthAttachment.texture = self.depthStencilTexture
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let stencilDepthDescription = MTLDepthStencilDescriptor()
 | 
					    let stencilDepthDescription = MTLDepthStencilDescriptor()
 | 
				
			||||||
    stencilDepthDescription.depthCompareFunction = .less  // OpenGL default
 | 
					    stencilDepthDescription.depthCompareFunction = .less  // OpenGL default
 | 
				
			||||||
@ -266,9 +271,8 @@ class Renderer {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  func resize(size: SIMD2<Int>) {
 | 
					  func resize(size: SIMD2<Int>) {
 | 
				
			||||||
    if Int(self.viewport.width) != size.x || Int(self.viewport.height) != size.y {
 | 
					    if Int(self.viewport.width) != size.x || Int(self.viewport.height) != size.y {
 | 
				
			||||||
      if let depthStencilTexture = Self.createDepthTexture(device, size, format: depthFormat) {
 | 
					      self.depthTextures = (0..<numFramesInFlight).map { _ in
 | 
				
			||||||
        self.depthStencilTexture = depthStencilTexture
 | 
					        Self.createDepthTexture(device, size, format: depthFormat)!
 | 
				
			||||||
        passDescription.depthAttachment.texture = self.depthStencilTexture
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -307,15 +311,23 @@ class Renderer {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    var uniforms = ShaderUniforms(projView: projection * view)
 | 
					    var uniforms = ShaderUniforms(projView: projection * view)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Lock the semaphore here if too many frames are "in flight"
 | 
				
			||||||
 | 
					    _ = inFlightSemaphore.wait(timeout: .distantFuture)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    guard let rt = layer.nextDrawable() else {
 | 
					    guard let rt = layer.nextDrawable() else {
 | 
				
			||||||
      throw RendererError.drawFailure("Failed to get next drawable render target")
 | 
					      throw RendererError.drawFailure("Failed to get next drawable render target")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    passDescription.colorAttachments[0].texture = rt.texture
 | 
					    passDescription.colorAttachments[0].texture = rt.texture
 | 
				
			||||||
 | 
					    passDescription.depthAttachment.texture = self.depthTextures[self.frame]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    guard let commandBuf: MTLCommandBuffer = queue.makeCommandBuffer() else {
 | 
					    guard let commandBuf: MTLCommandBuffer = queue.makeCommandBuffer() else {
 | 
				
			||||||
      throw RendererError.drawFailure("Failed to make command buffer from queue")
 | 
					      throw RendererError.drawFailure("Failed to make command buffer from queue")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    commandBuf.addCompletedHandler { _ in
 | 
				
			||||||
 | 
					      self.inFlightSemaphore.signal()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    guard let encoder = commandBuf.makeRenderCommandEncoder(descriptor: passDescription) else {
 | 
					    guard let encoder = commandBuf.makeRenderCommandEncoder(descriptor: passDescription) else {
 | 
				
			||||||
      throw RendererError.drawFailure("Failed to make render encoder from command buffer")
 | 
					      throw RendererError.drawFailure("Failed to make render encoder from command buffer")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -350,6 +362,11 @@ class Renderer {
 | 
				
			|||||||
    encoder.endEncoding()
 | 
					    encoder.endEncoding()
 | 
				
			||||||
    commandBuf.present(rt)
 | 
					    commandBuf.present(rt)
 | 
				
			||||||
    commandBuf.commit()
 | 
					    commandBuf.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self.frame &+= 1
 | 
				
			||||||
 | 
					    if self.frame == numFramesInFlight {
 | 
				
			||||||
 | 
					      self.frame = 0
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user