Merge pull request #3 from GayPizzaSpecifications/parallel-regen

Parallelize chunk generation using fan-out pattern.
This commit is contained in:
a dinosaur 2024-09-02 18:29:32 +10:00 committed by GitHub
commit b1f2f645f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 90 additions and 2 deletions

View File

@ -7,6 +7,9 @@ add_executable(Voxelotl MACOSX_BUNDLE
shadertypes.h
shader.metal
# Common library
Common/ConcurrentDictionary.swift
# Maths library
Math/FloatExtensions.swift
Math/IntegerExtensions.swift
@ -98,6 +101,7 @@ set_source_files_properties(test.png PROPERTIES MACOSX_PACKAGE_LOCATION Resource
#TODO: should use TREE mode as documented in https://cmake.org/cmake/help/latest/command/source_group.html
source_group("Resources" FILES Assets.xcassets test.png)
source_group("Source Files\\Common" REGULAR_EXPRESSION "Common/")
source_group("Source Files" REGULAR_EXPRESSION "\\.(swift|metal)$")
source_group("Source Files\\Random" REGULAR_EXPRESSION "Random/")
source_group("Source Files\\Math" REGULAR_EXPRESSION "Math/")

View File

@ -0,0 +1,73 @@
import Foundation
public class ConcurrentDictionary<V: Hashable, T>: Collection {
private var inner: [V : T]
private var lock: NSLock = .init()
public var keys: Dictionary<V, T>.Keys {
self.locked {
inner.keys
}
}
public var values: Dictionary<V, T>.Values {
self.locked {
self.inner.values
}
}
public var startIndex: Dictionary<V, T>.Index {
self.locked {
self.inner.startIndex
}
}
public var endIndex: Dictionary<V, T>.Index {
self.locked {
self.inner.endIndex
}
}
public init(inner: [V:T]) {
self.inner = inner
}
public convenience init() {
self.init(inner: [:])
}
public func index(after i: Dictionary<V, T>.Index) -> Dictionary<V, T>.Index {
self.locked {
self.inner.index(after: i)
}
}
public subscript(key: V) -> T? {
set(newValue) {
self.locked {
self.inner[key] = newValue
}
}
get {
self.locked {
self.inner[key]
}
}
}
public subscript(index: Dictionary<V, T>.Index) -> Dictionary<V, T>.Element {
self.locked {
self.inner[index]
}
}
fileprivate func locked<X>(_ perform: () -> X) -> X {
self.lock.lock()
defer {
self.lock.unlock()
}
let value = perform()
return value
}
}

View File

@ -62,15 +62,26 @@ public class World {
func generate(width: Int, height: Int, depth: Int, seed: UInt64) {
self._generator.reset(seed: seed)
let orig = SIMD3(width, height, depth) / 2
let localChunks = ConcurrentDictionary<ChunkID, Chunk>()
let queue = OperationQueue()
queue.qualityOfService = .userInitiated
for z in 0..<depth {
for y in 0..<height {
for x in 0..<width {
let chunkID = SIMD3(x, y, z) &- orig
self._chunks[chunkID] = self._generator.makeChunk(id: chunkID)
self._chunkDamage.insert(chunkID)
queue.addOperation {
let chunk = self._generator.makeChunk(id: chunkID)
localChunks[chunkID] = chunk
}
}
}
}
queue.waitUntilAllOperationsAreFinished()
for (chunkID, chunk) in localChunks {
self._chunks[chunkID] = chunk
self._chunkDamage.insert(chunkID)
}
}
func generate(chunkID: ChunkID) {