mirror of
https://github.com/encounter/aurora.git
synced 2025-07-13 16:46:07 +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" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef AURORA
|
||||||
|
#define GXCallDisplayListNative GXCallDisplayListLE
|
||||||
|
#else
|
||||||
|
#define GXCallDisplayListNative GXCallDisplayList
|
||||||
|
#endif
|
||||||
|
|
||||||
void GXBeginDisplayList(void* list, u32 size);
|
void GXBeginDisplayList(void* list, u32 size);
|
||||||
u32 GXEndDisplayList(void);
|
u32 GXEndDisplayList(void);
|
||||||
|
void GXCallDisplayListLE(const void* list, u32 nbytes);
|
||||||
void GXCallDisplayList(const void* list, u32 nbytes);
|
void GXCallDisplayList(const void* list, u32 nbytes);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -2,17 +2,28 @@
|
|||||||
|
|
||||||
#include "../../gfx/model/shader.hpp"
|
#include "../../gfx/model/shader.hpp"
|
||||||
|
|
||||||
|
#define ROUNDUP32(x) (((x) + 31) & ~31)
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void GXBeginDisplayList(void* list, u32 size) {
|
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() {
|
u32 GXEndDisplayList() {
|
||||||
// TODO
|
auto &dlBuf = g_gxState.dynamicDlBuf;
|
||||||
return 0;
|
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) {
|
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" {
|
extern "C" {
|
||||||
void GXBegin(GXPrimitive primitive, GXVtxFmt vtxFmt, u16 nVerts) {
|
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!");
|
CHECK(!sStreamState, "Stream began twice!");
|
||||||
|
|
||||||
uint16_t vertexSize = 0;
|
uint16_t vertexSize = 0;
|
||||||
@ -180,267 +186,508 @@ void GXBegin(GXPrimitive primitive, GXVtxFmt vtxFmt, u16 nVerts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GXPosition3f32(f32 x, f32 y, f32 z) {
|
void GXPosition3f32(f32 x, f32 y, f32 z) {
|
||||||
sStreamState->check_direct(GX_VA_POS, GX_POS_XYZ, GX_F32);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{x, y, z});
|
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) {
|
void GXPosition3u16(u16 x, u16 y, u16 z) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XYZ, GX_U16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{
|
dlBuf->append(x);
|
||||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
dlBuf->append(y);
|
||||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
dlBuf->append(z);
|
||||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
} 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) {
|
void GXPosition3s16(s16 x, s16 y, s16 z) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XYZ, GX_S16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{
|
dlBuf->append(x);
|
||||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
dlBuf->append(y);
|
||||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
dlBuf->append(z);
|
||||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
} 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) {
|
void GXPosition3u8(u8 x, u8 y, u8 z) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XYZ, GX_U8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{
|
dlBuf->append(x);
|
||||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
dlBuf->append(y);
|
||||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
dlBuf->append(z);
|
||||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
} 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) {
|
void GXPosition3s8(s8 x, s8 y, s8 z) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XYZ, GX_S8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{
|
dlBuf->append(x);
|
||||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
dlBuf->append(y);
|
||||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
dlBuf->append(z);
|
||||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
} 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) {
|
void GXPosition2f32(f32 x, f32 y) {
|
||||||
sStreamState->check_direct(GX_VA_POS, GX_POS_XY, GX_F32);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{x, y, 0.f});
|
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) {
|
void GXPosition2u16(u16 x, u16 y) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XY, GX_U16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{
|
dlBuf->append(x);
|
||||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
dlBuf->append(y);
|
||||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
} else if (auto& stream = sStreamState) {
|
||||||
0.f,
|
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) {
|
void GXPosition2s16(s16 x, s16 y) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XY, GX_S16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{
|
dlBuf->append(x);
|
||||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
dlBuf->append(y);
|
||||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
} else if (auto& stream = sStreamState) {
|
||||||
0.f,
|
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) {
|
void GXPosition2u8(u8 x, u8 y) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XY, GX_U8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{
|
dlBuf->append(x);
|
||||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
dlBuf->append(y);
|
||||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
} else if (auto& stream = sStreamState) {
|
||||||
0.f,
|
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) {
|
void GXPosition2s8(s8 x, s8 y) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_POS, GX_POS_XY, GX_S8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{
|
dlBuf->append(x);
|
||||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
dlBuf->append(y);
|
||||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
} else if (auto& stream = sStreamState) {
|
||||||
0.f,
|
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) {
|
void GXPosition1x16(u16 idx) {
|
||||||
sStreamState->check_indexed(GX_VA_POS, GX_INDEX16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append<u16>(idx);
|
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) {
|
void GXPosition1x8(u8 idx) {
|
||||||
sStreamState->check_indexed(GX_VA_POS, GX_INDEX8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append<u16>(idx);
|
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) {
|
void GXNormal3f32(f32 x, f32 y, f32 z) {
|
||||||
sStreamState->check_direct(GX_VA_NRM, GX_NRM_XYZ, GX_F32);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{x, y, z});
|
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) {
|
void GXNormal3s16(s16 x, s16 y, s16 z) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_NRM, GX_NRM_XYZ, GX_S16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{
|
dlBuf->append(x);
|
||||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
dlBuf->append(y);
|
||||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
dlBuf->append(z);
|
||||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
} 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) {
|
void GXNormal3s8(s8 x, s8 y, s8 z) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_NRM, GX_NRM_XYZ, GX_S8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec3{
|
dlBuf->append(x);
|
||||||
static_cast<f32>(x) / static_cast<f32>(1 << frac),
|
dlBuf->append(y);
|
||||||
static_cast<f32>(y) / static_cast<f32>(1 << frac),
|
dlBuf->append(z);
|
||||||
static_cast<f32>(z) / static_cast<f32>(1 << frac),
|
} 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) {
|
void GXNormal1x16(u16 index) {
|
||||||
sStreamState->check_indexed(GX_VA_NRM, GX_INDEX16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append<u16>(index);
|
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) {
|
void GXNormal1x8(u8 index) {
|
||||||
sStreamState->check_indexed(GX_VA_POS, GX_INDEX8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append<u16>(index);
|
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) {
|
void GXColor4f32(f32 r, f32 g, f32 b, f32 a) {
|
||||||
sStreamState->check_direct(GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec4{r, g, b, a});
|
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) {
|
void GXColor4u8(u8 r, u8 g, u8 b, u8 a) {
|
||||||
sStreamState->check_direct(GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec4{
|
dlBuf->append(r);
|
||||||
static_cast<f32>(r) / 255.f,
|
dlBuf->append(g);
|
||||||
static_cast<f32>(g) / 255.f,
|
dlBuf->append(b);
|
||||||
static_cast<f32>(b) / 255.f,
|
dlBuf->append(a);
|
||||||
static_cast<f32>(a) / 255.f,
|
} 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) {
|
void GXColor3u8(u8 r, u8 g, u8 b) {
|
||||||
sStreamState->check_direct(GX_VA_CLR0, GX_CLR_RGB, GX_RGB8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec4{
|
dlBuf->append(r);
|
||||||
static_cast<f32>(r) / 255.f,
|
dlBuf->append(g);
|
||||||
static_cast<f32>(g) / 255.f,
|
dlBuf->append(b);
|
||||||
static_cast<f32>(b) / 255.f,
|
} else if (auto& stream = sStreamState) {
|
||||||
1.f,
|
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) {
|
void GXColor1u32(u32 clr) {
|
||||||
sStreamState->check_direct(GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec4{
|
dlBuf->append(clr);
|
||||||
static_cast<f32>((clr >> 24) & 0xff) / 255.f,
|
} else if (auto& stream = sStreamState) {
|
||||||
static_cast<f32>((clr >> 16) & 0xff) / 255.f,
|
stream->check_direct(GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8);
|
||||||
static_cast<f32>((clr >> 8) & 0xff) / 255.f,
|
stream->append(aurora::Vec4{
|
||||||
static_cast<f32>(clr & 0xff) / 255.f,
|
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) {
|
void GXColor1u16(u16 clr) {
|
||||||
sStreamState->check_direct(GX_VA_CLR0, GX_CLR_RGB, GX_RGB565);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec4{
|
dlBuf->append(clr);
|
||||||
static_cast<f32>((clr >> 11) & 0x1f) / 31.f,
|
} else if (auto& stream = sStreamState) {
|
||||||
static_cast<f32>((clr >> 5) & 0x3f) / 63.f,
|
stream->check_direct(GX_VA_CLR0, GX_CLR_RGB, GX_RGB565);
|
||||||
static_cast<f32>(clr & 0x1f) / 31.f,
|
stream->append(aurora::Vec4{
|
||||||
1.f,
|
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) {
|
void GXColor1x16(u16 index) {
|
||||||
sStreamState->check_indexed(GX_VA_CLR0, GX_INDEX16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append<u16>(index);
|
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) {
|
void GXColor1x8(u8 index) {
|
||||||
sStreamState->check_indexed(GX_VA_CLR0, GX_INDEX8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append<u16>(index);
|
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) {
|
void GXTexCoord2f32(f32 s, f32 t) {
|
||||||
sStreamState->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_F32);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec2{s, t});
|
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) {
|
void GXTexCoord2u16(u16 s, u16 t) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_U16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec2{
|
dlBuf->append(s);
|
||||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
dlBuf->append(t);
|
||||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
} 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) {
|
void GXTexCoord2s16(s16 s, s16 t) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_S16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec2{
|
dlBuf->append(s);
|
||||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
dlBuf->append(t);
|
||||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
} 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) {
|
void GXTexCoord2u8(u8 s, u8 t) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_U8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec2{
|
dlBuf->append(s);
|
||||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
dlBuf->append(t);
|
||||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
} 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) {
|
void GXTexCoord2s8(s8 s, s8 t) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_ST, GX_S8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec2{
|
dlBuf->append(s);
|
||||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
dlBuf->append(t);
|
||||||
static_cast<f32>(t) / static_cast<f32>(1 << frac),
|
} 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) {
|
void GXTexCoord1f32(f32 s) {
|
||||||
sStreamState->check_direct(GX_VA_TEX0, GX_TEX_S, GX_F32);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec2{s, 0.f});
|
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) {
|
void GXTexCoord1u16(u16 s) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_S, GX_U16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec2{
|
dlBuf->append(s);
|
||||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
} else if (auto& stream = sStreamState) {
|
||||||
0.f,
|
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) {
|
void GXTexCoord1s16(s16 s) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_S, GX_S16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec2{
|
dlBuf->append(s);
|
||||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
} else if (auto& stream = sStreamState) {
|
||||||
0.f,
|
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) {
|
void GXTexCoord1u8(u8 s) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_S, GX_U8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec2{
|
dlBuf->append(s);
|
||||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
} else if (auto& stream = sStreamState) {
|
||||||
0.f,
|
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) {
|
void GXTexCoord1s8(s8 s) {
|
||||||
const auto frac = sStreamState->check_direct(GX_VA_TEX0, GX_TEX_S, GX_S8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(aurora::Vec2{
|
dlBuf->append(s);
|
||||||
static_cast<f32>(s) / static_cast<f32>(1 << frac),
|
} else if (auto& stream = sStreamState) {
|
||||||
0.f,
|
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) {
|
void GXTexCoord1x16(u16 index) {
|
||||||
sStreamState->check_indexed(GX_VA_TEX0, GX_INDEX16);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(index);
|
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) {
|
void GXTexCoord1x8(u8 index) {
|
||||||
sStreamState->check_indexed(GX_VA_TEX0, GX_INDEX8);
|
if (auto& dlBuf = g_gxState.dynamicDlBuf) {
|
||||||
sStreamState->append(static_cast<u16>(index));
|
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() {
|
void GXEnd() {
|
||||||
|
@ -17,7 +17,7 @@ struct DisplayListCache {
|
|||||||
|
|
||||||
static absl::flat_hash_map<HashType, DisplayListCache> sCachedDisplayLists;
|
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;
|
using gx::g_gxState;
|
||||||
struct {
|
struct {
|
||||||
u8 count;
|
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));
|
buf.append(static_cast<u16>(*ptr));
|
||||||
++ptr;
|
++ptr;
|
||||||
} else if (g_gxState.vtxDesc[attr] == GX_INDEX16) {
|
} 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;
|
ptr += 2;
|
||||||
}
|
}
|
||||||
if (g_gxState.vtxDesc[attr] != GX_DIRECT) {
|
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;
|
break;
|
||||||
case GX_U16:
|
case GX_U16:
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
const auto value = bswap(reinterpret_cast<const u16*>(ptr)[i]);
|
auto value = reinterpret_cast<const u16*>(ptr)[i];
|
||||||
out[i] = static_cast<f32>(value) / static_cast<f32>(1 << attrFmt.frac);
|
out[i] = static_cast<f32>(bigEndian ? bswap(value) : value) / static_cast<f32>(1 << attrFmt.frac);
|
||||||
}
|
}
|
||||||
buf.append(out.data(), sizeof(f32) * count);
|
buf.append(out.data(), sizeof(f32) * count);
|
||||||
ptr += count * sizeof(u16);
|
ptr += count * sizeof(u16);
|
||||||
break;
|
break;
|
||||||
case GX_S16:
|
case GX_S16:
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
const auto value = bswap(reinterpret_cast<const s16*>(ptr)[i]);
|
const auto value = reinterpret_cast<const s16*>(ptr)[i];
|
||||||
out[i] = static_cast<f32>(value) / static_cast<f32>(1 << attrFmt.frac);
|
out[i] = static_cast<f32>(bigEndian ? bswap(value) : value) / static_cast<f32>(1 << attrFmt.frac);
|
||||||
}
|
}
|
||||||
buf.append(out.data(), sizeof(f32) * count);
|
buf.append(out.data(), sizeof(f32) * count);
|
||||||
ptr += count * sizeof(s16);
|
ptr += count * sizeof(s16);
|
||||||
break;
|
break;
|
||||||
case GX_F32:
|
case GX_F32:
|
||||||
for (int i = 0; i < count; ++i) {
|
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);
|
buf.append(out.data(), sizeof(f32) * count);
|
||||||
ptr += count * sizeof(f32);
|
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) {
|
static u16 prepare_idx_buffer(ByteBuffer& buf, GXPrimitive prim, u16 vtxStart, u16 vtxCount) {
|
||||||
u16 numIndices = 0;
|
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));
|
buf.reserve_extra(vtxCount * sizeof(u16));
|
||||||
for (u16 v = 0; v < vtxCount; ++v) {
|
for (u16 v = 0; v < vtxCount; ++v) {
|
||||||
const u16 idx = vtxStart + v;
|
const u16 idx = vtxStart + v;
|
||||||
@ -222,7 +243,7 @@ static u16 prepare_idx_buffer(ByteBuffer& buf, GXPrimitive prim, u16 vtxStart, u
|
|||||||
return numIndices;
|
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);
|
const auto hash = xxh3_hash_s(dlStart, dlSize, 0);
|
||||||
Range vertRange, idxRange;
|
Range vertRange, idxRange;
|
||||||
u32 numIndices = 0;
|
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);
|
FATAL("Vertex format changed mid-display list: {} -> {}", fmt, newFmt);
|
||||||
}
|
}
|
||||||
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 += 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);
|
numIndices += prepare_idx_buffer(idxBuf, prim, vtxStart, vtxCount);
|
||||||
vtxStart += vtxCount;
|
vtxStart += vtxCount;
|
||||||
break;
|
break;
|
||||||
|
@ -10,5 +10,5 @@ struct DisplayListResult {
|
|||||||
GXVtxFmt fmt;
|
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
|
}; // namespace aurora::gfx::gx
|
||||||
|
@ -294,6 +294,7 @@ struct GXState {
|
|||||||
ClipRect texCopySrc;
|
ClipRect texCopySrc;
|
||||||
GXTexFmt texCopyFmt;
|
GXTexFmt texCopyFmt;
|
||||||
absl::flat_hash_map<void*, TextureHandle> copyTextures;
|
absl::flat_hash_map<void*, TextureHandle> copyTextures;
|
||||||
|
std::optional<ByteBuffer> dynamicDlBuf;
|
||||||
bool depthCompare = true;
|
bool depthCompare = true;
|
||||||
bool depthUpdate = true;
|
bool depthUpdate = true;
|
||||||
bool colorUpdate = 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,
|
static std::string color_arg_reg(GXTevColorArg arg, size_t stageIdx, const ShaderConfig& config,
|
||||||
const TevStage& stage) {
|
const TevStage& stage) {
|
||||||
switch (arg) {
|
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) {
|
if (stage.channelId == GX_COLOR_ZERO) {
|
||||||
return "vec3f(0.0)";
|
return "vec3f(0.0)";
|
||||||
}
|
}
|
||||||
CHECK(stage.channelId >= GX_COLOR0A0 && stage.channelId <= GX_COLOR1A1, "invalid color channel {} for stage {}",
|
u32 idx = color_channel(stage.channelId);
|
||||||
underlying(stage.channelId), stageIdx);
|
|
||||||
u32 idx = stage.channelId - GX_COLOR0A0;
|
|
||||||
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
|
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
|
||||||
return fmt::format("rast{}.{}{}{}", idx, chan_comp(swap.red), chan_comp(swap.green), chan_comp(swap.blue));
|
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) {
|
if (stage.channelId == GX_COLOR_ZERO) {
|
||||||
return "vec3f(0.0)";
|
return "vec3f(0.0)";
|
||||||
}
|
}
|
||||||
CHECK(stage.channelId >= GX_COLOR0A0 && stage.channelId <= GX_COLOR1A1, "invalid color channel {} for stage {}",
|
u32 idx = color_channel(stage.channelId);
|
||||||
underlying(stage.channelId), stageIdx);
|
|
||||||
u32 idx = stage.channelId - GX_COLOR0A0;
|
|
||||||
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
|
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
|
||||||
return fmt::format("vec3f(rast{}.{})", idx, chan_comp(swap.alpha));
|
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) {
|
if (stage.channelId == GX_COLOR_ZERO) {
|
||||||
return "0.0";
|
return "0.0";
|
||||||
}
|
}
|
||||||
CHECK(stage.channelId >= GX_COLOR0A0 && stage.channelId <= GX_COLOR1A1, "invalid color channel {} for stage {}",
|
u32 idx = color_channel(stage.channelId);
|
||||||
underlying(stage.channelId), stageIdx);
|
|
||||||
u32 idx = stage.channelId - GX_COLOR0A0;
|
|
||||||
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
|
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
|
||||||
return fmt::format("rast{}.{}", idx, chan_comp(swap.alpha));
|
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
|
// Default normal
|
||||||
return "vec3f(1.0, 0.0, 0.0)"s;
|
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));
|
UNLIKELY FATAL("unmapped vtx attr {}", underlying(attr));
|
||||||
}
|
}
|
||||||
if (attr == GX_VA_POS) {
|
if (attr == GX_VA_POS) {
|
||||||
@ -499,6 +510,16 @@ auto storage_load(const StorageConfig& mapping, u32 attrIdx) -> StorageLoadResul
|
|||||||
std::string attrLoad;
|
std::string attrLoad;
|
||||||
|
|
||||||
switch (compType) {
|
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:
|
case GX_U16:
|
||||||
switch (compCnt) {
|
switch (compCnt) {
|
||||||
case 2:
|
case 2:
|
||||||
@ -541,6 +562,10 @@ auto storage_load(const StorageConfig& mapping, u32 attrIdx) -> StorageLoadResul
|
|||||||
Log.fatal("storage_load: Unsupported {} count {}", compType, compCnt);
|
Log.fatal("storage_load: Unsupported {} count {}", compType, compCnt);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case GX_RGBA8:
|
||||||
|
arrType = "u32";
|
||||||
|
attrLoad = fmt::format("unpack4x8unorm(v_arr_{}[{}])", attrName, idxFetch);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Log.fatal("storage_load: Unimplemented {}", compType);
|
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);
|
var o1 = select(extractBits(v0, 8, 8), extractBits(v0, 24, 8), r);
|
||||||
return vec2<f32>(f32(o0), f32(o1)) / f32(1u << frac);
|
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> {{
|
fn fetch_u16_2(p: ptr<storage, array<u32>>, idx: u32, frac: u32) -> vec2<f32> {{
|
||||||
var v0 = p[idx];
|
var v0 = p[idx];
|
||||||
var o0 = extractBits(v0, 0, 16);
|
var o0 = extractBits(v0, 0, 16);
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
namespace aurora::gfx::model {
|
namespace aurora::gfx::model {
|
||||||
static Module Log("aurora::gfx::model");
|
static Module Log("aurora::gfx::model");
|
||||||
|
|
||||||
void queue_surface(const u8* dlStart, u32 dlSize) noexcept {
|
void queue_surface(const u8* dlStart, u32 dlSize, bool bigEndian) noexcept {
|
||||||
const auto result = aurora::gfx::gx::process_display_list(dlStart, dlSize);
|
const auto result = aurora::gfx::gx::process_display_list(dlStart, dlSize, bigEndian);
|
||||||
|
|
||||||
gx::BindGroupRanges ranges{};
|
gx::BindGroupRanges ranges{};
|
||||||
for (int i = 0; i < GX_VA_MAX_ATTR; ++i) {
|
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);
|
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 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
|
} // namespace aurora::gfx::model
|
||||||
|
@ -39,9 +39,7 @@ void color_arg_reg_info(GXTevColorArg arg, const TevStage& stage, ShaderInfo& in
|
|||||||
break;
|
break;
|
||||||
case GX_CC_RASC:
|
case GX_CC_RASC:
|
||||||
case GX_CC_RASA:
|
case GX_CC_RASA:
|
||||||
if (stage.channelId >= GX_COLOR0A0 && stage.channelId <= GX_COLOR1A1) {
|
info.sampledColorChannels.set(color_channel(stage.channelId));
|
||||||
info.sampledColorChannels.set(stage.channelId - GX_COLOR0A0);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case GX_CC_KONST:
|
case GX_CC_KONST:
|
||||||
switch (stage.kcSel) {
|
switch (stage.kcSel) {
|
||||||
@ -111,9 +109,7 @@ void alpha_arg_reg_info(GXTevAlphaArg arg, const TevStage& stage, ShaderInfo& in
|
|||||||
info.sampledTextures.set(stage.texMapId);
|
info.sampledTextures.set(stage.texMapId);
|
||||||
break;
|
break;
|
||||||
case GX_CA_RASA:
|
case GX_CA_RASA:
|
||||||
if (stage.channelId >= GX_COLOR0A0 && stage.channelId <= GX_COLOR1A1) {
|
info.sampledColorChannels.set(color_channel(stage.channelId));
|
||||||
info.sampledColorChannels.set(stage.channelId - GX_COLOR0A0);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case GX_CA_KONST:
|
case GX_CA_KONST:
|
||||||
switch (stage.kaSel) {
|
switch (stage.kaSel) {
|
||||||
|
@ -5,4 +5,5 @@
|
|||||||
namespace aurora::gfx::gx {
|
namespace aurora::gfx::gx {
|
||||||
ShaderInfo build_shader_info(const ShaderConfig& config) noexcept;
|
ShaderInfo build_shader_info(const ShaderConfig& config) noexcept;
|
||||||
Range build_uniform(const ShaderInfo& info) noexcept;
|
Range build_uniform(const ShaderInfo& info) noexcept;
|
||||||
|
u8 color_channel(GXChannelID id) noexcept;
|
||||||
}; // namespace aurora::gfx::gx
|
}; // namespace aurora::gfx::gx
|
||||||
|
Loading…
x
Reference in New Issue
Block a user