From 5803810069ecb7a6fb1d10bb4f882f7793a03e3d Mon Sep 17 00:00:00 2001 From: XProger Date: Wed, 19 Feb 2020 05:12:41 +0300 Subject: [PATCH] fix 3DS stability --- src/core.h | 2 + src/gapi/c3d.h | 81 +++++++++++++++++++-------------------- src/inventory.h | 18 ++++++--- src/platform/3ds/Makefile | 2 +- src/utils.h | 7 +--- 5 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/core.h b/src/core.h index 1c8719f..a0dd4c6 100644 --- a/src/core.h +++ b/src/core.h @@ -96,6 +96,8 @@ extern int WEBGL_VERSION; #elif _3DS + #include <3ds.h> + #define _OS_3DS 1 #define _GAPI_C3D 1 diff --git a/src/gapi/c3d.h b/src/gapi/c3d.h index cf6f7ac..2c0ea1e 100644 --- a/src/gapi/c3d.h +++ b/src/gapi/c3d.h @@ -1,9 +1,7 @@ #ifndef H_GAPI_C3D #define H_GAPI_C3D -#include <3ds.h> #include - #include "core.h" #define PROFILE_MARKER(title) @@ -34,11 +32,10 @@ namespace GAPI { ubyte4 light; }; - int VRAM = 0; + int VRAM_TOTAL = 0; - void mmLogVRAM(int size) { - VRAM += size; - LOG("VRAM: %d = %d kb\n", size / 1024, VRAM / 1024); + void mmLogVRAM() { + LOG("VRAM: %d / %d kb\n", (VRAM_TOTAL - vramSpaceFree()) / 1024, VRAM_TOTAL / 1024); } bool mmIsVRAM(void *addr) { @@ -49,11 +46,11 @@ namespace GAPI { void* mmAlloc(size_t size) { void *addr = vramAlloc(size); if (!addr) { - LOG("! OUT OF VRAM %d + %d\n", VRAM / 1024, size / 1024); + LOG("! OUT OF VRAM %d < %d\n", vramSpaceFree() / 1024, size / 1024); addr = linearAlloc(size); ASSERT(addr); } else { - mmLogVRAM(size); + mmLogVRAM(); } return addr; } @@ -61,8 +58,8 @@ namespace GAPI { void mmFree(void *addr) { if (!addr) return; if (mmIsVRAM(addr)) { - mmLogVRAM(-vramGetSize(addr)); vramFree(addr); + mmLogVRAM(); } else { linearFree(addr); } @@ -70,7 +67,7 @@ namespace GAPI { void mmCopy(void *dst, void *src, size_t size) { if (mmIsVRAM(dst)) { - GSPGPU_FlushDataCache(dst, size); + GSPGPU_FlushDataCache(src, size); GX_RequestDma((u32*)src, (u32*)dst, size); gspWaitForDMA(); } else { @@ -321,7 +318,7 @@ namespace GAPI { C3D_Tex tex; C3D_TexCube texCube; - C3D_RenderTarget *target[6]; + C3D_RenderTarget *target; void convertImage32(uint32 *dst, uint32 *src, int dstWidth, int dstHeight, int srcWidth, int srcHeight) { // 8x8 tiles swizzling @@ -422,7 +419,8 @@ namespace GAPI { Texture(int width, int height, int depth, uint32 opt) : width(width), height(height), origWidth(width), origHeight(height), fmt(FMT_RGBA), opt(opt) { opt |= OPT_NEAREST; - memset(target, 0, sizeof(target)); + target = (C3D_RenderTarget*)malloc(sizeof(C3D_RenderTarget) * 6); + memset(target, 0, sizeof(C3D_RenderTarget) * 6); } void init(void *data) { @@ -472,9 +470,7 @@ namespace GAPI { ASSERT(ret); - if (mmIsVRAM(tex.data)) { - mmLogVRAM(C3D_TexCalcTotalSize(tex.size, tex.maxLevel) * (isCube ? 6 : 1)); - } + mmLogVRAM(); if (data && !isCube) { update(data); @@ -486,17 +482,10 @@ namespace GAPI { } void deinit() { - for (int i = 0; i < 6; i++) { - if (target[i]) { - C3D_RenderTargetDelete(target[i]); - } - } - - if (mmIsVRAM(tex.data)) { - mmLogVRAM(-C3D_TexCalcTotalSize(tex.size, tex.maxLevel) * ((opt & OPT_CUBEMAP) ? 6 : 1)); - } - C3D_TexDelete(&tex); + mmLogVRAM(); + + free(target); } void generateMipMap() { @@ -739,12 +728,7 @@ namespace GAPI { DepthBuffer &db = depthBuffers[group]; - int size = width * height; - switch (format) { - case GPU_RB_DEPTH16 : size *= 2; break; - case GPU_RB_DEPTH24 : size *= 3; break; - case GPU_RB_DEPTH24_STENCIL8 : size *= 4; break; - } + int size = C3D_CalcDepthBufSize(width, height, format); if (!db.data) { LOG("alloc depth alias group %d (size: %d %dx%d)\n", group, size / 1024, width, height); @@ -758,28 +742,39 @@ namespace GAPI { return db.data; } + LOG("! can't fit depth %dx%d %d ([%d] = %d)\n", width, height, size / 1024, group, db.size / 1024); + ASSERT(false); return NULL; } C3D_RenderTarget* checkRenderTarget(Texture *texture, int face, int group, GPU_DEPTHBUF depthFmt) { - if (!texture->target[face]) { - if (face > 0) { - LOG("create RT for face:%d %dx%d\n", face, texture->width, texture->height); - } - C3D_RenderTarget *target = C3D_RenderTargetCreateFromTex(&texture->tex, GPU_TEXFACE(face), 0, GPU_DEPTHBUF(-1)); - void *depthBuf = getDepthBuffer(texture->width, texture->height, group, depthFmt); - C3D_FrameBufDepth(&target->frameBuf, depthBuf, depthFmt); - texture->target[face] = target; + if (!texture->target[face].frameBuf.colorBuf) { + LOG("create RT for face:%d %dx%d\n", face, texture->width, texture->height); + + C3D_FrameBuf &fb = texture->target[face].frameBuf; + fb.colorBuf = (texture->opt & OPT_CUBEMAP) ? texture->texCube.data[face] : texture->tex.data; + fb.depthBuf = getDepthBuffer(texture->width, texture->height, group, depthFmt); + fb.colorFmt = GPU_COLORBUF(formats[texture->fmt].format); + fb.depthFmt = depthFmt; + fb.colorMask = 0x0F; + fb.depthMask = 0x02; // no stencil + fb.width = texture->width; + fb.height = texture->height; + fb.block32 = false; } - return texture->target[face]; + return &texture->target[face]; } void init() { memset(depthBuffers, 0, sizeof(depthBuffers)); gfxInitDefault(); + + vramAlloc(0); + VRAM_TOTAL = vramSpaceFree(); + consoleInit(GFX_BOTTOM, NULL); LOG("Vendor : %s\n", "DMP"); @@ -832,11 +827,13 @@ namespace GAPI { int height = tex->width; C3D_RenderTarget *target = C3D_RenderTargetCreate(width, height, GPU_RB_RGB8, C3D_DEPTHTYPE(-1)); - mmLogVRAM(width * height * 3); + mmLogVRAM(); void *depthBuf = getDepthBuffer(width, height, 0, GPU_RB_DEPTH16); C3D_FrameBufDepth(&target->frameBuf, depthBuf, GPU_RB_DEPTH16); - GAPI::defTarget[i] = tex->target[0] = target; + tex->target[0] = *target; + + GAPI::defTarget[i] = &tex->target[0]; } C3D_RenderTargetSetOutput(defTarget[0], GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); diff --git a/src/inventory.h b/src/inventory.h index b98d836..978406e 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -235,6 +235,7 @@ struct Inventory { }; IGame *game; + Texture *title; Texture *background[3]; // [LEFT EYE or SINGLE, RIGHT EYE, TEMP] Video *video; @@ -592,7 +593,8 @@ struct Inventory { } inv->titleTimer = inv->game->getLevel()->isTitle() ? 0.0f : 3.0f; - inv->background[0] = Texture::Load(*stream); + inv->title = Texture::Load(*stream); + inv->background[0] = inv->title; delete stream; } @@ -615,7 +617,7 @@ struct Inventory { } } - Inventory() : game(NULL), itemsCount(0) { + Inventory() : game(NULL), title(NULL), itemsCount(0) { memset(background, 0, sizeof(background)); reset(); } @@ -630,10 +632,17 @@ struct Inventory { delete items[i]; itemsCount = 0; + if (background[0] == title) { + background[0] = NULL; + } + for (int i = 0; i < COUNT(background); i++) { delete background[i]; background[i] = NULL; } + + delete title; + title = NULL; } void reset() { @@ -1392,14 +1401,13 @@ struct Inventory { } Texture* getBackgroundTarget(int view) { - if (background[0] && (background[0]->origWidth != INV_BG_SIZE || background[0]->origHeight != INV_BG_SIZE)) { - delete background[0]; + if (background[0] == title) { background[0] = NULL; } for (int i = 0; i < COUNT(background); i++) { if (!background[i]) { - background[i] = new Texture(INV_BG_SIZE, INV_BG_SIZE, 1, FMT_RGB16, OPT_TARGET); + background[i] = new Texture(INV_BG_SIZE, INV_BG_SIZE, 1, FMT_RGBA, OPT_TARGET); } } diff --git a/src/platform/3ds/Makefile b/src/platform/3ds/Makefile index 406589d..8d77d99 100644 --- a/src/platform/3ds/Makefile +++ b/src/platform/3ds/Makefile @@ -48,7 +48,7 @@ APP_DESCRIPTION := Classic Tomb Raider open-source engine #--------------------------------------------------------------------------------- ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft -CFLAGS := -g -w -Ofast -ffast-math -mword-relocations \ +CFLAGS := -g0 -w -Ofast -ffast-math -mword-relocations \ -fomit-frame-pointer -ffunction-sections \ $(ARCH) diff --git a/src/utils.h b/src/utils.h index 973c34c..431bf48 100644 --- a/src/utils.h +++ b/src/utils.h @@ -10,6 +10,8 @@ #ifdef _DEBUG #if defined(_OS_LINUX) || defined(_OS_RPI) || defined(_OS_CLOVER) #define debugBreak() raise(SIGTRAP); + #elif defined(_OS_3DS) + #define debugBreak() svcBreak(USERBREAK_ASSERT); #else #define debugBreak() _asm { int 3 } #endif @@ -23,12 +25,7 @@ #else -#ifdef _OS_3DS - #define ASSERT(expr) if (expr) {} else { LOG("ASSERT:\n %s:%d\n %s => %s\n", __FILE__, __LINE__, __FUNCTION__, #expr); /* svcSleepThread(3000000000LL);*/ abort(); } -#else #define ASSERT(expr) -#endif - #define ASSERTV(expr) (expr) ? 1 : 0 #ifdef PROFILE