mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-18 10:05:24 +00:00
Implement CGX & migrate usages to CGX/GX
This commit is contained in:
@@ -4,7 +4,119 @@
|
||||
#include "common.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
using aurora::gfx::gx::g_gxState;
|
||||
static logvisor::Module Log("aurora::gx");
|
||||
|
||||
void GXSetNumChans(u8 num) noexcept { g_gxState.numChans = num; }
|
||||
void GXSetNumIndStages(u8 num) noexcept { g_gxState.numIndStages = num; }
|
||||
void GXSetNumTevStages(u8 num) noexcept { g_gxState.numTevStages = num; }
|
||||
void GXSetNumTexGens(u8 num) noexcept { g_gxState.numTexGens = num; }
|
||||
void GXSetTevAlphaIn(GX::TevStageID stageId, GX::TevAlphaArg a, GX::TevAlphaArg b, GX::TevAlphaArg c,
|
||||
GX::TevAlphaArg d) noexcept {
|
||||
g_gxState.tevStages[stageId].alphaPass = {a, b, c, d};
|
||||
}
|
||||
void GXSetTevAlphaOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, bool clamp,
|
||||
GX::TevRegID outReg) noexcept {
|
||||
g_gxState.tevStages[stageId].alphaOp = {op, bias, scale, outReg, clamp};
|
||||
}
|
||||
void GXSetTevColorIn(GX::TevStageID stageId, GX::TevColorArg a, GX::TevColorArg b, GX::TevColorArg c,
|
||||
GX::TevColorArg d) noexcept {
|
||||
g_gxState.tevStages[stageId].colorPass = {a, b, c, d};
|
||||
}
|
||||
void GXSetTevColorOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, bool clamp,
|
||||
GX::TevRegID outReg) noexcept {
|
||||
g_gxState.tevStages[stageId].colorOp = {op, bias, scale, outReg, clamp};
|
||||
}
|
||||
void GXSetCullMode(GX::CullMode mode) noexcept { g_gxState.cullMode = mode; }
|
||||
void GXSetBlendMode(GX::BlendMode mode, GX::BlendFactor src, GX::BlendFactor dst, GX::LogicOp op) noexcept {
|
||||
g_gxState.blendMode = mode;
|
||||
g_gxState.blendFacSrc = src;
|
||||
g_gxState.blendFacDst = dst;
|
||||
g_gxState.blendOp = op;
|
||||
}
|
||||
void GXSetZMode(bool compare_enable, GX::Compare func, bool update_enable) noexcept {
|
||||
g_gxState.depthCompare = compare_enable;
|
||||
g_gxState.depthFunc = func;
|
||||
g_gxState.depthUpdate = update_enable;
|
||||
}
|
||||
void GXSetTevColor(GX::TevRegID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::TEVREG0 || id > GX::TEVREG2) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("bad tevreg {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_gxState.colorRegs[id - 1] = color;
|
||||
}
|
||||
void GXSetTevKColor(GX::TevKColorID id, const zeus::CColor& color) noexcept {
|
||||
if (id >= GX::MAX_KCOLOR) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("bad kcolor {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_gxState.kcolors[id] = color;
|
||||
}
|
||||
void GXSetAlphaUpdate(bool enabled) noexcept { g_gxState.alphaUpdate = enabled; }
|
||||
void GXSetDstAlpha(bool enabled, float value) noexcept {
|
||||
if (enabled) {
|
||||
g_gxState.dstAlpha = value;
|
||||
} else {
|
||||
g_gxState.dstAlpha.reset();
|
||||
}
|
||||
}
|
||||
void GXSetCopyClear(const zeus::CColor& color, float depth) noexcept { g_gxState.clearColor = color; }
|
||||
void GXSetTevOrder(GX::TevStageID id, GX::TexCoordID tcid, GX::TexMapID tmid, GX::ChannelID cid) noexcept {
|
||||
auto& stage = g_gxState.tevStages[id];
|
||||
stage.texCoordId = tcid;
|
||||
stage.texMapId = tmid;
|
||||
stage.channelId = cid;
|
||||
}
|
||||
void GXSetTevKColorSel(GX::TevStageID id, GX::TevKColorSel sel) noexcept { g_gxState.tevStages[id].kcSel = sel; }
|
||||
void GXSetTevKAlphaSel(GX::TevStageID id, GX::TevKAlphaSel sel) noexcept { g_gxState.tevStages[id].kaSel = sel; }
|
||||
void GXSetChanAmbColor(GX::ChannelID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("bad channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_gxState.colorChannelState[id - GX::COLOR0A0].ambColor = color;
|
||||
}
|
||||
void GXSetChanMatColor(GX::ChannelID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("bad channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_gxState.colorChannelState[id - GX::COLOR0A0].matColor = color;
|
||||
}
|
||||
void GXSetChanCtrl(GX::ChannelID id, bool lightingEnabled, GX::ColorSrc ambSrc, GX::ColorSrc matSrc,
|
||||
GX::LightMask lightState, GX::DiffuseFn diffFn, GX::AttnFn attnFn) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("bad channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
if (diffFn != GX::DF_NONE && diffFn != GX::DF_CLAMP) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled diffuse fn {}"), diffFn);
|
||||
unreachable();
|
||||
}
|
||||
if (attnFn != GX::AF_NONE && attnFn != GX::AF_SPOT) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled attn fn {}"), attnFn);
|
||||
unreachable();
|
||||
}
|
||||
u32 idx = id - GX::COLOR0A0;
|
||||
auto& chan = g_gxState.colorChannelConfig[idx];
|
||||
chan.lightingEnabled = lightingEnabled;
|
||||
chan.ambSrc = ambSrc;
|
||||
chan.matSrc = matSrc;
|
||||
g_gxState.colorChannelState[idx].lightState = lightState;
|
||||
}
|
||||
void GXSetAlphaCompare(GX::Compare comp0, float ref0, GX::AlphaOp op, GX::Compare comp1, float ref1) noexcept {
|
||||
if (comp0 == GX::ALWAYS && comp1 == GX::ALWAYS) {
|
||||
g_gxState.alphaDiscard.reset();
|
||||
} else if (comp0 == GX::GEQUAL && comp1 == GX::NEVER) {
|
||||
g_gxState.alphaDiscard = ref0;
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("GXSetAlphaCompare: unknown operands"));
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
void GXSetVtxDescv(GX::VtxDescList* list) noexcept;
|
||||
|
||||
namespace aurora::gfx {
|
||||
static logvisor::Module Log("aurora::gfx::gx");
|
||||
@@ -14,51 +126,13 @@ extern std::mutex g_pipelineMutex;
|
||||
|
||||
// GX state
|
||||
void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp, const TextureHandle& tex, float lod) noexcept {
|
||||
gx::g_textures[static_cast<size_t>(id)] = {tex, clamp, lod};
|
||||
gx::g_gxState.textures[static_cast<size_t>(id)] = {tex, clamp, lod};
|
||||
}
|
||||
void unbind_texture(GX::TexMapID id) noexcept { gx::g_textures[static_cast<size_t>(id)].reset(); }
|
||||
|
||||
void set_cull_mode(metaforce::ERglCullMode mode) noexcept { gx::g_cullMode = mode; }
|
||||
void set_blend_mode(metaforce::ERglBlendMode mode, metaforce::ERglBlendFactor src, metaforce::ERglBlendFactor dst,
|
||||
metaforce::ERglLogicOp op) noexcept {
|
||||
gx::g_blendMode = mode;
|
||||
gx::g_blendFacSrc = src;
|
||||
gx::g_blendFacDst = dst;
|
||||
gx::g_blendOp = op;
|
||||
}
|
||||
void set_depth_mode(bool compare_enable, metaforce::ERglEnum func, bool update_enable) noexcept {
|
||||
gx::g_depthCompare = compare_enable;
|
||||
gx::g_depthFunc = func;
|
||||
gx::g_depthUpdate = update_enable;
|
||||
}
|
||||
void set_tev_reg_color(GX::TevRegID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::TEVREG0 || id > GX::TEVREG2) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_reg_color: bad reg {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
gx::g_colorRegs[id - 1] = color;
|
||||
}
|
||||
void set_tev_k_color(GX::TevKColorID id, const zeus::CColor& color) noexcept {
|
||||
if (id >= GX::MAX_KCOLOR) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_k_color: bad reg {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
gx::g_kcolors[id] = color;
|
||||
}
|
||||
void set_alpha_update(bool enabled) noexcept { gx::g_alphaUpdate = enabled; }
|
||||
void set_dst_alpha(bool enabled, float value) noexcept {
|
||||
if (enabled) {
|
||||
gx::g_dstAlpha = value;
|
||||
} else {
|
||||
gx::g_dstAlpha.reset();
|
||||
}
|
||||
}
|
||||
void set_clear_color(const zeus::CColor& color) noexcept { gx::g_clearColor = color; }
|
||||
void set_alpha_discard(bool v) { gx::g_alphaDiscard = v; }
|
||||
void unbind_texture(GX::TexMapID id) noexcept { gx::g_gxState.textures[static_cast<size_t>(id)].reset(); }
|
||||
|
||||
void update_model_view(const zeus::CMatrix4f& mv, const zeus::CMatrix4f& mv_inv) noexcept {
|
||||
gx::g_mv = mv;
|
||||
gx::g_mvInv = mv_inv;
|
||||
gx::g_gxState.mv = mv;
|
||||
gx::g_gxState.mvInv = mv_inv;
|
||||
}
|
||||
constexpr zeus::CMatrix4f DepthCorrect{
|
||||
// clang-format off
|
||||
@@ -68,133 +142,44 @@ constexpr zeus::CMatrix4f DepthCorrect{
|
||||
0.f, 0.f, 0.f, 1.f,
|
||||
// clang-format on
|
||||
};
|
||||
void update_projection(const zeus::CMatrix4f& proj) noexcept { gx::g_proj = DepthCorrect * proj; }
|
||||
void update_fog_state(const metaforce::CFogState& state) noexcept { gx::g_fogState = state; }
|
||||
void update_projection(const zeus::CMatrix4f& proj) noexcept { gx::g_gxState.proj = DepthCorrect * proj; }
|
||||
void update_fog_state(const metaforce::CFogState& state) noexcept { gx::g_gxState.fogState = state; }
|
||||
|
||||
void disable_tev_stage(metaforce::ERglTevStage stage) noexcept { gx::g_tevStages[static_cast<size_t>(stage)].reset(); }
|
||||
void update_tev_stage(metaforce::ERglTevStage stage, const metaforce::CTevCombiners::ColorPass& colPass,
|
||||
const metaforce::CTevCombiners::AlphaPass& alphaPass,
|
||||
const metaforce::CTevCombiners::CTevOp& colorOp,
|
||||
const metaforce::CTevCombiners::CTevOp& alphaOp) noexcept {
|
||||
gx::g_tevStages[static_cast<size_t>(stage)] = {colPass, alphaPass, colorOp, alphaOp};
|
||||
void load_light(GX::LightID id, const Light& light) noexcept { gx::g_gxState.lights[std::log2<u32>(id)] = light; }
|
||||
void load_light_ambient(GX::LightID id, const zeus::CColor& ambient) noexcept {
|
||||
gx::g_gxState.lights[std::log2<u32>(id)] = ambient;
|
||||
}
|
||||
|
||||
void set_tev_order(GX::TevStageID id, GX::TexCoordID tcid, GX::TexMapID tmid, GX::ChannelID cid) noexcept {
|
||||
auto& stage = gx::g_tevStages[id];
|
||||
if (!stage) {
|
||||
// Log.report(logvisor::Fatal, FMT_STRING("set_tev_order: disabled stage {}"), id);
|
||||
// unreachable();
|
||||
return;
|
||||
}
|
||||
stage->texCoordId = tcid;
|
||||
stage->texMapId = tmid;
|
||||
stage->channelId = cid;
|
||||
}
|
||||
void set_tev_k_color_sel(GX::TevStageID id, GX::TevKColorSel sel) noexcept {
|
||||
auto& stage = gx::g_tevStages[id];
|
||||
if (!stage) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_k_color_sel: disabled stage {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
stage->kcSel = sel;
|
||||
}
|
||||
void set_tev_k_alpha_sel(GX::TevStageID id, GX::TevKAlphaSel sel) noexcept {
|
||||
auto& stage = gx::g_tevStages[id];
|
||||
if (!stage) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_k_alpha_sel: disabled stage {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
stage->kaSel = sel;
|
||||
}
|
||||
|
||||
void set_chan_amb_color(GX::ChannelID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_chan_amb_color: invalid channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
gx::g_colorChannels[id - GX::COLOR0A0].ambColor = color;
|
||||
}
|
||||
void set_chan_mat_color(GX::ChannelID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_chan_mat_color: invalid channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
gx::g_colorChannels[id - GX::COLOR0A0].matColor = color;
|
||||
}
|
||||
void set_chan_mat_src(GX::ChannelID id, GX::ColorSrc src) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_chan_mat_src: invalid channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
gx::g_colorChannels[id - GX::COLOR0A0].matSrc = src;
|
||||
}
|
||||
|
||||
static inline u8 light_idx(GX::LightID id) {
|
||||
#ifdef _MSC_VER
|
||||
unsigned long r = 0;
|
||||
_BitScanForward(&r, id);
|
||||
return r;
|
||||
#else
|
||||
return __builtin_ctz(id);
|
||||
#endif
|
||||
}
|
||||
void load_light(GX::LightID id, const Light& light) noexcept { gx::g_lights[light_idx(id)] = light; }
|
||||
void load_light_ambient(GX::LightID id, const zeus::CColor& ambient) noexcept { gx::g_lights[light_idx(id)] = ambient; }
|
||||
void set_light_state(std::bitset<MaxLights> bits) noexcept { gx::g_lightState = bits; }
|
||||
void set_light_state(GX::LightMask bits) noexcept { gx::g_gxState.lightState = bits; }
|
||||
|
||||
namespace gx {
|
||||
using gpu::g_device;
|
||||
using gpu::g_graphicsConfig;
|
||||
|
||||
zeus::CMatrix4f g_mv;
|
||||
zeus::CMatrix4f g_mvInv;
|
||||
zeus::CMatrix4f g_proj;
|
||||
metaforce::CFogState g_fogState;
|
||||
metaforce::ERglCullMode g_cullMode;
|
||||
metaforce::ERglBlendMode g_blendMode;
|
||||
metaforce::ERglBlendFactor g_blendFacSrc;
|
||||
metaforce::ERglBlendFactor g_blendFacDst;
|
||||
metaforce::ERglLogicOp g_blendOp;
|
||||
bool g_depthCompare;
|
||||
bool g_depthUpdate;
|
||||
metaforce::ERglEnum g_depthFunc;
|
||||
std::array<zeus::CColor, 3> g_colorRegs;
|
||||
std::array<zeus::CColor, GX::MAX_KCOLOR> g_kcolors;
|
||||
bool g_alphaUpdate;
|
||||
std::optional<float> g_dstAlpha;
|
||||
zeus::CColor g_clearColor = zeus::skClear;
|
||||
bool g_alphaDiscard;
|
||||
GXState g_gxState;
|
||||
|
||||
std::array<SChannelState, 2> g_colorChannels;
|
||||
std::array<LightVariant, MaxLights> g_lights;
|
||||
std::bitset<MaxLights> g_lightState;
|
||||
const TextureBind& get_texture(GX::TexMapID id) noexcept { return g_gxState.textures[static_cast<size_t>(id)]; }
|
||||
|
||||
std::array<std::optional<STevStage>, maxTevStages> g_tevStages;
|
||||
std::array<TextureBind, maxTextures> g_textures;
|
||||
|
||||
const gx::TextureBind& get_texture(GX::TexMapID id) noexcept { return gx::g_textures[static_cast<size_t>(id)]; }
|
||||
|
||||
static inline wgpu::BlendFactor to_blend_factor(metaforce::ERglBlendFactor fac) {
|
||||
static inline wgpu::BlendFactor to_blend_factor(GX::BlendFactor fac) {
|
||||
switch (fac) {
|
||||
case metaforce::ERglBlendFactor::Zero:
|
||||
case GX::BL_ZERO:
|
||||
return wgpu::BlendFactor::Zero;
|
||||
case metaforce::ERglBlendFactor::One:
|
||||
case GX::BL_ONE:
|
||||
return wgpu::BlendFactor::One;
|
||||
case metaforce::ERglBlendFactor::SrcColor:
|
||||
case GX::BL_SRCCLR:
|
||||
return wgpu::BlendFactor::Src;
|
||||
case metaforce::ERglBlendFactor::InvSrcColor:
|
||||
case GX::BL_INVSRCCLR:
|
||||
return wgpu::BlendFactor::OneMinusSrc;
|
||||
case metaforce::ERglBlendFactor::SrcAlpha:
|
||||
case GX::BL_SRCALPHA:
|
||||
return wgpu::BlendFactor::SrcAlpha;
|
||||
case metaforce::ERglBlendFactor::InvSrcAlpha:
|
||||
case GX::BL_INVSRCALPHA:
|
||||
return wgpu::BlendFactor::OneMinusSrcAlpha;
|
||||
case metaforce::ERglBlendFactor::DstAlpha:
|
||||
case GX::BL_DSTALPHA:
|
||||
return wgpu::BlendFactor::DstAlpha;
|
||||
case metaforce::ERglBlendFactor::InvDstAlpha:
|
||||
case GX::BL_INVDSTALPHA:
|
||||
return wgpu::BlendFactor::OneMinusDstAlpha;
|
||||
case metaforce::ERglBlendFactor::DstColor:
|
||||
case GX::BL_DSTCLR:
|
||||
return wgpu::BlendFactor::Dst;
|
||||
case metaforce::ERglBlendFactor::InvDstColor:
|
||||
case GX::BL_INVDSTCLR:
|
||||
return wgpu::BlendFactor::OneMinusDst;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid blend factor {}"), fac);
|
||||
@@ -202,23 +187,23 @@ static inline wgpu::BlendFactor to_blend_factor(metaforce::ERglBlendFactor fac)
|
||||
}
|
||||
}
|
||||
|
||||
static inline wgpu::CompareFunction to_compare_function(metaforce::ERglEnum func) {
|
||||
static inline wgpu::CompareFunction to_compare_function(GX::Compare func) {
|
||||
switch (func) {
|
||||
case metaforce::ERglEnum::Never:
|
||||
case GX::NEVER:
|
||||
return wgpu::CompareFunction::Never;
|
||||
case metaforce::ERglEnum::Less:
|
||||
case GX::LESS:
|
||||
return wgpu::CompareFunction::Less;
|
||||
case metaforce::ERglEnum::Equal:
|
||||
case GX::EQUAL:
|
||||
return wgpu::CompareFunction::Equal;
|
||||
case metaforce::ERglEnum::LEqual:
|
||||
case GX::LEQUAL:
|
||||
return wgpu::CompareFunction::LessEqual;
|
||||
case metaforce::ERglEnum::Greater:
|
||||
case GX::GREATER:
|
||||
return wgpu::CompareFunction::Greater;
|
||||
case metaforce::ERglEnum::NEqual:
|
||||
case GX::NEQUAL:
|
||||
return wgpu::CompareFunction::NotEqual;
|
||||
case metaforce::ERglEnum::GEqual:
|
||||
case GX::GEQUAL:
|
||||
return wgpu::CompareFunction::GreaterEqual;
|
||||
case metaforce::ERglEnum::Always:
|
||||
case GX::ALWAYS:
|
||||
return wgpu::CompareFunction::Always;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid depth fn {}"), func);
|
||||
@@ -226,10 +211,10 @@ static inline wgpu::CompareFunction to_compare_function(metaforce::ERglEnum func
|
||||
}
|
||||
}
|
||||
|
||||
static inline wgpu::BlendState to_blend_state(metaforce::ERglBlendMode mode, metaforce::ERglBlendFactor srcFac,
|
||||
metaforce::ERglBlendFactor dstFac, std::optional<float> dstAlpha) {
|
||||
if (mode != metaforce::ERglBlendMode::Blend) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("How to {}?"), magic_enum::enum_name(mode));
|
||||
static inline wgpu::BlendState to_blend_state(GX::BlendMode mode, GX::BlendFactor srcFac, GX::BlendFactor dstFac,
|
||||
std::optional<float> dstAlpha) {
|
||||
if (mode != GX::BM_BLEND) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("How to {}?"), mode);
|
||||
}
|
||||
const auto colorBlendComponent = wgpu::BlendComponent{
|
||||
.operation = wgpu::BlendOperation::Add,
|
||||
@@ -258,7 +243,7 @@ static inline wgpu::ColorWriteMask to_write_mask(bool alphaUpdate) {
|
||||
return writeMask;
|
||||
}
|
||||
|
||||
static inline wgpu::PrimitiveState to_primitive_state(GX::Primitive gx_prim, metaforce::ERglCullMode e_cullMode) {
|
||||
static inline wgpu::PrimitiveState to_primitive_state(GX::Primitive gx_prim, GX::CullMode gx_cullMode) {
|
||||
wgpu::PrimitiveTopology primitive = wgpu::PrimitiveTopology::TriangleList;
|
||||
switch (gx_prim) {
|
||||
case GX::TRIANGLES:
|
||||
@@ -272,14 +257,17 @@ static inline wgpu::PrimitiveState to_primitive_state(GX::Primitive gx_prim, met
|
||||
}
|
||||
wgpu::FrontFace frontFace = wgpu::FrontFace::CCW;
|
||||
wgpu::CullMode cullMode = wgpu::CullMode::None;
|
||||
switch (e_cullMode) {
|
||||
case metaforce::ERglCullMode::Front:
|
||||
switch (gx_cullMode) {
|
||||
case GX::CULL_FRONT:
|
||||
frontFace = wgpu::FrontFace::CW;
|
||||
cullMode = wgpu::CullMode::Front;
|
||||
break;
|
||||
case metaforce::ERglCullMode::Back:
|
||||
case GX::CULL_BACK:
|
||||
cullMode = wgpu::CullMode::Back;
|
||||
break;
|
||||
case GX::CULL_ALL:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Unsupported cull mode {}"), gx_cullMode);
|
||||
unreachable();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -345,29 +333,24 @@ wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderIn
|
||||
|
||||
ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive,
|
||||
const BindGroupRanges& ranges) noexcept {
|
||||
for (size_t idx = 0; const auto& item : g_tevStages) {
|
||||
// Copy until disabled TEV stage (indicating end)
|
||||
if (!item) {
|
||||
break;
|
||||
}
|
||||
config.shaderConfig.tevStages[idx++] = item;
|
||||
for (size_t i = 0; i < g_gxState.numTevStages; ++i) {
|
||||
config.shaderConfig.tevStages[i] = g_gxState.tevStages[i];
|
||||
}
|
||||
config.shaderConfig.channelMatSrcs[0] = g_colorChannels[0].matSrc;
|
||||
config.shaderConfig.channelMatSrcs[1] = g_colorChannels[1].matSrc;
|
||||
config.shaderConfig.alphaDiscard = g_alphaDiscard;
|
||||
config.shaderConfig.colorChannels = g_gxState.colorChannelConfig;
|
||||
config.shaderConfig.alphaDiscard = g_gxState.alphaDiscard;
|
||||
config = {
|
||||
.shaderConfig = config.shaderConfig,
|
||||
.primitive = primitive,
|
||||
.depthFunc = g_depthFunc,
|
||||
.cullMode = g_cullMode,
|
||||
.blendMode = g_blendMode,
|
||||
.blendFacSrc = g_blendFacSrc,
|
||||
.blendFacDst = g_blendFacDst,
|
||||
.blendOp = g_blendOp,
|
||||
.dstAlpha = g_dstAlpha,
|
||||
.depthCompare = g_depthCompare,
|
||||
.depthUpdate = g_depthUpdate,
|
||||
.alphaUpdate = g_alphaUpdate,
|
||||
.depthFunc = g_gxState.depthFunc,
|
||||
.cullMode = g_gxState.cullMode,
|
||||
.blendMode = g_gxState.blendMode,
|
||||
.blendFacSrc = g_gxState.blendFacSrc,
|
||||
.blendFacDst = g_gxState.blendFacDst,
|
||||
.blendOp = g_gxState.blendOp,
|
||||
.dstAlpha = g_gxState.dstAlpha,
|
||||
.depthCompare = g_gxState.depthCompare,
|
||||
.depthUpdate = g_gxState.depthUpdate,
|
||||
.alphaUpdate = g_gxState.alphaUpdate,
|
||||
};
|
||||
// TODO separate shader info from build_shader for async
|
||||
{
|
||||
@@ -381,51 +364,51 @@ ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primit
|
||||
Range build_uniform(const ShaderInfo& info) noexcept {
|
||||
auto [buf, range] = map_uniform(info.uniformSize);
|
||||
{
|
||||
buf.append(&g_mv, 64);
|
||||
buf.append(&g_mvInv, 64);
|
||||
buf.append(&g_proj, 64);
|
||||
buf.append(&g_gxState.mv, 64);
|
||||
buf.append(&g_gxState.mvInv, 64);
|
||||
buf.append(&g_gxState.proj, 64);
|
||||
}
|
||||
for (int i = 0; i < info.usesTevReg.size(); ++i) {
|
||||
if (!info.usesTevReg.test(i)) {
|
||||
continue;
|
||||
}
|
||||
buf.append(&g_colorRegs[i], 16);
|
||||
}
|
||||
if (info.sampledColorChannels.any()) {
|
||||
zeus::CColor ambient = zeus::skClear;
|
||||
int addedLights = 0;
|
||||
for (int i = 0; i < g_lightState.size(); ++i) {
|
||||
if (!g_lightState.test(i)) {
|
||||
continue;
|
||||
}
|
||||
const auto& variant = g_lights[i];
|
||||
if (std::holds_alternative<zeus::CColor>(variant)) {
|
||||
ambient += std::get<zeus::CColor>(variant);
|
||||
} else if (std::holds_alternative<Light>(variant)) {
|
||||
static_assert(sizeof(Light) == 80);
|
||||
buf.append(&std::get<Light>(variant), sizeof(Light));
|
||||
++addedLights;
|
||||
}
|
||||
}
|
||||
constexpr Light emptyLight{};
|
||||
for (int i = addedLights; i < MaxLights; ++i) {
|
||||
buf.append(&emptyLight, sizeof(Light));
|
||||
}
|
||||
buf.append(&ambient, 16);
|
||||
// fmt::print(FMT_STRING("Added lights: {}, ambient: {},{},{},{}\n"), addedLights, ambient.r(), ambient.g(), ambient.b(), ambient.a());
|
||||
buf.append(&g_gxState.colorRegs[i], 16);
|
||||
}
|
||||
for (int i = 0; i < info.sampledColorChannels.size(); ++i) {
|
||||
if (!info.sampledColorChannels.test(i)) {
|
||||
continue;
|
||||
}
|
||||
buf.append(&g_colorChannels[i].ambColor, 16);
|
||||
buf.append(&g_colorChannels[i].matColor, 16);
|
||||
buf.append(&g_gxState.colorChannelState[i].ambColor, 16);
|
||||
buf.append(&g_gxState.colorChannelState[i].matColor, 16);
|
||||
|
||||
if (g_gxState.colorChannelConfig[i].lightingEnabled) {
|
||||
zeus::CColor ambient = zeus::skClear;
|
||||
int addedLights = 0;
|
||||
for (int li = 0; li < g_gxState.lightState.size(); ++li) {
|
||||
if (!g_gxState.lightState.test(li)) {
|
||||
continue;
|
||||
}
|
||||
const auto& variant = g_gxState.lights[li];
|
||||
if (std::holds_alternative<zeus::CColor>(variant)) {
|
||||
ambient += std::get<zeus::CColor>(variant);
|
||||
} else if (std::holds_alternative<Light>(variant)) {
|
||||
static_assert(sizeof(Light) == 80);
|
||||
buf.append(&std::get<Light>(variant), sizeof(Light));
|
||||
++addedLights;
|
||||
}
|
||||
}
|
||||
constexpr Light emptyLight{};
|
||||
for (int li = addedLights; li < GX::MaxLights; ++li) {
|
||||
buf.append(&emptyLight, sizeof(Light));
|
||||
}
|
||||
buf.append(&ambient, 16);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < info.sampledKcolors.size(); ++i) {
|
||||
if (!info.sampledKcolors.test(i)) {
|
||||
for (int i = 0; i < info.sampledKColors.size(); ++i) {
|
||||
if (!info.sampledKColors.test(i)) {
|
||||
continue;
|
||||
}
|
||||
buf.append(&g_kcolors[i], 16);
|
||||
buf.append(&g_gxState.kcolors[i], 16);
|
||||
}
|
||||
for (int i = 0; i < info.sampledTextures.size(); ++i) {
|
||||
if (!info.sampledTextures.test(i)) {
|
||||
@@ -480,13 +463,13 @@ GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& confi
|
||||
.size = ranges.packedTcDataRange.second - ranges.packedTcDataRange.first,
|
||||
},
|
||||
};
|
||||
std::array<wgpu::BindGroupEntry, maxTextures> samplerEntries;
|
||||
std::array<wgpu::BindGroupEntry, maxTextures> textureEntries;
|
||||
std::array<wgpu::BindGroupEntry, MaxTextures> samplerEntries;
|
||||
std::array<wgpu::BindGroupEntry, MaxTextures> textureEntries;
|
||||
for (u32 texIdx = 0, i = 0; texIdx < info.sampledTextures.size(); ++texIdx) {
|
||||
if (!info.sampledTextures.test(texIdx)) {
|
||||
continue;
|
||||
}
|
||||
const auto& tex = g_textures[texIdx];
|
||||
const auto& tex = g_gxState.textures[texIdx];
|
||||
if (!tex) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unbound texture {}"), texIdx);
|
||||
unreachable();
|
||||
@@ -592,8 +575,8 @@ GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info, const Shader
|
||||
out.samplerLayout = sl;
|
||||
out.textureLayout = tl;
|
||||
} else {
|
||||
std::array<wgpu::BindGroupLayoutEntry, maxTextures> samplerEntries;
|
||||
std::array<wgpu::BindGroupLayoutEntry, maxTextures> textureEntries;
|
||||
std::array<wgpu::BindGroupLayoutEntry, MaxTextures> samplerEntries;
|
||||
std::array<wgpu::BindGroupLayoutEntry, MaxTextures> textureEntries;
|
||||
for (u32 i = 0; i < textureCount; ++i) {
|
||||
samplerEntries[i] = {
|
||||
.binding = i,
|
||||
@@ -637,7 +620,7 @@ void shutdown() noexcept {
|
||||
// TODO we should probably store this all in g_state.gx instead
|
||||
sUniformBindGroupLayouts.clear();
|
||||
sTextureBindGroupLayouts.clear();
|
||||
g_textures.fill({});
|
||||
g_gxState.textures.fill({});
|
||||
g_gxCachedShaders.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,51 +5,36 @@
|
||||
#include <variant>
|
||||
|
||||
namespace aurora::gfx::gx {
|
||||
extern zeus::CMatrix4f g_mv;
|
||||
extern zeus::CMatrix4f g_mvInv;
|
||||
extern zeus::CMatrix4f g_proj;
|
||||
extern metaforce::CFogState g_fogState;
|
||||
extern metaforce::ERglCullMode g_cullMode;
|
||||
extern metaforce::ERglBlendMode g_blendMode;
|
||||
extern metaforce::ERglBlendFactor g_blendFacSrc;
|
||||
extern metaforce::ERglBlendFactor g_blendFacDst;
|
||||
extern metaforce::ERglLogicOp g_blendOp;
|
||||
extern bool g_depthCompare;
|
||||
extern bool g_depthUpdate;
|
||||
extern metaforce::ERglEnum g_depthFunc;
|
||||
extern std::array<zeus::CColor, 3> g_colorRegs;
|
||||
extern std::array<zeus::CColor, GX::MAX_KCOLOR> g_kcolors;
|
||||
extern bool g_alphaUpdate;
|
||||
extern std::optional<float> g_dstAlpha;
|
||||
extern zeus::CColor g_clearColor;
|
||||
extern bool g_alphaDiscard;
|
||||
constexpr u32 MaxTextures = GX::MAX_TEXMAP;
|
||||
constexpr u32 MaxTevStages = GX::MAX_TEVSTAGE;
|
||||
constexpr u32 MaxColorChannels = 2; // COLOR0A0, COLOR1A1
|
||||
constexpr u32 MaxTevRegs = 3; // TEVREG0-2
|
||||
constexpr u32 MaxKColors = GX::MAX_KCOLOR;
|
||||
|
||||
struct SChannelState {
|
||||
zeus::CColor matColor;
|
||||
zeus::CColor ambColor;
|
||||
GX::ColorSrc matSrc;
|
||||
template <typename Arg, Arg Default>
|
||||
struct TevPass {
|
||||
Arg a = Default;
|
||||
Arg b = Default;
|
||||
Arg c = Default;
|
||||
Arg d = Default;
|
||||
};
|
||||
extern std::array<SChannelState, 2> g_colorChannels;
|
||||
using LightVariant = std::variant<std::monostate, Light, zeus::CColor>;
|
||||
extern std::array<LightVariant, MaxLights> g_lights;
|
||||
extern std::bitset<MaxLights> g_lightState;
|
||||
|
||||
struct STevStage {
|
||||
metaforce::CTevCombiners::ColorPass colorPass;
|
||||
metaforce::CTevCombiners::AlphaPass alphaPass;
|
||||
metaforce::CTevCombiners::CTevOp colorOp;
|
||||
metaforce::CTevCombiners::CTevOp alphaOp;
|
||||
struct TevOp {
|
||||
GX::TevOp op = GX::TevOp::TEV_ADD;
|
||||
GX::TevBias bias = GX::TevBias::TB_ZERO;
|
||||
GX::TevScale scale = GX::TevScale::CS_SCALE_1;
|
||||
GX::TevRegID outReg = GX::TevRegID::TEVPREV;
|
||||
bool clamp = true;
|
||||
};
|
||||
struct TevStage {
|
||||
TevPass<GX::TevColorArg, GX::CC_ZERO> colorPass;
|
||||
TevPass<GX::TevAlphaArg, GX::CA_ZERO> alphaPass;
|
||||
TevOp colorOp;
|
||||
TevOp alphaOp;
|
||||
GX::TevKColorSel kcSel = GX::TEV_KCSEL_1;
|
||||
GX::TevKAlphaSel kaSel = GX::TEV_KASEL_1;
|
||||
GX::TexCoordID texCoordId = GX::TEXCOORD_NULL;
|
||||
GX::TexMapID texMapId = GX::TEXMAP_NULL;
|
||||
GX::ChannelID channelId = GX::COLOR_NULL;
|
||||
|
||||
constexpr STevStage(const metaforce::CTevCombiners::ColorPass& colPass,
|
||||
const metaforce::CTevCombiners::AlphaPass& alphaPass,
|
||||
const metaforce::CTevCombiners::CTevOp& colorOp,
|
||||
const metaforce::CTevCombiners::CTevOp& alphaOp) noexcept
|
||||
: colorPass(colPass), alphaPass(alphaPass), colorOp(colorOp), alphaOp(alphaOp) {}
|
||||
};
|
||||
struct TextureBind {
|
||||
aurora::gfx::TextureHandle handle;
|
||||
@@ -63,32 +48,72 @@ struct TextureBind {
|
||||
[[nodiscard]] wgpu::SamplerDescriptor get_descriptor() const noexcept;
|
||||
operator bool() const noexcept { return handle; }
|
||||
};
|
||||
// For shader generation
|
||||
struct ColorChannelConfig {
|
||||
GX::ColorSrc matSrc = GX::SRC_REG;
|
||||
GX::ColorSrc ambSrc = GX::SRC_REG;
|
||||
bool lightingEnabled = false;
|
||||
};
|
||||
// For uniform generation
|
||||
struct ColorChannelState {
|
||||
zeus::CColor matColor = zeus::skClear;
|
||||
zeus::CColor ambColor = zeus::skClear;
|
||||
GX::LightMask lightState;
|
||||
};
|
||||
using LightVariant = std::variant<std::monostate, Light, zeus::CColor>;
|
||||
|
||||
constexpr u32 maxTevStages = GX::MAX_TEVSTAGE;
|
||||
extern std::array<std::optional<STevStage>, maxTevStages> g_tevStages;
|
||||
constexpr u32 maxTextures = 8;
|
||||
extern std::array<TextureBind, maxTextures> g_textures;
|
||||
struct GXState {
|
||||
zeus::CMatrix4f mv;
|
||||
zeus::CMatrix4f mvInv;
|
||||
zeus::CMatrix4f proj;
|
||||
metaforce::CFogState fogState;
|
||||
GX::CullMode cullMode = GX::CULL_BACK;
|
||||
GX::BlendMode blendMode = GX::BM_NONE;
|
||||
GX::BlendFactor blendFacSrc = GX::BL_SRCALPHA;
|
||||
GX::BlendFactor blendFacDst = GX::BL_INVSRCALPHA;
|
||||
GX::LogicOp blendOp = GX::LO_CLEAR;
|
||||
GX::Compare depthFunc = GX::LEQUAL;
|
||||
zeus::CColor clearColor = zeus::skBlack;
|
||||
std::optional<float> dstAlpha;
|
||||
std::optional<float> alphaDiscard;
|
||||
std::array<zeus::CColor, MaxTevRegs> colorRegs;
|
||||
std::array<zeus::CColor, GX::MAX_KCOLOR> kcolors;
|
||||
std::array<ColorChannelConfig, MaxColorChannels> colorChannelConfig;
|
||||
std::array<ColorChannelState, MaxColorChannels> colorChannelState;
|
||||
std::array<LightVariant, GX::MaxLights> lights;
|
||||
std::array<TevStage, MaxTevStages> tevStages;
|
||||
std::array<TextureBind, MaxTextures> textures;
|
||||
GX::LightMask lightState;
|
||||
bool depthCompare = true;
|
||||
bool depthUpdate = true;
|
||||
bool alphaUpdate = true;
|
||||
u8 numChans = 0;
|
||||
u8 numIndStages = 0;
|
||||
u8 numTevStages = 0;
|
||||
u8 numTexGens = 0;
|
||||
};
|
||||
extern GXState g_gxState;
|
||||
|
||||
static inline Mat4x4<float> get_combined_matrix() noexcept { return g_proj * g_mv; }
|
||||
static inline Mat4x4<float> get_combined_matrix() noexcept { return g_gxState.proj * g_gxState.mv; }
|
||||
|
||||
void shutdown() noexcept;
|
||||
const TextureBind& get_texture(GX::TexMapID id) noexcept;
|
||||
|
||||
struct ShaderConfig {
|
||||
std::array<std::optional<STevStage>, maxTevStages> tevStages;
|
||||
std::array<GX::ColorSrc, 2> channelMatSrcs;
|
||||
bool alphaDiscard = false;
|
||||
std::array<std::optional<TevStage>, MaxTevStages> tevStages;
|
||||
std::array<ColorChannelConfig, MaxColorChannels> colorChannels;
|
||||
std::optional<float> alphaDiscard;
|
||||
bool denormalizedVertexAttributes = false;
|
||||
bool denormalizedHasNrm = false; // TODO this is a hack
|
||||
};
|
||||
struct PipelineConfig {
|
||||
ShaderConfig shaderConfig;
|
||||
GX::Primitive primitive;
|
||||
metaforce::ERglEnum depthFunc;
|
||||
metaforce::ERglCullMode cullMode;
|
||||
metaforce::ERglBlendMode blendMode;
|
||||
metaforce::ERglBlendFactor blendFacSrc, blendFacDst;
|
||||
metaforce::ERglLogicOp blendOp;
|
||||
GX::Compare depthFunc;
|
||||
GX::CullMode cullMode;
|
||||
GX::BlendMode blendMode;
|
||||
GX::BlendFactor blendFacSrc, blendFacDst;
|
||||
GX::LogicOp blendOp;
|
||||
std::optional<float> dstAlpha;
|
||||
bool depthCompare, depthUpdate, alphaUpdate;
|
||||
};
|
||||
@@ -105,10 +130,10 @@ struct GXBindGroups {
|
||||
// Output info from shader generation
|
||||
struct ShaderInfo {
|
||||
GXBindGroups bindGroups;
|
||||
std::bitset<maxTextures> sampledTextures;
|
||||
std::bitset<4> sampledKcolors;
|
||||
std::bitset<2> sampledColorChannels;
|
||||
std::bitset<3> usesTevReg;
|
||||
std::bitset<MaxTextures> sampledTextures;
|
||||
std::bitset<MaxKColors> sampledKColors;
|
||||
std::bitset<MaxColorChannels> sampledColorChannels;
|
||||
std::bitset<MaxTevRegs> usesTevReg;
|
||||
u32 uniformSize = 0;
|
||||
bool usesVtxColor : 1 = false;
|
||||
bool usesNormal : 1 = false;
|
||||
@@ -143,25 +168,41 @@ struct DlVert {
|
||||
} // namespace aurora::gfx::gx
|
||||
|
||||
namespace aurora {
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const metaforce::CTevCombiners::CTevOp& input) {
|
||||
XXH3_64bits_update(&state, &input.x0_clamp, sizeof(bool));
|
||||
XXH3_64bits_update(&state, &input.x4_op, sizeof(metaforce::CTevCombiners::CTevOp::x4_op));
|
||||
XXH3_64bits_update(&state, &input.x8_bias, sizeof(metaforce::CTevCombiners::CTevOp::x8_bias));
|
||||
XXH3_64bits_update(&state, &input.xc_scale, sizeof(metaforce::CTevCombiners::CTevOp::xc_scale));
|
||||
XXH3_64bits_update(&state, &input.x10_regId, sizeof(metaforce::CTevCombiners::CTevOp::x10_regId));
|
||||
template <typename Arg, Arg Default>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::TevPass<Arg, Default>& input) {
|
||||
XXH3_64bits_update(&state, &input.a, sizeof(Arg));
|
||||
XXH3_64bits_update(&state, &input.b, sizeof(Arg));
|
||||
XXH3_64bits_update(&state, &input.c, sizeof(Arg));
|
||||
XXH3_64bits_update(&state, &input.d, sizeof(Arg));
|
||||
}
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::STevStage& input) {
|
||||
XXH3_64bits_update(&state, &input.colorPass, sizeof(gfx::gx::STevStage::colorPass));
|
||||
XXH3_64bits_update(&state, &input.alphaPass, sizeof(gfx::gx::STevStage::alphaPass));
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::TevOp& input) {
|
||||
XXH3_64bits_update(&state, &input.op, sizeof(gfx::gx::TevOp::op));
|
||||
XXH3_64bits_update(&state, &input.bias, sizeof(gfx::gx::TevOp::bias));
|
||||
XXH3_64bits_update(&state, &input.scale, sizeof(gfx::gx::TevOp::scale));
|
||||
XXH3_64bits_update(&state, &input.outReg, sizeof(gfx::gx::TevOp::outReg));
|
||||
XXH3_64bits_update(&state, &input.clamp, sizeof(bool));
|
||||
}
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::TevStage& input) {
|
||||
xxh3_update(state, input.colorPass);
|
||||
xxh3_update(state, input.alphaPass);
|
||||
xxh3_update(state, input.colorOp);
|
||||
xxh3_update(state, input.alphaOp);
|
||||
XXH3_64bits_update(&state, &input.kcSel, sizeof(gfx::gx::STevStage::kcSel));
|
||||
XXH3_64bits_update(&state, &input.kaSel, sizeof(gfx::gx::STevStage::kaSel));
|
||||
XXH3_64bits_update(&state, &input.texCoordId, sizeof(gfx::gx::STevStage::texCoordId));
|
||||
XXH3_64bits_update(&state, &input.texMapId, sizeof(gfx::gx::STevStage::texMapId));
|
||||
XXH3_64bits_update(&state, &input.channelId, sizeof(gfx::gx::STevStage::channelId));
|
||||
XXH3_64bits_update(&state, &input.kcSel, sizeof(gfx::gx::TevStage::kcSel));
|
||||
XXH3_64bits_update(&state, &input.kaSel, sizeof(gfx::gx::TevStage::kaSel));
|
||||
XXH3_64bits_update(&state, &input.texCoordId, sizeof(gfx::gx::TevStage::texCoordId));
|
||||
XXH3_64bits_update(&state, &input.texMapId, sizeof(gfx::gx::TevStage::texMapId));
|
||||
XXH3_64bits_update(&state, &input.channelId, sizeof(gfx::gx::TevStage::channelId));
|
||||
}
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ColorChannelConfig& input) {
|
||||
XXH3_64bits_update(&state, &input.lightingEnabled, sizeof(gfx::gx::ColorChannelConfig::lightingEnabled));
|
||||
XXH3_64bits_update(&state, &input.matSrc, sizeof(gfx::gx::ColorChannelConfig::matSrc));
|
||||
if (input.lightingEnabled) {
|
||||
// Unused when lighting is disabled
|
||||
XXH3_64bits_update(&state, &input.ambSrc, sizeof(gfx::gx::ColorChannelConfig::ambSrc));
|
||||
}
|
||||
}
|
||||
template <>
|
||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input) {
|
||||
@@ -171,10 +212,12 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input)
|
||||
}
|
||||
xxh3_update(state, *item);
|
||||
}
|
||||
for (const auto& item : input.channelMatSrcs) {
|
||||
XXH3_64bits_update(&state, &item, sizeof(GX::ColorSrc));
|
||||
for (const auto& item : input.colorChannels) {
|
||||
xxh3_update(state, item);
|
||||
}
|
||||
if (input.alphaDiscard) {
|
||||
XXH3_64bits_update(&state, &*input.alphaDiscard, sizeof(float));
|
||||
}
|
||||
XXH3_64bits_update(&state, &input.alphaDiscard, sizeof(bool));
|
||||
XXH3_64bits_update(&state, &input.denormalizedVertexAttributes, sizeof(bool));
|
||||
XXH3_64bits_update(&state, &input.denormalizedHasNrm, sizeof(bool));
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ static logvisor::Module Log("aurora::gfx::gx");
|
||||
|
||||
std::unordered_map<ShaderRef, std::pair<wgpu::ShaderModule, gx::ShaderInfo>> g_gxCachedShaders;
|
||||
|
||||
static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const STevStage& stage, ShaderInfo& info) {
|
||||
static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const TevStage& stage, ShaderInfo& info) {
|
||||
switch (arg) {
|
||||
case GX::CC_CPREV:
|
||||
return "prev.rgb";
|
||||
@@ -105,64 +105,64 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const STe
|
||||
case GX::TEV_KCSEL_1_8:
|
||||
return "(1.0/8.0)";
|
||||
case GX::TEV_KCSEL_K0:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.rgb";
|
||||
case GX::TEV_KCSEL_K1:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.rgb";
|
||||
case GX::TEV_KCSEL_K2:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.rgb";
|
||||
case GX::TEV_KCSEL_K3:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.rgb";
|
||||
case GX::TEV_KCSEL_K0_R:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.r";
|
||||
case GX::TEV_KCSEL_K1_R:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.r";
|
||||
case GX::TEV_KCSEL_K2_R:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.r";
|
||||
case GX::TEV_KCSEL_K3_R:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.r";
|
||||
case GX::TEV_KCSEL_K0_G:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.g";
|
||||
case GX::TEV_KCSEL_K1_G:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.g";
|
||||
case GX::TEV_KCSEL_K2_G:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.g";
|
||||
case GX::TEV_KCSEL_K3_G:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.g";
|
||||
case GX::TEV_KCSEL_K0_B:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.b";
|
||||
case GX::TEV_KCSEL_K1_B:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.b";
|
||||
case GX::TEV_KCSEL_K2_B:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.b";
|
||||
case GX::TEV_KCSEL_K3_B:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.b";
|
||||
case GX::TEV_KCSEL_K0_A:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.a";
|
||||
case GX::TEV_KCSEL_K1_A:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.a";
|
||||
case GX::TEV_KCSEL_K2_A:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.a";
|
||||
case GX::TEV_KCSEL_K3_A:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.a";
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid kcSel {}"), stage.kcSel);
|
||||
@@ -177,7 +177,7 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const STe
|
||||
}
|
||||
}
|
||||
|
||||
static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const STevStage& stage, ShaderInfo& info) {
|
||||
static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const TevStage& stage, ShaderInfo& info) {
|
||||
switch (arg) {
|
||||
case GX::CA_APREV:
|
||||
return "prev.a";
|
||||
@@ -232,52 +232,52 @@ static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const STe
|
||||
case GX::TEV_KASEL_1_8:
|
||||
return "(1.0/8.0)";
|
||||
case GX::TEV_KASEL_K0_R:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.r";
|
||||
case GX::TEV_KASEL_K1_R:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.r";
|
||||
case GX::TEV_KASEL_K2_R:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.r";
|
||||
case GX::TEV_KASEL_K3_R:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.r";
|
||||
case GX::TEV_KASEL_K0_G:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.g";
|
||||
case GX::TEV_KASEL_K1_G:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.g";
|
||||
case GX::TEV_KASEL_K2_G:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.g";
|
||||
case GX::TEV_KASEL_K3_G:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.g";
|
||||
case GX::TEV_KASEL_K0_B:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.b";
|
||||
case GX::TEV_KASEL_K1_B:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.b";
|
||||
case GX::TEV_KASEL_K2_B:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.b";
|
||||
case GX::TEV_KASEL_K3_B:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.b";
|
||||
case GX::TEV_KASEL_K0_A:
|
||||
info.sampledKcolors.set(0);
|
||||
info.sampledKColors.set(0);
|
||||
return "ubuf.kcolor0.a";
|
||||
case GX::TEV_KASEL_K1_A:
|
||||
info.sampledKcolors.set(1);
|
||||
info.sampledKColors.set(1);
|
||||
return "ubuf.kcolor1.a";
|
||||
case GX::TEV_KASEL_K2_A:
|
||||
info.sampledKcolors.set(2);
|
||||
info.sampledKColors.set(2);
|
||||
return "ubuf.kcolor2.a";
|
||||
case GX::TEV_KASEL_K3_A:
|
||||
info.sampledKcolors.set(3);
|
||||
info.sampledKColors.set(3);
|
||||
return "ubuf.kcolor3.a";
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid kaSel {}"), stage.kaSel);
|
||||
@@ -352,34 +352,34 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
||||
break;
|
||||
}
|
||||
Log.report(logvisor::Info, FMT_STRING(" tevStages[{}]:"), i);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_a: {}"), stage->colorPass.x0_a);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_b: {}"), stage->colorPass.x4_b);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_c: {}"), stage->colorPass.x8_c);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_d: {}"), stage->colorPass.xc_d);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_a: {}"), stage->alphaPass.x0_a);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_b: {}"), stage->alphaPass.x4_b);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_c: {}"), stage->alphaPass.x8_c);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_d: {}"), stage->alphaPass.xc_d);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_clamp: {}"), stage->colorOp.x0_clamp);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_op: {}"), stage->colorOp.x4_op);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_bias: {}"), stage->colorOp.x8_bias);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_scale: {}"), stage->colorOp.xc_scale);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_reg_id: {}"), stage->colorOp.x10_regId);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_clamp: {}"), stage->alphaOp.x0_clamp);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_op: {}"), stage->alphaOp.x4_op);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_bias: {}"), stage->alphaOp.x8_bias);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_scale: {}"), stage->alphaOp.xc_scale);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_reg_id: {}"), stage->alphaOp.x10_regId);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_a: {}"), stage->colorPass.a);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_b: {}"), stage->colorPass.b);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_c: {}"), stage->colorPass.c);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_d: {}"), stage->colorPass.d);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_a: {}"), stage->alphaPass.a);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_b: {}"), stage->alphaPass.b);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_c: {}"), stage->alphaPass.c);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_d: {}"), stage->alphaPass.d);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_clamp: {}"), stage->colorOp.clamp);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_op: {}"), stage->colorOp.op);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_bias: {}"), stage->colorOp.bias);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_scale: {}"), stage->colorOp.scale);
|
||||
Log.report(logvisor::Info, FMT_STRING(" color_op_reg_id: {}"), stage->colorOp.outReg);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_clamp: {}"), stage->alphaOp.clamp);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_op: {}"), stage->alphaOp.op);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_bias: {}"), stage->alphaOp.bias);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_scale: {}"), stage->alphaOp.scale);
|
||||
Log.report(logvisor::Info, FMT_STRING(" alpha_op_reg_id: {}"), stage->alphaOp.outReg);
|
||||
Log.report(logvisor::Info, FMT_STRING(" kc_sel: {}"), stage->kcSel);
|
||||
Log.report(logvisor::Info, FMT_STRING(" ka_sel: {}"), stage->kaSel);
|
||||
Log.report(logvisor::Info, FMT_STRING(" texCoordId: {}"), stage->texCoordId);
|
||||
Log.report(logvisor::Info, FMT_STRING(" texMapId: {}"), stage->texMapId);
|
||||
Log.report(logvisor::Info, FMT_STRING(" channelId: {}"), stage->channelId);
|
||||
}
|
||||
for (int i = 0; i < config.channelMatSrcs.size(); ++i) {
|
||||
Log.report(logvisor::Info, FMT_STRING(" channelMatSrcs[{}]: {}"), i, config.channelMatSrcs[i]);
|
||||
}
|
||||
Log.report(logvisor::Info, FMT_STRING(" alphaDiscard: {}"), config.alphaDiscard);
|
||||
// for (int i = 0; i < config.channelMatSrcs.size(); ++i) {
|
||||
// Log.report(logvisor::Info, FMT_STRING(" channelMatSrcs[{}]: {}"), i, config.channelMatSrcs[i]);
|
||||
// }
|
||||
// Log.report(logvisor::Info, FMT_STRING(" alphaDiscard: {}"), config.alphaDiscard);
|
||||
Log.report(logvisor::Info, FMT_STRING(" denormalizedVertexAttributes: {}"), config.denormalizedVertexAttributes);
|
||||
}
|
||||
|
||||
@@ -396,14 +396,16 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
||||
if (config.denormalizedVertexAttributes) {
|
||||
vtxInAttrs += "\n @location(0) in_pos: vec3<f32>";
|
||||
vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;";
|
||||
vtxXfrAttrsPre += "\n var obj_pos = vec4<f32>(in_pos, 1.0);"
|
||||
vtxXfrAttrsPre +=
|
||||
"\n var obj_pos = vec4<f32>(in_pos, 1.0);"
|
||||
"\n var mv_pos = ubuf.mv * obj_pos;"
|
||||
"\n out.pos = ubuf.proj * mv_pos;";
|
||||
if (config.denormalizedHasNrm) {
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) nrm: vec3<f32>;"), locIdx);
|
||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_nrm: vec3<f32>"), ++locIdx);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.nrm = in_nrm;"));
|
||||
vtxXfrAttrsPre += "\n var obj_norm = vec4<f32>(in_nrm, 0.0);"
|
||||
vtxXfrAttrsPre +=
|
||||
"\n var obj_norm = vec4<f32>(in_nrm, 0.0);"
|
||||
"\n var mv_norm = ubuf.mv_inv * obj_norm;";
|
||||
info.usesNormal = true;
|
||||
}
|
||||
@@ -429,7 +431,8 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
||||
"\n , @location(1) in_uv_0_4_idx: vec4<i32>"
|
||||
"\n , @location(2) in_uv_5_7_idx: vec4<i32>";
|
||||
vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;";
|
||||
vtxXfrAttrsPre += "\n var obj_pos = vec4<f32>(v_verts.data[in_pos_nrm_idx[0]].xyz, 1.0);"
|
||||
vtxXfrAttrsPre +=
|
||||
"\n var obj_pos = vec4<f32>(v_verts.data[in_pos_nrm_idx[0]].xyz, 1.0);"
|
||||
"\n var obj_norm = vec4<f32>(v_verts.data[in_pos_nrm_idx[1]].xyz, 0.0);"
|
||||
"\n var mv_pos = ubuf.mv * obj_pos;"
|
||||
"\n var mv_norm = ubuf.mv_inv * obj_norm;"
|
||||
@@ -444,7 +447,7 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
||||
}
|
||||
{
|
||||
std::string outReg;
|
||||
switch (stage->colorOp.x10_regId) {
|
||||
switch (stage->colorOp.outReg) {
|
||||
case GX::TevRegID::TEVPREV:
|
||||
outReg = "prev";
|
||||
break;
|
||||
@@ -461,23 +464,21 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
||||
info.usesTevReg.set(2);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("TODO: colorOp outReg {}"), stage->colorOp.x10_regId);
|
||||
Log.report(logvisor::Fatal, FMT_STRING("TODO: colorOp outReg {}"), stage->colorOp.outReg);
|
||||
}
|
||||
std::string op =
|
||||
fmt::format(FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||
color_arg_reg(stage->colorPass.x0_a, idx, *stage, info),
|
||||
color_arg_reg(stage->colorPass.x4_b, idx, *stage, info),
|
||||
color_arg_reg(stage->colorPass.x8_c, idx, *stage, info),
|
||||
color_arg_reg(stage->colorPass.xc_d, idx, *stage, info), tev_op(stage->colorOp.x4_op),
|
||||
tev_bias(stage->colorOp.x8_bias), tev_scale(stage->colorOp.xc_scale));
|
||||
if (stage->colorOp.x0_clamp) {
|
||||
std::string op = fmt::format(
|
||||
FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||
color_arg_reg(stage->colorPass.a, idx, *stage, info), color_arg_reg(stage->colorPass.b, idx, *stage, info),
|
||||
color_arg_reg(stage->colorPass.c, idx, *stage, info), color_arg_reg(stage->colorPass.d, idx, *stage, info),
|
||||
tev_op(stage->colorOp.op), tev_bias(stage->colorOp.bias), tev_scale(stage->colorOp.scale));
|
||||
if (stage->colorOp.clamp) {
|
||||
op = fmt::format(FMT_STRING("clamp(vec3<f32>({}), vec3<f32>(0.0), vec3<f32>(1.0))"), op);
|
||||
}
|
||||
fragmentFn += fmt::format(FMT_STRING("\n {0} = vec4<f32>({1}, {0}.a);"), outReg, op);
|
||||
}
|
||||
{
|
||||
std::string outReg;
|
||||
switch (stage->alphaOp.x10_regId) {
|
||||
switch (stage->alphaOp.outReg) {
|
||||
case GX::TevRegID::TEVPREV:
|
||||
outReg = "prev.a";
|
||||
break;
|
||||
@@ -494,16 +495,14 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
||||
info.usesTevReg.set(2);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("TODO: alphaOp outReg {}"), stage->alphaOp.x10_regId);
|
||||
Log.report(logvisor::Fatal, FMT_STRING("TODO: alphaOp outReg {}"), stage->alphaOp.outReg);
|
||||
}
|
||||
std::string op =
|
||||
fmt::format(FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||
alpha_arg_reg(stage->alphaPass.x0_a, idx, *stage, info),
|
||||
alpha_arg_reg(stage->alphaPass.x4_b, idx, *stage, info),
|
||||
alpha_arg_reg(stage->alphaPass.x8_c, idx, *stage, info),
|
||||
alpha_arg_reg(stage->alphaPass.xc_d, idx, *stage, info), tev_op(stage->alphaOp.x4_op),
|
||||
tev_bias(stage->alphaOp.x8_bias), tev_scale(stage->alphaOp.xc_scale));
|
||||
if (stage->alphaOp.x0_clamp) {
|
||||
std::string op = fmt::format(
|
||||
FMT_STRING("({3} {4} ((1.0 - {2}) * {0} + {2} * {1}){5}){6}"),
|
||||
alpha_arg_reg(stage->alphaPass.a, idx, *stage, info), alpha_arg_reg(stage->alphaPass.b, idx, *stage, info),
|
||||
alpha_arg_reg(stage->alphaPass.c, idx, *stage, info), alpha_arg_reg(stage->alphaPass.d, idx, *stage, info),
|
||||
tev_op(stage->alphaOp.op), tev_bias(stage->alphaOp.bias), tev_scale(stage->alphaOp.scale));
|
||||
if (stage->alphaOp.clamp) {
|
||||
op = fmt::format(FMT_STRING("clamp({}, 0.0, 1.0)"), op);
|
||||
}
|
||||
fragmentFn += fmt::format(FMT_STRING("\n {0} = {1};"), outReg, op);
|
||||
@@ -518,19 +517,7 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var tevreg{0} = ubuf.tevreg{0};"), i);
|
||||
info.uniformSize += 16;
|
||||
}
|
||||
if (info.sampledColorChannels.any()) {
|
||||
uniformPre += "\n"
|
||||
"struct Light {\n"
|
||||
" pos: vec3<f32>;\n"
|
||||
" dir: vec3<f32>;\n"
|
||||
" color: vec4<f32>;\n"
|
||||
" lin_att: vec3<f32>;\n"
|
||||
" ang_att: vec3<f32>;\n"
|
||||
"};";
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n lights: array<Light, {}>;"), MaxLights);
|
||||
uniBufAttrs += "\n lighting_ambient: vec4<f32>;";
|
||||
info.uniformSize += (80 * MaxLights) + 16;
|
||||
}
|
||||
bool addedLightStruct = false;
|
||||
for (int i = 0; i < info.sampledColorChannels.size(); ++i) {
|
||||
if (!info.sampledColorChannels.test(i)) {
|
||||
continue;
|
||||
@@ -540,26 +527,30 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_mat: vec4<f32>;"), i);
|
||||
info.uniformSize += 32;
|
||||
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), locIdx++, i);
|
||||
|
||||
if (config.channelMatSrcs[i] == GX::SRC_VTX) {
|
||||
if (config.denormalizedVertexAttributes) {
|
||||
if (!info.usesVtxColor) {
|
||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_clr: vec4<f32>"), locIdx);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = in_clr;"), i);
|
||||
}
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("SRC_VTX unsupported with normalized vertex attributes"));
|
||||
if (config.colorChannels[i].lightingEnabled) {
|
||||
if (!addedLightStruct) {
|
||||
uniformPre +=
|
||||
"\n"
|
||||
"struct Light {\n"
|
||||
" pos: vec3<f32>;\n"
|
||||
" dir: vec3<f32>;\n"
|
||||
" color: vec4<f32>;\n"
|
||||
" lin_att: vec3<f32>;\n"
|
||||
" ang_att: vec3<f32>;\n"
|
||||
"};";
|
||||
addedLightStruct = true;
|
||||
}
|
||||
info.usesVtxColor = true;
|
||||
} else {
|
||||
// TODO only perform lighting on CC0 when enabled
|
||||
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n lights{}: array<Light, {}>;"), i, GX::MaxLights);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n lighting_ambient{}: vec4<f32>;"), i);
|
||||
info.uniformSize += (80 * GX::MaxLights) + 16;
|
||||
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), locIdx++, i);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING(R"""(
|
||||
{{
|
||||
var lighting = ubuf.lighting_ambient + ubuf.cc{0}_amb;
|
||||
var lighting = ubuf.lighting_ambient{0} + ubuf.cc{0}_amb;
|
||||
for (var i = 0; i < {1}; i = i + 1) {{
|
||||
var light = ubuf.lights[i];
|
||||
var light = ubuf.lights{0}[i];
|
||||
var delta = mv_pos.xyz - light.pos;
|
||||
var dist = length(delta);
|
||||
var delta_norm = delta / dist;
|
||||
@@ -575,12 +566,27 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
||||
lighting = lighting + vec4<f32>(this_color, 0.0);
|
||||
}}
|
||||
out.cc{0} = clamp(lighting, vec4<f32>(0.0), vec4<f32>(1.0));
|
||||
}})"""), i, MaxLights);
|
||||
}})"""),
|
||||
i, GX::MaxLights);
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||
} else if (config.colorChannels[i].matSrc == GX::SRC_VTX) {
|
||||
if (config.denormalizedVertexAttributes) {
|
||||
if (!info.usesVtxColor) {
|
||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_clr: vec4<f32>"), locIdx);
|
||||
}
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), locIdx++, i);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = in_clr;"), i);
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("SRC_VTX unsupported with normalized vertex attributes"));
|
||||
}
|
||||
info.usesVtxColor = true;
|
||||
} else {
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = ubuf.cc{0}_mat;"), i);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < info.sampledKcolors.size(); ++i) {
|
||||
if (!info.sampledKcolors.test(i)) {
|
||||
for (int i = 0; i < info.sampledKColors.size(); ++i) {
|
||||
if (!info.sampledKColors.test(i)) {
|
||||
continue;
|
||||
}
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n kcolor{}: vec4<f32>;"), i);
|
||||
@@ -622,6 +628,9 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
||||
FMT_STRING("\n var sampled{0} = textureSampleBias(tex{0}, tex{0}_samp, in.tex{0}_uv, ubuf.tex{0}_lod);"), i);
|
||||
locIdx++;
|
||||
}
|
||||
if (config.alphaDiscard) {
|
||||
fragmentFn += fmt::format(FMT_STRING("\n if (prev.a < {}f) {{ discard; }}"), *config.alphaDiscard);
|
||||
}
|
||||
|
||||
const auto shaderSource =
|
||||
fmt::format(FMT_STRING(R"""({uniformPre}
|
||||
|
||||
@@ -54,10 +54,10 @@ static const std::vector<zeus::CVector3f>* nrmData;
|
||||
static const std::vector<Vec2<float>>* tex0TcData;
|
||||
static const std::vector<Vec2<float>>* tcData;
|
||||
|
||||
void set_vertex_buffer(const std::vector<zeus::CVector3f>* data) noexcept { vtxData = data; }
|
||||
void set_normal_buffer(const std::vector<zeus::CVector3f>* norm) noexcept { nrmData = norm; }
|
||||
void set_tex0_tc_buffer(const std::vector<Vec2<float>>* tcs) noexcept { tex0TcData = tcs; }
|
||||
void set_tc_buffer(const std::vector<Vec2<float>>* tcs) noexcept { tcData = tcs; }
|
||||
// void set_vertex_buffer(const std::vector<zeus::CVector3f>* data) noexcept { vtxData = data; }
|
||||
// void set_normal_buffer(const std::vector<zeus::CVector3f>* norm) noexcept { nrmData = norm; }
|
||||
// void set_tex0_tc_buffer(const std::vector<Vec2<float>>* tcs) noexcept { tex0TcData = tcs; }
|
||||
// void set_tc_buffer(const std::vector<Vec2<float>>* tcs) noexcept { tcData = tcs; }
|
||||
|
||||
enum class VertexFormat : u8 {
|
||||
F32F32,
|
||||
@@ -233,3 +233,27 @@ void render(const State& state, const DrawData& data, const wgpu::RenderPassEnco
|
||||
pass.DrawIndexed(data.indexCount);
|
||||
}
|
||||
} // namespace aurora::gfx::model
|
||||
|
||||
void GXSetArray(GX::Attr attr, const void* data, u8 stride) noexcept {
|
||||
switch (attr) {
|
||||
case GX::VA_POS:
|
||||
aurora::gfx::model::vtxData = static_cast<const std::vector<zeus::CVector3f>*>(data);
|
||||
break;
|
||||
case GX::VA_NRM:
|
||||
aurora::gfx::model::nrmData = static_cast<const std::vector<zeus::CVector3f>*>(data);
|
||||
break;
|
||||
case GX::VA_TEX0:
|
||||
aurora::gfx::model::tex0TcData = static_cast<const std::vector<aurora::Vec2<float>>*>(data);
|
||||
break;
|
||||
case GX::VA_TEX1:
|
||||
aurora::gfx::model::tcData = static_cast<const std::vector<aurora::Vec2<float>>*>(data);
|
||||
break;
|
||||
default:
|
||||
aurora::gfx::model::Log.report(logvisor::Fatal, FMT_STRING("GXSetArray: invalid attr {}"), attr);
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
void GXCallDisplayList(const void* data, u32 nbytes) noexcept {
|
||||
aurora::gfx::model::queue_surface(static_cast<const u8*>(data), nbytes);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user