 		
 		effectRenderer = EffectRenderer(withDevice: device, pixelFormat: view.colorPixelFormat)
 		debugRenderer = DebugRenderer(withDevice: device, pixelFormat: view.colorPixelFormat)
+		
+		frameSemaphore = DispatchSemaphore(value: 1)
 	}
 	
 	func updateProjection(viewSize: CGSize, mapSize: CGSize, centeredOn offset: CGPoint, zoomedTo zoom: Float) {

	}
	
	func prepareFrame(forWorld worldState: RuntimeWorld) {
		let available = AppDelegate.sharedUserState.availableSet
		let visible = AppDelegate.sharedUIState.visibleRegionHashes
		let renderSet = available.intersection(visible)

		guard let markerBuffer = commandQueue.makeCommandBuffer() else { return }
		guard let overlayBuffer = commandQueue.makeCommandBuffer() else { return }
		
		geographyBuffer.label = "Geography buffer"
		geographyBuffer.enqueue()
		markerBuffer.label = "Marker buffer"
		markerBuffer.enqueue()
		overlayBuffer.label = "Overlay buffer"
		overlayBuffer.enqueue()
		
		// Present after the last render pass
		overlayBuffer.addCompletedHandler { buffer in
			drawable.present()
			self.frameSemaphore.signal()
		}

		let available = AppDelegate.sharedUserState.availableSet
		let visible = AppDelegate.sharedUIState.visibleRegionHashes
		let renderSet = available.intersection(visible)	// $ visible gets changed from main thread, while render thread is interested in renderSet...
		let borderedContinents = visible.intersection(worldState.allContinents.keys)	// All visible continents (even if visited)
		let borderedCountries = Set(worldState.visibleCountries.keys)
		
