Optimize the inner loop of the renderer to save some cycles by hoisting out version checks and common indexing.

This commit is contained in:
Sascha L. Teichmann 2017-03-01 13:06:51 +01:00
parent 08d32826dc
commit 75aeb36c95

View File

@ -201,6 +201,42 @@ func (r *Renderer) IsEmpty() bool {
return r.SolidBlocks == 0 && r.TransparentBlocks == 0 return r.SolidBlocks == 0 && r.TransparentBlocks == 0
} }
// down goes down the y direction in a block from top to bottom.
// In its loop it copies the logic of Block.Content pulling some
// things like the version check and common indexing out to
// save some cycles.
func down(db *DecodedBlock, x, y, z int) (int32, int) {
mc := db.MapContent
switch {
case db.Version >= 24:
for sliver := (z<<8 + x) << 1; y >= 0; y-- {
pos := sliver + y<<5
content := int32(mc[pos])<<8 | int32(mc[pos+1])
if content != db.AirID && content != db.IgnoreID {
if c, found := db.IndexMap[content]; found {
return c, y
}
}
}
case db.Version >= 20:
for sliver := z<<8 + x; y >= 0; y-- {
pos := sliver + y<<4
var content int32
if c := mc[pos]; c <= 0x80 {
content = int32(c)
} else {
content = int32(c)<<4 | int32(mc[pos+0x2000])>>4
}
if content != db.AirID && content != db.IgnoreID {
if c, found := db.IndexMap[content]; found {
return c, y
}
}
}
}
return -1, -1
}
func (r *Renderer) RenderBlock(block *Block, colors *Colors) (err error) { func (r *Renderer) RenderBlock(block *Block, colors *Colors) (err error) {
bx := block.Coord.X - r.xOfs bx := block.Coord.X - r.xOfs
@ -238,18 +274,22 @@ func (r *Renderer) RenderBlock(block *Block, colors *Colors) (err error) {
for x := 0; x < 16; x++ { for x := 0; x < 16; x++ {
currentY := yB[ofs] currentY := yB[ofs]
if currentY < blockY { if currentY < blockY {
for y := 15; y >= 0; y-- { var c int32
if c, ok := db.Content(x, y, z); ok { for y := 15; ; y-- {
cY := blockY + int32(y) if c, y = down(db, x, y, z); y < 0 {
break
}
cY := blockY + int32(y)
if colors.IsTransparent(c) { if colors.IsTransparent(c) {
r.tBuffer[ofs] = r.spans.Insert(r.tBuffer[ofs], cY, c) r.tBuffer[ofs] = r.spans.Insert(r.tBuffer[ofs], cY, c)
} else { // We need to continue to go down because we
r.cBuffer[ofs] = c // can see through this node.
currentY = cY } else {
yB[ofs] = currentY r.cBuffer[ofs] = c
break currentY = cY
} yB[ofs] = currentY
break
} }
} }
} }
@ -267,13 +307,10 @@ func (r *Renderer) RenderBlock(block *Block, colors *Colors) (err error) {
for x := 0; x < 16; x++ { for x := 0; x < 16; x++ {
currentY := yB[ofs] currentY := yB[ofs]
if currentY < blockY { if currentY < blockY {
for y := 15; y >= 0; y-- { if c, y := down(db, x, 15, z); y >= 0 {
if c, ok := db.Content(x, y, z); ok { r.cBuffer[ofs] = c
r.cBuffer[ofs] = c currentY = blockY + int32(y)
currentY = blockY + int32(y) yB[ofs] = currentY
yB[ofs] = currentY
break
}
} }
} }
if currentY < yMin { if currentY < yMin {