optimize color write and increase bitblt limits

the color write improvements appears to give clients a 90% speed up on loading color nbt
This commit is contained in:
payonel 2020-05-23 22:59:27 -07:00
parent 6ff0d7865e
commit 20f2cc460f
5 changed files with 58 additions and 21 deletions

View File

@ -1598,8 +1598,8 @@ opencomputers {
# This setting assigns the budget call cost to invoke bitblt to write vram
# to a screen. Video ram can bitblit to a screen which can cause real life
# network laod the defaults settings put bitblit network impact close to gpu.set
# Increase these values to throttle bitblt more. These values appear inverted
# but the cost of bitblt is based on the max resolution of the device
bitbltCosts: [ 1, 2, 8 ]
# Increase these values to throttle bitblt more. The cost tier N is bitbltCost * 2^(tier)
# default is .5, which gives: .5, 1, 4
bitbltCost: 0.5
}
}

View File

@ -476,12 +476,7 @@ class Settings(val config: Config) {
Array(1, 2, 3)
}
val bitbltCosts: Array[Double] = Array(config.getDoubleList("gpu.bitbltCosts"): _*) match {
case Array(tier1, tier2, tier3) => Array(tier1: Double, tier2: Double, tier3: Double)
case _ =>
OpenComputers.log.warn("Bad number of bitblit costs (expected 3), ignoring.")
Array(1, 2, 8)
}
val bitbltCost: Double = if (config.hasPath("gpu.bitbltCost")) config.getDouble("gpu.bitbltCost") else 0.5
}
object Settings {

View File

@ -71,7 +71,7 @@ class GraphicsCard(val tier: Int) extends prefab.ManagedEnvironment with DeviceI
// These are dirty page bitblt budget costs
// a single bitblt can send a screen of data, which is n*set calls where set is writing an entire line
// So for each tier, we multiple the set cost with the number of lines the screen may have
final val bitbltCost: Double = Settings.get.bitbltCosts(0 max tier min 2)
final val bitbltCost: Double = Settings.get.bitbltCost * scala.math.pow(2, tier)
final val totalVRAM: Double = (maxResolution._1 * maxResolution._2) * Settings.get.vramSizes(0 max tier min 2)
var budgetExhausted: Boolean = false // for especially expensive calls, bitblt

View File

@ -0,0 +1,49 @@
package li.cil.oc.util
import net.minecraft.nbt.NBTTagCompound
object NbtDataStream {
def getShortArray(nbt: NBTTagCompound, key: String, array2d: Array[Array[Short]], w: Int, h: Int) : Boolean = {
if (!nbt.hasKey(key)) {
return false
}
val rawByteReader = new java.io.ByteArrayInputStream(nbt.getByteArray(key))
val memReader = new java.io.DataInputStream(rawByteReader)
for (y <- 0 until h) {
for (x <- 0 until w) {
if (2 > memReader.available()) {
return true // not great, but get out now
}
array2d(y)(x) = memReader.readShort()
}
}
true
}
def getIntArrayLegacy(nbt: NBTTagCompound, key: String, array2d: Array[Array[Short]], w: Int, h: Int) : Boolean = {
if (!nbt.hasKey(key)) {
return false
}
// legacy format
val c = nbt.getIntArray(key)
for (y <- 0 until h) {
val rowColor = array2d(y)
for (x <- 0 until w) {
val index = x + y * w
if (index >= c.length) {
return true // not great, but, the read at least started
}
rowColor(x) = c(index).toShort
}
}
true
}
def setShortArray(nbt: NBTTagCompound, key: String, array: Array[Short]): Unit = {
val rawByteWriter = new java.io.ByteArrayOutputStream()
val memWriter = new java.io.DataOutputStream(rawByteWriter)
array.foreach(memWriter.writeShort(_))
nbt.setByteArray(key, rawByteWriter.toByteArray)
}
}

View File

@ -262,15 +262,8 @@ class TextBuffer(var width: Int, var height: Int, initialFormat: PackedColor.Col
foreground = PackedColor.Color(nbt.getInteger("foreground"), nbt.getBoolean("foregroundIsPalette"))
background = PackedColor.Color(nbt.getInteger("background"), nbt.getBoolean("backgroundIsPalette"))
val c = nbt.getIntArray("color")
for (i <- 0 until h) {
val rowColor = color(i)
for (j <- 0 until w) {
val index = j + i * w
if (index < c.length) {
rowColor(j) = c(index).toShort
}
}
if (!NbtDataStream.getShortArray(nbt, "color_bytes", color, w, h)) {
NbtDataStream.getIntArrayLegacy(nbt, "color", color, w, h)
}
}
@ -291,10 +284,10 @@ class TextBuffer(var width: Int, var height: Int, initialFormat: PackedColor.Col
nbt.setInteger("background", _background.value)
nbt.setBoolean("backgroundIsPalette", _background.isPalette)
nbt.setTag("color", new NBTTagIntArray(color.flatten.map(_.toInt)))
NbtDataStream.setShortArray(nbt, "color_bytes", color.flatten.map(_.toShort))
}
override def toString = {
override def toString: String = {
val b = StringBuilder.newBuilder
if (buffer.length > 0) {
b.appendAll(buffer(0))