From 39cfc3a4d945afec5c1ecb4def2fb479c3ce0bfe Mon Sep 17 00:00:00 2001 From: minjaesong Date: Tue, 22 Oct 2024 11:47:21 +0900 Subject: [PATCH] chunkpoolnig wip --- .../torvald/terrarum/gameworld/BlockLayer.kt | 16 +++--- .../gameworld/BlockLayerFluidI16F16.kt | 50 ++++++++++++---- .../gameworld/BlockLayerGenericI16.kt | 56 ++++++++++++------ .../terrarum/gameworld/BlockLayerOresI16I8.kt | 50 ++++++++++++---- .../torvald/terrarum/gameworld/ChunkPool.kt | 57 ++++++++++++++++--- 5 files changed, 172 insertions(+), 57 deletions(-) diff --git a/src/net/torvald/terrarum/gameworld/BlockLayer.kt b/src/net/torvald/terrarum/gameworld/BlockLayer.kt index 91edf45f6..1051ebf4b 100644 --- a/src/net/torvald/terrarum/gameworld/BlockLayer.kt +++ b/src/net/torvald/terrarum/gameworld/BlockLayer.kt @@ -5,14 +5,14 @@ import com.badlogic.gdx.utils.Disposable /** * Created by minjaesong on 2023-10-10. */ -interface BlockLayer : Disposable { - - val width: Int - val height: Int - val bytesPerBlock: Long - fun unsafeToBytes(x: Int, y: Int): ByteArray - fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) - fun unsafeGetTile(x: Int, y: Int): Int +abstract class BlockLayer : Disposable { + abstract val chunkPool: ChunkPool + abstract val width: Int + abstract val height: Int + abstract val bytesPerBlock: Long + abstract fun unsafeToBytes(x: Int, y: Int): ByteArray + abstract fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) + abstract fun unsafeGetTile(x: Int, y: Int): Int } diff --git a/src/net/torvald/terrarum/gameworld/BlockLayerFluidI16F16.kt b/src/net/torvald/terrarum/gameworld/BlockLayerFluidI16F16.kt index acfbc8399..852b5cd12 100644 --- a/src/net/torvald/terrarum/gameworld/BlockLayerFluidI16F16.kt +++ b/src/net/torvald/terrarum/gameworld/BlockLayerFluidI16F16.kt @@ -1,6 +1,11 @@ package net.torvald.terrarum.gameworld import net.torvald.terrarum.App +import net.torvald.terrarum.gameworld.BlockLayerGenericI16.Companion +import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN +import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL +import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM +import net.torvald.terrarum.savegame.DiskSkimmer import net.torvald.terrarum.serialise.toUint import net.torvald.unsafe.UnsafeHelper import net.torvald.unsafe.UnsafePtr @@ -17,12 +22,41 @@ const val FLUID_MIN_MASS = 1f / 1024f //Ignore cells that are almost dry (smalle * * Created by minjaesong on 2023-10-10. */ -class BlockLayerI16F16(override val width: Int, override val height: Int) : BlockLayer { +class BlockLayerFluidI16F16 : BlockLayer { + + override val width: Int + override val height: Int + override val chunkPool: ChunkPool + + constructor( + width: Int, + height: Int, + disk: ClusteredFormatDOM, + layerNum: Int, + world: GameWorld + ) { + this.width = width + this.height = height + + chunkPool = ChunkPool(disk, layerNum, BlockLayerGenericI16.BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world)) + } + + constructor( + width: Int, + height: Int, + disk: DiskSkimmer, + layerNum: Int, + world: GameWorld + ) { + this.width = width + this.height = height + + chunkPool = ChunkPool(disk, layerNum, BlockLayerGenericI16.BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world)) + } + + override val bytesPerBlock = BYTES_PER_BLOCK - // for some reason, all the efforts of saving the memory space were futile. - - // using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90 internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock) val ptrDestroyed: Boolean @@ -32,14 +66,6 @@ class BlockLayerI16F16(override val width: Int, override val height: Int) : Bloc ptr.fillWith(-1) } - /** - * @param data Byte array representation of the layer - */ - constructor(width: Int, height: Int, data: ByteArray) : this(width, height) { - TODO() - data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) } - } - /** * Returns an iterator over stored bytes. * diff --git a/src/net/torvald/terrarum/gameworld/BlockLayerGenericI16.kt b/src/net/torvald/terrarum/gameworld/BlockLayerGenericI16.kt index 94d4cf62c..8ffd29bc9 100644 --- a/src/net/torvald/terrarum/gameworld/BlockLayerGenericI16.kt +++ b/src/net/torvald/terrarum/gameworld/BlockLayerGenericI16.kt @@ -1,10 +1,10 @@ package net.torvald.terrarum.gameworld -import com.badlogic.gdx.utils.Disposable import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM +import net.torvald.terrarum.savegame.DiskSkimmer import net.torvald.terrarum.serialise.toUint import net.torvald.unsafe.UnsafeHelper import net.torvald.unsafe.UnsafePtr @@ -21,25 +21,49 @@ import net.torvald.unsafe.UnsafePtr * * Note to self: refrain from using shorts--just do away with two bytes: different system have different endianness */ -class BlockLayerI16( - override val width: Int, - override val height: Int, - disk: ClusteredFormatDOM, - layerNum: Int, - world: GameWorld -): BlockLayer() { +class BlockLayerGenericI16: BlockLayer { + + override val width: Int + override val height: Int + override val chunkPool: ChunkPool + + constructor( + width: Int, + height: Int, + disk: ClusteredFormatDOM, + layerNum: Int, + world: GameWorld + ) { + this.width = width + this.height = height + + chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, when (layerNum) { + TERRAIN -> ChunkPool.getRenameFunTerrain(world) + WALL -> ChunkPool.getRenameFunTerrain(world) + else -> throw IllegalArgumentException("Unknown layer number for I16: $layerNum") + }) + } + + constructor( + width: Int, + height: Int, + disk: DiskSkimmer, + layerNum: Int, + world: GameWorld + ) { + this.width = width + this.height = height + + chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, when (layerNum) { + TERRAIN -> ChunkPool.getRenameFunTerrain(world) + WALL -> ChunkPool.getRenameFunTerrain(world) + else -> throw IllegalArgumentException("Unknown layer number for I16: $layerNum") + }) + } - override val chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, when (layerNum) { - TERRAIN -> ChunkPool.getRenameFunTerrain(world) - WALL -> ChunkPool.getRenameFunTerrain(world) - else -> throw IllegalArgumentException("Unknown layer number for I16: $layerNum") - }) override val bytesPerBlock = BYTES_PER_BLOCK - // for some reason, all the efforts of saving the memory space were futile. - - // using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90 internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock) val ptrDestroyed: Boolean diff --git a/src/net/torvald/terrarum/gameworld/BlockLayerOresI16I8.kt b/src/net/torvald/terrarum/gameworld/BlockLayerOresI16I8.kt index 0010a92ab..0552d47f0 100644 --- a/src/net/torvald/terrarum/gameworld/BlockLayerOresI16I8.kt +++ b/src/net/torvald/terrarum/gameworld/BlockLayerOresI16I8.kt @@ -1,6 +1,11 @@ package net.torvald.terrarum.gameworld import net.torvald.terrarum.App +import net.torvald.terrarum.gameworld.BlockLayerFluidI16F16.Companion +import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN +import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL +import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM +import net.torvald.terrarum.savegame.DiskSkimmer import net.torvald.terrarum.serialise.toUint import net.torvald.unsafe.UnsafeHelper import net.torvald.unsafe.UnsafePtr @@ -13,12 +18,41 @@ import net.torvald.unsafe.UnsafePtr * where a_n is a tile number, p_n is a placement index * Created by minjaesong on 2023-10-10. */ -class BlockLayerOresI16I8 (override val width: Int, override val height: Int) : BlockLayer { +class BlockLayerOresI16I8 : BlockLayer { + + override val width: Int + override val height: Int + override val chunkPool: ChunkPool + + constructor( + width: Int, + height: Int, + disk: ClusteredFormatDOM, + layerNum: Int, + world: GameWorld + ) { + this.width = width + this.height = height + + chunkPool = ChunkPool(disk, layerNum, BlockLayerGenericI16.BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world)) + } + + constructor( + width: Int, + height: Int, + disk: DiskSkimmer, + layerNum: Int, + world: GameWorld + ) { + this.width = width + this.height = height + + chunkPool = ChunkPool(disk, layerNum, BlockLayerGenericI16.BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world)) + } + + override val bytesPerBlock = BYTES_PER_BLOCK - // for some reason, all the efforts of saving the memory space were futile. - - // using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90 internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock) val ptrDestroyed: Boolean @@ -28,14 +62,6 @@ class BlockLayerOresI16I8 (override val width: Int, override val height: Int) : ptr.fillWith(0) // there is no NOT-GENERATED for ores, keep it as 0 } - /** - * @param data Byte array representation of the layer - */ - constructor(width: Int, height: Int, data: ByteArray) : this(width, height) { - TODO() - data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) } - } - /** * Returns an iterator over stored bytes. * diff --git a/src/net/torvald/terrarum/gameworld/ChunkPool.kt b/src/net/torvald/terrarum/gameworld/ChunkPool.kt index 7a89f0586..31a8b2870 100644 --- a/src/net/torvald/terrarum/gameworld/ChunkPool.kt +++ b/src/net/torvald/terrarum/gameworld/ChunkPool.kt @@ -39,21 +39,60 @@ enum class ChunkAllocClass { * * Created by minjaesong on 2024-09-07. */ -open class ChunkPool( +open class ChunkPool { + // `DiskSkimmer` or `ClusteredFormatDOM` - val disk: Any, - val layerIndex: Int, - val wordSizeInBytes: Long, - val world: GameWorld, - val renumberFun: (Int) -> Int, -) { + private val disk: Any + private val layerIndex: Int + private val wordSizeInBytes: Long + private val world: GameWorld + private val initialValue: Int // bytes to fill the new chunk + private val renumberFun: (Int) -> Int + private val pointers = TreeMap() private var allocCap = 32 private var allocMap = Array(allocCap) { null } private var allocCounter = 0 + private val chunkSize: Long + private val pool: UnsafePtr - private val chunkSize = (wordSizeInBytes * CHUNK_W * CHUNK_H) - private val pool = UnsafeHelper.allocate(chunkSize * allocCap) + constructor( + disk: DiskSkimmer, + layerIndex: Int, + wordSizeInBytes: Long, + world: GameWorld, + initialValue: Int, + renumberFun: (Int) -> Int, + ) { + this.disk = disk + this.layerIndex = layerIndex + this.wordSizeInBytes = wordSizeInBytes + this.world = world + this.initialValue = initialValue + this.renumberFun = renumberFun + + chunkSize = wordSizeInBytes * CHUNK_W * CHUNK_H + pool = UnsafeHelper.allocate(chunkSize * allocCap) + } + + constructor( + disk: ClusteredFormatDOM, + layerIndex: Int, + wordSizeInBytes: Long, + world: GameWorld, + initialValue: Int, + renumberFun: (Int) -> Int, + ) { + this.disk = disk + this.layerIndex = layerIndex + this.wordSizeInBytes = wordSizeInBytes + this.world = world + this.initialValue = initialValue + this.renumberFun = renumberFun + + chunkSize = wordSizeInBytes * CHUNK_W * CHUNK_H + pool = UnsafeHelper.allocate(chunkSize * allocCap) + } init { allocMap.fill(null)