section occlusion: set invalid region for full opaque blocks

No need to check if the block is full opaque multiple times.
Benchmark time goes down from 18s to 15s, so 17% improvement. Not bad.
This commit is contained in:
Moritz Zwerger 2025-02-09 19:05:17 +01:00
parent 3fadadd441
commit dbd4752d09
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
2 changed files with 12 additions and 9 deletions

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020-2024 Moritz Zwerger * Copyright (C) 2020-2025 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -33,7 +33,7 @@ class ChunkNeighbours(val chunk: Chunk) : Iterable<Chunk?> {
val complete: Boolean get() = count == COUNT val complete: Boolean get() = count == COUNT
fun get(): Array<Chunk>? { fun get(): Array<Chunk>? {
if (count == COUNT) { if (count == COUNT) { // TODO: Race condition!
return neighbours.unsafeCast() return neighbours.unsafeCast()
} }
return null return null

View File

@ -58,13 +58,14 @@ class SectionOcclusion(
} }
} }
private inline fun ShortArray.updateRegion(x: Int, y: Int, z: Int, id: Short): Boolean { private inline fun ShortArray.setIfUnset(x: Int, y: Int, z: Int, id: Short): Boolean {
val index = y shl 8 or (z shl 4) or x val index = y shl 8 or (z shl 4) or x
if (this[index] > 0) { if (this[index] != EMPTY_REGION) {
return true return true
} }
val state = provider[index] val state = provider[index]
if (state.isFullyOpaque()) { if (state.isFullyOpaque()) {
this[index] = INVALID_REGION
return true return true
} }
this[index] = id this[index] = id
@ -72,7 +73,7 @@ class SectionOcclusion(
} }
private fun startTrace(regions: ShortArray, x: Int, y: Int, z: Int, nextId: Short) { private fun startTrace(regions: ShortArray, x: Int, y: Int, z: Int, nextId: Short) {
if (regions.updateRegion(x, y, z, nextId)) return if (regions.setIfUnset(x, y, z, nextId)) return
// no need to trace negative coordinates initially // no need to trace negative coordinates initially
if (x < ProtocolDefinition.SECTION_MAX_X) trace(regions, x + 1, y, z, nextId) if (x < ProtocolDefinition.SECTION_MAX_X) trace(regions, x + 1, y, z, nextId)
@ -81,7 +82,7 @@ class SectionOcclusion(
} }
private fun trace(regions: ShortArray, x: Int, y: Int, z: Int, nextId: Short) { private fun trace(regions: ShortArray, x: Int, y: Int, z: Int, nextId: Short) {
if (regions.updateRegion(x, y, z, nextId)) return if (regions.setIfUnset(x, y, z, nextId)) return
if (x > 0) trace(regions, x - 1, y, z, nextId) if (x > 0) trace(regions, x - 1, y, z, nextId)
if (x < ProtocolDefinition.SECTION_MAX_X) trace(regions, x + 1, y, z, nextId) if (x < ProtocolDefinition.SECTION_MAX_X) trace(regions, x + 1, y, z, nextId)
@ -93,9 +94,9 @@ class SectionOcclusion(
private fun floodFill(array: ShortArray): ShortArray { private fun floodFill(array: ShortArray): ShortArray {
// mark regions and check direct neighbours // mark regions and check direct neighbours
Arrays.fill(array, 0.toShort()) Arrays.fill(array, EMPTY_REGION)
var next: Short = 0 var next = EMPTY_REGION
for (y in 0 until ProtocolDefinition.SECTION_HEIGHT_Y) { for (y in 0 until ProtocolDefinition.SECTION_HEIGHT_Y) {
for (z in 0 until ProtocolDefinition.SECTION_WIDTH_Z) { for (z in 0 until ProtocolDefinition.SECTION_WIDTH_Z) {
for (x in 0 until ProtocolDefinition.SECTION_WIDTH_X) { for (x in 0 until ProtocolDefinition.SECTION_WIDTH_X) {
@ -124,7 +125,7 @@ class SectionOcclusion(
Axes.Z -> Directions.NORTH Axes.Z -> Directions.NORTH
} }
val nRegion = regions[indexPrefix].toInt() val nRegion = regions[indexPrefix].toInt()
if (nRegion > 0) { if (nRegion > EMPTY_REGION) {
sideRegions[nDirection.ordinal].add(nRegion) // primitive sideRegions[nDirection.ordinal].add(nRegion) // primitive
} }
@ -203,6 +204,8 @@ class SectionOcclusion(
} }
companion object { companion object {
private const val EMPTY_REGION = 0.toShort()
private const val INVALID_REGION = (-1).toShort()
private val EMPTY = BooleanArray(CubeDirections.CUBE_DIRECTION_COMBINATIONS) private val EMPTY = BooleanArray(CubeDirections.CUBE_DIRECTION_COMBINATIONS)
private val ALLOCATOR = ShortAllocator() private val ALLOCATOR = ShortAllocator()