2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-21 16:59:12 +00:00

aurora: Rework texture binding API

- Texture binding is now handled by GX calls
- More CCubeMaterial / CCubeRenderer impl
- Semi-working thermal visor rendering
- More CGraphicsPalette impl
- Some CWorldShadow impl
- Start work on indirect texturing
- Stub out CTextRenderBuffer
This commit is contained in:
2022-05-13 19:40:19 -04:00
parent 22256228fb
commit 22dfd3b3f7
45 changed files with 1511 additions and 868 deletions

View File

@@ -5,74 +5,6 @@
#include <zeus/Math.hpp>
#include <magic_enum.hpp>
u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, bool mipmap, u8 max_lod) {
s32 shiftX = 0;
s32 shiftY = 0;
switch (format) {
case GX::TF_I4:
case GX::TF_C4:
case GX::TF_CMPR:
case GX::CTF_R4:
case GX::CTF_Z4:
shiftX = 3;
shiftY = 3;
break;
case GX::TF_I8:
case GX::TF_IA4:
case GX::TF_C8:
case GX::TF_Z8:
case GX::CTF_RA4:
case GX::CTF_A8:
case GX::CTF_R8:
case GX::CTF_G8:
case GX::CTF_B8:
case GX::CTF_Z8M:
case GX::CTF_Z8L:
shiftX = 3;
shiftY = 2;
break;
case GX::TF_IA8:
case GX::TF_RGB565:
case GX::TF_RGB5A3:
case GX::TF_RGBA8:
case GX::TF_C14X2:
case GX::TF_Z16:
case GX::TF_Z24X8:
case GX::CTF_RA8:
case GX::CTF_RG8:
case GX::CTF_GB8:
case GX::CTF_Z16L:
shiftX = 2;
shiftY = 2;
break;
default:
break;
}
u32 bitSize = format == GX::TF_RGBA8 || format == GX::TF_Z24X8 ? 64 : 32;
u32 bufLen = 0;
if (mipmap) {
while (max_lod != 0) {
const u32 tileX = ((width + (1 << shiftX) - 1) >> shiftX);
const u32 tileY = ((height + (1 << shiftY) - 1) >> shiftY);
bufLen += bitSize * tileX * tileY;
if (width == 1 && height == 1) {
return bufLen;
}
width = (width < 2) ? 1 : width / 2;
height = (height < 2) ? 1 : height / 2;
--max_lod;
};
} else {
const u32 tileX = ((width + (1 << shiftX) - 1) >> shiftX);
const u32 tileY = ((height + (1 << shiftY) - 1) >> shiftY);
bufLen = bitSize * tileX * tileY;
}
return bufLen;
}
namespace metaforce {
static std::array<CTexture*, GX::MAX_TEXMAP> sLoadedTextures{};
@@ -85,7 +17,7 @@ CTexture::CTexture(ETexelFormat fmt, u16 w, u16 h, s32 mips, std::string_view la
, x64_frameAllocated(sCurrentFrameCount)
, m_label(fmt::format(FMT_STRING("{} ({})"), label, magic_enum::enum_name(fmt))) {
InitBitmapBuffers(fmt, w, h, mips);
InitTextureObjs(false);
InitTextureObjs();
}
CTexture::CTexture(CInputStream& in, std::string_view label, EAutoMipmap automip, EBlackKey blackKey)
@@ -129,7 +61,7 @@ CTexture::CTexture(CInputStream& in, std::string_view label, EAutoMipmap automip
}
}
InitTextureObjs(true);
InitTextureObjs();
}
u8* CTexture::Lock() {
@@ -141,11 +73,14 @@ void CTexture::UnLock() {
xa_24_locked = false;
CountMemory();
// DCFlushRange(x44_aramToken.GetMRAMSafe(), ROUND_UP_32(xc_memoryAllocated));
// Aurora change: track when texture data needs to be invalidated
m_needsTexObjDataLoad = true;
}
void CTexture::Load(GX::TexMapID id, EClampMode clamp) {
if (sLoadedTextures[id] != this || xa_29_canLoadObj) {
// auto* image_ptr = /*x44_aramToken.GetMRAMSafe() */ x44_aramToken_x4_buff.get();
auto* data = /*x44_aramToken.GetMRAMSafe() */ x44_aramToken_x4_buff.get();
CountMemory();
if (HasPalette()) {
x10_graphicsPalette->Load();
@@ -154,12 +89,16 @@ void CTexture::Load(GX::TexMapID id, EClampMode clamp) {
xa_29_canLoadObj = false;
if (x40_clampMode != clamp) {
x40_clampMode = !xa_26_isPowerOfTwo ? EClampMode::Clamp : clamp;
// GXInitTexObjWrapMode(x20_texObj, static_cast<u32>(x40_clampMode), static_cast<u32>(x40_clampMode));
GXInitTexObjWrapMode(&x20_texObj, static_cast<GXTexWrapMode>(x40_clampMode),
static_cast<GXTexWrapMode>(x40_clampMode));
}
// GXInitObjectData(x20_texObj, image_ptr);
// GXLoadObj(x20_texObj, id);
aurora::gfx::bind_texture(id, clamp, x20_texObj, 0.f);
// Aurora change: track when texture data needs to be invalidated
if (m_needsTexObjDataLoad) {
GXInitTexObjData(&x20_texObj, data);
m_needsTexObjDataLoad = false;
}
GXLoadTexObj(&x20_texObj, id);
sLoadedTextures[id] = this;
x64_frameAllocated = sCurrentFrameCount;
}
@@ -179,15 +118,15 @@ void CTexture::LoadMipLevel(float lod, GX::TexMapID id, EClampMode clamp) {
// }
// }
// TODO
// GXTexObj texObj;
// GXInitTexObj(&texObj, image_ptr + offset, width, height, x18_gxFormat);
// GXInitTexObjLod(&texObj, GX_LINEAR, GX_LINEAR, 0.f, 1.f, 0.f, false, false, GX_ANISO_1);
if (HasPalette()) {
x10_graphicsPalette->Load();
xa_25_canLoadPalette = false;
}
// GXLoadTexObj(&texObj, mapId);
aurora::gfx::bind_texture(id, clamp, x20_texObj, lod);
// GXInitTexObjLOD(&texObj, GX_LINEAR, GX_LINEAR, 0.f, 1.f, 0.f, false, false, GX_ANISO_1);
// if (HasPalette()) {
// x10_graphicsPalette->Load();
// xa_25_canLoadPalette = false;
// }
// GXLoadTexObj(&x20_texObj, id);
x64_frameAllocated = sCurrentFrameCount;
sLoadedTextures[id] = nullptr;
}
@@ -227,13 +166,13 @@ void CTexture::InitBitmapBuffers(ETexelFormat fmt, u16 width, u16 height, s32 mi
x18_gxFormat = GX::TF_IA8;
break;
case ETexelFormat::C4:
x1c_gxCIFormat = GX::TF_C4;
x1c_gxCIFormat = GX_TF_C4;
break;
case ETexelFormat::C8:
x1c_gxCIFormat = GX::TF_C8;
x1c_gxCIFormat = GX_TF_C8;
break;
case ETexelFormat::C14X2:
x1c_gxCIFormat = GX::TF_C14X2;
x1c_gxCIFormat = GX_TF_C14X2;
break;
case ETexelFormat::RGB565:
x18_gxFormat = GX::TF_RGB565;
@@ -252,16 +191,15 @@ void CTexture::InitBitmapBuffers(ETexelFormat fmt, u16 width, u16 height, s32 mi
}
u32 format = (x0_fmt == ETexelFormat::C4 || x0_fmt == ETexelFormat::C8 || x0_fmt == ETexelFormat::C14X2)
? x1c_gxCIFormat
: x18_gxFormat;
? u32(x1c_gxCIFormat)
: u32(x18_gxFormat);
xc_memoryAllocated = GXGetTexBufferSize(width, height, format, mips > 1, mips > 1 ? 11 : 0);
x44_aramToken_x4_buff = std::make_unique<u8[]>(xc_memoryAllocated);
/*x44_aramToken.PostConstruct(buf, xc_memoryAllocated, 1);*/
CountMemory();
}
void CTexture::InitTextureObjs(bool write) {
void CTexture::InitTextureObjs() {
xa_26_isPowerOfTwo = zeus::floorPowerOfTwo(x4_w) == x4_w && zeus::floorPowerOfTwo(x6_h) == x6_h;
if (!xa_26_isPowerOfTwo) {
@@ -270,19 +208,14 @@ void CTexture::InitTextureObjs(bool write) {
CountMemory();
if (IsCITexture()) {
// GXInitTexObjCI(x20_texObj, x44_aramToken_x4_buff.get(), x4_w, x6_h, x1c_gxCIFormat, u32(x40_clampMode),
// u32(x40_clampMode), x8_mips > 1, 0);
// TODO
GXInitTexObjCI(&x20_texObj, x44_aramToken_x4_buff.get(), x4_w, x6_h, x1c_gxCIFormat,
static_cast<GXTexWrapMode>(x40_clampMode), static_cast<GXTexWrapMode>(x40_clampMode), x8_mips > 1,
0);
} else {
// GXInitTexObj(x20_texObj, x44_aramToken_x4_buff.get(), x4_w, x6_h, x1c_gxCIFormat, u32(x40_clampMode),
// u32(x40_clampMode), x8_mips > 1);
// GXInitTexObjLOD(x20_texObj, x8_mips > 1 ? GX_LIN_MIP_LIN : GX_LINEAR, 0.f, static_cast<float>(x8_mips) - 1.f,
// 0.f,
// false, false, x8_mips > 1 ? GX_ANISO_4 : GX_ANISO_1);
x20_texObj = aurora::gfx::new_dynamic_texture_2d(x4_w, x6_h, x8_mips, x0_fmt, m_label);
if (write) {
aurora::gfx::write_texture(x20_texObj, {x44_aramToken_x4_buff.get(), xc_memoryAllocated});
}
GXInitTexObj(&x20_texObj, x44_aramToken_x4_buff.get(), x4_w, x6_h, x18_gxFormat,
static_cast<GXTexWrapMode>(x40_clampMode), static_cast<GXTexWrapMode>(x40_clampMode), x8_mips > 1);
GXInitTexObjLOD(&x20_texObj, x8_mips > 1 ? GX_LIN_MIP_LIN : GX_LINEAR, GX_LINEAR, 0.f,
static_cast<float>(x8_mips) - 1.f, 0.f, false, false, x8_mips > 1 ? GX_ANISO_4 : GX_ANISO_1);
}
xa_29_canLoadObj = true;
}
@@ -336,7 +269,7 @@ u32 CTexture::sCurrentFrameCount = 0;
u32 CTexture::sTotalAllocatedMemory = 0;
void CTexture::InvalidateTexMap(GX::TexMapID id) {
aurora::gfx::unbind_texture(id);
// TODO: can we unbind in GX?
sLoadedTextures[id] = nullptr;
}