mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-16 10:55:01 -04:00
world renderer: remove locking hell
This commit is contained in:
parent
5672bacb75
commit
a4928205f0
@ -31,7 +31,7 @@ class LoadedMeshes(
|
||||
|
||||
|
||||
fun cleanup(lock: Boolean) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
|
||||
val iterator = meshes.iterator()
|
||||
for ((chunkPosition, sections) in iterator) {
|
||||
@ -42,21 +42,22 @@ class LoadedMeshes(
|
||||
renderer.unloadingQueue.forceQueue(sections.values)
|
||||
}
|
||||
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
fun clear(lock: Boolean) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
|
||||
for (sections in meshes.values) {
|
||||
renderer.unloadingQueue.forceQueue(sections.values, lock)
|
||||
}
|
||||
this.meshes.clear()
|
||||
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
fun unload(position: ChunkPosition, lock: Boolean) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
|
||||
val meshes = this.meshes.remove(position)
|
||||
|
||||
@ -64,11 +65,11 @@ class LoadedMeshes(
|
||||
renderer.unloadingQueue.forceQueue(meshes.values, lock)
|
||||
}
|
||||
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
fun unload(position: ChunkPosition, sectionHeight: Int, lock: Boolean) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
|
||||
val meshes = this.meshes[position]
|
||||
|
||||
@ -82,7 +83,7 @@ class LoadedMeshes(
|
||||
}
|
||||
}
|
||||
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
|
||||
@ -113,10 +114,12 @@ class LoadedMeshes(
|
||||
}
|
||||
|
||||
fun lock() {
|
||||
renderer.lock.acquire()
|
||||
this.lock.lock()
|
||||
}
|
||||
|
||||
fun unlock() {
|
||||
this.lock.unlock()
|
||||
renderer.lock.release()
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ package de.bixilon.minosoft.gui.rendering.world
|
||||
|
||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.kutil.concurrent.lock.simple.SimpleLock
|
||||
import de.bixilon.kutil.latch.CountUpAndDownLatch
|
||||
import de.bixilon.kutil.observer.DataObserver.Companion.observe
|
||||
import de.bixilon.minosoft.config.key.KeyActions
|
||||
@ -60,6 +61,7 @@ class WorldRenderer(
|
||||
private val shader = renderSystem.createShader(minosoft("world")) { WorldShader(it, false) }
|
||||
private val transparentShader = renderSystem.createShader(minosoft("world")) { WorldShader(it, true) }
|
||||
private val textShader = renderSystem.createShader(minosoft("world/text")) { WorldTextShader(it) }
|
||||
val lock = SimpleLock()
|
||||
val world: World = connection.world
|
||||
|
||||
val loaded = LoadedMeshes(this)
|
||||
@ -111,13 +113,10 @@ class WorldRenderer(
|
||||
}
|
||||
}
|
||||
|
||||
renderWindow.inputHandler.registerKeyCallback(
|
||||
"minosoft:clear_chunk_cache".toResourceLocation(),
|
||||
KeyBinding(
|
||||
renderWindow.inputHandler.registerKeyCallback("minosoft:clear_chunk_cache".toResourceLocation(), KeyBinding(
|
||||
KeyActions.MODIFIER to setOf(KeyCodes.KEY_F3),
|
||||
KeyActions.PRESS to setOf(KeyCodes.KEY_A),
|
||||
)
|
||||
) { clearChunkCache() }
|
||||
)) { clearChunkCache() }
|
||||
|
||||
profile.rendering::antiMoirePattern.observe(this) { clearChunkCache() }
|
||||
val rendering = connection.profiles.rendering
|
||||
@ -127,26 +126,17 @@ class WorldRenderer(
|
||||
val distance = maxOf(viewDistance, profile.simulationDistance)
|
||||
if (distance < this.previousViewDistance) {
|
||||
// Unload all chunks(-sections) that are out of view distance
|
||||
culledQueue.lock()
|
||||
meshingQueue.lock()
|
||||
loadingQueue.lock()
|
||||
unloadingQueue.lock()
|
||||
loaded.lock()
|
||||
lock.lock()
|
||||
|
||||
loaded.cleanup(false)
|
||||
culledQueue.cleanup(false)
|
||||
|
||||
meshingQueue.cleanup()
|
||||
meshingQueue.cleanup(false)
|
||||
|
||||
meshingQueue.tasks.cleanup()
|
||||
loadingQueue.cleanup(false)
|
||||
|
||||
|
||||
loaded.unlock()
|
||||
meshingQueue.unlock()
|
||||
culledQueue.unlock()
|
||||
loadingQueue.unlock()
|
||||
unloadingQueue.unlock()
|
||||
lock.unlock()
|
||||
} else {
|
||||
master.tryQueue(world)
|
||||
}
|
||||
@ -166,16 +156,10 @@ class WorldRenderer(
|
||||
}
|
||||
|
||||
fun unloadWorld() {
|
||||
culledQueue.lock()
|
||||
meshingQueue.lock()
|
||||
loadingQueue.lock()
|
||||
loaded.lock()
|
||||
|
||||
|
||||
lock.lock()
|
||||
|
||||
meshingQueue.tasks.interruptAll()
|
||||
|
||||
unloadingQueue.lock()
|
||||
loaded.clear(false)
|
||||
|
||||
culledQueue.clear(false)
|
||||
@ -184,19 +168,11 @@ class WorldRenderer(
|
||||
|
||||
clearVisibleNextFrame = true
|
||||
|
||||
loaded.unlock()
|
||||
meshingQueue.unlock()
|
||||
culledQueue.unlock()
|
||||
loadingQueue.unlock()
|
||||
lock.unlock()
|
||||
}
|
||||
|
||||
fun unloadChunk(chunkPosition: Vec2i) {
|
||||
culledQueue.lock()
|
||||
meshingQueue.lock()
|
||||
loadingQueue.lock()
|
||||
unloadingQueue.lock()
|
||||
loaded.lock()
|
||||
|
||||
lock.lock()
|
||||
|
||||
meshingQueue.tasks.interrupt(chunkPosition)
|
||||
|
||||
@ -209,20 +185,13 @@ class WorldRenderer(
|
||||
|
||||
loaded.unload(chunkPosition, false)
|
||||
|
||||
loaded.unlock()
|
||||
culledQueue.unlock()
|
||||
loadingQueue.unlock()
|
||||
unloadingQueue.unlock()
|
||||
meshingQueue.unlock()
|
||||
lock.unlock()
|
||||
}
|
||||
|
||||
|
||||
fun queueItemUnload(item: WorldQueueItem) {
|
||||
culledQueue.lock()
|
||||
meshingQueue.lock()
|
||||
loadingQueue.lock()
|
||||
unloadingQueue.lock()
|
||||
loaded.lock()
|
||||
lock.lock()
|
||||
|
||||
loaded.unload(item.chunkPosition, item.sectionHeight, false)
|
||||
|
||||
culledQueue.remove(item.chunkPosition, item.sectionHeight, false)
|
||||
@ -233,11 +202,7 @@ class WorldRenderer(
|
||||
|
||||
meshingQueue.tasks.interrupt(item.chunkPosition, item.sectionHeight)
|
||||
|
||||
loaded.unlock()
|
||||
meshingQueue.unlock()
|
||||
culledQueue.unlock()
|
||||
loadingQueue.unlock()
|
||||
unloadingQueue.unlock()
|
||||
lock.unlock()
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,7 +31,7 @@ class CulledQueue(
|
||||
|
||||
|
||||
fun cleanup(lock: Boolean) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
val iterator = queue.iterator()
|
||||
for ((chunkPosition, _) in iterator) {
|
||||
if (renderer.visibilityGraph.isChunkVisible(chunkPosition)) {
|
||||
@ -39,34 +39,36 @@ class CulledQueue(
|
||||
}
|
||||
iterator.remove()
|
||||
}
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
fun lock() {
|
||||
renderer.lock.acquire()
|
||||
this.lock.lock()
|
||||
}
|
||||
|
||||
fun unlock() {
|
||||
this.lock.unlock()
|
||||
renderer.lock.release()
|
||||
}
|
||||
|
||||
|
||||
fun clear(lock: Boolean) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
this.queue.clear()
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
fun remove(position: ChunkPosition, lock: Boolean) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
|
||||
queue -= position
|
||||
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
fun remove(position: ChunkPosition, height: SectionHeight, lock: Boolean) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
|
||||
queue[position]?.let {
|
||||
if (it.remove(height) && it.isEmpty()) {
|
||||
@ -74,7 +76,7 @@ class CulledQueue(
|
||||
}
|
||||
}
|
||||
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,9 +34,9 @@ class MeshLoadingQueue(
|
||||
|
||||
|
||||
fun work() {
|
||||
lock.lock()
|
||||
lock()
|
||||
if (meshes.isEmpty()) {
|
||||
lock.unlock()
|
||||
unlock()
|
||||
return
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ class MeshLoadingQueue(
|
||||
}
|
||||
renderer.loaded.unlock()
|
||||
|
||||
lock.unlock()
|
||||
unlock()
|
||||
|
||||
if (count > 0) {
|
||||
renderer.visible.sort()
|
||||
@ -82,7 +82,7 @@ class MeshLoadingQueue(
|
||||
|
||||
|
||||
fun queue(mesh: WorldMesh) {
|
||||
lock.lock()
|
||||
lock()
|
||||
if (!this.positions.add(QueuePosition(mesh))) {
|
||||
// already inside, remove
|
||||
meshes.remove(mesh)
|
||||
@ -93,11 +93,11 @@ class MeshLoadingQueue(
|
||||
} else {
|
||||
meshes += mesh
|
||||
}
|
||||
lock.unlock()
|
||||
unlock()
|
||||
}
|
||||
|
||||
fun abort(position: ChunkPosition, lock: Boolean = true) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
val positions: MutableSet<QueuePosition> = mutableSetOf()
|
||||
this.positions.removeAll {
|
||||
if (it.position != position) {
|
||||
@ -107,14 +107,14 @@ class MeshLoadingQueue(
|
||||
return@removeAll true
|
||||
}
|
||||
this.meshes.removeAll { QueuePosition(it.chunkPosition, it.sectionHeight) in positions }
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
|
||||
fun cleanup(lock: Boolean) {
|
||||
val remove: MutableSet<QueuePosition> = mutableSetOf()
|
||||
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
this.positions.removeAll {
|
||||
if (renderer.visibilityGraph.isChunkVisible(it.position)) {
|
||||
return@removeAll false
|
||||
@ -124,22 +124,24 @@ class MeshLoadingQueue(
|
||||
}
|
||||
|
||||
this.meshes.removeAll { QueuePosition(it) in remove }
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
fun clear(lock: Boolean) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
this.positions.clear()
|
||||
this.meshes.clear()
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
|
||||
fun lock() {
|
||||
renderer.lock.acquire()
|
||||
this.lock.lock()
|
||||
}
|
||||
|
||||
fun unlock() {
|
||||
this.lock.unlock()
|
||||
renderer.lock.release()
|
||||
}
|
||||
}
|
||||
|
@ -45,16 +45,16 @@ class MeshUnloadingQueue(
|
||||
}
|
||||
|
||||
fun work() {
|
||||
lock.lock()
|
||||
lock()
|
||||
try {
|
||||
forceWork()
|
||||
} finally {
|
||||
lock.unlock()
|
||||
unlock()
|
||||
}
|
||||
}
|
||||
|
||||
fun forceQueue(mesh: WorldMesh, lock: Boolean = true) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
|
||||
if (mesh.chunkPosition == renderer.connection.player.positionInfo.chunkPosition) { // TODO: camera
|
||||
this.meshes.add(0, mesh)
|
||||
@ -63,42 +63,44 @@ class MeshUnloadingQueue(
|
||||
}
|
||||
this.positions += QueuePosition(mesh)
|
||||
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
fun queue(mesh: WorldMesh, lock: Boolean = true) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
if (QueuePosition(mesh) in this.positions) {
|
||||
// already queued
|
||||
// TODO: maybe camera chunk position changed?
|
||||
this.lock.unlock()
|
||||
unlock()
|
||||
return
|
||||
}
|
||||
forceQueue(mesh, false)
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
fun forceQueue(meshes: Collection<WorldMesh>, lock: Boolean = true) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
for (mesh in meshes) {
|
||||
forceQueue(mesh, false)
|
||||
}
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
fun queue(meshes: Collection<WorldMesh>) {
|
||||
this.lock.lock()
|
||||
lock()
|
||||
for (mesh in meshes) {
|
||||
queue(mesh, false)
|
||||
}
|
||||
this.lock.unlock()
|
||||
unlock()
|
||||
}
|
||||
|
||||
fun lock() {
|
||||
lock.lock()
|
||||
renderer.lock.acquire()
|
||||
this.lock.lock()
|
||||
}
|
||||
|
||||
fun unlock() {
|
||||
lock.unlock()
|
||||
this.lock.unlock()
|
||||
renderer.lock.release()
|
||||
}
|
||||
}
|
||||
|
@ -33,17 +33,17 @@ class ChunkMeshingQueue(
|
||||
|
||||
@Volatile
|
||||
private var working = false
|
||||
private val queue: MutableList<WorldQueueItem> = mutableListOf() // queue, that is visible, and should be rendered
|
||||
private val set: MutableSet<WorldQueueItem> = HashSet() // queue, that is visible, and should be rendered
|
||||
private val queue: MutableList<WorldQueueItem> = mutableListOf()
|
||||
private val set: MutableSet<WorldQueueItem> = HashSet()
|
||||
|
||||
val lock = SimpleLock()
|
||||
private val lock = SimpleLock()
|
||||
|
||||
|
||||
val size: Int get() = queue.size
|
||||
|
||||
|
||||
fun sort() {
|
||||
lock.lock()
|
||||
lock()
|
||||
val position = renderer.cameraChunkPosition
|
||||
val height = renderer.cameraSectionHeight
|
||||
val cameraSectionPosition = Vec3i(position.x, height, position.y)
|
||||
@ -54,7 +54,7 @@ class ChunkMeshingQueue(
|
||||
}
|
||||
(it.sectionPosition - cameraSectionPosition).length2()
|
||||
}
|
||||
lock.unlock()
|
||||
unlock()
|
||||
}
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ class ChunkMeshingQueue(
|
||||
|
||||
|
||||
val items: MutableList<WorldQueueItem> = mutableListOf()
|
||||
lock.lock()
|
||||
lock()
|
||||
for (i in 0 until tasks.max - size) {
|
||||
if (queue.isEmpty()) {
|
||||
break
|
||||
@ -77,9 +77,9 @@ class ChunkMeshingQueue(
|
||||
set -= item
|
||||
items += item
|
||||
}
|
||||
lock.unlock()
|
||||
unlock()
|
||||
for (item in items) {
|
||||
val runnable = ThreadPoolRunnable(if (item.chunkPosition == renderer.cameraChunkPosition) ThreadPool.HIGH else ThreadPool.LOW, interruptable = true) // Our own chunk is the most important one ToDo: Also make neighbour chunks important
|
||||
val runnable = ThreadPoolRunnable(if (item.chunkPosition == renderer.cameraChunkPosition) ThreadPool.HIGH else ThreadPool.LOW, interruptable = true) // ToDo: Also make neighbour chunks important
|
||||
val task = MeshPrepareTask(item.chunkPosition, item.sectionHeight, runnable)
|
||||
task.runnable.runnable = Runnable { renderer.mesher.tryMesh(item, task, task.runnable) }
|
||||
tasks += task
|
||||
@ -100,7 +100,8 @@ class ChunkMeshingQueue(
|
||||
set -= remove
|
||||
}
|
||||
|
||||
fun cleanup() {
|
||||
fun cleanup(lock: Boolean) {
|
||||
if (lock) lock()
|
||||
val remove: MutableSet<WorldQueueItem> = mutableSetOf()
|
||||
queue.removeAll {
|
||||
if (renderer.visibilityGraph.isChunkVisible(it.chunkPosition)) {
|
||||
@ -110,36 +111,39 @@ class ChunkMeshingQueue(
|
||||
return@removeAll true
|
||||
}
|
||||
set -= remove
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
fun lock() {
|
||||
renderer.lock.acquire()
|
||||
this.lock.lock()
|
||||
}
|
||||
|
||||
fun unlock() {
|
||||
this.lock.unlock()
|
||||
renderer.lock.release()
|
||||
}
|
||||
|
||||
|
||||
fun clear(lock: Boolean) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
this.queue.clear()
|
||||
this.set.clear()
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
|
||||
fun remove(item: WorldQueueItem, lock: Boolean) {
|
||||
if (lock) this.lock.lock()
|
||||
if (lock) lock()
|
||||
if (this.set.remove(item)) {
|
||||
this.queue -= item
|
||||
}
|
||||
if (lock) this.lock.unlock()
|
||||
if (lock) unlock()
|
||||
}
|
||||
|
||||
|
||||
fun queue(item: WorldQueueItem) {
|
||||
lock.lock()
|
||||
lock()
|
||||
if (set.remove(item)) {
|
||||
queue -= item
|
||||
}
|
||||
@ -149,6 +153,6 @@ class ChunkMeshingQueue(
|
||||
queue += item
|
||||
}
|
||||
set += item
|
||||
lock.unlock()
|
||||
unlock()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user