mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-08-20 09:57:10 +00:00
perf(render): improve chunk scheduling and refine rebuild profiling
This commit is contained in:
parent
47b7d90835
commit
a3f7f7d03c
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.h"
|
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.h"
|
||||||
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.entity.h"
|
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.entity.h"
|
||||||
#include "LevelRenderer.h"
|
#include "LevelRenderer.h"
|
||||||
|
#include "../Utils/FrameProfiler.h"
|
||||||
|
|
||||||
#ifdef __PS3__
|
#ifdef __PS3__
|
||||||
#include "../Platform/PS3/SPU_Tasks/ChunkUpdate/ChunkRebuildData.h"
|
#include "../Platform/PS3/SPU_Tasks/ChunkUpdate/ChunkRebuildData.h"
|
||||||
|
|
@ -252,94 +253,97 @@ void Chunk::rebuild() {
|
||||||
// into this category. By far the largest category of these are tiles in
|
// into this category. By far the largest category of these are tiles in
|
||||||
// solid regions of rock.
|
// solid regions of rock.
|
||||||
bool empty = true;
|
bool empty = true;
|
||||||
for (int yy = y0; yy < y1; yy++) {
|
{
|
||||||
for (int zz = 0; zz < 16; zz++) {
|
FRAME_PROFILE_SCOPE(ChunkPrepass);
|
||||||
for (int xx = 0; xx < 16; xx++) {
|
for (int yy = y0; yy < y1; yy++) {
|
||||||
// 4J Stu - tile data is ordered in 128 blocks of full width,
|
for (int zz = 0; zz < 16; zz++) {
|
||||||
// lower 128 then upper 128
|
for (int xx = 0; xx < 16; xx++) {
|
||||||
int indexY = yy;
|
// 4J Stu - tile data is ordered in 128 blocks of full width,
|
||||||
int offset = 0;
|
// lower 128 then upper 128
|
||||||
if (indexY >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
|
int indexY = yy;
|
||||||
indexY -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
|
int offset = 0;
|
||||||
offset = Level::COMPRESSED_CHUNK_SECTION_TILES;
|
if (indexY >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
|
||||||
}
|
indexY -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
|
||||||
|
offset = Level::COMPRESSED_CHUNK_SECTION_TILES;
|
||||||
unsigned char tileId =
|
|
||||||
tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
|
|
||||||
(indexY + 0))];
|
|
||||||
if (tileId > 0) empty = false;
|
|
||||||
|
|
||||||
// Don't bother trying to work out neighbours for this tile if
|
|
||||||
// we are at the edge of the chunk - apart from the very bottom
|
|
||||||
// of the world where we shouldn't ever be able to see
|
|
||||||
if (yy == (Level::maxBuildHeight - 1)) continue;
|
|
||||||
if ((xx == 0) || (xx == 15)) continue;
|
|
||||||
if ((zz == 0) || (zz == 15)) continue;
|
|
||||||
|
|
||||||
// Establish whether this tile and its neighbours are all made
|
|
||||||
// of rock, dirt, unbreakable tiles, or have already been
|
|
||||||
// determined to meet this criteria themselves and have a tile
|
|
||||||
// of 255 set.
|
|
||||||
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
|
||||||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
|
||||||
continue;
|
|
||||||
tileId = tileIds[offset + (((xx - 1) << 11) | ((zz + 0) << 7) |
|
|
||||||
(indexY + 0))];
|
|
||||||
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
|
||||||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
|
||||||
continue;
|
|
||||||
tileId = tileIds[offset + (((xx + 1) << 11) | ((zz + 0) << 7) |
|
|
||||||
(indexY + 0))];
|
|
||||||
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
|
||||||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
|
||||||
continue;
|
|
||||||
tileId = tileIds[offset + (((xx + 0) << 11) | ((zz - 1) << 7) |
|
|
||||||
(indexY + 0))];
|
|
||||||
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
|
||||||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
|
||||||
continue;
|
|
||||||
tileId = tileIds[offset + (((xx + 0) << 11) | ((zz + 1) << 7) |
|
|
||||||
(indexY + 0))];
|
|
||||||
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
|
||||||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
|
||||||
continue;
|
|
||||||
// Treat the bottom of the world differently - we shouldn't ever
|
|
||||||
// be able to look up at this, so consider tiles as invisible if
|
|
||||||
// they are surrounded on sides other than the bottom
|
|
||||||
if (yy > 0) {
|
|
||||||
int indexYMinusOne = yy - 1;
|
|
||||||
int yMinusOneOffset = 0;
|
|
||||||
if (indexYMinusOne >=
|
|
||||||
Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
|
|
||||||
indexYMinusOne -=
|
|
||||||
Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
|
|
||||||
yMinusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
|
|
||||||
}
|
}
|
||||||
tileId = tileIds[yMinusOneOffset + (((xx + 0) << 11) |
|
|
||||||
((zz + 0) << 7) |
|
unsigned char tileId =
|
||||||
indexYMinusOne)];
|
tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
|
||||||
if (!((tileId == Tile::stone_Id) ||
|
(indexY + 0))];
|
||||||
(tileId == Tile::dirt_Id) ||
|
if (tileId > 0) empty = false;
|
||||||
|
|
||||||
|
// Don't bother trying to work out neighbours for this tile if
|
||||||
|
// we are at the edge of the chunk - apart from the very bottom
|
||||||
|
// of the world where we shouldn't ever be able to see
|
||||||
|
if (yy == (Level::maxBuildHeight - 1)) continue;
|
||||||
|
if ((xx == 0) || (xx == 15)) continue;
|
||||||
|
if ((zz == 0) || (zz == 15)) continue;
|
||||||
|
|
||||||
|
// Establish whether this tile and its neighbours are all made
|
||||||
|
// of rock, dirt, unbreakable tiles, or have already been
|
||||||
|
// determined to meet this criteria themselves and have a tile
|
||||||
|
// of 255 set.
|
||||||
|
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
||||||
|
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
||||||
|
continue;
|
||||||
|
tileId = tileIds[offset + (((xx - 1) << 11) | ((zz + 0) << 7) |
|
||||||
|
(indexY + 0))];
|
||||||
|
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
||||||
|
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
||||||
|
continue;
|
||||||
|
tileId = tileIds[offset + (((xx + 1) << 11) | ((zz + 0) << 7) |
|
||||||
|
(indexY + 0))];
|
||||||
|
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
||||||
|
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
||||||
|
continue;
|
||||||
|
tileId = tileIds[offset + (((xx + 0) << 11) | ((zz - 1) << 7) |
|
||||||
|
(indexY + 0))];
|
||||||
|
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
||||||
|
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
||||||
|
continue;
|
||||||
|
tileId = tileIds[offset + (((xx + 0) << 11) | ((zz + 1) << 7) |
|
||||||
|
(indexY + 0))];
|
||||||
|
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
||||||
|
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
||||||
|
continue;
|
||||||
|
// Treat the bottom of the world differently - we shouldn't ever
|
||||||
|
// be able to look up at this, so consider tiles as invisible if
|
||||||
|
// they are surrounded on sides other than the bottom
|
||||||
|
if (yy > 0) {
|
||||||
|
int indexYMinusOne = yy - 1;
|
||||||
|
int yMinusOneOffset = 0;
|
||||||
|
if (indexYMinusOne >=
|
||||||
|
Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
|
||||||
|
indexYMinusOne -=
|
||||||
|
Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
|
||||||
|
yMinusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
|
||||||
|
}
|
||||||
|
tileId = tileIds[yMinusOneOffset + (((xx + 0) << 11) |
|
||||||
|
((zz + 0) << 7) |
|
||||||
|
indexYMinusOne)];
|
||||||
|
if (!((tileId == Tile::stone_Id) ||
|
||||||
|
(tileId == Tile::dirt_Id) ||
|
||||||
|
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int indexYPlusOne = yy + 1;
|
||||||
|
int yPlusOneOffset = 0;
|
||||||
|
if (indexYPlusOne >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
|
||||||
|
indexYPlusOne -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
|
||||||
|
yPlusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
|
||||||
|
}
|
||||||
|
tileId =
|
||||||
|
tileIds[yPlusOneOffset + (((xx + 0) << 11) |
|
||||||
|
((zz + 0) << 7) | indexYPlusOne)];
|
||||||
|
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
||||||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
int indexYPlusOne = yy + 1;
|
|
||||||
int yPlusOneOffset = 0;
|
|
||||||
if (indexYPlusOne >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
|
|
||||||
indexYPlusOne -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
|
|
||||||
yPlusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
|
|
||||||
}
|
|
||||||
tileId =
|
|
||||||
tileIds[yPlusOneOffset + (((xx + 0) << 11) |
|
|
||||||
((zz + 0) << 7) | indexYPlusOne)];
|
|
||||||
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
|
|
||||||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// This tile is surrounded. Flag it as not requiring to be
|
// This tile is surrounded. Flag it as not requiring to be
|
||||||
// rendered by setting its id to 255.
|
// rendered by setting its id to 255.
|
||||||
tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
|
tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
|
||||||
(indexY + 0))] = 0xff;
|
(indexY + 0))] = 0xff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -752,7 +756,7 @@ void Chunk::rebuild_SPU() {
|
||||||
if (currentLayer == 0 &&
|
if (currentLayer == 0 &&
|
||||||
Tile::tiles[tileId]->isEntityTile()) {
|
Tile::tiles[tileId]->isEntityTile()) {
|
||||||
std::shared_ptr<TileEntity> et =
|
std::shared_ptr<TileEntity> et =
|
||||||
region.getTileEntity(x, y, z);
|
region->getTileEntity(x, y, z);
|
||||||
if (TileEntityRenderDispatcher::instance
|
if (TileEntityRenderDispatcher::instance
|
||||||
->hasRenderer(et)) {
|
->hasRenderer(et)) {
|
||||||
renderableTileEntities.push_back(et);
|
renderableTileEntities.push_back(et);
|
||||||
|
|
@ -770,7 +774,7 @@ void Chunk::rebuild_SPU() {
|
||||||
} else if (renderLayer == currentLayer) {
|
} else if (renderLayer == currentLayer) {
|
||||||
// if(currentLayer == 0)
|
// if(currentLayer == 0)
|
||||||
// numRenderedLayer0++;
|
// numRenderedLayer0++;
|
||||||
rendered |= tileRenderer.tesselateInWorld(
|
rendered |= tileRenderer->tesselateInWorld(
|
||||||
tile, x, y, z);
|
tile, x, y, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include "../../../Minecraft.World/Headers/net.minecraft.h"
|
#include "../../../Minecraft.World/Headers/net.minecraft.h"
|
||||||
#include "../../../Minecraft.World/Headers/net.minecraft.world.h"
|
#include "../../../Minecraft.World/Headers/net.minecraft.world.h"
|
||||||
#include "../Tesselator.h"
|
#include "../Tesselator.h"
|
||||||
|
#include "../../Utils/FrameProfiler.h"
|
||||||
#include "EntityTileRenderer.h"
|
#include "EntityTileRenderer.h"
|
||||||
#include "../../GameState/Options.h"
|
#include "../../GameState/Options.h"
|
||||||
|
|
||||||
|
|
@ -267,7 +268,12 @@ bool TileRenderer::tesselateInWorld(
|
||||||
{
|
{
|
||||||
Tesselator* t = Tesselator::getInstance();
|
Tesselator* t = Tesselator::getInstance();
|
||||||
int shape = tt->getRenderShape();
|
int shape = tt->getRenderShape();
|
||||||
tt->updateShape(level, x, y, z, forceData, forceEntity);
|
if (shape == Tile::SHAPE_BLOCK) {
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockShape);
|
||||||
|
tt->updateShape(level, x, y, z, forceData, forceEntity);
|
||||||
|
} else {
|
||||||
|
tt->updateShape(level, x, y, z, forceData, forceEntity);
|
||||||
|
}
|
||||||
// AP - now that the culling is done earlier we don't need to call setShape
|
// AP - now that the culling is done earlier we don't need to call setShape
|
||||||
// until later on (only for SHAPE_BLOCK)
|
// until later on (only for SHAPE_BLOCK)
|
||||||
if (shape != Tile::SHAPE_BLOCK) {
|
if (shape != Tile::SHAPE_BLOCK) {
|
||||||
|
|
@ -278,6 +284,11 @@ bool TileRenderer::tesselateInWorld(
|
||||||
bool retVal = false;
|
bool retVal = false;
|
||||||
switch (shape) {
|
switch (shape) {
|
||||||
case Tile::SHAPE_BLOCK: {
|
case Tile::SHAPE_BLOCK: {
|
||||||
|
{
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockShape);
|
||||||
|
setShape(tt);
|
||||||
|
}
|
||||||
|
|
||||||
// 4J - added these faceFlags so we can detect whether this block is
|
// 4J - added these faceFlags so we can detect whether this block is
|
||||||
// going to have no visible faces and early out the original code
|
// going to have no visible faces and early out the original code
|
||||||
// checked noCulling and shouldRenderFace directly where faceFlags
|
// checked noCulling and shouldRenderFace directly where faceFlags
|
||||||
|
|
@ -290,6 +301,7 @@ bool TileRenderer::tesselateInWorld(
|
||||||
if (noCulling) {
|
if (noCulling) {
|
||||||
faceFlags = 0x3f;
|
faceFlags = 0x3f;
|
||||||
} else {
|
} else {
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockFaceCull);
|
||||||
// these block types can take advantage of a faster version of
|
// these block types can take advantage of a faster version of
|
||||||
// shouldRenderFace there are others but this is an easy check
|
// shouldRenderFace there are others but this is an easy check
|
||||||
// which covers the majority Note: This now covers rock, grass,
|
// which covers the majority Note: This now covers rock, grass,
|
||||||
|
|
@ -319,9 +331,6 @@ bool TileRenderer::tesselateInWorld(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we need to set the shape
|
|
||||||
setShape(tt);
|
|
||||||
|
|
||||||
retVal = tesselateBlockInWorld(tt, x, y, z, faceFlags);
|
retVal = tesselateBlockInWorld(tt, x, y, z, faceFlags);
|
||||||
} break;
|
} break;
|
||||||
case Tile::SHAPE_TREE:
|
case Tile::SHAPE_TREE:
|
||||||
|
|
@ -4828,9 +4837,11 @@ bool TileRenderer::tesselateBlockInWorld(Tile* tt, int x, int y, int z) {
|
||||||
if (Tile::lightEmission[tt->id] ==
|
if (Tile::lightEmission[tt->id] ==
|
||||||
0) // 4J - TODO/remove (Minecraft::useAmbientOcclusion())
|
0) // 4J - TODO/remove (Minecraft::useAmbientOcclusion())
|
||||||
{
|
{
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockLighting);
|
||||||
return tesselateBlockInWorldWithAmbienceOcclusionTexLighting(
|
return tesselateBlockInWorldWithAmbienceOcclusionTexLighting(
|
||||||
tt, x, y, z, r, g, b, 0, smoothShapeLighting);
|
tt, x, y, z, r, g, b, 0, smoothShapeLighting);
|
||||||
} else {
|
} else {
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockLighting);
|
||||||
return tesselateBlockInWorld(tt, x, y, z, r, g, b);
|
return tesselateBlockInWorld(tt, x, y, z, r, g, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4856,9 +4867,11 @@ bool TileRenderer::tesselateBlockInWorld(Tile* tt, int x, int y, int z,
|
||||||
if (Tile::lightEmission[tt->id] ==
|
if (Tile::lightEmission[tt->id] ==
|
||||||
0) // 4J - TODO/remove (Minecraft::useAmbientOcclusion())
|
0) // 4J - TODO/remove (Minecraft::useAmbientOcclusion())
|
||||||
{
|
{
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockLighting);
|
||||||
return tesselateBlockInWorldWithAmbienceOcclusionTexLighting(
|
return tesselateBlockInWorldWithAmbienceOcclusionTexLighting(
|
||||||
tt, x, y, z, r, g, b, faceFlags, smoothShapeLighting);
|
tt, x, y, z, r, g, b, faceFlags, smoothShapeLighting);
|
||||||
} else {
|
} else {
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockLighting);
|
||||||
return tesselateBlockInWorld(tt, x, y, z, r, g, b);
|
return tesselateBlockInWorld(tt, x, y, z, r, g, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7049,6 +7062,7 @@ bool TileRenderer::tesselateDoorInWorld(Tile* tt, int x, int y, int z) {
|
||||||
|
|
||||||
void TileRenderer::renderFaceDown(Tile* tt, double x, double y, double z,
|
void TileRenderer::renderFaceDown(Tile* tt, double x, double y, double z,
|
||||||
Icon* tex) {
|
Icon* tex) {
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
|
||||||
Tesselator* t = Tesselator::getInstance();
|
Tesselator* t = Tesselator::getInstance();
|
||||||
|
|
||||||
if (hasFixedTexture()) tex = fixedTexture;
|
if (hasFixedTexture()) tex = fixedTexture;
|
||||||
|
|
@ -7167,6 +7181,7 @@ void TileRenderer::renderFaceDown(Tile* tt, double x, double y, double z,
|
||||||
|
|
||||||
void TileRenderer::renderFaceUp(Tile* tt, double x, double y, double z,
|
void TileRenderer::renderFaceUp(Tile* tt, double x, double y, double z,
|
||||||
Icon* tex) {
|
Icon* tex) {
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
|
||||||
Tesselator* t = Tesselator::getInstance();
|
Tesselator* t = Tesselator::getInstance();
|
||||||
|
|
||||||
if (hasFixedTexture()) tex = fixedTexture;
|
if (hasFixedTexture()) tex = fixedTexture;
|
||||||
|
|
@ -7286,6 +7301,7 @@ void TileRenderer::renderFaceUp(Tile* tt, double x, double y, double z,
|
||||||
|
|
||||||
void TileRenderer::renderNorth(Tile* tt, double x, double y, double z,
|
void TileRenderer::renderNorth(Tile* tt, double x, double y, double z,
|
||||||
Icon* tex) {
|
Icon* tex) {
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
|
||||||
Tesselator* t = Tesselator::getInstance();
|
Tesselator* t = Tesselator::getInstance();
|
||||||
|
|
||||||
if (hasFixedTexture()) tex = fixedTexture;
|
if (hasFixedTexture()) tex = fixedTexture;
|
||||||
|
|
@ -7410,6 +7426,7 @@ void TileRenderer::renderNorth(Tile* tt, double x, double y, double z,
|
||||||
|
|
||||||
void TileRenderer::renderSouth(Tile* tt, double x, double y, double z,
|
void TileRenderer::renderSouth(Tile* tt, double x, double y, double z,
|
||||||
Icon* tex) {
|
Icon* tex) {
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
|
||||||
Tesselator* t = Tesselator::getInstance();
|
Tesselator* t = Tesselator::getInstance();
|
||||||
|
|
||||||
if (hasFixedTexture()) tex = fixedTexture;
|
if (hasFixedTexture()) tex = fixedTexture;
|
||||||
|
|
@ -7534,6 +7551,7 @@ void TileRenderer::renderSouth(Tile* tt, double x, double y, double z,
|
||||||
|
|
||||||
void TileRenderer::renderWest(Tile* tt, double x, double y, double z,
|
void TileRenderer::renderWest(Tile* tt, double x, double y, double z,
|
||||||
Icon* tex) {
|
Icon* tex) {
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
|
||||||
Tesselator* t = Tesselator::getInstance();
|
Tesselator* t = Tesselator::getInstance();
|
||||||
|
|
||||||
if (hasFixedTexture()) tex = fixedTexture;
|
if (hasFixedTexture()) tex = fixedTexture;
|
||||||
|
|
@ -7658,6 +7676,7 @@ void TileRenderer::renderWest(Tile* tt, double x, double y, double z,
|
||||||
|
|
||||||
void TileRenderer::renderEast(Tile* tt, double x, double y, double z,
|
void TileRenderer::renderEast(Tile* tt, double x, double y, double z,
|
||||||
Icon* tex) {
|
Icon* tex) {
|
||||||
|
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
|
||||||
Tesselator* t = Tesselator::getInstance();
|
Tesselator* t = Tesselator::getInstance();
|
||||||
|
|
||||||
if (hasFixedTexture()) tex = fixedTexture;
|
if (hasFixedTexture()) tex = fixedTexture;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "../Platform/stdafx.h"
|
#include "../Platform/stdafx.h"
|
||||||
#include "LevelRenderer.h"
|
#include "LevelRenderer.h"
|
||||||
|
|
@ -904,11 +905,12 @@ int LevelRenderer::renderChunks(int from, int to, int layer, double alpha) {
|
||||||
int list = chunk->globalIdx * 2 + layer;
|
int list = chunk->globalIdx * 2 + layer;
|
||||||
list += chunkLists;
|
list += chunkLists;
|
||||||
|
|
||||||
// 4jcraft: replaced glPushMatrix/glTranslatef/glPopMatrix per chunk
|
// 4jcraft: replaced glPushMatrix/glTranslatef/glPopMatrix per
|
||||||
// no more full MVP upload per chunk, can also be bkwards compat
|
// chunk no more full MVP upload per chunk, can also be bkwards
|
||||||
RenderManager.SetChunkOffset((float)chunk->chunk->x,
|
// compat
|
||||||
(float)chunk->chunk->y,
|
RenderManager.SetChunkOffset((float)chunk->chunk->x,
|
||||||
(float)chunk->chunk->z);
|
(float)chunk->chunk->y,
|
||||||
|
(float)chunk->chunk->z);
|
||||||
|
|
||||||
if (RenderManager.CBuffCall(list, first)) {
|
if (RenderManager.CBuffCall(list, first)) {
|
||||||
first = false;
|
first = false;
|
||||||
|
|
@ -1964,7 +1966,41 @@ void LevelRenderer::renderAdvancedClouds(float alpha) {
|
||||||
|
|
||||||
bool LevelRenderer::updateDirtyChunks() {
|
bool LevelRenderer::updateDirtyChunks() {
|
||||||
#ifdef _LARGE_WORLDS
|
#ifdef _LARGE_WORLDS
|
||||||
std::list<std::pair<ClipChunk*, int> > nearestClipChunks;
|
struct NearestClipChunkSet {
|
||||||
|
std::array<std::pair<ClipChunk*, int>, MAX_CONCURRENT_CHUNK_REBUILDS>
|
||||||
|
items;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
bool empty() const noexcept { return count == 0; }
|
||||||
|
int size() const noexcept { return count; }
|
||||||
|
|
||||||
|
bool wouldAccept(int distSqWeighted) const noexcept {
|
||||||
|
return (count < MAX_CONCURRENT_CHUNK_REBUILDS) ||
|
||||||
|
(distSqWeighted < items[count - 1].second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(ClipChunk* chunk, int distSqWeighted) noexcept {
|
||||||
|
int pos = 0;
|
||||||
|
while ((pos < count) && (items[pos].second <= distSqWeighted)) {
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((count == MAX_CONCURRENT_CHUNK_REBUILDS) &&
|
||||||
|
(pos >= MAX_CONCURRENT_CHUNK_REBUILDS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int newCount =
|
||||||
|
(count < MAX_CONCURRENT_CHUNK_REBUILDS)
|
||||||
|
? (count + 1)
|
||||||
|
: MAX_CONCURRENT_CHUNK_REBUILDS;
|
||||||
|
for (int i = newCount - 1; i > pos; --i) {
|
||||||
|
items[i] = items[i - 1];
|
||||||
|
}
|
||||||
|
items[pos] = std::pair<ClipChunk*, int>(chunk, distSqWeighted);
|
||||||
|
count = newCount;
|
||||||
|
}
|
||||||
|
} nearestClipChunks;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ClipChunk* nearChunk = NULL; // Nearest chunk that is dirty
|
ClipChunk* nearChunk = NULL; // Nearest chunk that is dirty
|
||||||
|
|
@ -2090,11 +2126,6 @@ bool LevelRenderer::updateDirtyChunks() {
|
||||||
veryNearCount = g_findNearestChunkDataIn.veryNearCount;
|
veryNearCount = g_findNearestChunkDataIn.veryNearCount;
|
||||||
#else // __PS3__
|
#else // __PS3__
|
||||||
|
|
||||||
#ifdef _LARGE_WORLDS
|
|
||||||
int maxNearestChunks = MAX_CONCURRENT_CHUNK_REBUILDS;
|
|
||||||
// 4J Stu - On XboxOne we should cut this down if in a constrained state
|
|
||||||
// so the saving threads get more time
|
|
||||||
#endif
|
|
||||||
// Find nearest chunk that is dirty
|
// Find nearest chunk that is dirty
|
||||||
for (int p = 0; p < XUSER_MAX_COUNT; p++) {
|
for (int p = 0; p < XUSER_MAX_COUNT; p++) {
|
||||||
// It's possible that the localplayers member can be set to NULL on
|
// It's possible that the localplayers member can be set to NULL on
|
||||||
|
|
@ -2150,17 +2181,9 @@ bool LevelRenderer::updateDirtyChunks() {
|
||||||
considered++;
|
considered++;
|
||||||
// Is this chunk nearer than our nearest?
|
// Is this chunk nearer than our nearest?
|
||||||
#ifdef _LARGE_WORLDS
|
#ifdef _LARGE_WORLDS
|
||||||
bool isNearer = nearestClipChunks.empty();
|
bool isNearer =
|
||||||
AUTO_VAR(itNearest, nearestClipChunks.begin());
|
nearestClipChunks.wouldAccept(
|
||||||
for (; itNearest != nearestClipChunks.end();
|
distSqWeighted);
|
||||||
++itNearest) {
|
|
||||||
isNearer =
|
|
||||||
distSqWeighted < itNearest->second;
|
|
||||||
if (isNearer) break;
|
|
||||||
}
|
|
||||||
isNearer =
|
|
||||||
isNearer || (nearestClipChunks.size() <
|
|
||||||
maxNearestChunks);
|
|
||||||
#else
|
#else
|
||||||
bool isNearer = distSqWeighted < minDistSq;
|
bool isNearer = distSqWeighted < minDistSq;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2203,13 +2226,7 @@ bool LevelRenderer::updateDirtyChunks() {
|
||||||
minDistSq = distSqWeighted;
|
minDistSq = distSqWeighted;
|
||||||
#ifdef _LARGE_WORLDS
|
#ifdef _LARGE_WORLDS
|
||||||
nearestClipChunks.insert(
|
nearestClipChunks.insert(
|
||||||
itNearest,
|
nearChunk, minDistSq);
|
||||||
std::pair<ClipChunk*, int>(
|
|
||||||
nearChunk, minDistSq));
|
|
||||||
if (nearestClipChunks.size() >
|
|
||||||
maxNearestChunks) {
|
|
||||||
nearestClipChunks.pop_back();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
chunk->clearDirty();
|
chunk->clearDirty();
|
||||||
|
|
@ -2249,9 +2266,8 @@ bool LevelRenderer::updateDirtyChunks() {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
{
|
{
|
||||||
FRAME_PROFILE_SCOPE(ChunkRebuildSchedule);
|
FRAME_PROFILE_SCOPE(ChunkRebuildSchedule);
|
||||||
for (AUTO_VAR(it, nearestClipChunks.begin());
|
for (int i = 0; i < nearestClipChunks.size(); ++i) {
|
||||||
it != nearestClipChunks.end(); ++it) {
|
chunk = nearestClipChunks.items[i].first->chunk;
|
||||||
chunk = it->first->chunk;
|
|
||||||
// If this chunk is very near, then move the renderer into a
|
// If this chunk is very near, then move the renderer into a
|
||||||
// deferred mode. This won't commit any command buffers for
|
// deferred mode. This won't commit any command buffers for
|
||||||
// rendering until we call CBuffDeferredModeEnd(), allowing us to
|
// rendering until we call CBuffDeferredModeEnd(), allowing us to
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,11 @@ constexpr std::array<FrameProfiler::BucketDescriptor, kBucketCount>
|
||||||
{Bucket::ChunkDirtyScan, "chunkDirtyScan"},
|
{Bucket::ChunkDirtyScan, "chunkDirtyScan"},
|
||||||
{Bucket::ChunkRebuildSchedule, "chunkRebuildSchedule"},
|
{Bucket::ChunkRebuildSchedule, "chunkRebuildSchedule"},
|
||||||
{Bucket::ChunkRebuildBody, "chunkRebuildBody"},
|
{Bucket::ChunkRebuildBody, "chunkRebuildBody"},
|
||||||
|
{Bucket::ChunkPrepass, "chunkPrepass"},
|
||||||
|
{Bucket::ChunkBlockShape, "chunkBlockShape"},
|
||||||
|
{Bucket::ChunkBlockFaceCull, "chunkBlockFaceCull"},
|
||||||
|
{Bucket::ChunkBlockLighting, "chunkBlockLighting"},
|
||||||
|
{Bucket::ChunkBlockEmit, "chunkBlockEmit"},
|
||||||
{Bucket::Entity, "entities"},
|
{Bucket::Entity, "entities"},
|
||||||
{Bucket::Particle, "particles"},
|
{Bucket::Particle, "particles"},
|
||||||
{Bucket::WeatherSky, "weather"},
|
{Bucket::WeatherSky, "weather"},
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,11 @@ public:
|
||||||
ChunkDirtyScan,
|
ChunkDirtyScan,
|
||||||
ChunkRebuildSchedule,
|
ChunkRebuildSchedule,
|
||||||
ChunkRebuildBody,
|
ChunkRebuildBody,
|
||||||
|
ChunkPrepass,
|
||||||
|
ChunkBlockShape,
|
||||||
|
ChunkBlockFaceCull,
|
||||||
|
ChunkBlockLighting,
|
||||||
|
ChunkBlockEmit,
|
||||||
Entity,
|
Entity,
|
||||||
Particle,
|
Particle,
|
||||||
WeatherSky,
|
WeatherSky,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue