Gfx: Initial work on supporting graphics backends whose available VRAM size for texture storage is smaller than their maximum supported texture dimensions

This commit is contained in:
UnknownShadow200 2023-11-28 09:00:13 +11:00
parent 542325c75c
commit b603cad5ae
20 changed files with 80 additions and 40 deletions

View File

@ -326,7 +326,7 @@ static cc_result ApplySkin(struct Entity* e, struct Bitmap* bmp, struct Stream*
if ((res = EnsurePow2Skin(e, bmp))) return res;
e->SkinType = Utils_CalcSkinType(bmp);
if (bmp->width > Gfx.MaxTexWidth || bmp->height > Gfx.MaxTexHeight) {
if (!Gfx_CheckTextureSize(bmp->width, bmp->height)) {
Chat_Add1("&cSkin %s is too large", skin);
} else {
if (e->Model->flags & MODEL_FLAG_CLEAR_HAT)

View File

@ -231,6 +231,8 @@ cc_bool Game_UpdateTexture(GfxResourceID* texId, struct Stream* src, const cc_st
cc_bool Game_ValidateBitmap(const cc_string* file, struct Bitmap* bmp) {
int maxWidth = Gfx.MaxTexWidth, maxHeight = Gfx.MaxTexHeight;
float texSize, maxSize;
if (!bmp->scan0) {
Chat_Add1("&cError loading %s from the texture pack.", file);
return false;
@ -240,7 +242,17 @@ cc_bool Game_ValidateBitmap(const cc_string* file, struct Bitmap* bmp) {
Chat_Add1("&cUnable to use %s from the texture pack.", file);
Chat_Add4("&c Its size is (%i,%i), your GPU supports (%i,%i) at most.",
&bmp->width, &bmp->height, &maxWidth, &maxHeight);
&bmp->width, &bmp->height, &maxWidth, &maxHeight);
return false;
}
if (Gfx.MaxTexSize && (bmp->width * bmp->height > Gfx.MaxTexSize)) {
Chat_Add1("&cUnable to use %s from the texture pack.", file);
texSize = (bmp->width * bmp->height) / (1024.0f * 1024.0f);
maxSize = Gfx.MaxTexSize / (1024.0f * 1024.0f);
Chat_Add2("&c Its size is %f3 MB, your GPU supports %f3 MB at most.",
&texSize, &maxSize);
return false;
}

View File

@ -53,6 +53,9 @@ CC_VAR extern struct _GfxData {
/* Whether graphics context has been created */
cc_bool Created;
struct Matrix View, Projection;
/* Maximum size in pixels a texture can consist of */
/* NOTE: Not all graphics backends specify a value for this */
int MaxTexSize;
} Gfx;
extern GfxResourceID Gfx_defaultIb;
@ -69,10 +72,10 @@ extern const cc_string Gfx_LowPerfMessage;
#define LOWPERF_EXIT_MESSAGE "&eExited reduced performance mode"
void Gfx_RecreateDynamicVb(GfxResourceID* vb, VertexFormat fmt, int maxVertices);
void Gfx_RecreateTexture(GfxResourceID* tex, struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps);
void Gfx_RecreateTexture(GfxResourceID* tex, struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps);
void* Gfx_RecreateAndLockVb(GfxResourceID* vb, VertexFormat fmt, int count);
cc_bool Gfx_CheckTextureSize(int width, int height);
/* Creates a new texture. (and also generates mipmaps if mipmaps) */
/* Supported flags: TEXTURE_FLAG_MANAGED, TEXTURE_FLAG_DYNAMIC */
/* NOTE: Only set mipmaps to true if Gfx_Mipmaps is also true, because whether textures
@ -87,6 +90,7 @@ void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, i
CC_API void Gfx_BindTexture(GfxResourceID texId);
/* Deletes the given texture, then sets it to 0 */
CC_API void Gfx_DeleteTexture(GfxResourceID* texId);
/* NOTE: Completely useless now, and does nothing in all graphics backends */
/* (used to set whether texture colour is used when rendering vertices) */
CC_API void Gfx_SetTexturing(cc_bool enabled);

View File

@ -339,7 +339,7 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
void Gfx_GetApiInfo(cc_string* info) {
String_Format1(info, "-- Using 3DS --\n", NULL);
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
PrintMaxTextureInfo(info);
}
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {

View File

@ -1160,7 +1160,7 @@ void Gfx_GetApiInfo(cc_string* info) {
String_Format1(info, "Adapter: %c\n", adapter);
String_Format2(info, "Graphics memory: %f2 MB total (%f2 MB VRAM)\n", &tram_, &vram_);
String_Format2(info, "Max texture size: (%i x %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
PrintMaxTextureInfo(info);
release_adapter:
IDXGIAdapter_Release(dxgi_adapter);

View File

@ -880,7 +880,7 @@ void Gfx_GetApiInfo(cc_string* info) {
String_Format1(info, "Adapter: %c\n", adapter.Description);
String_Format1(info, "Processing mode: %c\n", D3D9_StrFlags());
String_Format2(info, "Video memory: %f2 MB total, %f2 free\n", &totalMem, &curMem);
String_Format2(info, "Max texture size: (%i x %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
PrintMaxTextureInfo(info);
String_Format1(info, "Depth buffer bits: %i", &depthBits);
}

View File

@ -520,7 +520,7 @@ void Gfx_GetApiInfo(cc_string* info) {
String_AppendConst(info, "GPU: PowerVR2 CLX2 100mHz\n");
String_AppendConst(info, "T&L: GLdc library (KallistiOS / Kazade)\n");
String_Format2(info, "Texture memory: %f2 MB used, %f2 MB free\n", &usedMemMB, &freeMemMB);
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
PrintMaxTextureInfo(info);
}
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {

View File

@ -240,8 +240,8 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
}
void Gfx_GetApiInfo(cc_string* info) {
String_Format1(info, "-- Using GC/WII --", NULL);
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
String_AppendConst(info, "-- Using GC/Wii --\n");
PrintMaxTextureInfo(info);
}
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {

View File

@ -62,7 +62,7 @@ void Gfx_GetApiInfo(cc_string* info) {
String_AppendConst(info, "-- Using Nintendo 64 --\n");
String_AppendConst(info, "GPU: Nintendo 64 RDP (LibDragon OpenGL)\n");
String_AppendConst(info, "T&L: Nintendo 64 RSP (LibDragon OpenGL)\n");
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
PrintMaxTextureInfo(info);
}
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
@ -121,8 +121,6 @@ typedef struct CCTexture {
} CCTexture;
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
if (bmp->width > 32 || bmp->height > 32) return NULL;
CCTexture* tex = Mem_Alloc(1, sizeof(CCTexture), "texture");
glGenTextures(1, &tex->textureID);

View File

@ -617,9 +617,8 @@ void Gfx_OnWindowResize(void) {
}
void Gfx_GetApiInfo(cc_string* info) {
int pointerSize = sizeof(void*) * 8;
String_Format1(info, "-- Using PS2 (%i bit) --\n", &pointerSize);
String_Format2(info, "Max texture size: (%i x %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
String_AppendConst(info, "-- Using PS2 --\n");
PrintMaxTextureInfo(info);
}
cc_bool Gfx_TryRestoreContext(void) { return true; }

View File

@ -384,7 +384,7 @@ void Gfx_GetApiInfo(cc_string* info) {
int pointerSize = sizeof(void*) * 8;
String_Format1(info, "-- Using PS3 (%i bit) --\n", &pointerSize);
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
PrintMaxTextureInfo(info);
}
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {

View File

@ -239,8 +239,8 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
}
void Gfx_GetApiInfo(cc_string* info) {
String_Format1(info, "-- Using PSP--\n", NULL);
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
String_AppendConst(info, "-- Using PSP--\n");
PrintMaxTextureInfo(info);
}
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {

View File

@ -750,10 +750,8 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
}
void Gfx_GetApiInfo(cc_string* info) {
int pointerSize = sizeof(void*) * 8;
String_Format1(info, "-- Using PS VITA (%i bit) --\n", &pointerSize);
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
String_AppendConst(info, "-- Using PS Vita --\n");
PrintMaxTextureInfo(info);
}
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {

View File

@ -481,7 +481,7 @@ void Gfx_OnWindowResize(void) {
void Gfx_GetApiInfo(cc_string* info) {
int pointerSize = sizeof(void*) * 8;
String_Format1(info, "-- Using software (%i bit) --\n", &pointerSize);
String_Format2(info, "Max texture size: (%i x %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
PrintMaxTextureInfo(info);
}
cc_bool Gfx_TryRestoreContext(void) { return true; }

View File

@ -345,7 +345,8 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
}
void Gfx_GetApiInfo(cc_string* info) {
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
String_AppendConst(info, "-- Using XBox --\n");
PrintMaxTextureInfo(info);
}
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {

View File

@ -357,10 +357,8 @@ void Gfx_EndFrame(void) {
cc_bool Gfx_WarnIfNecessary(void) { return false; }
void Gfx_GetApiInfo(cc_string* info) {
int pointerSize = sizeof(void*) * 8;
String_Format1(info, "-- Using XBox 360 (%i bit) --\n", &pointerSize);
String_Format2(info, "Max texture size: (%i x %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
String_AppendConst(info, "-- Using XBox 360 --\n");
PrintMaxTextureInfo(info);
}
void Gfx_OnWindowResize(void) {

View File

@ -435,7 +435,8 @@ void Screen_Render2Widgets(void* screen, double delta) {
void Screen_UpdateVb(void* screen) {
struct Screen* s = (struct Screen*)screen;
Gfx_RecreateDynamicVb(&s->vb, VERTEX_FORMAT_TEXTURED, s->maxVertices);
Gfx_DeleteDynamicVb(&s->vb);
s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, s->maxVertices);
}
struct VertexTextured* Screen_LockVb(void* screen) {

View File

@ -63,8 +63,16 @@ static void Atlas_Convert2DTo1D(void) {
static void Atlas_Update1D(void) {
int maxAtlasHeight, maxTilesPerAtlas, maxTiles;
int maxTexHeight = Gfx.MaxTexHeight;
maxAtlasHeight = min(4096, Gfx.MaxTexHeight);
/* E.g. a graphics backend may support textures up to 256 x 256 */
/* dimension wise, but only have enough storage for 16 x 256 */
if (Gfx.MaxTexSize) {
int maxCurHeight = Gfx.MaxTexSize / Atlas2D.TileSize;
maxTexHeight = min(maxTexHeight, maxCurHeight);
}
maxAtlasHeight = min(4096, maxTexHeight);
maxTilesPerAtlas = maxAtlasHeight / Atlas2D.TileSize;
maxTiles = Atlas2D.RowsCount * ATLAS2D_TILES_PER_ROW;
@ -145,7 +153,7 @@ cc_bool Atlas_TryChange(struct Bitmap* atlas) {
return false;
}
if (tileSize > Gfx.MaxTexWidth) {
if (!Gfx_CheckTextureSize(tileSize, tileSize)) {
Chat_AddRaw("&cUnable to use terrain.png from the texture pack.");
Chat_Add4("&c Tile size is (%i,%i), your GPU supports (%i,%i) at most.",
&tileSize, &tileSize, &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);

View File

@ -285,7 +285,7 @@ void Gfx_GetApiInfo(cc_string* info) {
String_Format1(info, "Renderer: %c\n", glGetString(GL_RENDERER));
String_Format1(info, "GL version: %c\n", glGetString(GL_VERSION));
AppendVRAMStats(info);
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
PrintMaxTextureInfo(info);
String_Format1(info, "Depth buffer bits: %i\n", &depthBits);
GLContext_GetApiInfo(info);
}

View File

@ -51,11 +51,16 @@ static void MakeIndices(cc_uint16* indices, int count, void* obj) {
}
}
static void RecreateDynamicVb(GfxResourceID* vb, VertexFormat fmt, int maxVertices) {
Gfx_DeleteDynamicVb(vb);
*vb = Gfx_CreateDynamicVb(fmt, maxVertices);
}
static void InitDefaultResources(void) {
Gfx_defaultIb = Gfx_CreateIb2(GFX_MAX_INDICES, MakeIndices, NULL);
Gfx_RecreateDynamicVb(&Gfx_quadVb, VERTEX_FORMAT_COLOURED, 4);
Gfx_RecreateDynamicVb(&Gfx_texVb, VERTEX_FORMAT_TEXTURED, 4);
RecreateDynamicVb(&Gfx_quadVb, VERTEX_FORMAT_COLOURED, 4);
RecreateDynamicVb(&Gfx_texVb, VERTEX_FORMAT_TEXTURED, 4);
}
static void FreeDefaultResources(void) {
@ -129,11 +134,6 @@ static void EndReducedPerformance(void) {
}
void Gfx_RecreateDynamicVb(GfxResourceID* vb, VertexFormat fmt, int maxVertices) {
Gfx_DeleteDynamicVb(vb);
*vb = Gfx_CreateDynamicVb(fmt, maxVertices);
}
void Gfx_RecreateTexture(GfxResourceID* tex, struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
Gfx_DeleteTexture(tex);
*tex = Gfx_CreateTexture(bmp, flags, mipmaps);
@ -252,6 +252,17 @@ static CC_INLINE float Reversed_CalcZNear(float fov, int depthbufferBits) {
return 0.00390625f;
}
static void PrintMaxTextureInfo(cc_string* info) {
if (Gfx.MaxTexSize) {
float maxSize = Gfx.MaxTexSize / (1024.0f * 1024.0f);
String_Format3(info, "Max texture size: (%i, %i), up to %f3 MB\n",
&Gfx.MaxTexWidth, &Gfx.MaxTexHeight, &maxSize);
} else {
String_Format2(info, "Max texture size: (%i, %i)\n",
&Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
}
}
/*########################################################################################################################*
*---------------------------------------------------------Textures--------------------------------------------------------*
@ -339,6 +350,15 @@ static CC_NOINLINE int CalcMipmapsLevels(int width, int height) {
}
}
cc_bool Gfx_CheckTextureSize(int width, int height) {
if (width > Gfx.MaxTexWidth) return false;
if (height > Gfx.MaxTexHeight) return false;
if (Gfx.MaxTexSize && (width * height > Gfx.MaxTexSize))
return false;
return true;
}
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps);
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
@ -346,6 +366,7 @@ GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipm
Logger_Abort("Textures must have power of two dimensions");
}
if (Gfx.LostContext) return 0;
if (!Gfx_CheckTextureSize(bmp->width, bmp->height)) return 0;
return Gfx_AllocTexture(bmp, flags, mipmaps);
}