Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 35 additions & 23 deletions Minecraft.Client/Chunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ void Chunk::setPos(int x, int y, int z)
clipChunk->zm = zm;

clipChunk->globalIdx = LevelRenderer::getGlobalIndexForChunk(x, y, z, level);
int globalIdx = clipChunk->globalIdx;

#if 1
// 4J - we're not using offsetted renderlists anymore, so just set the full position of this chunk into x/y/zRenderOffs where
Expand Down Expand Up @@ -126,6 +127,11 @@ void Chunk::setPos(int x, int y, int z)
// If we're the first thing to be referencing this, mark it up as dirty to get rebuilt
if( refCount == 1 )
{
int listBase = levelRenderer->allocateListBaseForGlobalIdx(globalIdx);
if (listBase < 0)
{
__debugbreak();
}
// printf("Setting %d %d %d dirty [%d]\n",x,y,z, idx);
// Chunks being made dirty in this way can be very numerous (eg the full visible area of the world at start up, or a whole edge of the world when moving).
// On account of this, don't want to stick them into our lock free queue that we would normally use for letting the render update thread know about this chunk.
Expand Down Expand Up @@ -211,8 +217,14 @@ void Chunk::rebuild()

int r = 1;

int lists = levelRenderer->getGlobalIndexForChunk(this->x,this->y,this->z,level) * 2;
lists += levelRenderer->chunkLists;
int globalIdx = levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
int listBase = levelRenderer->getListBaseForGlobalIdx(globalIdx);
if (listBase < 0)
{
__debugbreak();
PIXEndNamedEvent();
return;
}

PIXEndNamedEvent();

Expand Down Expand Up @@ -324,7 +336,7 @@ void Chunk::rebuild()
for (int currentLayer = 0; currentLayer < 2; currentLayer++)
{
levelRenderer->setGlobalChunkFlag(this->x, this->y, this->z, level, LevelRenderer::CHUNK_FLAG_EMPTY0, currentLayer);
RenderManager.CBuffClear(lists + currentLayer);
RenderManager.CBuffClear(listBase + currentLayer);
}

delete region;
Expand Down Expand Up @@ -381,7 +393,7 @@ void Chunk::rebuild()
started = true;

MemSect(31);
glNewList(lists + currentLayer, GL_COMPILE);
glNewList(listBase + currentLayer, GL_COMPILE);
MemSect(0);
glPushMatrix();
glDepthMask(true); // 4J added
Expand Down Expand Up @@ -459,12 +471,12 @@ void Chunk::rebuild()
{
// 4J - added - clear any renderer data associated with this unused list
levelRenderer->setGlobalChunkFlag(this->x, this->y, this->z, level, LevelRenderer::CHUNK_FLAG_EMPTY0, currentLayer);
RenderManager.CBuffClear(lists + currentLayer);
RenderManager.CBuffClear(listBase + currentLayer);
}
if((currentLayer==0)&&(!renderNextLayer))
{
levelRenderer->setGlobalChunkFlag(this->x, this->y, this->z, level, LevelRenderer::CHUNK_FLAG_EMPTY1);
RenderManager.CBuffClear(lists + 1);
RenderManager.CBuffClear(listBase + 1);
break;
}
}
Expand Down Expand Up @@ -670,8 +682,12 @@ void Chunk::rebuild_SPU()
Region region(level, x0 - r, y0 - r, z0 - r, x1 + r, y1 + r, z1 + r);
TileRenderer tileRenderer(&region);

int lists = levelRenderer->getGlobalIndexForChunk(this->x,this->y,this->z,level) * 2;
lists += levelRenderer->chunkLists;
int globalIdx = levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
int listBase = levelRenderer->getListBaseForGlobalIdx(globalIdx);
if (listBase < 0)
{
return;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 4J - optimisation begins.
Expand Down Expand Up @@ -700,7 +716,7 @@ void Chunk::rebuild_SPU()
bool rendered = false;

{
glNewList(lists + currentLayer, GL_COMPILE);
glNewList(listBase + currentLayer, GL_COMPILE);
MemSect(0);
glPushMatrix();
glDepthMask(true); // 4J added
Expand Down Expand Up @@ -796,7 +812,7 @@ void Chunk::rebuild_SPU()
{
// 4J - added - clear any renderer data associated with this unused list
levelRenderer->setGlobalChunkFlag(this->x, this->y, this->z, level, LevelRenderer::CHUNK_FLAG_EMPTY0, currentLayer);
RenderManager.CBuffClear(lists + currentLayer);
RenderManager.CBuffClear(listBase + currentLayer);
}

}
Expand Down Expand Up @@ -965,18 +981,13 @@ void Chunk::reset()
unsigned char refCount = levelRenderer->decGlobalChunkRefCount(x, y, z, level);
assigned = false;
// printf("\t\t [dec] refcount %d at %d, %d, %d\n",refCount,x,y,z);
if( refCount == 0 )
if (refCount == 0)
{
int lists = levelRenderer->getGlobalIndexForChunk(x, y, z, level) * 2;
if(lists >= 0)
int globalIdx = levelRenderer->getGlobalIndexForChunk(x, y, z, level);
if (globalIdx >= 0)
{
lists += levelRenderer->chunkLists;
for (int i = 0; i < 2; i++)
{
// 4J - added - clear any renderer data associated with this unused list
RenderManager.CBuffClear(lists + i);
}
levelRenderer->setGlobalChunkFlags(x, y, z, level, 0);
levelRenderer->freeListBaseForGlobalIdx(globalIdx);
}
}
LeaveCriticalSection(&levelRenderer->m_csDirtyChunks);
Expand All @@ -995,11 +1006,12 @@ int Chunk::getList(int layer)
{
if (!clipChunk->visible) return -1;

int lists = levelRenderer->getGlobalIndexForChunk(x, y, z,level) * 2;
lists += levelRenderer->chunkLists;
int globalIdx = levelRenderer->getGlobalIndexForChunk(x, y, z, level);
int listBase = levelRenderer->getListBaseForGlobalIdx(globalIdx);
if (listBase < 0) return -1;

bool empty = levelRenderer->getGlobalChunkFlag(x, y, z, level, LevelRenderer::CHUNK_FLAG_EMPTY0, layer);
if (!empty) return lists + layer;
bool empty = levelRenderer->getGlobalChunkFlag(x, y, z, level, LevelRenderer::CHUNK_FLAG_EMPTY0, layer);
if (!empty) return listBase + layer;
return -1;
}

Expand Down
56 changes: 53 additions & 3 deletions Minecraft.Client/LevelRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ C4JThread *LevelRenderer::rebuildThreads[MAX_CHUNK_REBUILD_THREADS];
C4JThread::EventArray *LevelRenderer::s_rebuildCompleteEvents;
C4JThread::Event *LevelRenderer::s_activationEventA[MAX_CHUNK_REBUILD_THREADS];

unordered_map<int, int> m_globalIdxToListBase;
vector<int> m_freeListBases;

// This defines the maximum size of renderable level, must be big enough to cope with actual size of level + view distance at each side
// so that we can render the "infinite" sea at the edges. Currently defined as:
const int overworldSize = LEVEL_MAX_WIDTH + LevelRenderer::PLAYER_VIEW_DISTANCE + LevelRenderer::PLAYER_VIEW_DISTANCE;
Expand Down Expand Up @@ -149,10 +152,18 @@ LevelRenderer::LevelRenderer(Minecraft *mc, Textures *textures)
this->mc = mc;
this->textures = textures;

chunkLists = MemoryTracker::genLists(getGlobalChunkCount()*2); // *2 here is because there is one renderlist per chunk here for each of the opaque & transparent layers
chunkLists = MemoryTracker::genLists(MAX_RENDER_CHUNK_SLOTS * 2); // *2 here is because there is one renderlist per chunk here for each of the opaque & transparent layers
globalChunkFlags = new unsigned char[getGlobalChunkCount()];
memset(globalChunkFlags, 0, getGlobalChunkCount());

m_globalIdxToListBase.clear();
m_freeListBases.clear();
m_freeListBases.reserve(MAX_RENDER_CHUNK_SLOTS);
for (int i = 0; i < MAX_RENDER_CHUNK_SLOTS; ++i)
{
m_freeListBases.push_back(chunkLists + i * 2);
}

starList = MemoryTracker::genLists(4);

glPushMatrix();
Expand Down Expand Up @@ -250,6 +261,43 @@ LevelRenderer::LevelRenderer(Minecraft *mc, Textures *textures)
#endif // __PS3__
}

int LevelRenderer::allocateListBaseForGlobalIdx(int globalIdx)
{
AUTO_VAR(it, m_globalIdxToListBase.find(globalIdx));
if (it != m_globalIdxToListBase.end())
return it->second;

if (m_freeListBases.empty())
return -1;

int listBase = m_freeListBases.back();
m_freeListBases.pop_back();
m_globalIdxToListBase[globalIdx] = listBase;
return listBase;
}

void LevelRenderer::freeListBaseForGlobalIdx(int globalIdx)
{
AUTO_VAR(it, m_globalIdxToListBase.find(globalIdx));
if (it == m_globalIdxToListBase.end())
return;

int listBase = it->second;
RenderManager.CBuffClear(listBase + 0);
RenderManager.CBuffClear(listBase + 1);

m_freeListBases.push_back(listBase);
m_globalIdxToListBase.erase(it);
}

int LevelRenderer::getListBaseForGlobalIdx(int globalIdx) const
{
AUTO_VAR(it, m_globalIdxToListBase.find(globalIdx));
if (it == m_globalIdxToListBase.end())
return -1;
return it->second;
}

void LevelRenderer::renderStars()
{
Random random = Random(10842);
Expand Down Expand Up @@ -787,8 +835,10 @@ int LevelRenderer::renderChunks(int from, int to, int layer, double alpha)
if( ( globalChunkFlags[pClipChunk->globalIdx] & emptyFlag ) == emptyFlag ) continue; // Check that this particular layer isn't empty

// List can be calculated directly from the chunk's global idex
int list = pClipChunk->globalIdx * 2 + layer;
list += chunkLists;
int listBase = getListBaseForGlobalIdx(pClipChunk->globalIdx);
if (listBase < 0)
continue;
int list = listBase + layer;

if(RenderManager.CBuffCall(list, first))
{
Expand Down
7 changes: 7 additions & 0 deletions Minecraft.Client/LevelRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ class LevelRenderer : public LevelListener
#ifdef _LARGE_WORLDS
static const int PLAYER_VIEW_DISTANCE = 18; // Straight line distance from centre to extent of visible world
static const int PLAYER_RENDER_AREA = (PLAYER_VIEW_DISTANCE * PLAYER_VIEW_DISTANCE * 4);

static const int MAX_CHUNKS_PER_PLAYER = PLAYER_RENDER_AREA * CHUNK_Y_COUNT;
static const int MAX_RENDER_CHUNK_SLOTS = MAX_CHUNKS_PER_PLAYER * 4;
#else
static const int PLAYER_RENDER_AREA = 400;
#endif
Expand Down Expand Up @@ -271,6 +274,10 @@ class LevelRenderer : public LevelListener
static void staticCtor();
static int rebuildChunkThreadProc(LPVOID lpParam);

int allocateListBaseForGlobalIdx(int globalIdx);
void freeListBaseForGlobalIdx(int globalIdx);
int getListBaseForGlobalIdx(int globalIdx) const;

CRITICAL_SECTION m_csChunkFlags;
#endif
void nonStackDirtyChunksAdded();
Expand Down
2 changes: 1 addition & 1 deletion Minecraft.World/ChunkSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class TilePos;
// The maximum number of chunks that we can store
#ifdef _LARGE_WORLDS
// 4J Stu - Our default map (at zoom level 3) is 1024x1024 blocks (or 64 chunks)
#define LEVEL_MAX_WIDTH (5*64) //(6*54)
#define LEVEL_MAX_WIDTH (64*64) //(6*54) I have tested up to 512x64, but the game was using 16gb of ram to do so, so probably don't set it this high. I am leaving this at 64*64 for now, but feel free to change it lol
#else
#define LEVEL_MAX_WIDTH 54
#endif
Expand Down
37 changes: 25 additions & 12 deletions Minecraft.World/Dimension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,29 +67,42 @@ Dimension::~Dimension()
delete biomeSource;
}

ChunkSource *Dimension::createRandomLevelSource() const
ChunkSource* Dimension::createRandomLevelSource() const
{
ChunkSource* src = NULL;

#ifdef _OVERRIDE_HEIGHTMAP
// 4J Stu - Added to enable overriding the heightmap from a loaded in data file
if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_EnableHeightWaterBiomeOverride))
if (app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad()) & (1L << eDebugSetting_EnableHeightWaterBiomeOverride))
{
return new CustomLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
src = new CustomLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
}
else
#endif
if (levelType == LevelType::lvl_flat)
if (levelType == LevelType::lvl_flat)
{
src = new FlatLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
}
else
{
src = new RandomLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
}

if (src != NULL)
{
return new FlatLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
}
else
{
return new RandomLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
src->m_XZSize = level->getLevelData()->getXZSize();
}

return src;
}

ChunkSource *Dimension::createFlatLevelSource() const
ChunkSource* Dimension::createFlatLevelSource() const
{
return new FlatLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
ChunkSource* src = new FlatLevelSource(level, level->getSeed(), level->getLevelData()->isGenerateMapFeatures());
if (src != NULL)
{
src->m_XZSize = level->getLevelData()->getXZSize();
}
return src;
}

ChunkStorage *Dimension::createStorage(File dir)
Expand Down
7 changes: 5 additions & 2 deletions Minecraft.World/RandomLevelSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,9 +573,12 @@ doubleArray RandomLevelSource::getHeights(doubleArray buffer, int x, int y, int

}

bool RandomLevelSource::hasChunk(int x, int y)
bool RandomLevelSource::hasChunk(int x, int z)
{
return true;
const int half = m_XZSize / 2;

return (x >= -half && x < half &&
z >= -half && z < half);
}

void RandomLevelSource::calcWaterDepths(ChunkSource *parent, int xt, int zt)
Expand Down