diff --git a/Terrain2/Algorithms.swift b/Terrain2/Algorithms.swift index b74a294..c9be207 100644 --- a/Terrain2/Algorithms.swift +++ b/Terrain2/Algorithms.swift @@ -329,18 +329,24 @@ public class DiamondSquareGenerator: TerrainGenerator { } var algorithm: Algorithm - let texture: MTLTexture - let textureSemaphore = DispatchSemaphore(value: 1) + let textures: [MTLTexture] + private var activeTexture: Int = 0 init?(device: MTLDevice) { let size = DiamondSquareGenerator.textureSize - let desc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .r32Float, width: size.width, height: size.height, mipmapped: false) - desc.usage = [.shaderRead, .shaderWrite] - guard let tex = device.makeTexture(descriptor: desc) else { + do { + textures = try (0..<2).map { (i: Int) -> MTLTexture in + let desc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .r32Float, width: size.width, height: size.height, mipmapped: false) + desc.usage = [.shaderRead, .shaderWrite] + guard let tex = device.makeTexture(descriptor: desc) else { + throw KernelError.textureCreationFailed + } + return tex + } + } catch { print("Couldn't create texture for Diamond-Squares algorithm.") return nil } - texture = tex algorithm = Algorithm(grid: Box(origin: Point(), size: Size(w: DiamondSquareGenerator.textureSize.width, h: DiamondSquareGenerator.textureSize.height))) } @@ -348,13 +354,15 @@ public class DiamondSquareGenerator: TerrainGenerator { func render() { let heightMap = algorithm.render() let region = MTLRegion(origin: MTLOrigin(), size: DiamondSquareGenerator.textureSize) - texture.replace(region: region, mipmapLevel: 0, withBytes: heightMap, bytesPerRow: MemoryLayout.stride * DiamondSquareGenerator.textureSize.width) + let newActiveTexture = (activeTexture + 1) % textures.count + textures[newActiveTexture].replace(region: region, mipmapLevel: 0, withBytes: heightMap, bytesPerRow: MemoryLayout.stride * DiamondSquareGenerator.textureSize.width) + activeTexture = newActiveTexture } // MARK: Algorithm var outTexture: MTLTexture { - return texture + return textures[activeTexture] } func encode(in encoder: MTLComputeCommandEncoder) { diff --git a/Terrain2/Renderer.swift b/Terrain2/Renderer.swift index 1777b20..eb4b83a 100644 --- a/Terrain2/Renderer.swift +++ b/Terrain2/Renderer.swift @@ -34,14 +34,13 @@ class Renderer: NSObject, MTKViewDelegate { let inFlightSemaphore = DispatchSemaphore(value: maxBuffersInFlight) let regenerationSemaphore = DispatchSemaphore(value: 1) + let generatorQueue = DispatchQueue(label: "me.erynwells.Terrain.generatorQueue") + var uniformBufferOffset = 0 - var uniformBufferIndex = 0 - var uniforms: UnsafeMutablePointer var projectionMatrix: matrix_float4x4 = matrix_float4x4() - var rotation: Float = 0 var terrain: Terrain @@ -142,7 +141,13 @@ class Renderer: NSObject, MTKViewDelegate { func scheduleAlgorithmIteration() { regenerationSemaphore.wait() - iterateTerrainAlgorithm = true + if !terrain.generator.needsGPU { + generatorQueue.async { + print("Rendering terrain...") + self.terrain.generator.render() + print("Rendering terrain...complete!") + } + } regenerationSemaphore.signal() } @@ -161,9 +166,6 @@ class Renderer: NSObject, MTKViewDelegate { if iterateTerrainAlgorithm { if terrain.generator.needsGPU { terrain.generator.updateUniforms() - } else { - print("Rendering terrain...") - terrain.generator.render() } } @@ -198,7 +200,7 @@ class Renderer: NSObject, MTKViewDelegate { self.updateGameState() - if iterateTerrainAlgorithm && !terrain.generator.needsGPU, let computeEncoder = commandBuffer.makeComputeCommandEncoder() { + if iterateTerrainAlgorithm && terrain.generator.needsGPU, let computeEncoder = commandBuffer.makeComputeCommandEncoder() { print("Scheduling terrain generator iteration with \(terrain.generator.name) algorithm") computeEncoder.label = "Generator Encoder" computeEncoder.pushDebugGroup("Generate Terrain: \(terrain.generator.name)")