mirror of
https://github.com/encounter/aurora.git
synced 2025-07-13 00:25:55 +00:00
Support making simple display lists on the fly and more data formats (#5)
* Support making simple display lists on the fly and more data formats * Add a macro for GXCallDisplayListLE * Resolve conversations
This commit is contained in:
parent
c4d91f18a1
commit
23522538e1
@ -7,8 +7,15 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef AURORA
|
||||
#define GXCallDisplayListNative GXCallDisplayListLE
|
||||
#else
|
||||
#define GXCallDisplayListNative GXCallDisplayList
|
||||
#endif
|
||||
|
||||
void GXBeginDisplayList(void* list, u32 size);
|
||||
u32 GXEndDisplayList(void);
|
||||
void GXCallDisplayListLE(const void* list, u32 nbytes);
|
||||
void GXCallDisplayList(const void* list, u32 nbytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -2,17 +2,28 @@
|
||||
|
||||
#include "../../gfx/model/shader.hpp"
|
||||
|
||||
#define ROUNDUP32(x) (((x) + 31) & ~31)
|
||||
|
||||
extern "C" {
|
||||
void GXBeginDisplayList(void* list, u32 size) {
|
||||
// TODO
|
||||
CHECK(!g_gxState.dynamicDlBuf, "Display list began twice!");
|
||||
g_gxState.dynamicDlBuf.emplace(static_cast<u8*>(list), size);
|
||||
}
|
||||
|
||||
u32 GXEndDisplayList() {
|
||||
// TODO
|
||||
return 0;
|
||||
auto &dlBuf = g_gxState.dynamicDlBuf;
|
||||
size_t size = dlBuf->size();
|
||||
size_t paddedSize = ROUNDUP32(size);
|
||||
dlBuf->append_zeroes(paddedSize - size);
|
||||
dlBuf.reset();
|
||||
return paddedSize;
|
||||
}
|
||||
|
||||
void GXCallDisplayListLE(const void* data, u32 nbytes) {
|
||||
aurora::gfx::model::queue_surface(static_cast<const u8*>(data), nbytes, false);
|
||||
}
|
||||
|
||||
void GXCallDisplayList(const void* data, u32 nbytes) {
|
||||
aurora::gfx::model::queue_surface(static_cast<const u8*>(data), nbytes);
|
||||
aurora::gfx::model::queue_surface(static_cast<const u8*>(data), nbytes, true);
|
||||
}
|
||||
}
|
||||
}
|
@ -117,6 +117,12 @@ static u16 lastVertexStart = 0;
|
||||
|
||||
extern "C" {
|
||||
void GXBegin(GXPrimitive primitive, GXVtxFmt vtxFmt, u16 nVerts) {
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
const u8 fmtAndPrimitive = vtxFmt | primitive;
|
||||
dlBuf->append(fmtAndPrimitive);
|
||||
dlBuf->append(nVerts);
|
||||
return;
|
||||
}
|
||||
CHECK(!sStreamState, "Stream began twice!");
|
||||
|
||||
uint16_t vertexSize = 0;
|
||||
@ -180,267 +186,508 @@ void GXBegin(GXPrimitive primitive, GXVtxFmt vtxFmt, u16 nVerts) {
|
||||
}
|
||||
|
||||
void GXPosition3f32(f32 x, f32 y, f32 z) {
|
||||
sStreamState->check_direct(GX_VA_POS, GX_POS_XYZ, GX_F32);
|
||||
sStreamState->append(aurora::Vec3{x, y, z});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(aurora::Vec3{x, y, z});
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_direct(GX_VA_POS, GX_POS_XYZ, GX_F32);
|
||||
stream->append(aurora::Vec3{x, y, z});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXPosition3u16(u16 x, u16 y, u16 z) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XYZ, GX_U16);
|
||||
sStreamState->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(x);
|
||||
dlBuf->append(y);
|
||||
dlBuf->append(z);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_POS, GX_POS_XYZ, GX_U16);
|
||||
stream->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXPosition3s16(s16 x, s16 y, s16 z) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XYZ, GX_S16);
|
||||
sStreamState->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(x);
|
||||
dlBuf->append(y);
|
||||
dlBuf->append(z);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_POS, GX_POS_XYZ, GX_S16);
|
||||
stream->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXPosition3u8(u8 x, u8 y, u8 z) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XYZ, GX_U8);
|
||||
sStreamState->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(x);
|
||||
dlBuf->append(y);
|
||||
dlBuf->append(z);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_POS, GX_POS_XYZ, GX_U8);
|
||||
stream->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXPosition3s8(s8 x, s8 y, s8 z) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XYZ, GX_S8);
|
||||
sStreamState->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(x);
|
||||
dlBuf->append(y);
|
||||
dlBuf->append(z);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_POS, GX_POS_XYZ, GX_S8);
|
||||
stream->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXPosition2f32(f32 x, f32 y) {
|
||||
sStreamState->check_direct(GX_VA_POS, GX_POS_XY, GX_F32);
|
||||
sStreamState->append(aurora::Vec3{x, y, 0.f});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(aurora::Vec2{x, y});
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_direct(GX_VA_POS, GX_POS_XY, GX_F32);
|
||||
stream->append(aurora::Vec3{x, y, 0.f});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXPosition2u16(u16 x, u16 y) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XY, GX_U16);
|
||||
sStreamState->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(x);
|
||||
dlBuf->append(y);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_POS, GX_POS_XY, GX_U16);
|
||||
stream->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXPosition2s16(s16 x, s16 y) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XY, GX_S16);
|
||||
sStreamState->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(x);
|
||||
dlBuf->append(y);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_POS, GX_POS_XY, GX_S16);
|
||||
stream->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXPosition2u8(u8 x, u8 y) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XY, GX_U8);
|
||||
sStreamState->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(x);
|
||||
dlBuf->append(y);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_POS, GX_POS_XY, GX_U8);
|
||||
stream->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXPosition2s8(s8 x, s8 y) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XY, GX_S8);
|
||||
sStreamState->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(x);
|
||||
dlBuf->append(y);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_POS, GX_POS_XY, GX_S8);
|
||||
stream->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXPosition1x16(u16 idx) {
|
||||
sStreamState->check_indexed(GX_VA_POS, GX_INDEX16);
|
||||
sStreamState->append<u16>(idx);
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(idx);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_indexed(GX_VA_POS, GX_INDEX16);
|
||||
stream->append<u16>(idx);
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXPosition1x8(u8 idx) {
|
||||
sStreamState->check_indexed(GX_VA_POS, GX_INDEX8);
|
||||
sStreamState->append<u16>(idx);
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(idx);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_indexed(GX_VA_POS, GX_INDEX8);
|
||||
stream->append<u16>(idx);
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXNormal3f32(f32 x, f32 y, f32 z) {
|
||||
sStreamState->check_direct(GX_VA_NRM, GX_NRM_XYZ, GX_F32);
|
||||
sStreamState->append(aurora::Vec3{x, y, z});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(aurora::Vec3{x, y, z});
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_direct(GX_VA_NRM, GX_NRM_XYZ, GX_F32);
|
||||
stream->append(aurora::Vec3{x, y, z});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXNormal3s16(s16 x, s16 y, s16 z) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_NRM, GX_NRM_XYZ, GX_S16);
|
||||
sStreamState->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(x);
|
||||
dlBuf->append(y);
|
||||
dlBuf->append(z);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_NRM, GX_NRM_XYZ, GX_S16);
|
||||
stream->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXNormal3s8(s8 x, s8 y, s8 z) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_NRM, GX_NRM_XYZ, GX_S8);
|
||||
sStreamState->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(x);
|
||||
dlBuf->append(y);
|
||||
dlBuf->append(z);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_NRM, GX_NRM_XYZ, GX_S8);
|
||||
stream->append(aurora::Vec3{
|
||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXNormal1x16(u16 index) {
|
||||
sStreamState->check_indexed(GX_VA_NRM, GX_INDEX16);
|
||||
sStreamState->append<u16>(index);
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(index);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_indexed(GX_VA_NRM, GX_INDEX16);
|
||||
stream->append<u16>(index);
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXNormal1x8(u8 index) {
|
||||
sStreamState->check_indexed(GX_VA_POS, GX_INDEX8);
|
||||
sStreamState->append<u16>(index);
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(index);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_indexed(GX_VA_POS, GX_INDEX8);
|
||||
stream->append<u16>(index);
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXColor4f32(f32 r, f32 g, f32 b, f32 a) {
|
||||
sStreamState->check_direct(GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8);
|
||||
sStreamState->append(aurora::Vec4{r, g, b, a});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(aurora::Vec4{r, g, b, a});
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_direct(GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8);
|
||||
stream->append(aurora::Vec4{r, g, b, a});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXColor4u8(u8 r, u8 g, u8 b, u8 a) {
|
||||
sStreamState->check_direct(GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8);
|
||||
sStreamState->append(aurora::Vec4{
|
||||
static_cast<f32>(r) / 255.f,
|
||||
static_cast<f32>(g) / 255.f,
|
||||
static_cast<f32>(b) / 255.f,
|
||||
static_cast<f32>(a) / 255.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(r);
|
||||
dlBuf->append(g);
|
||||
dlBuf->append(b);
|
||||
dlBuf->append(a);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_direct(GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8);
|
||||
stream->append(aurora::Vec4{
|
||||
static_cast<f32>(r) / 255.f,
|
||||
static_cast<f32>(g) / 255.f,
|
||||
static_cast<f32>(b) / 255.f,
|
||||
static_cast<f32>(a) / 255.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXColor3u8(u8 r, u8 g, u8 b) {
|
||||
sStreamState->check_direct(GX_VA_CLR0, GX_CLR_RGB, GX_RGB8);
|
||||
sStreamState->append(aurora::Vec4{
|
||||
static_cast<f32>(r) / 255.f,
|
||||
static_cast<f32>(g) / 255.f,
|
||||
static_cast<f32>(b) / 255.f,
|
||||
1.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(r);
|
||||
dlBuf->append(g);
|
||||
dlBuf->append(b);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_direct(GX_VA_CLR0, GX_CLR_RGB, GX_RGB8);
|
||||
stream->append(aurora::Vec4{
|
||||
static_cast<f32>(r) / 255.f,
|
||||
static_cast<f32>(g) / 255.f,
|
||||
static_cast<f32>(b) / 255.f,
|
||||
1.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXColor1u32(u32 clr) {
|
||||
sStreamState->check_direct(GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8);
|
||||
sStreamState->append(aurora::Vec4{
|
||||
static_cast<f32>((clr >> 24) & 0xff) / 255.f,
|
||||
static_cast<f32>((clr >> 16) & 0xff) / 255.f,
|
||||
static_cast<f32>((clr >> 8) & 0xff) / 255.f,
|
||||
static_cast<f32>(clr & 0xff) / 255.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(clr);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_direct(GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8);
|
||||
stream->append(aurora::Vec4{
|
||||
static_cast<f32>((clr >> 24) & 0xff) / 255.f,
|
||||
static_cast<f32>((clr >> 16) & 0xff) / 255.f,
|
||||
static_cast<f32>((clr >> 8) & 0xff) / 255.f,
|
||||
static_cast<f32>(clr & 0xff) / 255.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXColor1u16(u16 clr) {
|
||||
sStreamState->check_direct(GX_VA_CLR0, GX_CLR_RGB, GX_RGB565);
|
||||
sStreamState->append(aurora::Vec4{
|
||||
static_cast<f32>((clr >> 11) & 0x1f) / 31.f,
|
||||
static_cast<f32>((clr >> 5) & 0x3f) / 63.f,
|
||||
static_cast<f32>(clr & 0x1f) / 31.f,
|
||||
1.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(clr);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_direct(GX_VA_CLR0, GX_CLR_RGB, GX_RGB565);
|
||||
stream->append(aurora::Vec4{
|
||||
static_cast<f32>((clr >> 11) & 0x1f) / 31.f,
|
||||
static_cast<f32>((clr >> 5) & 0x3f) / 63.f,
|
||||
static_cast<f32>(clr & 0x1f) / 31.f,
|
||||
1.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXColor1x16(u16 index) {
|
||||
sStreamState->check_indexed(GX_VA_CLR0, GX_INDEX16);
|
||||
sStreamState->append<u16>(index);
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(index);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_indexed(GX_VA_CLR0, GX_INDEX16);
|
||||
stream->append<u16>(index);
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXColor1x8(u8 index) {
|
||||
sStreamState->check_indexed(GX_VA_CLR0, GX_INDEX8);
|
||||
sStreamState->append<u16>(index);
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(index);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_indexed(GX_VA_CLR0, GX_INDEX8);
|
||||
stream->append<u16>(index);
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord2f32(f32 s, f32 t) {
|
||||
sStreamState->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_F32);
|
||||
sStreamState->append(aurora::Vec2{s, t});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(aurora::Vec2{s, t});
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_F32);
|
||||
stream->append(aurora::Vec2{s, t});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord2u16(u16 s, u16 t) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_U16);
|
||||
sStreamState->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(s);
|
||||
dlBuf->append(t);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_U16);
|
||||
stream->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord2s16(s16 s, s16 t) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_S16);
|
||||
sStreamState->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(s);
|
||||
dlBuf->append(t);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_S16);
|
||||
stream->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord2u8(u8 s, u8 t) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_U8);
|
||||
sStreamState->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(s);
|
||||
dlBuf->append(t);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_U8);
|
||||
stream->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord2s8(s8 s, s8 t) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_S8);
|
||||
sStreamState->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(s);
|
||||
dlBuf->append(t);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_S8);
|
||||
stream->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord1f32(f32 s) {
|
||||
sStreamState->check_direct(GX_VA_TEX0, GX_TEX_S, GX_F32);
|
||||
sStreamState->append(aurora::Vec2{s, 0.f});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(s);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_direct(GX_VA_TEX0, GX_TEX_S, GX_F32);
|
||||
stream->append(aurora::Vec2{s, 0.f});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord1u16(u16 s) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_S, GX_U16);
|
||||
sStreamState->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(s);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_TEX0, GX_TEX_S, GX_U16);
|
||||
stream->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord1s16(s16 s) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_S, GX_S16);
|
||||
sStreamState->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(s);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_TEX0, GX_TEX_S, GX_S16);
|
||||
stream->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord1u8(u8 s) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_S, GX_U8);
|
||||
sStreamState->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(s);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_TEX0, GX_TEX_S, GX_U8);
|
||||
stream->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord1s8(s8 s) {
|
||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_S, GX_S8);
|
||||
sStreamState->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(s);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
const auto frac = stream->check_direct(GX_VA_TEX0, GX_TEX_S, GX_S8);
|
||||
stream->append(aurora::Vec2{
|
||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
||||
0.f,
|
||||
});
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord1x16(u16 index) {
|
||||
sStreamState->check_indexed(GX_VA_TEX0, GX_INDEX16);
|
||||
sStreamState->append(index);
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(index);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_indexed(GX_VA_TEX0, GX_INDEX16);
|
||||
stream->append(index);
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXTexCoord1x8(u8 index) {
|
||||
sStreamState->check_indexed(GX_VA_TEX0, GX_INDEX8);
|
||||
sStreamState->append(static_cast<u16>(index));
|
||||
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||
dlBuf->append(index);
|
||||
} else if (auto& stream = sStreamState) {
|
||||
stream->check_indexed(GX_VA_TEX0, GX_INDEX8);
|
||||
stream->append(static_cast<u16>(index));
|
||||
} else {
|
||||
FATAL("Stream function called with no stream or DL active");
|
||||
}
|
||||
}
|
||||
|
||||
void GXEnd() {
|
||||
|
@ -17,7 +17,7 @@ struct DisplayListCache {
|
||||
|
||||
static absl::flat_hash_map<HashType, DisplayListCache> sCachedDisplayLists;
|
||||
|
||||
static u32 prepare_vtx_buffer(ByteBuffer& buf, GXVtxFmt vtxfmt, const u8* ptr, u16 vtxCount) {
|
||||
static u32 prepare_vtx_buffer(ByteBuffer& buf, GXVtxFmt vtxfmt, const u8* ptr, u16 vtxCount, bool bigEndian) {
|
||||
using gx::g_gxState;
|
||||
struct {
|
||||
u8 count;
|
||||
@ -114,7 +114,8 @@ static u32 prepare_vtx_buffer(ByteBuffer& buf, GXVtxFmt vtxfmt, const u8* ptr, u
|
||||
buf.append(static_cast<u16>(*ptr));
|
||||
++ptr;
|
||||
} else if (g_gxState.vtxDesc[attr] == GX_INDEX16) {
|
||||
buf.append(bswap(*reinterpret_cast<const u16*>(ptr)));
|
||||
const auto value = *reinterpret_cast<const u16*>(ptr);
|
||||
buf.append(bigEndian ? bswap(value) : value);
|
||||
ptr += 2;
|
||||
}
|
||||
if (g_gxState.vtxDesc[attr] != GX_DIRECT) {
|
||||
@ -141,23 +142,24 @@ static u32 prepare_vtx_buffer(ByteBuffer& buf, GXVtxFmt vtxfmt, const u8* ptr, u
|
||||
break;
|
||||
case GX_U16:
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const auto value = bswap(reinterpret_cast<const u16*>(ptr)[i]);
|
||||
out[i] = static_cast<f32>(value) / static_cast<f32>(1 << attrFmt.frac);
|
||||
auto value = reinterpret_cast<const u16*>(ptr)[i];
|
||||
out[i] = static_cast<f32>(bigEndian ? bswap(value) : value) / static_cast<f32>(1 << attrFmt.frac);
|
||||
}
|
||||
buf.append(out.data(), sizeof(f32) * count);
|
||||
ptr += count * sizeof(u16);
|
||||
break;
|
||||
case GX_S16:
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const auto value = bswap(reinterpret_cast<const s16*>(ptr)[i]);
|
||||
out[i] = static_cast<f32>(value) / static_cast<f32>(1 << attrFmt.frac);
|
||||
const auto value = reinterpret_cast<const s16*>(ptr)[i];
|
||||
out[i] = static_cast<f32>(bigEndian ? bswap(value) : value) / static_cast<f32>(1 << attrFmt.frac);
|
||||
}
|
||||
buf.append(out.data(), sizeof(f32) * count);
|
||||
ptr += count * sizeof(s16);
|
||||
break;
|
||||
case GX_F32:
|
||||
for (int i = 0; i < count; ++i) {
|
||||
out[i] = bswap(reinterpret_cast<const f32*>(ptr)[i]);
|
||||
const auto value = reinterpret_cast<const f32*>(ptr)[i];
|
||||
out[i] = bigEndian ? bswap(value) : value;
|
||||
}
|
||||
buf.append(out.data(), sizeof(f32) * count);
|
||||
ptr += count * sizeof(f32);
|
||||
@ -182,7 +184,26 @@ static u32 prepare_vtx_buffer(ByteBuffer& buf, GXVtxFmt vtxfmt, const u8* ptr, u
|
||||
|
||||
static u16 prepare_idx_buffer(ByteBuffer& buf, GXPrimitive prim, u16 vtxStart, u16 vtxCount) {
|
||||
u16 numIndices = 0;
|
||||
if (prim == GX_TRIANGLES) {
|
||||
if (prim == GX_QUADS) {
|
||||
buf.reserve_extra((vtxCount / 4) * 6 * sizeof(u16));
|
||||
|
||||
for (u16 v = 0; v < vtxCount; v += 4) {
|
||||
u16 idx0 = vtxStart + v;
|
||||
u16 idx1 = vtxStart + v + 1;
|
||||
u16 idx2 = vtxStart + v + 2;
|
||||
u16 idx3 = vtxStart + v + 3;
|
||||
|
||||
buf.append(idx0);
|
||||
buf.append(idx1);
|
||||
buf.append(idx2);
|
||||
numIndices += 3;
|
||||
|
||||
buf.append(idx2);
|
||||
buf.append(idx3);
|
||||
buf.append(idx0);
|
||||
numIndices += 3;
|
||||
}
|
||||
} else if (prim == GX_TRIANGLES) {
|
||||
buf.reserve_extra(vtxCount * sizeof(u16));
|
||||
for (u16 v = 0; v < vtxCount; ++v) {
|
||||
const u16 idx = vtxStart + v;
|
||||
@ -222,7 +243,7 @@ static u16 prepare_idx_buffer(ByteBuffer& buf, GXPrimitive prim, u16 vtxStart, u
|
||||
return numIndices;
|
||||
}
|
||||
|
||||
auto process_display_list(const u8* dlStart, u32 dlSize) -> DisplayListResult {
|
||||
auto process_display_list(const u8* dlStart, u32 dlSize, bool bigEndian) -> DisplayListResult {
|
||||
const auto hash = xxh3_hash_s(dlStart, dlSize, 0);
|
||||
Range vertRange, idxRange;
|
||||
u32 numIndices = 0;
|
||||
@ -259,9 +280,11 @@ auto process_display_list(const u8* dlStart, u32 dlSize) -> DisplayListResult {
|
||||
FATAL("Vertex format changed mid-display list: {} -> {}", fmt, newFmt);
|
||||
}
|
||||
fmt = newFmt;
|
||||
u16 vtxCount = bswap(*reinterpret_cast<const u16*>(data + pos));
|
||||
u16 vtxCount = *reinterpret_cast<const u16*>(data + pos);
|
||||
if (bigEndian)
|
||||
vtxCount = bswap(vtxCount);
|
||||
pos += 2;
|
||||
pos += vtxCount * prepare_vtx_buffer(vtxBuf, fmt, data + pos, vtxCount);
|
||||
pos += vtxCount * prepare_vtx_buffer(vtxBuf, fmt, data + pos, vtxCount, bigEndian);
|
||||
numIndices += prepare_idx_buffer(idxBuf, prim, vtxStart, vtxCount);
|
||||
vtxStart += vtxCount;
|
||||
break;
|
||||
|
@ -10,5 +10,5 @@ struct DisplayListResult {
|
||||
GXVtxFmt fmt;
|
||||
};
|
||||
|
||||
auto process_display_list(const u8* dlStart, u32 dlSize) -> DisplayListResult;
|
||||
auto process_display_list(const u8* dlStart, u32 dlSize, bool bigEndian) -> DisplayListResult;
|
||||
}; // namespace aurora::gfx::gx
|
||||
|
@ -294,6 +294,7 @@ struct GXState {
|
||||
ClipRect texCopySrc;
|
||||
GXTexFmt texCopyFmt;
|
||||
absl::flat_hash_map<void*, TextureHandle> copyTextures;
|
||||
std::optional<ByteBuffer> dynamicDlBuf;
|
||||
bool depthCompare = true;
|
||||
bool depthUpdate = true;
|
||||
bool colorUpdate = true;
|
||||
|
@ -38,6 +38,20 @@ static inline std::string_view chan_comp(GXTevColorChan chan) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
u8 color_channel(GXChannelID id) {
|
||||
switch (id) {
|
||||
DEFAULT_FATAL("unimplemented color channel {}", id);
|
||||
case GX_COLOR0:
|
||||
case GX_ALPHA0:
|
||||
case GX_COLOR0A0:
|
||||
return 0;
|
||||
case GX_COLOR1:
|
||||
case GX_ALPHA1:
|
||||
case GX_COLOR1A1:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static std::string color_arg_reg(GXTevColorArg arg, size_t stageIdx, const ShaderConfig& config,
|
||||
const TevStage& stage) {
|
||||
switch (arg) {
|
||||
@ -77,9 +91,7 @@ static std::string color_arg_reg(GXTevColorArg arg, size_t stageIdx, const Shade
|
||||
if (stage.channelId == GX_COLOR_ZERO) {
|
||||
return "vec3f(0.0)";
|
||||
}
|
||||
CHECK(stage.channelId >= GX_COLOR0A0 && stage.channelId <= GX_COLOR1A1, "invalid color channel {} for stage {}",
|
||||
underlying(stage.channelId), stageIdx);
|
||||
u32 idx = stage.channelId - GX_COLOR0A0;
|
||||
u32 idx = color_channel(stage.channelId);
|
||||
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
|
||||
return fmt::format("rast{}.{}{}{}", idx, chan_comp(swap.red), chan_comp(swap.green), chan_comp(swap.blue));
|
||||
}
|
||||
@ -88,9 +100,7 @@ static std::string color_arg_reg(GXTevColorArg arg, size_t stageIdx, const Shade
|
||||
if (stage.channelId == GX_COLOR_ZERO) {
|
||||
return "vec3f(0.0)";
|
||||
}
|
||||
CHECK(stage.channelId >= GX_COLOR0A0 && stage.channelId <= GX_COLOR1A1, "invalid color channel {} for stage {}",
|
||||
underlying(stage.channelId), stageIdx);
|
||||
u32 idx = stage.channelId - GX_COLOR0A0;
|
||||
u32 idx = color_channel(stage.channelId);
|
||||
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
|
||||
return fmt::format("vec3f(rast{}.{})", idx, chan_comp(swap.alpha));
|
||||
}
|
||||
@ -188,9 +198,7 @@ static std::string alpha_arg_reg(GXTevAlphaArg arg, size_t stageIdx, const Shade
|
||||
if (stage.channelId == GX_COLOR_ZERO) {
|
||||
return "0.0";
|
||||
}
|
||||
CHECK(stage.channelId >= GX_COLOR0A0 && stage.channelId <= GX_COLOR1A1, "invalid color channel {} for stage {}",
|
||||
underlying(stage.channelId), stageIdx);
|
||||
u32 idx = stage.channelId - GX_COLOR0A0;
|
||||
u32 idx = color_channel(stage.channelId);
|
||||
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
|
||||
return fmt::format("rast{}.{}", idx, chan_comp(swap.alpha));
|
||||
}
|
||||
@ -319,6 +327,9 @@ static inline std::string vtx_attr(const ShaderConfig& config, GXAttr attr) {
|
||||
// Default normal
|
||||
return "vec3f(1.0, 0.0, 0.0)"s;
|
||||
}
|
||||
if (attr == GX_VA_CLR0 || attr == GX_VA_CLR1) {
|
||||
return "vec4f(0.0, 0.0, 0.0, 0.0)"s;
|
||||
}
|
||||
UNLIKELY FATAL("unmapped vtx attr {}", underlying(attr));
|
||||
}
|
||||
if (attr == GX_VA_POS) {
|
||||
@ -499,6 +510,16 @@ auto storage_load(const StorageConfig& mapping, u32 attrIdx) -> StorageLoadResul
|
||||
std::string attrLoad;
|
||||
|
||||
switch (compType) {
|
||||
case GX_S8:
|
||||
switch (compCnt) {
|
||||
case 3:
|
||||
arrType = "i32";
|
||||
attrLoad = fmt::format("fetch_i8_3(&v_arr_{}, {}, {})", attrName, idxFetch, mapping.frac);
|
||||
break;
|
||||
default:
|
||||
Log.fatal("storage_load: Unsupported {} count {}", compType, compCnt);
|
||||
}
|
||||
break;
|
||||
case GX_U16:
|
||||
switch (compCnt) {
|
||||
case 2:
|
||||
@ -541,6 +562,10 @@ auto storage_load(const StorageConfig& mapping, u32 attrIdx) -> StorageLoadResul
|
||||
Log.fatal("storage_load: Unsupported {} count {}", compType, compCnt);
|
||||
}
|
||||
break;
|
||||
case GX_RGBA8:
|
||||
arrType = "u32";
|
||||
attrLoad = fmt::format("unpack4x8unorm(v_arr_{}[{}])", attrName, idxFetch);
|
||||
break;
|
||||
default:
|
||||
Log.fatal("storage_load: Unimplemented {}", compType);
|
||||
}
|
||||
@ -1136,6 +1161,22 @@ fn fetch_u8_2(p: ptr<storage, array<u32>>, idx: u32, frac: u32) -> vec2<f32> {{
|
||||
var o1 = select(extractBits(v0, 8, 8), extractBits(v0, 24, 8), r);
|
||||
return vec2<f32>(f32(o0), f32(o1)) / f32(1u << frac);
|
||||
}}
|
||||
fn fetch_i8_3(p: ptr<storage, array<i32>>, idx: u32, frac: u32) -> vec3<f32> {{
|
||||
let byte_idx = idx * 3u;
|
||||
let word0 = p[byte_idx / 4u];
|
||||
let word1 = p[(byte_idx + 1u) / 4u];
|
||||
let word2 = p[(byte_idx + 2u) / 4u];
|
||||
|
||||
let shift0 = (byte_idx % 4u) * 8u;
|
||||
let shift1 = ((byte_idx + 1u) % 4u) * 8u;
|
||||
let shift2 = ((byte_idx + 2u) % 4u) * 8u;
|
||||
|
||||
let o0 = extractBits(word0, shift0, 8);
|
||||
let o1 = extractBits(word1, shift1, 8);
|
||||
let o2 = extractBits(word2, shift2, 8);
|
||||
|
||||
return vec3<f32>(f32(o0), f32(o1), f32(o2)) / f32(1u << frac);
|
||||
}}
|
||||
fn fetch_u16_2(p: ptr<storage, array<u32>>, idx: u32, frac: u32) -> vec2<f32> {{
|
||||
var v0 = p[idx];
|
||||
var o0 = extractBits(v0, 0, 16);
|
||||
|
@ -10,8 +10,8 @@
|
||||
namespace aurora::gfx::model {
|
||||
static Module Log("aurora::gfx::model");
|
||||
|
||||
void queue_surface(const u8* dlStart, u32 dlSize) noexcept {
|
||||
const auto result = aurora::gfx::gx::process_display_list(dlStart, dlSize);
|
||||
void queue_surface(const u8* dlStart, u32 dlSize, bool bigEndian) noexcept {
|
||||
const auto result = aurora::gfx::gx::process_display_list(dlStart, dlSize, bigEndian);
|
||||
|
||||
gx::BindGroupRanges ranges{};
|
||||
for (int i = 0; i < GX_VA_MAX_ATTR; ++i) {
|
||||
|
@ -23,5 +23,5 @@ State construct_state();
|
||||
wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] const PipelineConfig& config);
|
||||
void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass);
|
||||
|
||||
void queue_surface(const u8* dlStart, u32 dlSize) noexcept;
|
||||
void queue_surface(const u8* dlStart, u32 dlSize, bool bigEndian) noexcept;
|
||||
} // namespace aurora::gfx::model
|
||||
|
@ -39,9 +39,7 @@ void color_arg_reg_info(GXTevColorArg arg, const TevStage& stage, ShaderInfo& in
|
||||
break;
|
||||
case GX_CC_RASC:
|
||||
case GX_CC_RASA:
|
||||
if (stage.channelId >= GX_COLOR0A0 && stage.channelId <= GX_COLOR1A1) {
|
||||
info.sampledColorChannels.set(stage.channelId - GX_COLOR0A0);
|
||||
}
|
||||
info.sampledColorChannels.set(color_channel(stage.channelId));
|
||||
break;
|
||||
case GX_CC_KONST:
|
||||
switch (stage.kcSel) {
|
||||
@ -111,9 +109,7 @@ void alpha_arg_reg_info(GXTevAlphaArg arg, const TevStage& stage, ShaderInfo& in
|
||||
info.sampledTextures.set(stage.texMapId);
|
||||
break;
|
||||
case GX_CA_RASA:
|
||||
if (stage.channelId >= GX_COLOR0A0 && stage.channelId <= GX_COLOR1A1) {
|
||||
info.sampledColorChannels.set(stage.channelId - GX_COLOR0A0);
|
||||
}
|
||||
info.sampledColorChannels.set(color_channel(stage.channelId));
|
||||
break;
|
||||
case GX_CA_KONST:
|
||||
switch (stage.kaSel) {
|
||||
|
@ -5,4 +5,5 @@
|
||||
namespace aurora::gfx::gx {
|
||||
ShaderInfo build_shader_info(const ShaderConfig& config) noexcept;
|
||||
Range build_uniform(const ShaderInfo& info) noexcept;
|
||||
u8 color_channel(GXChannelID id) noexcept;
|
||||
}; // namespace aurora::gfx::gx
|
||||
|
Loading…
x
Reference in New Issue
Block a user