From a8022a70b314d39d1a53d3e393bcbc7e92291f9b Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 17 Jun 2024 20:39:03 +1000 Subject: [PATCH] Lazy load 1D atlases in LOWMEM builds --- src/IsometricDrawer.c | 4 +-- src/MapRenderer.c | 14 +++++---- src/Menus.c | 5 ++-- src/Model.c | 7 +++-- src/Particle.c | 14 +++++---- src/Platform_Dreamcast.c | 2 +- src/Platform_PS2.c | 3 +- src/Screens.c | 2 +- src/TexturePack.c | 64 +++++++++++++++++++++++++++++++++------- src/TexturePack.h | 1 + 10 files changed, 85 insertions(+), 31 deletions(-) diff --git a/src/IsometricDrawer.c b/src/IsometricDrawer.c index 88e4013e7..454d682c0 100644 --- a/src/IsometricDrawer.c +++ b/src/IsometricDrawer.c @@ -156,7 +156,7 @@ void IsometricDrawer_Render(int count, int offset, int* state) { if (state[i] == curIdx) continue; /* Flush previous batch */ - Gfx_BindTexture(Atlas1D.TexIds[curIdx]); + Atlas1D_Bind(curIdx); Gfx_DrawVb_IndexedTris_Range(batchLen, batchBeg); /* Reset for next batch */ @@ -165,6 +165,6 @@ void IsometricDrawer_Render(int count, int offset, int* state) { batchLen = 0; } - Gfx_BindTexture(Atlas1D.TexIds[curIdx]); + Atlas1D_Bind(curIdx); Gfx_DrawVb_IndexedTris_Range(batchLen, batchBeg); } diff --git a/src/MapRenderer.c b/src/MapRenderer.c index 9815474a4..4587fecec 100644 --- a/src/MapRenderer.c +++ b/src/MapRenderer.c @@ -195,10 +195,11 @@ void MapRenderer_RenderNormal(float delta) { Gfx_SetAlphaTest(true); Gfx_EnableMipmaps(); - for (batch = 0; batch < MapRenderer_1DUsedCount; batch++) { + for (batch = 0; batch < MapRenderer_1DUsedCount; batch++) + { if (normPartsCount[batch] <= 0) continue; if (hasNormParts[batch] || checkNormParts[batch]) { - Gfx_BindTexture(Atlas1D.TexIds[batch]); + Atlas1D_Bind(batch); RenderNormalBatch(batch); checkNormParts[batch] = false; } @@ -270,7 +271,8 @@ void MapRenderer_RenderTranslucent(float delta) { Gfx_SetAlphaBlending(false); Gfx_DepthOnlyRendering(true); - for (batch = 0; batch < MapRenderer_1DUsedCount; batch++) { + for (batch = 0; batch < MapRenderer_1DUsedCount; batch++) + { if (tranPartsCount[batch] <= 0) continue; if (hasTranParts[batch] || checkTranParts[batch]) { RenderTranslucentBatch(batch); @@ -285,10 +287,12 @@ void MapRenderer_RenderTranslucent(float delta) { Gfx_SetDepthWrite(false); /* already calculated depth values in depth pass */ Gfx_EnableMipmaps(); - for (batch = 0; batch < MapRenderer_1DUsedCount; batch++) { + for (batch = 0; batch < MapRenderer_1DUsedCount; batch++) + { if (tranPartsCount[batch] <= 0) continue; if (!hasTranParts[batch]) continue; - Gfx_BindTexture(Atlas1D.TexIds[batch]); + + Atlas1D_Bind(batch); RenderTranslucentBatch(batch); } Gfx_DisableMipmaps(); diff --git a/src/Menus.c b/src/Menus.c index 8cbba8486..9c17edccc 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -3708,8 +3708,9 @@ static void TexIdsOverlay_BuildMesh(void* screen) { static int TexIdsOverlay_RenderTerrain(struct TexIdsOverlay* s, int offset) { int i, count = Atlas1D.TilesPerAtlas * 4; - for (i = 0; i < Atlas1D.Count; i++) { - Gfx_BindTexture(Atlas1D.TexIds[i]); + for (i = 0; i < Atlas1D.Count; i++) + { + Atlas1D_Bind(i); Gfx_DrawVb_IndexedTris_Range(count, offset); offset += count; diff --git a/src/Model.c b/src/Model.c index 7df5d52cc..e6bcf25ec 100644 --- a/src/Model.c +++ b/src/Model.c @@ -2190,11 +2190,12 @@ static void BlockModel_DrawParts(void) { int lastTexIndex, i, offset = 0, count = 0; lastTexIndex = bModel_texIndices[0]; - for (i = 0; i < bModel_index; i++, count += 4) { + for (i = 0; i < bModel_index; i++, count += 4) + { if (bModel_texIndices[i] == lastTexIndex) continue; /* Different 1D flush texture, flush current vertices */ - Gfx_BindTexture(Atlas1D.TexIds[lastTexIndex]); + Atlas1D_Bind(lastTexIndex); Gfx_DrawVb_IndexedTris_Range(count, offset); lastTexIndex = bModel_texIndices[i]; @@ -2204,7 +2205,7 @@ static void BlockModel_DrawParts(void) { /* Leftover vertices */ if (!count) return; - Gfx_BindTexture(Atlas1D.TexIds[lastTexIndex]); + Atlas1D_Bind(lastTexIndex); Gfx_DrawVb_IndexedTris_Range(count, offset); } diff --git a/src/Particle.c b/src/Particle.c index 403900c8e..719f3ef30 100644 --- a/src/Particle.c +++ b/src/Particle.c @@ -280,7 +280,8 @@ static void Terrain_Render(float t) { data = (struct VertexTextured*)Gfx_LockDynamicVb(particles_VB, VERTEX_FORMAT_TEXTURED, terrain_count * 4); Terrain_Update1DCounts(); - for (i = 0; i < terrain_count; i++) { + for (i = 0; i < terrain_count; i++) + { index = Atlas1D_Index(terrain_particles[i].texLoc); ptr = data + terrain_1DIndices[index]; @@ -289,18 +290,20 @@ static void Terrain_Render(float t) { } Gfx_UnlockDynamicVb(particles_VB); - for (i = 0; i < Atlas1D.Count; i++) { + for (i = 0; i < Atlas1D.Count; i++) + { int partCount = terrain_1DCount[i]; if (!partCount) continue; - Gfx_BindTexture(Atlas1D.TexIds[i]); + Atlas1D_Bind(i); Gfx_DrawVb_IndexedTris_Range(partCount, offset); offset += partCount; } } static void Terrain_RemoveAt(int i) { - for (; i < terrain_count - 1; i++) { + for (; i < terrain_count - 1; i++) + { terrain_particles[i] = terrain_particles[i + 1]; } terrain_count--; @@ -308,7 +311,8 @@ static void Terrain_RemoveAt(int i) { static void Terrain_Tick(float delta) { int i; - for (i = 0; i < terrain_count; i++) { + for (i = 0; i < terrain_count; i++) + { if (TerrainParticle_Tick(&terrain_particles[i], delta)) { Terrain_RemoveAt(i); i--; } diff --git a/src/Platform_Dreamcast.c b/src/Platform_Dreamcast.c index d37d1b720..ed7cfc0de 100644 --- a/src/Platform_Dreamcast.c +++ b/src/Platform_Dreamcast.c @@ -263,7 +263,7 @@ static cc_result File_Do(cc_file* file, const char* path, int mode) { // Read/Write VMU for options.txt if no SD card, since that file is critical cc_string raw = String_FromReadonly(path); - if (err && String_CaselessEqualsConst(raw, "/cd/options.txt")) { + if (err && String_CaselessEqualsConst(&raw, "/cd/options.txt")) { return VMUFile_Do(file, mode); } return err; diff --git a/src/Platform_PS2.c b/src/Platform_PS2.c index 5f9347c40..2a9ed30c4 100644 --- a/src/Platform_PS2.c +++ b/src/Platform_PS2.c @@ -63,6 +63,7 @@ void Platform_Log(const char* msg, int len) { Mem_Copy(tmp, msg, len); tmp[len] = '\0'; _print("%s", tmp); +#define PS2_DEBUG #ifdef PS2_DEBUG volatile char* dst = (char*)0x1000F180; @@ -689,7 +690,7 @@ void Platform_Init(void) { // Create root directory cc_filepath* root = FILEPATH_RAW("mass:/ClassiCube"); - int res = Diectory_Create(root); + int res = Directory_Create(root); Platform_Log1("ROOT CREATE %i", &res); } diff --git a/src/Screens.c b/src/Screens.c index 2e12b0524..d5cafcda9 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -1927,7 +1927,7 @@ static void LoadingScreen_Render(void* screen, float delta) { offset = 0; if (s->rows) { loc = Block_Tex(BLOCK_DIRT, FACE_YMAX); - Gfx_BindTexture(Atlas1D.TexIds[Atlas1D_Index(loc)]); + Atlas1D_Bind(Atlas1D_Index(loc)); Gfx_DrawVb_IndexedTris(s->rows * 4); offset = s->rows * 4; } diff --git a/src/TexturePack.c b/src/TexturePack.c index b66c58635..354fc4da8 100644 --- a/src/TexturePack.c +++ b/src/TexturePack.c @@ -79,29 +79,71 @@ TextureRec Atlas1D_TexRec(TextureLoc texLoc, int uCount, int* index) { return rec; } + +static void Atlas1D_Load(int index, struct Bitmap* atlas1D) { + int tileSize = Atlas2D.TileSize; + int tilesPerAtlas = Atlas1D.TilesPerAtlas; + int y, tile = index * tilesPerAtlas; + int atlasX, atlasY; + + for (y = 0; y < tilesPerAtlas; y++, tile++) + { + atlasX = Atlas2D_TileX(tile) * tileSize; + atlasY = Atlas2D_TileY(tile) * tileSize; + + Bitmap_UNSAFE_CopyBlock(atlasX, atlasY, 0, y * tileSize, + &Atlas2D.Bmp, atlas1D, tileSize); + } + Gfx_RecreateTexture(&Atlas1D.TexIds[index], atlas1D, TEXTURE_FLAG_MANAGED | TEXTURE_FLAG_DYNAMIC, Gfx.Mipmaps); +} + +/* TODO: always do this? */ +#ifdef CC_BUILD_LOWMEM +static void Atlas1D_LoadBlock(int index) { + int tileSize = Atlas2D.TileSize; + int tilesPerAtlas = Atlas1D.TilesPerAtlas; + struct Bitmap atlas1D; + + Platform_Log2("Lazy load atlas #%i (%i per bmp)", &index, &tilesPerAtlas); + Bitmap_Allocate(&atlas1D, tileSize, tilesPerAtlas * tileSize); + + Atlas1D_Load(index, &atlas1D); + Mem_Free(atlas1D.scan0); +} + +void Atlas1D_Bind(int index) { + if (index < Atlas1D.Count && !Atlas1D.TexIds[index]) + Atlas1D_LoadBlock(index); + Gfx_BindTexture(Atlas1D.TexIds[index]); +} + +static void Atlas_Convert2DTo1D(void) { + int tilesPerAtlas = Atlas1D.TilesPerAtlas; + int atlasesCount = Atlas1D.Count; + Platform_Log2("Terrain atlas: %i bmps, %i per bmp", &atlasesCount, &tilesPerAtlas); +} +#else +void Atlas1D_Bind(int index) { + Gfx_BindTexture(Atlas1D.TexIds[index]); +} + static void Atlas_Convert2DTo1D(void) { int tileSize = Atlas2D.TileSize; int tilesPerAtlas = Atlas1D.TilesPerAtlas; int atlasesCount = Atlas1D.Count; struct Bitmap atlas1D; - int atlasX, atlasY; - int tile = 0, i, y; + int tile = 0, i; Platform_Log2("Loaded terrain atlas: %i bmps, %i per bmp", &atlasesCount, &tilesPerAtlas); Bitmap_Allocate(&atlas1D, tileSize, tilesPerAtlas * tileSize); - for (i = 0; i < atlasesCount; i++) { - for (y = 0; y < tilesPerAtlas; y++, tile++) { - atlasX = Atlas2D_TileX(tile) * tileSize; - atlasY = Atlas2D_TileY(tile) * tileSize; - - Bitmap_UNSAFE_CopyBlock(atlasX, atlasY, 0, y * tileSize, - &Atlas2D.Bmp, &atlas1D, tileSize); - } - Gfx_RecreateTexture(&Atlas1D.TexIds[i], &atlas1D, TEXTURE_FLAG_MANAGED | TEXTURE_FLAG_DYNAMIC, Gfx.Mipmaps); + for (i = 0; i < atlasesCount; i++) + { + Atlas1D_Load(i, &atlas1D); } Mem_Free(atlas1D.scan0); } +#endif static void Atlas_Update1D(void) { int maxAtlasHeight, maxTilesPerAtlas, maxTiles; diff --git a/src/TexturePack.h b/src/TexturePack.h index 781e38043..b98c87fe6 100644 --- a/src/TexturePack.h +++ b/src/TexturePack.h @@ -73,6 +73,7 @@ cc_bool Atlas_TryChange(struct Bitmap* bmp); /* That is, returns U1/U2/V1/V2 coords that make up the tile in a 1D atlas. */ /* index is set to the index of the 1D atlas that the tile is in. */ TextureRec Atlas1D_TexRec(TextureLoc texLoc, int uCount, int* index); +void Atlas1D_Bind(int index); /* Whether the given URL is in list of accepted URLs. */ cc_bool TextureCache_HasAccepted(const cc_string* url);