mirror of
https://github.com/GayPizzaSpecifications/voxelotl-engine.git
synced 2025-08-02 21:00:57 +00:00
allow for up to 3 frames to be processed at once
This commit is contained in:
parent
5f69da369d
commit
5b97a02288
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user