diff --git a/.gitmodules b/.gitmodules index 59d2c0ac9..42a3671bf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -42,18 +42,12 @@ path = extern/zeus url = ../zeus.git branch = master -[submodule "extern/imgui"] - path = extern/imgui - url = https://github.com/ocornut/imgui.git -[submodule "extern/SDL"] - path = extern/SDL - url = https://github.com/libsdl-org/SDL.git -[submodule "extern/dawn"] - path = extern/dawn - url = https://github.com/encounter/dawn-cmake.git [submodule "extern/nativefiledialog"] path = extern/nativefiledialog url = https://github.com/mlabbe/nativefiledialog.git [submodule "extern/optick"] path = extern/optick url = https://github.com/AxioDL/optick.git +[submodule "extern/aurora"] + path = extern/aurora + url = https://github.com/encounter/aurora.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 786b2da06..c5a88e031 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -365,7 +365,6 @@ if(NOT TARGET atdna) endif() add_subdirectory(NESEmulator EXCLUDE_FROM_ALL) -add_subdirectory(aurora) add_subdirectory(Runtime) add_subdirectory(gbalink EXCLUDE_FROM_ALL) diff --git a/NESEmulator/CNESEmulator.cpp b/NESEmulator/CNESEmulator.cpp index 09cfa0fe9..8fe6fd040 100644 --- a/NESEmulator/CNESEmulator.cpp +++ b/NESEmulator/CNESEmulator.cpp @@ -604,9 +604,9 @@ void CNESEmulator::ProcessUserInput(const CFinalInput& input, int) { if (GetPasswordEntryState() != EPasswordEntryState::NotPasswordScreen) { // Don't swap A/B - inValReads[BUTTON_A] = input.DA() || input.DSpecialKey(aurora::SpecialKey::Enter) || + inValReads[BUTTON_A] = input.DA() || input.DSpecialKey(ESpecialKey::Enter) || input.DMouseButton(EMouseButton::Primary); - inValReads[BUTTON_B] = input.DB() || input.DSpecialKey(aurora::SpecialKey::Esc); + inValReads[BUTTON_B] = input.DB() || input.DSpecialKey(ESpecialKey::Esc); } else { // Prime controls (B jumps, A shoots) inValReads[BUTTON_B] = input.DA() || input.DY() || input.DMouseButton(EMouseButton::Primary); @@ -617,8 +617,8 @@ void CNESEmulator::ProcessUserInput(const CFinalInput& input, int) { inValReads[BUTTON_DOWN] = input.DDPDown() || input.DLADown(); inValReads[BUTTON_LEFT] = input.DDPLeft() || input.DLALeft(); inValReads[BUTTON_RIGHT] = input.DDPRight() || input.DLARight(); - inValReads[BUTTON_SELECT] = input.DZ() || input.DSpecialKey(aurora::SpecialKey::Tab); - inValReads[BUTTON_START] = input.DStart() || input.DSpecialKey(aurora::SpecialKey::Esc); + inValReads[BUTTON_SELECT] = input.DZ() || input.DSpecialKey(ESpecialKey::Tab); + inValReads[BUTTON_START] = input.DStart() || input.DSpecialKey(ESpecialKey::Esc); } bool CNESEmulator::CheckForGameOver(const u8* vram, u8* passwordOut) { diff --git a/NESEmulator/CNESEmulator.hpp b/NESEmulator/CNESEmulator.hpp index 47c2986bc..777ebc0fe 100644 --- a/NESEmulator/CNESEmulator.hpp +++ b/NESEmulator/CNESEmulator.hpp @@ -35,7 +35,7 @@ private: zeus::CColor m_color; }; - aurora::gfx::TextureHandle m_texture; + GXTexObj m_texture; // boo::ObjToken m_uniBuf; // boo::ObjToken m_vbo; // boo::ObjToken m_shadBind; diff --git a/Runtime/AutoMapper/CAutoMapper.cpp b/Runtime/AutoMapper/CAutoMapper.cpp index d16f3468d..5f33b51de 100644 --- a/Runtime/AutoMapper/CAutoMapper.cpp +++ b/Runtime/AutoMapper/CAutoMapper.cpp @@ -788,10 +788,10 @@ void CAutoMapper::SetShouldRotatingSoundBePlaying(bool shouldBePlaying) { void CAutoMapper::ProcessMapScreenInput(const CFinalInput& input, CStateManager& mgr) { zeus::CMatrix3f camRot = xa8_renderStates[0].x8_camOrientation.toTransform().buildMatrix3f(); if (x1bc_state == EAutoMapperState::MapScreen) { - if ((input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter)) && x328_ == 0 && HasCurrentMapUniverseWorld()) + if ((input.PA() || input.PSpecialKey(ESpecialKey::Enter)) && x328_ == 0 && HasCurrentMapUniverseWorld()) BeginMapperStateTransition(EAutoMapperState::MapScreenUniverse, mgr); } else if (x1bc_state == EAutoMapperState::MapScreenUniverse && - (input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter))) { + (input.PA() || input.PSpecialKey(ESpecialKey::Enter))) { const CMapUniverse::CMapWorldData& mapuWld = x8_mapu->GetMapWorldData(x9c_worldIdx); zeus::CVector3f pointLocal = mapuWld.GetWorldTransform().inverse() * xa8_renderStates[0].x20_areaPoint; if (mapuWld.GetWorldAssetId() != g_GameState->CurrentWorldAssetId()) { @@ -806,7 +806,7 @@ void CAutoMapper::ProcessMapScreenInput(const CFinalInput& input, CStateManager& } x2f4_aButtonPos = 0; - if (input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter)) + if (input.PA() || input.PSpecialKey(ESpecialKey::Enter)) x2f4_aButtonPos = 1; if (IsInPlayerControlState()) { @@ -1083,8 +1083,8 @@ void CAutoMapper::ProcessControllerInput(const CFinalInput& input, CStateManager } } - if (input.PZ() || input.PSpecialKey(aurora::SpecialKey::Tab) || input.PB() || - input.PSpecialKey(aurora::SpecialKey::Esc)) { + if (input.PZ() || input.PSpecialKey(ESpecialKey::Tab) || input.PB() || + input.PSpecialKey(ESpecialKey::Esc)) { if (x328_ == 0) { if (CanLeaveMapScreenInternal(mgr)) { LeaveMapScreen(mgr); diff --git a/Runtime/AutoMapper/CMapArea.cpp b/Runtime/AutoMapper/CMapArea.cpp index 8168ad9e6..7fd5283b2 100644 --- a/Runtime/AutoMapper/CMapArea.cpp +++ b/Runtime/AutoMapper/CMapArea.cpp @@ -197,10 +197,10 @@ void CMapArea::CMapAreaSurface::PostConstruct(const u8* buf, std::vector& i CMemoryInStream r(x18_surfOffset, INT_MAX, CMemoryInStream::EOwnerShip::NotOwned); u32 primCount = r.ReadLong(); for (u32 i = 0; i < primCount; ++i) { - GX::Primitive prim = GX::Primitive(r.ReadLong()); + GXPrimitive prim = GXPrimitive(r.ReadLong()); u32 count = r.ReadLong(); switch (prim) { - case GX::Primitive::TRIANGLES: { + case GX_TRIANGLES: { for (u32 v = 0; v < count; v += 3) { if (!start) { index.push_back(index.back()); @@ -216,7 +216,7 @@ void CMapArea::CMapAreaSurface::PostConstruct(const u8* buf, std::vector& i } break; } - case GX::Primitive::TRIANGLESTRIP: { + case GX_TRIANGLESTRIP: { if (!start) { index.push_back(index.back()); index.push_back(r.ReadUint8()); @@ -231,7 +231,7 @@ void CMapArea::CMapAreaSurface::PostConstruct(const u8* buf, std::vector& i index.push_back(index.back()); break; } - case GX::Primitive::TRIANGLEFAN: { + case GX_TRIANGLEFAN: { u8 firstVert = r.ReadUint8(); if (!start) { index.push_back(index.back()); diff --git a/Runtime/AutoMapper/CMapArea.hpp b/Runtime/AutoMapper/CMapArea.hpp index 703b2da15..642ad0b97 100644 --- a/Runtime/AutoMapper/CMapArea.hpp +++ b/Runtime/AutoMapper/CMapArea.hpp @@ -27,8 +27,8 @@ public: struct Instance { CMapSurfaceShader m_surfacePrims; std::vector m_linePrims; - Instance(aurora::ArrayRef vbo, - aurora::ArrayRef ibo) + Instance(std::vector vbo, + std::vector ibo) : m_surfacePrims(vbo, ibo) {} Instance(Instance&&) = default; Instance& operator=(Instance&&) = default; diff --git a/Runtime/AutoMapper/CMappableObject.cpp b/Runtime/AutoMapper/CMappableObject.cpp index 609da4ab3..509dd14f7 100644 --- a/Runtime/AutoMapper/CMappableObject.cpp +++ b/Runtime/AutoMapper/CMappableObject.cpp @@ -112,19 +112,19 @@ void CMappableObject::Draw(int curArea, const CMapWorldInfo& mwInfo, float alpha SCOPED_GRAPHICS_DEBUG_GROUP("CMappableObject::Draw", zeus::skCyan); if (IsDoorType(x0_type)) { std::pair colors = GetDoorColors(curArea, mwInfo, alpha); - if (m_doorSurface) // TODO - for (int s = 0; s < 6; ++s) { - DoorSurface& ds = *m_doorSurface; - ds.m_surface.draw(colors.first, s * 4, 4); - CLineRenderer& line = ds.m_outline; - const u16* baseIdx = &skDoorIndices[s * 4]; - line.Reset(); - line.AddVertex(skDoorVerts[baseIdx[0]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[1]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[3]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[2]], colors.second, 1.f); - line.Render(); - } + // TODO +// for (int s = 0; s < 6; ++s) { +// DoorSurface& ds = *m_doorSurface; +// ds.m_surface.draw(colors.first, s * 4, 4); +// CLineRenderer& line = ds.m_outline; +// const u16* baseIdx = &skDoorIndices[s * 4]; +// line.Reset(); +// line.AddVertex(skDoorVerts[baseIdx[0]], colors.second, 1.f); +// line.AddVertex(skDoorVerts[baseIdx[1]], colors.second, 1.f); +// line.AddVertex(skDoorVerts[baseIdx[3]], colors.second, 1.f); +// line.AddVertex(skDoorVerts[baseIdx[2]], colors.second, 1.f); +// line.Render(); +// } } else { CAssetId iconRes; zeus::CColor iconColor = zeus::skWhite; @@ -184,16 +184,16 @@ void CMappableObject::Draw(int curArea, const CMapWorldInfo& mwInfo, float alpha void CMappableObject::DrawDoorSurface(int curArea, const CMapWorldInfo& mwInfo, float alpha, int surfIdx, bool needsVtxLoad) { std::pair colors = GetDoorColors(curArea, mwInfo, alpha); - DoorSurface& ds = *m_doorSurface; - ds.m_surface.draw(colors.first, surfIdx * 4, 4); - CLineRenderer& line = ds.m_outline; - const u16* baseIdx = &skDoorIndices[surfIdx * 4]; - line.Reset(); - line.AddVertex(skDoorVerts[baseIdx[0]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[1]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[3]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[2]], colors.second, 1.f); - line.Render(); +// DoorSurface& ds = *m_doorSurface; +// ds.m_surface.draw(colors.first, surfIdx * 4, 4); +// CLineRenderer& line = ds.m_outline; +// const u16* baseIdx = &skDoorIndices[surfIdx * 4]; +// line.Reset(); +// line.AddVertex(skDoorVerts[baseIdx[0]], colors.second, 1.f); +// line.AddVertex(skDoorVerts[baseIdx[1]], colors.second, 1.f); +// line.AddVertex(skDoorVerts[baseIdx[3]], colors.second, 1.f); +// line.AddVertex(skDoorVerts[baseIdx[2]], colors.second, 1.f); +// line.Render(); } zeus::CVector3f CMappableObject::BuildSurfaceCenterPoint(int surfIdx) const { diff --git a/Runtime/AutoMapper/CMappableObject.hpp b/Runtime/AutoMapper/CMappableObject.hpp index 53809fe7b..675e440a5 100644 --- a/Runtime/AutoMapper/CMappableObject.hpp +++ b/Runtime/AutoMapper/CMappableObject.hpp @@ -58,14 +58,14 @@ private: u32 xc_; zeus::CTransform x10_transform; - struct DoorSurface { - CMapSurfaceShader m_surface; - CLineRenderer m_outline; - explicit DoorSurface() - : m_surface(skDoorVerts, skDoorIndices) - , m_outline(CLineRenderer::EPrimitiveMode::LineLoop, 5, {}, false, false, true) {} - }; - std::optional m_doorSurface; +// struct DoorSurface { +// CMapSurfaceShader m_surface; +// CLineRenderer m_outline; +// explicit DoorSurface() +// : m_surface(skDoorVerts, skDoorIndices) +// , m_outline(CLineRenderer::EPrimitiveMode::LineLoop, 5, {}, false, false, true) {} +// }; +// std::optional m_doorSurface; zeus::CTransform AdjustTransformForType() const; std::pair GetDoorColors(int idx, const CMapWorldInfo& mwInfo, float alpha) const; @@ -83,7 +83,7 @@ public: bool IsDoorConnectedToVisitedArea(const CStateManager&) const; bool IsVisibleToAutoMapper(bool worldVis, const CMapWorldInfo& mwInfo) const; bool GetIsSeen() const; - void CreateDoorSurface() { m_doorSurface.emplace(); } +// void CreateDoorSurface() { m_doorSurface.emplace(); } static void ReadAutoMapperTweaks(const ITweakAutoMapper&); static bool GetTweakIsMapVisibilityCheat(); diff --git a/Runtime/CGameOptions.cpp b/Runtime/CGameOptions.cpp index 3f3db333d..8f6dbb68b 100644 --- a/Runtime/CGameOptions.cpp +++ b/Runtime/CGameOptions.cpp @@ -446,7 +446,7 @@ void CGameOptions::TryRestoreDefaults(const CFinalInput& input, int category, in if (options.second[option].option != EGameOption::RestoreDefaults) return; - if (!forceRestore && !input.PA() && !input.PSpecialKey(aurora::SpecialKey::Enter)) + if (!forceRestore && !input.PA() && !input.PSpecialKey(ESpecialKey::Enter)) return; if (frontend) { diff --git a/Runtime/CMain.cpp b/Runtime/CMain.cpp index db081deef..3947e8391 100644 --- a/Runtime/CMain.cpp +++ b/Runtime/CMain.cpp @@ -29,8 +29,8 @@ //#include //#pragma STDC FENV_ACCESS ON -#include -#include +#include +#include using namespace std::literals; @@ -147,8 +147,10 @@ static std::string CPUFeatureString(const zeus::CPUInfo& cpuInf) { return features; } -struct Application : aurora::AppDelegate { +struct Application { private: + int m_argc; + char** m_argv; FileStoreManager& m_fileMgr; CVarManager& m_cvarManager; CVarCommons& m_cvarCommons; @@ -171,14 +173,20 @@ private: // is built, i.e during initialization public: - Application(FileStoreManager& fileMgr, CVarManager& cvarMgr, CVarCommons& cvarCmns) - : m_fileMgr(fileMgr), m_cvarManager(cvarMgr), m_cvarCommons(cvarCmns), m_imGuiConsole(cvarMgr, cvarCmns) {} + Application(int argc, char** argv, FileStoreManager& fileMgr, CVarManager& cvarMgr, CVarCommons& cvarCmns) + : m_argc(argc) + , m_argv(argv) + , m_fileMgr(fileMgr) + , m_cvarManager(cvarMgr) + , m_cvarCommons(cvarCmns) + , m_imGuiConsole(cvarMgr, cvarCmns) {} - void onAppLaunched() noexcept override { + void onAppLaunched() noexcept { initialize(); - auto backend = static_cast(aurora::get_backend_string()); - aurora::set_window_title(fmt::format(FMT_STRING("Metaforce {} [{}]"), METAFORCE_WC_DESCRIBE, backend)); + // TODO + // auto backend = static_cast(aurora::get_backend_string()); + // aurora::set_window_title(fmt::format(FMT_STRING("Metaforce {} [{}]"), METAFORCE_WC_DESCRIBE, backend)); m_voiceEngine = boo::NewAudioVoiceEngine("metaforce", "Metaforce"); m_voiceEngine->setVolume(0.7f); @@ -187,8 +195,8 @@ public: #if TARGET_OS_IOS || TARGET_OS_TV m_deferredProject = std::string{m_fileMgr.getStoreRoot()} + "game.iso"; #else - for (const auto& str : aurora::get_args()) { - auto arg = static_cast(str); + for (int i = 1; i < m_argc; ++i) { + std::string arg = m_argv[i]; if (m_deferredProject.empty() && !arg.starts_with('-') && !arg.starts_with('+')) m_deferredProject = arg; else if (arg == "--no-sound") @@ -202,17 +210,13 @@ public: void initialize() { zeus::detectCPU(); - for (const auto& str : aurora::get_args()) { - auto arg = static_cast(str); - } - const zeus::CPUInfo& cpuInf = zeus::cpuFeatures(); Log.report(logvisor::Info, FMT_STRING("CPU Name: {}"), cpuInf.cpuBrand); Log.report(logvisor::Info, FMT_STRING("CPU Vendor: {}"), cpuInf.cpuVendor); Log.report(logvisor::Info, FMT_STRING("CPU Features: {}"), CPUFeatureString(cpuInf)); } - bool onAppIdle(float realDt) noexcept override { + bool onAppIdle(float realDt) noexcept { #ifdef NDEBUG /* Ping the watchdog to let it know we're still alive */ CInfiniteLoopDetector::UpdateWatchDog(std::chrono::system_clock::now()); @@ -258,7 +262,8 @@ public: // Check if the user has modified the fullscreen CVar, if so set fullscreen state accordingly if (m_cvarCommons.m_fullscreen->isModified()) { - aurora::set_fullscreen(m_cvarCommons.getFullscreen()); + // TODO + // aurora::set_fullscreen(m_cvarCommons.getFullscreen()); } // Let CVarManager inform all CVar listeners of the CVar's state and clear all mdoified flags if necessary @@ -266,7 +271,8 @@ public: if (!g_mainMP1 && m_projectInitialized) { g_mainMP1.emplace(nullptr, nullptr); - auto result = g_mainMP1->Init(m_fileMgr, &m_cvarManager, m_voiceEngine.get(), *m_amuseAllocWrapper); + auto result = + g_mainMP1->Init(m_argc, m_argv, m_fileMgr, &m_cvarManager, m_voiceEngine.get(), *m_amuseAllocWrapper); if (!result.empty()) { Log.report(logvisor::Error, FMT_STRING("{}"), result); m_imGuiConsole.m_errorString = result; @@ -311,7 +317,7 @@ public: return true; } - void onAppDraw() noexcept override { + void onAppDraw() noexcept { OPTICK_EVENT("Draw"); if (g_Renderer != nullptr) { g_Renderer->BeginScene(); @@ -322,7 +328,7 @@ public: } } - void onAppPostDraw() noexcept override { + void onAppPostDraw() noexcept { OPTICK_EVENT("PostDraw"); if (m_voiceEngine) { m_voiceEngine->pumpAndMixVoices(); @@ -331,25 +337,17 @@ public: ++logvisor::FrameIndex; } - void onAppWindowResized(const aurora::WindowSize& size) noexcept override { + void onAppWindowResized(const AuroraWindowSize& size) noexcept { CGraphics::SetViewportResolution({static_cast(size.fb_width), static_cast(size.fb_height)}); } - void onAppWindowMoved(std::int32_t x, std::int32_t y) noexcept override { - // TODO: implement this - } + void onAppDisplayScaleChanged(float scale) noexcept { ImGuiEngine_Initialize(scale); } - void onAppDisplayScaleChanged(float scale) noexcept override { ImGuiEngine_Initialize(scale); } + void onControllerAdded(uint32_t which) noexcept { m_imGuiConsole.ControllerAdded(which); } - void onControllerButton(uint32_t idx, aurora::ControllerButton button, bool pressed) noexcept override {} + void onControllerRemoved(uint32_t which) noexcept { m_imGuiConsole.ControllerRemoved(which); } - void onControllerAxis(uint32_t idx, aurora::ControllerAxis axis, int16_t value) noexcept override {} - - void onControllerAdded(uint32_t which) noexcept override { m_imGuiConsole.ControllerAdded(which); } - - void onControllerRemoved(uint32_t which) noexcept override { m_imGuiConsole.ControllerRemoved(which); } - - void onAppExiting() noexcept override { + void onAppExiting() noexcept { m_imGuiConsole.Shutdown(); if (m_voiceEngine) { m_voiceEngine->unlockPump(); @@ -365,127 +363,9 @@ public: CDvdFile::Shutdown(); } - void onCharKeyDown(uint8_t code, aurora::ModifierKey mods, bool isRepeat) noexcept override { - if (g_mainMP1) { - if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) { - as->charKeyDown(code, mods, isRepeat); - } - } - } + void onImGuiInit(float scale) noexcept { ImGuiEngine_Initialize(scale); } - void onCharKeyUp(uint8_t code, aurora::ModifierKey mods) noexcept override { - if (g_mainMP1) { - if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) { - as->charKeyUp(code, mods); - } - } - } - - void onSpecialKeyDown(aurora::SpecialKey key, aurora::ModifierKey mods, bool isRepeat) noexcept override { - if (g_mainMP1) { - if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) { - as->specialKeyDown(key, mods, isRepeat); - } - } - if (True(mods & (aurora::ModifierKey::LeftAlt | aurora::ModifierKey::RightAlt))) { - if (key == aurora::SpecialKey::Enter) { - m_fullscreenToggleRequested = true; - } else if (key == aurora::SpecialKey::F4) { - m_quitRequested = true; - } - } - } - - void onSpecialKeyUp(aurora::SpecialKey key, aurora::ModifierKey mods) noexcept override { - if (g_mainMP1) { - if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) { - as->specialKeyUp(key, mods); - } - } - } - - void onTextInput(const std::string& text) noexcept override {} - - void onModifierKeyDown(aurora::ModifierKey mods, bool isRepeat) noexcept override {} - void onModifierKeyUp(aurora::ModifierKey mods) noexcept override {} - - void onMouseMove(int32_t x, int32_t y, int32_t xrel, int32_t yrel, aurora::MouseButton state) noexcept override { - if (g_mainMP1) { - if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) { - as->mouseMove(SWindowCoord{.pixel = {x, y}}); - } - } - } - - void onMouseButtonDown(int32_t x, int32_t y, aurora::MouseButton button, int32_t clicks) noexcept override { - if (g_mainMP1) { - if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) { - EMouseButton asBtn; - switch (button) { - case aurora::MouseButton::None: - asBtn = EMouseButton::None; - break; - case aurora::MouseButton::Primary: - asBtn = EMouseButton::Primary; - break; - case aurora::MouseButton::Middle: - asBtn = EMouseButton::Middle; - break; - case aurora::MouseButton::Secondary: - asBtn = EMouseButton::Secondary; - break; - case aurora::MouseButton::Aux1: - asBtn = EMouseButton::Aux1; - break; - case aurora::MouseButton::Aux2: - asBtn = EMouseButton::Aux2; - break; - } - as->mouseDown(SWindowCoord{.pixel = {x, y}}, asBtn, {}); - } - } - } - - void onMouseButtonUp(int32_t x, int32_t y, aurora::MouseButton button) noexcept override { - if (g_mainMP1) { - if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) { - EMouseButton asBtn; - switch (button) { - case aurora::MouseButton::None: - asBtn = EMouseButton::None; - break; - case aurora::MouseButton::Primary: - asBtn = EMouseButton::Primary; - break; - case aurora::MouseButton::Middle: - asBtn = EMouseButton::Middle; - break; - case aurora::MouseButton::Secondary: - asBtn = EMouseButton::Secondary; - break; - case aurora::MouseButton::Aux1: - asBtn = EMouseButton::Aux1; - break; - case aurora::MouseButton::Aux2: - asBtn = EMouseButton::Aux2; - break; - } - as->mouseUp(SWindowCoord{.pixel = {x, y}}, asBtn, {}); - } - } - } - - void onImGuiInit(float scale) noexcept override { ImGuiEngine_Initialize(scale); } - - void onImGuiAddTextures() noexcept override { ImGuiEngine_AddTextures(); } - - [[nodiscard]] std::string getGraphicsApi() const { return m_cvarCommons.getGraphicsApi(); } - - [[nodiscard]] uint32_t getSamples() const { return m_cvarCommons.getSamples(); } - - [[nodiscard]] uint32_t getAnisotropy() const { return m_cvarCommons.getAnisotropy(); } - - [[nodiscard]] bool getDeepColor() const { return m_cvarCommons.getDeepColor(); } + void onImGuiAddTextures() noexcept { ImGuiEngine_AddTextures(); } [[nodiscard]] std::chrono::nanoseconds getTargetFrameTime() const { if (m_cvarCommons.getVariableFrameTime()) { @@ -527,10 +407,32 @@ static bool IsClientLoggingEnabled(int argc, char** argv) { return false; } -static void SetupLogging() { +static void SetupLogging() {} +static std::unique_ptr g_app; +static bool g_paused; + +static void aurora_log_callback(AuroraLogLevel level, const char* message, unsigned int len) { + logvisor::Level severity = logvisor::Fatal; + switch (level) { + case LOG_DEBUG: + case LOG_INFO: + severity = logvisor::Info; + break; + case LOG_WARNING: + severity = logvisor::Warning; + break; + case LOG_ERROR: + severity = logvisor::Error; + break; + default: + break; + } + metaforce::Log.report(severity, FMT_STRING("{}"), message); } +static void aurora_imgui_init_callback(const AuroraWindowSize* size) { g_app->onImGuiInit(size->scale); } + #if !WINDOWS_STORE int main(int argc, char** argv) { // TODO: This seems to fix a lot of weird issues with rounding @@ -550,6 +452,8 @@ int main(int argc, char** argv) { args.emplace_back(argv[i]); } + auto icon = metaforce::GetIcon(); + // FIXME: logvisor needs to copy this std::string logFilePath; @@ -583,16 +487,72 @@ int main(int argc, char** argv) { } } - auto app = std::make_unique(fileMgr, cvarMgr, cvarCmns); - auto icon = metaforce::GetIcon(); - auto data = aurora::Icon{ - .data = std::move(icon.data), - .width = icon.width, - .height = icon.height, + g_app = std::make_unique(argc, argv, fileMgr, cvarMgr, cvarCmns); + std::string configPath{fileMgr.getStoreRoot()}; + const AuroraConfig config{ + .appName = "Metaforce", + .configPath = configPath.c_str(), + // .desiredBackend = TODO + .msaa = cvarCmns.getSamples(), + .maxTextureAnisotropy = static_cast(cvarCmns.getAnisotropy()), + .startFullscreen = cvarCmns.getFullscreen(), + .iconRGBA8 = icon.data.get(), + .iconWidth = icon.width, + .iconHeight = icon.height, + .logCallback = aurora_log_callback, + .imGuiInitCallback = aurora_imgui_init_callback, }; - aurora::app_run(std::move(app), std::move(data), argc, argv, fileMgr.getStoreRoot(), - aurora::backend_from_string(cvarCmns.getGraphicsApi()), cvarCmns.getSamples(), - cvarCmns.getAnisotropy(), cvarCmns.getFullscreen()); + const auto info = aurora_initialize(argc, argv, &config); + g_app->onImGuiAddTextures(); + g_app->onAppLaunched(); + g_app->onAppWindowResized(info.windowSize); + while (true) { + const auto* event = aurora_update(); + bool exiting = false; + while (event != nullptr && event->type != AURORA_NONE) { + switch (event->type) { + case AURORA_EXIT: + exiting = true; + break; + case AURORA_WINDOW_RESIZED: + g_app->onAppWindowResized(event->windowSize); + break; + case AURORA_CONTROLLER_ADDED: + g_app->onControllerAdded(event->controller); + break; + case AURORA_CONTROLLER_REMOVED: + g_app->onControllerRemoved(event->controller); + break; + case AURORA_PAUSED: + g_paused = true; + break; + case AURORA_UNPAUSED: + g_paused = false; + break; + default: + break; + } + if (exiting) { + break; + } + ++event; + } + if (exiting) { + break; + } + if (g_paused) { + continue; + } + g_app->onAppIdle(1.f / 60.f /* TODO */); + aurora_begin_frame(); + g_app->onAppDraw(); + aurora_end_frame(); + g_app->onAppPostDraw(); + } + g_app->onAppExiting(); + aurora_shutdown(); + g_app.reset(); + restart = cvarMgr.restartRequired(); } while (restart); return 0; diff --git a/Runtime/CMakeLists.txt b/Runtime/CMakeLists.txt index 5cc041221..4014a6905 100644 --- a/Runtime/CMakeLists.txt +++ b/Runtime/CMakeLists.txt @@ -153,11 +153,11 @@ set(DISCORD_RPC_LIBRARY "") if (NOT GEKKO AND NOT NX AND NOT IOS AND NOT TVOS) set(DISCORD_RPC_LIBRARY "discord-rpc") endif() -set(RUNTIME_LIBRARIES amuse zeus nod NESEmulator libjpeg-turbo jbus kabufuda logvisor OptickCore imgui aurora +set(RUNTIME_LIBRARIES amuse zeus nod NESEmulator libjpeg-turbo jbus kabufuda logvisor OptickCore + imgui_support aurora::aurora SDL2::SDL2-static SDL2::SDL2main boo # TODO move audiodev ${DISCORD_RPC_LIBRARY} ${ZLIB_LIBRARIES} - SDL2::SDL2-static SDL2::SDL2main ) add_runtime_common_library(RuntimeCommon ${RUNTIME_SOURCES_A}) @@ -229,7 +229,7 @@ add_executable(metaforce CMain.cpp ${PLAT_SRCS} ImGuiControllerConfig.hpp ImGuiControllerConfig.cpp ImGuiEntitySupport.hpp ImGuiEntitySupport.cpp) # RUNTIME_LIBRARIES repeated here for link ordering -target_link_libraries(metaforce PUBLIC RuntimeCommon RuntimeCommonB ${RUNTIME_LIBRARIES} ${PLAT_LIBS}) +target_link_libraries(metaforce PUBLIC RuntimeCommon RuntimeCommonB ${RUNTIME_LIBRARIES} ${PLAT_LIBS} aurora::main) if (TARGET nativefiledialog) target_link_libraries(metaforce PRIVATE nativefiledialog) endif() diff --git a/Runtime/Camera/CCameraFilter.cpp b/Runtime/Camera/CCameraFilter.cpp index b49a832dd..95cb8bec2 100644 --- a/Runtime/Camera/CCameraFilter.cpp +++ b/Runtime/Camera/CCameraFilter.cpp @@ -112,7 +112,7 @@ void CCameraFilterPass::DrawFilter(EFilterType type, EFilterShape shape, const z g_Renderer->SetBlendMode_AdditiveAlpha(); break; case EFilterType::Subtract: - CGX::SetBlendMode(GX::BM_SUBTRACT, GX::BL_ONE, GX::BL_ONE, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_SUBTRACT, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR); break; case EFilterType::Blend: g_Renderer->SetBlendMode_AlphaBlended(); @@ -186,12 +186,12 @@ void CCameraFilterPass::DrawFullScreenTexturedQuadQuarters(const zeus::CColor& c CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); g_Renderer->SetDepthReadWrite(false, false); if (tex != nullptr) { - tex->Load(GX::TEXMAP0, EClampMode::Repeat); + tex->Load(GX_TEXMAP0, EClampMode::Repeat); } CGraphics::SetCullMode(ERglCullMode::None); for (int i = 0; i < 4; ++i) { g_Renderer->SetModelMatrix(zeus::CTransform::Scale((i & 1) != 0 ? 1.f : -1.f, 0.f, (i & 2) != 0 ? 1.f : -1.f)); - CGraphics::StreamBegin(GX::TRIANGLESTRIP); + CGraphics::StreamBegin(GX_TRIANGLESTRIP); CGraphics::StreamColor(color); CGraphics::StreamTexcoord(lod, lod); CGraphics::StreamVertex(lt.x(), 0.f, rb.y()); @@ -213,11 +213,11 @@ void CCameraFilterPass::DrawFullScreenTexturedQuad(const zeus::CColor& color, CT const auto [lt, rb] = g_Renderer->SetViewportOrtho(true, -4096.f, 4096.f); g_Renderer->SetDepthReadWrite(false, false); if (tex != nullptr) { - tex->Load(GX::TEXMAP0, EClampMode::Repeat); + tex->Load(GX_TEXMAP0, EClampMode::Repeat); } CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc); CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); - CGraphics::StreamBegin(GX::TRIANGLESTRIP); + CGraphics::StreamBegin(GX_TRIANGLESTRIP); CGraphics::StreamColor(color); CGraphics::StreamTexcoord(u, v); CGraphics::StreamVertex(lt.x() - 1.f, 0.f, 1.f + rb.y()); @@ -253,9 +253,9 @@ void CCameraFilterPass::DrawRandomStatic(const zeus::CColor& color, float alpha, u8* out = m_randomStatic.Lock(); memcpy(out, buf + ROUND_UP_32(rand() & 0x7fff), m_randomStatic.GetMemoryAllocated()); m_randomStatic.UnLock(); - m_randomStatic.Load(GX::TEXMAP0, EClampMode::Clamp); + m_randomStatic.Load(GX_TEXMAP0, EClampMode::Clamp); - CGraphics::StreamBegin(GX::TRIANGLESTRIP); + CGraphics::StreamBegin(GX_TRIANGLESTRIP); CGraphics::StreamColor(color); CGraphics::StreamTexcoord(0.f, 1.f); CGraphics::StreamVertex(lb.x() - 1.f, 0.01f, rt.y() + 1.f); @@ -289,11 +289,11 @@ void CCameraFilterPass::DrawWideScreen(const zeus::CColor& color, CTexture* tex, // g_Renderer->SetDepthReadWrite(false, false); // g_Renderer->SetModelMatrix({}); // if (tex != nullptr) { - // tex->Load(GX::TEXMAP0, EClampMode::Repeat); + // tex->Load(GX_TEXMAP0, EClampMode::Repeat); // } // CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc); // CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); - // CGraphics::StreamBegin(GX::TRIANGLESTRIP); + // CGraphics::StreamBegin(GX_TRIANGLESTRIP); // float x = rand() % 4000; } diff --git a/Runtime/Flags.hpp b/Runtime/Flags.hpp new file mode 100644 index 000000000..622f932cd --- /dev/null +++ b/Runtime/Flags.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include + +namespace metaforce { +template +class Flags { +public: + using MaskType = std::underlying_type_t; + + // constructors + constexpr Flags() noexcept : m_mask(0) {} + + constexpr Flags(BitType bit) noexcept : m_mask(static_cast(bit)) {} + + constexpr Flags(Flags const& rhs) noexcept : m_mask(rhs.m_mask) {} + + constexpr explicit Flags(MaskType flags) noexcept : m_mask(flags) {} + + [[nodiscard]] constexpr bool IsSet(Flags const bit) const noexcept { return bool(*this & bit); } + + // relational operators + bool operator==(Flags const& rhs) const noexcept { return m_mask == rhs.m_mask; } + + // logical operator + constexpr bool operator!() const noexcept { return !m_mask; } + + // bitwise operators + constexpr Flags operator&(Flags const& rhs) const noexcept { + return Flags(m_mask & rhs.m_mask); + } + + constexpr Flags operator|(Flags const& rhs) const noexcept { + return Flags(m_mask | rhs.m_mask); + } + + constexpr Flags operator^(Flags const& rhs) const noexcept { + return Flags(m_mask ^ rhs.m_mask); + } + + // assignment operators + constexpr Flags& operator=(Flags const& rhs) noexcept { + m_mask = rhs.m_mask; + return *this; + } + + constexpr Flags& operator|=(Flags const& rhs) noexcept { + m_mask |= rhs.m_mask; + return *this; + } + + constexpr Flags& operator&=(Flags const& rhs) noexcept { + m_mask &= rhs.m_mask; + return *this; + } + + constexpr Flags& operator^=(Flags const& rhs) noexcept { + m_mask ^= rhs.m_mask; + return *this; + } + + // cast operators + explicit constexpr operator bool() const noexcept { return m_mask != 0; } + + explicit constexpr operator MaskType() const noexcept { return m_mask; } + +private: + MaskType m_mask; +}; +} // namespace metaforce diff --git a/Runtime/Graphics/CCubeMaterial.cpp b/Runtime/Graphics/CCubeMaterial.cpp index e22f8ecb3..f7c23dedd 100644 --- a/Runtime/Graphics/CCubeMaterial.cpp +++ b/Runtime/Graphics/CCubeMaterial.cpp @@ -55,7 +55,7 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur materialDataCur += 8; for (u32 i = 0; i < texCount; ++i) { u32 texIdx = SBig(*reinterpret_cast(materialDataCur)); - model.GetTexture(texIdx)->Load(static_cast(i), EClampMode::Repeat); + model.GetTexture(texIdx)->Load(static_cast(i), EClampMode::Repeat); materialDataCur += 4; } } @@ -83,14 +83,14 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur for (u32 i = 0; i < konstCount; ++i) { u32 kColor = SBig(*reinterpret_cast(materialDataCur)); materialDataCur += 4; - CGX::SetTevKColor(static_cast(i), kColor); + CGX::SetTevKColor(static_cast(i), kColor); } } u32 blendFactors = SBig(*reinterpret_cast(materialDataCur)); materialDataCur += 4; if (g_Renderer->IsInAreaDraw()) { - CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ONE, GX::BL_ONE, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR); } else { SetupBlendMode(blendFactors, flags, matFlags.IsSet(CCubeMaterialFlagBits::fAlphaTest)); } @@ -129,12 +129,12 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur finalTevCount = firstTev + 1; u32 ccFlags = SBig(*reinterpret_cast(materialDataCur + 8)); finalCCFlags = ccFlags; - auto outputReg = static_cast(ccFlags >> 9 & 0x3); - if (outputReg == GX::TEVREG0) { + auto outputReg = static_cast(ccFlags >> 9 & 0x3); + if (outputReg == GX_TEVREG0) { materialDataCur += 20; texMapTexCoordFlags += 1; finalCCFlags = SBig(*reinterpret_cast(materialDataCur + 8)); - GXSetTevColor(GX::TEVREG0, 0xc0c0c0c0); + GXSetTevColor(GX_TEVREG0, GXColor{0xc0, 0xc0, 0xc0, 0xc0}); } finalACFlags = SBig(*reinterpret_cast(materialDataCur + 12)); HandleTev(firstTev, reinterpret_cast(materialDataCur), texMapTexCoordFlags, @@ -148,8 +148,8 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur u32 ccFlags = SBig(*reinterpret_cast(materialDataCur + 8)); finalCCFlags = ccFlags; finalACFlags = SBig(*reinterpret_cast(materialDataCur + 12)); - auto outputReg = static_cast(ccFlags >> 9 & 0x3); - if (outputReg == GX::TEVREG2) { + auto outputReg = static_cast(ccFlags >> 9 & 0x3); + if (outputReg == GX_TEVREG2) { usesTevReg2 = true; } materialDataCur += 20; @@ -162,13 +162,13 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur u32 fullTcgCount = SBig(*tcgs); tcgCount = std::min(fullTcgCount, 2u); for (u32 i = 0; i < tcgCount; ++i) { - CGX::SetTexCoordGen(GX::TexCoordID(i), SBig(tcgs[i + 1])); + CGX::SetTexCoordGen(GXTexCoordID(i), SBig(tcgs[i + 1])); } tcgs += fullTcgCount + 1; } else { tcgCount = SBig(*tcgs); for (u32 i = 0; i < tcgCount; ++i) { - CGX::SetTexCoordGen(GX::TexCoordID(i), SBig(tcgs[i + 1])); + CGX::SetTexCoordGen(GXTexCoordID(i), SBig(tcgs[i + 1])); } tcgs += tcgCount + 1; } @@ -176,10 +176,10 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur const u32* uvAnim = tcgs; u32 animCount = SBig(uvAnim[1]); uvAnim += 2; - u32 texMtx = GX::TEXMTX0; - u32 pttTexMtx = GX::PTTEXMTX0; + u32 texMtx = GX_TEXMTX0; + u32 pttTexMtx = GX_PTTEXMTX0; for (u32 i = 0; i < animCount; ++i) { - u32 size = HandleAnimatedUV(uvAnim, static_cast(texMtx), static_cast(pttTexMtx)); + u32 size = HandleAnimatedUV(uvAnim, static_cast(texMtx), static_cast(pttTexMtx)); if (size == 0) break; uvAnim += size; @@ -228,17 +228,17 @@ void CCubeMaterial::SetCurrentBlack() { const auto flags = GetFlags(); const auto vatFlags = GetVatFlags(); if (flags.IsSet(CCubeMaterialFlagBits::fDepthSorting) || flags.IsSet(CCubeMaterialFlagBits::fAlphaTest)) { - CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ZERO, GX::BL_ONE, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_BLEND, GX_BL_ZERO, GX_BL_ONE, GX_LO_CLEAR); } else { - CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ONE, GX::BL_ZERO, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR); } CGX::SetVtxDescv_Compressed(vatFlags); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO /* ? CC_ONE */); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO /* ? CA_KONST */); - CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_1); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_POS, GX::IDENTITY, false, GX::PTIDENTITY); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO /* ? CC_ONE */); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO /* ? CA_KONST */); + CGX::SetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_1); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_POS, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); CGX::SetNumTevStages(1); CGX::SetNumChans(0); CGX::SetNumTexGens(1); @@ -246,35 +246,35 @@ void CCubeMaterial::SetCurrentBlack() { } void CCubeMaterial::SetupBlendMode(u32 blendFactors, const CModelFlags& flags, bool alphaTest) { - auto newSrcFactor = static_cast(blendFactors & 0xffff); - auto newDstFactor = static_cast(blendFactors >> 16 & 0xffff); + auto newSrcFactor = static_cast(blendFactors & 0xffff); + auto newDstFactor = static_cast(blendFactors >> 16 & 0xffff); if (alphaTest) { // discard fragments with alpha < 0.25 - CGX::SetAlphaCompare(GX::GEQUAL, 64, GX::AOP_OR, GX::NEVER, 0); - newSrcFactor = GX::BL_ONE; - newDstFactor = GX::BL_ZERO; + CGX::SetAlphaCompare(GX_GEQUAL, 64, GX_AOP_OR, GX_NEVER, 0); + newSrcFactor = GX_BL_ONE; + newDstFactor = GX_BL_ZERO; } else { - CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_OR, GX::ALWAYS, 0); + CGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0); } - if (flags.x0_blendMode > 4 && newSrcFactor == GX::BL_ONE) { - newSrcFactor = GX::BL_SRCALPHA; - if (newDstFactor == GX::BL_ZERO) { - newDstFactor = flags.x0_blendMode > 6 ? GX::BL_ONE : GX::BL_INVSRCALPHA; + if (flags.x0_blendMode > 4 && newSrcFactor == GX_BL_ONE) { + newSrcFactor = GX_BL_SRCALPHA; + if (newDstFactor == GX_BL_ZERO) { + newDstFactor = flags.x0_blendMode > 6 ? GX_BL_ONE : GX_BL_INVSRCALPHA; } } - CGX::SetBlendMode(GX::BM_BLEND, newSrcFactor, newDstFactor, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_BLEND, newSrcFactor, newDstFactor, GX_LO_CLEAR); } void CCubeMaterial::HandleDepth(CModelFlagsFlags modelFlags, CCubeMaterialFlags matFlags) { - GX::Compare func = GX::NEVER; + GXCompare func = GX_NEVER; if (!(modelFlags & CModelFlagBits::DepthTest)) { - func = GX::ALWAYS; + func = GX_ALWAYS; } else if (modelFlags & CModelFlagBits::DepthGreater) { - func = modelFlags & CModelFlagBits::DepthNonInclusive ? GX::GREATER : GX::GEQUAL; + func = modelFlags & CModelFlagBits::DepthNonInclusive ? GX_GREATER : GX_GEQUAL; } else { - func = modelFlags & CModelFlagBits::DepthNonInclusive ? GX::LESS : GX::LEQUAL; + func = modelFlags & CModelFlagBits::DepthNonInclusive ? GX_LESS : GX_LEQUAL; } bool depthWrite = modelFlags & CModelFlagBits::DepthUpdate && matFlags & CCubeMaterialFlagBits::fDepthWrite; CGX::SetZMode(true, func, depthWrite); @@ -309,14 +309,14 @@ void CCubeMaterial::EnsureViewDepStateCached(const CCubeSurface* surface) { u32 CCubeMaterial::HandleColorChannels(u32 chanCount, u32 firstChan) { if (CCubeModel::sRenderModelShadow) { if (chanCount != 0) { - CGX::SetChanAmbColor(CGX::EChannelId::Channel1, zeus::skBlack); - CGX::SetChanMatColor(CGX::EChannelId::Channel1, zeus::skWhite); + CGX::SetChanAmbColor(CGX::EChannelId::Channel1, GX_BLACK); + CGX::SetChanMatColor(CGX::EChannelId::Channel1, GX_WHITE); auto chan0Lights = CGraphics::g_LightActive & ~CCubeModel::sChannel0DisableLightMask; CGX::SetChanCtrl(CGX::EChannelId::Channel0, firstChan, chan0Lights); CGX::SetChanCtrl(CGX::EChannelId::Channel1, CCubeModel::sChannel1EnableLightMask); if (chan0Lights.any()) { - CGX::SetChanMatColor(CGX::EChannelId::Channel0, zeus::skWhite); + CGX::SetChanMatColor(CGX::EChannelId::Channel0, GX_WHITE); } else { CGX::SetChanMatColor(CGX::EChannelId::Channel0, CGX::GetChanAmbColor(CGX::EChannelId::Channel0)); } @@ -325,8 +325,8 @@ u32 CCubeMaterial::HandleColorChannels(u32 chanCount, u32 firstChan) { } if (chanCount == 2) { - CGX::SetChanAmbColor(CGX::EChannelId::Channel1, zeus::skBlack); - CGX::SetChanMatColor(CGX::EChannelId::Channel1, zeus::skWhite); + CGX::SetChanAmbColor(CGX::EChannelId::Channel1, GX_BLACK); + CGX::SetChanMatColor(CGX::EChannelId::Channel1, GX_WHITE); } else { CGX::SetChanCtrl(CGX::EChannelId::Channel1, {}); } @@ -336,7 +336,7 @@ u32 CCubeMaterial::HandleColorChannels(u32 chanCount, u32 firstChan) { } else { CGX::SetChanCtrl(CGX::EChannelId::Channel0, firstChan, CGraphics::g_LightActive); if (CGraphics::g_LightActive.any()) { - CGX::SetChanMatColor(CGX::EChannelId::Channel0, zeus::skWhite); + CGX::SetChanMatColor(CGX::EChannelId::Channel0, GX_WHITE); } else { CGX::SetChanMatColor(CGX::EChannelId::Channel0, CGX::GetChanAmbColor(CGX::EChannelId::Channel0)); } @@ -352,15 +352,15 @@ void CCubeMaterial::HandleTev(u32 tevCur, const u32* materialDataCur, const u32* const u32 colorOps = SBig(materialDataCur[2]); const u32 alphaOps = SBig(materialDataCur[3]); - const auto stage = static_cast(tevCur); + const auto stage = static_cast(tevCur); CGX::SetStandardDirectTev_Compressed(stage, colorArgs, alphaArgs, colorOps, alphaOps); u32 tmtcFlags = SBig(*texMapTexCoordFlags); u32 matFlags = SBig(materialDataCur[4]); - CGX::SetTevOrder(stage, static_cast(tmtcFlags & 0xFF), - static_cast(tmtcFlags >> 8 & 0xFF), static_cast(matFlags & 0xFF)); - CGX::SetTevKColorSel(stage, static_cast(matFlags >> 0x8 & 0xFF)); - CGX::SetTevKAlphaSel(stage, static_cast(matFlags >> 0x10 & 0xFF)); + CGX::SetTevOrder(stage, static_cast(tmtcFlags & 0xFF), static_cast(tmtcFlags >> 8 & 0xFF), + static_cast(matFlags & 0xFF)); + CGX::SetTevKColorSel(stage, static_cast(matFlags >> 0x8 & 0xFF)); + CGX::SetTevKAlphaSel(stage, static_cast(matFlags >> 0x10 & 0xFF)); } constexpr zeus::CTransform MvPostXf{ @@ -368,21 +368,21 @@ constexpr zeus::CTransform MvPostXf{ {0.5f, 0.5f, 1.f}, }; -u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, GX::TexMtx texMtx, GX::PTTexMtx pttTexMtx) { +u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, GXTexMtx texMtx, GXPTTexMtx pttTexMtx) { u32 type = SBig(*uvAnim); const float* params = reinterpret_cast(uvAnim + 1); switch (type) { case 0: { auto xf = CGraphics::g_ViewMatrix.inverse().multiplyIgnoreTranslation(CGraphics::g_GXModelMatrix); xf.origin.zeroOut(); - GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4); - GXLoadTexMtxImm(&MvPostXf, pttTexMtx, GX::MTX3x4); + GXLoadTexMtxImm(&xf, texMtx, GX_MTX3x4); + GXLoadTexMtxImm(&MvPostXf, pttTexMtx, GX_MTX3x4); return 1; } case 1: { auto xf = CGraphics::g_ViewMatrix.inverse() * CGraphics::g_GXModelMatrix; - GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4); - GXLoadTexMtxImm(&MvPostXf, pttTexMtx, GX::MTX3x4); + GXLoadTexMtxImm(&xf, texMtx, GX_MTX3x4); + GXLoadTexMtxImm(&MvPostXf, pttTexMtx, GX_MTX3x4); return 1; } case 2: { @@ -392,7 +392,7 @@ u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, GX::TexMtx texMtx, GX::PT const float f4 = SBig(params[3]); const float seconds = CGraphics::GetSecondsMod900(); const auto xf = zeus::CTransform::Translate(seconds * f3 + f1, seconds * f4 + f2, 0.f); - GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4); + GXLoadTexMtxImm(&xf, texMtx, GX_MTX3x4); return 5; } case 3: { @@ -406,7 +406,7 @@ u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, GX::TexMtx texMtx, GX::PT xf.basis[1][1] = acos; xf.origin[0] = (1.f - (acos - asin)) * 0.5f; xf.origin[1] = (1.f - (asin + acos)) * 0.5f; - GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4); + GXLoadTexMtxImm(&xf, texMtx, GX_MTX3x4); return 3; } case 4: @@ -420,7 +420,7 @@ u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, GX::TexMtx texMtx, GX::PT xf.origin.x() = 0.f; xf.origin.y() = std::trunc(SBig(params[1]) * std::fmod(value, 1.f)) * SBig(params[2]); } - GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4); + GXLoadTexMtxImm(&xf, texMtx, GX_MTX3x4); return 5; } case 6: { @@ -437,8 +437,8 @@ u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, GX::TexMtx texMtx, GX::PT 1.f, }, }; - GXLoadTexMtxImm(&mtx, texMtx, GX::MTX3x4); - GXLoadTexMtxImm(&postMtx, pttTexMtx, GX::MTX3x4); + GXLoadTexMtxImm(&mtx, texMtx, GX_MTX3x4); + GXLoadTexMtxImm(&postMtx, pttTexMtx, GX_MTX3x4); return 1; } case 7: { @@ -457,8 +457,8 @@ u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, GX::TexMtx texMtx, GX::PT }, zeus::CVector3f{xy, z, 1.f}, }; - GXLoadTexMtxImm(&mtx, texMtx, GX::MTX3x4); - GXLoadTexMtxImm(&postMtx, pttTexMtx, GX::MTX3x4); + GXLoadTexMtxImm(&mtx, texMtx, GX_MTX3x4); + GXLoadTexMtxImm(&postMtx, pttTexMtx, GX_MTX3x4); return 3; } default: @@ -476,38 +476,38 @@ void CCubeMaterial::HandleTransparency(u32& finalTevCount, u32& finalKColorCount } if (modelFlags.x0_blendMode == 3) { // Stage outputting splatted KAlpha as color to reg0 - auto stage = static_cast(finalTevCount); - CGX::SetTevColorIn(stage, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_KONST); - CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV); - CGX::SetTevColorOp(stage, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVREG0); - CGX::SetTevKColorSel(stage, static_cast(finalKColorCount + GX::TEV_KCSEL_K0_A)); - CGX::SetTevAlphaOp(stage, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); - CGX::SetTevOrder(stage, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL); + auto stage = static_cast(finalTevCount); + CGX::SetTevColorIn(stage, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_KONST); + CGX::SetTevAlphaIn(stage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV); + CGX::SetTevColorOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVREG0); + CGX::SetTevKColorSel(stage, static_cast(finalKColorCount + GX_TEV_KCSEL_K0_A)); + CGX::SetTevAlphaOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + CGX::SetTevOrder(stage, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); CGX::SetTevDirect(stage); // Stage interpolating from splatted KAlpha using KColor - stage = static_cast(stage + 1); - CGX::SetTevColorIn(stage, GX::CC_CPREV, GX::CC_C0, GX::CC_KONST, GX::CC_ZERO); - CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV); - CGX::SetTevKColorSel(stage, static_cast(finalKColorCount + GX::TEV_KCSEL_K0)); + stage = static_cast(stage + 1); + CGX::SetTevColorIn(stage, GX_CC_CPREV, GX_CC_C0, GX_CC_KONST, GX_CC_ZERO); + CGX::SetTevAlphaIn(stage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV); + CGX::SetTevKColorSel(stage, static_cast(finalKColorCount + GX_TEV_KCSEL_K0)); CGX::SetStandardTevColorAlphaOp(stage); CGX::SetTevDirect(stage); - CGX::SetTevOrder(stage, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL); - CGX::SetTevKColor(static_cast(finalKColorCount), modelFlags.x4_color); + CGX::SetTevOrder(stage, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + CGX::SetTevKColor(static_cast(finalKColorCount), modelFlags.x4_color); finalKColorCount += 1; finalTevCount += 2; } else { - auto stage = static_cast(finalTevCount); + auto stage = static_cast(finalTevCount); if (modelFlags.x0_blendMode == 8) { - CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_KONST); // Set KAlpha + CGX::SetTevAlphaIn(stage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_KONST); // Set KAlpha } else { - CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_KONST, GX::CA_APREV, GX::CA_ZERO); // Mul KAlpha + CGX::SetTevAlphaIn(stage, GX_CA_ZERO, GX_CA_KONST, GX_CA_APREV, GX_CA_ZERO); // Mul KAlpha } if (modelFlags.x0_blendMode == 2) { - CGX::SetTevColorIn(stage, GX::CC_ZERO, GX::CC_ONE, GX::CC_CPREV, GX::CC_KONST); // Add KColor + CGX::SetTevColorIn(stage, GX_CC_ZERO, GX_CC_ONE, GX_CC_CPREV, GX_CC_KONST); // Add KColor } else { - CGX::SetTevColorIn(stage, GX::CC_ZERO, GX::CC_KONST, GX::CC_CPREV, GX::CC_ZERO); // Mul KColor + CGX::SetTevColorIn(stage, GX_CC_ZERO, GX_CC_KONST, GX_CC_CPREV, GX_CC_ZERO); // Mul KColor } CGX::SetStandardTevColorAlphaOp(stage); @@ -515,10 +515,10 @@ void CCubeMaterial::HandleTransparency(u32& finalTevCount, u32& finalKColorCount finalACFlags = 0x100; CGX::SetTevDirect(stage); - CGX::SetTevOrder(stage, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL); - CGX::SetTevKColor(static_cast(finalKColorCount), modelFlags.x4_color); - CGX::SetTevKColorSel(stage, static_cast(finalKColorCount + GX::TEV_KCSEL_K0)); - CGX::SetTevKAlphaSel(stage, static_cast(finalKColorCount + GX::TEV_KASEL_K0_A)); + CGX::SetTevOrder(stage, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + CGX::SetTevKColor(static_cast(finalKColorCount), modelFlags.x4_color); + CGX::SetTevKColorSel(stage, static_cast(finalKColorCount + GX_TEV_KCSEL_K0)); + CGX::SetTevKAlphaSel(stage, static_cast(finalKColorCount + GX_TEV_KASEL_K0_A)); finalTevCount += 1; finalKColorCount += 1; @@ -528,22 +528,22 @@ void CCubeMaterial::HandleTransparency(u32& finalTevCount, u32& finalKColorCount u32 CCubeMaterial::HandleReflection(bool usesTevReg2, u32 indTexSlot, u32 r5, u32 finalTevCount, u32 texCount, u32 tcgCount, u32 finalKColorCount, u32& finalCCFlags, u32& finalACFlags) { u32 out = 0; - GX::TevColorArg colorArg = GX::CC_KONST; + GXTevColorArg colorArg = GX_CC_KONST; if (usesTevReg2) { - colorArg = GX::CC_C2; - const auto stage = static_cast(finalTevCount); - CGX::SetTevColorIn(stage, GX::CC_ZERO, GX::CC_C2, GX::CC_KONST, GX::CC_ZERO); - CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_A2); - CGX::SetTevColorOp(stage, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVREG2); - CGX::SetTevAlphaOp(stage, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVREG2); - CGX::SetTevOrder(stage, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_ZERO); + colorArg = GX_CC_C2; + const auto stage = static_cast(finalTevCount); + CGX::SetTevColorIn(stage, GX_CC_ZERO, GX_CC_C2, GX_CC_KONST, GX_CC_ZERO); + CGX::SetTevAlphaIn(stage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A2); + CGX::SetTevColorOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVREG2); + CGX::SetTevAlphaOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVREG2); + CGX::SetTevOrder(stage, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_ZERO); out = 1; } - CGX::SetTevKColor(static_cast(finalKColorCount), zeus::CColor{sReflectionAlpha, sReflectionAlpha}); - CGX::SetTevKColorSel(static_cast(finalTevCount), - static_cast(GX::TEV_KCSEL_K0 + finalKColorCount)); + CGX::SetTevKColor(static_cast(finalKColorCount), zeus::CColor{sReflectionAlpha, sReflectionAlpha}); + CGX::SetTevKColorSel(static_cast(finalTevCount), + static_cast(GX_TEV_KCSEL_K0 + finalKColorCount)); - const auto stage = static_cast(finalTevCount + out); + const auto stage = static_cast(finalTevCount + out); // tex = g_Renderer->GetRealReflection // tex.Load(texCount, 0) @@ -558,10 +558,10 @@ u32 CCubeMaterial::HandleReflection(bool usesTevReg2, u32 indTexSlot, u32 r5, u3 } void CCubeMaterial::DoPassthru(u32 finalTevCount) { - const auto stage = static_cast(finalTevCount); - CGX::SetTevColorIn(stage, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_CPREV); - CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV); - CGX::SetTevOrder(stage, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL); + const auto stage = static_cast(finalTevCount); + CGX::SetTevColorIn(stage, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_CPREV); + CGX::SetTevAlphaIn(stage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV); + CGX::SetTevOrder(stage, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); CGX::SetTevDirect(stage); CGX::SetStandardTevColorAlphaOp(stage); } @@ -571,14 +571,14 @@ void CCubeMaterial::DoModelShadow(u32 texCount, u32 tcgCount) { // TODO } -static GX::TevStageID sCurrentTevStage = GX::NULL_STAGE; +static GXTevStageID sCurrentTevStage = GX_MAX_TEVSTAGE; void CCubeMaterial::EnsureTevsDirect() { - if (sCurrentTevStage == GX::NULL_STAGE) { + if (sCurrentTevStage == GX_MAX_TEVSTAGE) { return; } CGX::SetNumIndStages(0); CGX::SetTevDirect(sCurrentTevStage); - sCurrentTevStage = GX::NULL_STAGE; + sCurrentTevStage = GX_MAX_TEVSTAGE; } } // namespace metaforce diff --git a/Runtime/Graphics/CCubeMaterial.hpp b/Runtime/Graphics/CCubeMaterial.hpp index be1a51f2a..0903ecc26 100644 --- a/Runtime/Graphics/CCubeMaterial.hpp +++ b/Runtime/Graphics/CCubeMaterial.hpp @@ -64,7 +64,7 @@ private: static void HandleDepth(CModelFlagsFlags modelFlags, CCubeMaterialFlags matFlags); static u32 HandleColorChannels(u32 chanCount, u32 firstChan); static void HandleTev(u32 tevCur, const u32* materialDataCur, const u32* texMapTexCoordFlags, bool shadowMapsEnabled); - static u32 HandleAnimatedUV(const u32* uvAnim, GX::TexMtx texMtx, GX::PTTexMtx pttTexMtx); + static u32 HandleAnimatedUV(const u32* uvAnim, GXTexMtx texMtx, GXPTTexMtx pttTexMtx); static void HandleTransparency(u32& finalTevCount, u32& finalKColorCount, const CModelFlags& modelFlags, u32 blendFactors, u32& finalCCFlags, u32& finalACFlags); static u32 HandleReflection(bool usesTevReg2, u32 indTexSlot, u32 r5, u32 finalTevCount, u32 texCount, u32 tcgCount, diff --git a/Runtime/Graphics/CCubeModel.cpp b/Runtime/Graphics/CCubeModel.cpp index 9fee6aff1..8f48febaf 100644 --- a/Runtime/Graphics/CCubeModel.cpp +++ b/Runtime/Graphics/CCubeModel.cpp @@ -177,12 +177,12 @@ void CCubeModel::DrawNormal(TConstVectorRef positions, TConstVectorRef normals, CGX::SetNumIndStages(0); CGX::SetNumTevStages(1); CGX::SetNumTexGens(1); // TODO should this be 0? - CGX::SetZMode(true, GX::LEQUAL, true); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); - CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ZERO, GX::BL_ONE, GX::LO_CLEAR); + CGX::SetZMode(true, GX_LEQUAL, true); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); + CGX::SetBlendMode(GX_BM_BLEND, GX_BL_ZERO, GX_BL_ONE, GX_LO_CLEAR); DrawFlat(positions, normals, surfaces); } @@ -259,8 +259,8 @@ void CCubeModel::EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransf void CCubeModel::DisableShadowMaps() { sRenderModelShadow = false; } void CCubeModel::SetArraysCurrent() { - CGX::SetArray(GX::VA_POS, x0_modelInstance.GetVertexPointer(), true); - CGX::SetArray(GX::VA_NRM, x0_modelInstance.GetNormalPointer(), true); + CGX::SetArray(GX_VA_POS, x0_modelInstance.GetVertexPointer(), true); + CGX::SetArray(GX_VA_NRM, x0_modelInstance.GetNormalPointer(), true); SetStaticArraysCurrent(); } @@ -280,8 +280,8 @@ void CCubeModel::SetRenderModelBlack(bool v) { } void CCubeModel::SetSkinningArraysCurrent(TConstVectorRef positions, TConstVectorRef normals) { - CGX::SetArray(GX::VA_POS, positions, false); - CGX::SetArray(GX::VA_NRM, normals, false); + CGX::SetArray(GX_VA_POS, positions, false); + CGX::SetArray(GX_VA_NRM, normals, false); // colors unused SetStaticArraysCurrent(); } @@ -294,22 +294,29 @@ void CCubeModel::SetStaticArraysCurrent() { sUsingPackedLightmaps = false; } if (sUsingPackedLightmaps) { - CGX::SetArray(GX::VA_TEX0, packedTexCoords, true); + CGX::SetArray(GX_VA_TEX0, packedTexCoords, true); } else { - CGX::SetArray(GX::VA_TEX0, texCoords, true); + CGX::SetArray(GX_VA_TEX0, texCoords, true); + } + for (int i = GX_VA_TEX1; i <= GX_VA_TEX7; ++i) { + CGX::SetArray(static_cast(i), texCoords, true); } - // TexCoord1 is currently used for all remaining - CGX::SetArray(GX::VA_TEX1, texCoords, true); CCubeMaterial::KillCachedViewDepState(); } void CCubeModel::SetUsingPackedLightmaps(bool v) { sUsingPackedLightmaps = v; if (v) { - CGX::SetArray(GX::VA_TEX0, x0_modelInstance.GetPackedTCPointer(), true); + CGX::SetArray(GX_VA_TEX0, x0_modelInstance.GetPackedTCPointer(), true); } else { - CGX::SetArray(GX::VA_TEX0, x0_modelInstance.GetTCPointer(), true); + CGX::SetArray(GX_VA_TEX0, x0_modelInstance.GetTCPointer(), true); } } +template <> +aurora::Vec2 cinput_stream_helper(CInputStream& in) { + float x = in.ReadFloat(); + float y = in.ReadFloat(); + return {x, y}; +} } // namespace metaforce diff --git a/Runtime/Graphics/CCubeModel.hpp b/Runtime/Graphics/CCubeModel.hpp index 164f93f30..4a91697cf 100644 --- a/Runtime/Graphics/CCubeModel.hpp +++ b/Runtime/Graphics/CCubeModel.hpp @@ -2,6 +2,7 @@ #include #include +#include #include "CStopwatch.hpp" #include "CToken.hpp" @@ -138,4 +139,7 @@ private: static GX::LightMask sChannel0DisableLightMask; static GX::LightMask sChannel1EnableLightMask; }; + +template <> +aurora::Vec2 cinput_stream_helper(CInputStream& in); } // namespace metaforce diff --git a/Runtime/Graphics/CCubeRenderer.cpp b/Runtime/Graphics/CCubeRenderer.cpp index 8cb58c6e4..b82cd09ce 100644 --- a/Runtime/Graphics/CCubeRenderer.cpp +++ b/Runtime/Graphics/CCubeRenderer.cpp @@ -16,6 +16,8 @@ #include "Runtime/Particle/CElementGen.hpp" #include "Runtime/CDvdFile.hpp" +#include + namespace metaforce { static logvisor::Module Log("CCubeRenderer"); @@ -792,22 +794,22 @@ void CCubeRenderer::SetDebugOption(IRenderer::EDebugOption option, s32 value) { void CCubeRenderer::BeginPrimitive(IRenderer::EPrimitiveType type, s32 nverts) { constexpr std::array vtxDescList{ - GX::VtxDescList{GX::VA_POS, GX::DIRECT}, - GX::VtxDescList{GX::VA_NRM, GX::DIRECT}, - GX::VtxDescList{GX::VA_CLR0, GX::DIRECT}, - GX::VtxDescList{}, + GXVtxDescList{GX_VA_POS, GX_DIRECT}, + GXVtxDescList{GX_VA_NRM, GX_DIRECT}, + GXVtxDescList{GX_VA_CLR0, GX_DIRECT}, + GXVtxDescList{GX_VA_NULL, GX_NONE}, }; - CGX::SetChanCtrl(CGX::EChannelId::Channel0, false, GX::SRC_REG, GX::SRC_VTX, {}, GX::DF_NONE, GX::AF_NONE); + CGX::SetChanCtrl(CGX::EChannelId::Channel0, false, GX_SRC_REG, GX_SRC_VTX, {}, GX_DF_NONE, GX_AF_NONE); CGX::SetNumChans(1); CGX::SetNumTexGens(0); CGX::SetNumTevStages(1); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR0A0); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_RASC); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_RASA); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); x18_primVertCount = nverts; CGX::SetVtxDescv(vtxDescList.data()); - CGX::Begin(GX::Primitive(type), GX::VTXFMT0, nverts); + CGX::Begin(GXPrimitive(type), GX_VTXFMT0, nverts); } void CCubeRenderer::BeginLines(s32 nverts) { BeginPrimitive(EPrimitiveType::Lines, nverts); } @@ -864,22 +866,22 @@ void CCubeRenderer::DrawThermalModel(CModel& model, const zeus::CColor& multCol, void CCubeRenderer::DrawModelDisintegrate(CModel& model, CTexture& tex, const zeus::CColor& color, TConstVectorRef positions, TConstVectorRef normals, float t) { - tex.Load(GX::TEXMAP0, EClampMode::Clamp); + tex.Load(GX_TEXMAP0, EClampMode::Clamp); CGX::SetNumIndStages(0); CGX::SetNumTevStages(2); CGX::SetNumTexGens(2); CGX::SetNumChans(0); - CGX::SetBlendMode(GX::BM_BLEND, GX::BL_SRCALPHA, GX::BL_INVSRCALPHA, GX::LO_CLEAR); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE1); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_TEXC); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_TEXA); - CGX::SetTevColorIn(GX::TEVSTAGE1, GX::CC_ZERO, GX::CC_TEXC, GX::CC_CPREV, GX::CC_KONST); - CGX::SetTevAlphaIn(GX::TEVSTAGE1, GX::CA_ZERO, GX::CA_TEXA, GX::CA_APREV, GX::CA_ZERO); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); - CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD1, GX::TEXMAP0, GX::COLOR_NULL); - CGX::SetTevKColorSel(GX::TEVSTAGE1, GX::TEV_KCSEL_K0); - CGX::SetTevKColor(GX::KCOLOR0, color); + CGX::SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE1); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA); + CGX::SetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_KONST); + CGX::SetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP0, GX_COLOR_NULL); + CGX::SetTevKColorSel(GX_TEVSTAGE1, GX_TEV_KCSEL_K0); + CGX::SetTevKColor(GX_KCOLOR0, color); const auto bounds = model.GetInstance().GetBounds(); const auto rotation = zeus::CTransform::RotateX(zeus::degToRad(-45.f)); const auto transformedBounds = bounds.getTransformedAABox(rotation); @@ -901,43 +903,43 @@ void CCubeRenderer::DrawModelDisintegrate(CModel& model, CTexture& tex, const ze }, zeus::CVector3f{t, ptTex1.origin.y(), 1.f}, }; - GXLoadTexMtxImm(&xf, GX::TEXMTX0, GX::MTX3x4); - GXLoadTexMtxImm(&ptTex0, GX::PTTEXMTX0, GX::MTX3x4); - GXLoadTexMtxImm(&ptTex1, GX::PTTEXMTX1, GX::MTX3x4); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX3x4, GX::TG_POS, GX::TEXMTX0, false, GX::PTTEXMTX0); - CGX::SetTexCoordGen(GX::TEXCOORD1, GX::TG_MTX3x4, GX::TG_POS, GX::TEXMTX0, false, GX::PTTEXMTX1); - CGX::SetAlphaCompare(GX::GREATER, 0, GX::AOP_AND, GX::ALWAYS, 0); - CGX::SetZMode(true, GX::LEQUAL, true); + GXLoadTexMtxImm(&xf, GX_TEXMTX0, GX_MTX3x4); + GXLoadTexMtxImm(&ptTex0, GX_PTTEXMTX0, GX_MTX3x4); + GXLoadTexMtxImm(&ptTex1, GX_PTTEXMTX1, GX_MTX3x4); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0, false, GX_PTTEXMTX0); + CGX::SetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0, false, GX_PTTEXMTX1); + CGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_ALWAYS, 0); + CGX::SetZMode(true, GX_LEQUAL, true); model.UpdateLastFrame(); model.GetInstance().DrawFlat(positions, normals, ESurfaceSelection::All); - CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_AND, GX::ALWAYS, 0); + CGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); } void CCubeRenderer::DrawModelFlat(CModel& model, const CModelFlags& flags, bool unsortedOnly, TConstVectorRef positions, TConstVectorRef normals) { if (flags.x0_blendMode >= 7) { - CGX::SetBlendMode(GX::BM_BLEND, GX::BL_SRCALPHA, GX::BL_ONE, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR); } else if (flags.x0_blendMode >= 5) { - CGX::SetBlendMode(GX::BM_BLEND, GX::BL_SRCALPHA, GX::BL_INVSRCALPHA, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); } else { - CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ONE, GX::BL_ZERO, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR); } - CGX::SetZMode(true, flags.x2_flags & CModelFlagBits::DepthTest ? GX::LEQUAL : GX::ALWAYS, + CGX::SetZMode(true, flags.x2_flags & CModelFlagBits::DepthTest ? GX_LEQUAL : GX_ALWAYS, flags.x2_flags.IsSet(CModelFlagBits::DepthUpdate)); CGX::SetNumTevStages(1); CGX::SetNumTexGens(1); CGX::SetNumChans(0); CGX::SetNumIndStages(0); - CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_AND, GX::ALWAYS, 0); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_KONST); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_KONST); - CGX::SetTevKColor(GX::KCOLOR0, flags.x4_color); - CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0); - CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); - CGX::SetTevDirect(GX::TEVSTAGE0); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_POS, GX::IDENTITY, false, GX::PTIDENTITY); + CGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_KONST); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_KONST); + CGX::SetTevKColor(GX_KCOLOR0, flags.x4_color); + CGX::SetTevKColorSel(GX_TEVSTAGE0, GX_TEV_KCSEL_K0); + CGX::SetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K0_A); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); + CGX::SetTevDirect(GX_TEVSTAGE0); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_POS, GX_IDENTITY, false, GX_PTIDENTITY); model.UpdateLastFrame(); model.GetInstance().DrawFlat(positions, normals, unsortedOnly ? ESurfaceSelection::Unsorted : ESurfaceSelection::All); } @@ -979,28 +981,29 @@ void CCubeRenderer::DoThermalBlendCold() { const auto width = CGraphics::GetViewportWidth(); const auto top = CGraphics::GetViewportTop(); const auto left = CGraphics::GetViewportLeft(); - CGX::SetZMode(true, GX::LEQUAL, false); + CGX::SetZMode(true, GX_LEQUAL, false); // GXSetTexCopySrc(left, top, width, height); - // GXSetTexCopyDst(width, height, GX::TF_I4, false); + // GXSetTexCopyDst(width, height, GX_TF_I4, false); // GXCopyTex(sSpareTextureData, true); - CGraphics::ResolveSpareTexture( - aurora::gfx::ClipRect{ - .x = static_cast(left), - .y = static_cast(top), - .width = static_cast(width), - .height = static_cast(height), - }, - 0, GX::TF_I4); - // CGraphics::LoadDolphinSpareTexture(width, height, GX::TF_I4, nullptr, GX::TEXMAP7); - CGraphics::LoadDolphinSpareTexture(0, GX::TF_I4, GX::TEXMAP7); + // TODO TODO TODO +// CGraphics::ResolveSpareTexture( +// aurora::gfx::ClipRect{ +// .x = static_cast(left), +// .y = static_cast(top), +// .width = static_cast(width), +// .height = static_cast(height), +// }, +// 0, GX_TF_I4); + // CGraphics::LoadDolphinSpareTexture(width, height, GX_TF_I4, nullptr, GX_TEXMAP7); + CGraphics::LoadDolphinSpareTexture(0, GX_TF_I4, GX_TEXMAP7); // Upload random static texture (game reads from .text) const u8* buf = CDvdFile::GetDolBuf() + 0x4f60; u8* out = m_thermalRandomStatic.Lock(); memcpy(out, buf + ROUND_UP_32(x2a8_thermalRand.Next()), m_thermalRandomStatic.GetMemoryAllocated()); m_thermalRandomStatic.UnLock(); - m_thermalRandomStatic.Load(GX::TEXMAP0, EClampMode::Clamp); - m_thermalRandomStatic.Load(GX::TEXMAP1, EClampMode::Clamp); + m_thermalRandomStatic.Load(GX_TEXMAP0, EClampMode::Clamp); + m_thermalRandomStatic.Load(GX_TEXMAP1, EClampMode::Clamp); // Configure indirect texturing const float level = std::clamp(x2f0_thermalVisorLevel * 0.5f, 0.f, 0.5f); @@ -1009,10 +1012,10 @@ void CCubeRenderer::DoThermalBlendCold() { aurora::Vec2{0.f, 0.f}, aurora::Vec2{0.f, level}, }; - GXSetIndTexMtx(GX::ITM_0, &mtx, -2); - CGX::SetTevIndirect(GX::TEVSTAGE0, GX::INDTEXSTAGE0, GX::ITF_8, GX::ITB_STU, GX::ITM_0, GX::ITW_OFF, GX::ITW_OFF, - false, false, GX::ITBA_OFF); - GXSetIndTexOrder(GX::INDTEXSTAGE0, GX::TEXCOORD0, GX::TEXMAP0); + GXSetIndTexMtx(GX_ITM_0, &mtx, -2); + CGX::SetTevIndirect(GX_TEVSTAGE0, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_STU, GX_ITM_0, GX_ITW_OFF, GX_ITW_OFF, false, + false, GX_ITBA_OFF); + GXSetIndTexOrder(GX_INDTEXSTAGE0, GX_TEXCOORD0, GX_TEXMAP0); // Configure register colors const auto color0 = zeus::CColor::lerp(x2f4_thermColor, zeus::skWhite, x2f8_thermColdScale); @@ -1028,40 +1031,40 @@ void CCubeRenderer::DoThermalBlendCold() { cFac = (x2f8_thermColdScale - 0.25f) * 4.f / 3.f; } const zeus::CColor color2{cFac, cFac}; - GXSetTevColor(GX::TEVREG0, color0); - GXSetTevColor(GX::TEVREG1, color1); - GXSetTevColor(GX::TEVREG2, color2); + GXSetTevColor(GX_TEVREG0, to_gx_color(color0)); + GXSetTevColor(GX_TEVREG1, to_gx_color(color1)); + GXSetTevColor(GX_TEVREG2, to_gx_color(color2)); // Configure TEV stage 0 - GXSetTevSwapMode(GX::TEVSTAGE0, GX::TEV_SWAP0, GX::TEV_SWAP1); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXC, GX::CC_C0, GX::CC_C2); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_TEXA, GX::CA_A1, GX::CA_A2); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP7, GX::COLOR_NULL); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP1); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_C0, GX_CC_C2); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_A1, GX_CA_A2); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP7, GX_COLOR_NULL); // Configure TEV stage 1 - GXSetTevSwapMode(GX::TEVSTAGE1, GX::TEV_SWAP0, GX::TEV_SWAP1); - CGX::SetTevColorIn(GX::TEVSTAGE1, GX::CC_ZERO, GX::CC_TEXC, GX::CC_C1, GX::CC_CPREV); - CGX::SetTevColorOp(GX::TEVSTAGE1, GX::TEV_SUB, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); - CGX::SetTevAlphaIn(GX::TEVSTAGE1, GX::CA_ZERO, GX::CA_A1, GX::CA_TEXA, GX::CA_APREV); - CGX::SetTevAlphaOp(GX::TEVSTAGE1, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_4, true, GX::TEVPREV); - CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD0, GX::TEXMAP1, GX::COLOR_NULL); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP1); + CGX::SetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_TEXC, GX_CC_C1, GX_CC_CPREV); + CGX::SetTevColorOp(GX_TEVSTAGE1, GX_TEV_SUB, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + CGX::SetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_A1, GX_CA_TEXA, GX_CA_APREV); + CGX::SetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, true, GX_TEVPREV); + CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR_NULL); // Configure everything else - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX3x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); - CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_AND, GX::ALWAYS, 0); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); CGX::SetNumTevStages(2); CGX::SetNumTexGens(1); CGX::SetNumChans(0); CGX::SetNumIndStages(1); - CGX::SetZMode(false, GX::ALWAYS, false); + CGX::SetZMode(false, GX_ALWAYS, false); constexpr std::array vtxDescList{ - GX::VtxDescList{GX::VA_POS, GX::DIRECT}, - GX::VtxDescList{GX::VA_TEX0, GX::DIRECT}, - GX::VtxDescList{}, + GXVtxDescList{GX_VA_POS, GX_DIRECT}, + GXVtxDescList{GX_VA_TEX0, GX_DIRECT}, + GXVtxDescList{GX_VA_NULL, GX_NONE}, }; CGX::SetVtxDescv(vtxDescList.data()); - CGX::SetBlendMode(GX::BM_NONE, GX::BL_ONE, GX::BL_ZERO, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR); // Backup & set viewport/projection const auto backupViewMatrix = CGraphics::g_ViewMatrix; @@ -1072,7 +1075,7 @@ void CCubeRenderer::DoThermalBlendCold() { GXPixModeSync(); // Draw - CGX::Begin(GX::TRIANGLEFAN, GX::VTXFMT0, 4); + CGX::Begin(GX_TRIANGLEFAN, GX_VTXFMT0, 4); GXPosition3f32(0.f, 0.5f, 0.f); GXTexCoord2f32(0.f, 0.f); GXPosition3f32(0.f, 0.5f, static_cast(height)); @@ -1084,10 +1087,10 @@ void CCubeRenderer::DoThermalBlendCold() { CGX::End(); // Cleanup - GXSetTevSwapMode(GX::TEVSTAGE0, GX::TEV_SWAP0, GX::TEV_SWAP0); - GXSetTevSwapMode(GX::TEVSTAGE1, GX::TEV_SWAP0, GX::TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0); CGX::SetNumIndStages(0); - CGX::SetTevDirect(GX::TEVSTAGE0); + CGX::SetTevDirect(GX_TEVSTAGE0); GXSetDstAlpha(false, 255); CGraphics::SetProjectionState(backupProjectionState); CGraphics::SetViewPointMatrix(backupViewMatrix); @@ -1104,31 +1107,31 @@ void CCubeRenderer::DoThermalBlendHot() { const auto width = CGraphics::GetViewportWidth(); const auto top = CGraphics::GetViewportTop(); const auto left = CGraphics::GetViewportLeft(); - CGX::SetZMode(true, GX::LEQUAL, true); + CGX::SetZMode(true, GX_LEQUAL, true); // GXSetTexCopySrc(left, top, width, height); - // GXSetTexCopyDst(width, height, GX::TF_I4, false); + // GXSetTexCopyDst(width, height, GX_TF_I4, false); // GXCopyTex(sSpareTextureData, false); - CGraphics::ResolveSpareTexture(CGraphics::g_Viewport, 0, GX::TF_I4); + CGraphics::ResolveSpareTexture(CGraphics::g_Viewport, 0, GX_TF_I4); x288_thermoPalette.Load(); - // CGraphics::LoadDolphinSpareTexture(width, height, GX::TF_C4, GX::TLUT0, nullptr, GX::TEXMAP7); - CGraphics::LoadDolphinSpareTexture(0, GX_TF_C4, GX_TLUT0, GX::TEXMAP7); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXA, GX::CC_TEXC, GX::CC_ZERO); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_TEXA); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP7, GX::COLOR_NULL); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX3x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); - CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_AND, GX::ALWAYS, 0); + // CGraphics::LoadDolphinSpareTexture(width, height, GX_TF_C4, GX::TLUT0, nullptr, GX_TEXMAP7); + CGraphics::LoadDolphinSpareTexture(0, GX_TF_C4, GX_TLUT0, GX_TEXMAP7); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXA, GX_CC_TEXC, GX_CC_ZERO); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP7, GX_COLOR_NULL); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); CGX::SetNumTevStages(1); CGX::SetNumTexGens(1); CGX::SetNumChans(0); - CGX::SetZMode(false, GX::LEQUAL, false); + CGX::SetZMode(false, GX_LEQUAL, false); constexpr std::array vtxDescList{ - GX::VtxDescList{GX::VA_POS, GX::DIRECT}, - GX::VtxDescList{GX::VA_TEX0, GX::DIRECT}, - GX::VtxDescList{}, + GXVtxDescList{GX_VA_POS, GX_DIRECT}, + GXVtxDescList{GX_VA_TEX0, GX_DIRECT}, + GXVtxDescList{GX_VA_NULL, GX_NONE}, }; CGX::SetVtxDescv(vtxDescList.data()); - CGX::SetBlendMode(GX::BM_BLEND, GX::BL_DSTALPHA, GX::BL_INVDSTALPHA, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_BLEND, GX_BL_DSTALPHA, GX_BL_INVDSTALPHA, GX_LO_CLEAR); // Backup & set viewport/projection const auto backupViewMatrix = CGraphics::g_ViewMatrix; @@ -1139,7 +1142,7 @@ void CCubeRenderer::DoThermalBlendHot() { GXPixModeSync(); // Draw - CGX::Begin(GX::TRIANGLEFAN, GX::VTXFMT0, 4); + CGX::Begin(GX_TRIANGLEFAN, GX_VTXFMT0, 4); GXPosition3f32(0.f, 0.5f, 0.f); GXTexCoord2f32(0.f, 0.f); GXPosition3f32(0.f, 0.5f, static_cast(height)); @@ -1152,7 +1155,7 @@ void CCubeRenderer::DoThermalBlendHot() { // Cleanup CGX::SetNumIndStages(0); - CGX::SetTevDirect(GX::TEVSTAGE0); + CGX::SetTevDirect(GX_TEVSTAGE0); GXSetAlphaUpdate(true); CGraphics::SetProjectionState(backupProjectionState); CGraphics::SetViewPointMatrix(backupViewMatrix); @@ -1165,7 +1168,7 @@ u32 CCubeRenderer::GetStaticWorldDataSize() { return 0; } -void CCubeRenderer::SetGXRegister1Color(const zeus::CColor& color) { GXSetTevColor(GX::TevRegID::TEVREG1, color); } +void CCubeRenderer::SetGXRegister1Color(const zeus::CColor& color) { GXSetTevColor(GX_TEVREG1, to_gx_color(color)); } void CCubeRenderer::SetWorldLightFadeLevel(float level) { x2fc_tevReg1Color = zeus::CColor(level, level, level, 1.f); } @@ -1348,7 +1351,7 @@ void CCubeRenderer::DrawOverlappingWorldModelShadows(s32 alphaVal, const std::ve } auto& model = *(*item.x10_models)[wordModel + j]; - CGX::SetTevKColor(GX::KCOLOR0, zeus::CColor{0.f, static_cast(alphaVal) / 255.f}); + CGX::SetTevKColor(GX_KCOLOR0, zeus::CColor{0.f, static_cast(alphaVal) / 255.f}); model.SetArraysCurrent(); for (const auto* surf = model.GetFirstUnsortedSurface(); surf != nullptr; surf = surf->GetNextSurface()) { if (surf->GetBounds().intersects(aabb)) { @@ -1373,8 +1376,7 @@ void CCubeRenderer::SetupCGraphicsState() { CGraphics::SetAmbientColor({0.4f}); CGX::SetChanMatColor(CGX::EChannelId::Channel0, zeus::skWhite); CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true); - CGX::SetChanCtrl(CGX::EChannelId::Channel1, false, GX::SRC_REG, GX::SRC_REG, GX::LIGHT_NULL, GX::DF_NONE, - GX::AF_NONE); + CGX::SetChanCtrl(CGX::EChannelId::Channel1, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); CCubeMaterial::EnsureTevsDirect(); } @@ -1384,7 +1386,7 @@ void CCubeRenderer::SetupRendererStates(bool depthWrite) { CGraphics::SetAmbientColor(zeus::skClear); CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, depthWrite); CCubeMaterial::ResetCachedMaterials(); - GXSetTevColor(GX::TEVREG1, x2fc_tevReg1Color); + GXSetTevColor(GX_TEVREG1, to_gx_color(x2fc_tevReg1Color)); } constexpr zeus::CTransform MvPostXf{ @@ -1395,26 +1397,26 @@ constexpr zeus::CTransform MvPostXf{ void CCubeRenderer::DoThermalModelDraw(CCubeModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol, TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags) { SCOPED_GRAPHICS_DEBUG_GROUP("CCubeRenderer::DoThermalModelDraw", zeus::skBlue); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX3x4, GX::TG_NRM, GX::TEXMTX0, true, GX::PTTEXMTX0); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_NRM, GX_TEXMTX0, true, GX_PTTEXMTX0); CGX::SetNumTexGens(1); CGX::SetNumChans(0); - x220_sphereRamp.Load(GX::TEXMAP0, EClampMode::Clamp); + x220_sphereRamp.Load(GX_TEXMAP0, EClampMode::Clamp); zeus::CTransform xf = CGraphics::g_ViewMatrix.inverse().multiplyIgnoreTranslation(CGraphics::g_GXModelMatrix); xf.origin.zeroOut(); - GXLoadTexMtxImm(&xf, GX::TEXMTX0, GX::MTX3x4); - GXLoadTexMtxImm(&MvPostXf, GX::PTTEXMTX0, GX::MTX3x4); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_C0, GX::CC_TEXC, GX::CC_KONST); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_TEXA, GX::CA_A0, GX::CA_KONST); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); + GXLoadTexMtxImm(&xf, GX_TEXMTX0, GX_MTX3x4); + GXLoadTexMtxImm(&MvPostXf, GX_PTTEXMTX0, GX_MTX3x4); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_C0, GX_CC_TEXC, GX_CC_KONST); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_A0, GX_CA_KONST); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); CGX::SetNumTevStages(1); - CGX::SetTevKColor(GX::KCOLOR0, addCol); - CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0); - CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A); - GXSetTevColor(GX::TEVREG0, multCol); - CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_OR, GX::ALWAYS, 0); - CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ONE, GX::BL_ONE, GX::LO_CLEAR); - CGX::SetZMode(flags.x2_flags.IsSet(CModelFlagBits::DepthTest), GX::LEQUAL, + CGX::SetTevKColor(GX_KCOLOR0, addCol); + CGX::SetTevKColorSel(GX_TEVSTAGE0, GX_TEV_KCSEL_K0); + CGX::SetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K0_A); + GXSetTevColor(GX_TEVREG0, to_gx_color(multCol)); + CGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0); + CGX::SetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR); + CGX::SetZMode(flags.x2_flags.IsSet(CModelFlagBits::DepthTest), GX_LEQUAL, flags.x2_flags.IsSet(CModelFlagBits::DepthUpdate)); model.DrawFlat(positions, normals, flags.x2_flags.IsSet(CModelFlagBits::ThermalUnsortedOnly) ? ESurfaceSelection::Unsorted @@ -1458,16 +1460,16 @@ void CCubeRenderer::ReallyDrawSpaceWarp(const zeus::CVector3f& pt, float strengt } const auto v2sub = v2left - v2right; if (v2sub.x > 0 && v2sub.y > 0) { - GX::FogType fogType; + GXFogType fogType; float fogStartZ; float fogEndZ; float fogNearZ; float fogFarZ; GXColor fogColor; CGX::GetFog(&fogType, &fogStartZ, &fogEndZ, &fogNearZ, &fogFarZ, &fogColor); - CGX::SetFog(GX::FOG_NONE, fogStartZ, fogEndZ, fogNearZ, fogFarZ, fogColor); + CGX::SetFog(GX_FOG_NONE, fogStartZ, fogEndZ, fogNearZ, fogFarZ, fogColor); // GXSetTexCopySrc(v2right.x, v2right.y, v2sub.x, v2sub.y); - // GXSetTexCopyDst(v2sub.x, v2sub.y, GX::TF_RGBA8, false); + // GXSetTexCopyDst(v2sub.x, v2sub.y, GX_TF_RGBA8, false); // GXCopyTex(sSpareTextureData, false); // GXPixModeSync(); CGraphics::ResolveSpareTexture( @@ -1477,14 +1479,14 @@ void CCubeRenderer::ReallyDrawSpaceWarp(const zeus::CVector3f& pt, float strengt .x8_width = static_cast(v2sub.x), .xc_height = static_cast(v2sub.y), }, - 1, GX::TF_RGBA8); - CGraphics::LoadDolphinSpareTexture(1, GX::TF_RGBA8, GX::TEXMAP7); - x150_reflectionTex.Load(GX::TEXMAP1, EClampMode::Clamp); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_TEXC); - CGX::SetTevColorOp(GX::TEVSTAGE0, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX3x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); - CGX::SetTexCoordGen(GX::TEXCOORD1, GX::TG_MTX3x4, GX::TG_TEX1, GX::IDENTITY, false, GX::PTIDENTITY); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP7, GX::COLOR_NULL); + 1, GX_TF_RGBA8); + CGraphics::LoadDolphinSpareTexture(1, GX_TF_RGBA8, GX_TEXMAP7); + x150_reflectionTex.Load(GX_TEXMAP1, EClampMode::Clamp); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC); + CGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::SetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX3x4, GX_TG_TEX1, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP7, GX_COLOR_NULL); } } diff --git a/Runtime/Graphics/CGX.cpp b/Runtime/Graphics/CGX.cpp index 8569877ad..ce3c618dc 100644 --- a/Runtime/Graphics/CGX.cpp +++ b/Runtime/Graphics/CGX.cpp @@ -4,27 +4,27 @@ namespace metaforce::CGX { SGXState sGXState{}; -std::array sVtxDescList{}; +std::array sVtxDescList{}; void ResetGXStates() noexcept { sGXState.x48_descList = 0; GXClearVtxDesc(); sGXState.x0_arrayPtrs.fill(nullptr); - for (GX::TexMapID id = GX::TEXMAP0; id < GX::MAX_TEXMAP; id = static_cast(id + 1)) { + for (GXTexMapID id = GX_TEXMAP0; id < GX_MAX_TEXMAP; id = static_cast(id + 1)) { CTexture::InvalidateTexMap(id); } - for (GX::TevKColorID id = GX::KCOLOR0; const auto& item : sGXState.x58_kColors) { + for (GXTevKColorID id = GX_KCOLOR0; const auto& item : sGXState.x58_kColors) { GXSetTevKColor(id, item); - id = static_cast(id + 1); + id = static_cast(id + 1); } - GXSetTevSwapModeTable(GX::TEV_SWAP1, GX::CH_RED, GX::CH_GREEN, GX::CH_BLUE, GX::CH_RED); - GXSetTevSwapModeTable(GX::TEV_SWAP2, GX::CH_RED, GX::CH_GREEN, GX::CH_BLUE, GX::CH_GREEN); - GXSetTevSwapModeTable(GX::TEV_SWAP3, GX::CH_RED, GX::CH_GREEN, GX::CH_BLUE, GX::CH_BLUE); - SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_AND, GX::ALWAYS, 0); - // GXSetCurrentMtx(0); + GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_RED); + GXSetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_GREEN); + GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_BLUE); + SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + GXSetCurrentMtx(GX_PNMTX0); SetNumIndStages(0); // TODO GXSetIndTexCoordScale - for (GX::TevStageID id = GX::TEVSTAGE0; id < GX::MAX_TEVSTAGE; id = static_cast(id + 1)) { + for (GXTevStageID id = GX_TEVSTAGE0; id < GX_MAX_TEVSTAGE; id = static_cast(id + 1)) { SetTevDirect(id); } // GXSetTexCoordCylWrap diff --git a/Runtime/Graphics/CGX.hpp b/Runtime/Graphics/CGX.hpp index ff52bdb10..efa17c9ba 100644 --- a/Runtime/Graphics/CGX.hpp +++ b/Runtime/Graphics/CGX.hpp @@ -7,8 +7,8 @@ namespace metaforce::CGX { enum class EChannelId { - Channel0, // GX::COLOR0 - Channel1, // GX::COLOR1 + Channel0, // GX_COLOR0 + Channel1, // GX_COLOR1 }; struct STevState { @@ -18,8 +18,8 @@ struct STevState { u32 xc_alphaOps = 0; u32 x10_indFlags = 0; u32 x14_tevOrderFlags = 0; - GX::TevKColorSel x18_kColorSel = GX::TEV_KCSEL_1; - GX::TevKAlphaSel x19_kAlphaSel = GX::TEV_KASEL_1; + GXTevKColorSel x18_kColorSel = GX_TEV_KCSEL_1; + GXTevKAlphaSel x19_kAlphaSel = GX_TEV_KASEL_1; }; struct STexState { u32 x0_coordGen = 0; @@ -38,12 +38,12 @@ struct SGXState { u8 x50_numTevStages = 0; u8 x51_numIndStages = 0; u8 x52_zmode = 0; - GX::FogType x53_fogType = GX::FOG_NONE; + GXFogType x53_fogType = GX_FOG_NONE; u16 x54_lineWidthAndOffset = 0; u16 x56_blendMode = 0; - std::array x58_kColors; - std::array x68_tevStates; - std::array x228_texStates; + std::array x58_kColors; + std::array x68_tevStates; + std::array x228_texStates; u32 x248_alphaCompare = 0; float x24c_fogStartZ = 0.f; float x250_fogEndZ = 0.f; @@ -52,14 +52,14 @@ struct SGXState { GXColor x25c_fogColor; }; extern SGXState sGXState; -extern std::array sVtxDescList; +extern std::array sVtxDescList; static inline void update_fog(u32 value) noexcept { - if (sGXState.x53_fogType == GX::FOG_NONE || (sGXState.x56_blendMode & 0xE0) == (value & 0xE0)) { + if (sGXState.x53_fogType == GX_FOG_NONE || (sGXState.x56_blendMode & 0xE0) == (value & 0xE0)) { return; } if ((value & 0xE0) == 0x20) { - GXSetFogColor(zeus::skClear); + GXSetFogColor(GX_CLEAR); return; } GXSetFogColor(sGXState.x25c_fogColor); @@ -72,23 +72,21 @@ static inline void FlushState() noexcept { sGXState.x4d_prevNumChans = numChans; } if ((sGXState.x4c_dirtyChans & 2) != 0) { - // TODO actually COLOR0 auto flags = sGXState.x34_chanCtrls[0]; - GXSetChanCtrl(GX::COLOR0A0, GXBool(flags & 1), GX::ColorSrc(flags >> 1 & 1), GX::ColorSrc(flags >> 2 & 1), - flags >> 3 & 0xFF, GX::DiffuseFn(flags >> 11 & 3), GX::AttnFn(flags >> 13 & 3)); + GXSetChanCtrl(GX_COLOR0, GXBool(flags & 1), GXColorSrc(flags >> 1 & 1), GXColorSrc(flags >> 2 & 1), + flags >> 3 & 0xFF, GXDiffuseFn(flags >> 11 & 3), GXAttnFn(flags >> 13 & 3)); sGXState.x30_prevChanCtrls[0] = flags; } if ((sGXState.x4c_dirtyChans & 4) != 0) { - // TODO actually COLOR1 auto flags = sGXState.x34_chanCtrls[1]; - GXSetChanCtrl(GX::COLOR1A1, GXBool(flags & 1), GX::ColorSrc(flags >> 1 & 1), GX::ColorSrc(flags >> 2 & 1), - flags >> 3 & 0xFF, GX::DiffuseFn(flags >> 11 & 3), GX::AttnFn(flags >> 13 & 3)); + GXSetChanCtrl(GX_COLOR1, GXBool(flags & 1), GXColorSrc(flags >> 1 & 1), GXColorSrc(flags >> 2 & 1), + flags >> 3 & 0xFF, GXDiffuseFn(flags >> 11 & 3), GXAttnFn(flags >> 13 & 3)); sGXState.x30_prevChanCtrls[1] = flags; } sGXState.x4c_dirtyChans = 0; } -static inline void Begin(GX::Primitive primitive, GX::VtxFmt fmt, u16 nverts) noexcept { +static inline void Begin(GXPrimitive primitive, GXVtxFmt fmt, u16 nverts) noexcept { if (sGXState.x4c_dirtyChans != 0) { FlushState(); } @@ -111,24 +109,23 @@ static inline const GXColor& GetChanAmbColor(EChannelId id) noexcept { void ResetGXStates() noexcept; -static inline void SetAlphaCompare(GX::Compare comp0, u8 ref0, GX::AlphaOp op, GX::Compare comp1, u8 ref1) noexcept { +static inline void SetAlphaCompare(GXCompare comp0, u8 ref0, GXAlphaOp op, GXCompare comp1, u8 ref1) noexcept { u32 flags = ref1 << 17 | (comp1 & 7) << 14 | (op & 7) << 11 | ref0 << 3 | (comp0 & 7); if (flags != sGXState.x248_alphaCompare) { sGXState.x248_alphaCompare = flags; GXSetAlphaCompare(comp0, ref0, op, comp1, ref1); - // GXSetZCompLoc(comp0 == GX::ALWAYS); + GXSetZCompLoc(comp0 == GX_ALWAYS); } } template -static inline void SetArray(GX::Attr attr, const std::vector* data, bool isStatic) noexcept { - if (data != nullptr && sGXState.x0_arrayPtrs[attr - GX::VA_POS] != data) { - GXSetArray(attr, data, isStatic ? 1 : 0); +static inline void SetArray(GXAttr attr, const std::vector* data, bool isStatic) noexcept { + if (data != nullptr && sGXState.x0_arrayPtrs[attr - GX_VA_POS] != data) { + GXSetArray(attr, data->data(), data->size() * sizeof(T), sizeof(T)); } } -static inline void SetBlendMode(GX::BlendMode mode, GX::BlendFactor srcFac, GX::BlendFactor dstFac, - GX::LogicOp op) noexcept { +static inline void SetBlendMode(GXBlendMode mode, GXBlendFactor srcFac, GXBlendFactor dstFac, GXLogicOp op) noexcept { const u16 flags = (op & 0xF) << 8 | (dstFac & 7) << 5 | (srcFac & 7) << 2 | (mode & 3); if (flags != sGXState.x56_blendMode) { update_fog(flags); @@ -137,16 +134,19 @@ static inline void SetBlendMode(GX::BlendMode mode, GX::BlendFactor srcFac, GX:: } } -static inline void SetChanAmbColor(EChannelId id, const GXColor& color) noexcept { +static inline void SetChanAmbColor(EChannelId id, GXColor color) noexcept { const auto idx = std::underlying_type_t(id); if (color != sGXState.x38_chanAmbColors[idx]) { sGXState.x38_chanAmbColors[idx] = color; - GXSetChanAmbColor(GX::ChannelID(idx + GX::COLOR0A0), color); + GXSetChanAmbColor(GXChannelID(idx + GX_COLOR0A0), color); } } +static inline void SetChanAmbColor(EChannelId id, const zeus::CColor& color) noexcept { + SetChanAmbColor(id, to_gx_color(color)); +} -static inline void SetChanCtrl(EChannelId id, GXBool enable, GX::ColorSrc ambSrc, GX::ColorSrc matSrc, - GX::LightMask lights, GX::DiffuseFn diffFn, GX::AttnFn attnFn) noexcept { +static inline void SetChanCtrl(EChannelId id, GXBool enable, GXColorSrc ambSrc, GXColorSrc matSrc, GX::LightMask lights, + GXDiffuseFn diffFn, GXAttnFn attnFn) noexcept { const auto idx = std::underlying_type_t(id); if (lights.none()) { enable = false; @@ -167,19 +167,22 @@ static inline void SetChanCtrl(EChannelId id, u32 flags, GX::LightMask lights) n // Helper function for common logic static inline void SetChanCtrl(EChannelId id, GX::LightMask lights) noexcept { const bool hasLights = lights.any(); - SetChanCtrl(id, hasLights, GX::SRC_REG, GX::SRC_REG, lights, hasLights ? GX::DF_CLAMP : GX::DF_NONE, - hasLights ? GX::AF_SPOT : GX::AF_NONE); + SetChanCtrl(id, hasLights, GX_SRC_REG, GX_SRC_REG, lights, hasLights ? GX_DF_CLAMP : GX_DF_NONE, + hasLights ? GX_AF_SPOT : GX_AF_NONE); } -static inline void SetChanMatColor(EChannelId id, const GXColor& color) noexcept { +static inline void SetChanMatColor(EChannelId id, GXColor color) noexcept { const auto idx = std::underlying_type_t(id); if (color != sGXState.x40_chanMatColors[idx]) { sGXState.x40_chanMatColors[idx] = color; - GXSetChanMatColor(GX::ChannelID(idx + GX::COLOR0A0), color); + GXSetChanMatColor(GXChannelID(idx + GX_COLOR0A0), color); } } +static inline void SetChanMatColor(EChannelId id, const zeus::CColor& color) noexcept { + SetChanMatColor(id, to_gx_color(color)); +} -static inline void SetFog(GX::FogType type, float startZ, float endZ, float nearZ, float farZ, +static inline void SetFog(GXFogType type, float startZ, float endZ, float nearZ, float farZ, const GXColor& color) noexcept { sGXState.x25c_fogColor = color; sGXState.x53_fogType = type; @@ -189,14 +192,14 @@ static inline void SetFog(GX::FogType type, float startZ, float endZ, float near sGXState.x258_fogFarZ = farZ; auto fogColor = color; if ((sGXState.x56_blendMode & 0xE0) == 0x20) { - fogColor = zeus::skClear; + fogColor = GX_CLEAR; } GXSetFog(type, startZ, endZ, nearZ, farZ, fogColor); } -void SetIndTexMtxSTPointFive(GX::IndTexMtxID id, s8 scaleExp) noexcept; +void SetIndTexMtxSTPointFive(GXIndTexMtxID id, s8 scaleExp) noexcept; -void SetLineWidth(u8 width, GX::TexOffset offset) noexcept; +void SetLineWidth(u8 width, GXTexOffset offset) noexcept; static inline void SetNumChans(u8 num) noexcept { sGXState.x4c_dirtyChans = 7; // TODO @@ -227,18 +230,18 @@ static inline void SetNumTexGens(u8 num) noexcept { } } -static inline void SetStandardTevColorAlphaOp(GX::TevStageID stageId) noexcept { +static inline void SetStandardTevColorAlphaOp(GXTevStageID stageId) noexcept { auto& state = sGXState.x68_tevStates[stageId]; if (state.x8_colorOps != 0x100 || state.xc_alphaOps != 0x100) { state.x8_colorOps = 0x100; state.xc_alphaOps = 0x100; - GXSetTevColorOp(stageId, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); - GXSetTevAlphaOp(stageId, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); + GXSetTevColorOp(stageId, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + GXSetTevAlphaOp(stageId, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); } } -static inline void SetTevAlphaIn(GX::TevStageID stageId, GX::TevAlphaArg a, GX::TevAlphaArg b, GX::TevAlphaArg c, - GX::TevAlphaArg d) noexcept { +static inline void SetTevAlphaIn(GXTevStageID stageId, GXTevAlphaArg a, GXTevAlphaArg b, GXTevAlphaArg c, + GXTevAlphaArg d) noexcept { u32 flags = (d & 31) << 15 | (c & 31) << 10 | (b & 31) << 5 | (a & 31); auto& state = sGXState.x68_tevStates[stageId].x4_alphaInArgs; if (flags != state) { @@ -247,8 +250,8 @@ static inline void SetTevAlphaIn(GX::TevStageID stageId, GX::TevAlphaArg a, GX:: } } -static inline void SetTevAlphaOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, - GXBool clamp, GX::TevRegID outReg) noexcept { +static inline void SetTevAlphaOp(GXTevStageID stageId, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, + GXTevRegID outReg) noexcept { u32 flags = (outReg & 3) << 9 | (u8(clamp) & 1) << 8 | (scale & 3) << 6 | (bias & 3) << 4 | (op & 15); auto& state = sGXState.x68_tevStates[stageId].xc_alphaOps; if (flags != state) { @@ -257,17 +260,17 @@ static inline void SetTevAlphaOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBi } } -static inline void SetTevAlphaOp_Compressed(GX::TevStageID stageId, u32 ops) noexcept { +static inline void SetTevAlphaOp_Compressed(GXTevStageID stageId, u32 ops) noexcept { auto& state = sGXState.x68_tevStates[stageId].xc_alphaOps; if (ops != state) { state = ops; - GXSetTevAlphaOp(stageId, GX::TevOp(ops & 31), GX::TevBias(ops >> 4 & 3), GX::TevScale(ops >> 6 & 3), - GXBool(ops >> 8 & 1), GX::TevRegID(ops >> 9 & 3)); + GXSetTevAlphaOp(stageId, GXTevOp(ops & 31), GXTevBias(ops >> 4 & 3), GXTevScale(ops >> 6 & 3), GXBool(ops >> 8 & 1), + GXTevRegID(ops >> 9 & 3)); } } -static inline void SetTevColorIn(GX::TevStageID stageId, GX::TevColorArg a, GX::TevColorArg b, GX::TevColorArg c, - GX::TevColorArg d) noexcept { +static inline void SetTevColorIn(GXTevStageID stageId, GXTevColorArg a, GXTevColorArg b, GXTevColorArg c, + GXTevColorArg d) noexcept { u32 flags = (d & 31) << 15 | (c & 31) << 10 | (b & 31) << 5 | (a & 31); auto& state = sGXState.x68_tevStates[stageId].x0_colorInArgs; if (flags != state) { @@ -276,8 +279,8 @@ static inline void SetTevColorIn(GX::TevStageID stageId, GX::TevColorArg a, GX:: } } -static inline void SetTevColorOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, - GXBool clamp, GX::TevRegID outReg) noexcept { +static inline void SetTevColorOp(GXTevStageID stageId, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, + GXTevRegID outReg) noexcept { u32 flags = (outReg & 3) << 9 | (u8(clamp) & 1) << 8 | (scale & 3) << 6 | (bias & 3) << 4 | (op & 15); auto& state = sGXState.x68_tevStates[stageId].x8_colorOps; if (flags != state) { @@ -286,16 +289,16 @@ static inline void SetTevColorOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBi } } -static inline void SetTevColorOp_Compressed(GX::TevStageID stageId, u32 ops) noexcept { +static inline void SetTevColorOp_Compressed(GXTevStageID stageId, u32 ops) noexcept { auto& state = sGXState.x68_tevStates[stageId].x8_colorOps; if (ops != state) { state = ops; - GXSetTevColorOp(stageId, GX::TevOp(ops & 31), GX::TevBias(ops >> 4 & 3), GX::TevScale(ops >> 6 & 3), - GXBool(ops >> 8 & 1), GX::TevRegID(ops >> 9 & 3)); + GXSetTevColorOp(stageId, GXTevOp(ops & 31), GXTevBias(ops >> 4 & 3), GXTevScale(ops >> 6 & 3), GXBool(ops >> 8 & 1), + GXTevRegID(ops >> 9 & 3)); } } -static inline void SetTevDirect(GX::TevStageID stageId) noexcept { +static inline void SetTevDirect(GXTevStageID stageId) noexcept { auto& state = sGXState.x68_tevStates[stageId].x10_indFlags; if (state != 0) { state = 0; @@ -303,19 +306,19 @@ static inline void SetTevDirect(GX::TevStageID stageId) noexcept { } } -static inline void SetStandardDirectTev_Compressed(GX::TevStageID stageId, u32 colorArgs, u32 alphaArgs, u32 colorOps, +static inline void SetStandardDirectTev_Compressed(GXTevStageID stageId, u32 colorArgs, u32 alphaArgs, u32 colorOps, u32 alphaOps) noexcept { auto& state = sGXState.x68_tevStates[stageId]; SetTevDirect(stageId); if (state.x0_colorInArgs != colorArgs) { state.x0_colorInArgs = colorArgs; - GXSetTevColorIn(stageId, GX::TevColorArg(colorArgs & 31), GX::TevColorArg(colorArgs >> 5 & 31), - GX::TevColorArg(colorArgs >> 10 & 31), GX::TevColorArg(colorArgs >> 15 & 31)); + GXSetTevColorIn(stageId, GXTevColorArg(colorArgs & 31), GXTevColorArg(colorArgs >> 5 & 31), + GXTevColorArg(colorArgs >> 10 & 31), GXTevColorArg(colorArgs >> 15 & 31)); } if (state.x4_alphaInArgs != alphaArgs) { state.x4_alphaInArgs = alphaArgs; - GXSetTevAlphaIn(stageId, GX::TevAlphaArg(alphaArgs & 31), GX::TevAlphaArg(alphaArgs >> 5 & 31), - GX::TevAlphaArg(alphaArgs >> 10 & 31), GX::TevAlphaArg(alphaArgs >> 15 & 31)); + GXSetTevAlphaIn(stageId, GXTevAlphaArg(alphaArgs & 31), GXTevAlphaArg(alphaArgs >> 5 & 31), + GXTevAlphaArg(alphaArgs >> 10 & 31), GXTevAlphaArg(alphaArgs >> 15 & 31)); } if (colorOps != alphaOps || (colorOps & 0x1FF) != 0x100) { SetTevColorOp_Compressed(stageId, colorOps); @@ -323,27 +326,26 @@ static inline void SetStandardDirectTev_Compressed(GX::TevStageID stageId, u32 c } else if (colorOps != state.x8_colorOps || colorOps != state.xc_alphaOps) { state.x8_colorOps = colorOps; state.xc_alphaOps = colorOps; - const auto outReg = GX::TevRegID(colorOps >> 9 & 3); - GXSetTevColorOp(stageId, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, outReg); - GXSetTevAlphaOp(stageId, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, outReg); + const auto outReg = GXTevRegID(colorOps >> 9 & 3); + GXSetTevColorOp(stageId, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, outReg); + GXSetTevAlphaOp(stageId, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, outReg); } } -static inline void SetTevIndirect(GX::TevStageID stageId, GX::IndTexStageID indStage, GX::IndTexFormat fmt, - GX::IndTexBiasSel biasSel, GX::IndTexMtxID mtxSel, GX::IndTexWrap wrapS, - GX::IndTexWrap wrapT, GXBool addPrev, GXBool indLod, - GX::IndTexAlphaSel alphaSel) noexcept { +static inline void SetTevIndirect(GXTevStageID stageId, GXIndTexStageID indStage, GXIndTexFormat fmt, + GXIndTexBiasSel biasSel, GXIndTexMtxID mtxSel, GXIndTexWrap wrapS, GXIndTexWrap wrapT, + GXBool addPrev, GXBool indLod, GXIndTexAlphaSel alphaSel) noexcept { // TODO GXSetTevIndirect(stageId, indStage, fmt, biasSel, mtxSel, wrapS, wrapT, addPrev, indLod, alphaSel); } -static inline void SetTevIndWarp(GX::TevStageID stageId, GX::IndTexStageID indStage, GXBool signedOffset, - GXBool replaceMode, GX::IndTexMtxID mtxSel) noexcept { +static inline void SetTevIndWarp(GXTevStageID stageId, GXIndTexStageID indStage, GXBool signedOffset, + GXBool replaceMode, GXIndTexMtxID mtxSel) noexcept { // TODO GXSetTevIndWarp(stageId, indStage, signedOffset, replaceMode, mtxSel); } -static inline void SetTevKAlphaSel(GX::TevStageID stageId, GX::TevKAlphaSel sel) noexcept { +static inline void SetTevKAlphaSel(GXTevStageID stageId, GXTevKAlphaSel sel) noexcept { auto& state = sGXState.x68_tevStates[stageId].x19_kAlphaSel; if (sel != state) { state = sel; @@ -351,15 +353,18 @@ static inline void SetTevKAlphaSel(GX::TevStageID stageId, GX::TevKAlphaSel sel) } } -static inline void SetTevKColor(GX::TevKColorID id, const GXColor& color) noexcept { +static inline void SetTevKColor(GXTevKColorID id, const GXColor& color) noexcept { auto& state = sGXState.x58_kColors[id]; if (color != state) { state = color; GXSetTevKColor(id, color); } } +static inline void SetTevKColor(GXTevKColorID id, const zeus::CColor& color) noexcept { + SetTevKColor(id, to_gx_color(color)); +} -static inline void SetTevKColorSel(GX::TevStageID stageId, GX::TevKColorSel sel) noexcept { +static inline void SetTevKColorSel(GXTevStageID stageId, GXTevKColorSel sel) noexcept { auto& state = sGXState.x68_tevStates[stageId].x18_kColorSel; if (sel != state) { state = sel; @@ -367,8 +372,8 @@ static inline void SetTevKColorSel(GX::TevStageID stageId, GX::TevKColorSel sel) } } -static inline void SetTevOrder(GX::TevStageID stageId, GX::TexCoordID texCoord, GX::TexMapID texMap, - GX::ChannelID color) noexcept { +static inline void SetTevOrder(GXTevStageID stageId, GXTexCoordID texCoord, GXTexMapID texMap, + GXChannelID color) noexcept { u32 flags = (color & 0xFF) << 16 | (texMap & 0xFF) << 8 | (texCoord & 0xFF); auto& state = sGXState.x68_tevStates[stageId].x14_tevOrderFlags; if (flags != state) { @@ -377,9 +382,9 @@ static inline void SetTevOrder(GX::TevStageID stageId, GX::TexCoordID texCoord, } } -static inline void SetTexCoordGen(GX::TexCoordID dstCoord, GX::TexGenType fn, GX::TexGenSrc src, GX::TexMtx mtx, - GXBool normalize, GX::PTTexMtx postMtx) noexcept { - u32 flags = ((postMtx - GX::PTTEXMTX0) & 63) << 15 | (u8(normalize) & 1) << 14 | ((mtx - GX::TEXMTX0) & 31) << 9 | +static inline void SetTexCoordGen(GXTexCoordID dstCoord, GXTexGenType fn, GXTexGenSrc src, GXTexMtx mtx, + GXBool normalize, GXPTTexMtx postMtx) noexcept { + u32 flags = ((postMtx - GX_PTTEXMTX0) & 63) << 15 | (u8(normalize) & 1) << 14 | ((mtx - GX_TEXMTX0) & 31) << 9 | (src & 31) << 4 | (fn & 15); auto& state = sGXState.x228_texStates[dstCoord].x0_coordGen; if (flags != state) { @@ -388,13 +393,13 @@ static inline void SetTexCoordGen(GX::TexCoordID dstCoord, GX::TexGenType fn, GX } } -static inline void SetTexCoordGen(GX::TexCoordID dstCoord, u32 flags) noexcept { +static inline void SetTexCoordGen(GXTexCoordID dstCoord, u32 flags) noexcept { auto& state = sGXState.x228_texStates[dstCoord].x0_coordGen; if (flags != state) { state = flags; - GXSetTexCoordGen2(dstCoord, GX::TexGenType(flags & 15), GX::TexGenSrc(flags >> 4 & 31), - GX::TexMtx((flags >> 9 & 31) + GX::TEXMTX0), GXBool(flags >> 14 & 1), - GX::PTTexMtx((flags >> 15 & 63) + GX::PTTEXMTX0)); + GXSetTexCoordGen2(dstCoord, GXTexGenType(flags & 15), GXTexGenSrc(flags >> 4 & 31), + GXTexMtx((flags >> 9 & 31) + GX_TEXMTX0), GXBool(flags >> 14 & 1), + GXPTTexMtx((flags >> 15 & 63) + GX_PTTEXMTX0)); } } @@ -406,28 +411,28 @@ static inline void SetVtxDescv_Compressed(u32 descList) noexcept { u32 attrIdx = 0; do { sVtxDescList[attrIdx] = { - GX::Attr(GX::VA_POS + attrIdx), - GX::AttrType(descList >> shift & 3), + GXAttr(GX_VA_POS + attrIdx), + GXAttrType(descList >> shift & 3), }; shift += 2; ++attrIdx; --remain; } while (remain != 0); - sVtxDescList[attrIdx] = {}; + sVtxDescList[attrIdx] = {GX_VA_NULL, GX_NONE}; GXSetVtxDescv(sVtxDescList.data()); sGXState.x48_descList = descList; } } -static inline void SetVtxDescv(const GX::VtxDescList* descList) noexcept { +static inline void SetVtxDescv(const GXVtxDescList* descList) noexcept { u32 flags = 0; - for (; descList->attr != GX::VA_NULL; ++descList) { - flags |= (descList->type & 3) << (descList->attr - GX::VA_POS) * 2; + for (; descList->attr != GX_VA_NULL; ++descList) { + flags |= (descList->type & 3) << (descList->attr - GX_VA_POS) * 2; } SetVtxDescv_Compressed(flags); } -static inline void SetZMode(GXBool compareEnable, GX::Compare func, GXBool updateEnable) noexcept { +static inline void SetZMode(GXBool compareEnable, GXCompare func, GXBool updateEnable) noexcept { u32 flags = (func & 0xFF) << 2 | (u8(updateEnable) << 1) | (u8(compareEnable) & 1); auto& state = sGXState.x52_zmode; if (flags != state) { @@ -436,7 +441,7 @@ static inline void SetZMode(GXBool compareEnable, GX::Compare func, GXBool updat } } -static inline void GetFog(GX::FogType* fogType, float* fogStartZ, float* fogEndZ, float* fogNearZ, float* fogFarZ, +static inline void GetFog(GXFogType* fogType, float* fogStartZ, float* fogEndZ, float* fogNearZ, float* fogFarZ, GXColor* fogColor) { if (fogType != nullptr) { *fogType = sGXState.x53_fogType; diff --git a/Runtime/Graphics/CGraphics.cpp b/Runtime/Graphics/CGraphics.cpp index 51fef2720..23e847654 100644 --- a/Runtime/Graphics/CGraphics.cpp +++ b/Runtime/Graphics/CGraphics.cpp @@ -18,7 +18,7 @@ u32 CGraphics::g_FlippingState; bool CGraphics::g_LastFrameUsedAbove = false; bool CGraphics::g_InterruptLastFrameUsedAbove = false; GX::LightMask CGraphics::g_LightActive{}; -std::array CGraphics::g_LightObjs; +std::array CGraphics::g_LightObjs; std::array CGraphics::g_LightTypes; zeus::CTransform CGraphics::g_GXModelView; zeus::CTransform CGraphics::g_GXModelViewInvXpose; @@ -59,8 +59,8 @@ const std::array CGraphics::skCubeBasisMats{{ }}; // Stream API -static EStreamFlags sStreamFlags; -static GX::Primitive sStreamPrimitive; +static u32 sStreamFlags; +static GXPrimitive sStreamPrimitive; static u32 sVerticesCount; static zeus::CColor sQueuedColor; // Originally writes directly to GX FIFO @@ -80,7 +80,7 @@ void CGraphics::DisableAllLights() { } void CGraphics::LoadLight(ERglLight light, const CLight& info) { - const auto lightId = static_cast(1 << light); + const auto lightId = static_cast(1 << light); auto& obj = g_LightObjs[light]; zeus::CVector3f pos = info.GetPosition(); @@ -97,7 +97,7 @@ void CGraphics::LoadLight(ERglLight light, const CLight& info) { GXInitLightDir(&obj, dir.x(), dir.y(), dir.z()); GXInitLightAttn(&obj, 1.f, 0.f, 0.f, info.GetAttenuationConstant(), info.GetAttenuationLinear(), info.GetAttenuationQuadratic()); - GXInitLightSpot(&obj, info.GetSpotCutoff(), GX::SP_COS2); + GXInitLightSpot(&obj, info.GetSpotCutoff(), GX_SP_COS2); } else if (type == ELightType::Custom) { pos = g_CameraMatrix * pos; GXInitLightPos(&obj, pos.x(), pos.y(), pos.z()); @@ -114,8 +114,8 @@ void CGraphics::LoadLight(ERglLight light, const CLight& info) { } g_LightTypes[light] = type; - GX::Color col(info.GetColor().r(), info.GetColor().g(), info.GetColor().b()); - GXInitLightColor(&obj, col); + zeus::CColor col(info.GetColor().r(), info.GetColor().g(), info.GetColor().b()); + GXInitLightColor(&obj, to_gx_color(col)); GXLoadLightObjImm(&obj, lightId); } @@ -130,9 +130,9 @@ void CGraphics::EnableLight(ERglLight light) { void CGraphics::SetLightState(GX::LightMask lightState) { g_LightActive = lightState; const bool hasLights = lightState.any(); - CGX::SetChanCtrl(CGX::EChannelId::Channel0, hasLights, GX::SRC_REG, - sStreamFlags & EStreamFlagBits::fHasColor ? GX::SRC_VTX : GX::SRC_REG, lightState, - hasLights ? GX::DF_CLAMP : GX::DF_NONE, hasLights ? GX::AF_SPOT : GX::AF_NONE); + CGX::SetChanCtrl(CGX::EChannelId::Channel0, hasLights, GX_SRC_REG, + sStreamFlags & 2 /* fHasColor */ ? GX_SRC_VTX : GX_SRC_REG, lightState, + hasLights ? GX_DF_CLAMP : GX_DF_NONE, hasLights ? GX_AF_SPOT : GX_AF_NONE); } void CGraphics::SetAmbientColor(const zeus::CColor& col) { @@ -141,21 +141,21 @@ void CGraphics::SetAmbientColor(const zeus::CColor& col) { } void CGraphics::SetFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) { - CGX::SetFog(GX::FogType(mode), startz, endz, g_Proj.x14_near, g_Proj.x18_far, color); + CGX::SetFog(GXFogType(mode), startz, endz, g_Proj.x14_near, g_Proj.x18_far, to_gx_color(color)); } void CGraphics::SetDepthWriteMode(bool compare_enable, ERglEnum comp, bool update_enable) { g_depthFunc = comp; - CGX::SetZMode(compare_enable, GX::Compare(comp), update_enable); + CGX::SetZMode(compare_enable, GXCompare(comp), update_enable); } void CGraphics::SetBlendMode(ERglBlendMode mode, ERglBlendFactor src, ERglBlendFactor dst, ERglLogicOp op) { - CGX::SetBlendMode(GX::BlendMode(mode), GX::BlendFactor(src), GX::BlendFactor(dst), GX::LogicOp(op)); + CGX::SetBlendMode(GXBlendMode(mode), GXBlendFactor(src), GXBlendFactor(dst), GXLogicOp(op)); } void CGraphics::SetCullMode(ERglCullMode mode) { g_cullMode = mode; - GXSetCullMode(GX::CullMode(mode)); + GXSetCullMode(GXCullMode(mode)); } void CGraphics::BeginScene() { @@ -163,7 +163,7 @@ void CGraphics::BeginScene() { } void CGraphics::EndScene() { - CGX::SetZMode(true, GX::LEQUAL, true); + CGX::SetZMode(true, GX_LEQUAL, true); /* Spinwait until g_NumBreakpointsWaiting is 0 */ /* ++g_NumBreakpointsWaiting; */ @@ -190,10 +190,10 @@ void CGraphics::Render2D(CTexture& tex, u32 x, u32 y, u32 w, u32 h, const zeus:: const auto oldLights = g_LightActive; SetOrtho(-g_Viewport.x10_halfWidth, g_Viewport.x10_halfWidth, g_Viewport.x14_halfHeight, -g_Viewport.x14_halfHeight, -1.f, -10.f); - GXLoadPosMtxImm({}, GX::PNMTX0); + GXLoadPosMtxImm({}, GX_PNMTX0); DisableAllLights(); SetCullMode(ERglCullMode::None); - tex.Load(GX::TEXMAP0, EClampMode::Repeat); + tex.Load(GX_TEXMAP0, EClampMode::Repeat); // float hPad, vPad; // if (CGraphics::GetViewportAspect() >= 1.78f) { @@ -213,7 +213,7 @@ void CGraphics::Render2D(CTexture& tex, u32 x, u32 y, u32 w, u32 h, const zeus:: float y1 = scaledY - g_Viewport.x14_halfHeight; float x2 = x1 + scaledW; float y2 = y1 + scaledH; - StreamBegin(GX::TRIANGLESTRIP); + StreamBegin(GX_TRIANGLESTRIP); StreamColor(col); StreamTexcoord(0.f, 0.f); StreamVertex(x1, y1, 1.f); @@ -240,8 +240,8 @@ void CGraphics::DoRender2D(const CTexture& tex, s32 x, s32 y, s32 w1, s32 w2, s3 void CGraphics::EndRender2D(bool v) {} void CGraphics::SetAlphaCompare(ERglAlphaFunc comp0, u8 ref0, ERglAlphaOp op, ERglAlphaFunc comp1, u8 ref1) { - CGX::SetAlphaCompare(static_cast(comp0), ref0, static_cast(op), - static_cast(comp1), ref1); + CGX::SetAlphaCompare(static_cast(comp0), ref0, static_cast(op), static_cast(comp1), + ref1); } void CGraphics::SetViewPointMatrix(const zeus::CTransform& xf) { @@ -259,12 +259,12 @@ void CGraphics::SetViewMatrix() { else g_GXModelView = g_CameraMatrix * g_GXModelMatrix; /* Load position matrix */ - GXLoadPosMtxImm(g_GXModelView, GX::PNMTX0); + GXLoadPosMtxImm(&g_GXModelView, GX_PNMTX0); /* Inverse-transpose */ g_GXModelViewInvXpose = g_GXModelView.inverse(); g_GXModelViewInvXpose.basis.transpose(); /* Load normal matrix */ - GXLoadNrmMtxImm(g_GXModelViewInvXpose, GX::PNMTX0); + GXLoadNrmMtxImm(&g_GXModelViewInvXpose, GX_PNMTX0); } void CGraphics::SetModelMatrix(const zeus::CTransform& xf) { @@ -316,7 +316,7 @@ zeus::CMatrix4f CGraphics::GetPerspectiveProjectionMatrix() { return { 2.f * g_Proj.x14_near / rml, 0.f, rpl / rml, 0.f, 0.f, 2.f * g_Proj.x14_near / tmb, tpb / tmb, 0.f, - 0.f, 0.f, -fpn / fmn, -2.f * g_Proj.x18_far * g_Proj.x14_near / fmn, + 0.f, 0.f, -g_Proj.x14_near / fmn, -(g_Proj.x18_far * g_Proj.x14_near) / fmn, 0.f, 0.f, -1.f, 0.f, }; // clang-format on @@ -330,7 +330,7 @@ zeus::CMatrix4f CGraphics::GetPerspectiveProjectionMatrix() { return { 2.f / rml, 0.f, 0.f, -rpl / rml, 0.f, 2.f / tmb, 0.f, -tpb / tmb, - 0.f, 0.f, -1.f / fmn, -g_Proj.x14_near / fmn, + 0.f, 0.f, -1.f / fmn, -g_Proj.x18_far / fmn, 0.f, 0.f, 0.f, 1.f }; // clang-format on @@ -375,10 +375,10 @@ void CGraphics::FlushProjection() { const auto mtx = GetPerspectiveProjectionMatrix(); if (g_Proj.x0_persp) { // Convert and load persp - GXSetProjection(mtx, GX::PERSPECTIVE); + GXSetProjection(&mtx, GX_PERSPECTIVE); } else { // Convert and load ortho - GXSetProjection(mtx, GX::ORTHOGRAPHIC); + GXSetProjection(&mtx, GX_ORTHOGRAPHIC); } } @@ -521,14 +521,14 @@ void CGraphics::SetUseVideoFilter(bool filter) { void CGraphics::SetClearColor(const zeus::CColor& color) { g_ClearColor = color; - GXSetCopyClear(color, g_ClearDepthValue); + GXSetCopyClear(to_gx_color(color), g_ClearDepthValue); } void CGraphics::SetCopyClear(const zeus::CColor& color, float depth) { g_ClearColor = color; g_ClearDepthValue = depth; // 1.6777215E7 * depth; Metroid Prime needed this to convert float [0,1] depth into 24 bit // range, we no longer have this requirement - GXSetCopyClear(g_ClearColor, g_ClearDepthValue); + GXSetCopyClear(to_gx_color(g_ClearColor), g_ClearDepthValue); } void CGraphics::SetIsBeginSceneClearFb(bool clear) { g_IsBeginSceneClearFb = clear; } @@ -537,19 +537,19 @@ void CGraphics::SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass CTevCombiners::SetupPass(stage, pass); } -void CGraphics::StreamBegin(GX::Primitive primitive) { +void CGraphics::StreamBegin(GXPrimitive primitive) { // Originally ResetVertexDataStream(true); sQueuedVertices.clear(); sQueuedVertices.emplace_back(sQueuedColor); sVerticesCount = 0; // End - sStreamFlags = EStreamFlagBits::fHasColor; + sStreamFlags = 2; sStreamPrimitive = primitive; } void CGraphics::StreamNormal(const zeus::CVector3f& nrm) { sQueuedVertices.back().normal = nrm; - sStreamFlags |= EStreamFlagBits::fHasNormal; + sStreamFlags |= 1; } void CGraphics::StreamColor(const zeus::CColor& color) { @@ -558,12 +558,12 @@ void CGraphics::StreamColor(const zeus::CColor& color) { } else { sQueuedColor = color; } - sStreamFlags |= EStreamFlagBits::fHasColor; + sStreamFlags |= 2; } void CGraphics::StreamTexcoord(const zeus::CVector2f& uv) { sQueuedVertices.back().texCoord = uv; - sStreamFlags |= EStreamFlagBits::fHasTexture; + sStreamFlags |= 4; } void CGraphics::StreamVertex(const zeus::CVector3f& pos) { @@ -589,35 +589,36 @@ void CGraphics::UpdateVertexDataStream() { } void CGraphics::FlushStream() { - std::array vtxDescList{}; + std::array vtxDescList{}; size_t idx = 0; - vtxDescList[idx++] = {GX::VA_POS, GX::DIRECT}; - if (sStreamFlags & EStreamFlagBits::fHasNormal) { - vtxDescList[idx++] = {GX::VA_NRM, GX::DIRECT}; + vtxDescList[idx++] = {GX_VA_POS, GX_DIRECT}; + if (sStreamFlags & 1) { + vtxDescList[idx++] = {GX_VA_NRM, GX_DIRECT}; } - if (sStreamFlags & EStreamFlagBits::fHasColor) { - vtxDescList[idx++] = {GX::VA_CLR0, GX::DIRECT}; + if (sStreamFlags & 2) { + vtxDescList[idx++] = {GX_VA_CLR0, GX_DIRECT}; } - if (sStreamFlags & EStreamFlagBits::fHasTexture) { - vtxDescList[idx++] = {GX::VA_TEX0, GX::DIRECT}; + if (sStreamFlags & 4) { + vtxDescList[idx++] = {GX_VA_TEX0, GX_DIRECT}; } + vtxDescList[idx] = {GX_VA_NULL, GX_NONE}; CGX::SetVtxDescv(vtxDescList.data()); SetTevStates(sStreamFlags); FullRender(); } void CGraphics::FullRender() { - CGX::Begin(sStreamPrimitive, GX::VTXFMT0, sVerticesCount); + CGX::Begin(sStreamPrimitive, GX_VTXFMT0, sVerticesCount); for (size_t i = 0; i < sVerticesCount; ++i) { const auto& item = sQueuedVertices[i]; GXPosition3f32(item.vertex); - if (sStreamFlags & EStreamFlagBits::fHasNormal) { + if (sStreamFlags & 1) { GXNormal3f32(item.normal); } - if (sStreamFlags & EStreamFlagBits::fHasColor) { + if (sStreamFlags & 2) { GXColor4f32(item.color); } - if (sStreamFlags & EStreamFlagBits::fHasTexture) { + if (sStreamFlags & 4) { GXTexCoord2f32(item.texCoord); } } @@ -638,7 +639,7 @@ void CGraphics::ResetVertexDataStream(bool end) { } } -void CGraphics::DrawPrimitive(GX::Primitive primitive, const zeus::CVector3f* pos, const zeus::CVector3f& normal, +void CGraphics::DrawPrimitive(GXPrimitive primitive, const zeus::CVector3f* pos, const zeus::CVector3f& normal, const zeus::CColor& col, s32 numVerts) { StreamBegin(primitive); StreamColor(col); @@ -649,25 +650,25 @@ void CGraphics::DrawPrimitive(GX::Primitive primitive, const zeus::CVector3f* po StreamEnd(); } -void CGraphics::SetTevStates(EStreamFlags flags) noexcept { - if (flags & EStreamFlagBits::fHasTexture) { +void CGraphics::SetTevStates(u32 flags) noexcept { + if (flags & 4 /* fHasTexture */) { CGX::SetNumTexGens(1); // sTextureUsed & 3? - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR0A0); - CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD1, GX::TEXMAP1, GX::COLOR0A0); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0); } else { CGX::SetNumTexGens(0); CGX::SetNumTevStages(1); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR0A0); - CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR0A0); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); } CGX::SetNumChans(1); CGX::SetNumIndStages(0); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); - CGX::SetTexCoordGen(GX::TEXCOORD1, GX::TG_MTX2x4, GX::TG_TEX1, GX::IDENTITY, false, GX::PTIDENTITY); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::SetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY, false, GX_PTIDENTITY); const bool hasLights = g_LightActive.any(); - CGX::SetChanCtrl(CGX::EChannelId::Channel0, hasLights, GX::SRC_REG, - flags & EStreamFlagBits::fHasColor ? GX::SRC_VTX : GX::SRC_REG, g_LightActive, - hasLights ? GX::DF_CLAMP : GX::DF_NONE, hasLights ? GX::AF_SPOT : GX::AF_NONE); + CGX::SetChanCtrl(CGX::EChannelId::Channel0, hasLights, GX_SRC_REG, + flags & 2 /* fHasColor */ ? GX_SRC_VTX : GX_SRC_REG, g_LightActive, + hasLights ? GX_DF_CLAMP : GX_DF_NONE, hasLights ? GX_AF_SPOT : GX_AF_NONE); CGX::FlushState(); // normally would be handled in FullRender TODO } @@ -715,22 +716,22 @@ void CGraphics::SetDefaultVtxAttrFmt() { // Unneeded, all attributes are expected to be full floats // Left here for reference - GXSetVtxAttrFmt(GX::VTXFMT0, GX::VA_POS, GX::POS_XYZ, GX::F32, 0); - GXSetVtxAttrFmt(GX::VTXFMT1, GX::VA_POS, GX::POS_XYZ, GX::F32, 0); - GXSetVtxAttrFmt(GX::VTXFMT2, GX::VA_POS, GX::POS_XYZ, GX::F32, 0); - GXSetVtxAttrFmt(GX::VTXFMT0, GX::VA_NRM, GX::NRM_XYZ, GX::F32, 0); - GXSetVtxAttrFmt(GX::VTXFMT1, GX::VA_NRM, GX::NRM_XYZ, GX::S16, 14); - GXSetVtxAttrFmt(GX::VTXFMT2, GX::VA_NRM, GX::NRM_XYZ, GX::S16, 14); - GXSetVtxAttrFmt(GX::VTXFMT0, GX::VA_CLR0, GX::CLR_RGBA, GX::RGBA8, 0); - GXSetVtxAttrFmt(GX::VTXFMT1, GX::VA_CLR0, GX::CLR_RGBA, GX::RGBA8, 0); - GXSetVtxAttrFmt(GX::VTXFMT2, GX::VA_CLR0, GX::CLR_RGBA, GX::RGBA8, 0); - GXSetVtxAttrFmt(GX::VTXFMT0, GX::VA_TEX0, GX::TEX_ST, GX::F32, 0); - GXSetVtxAttrFmt(GX::VTXFMT1, GX::VA_TEX0, GX::TEX_ST, GX::F32, 0); - GXSetVtxAttrFmt(GX::VTXFMT2, GX::VA_TEX0, GX::TEX_ST, GX::U16, 15); - for (GX::Attr attr = GX::VA_TEX1; attr <= GX::VA_TEX7; attr = GX::Attr(attr + 1)) { - GXSetVtxAttrFmt(GX::VTXFMT0, attr, GX::TEX_ST, GX::F32, 0); - GXSetVtxAttrFmt(GX::VTXFMT1, attr, GX::TEX_ST, GX::F32, 0); - GXSetVtxAttrFmt(GX::VTXFMT2, attr, GX::TEX_ST, GX::F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14); + GXSetVtxAttrFmt(GX_VTXFMT2, GX_VA_NRM, GX_NRM_XYZ, GX_S16, 14); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT2, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT2, GX_VA_TEX0, GX_TEX_ST, GX_U16, 15); + for (GXAttr attr = GX_VA_TEX1; attr <= GX_VA_TEX7; attr = GXAttr(attr + 1)) { + GXSetVtxAttrFmt(GX_VTXFMT0, attr, GX_TEX_ST, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, attr, GX_TEX_ST, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT2, attr, GX_TEX_ST, GX_F32, 0); } } diff --git a/Runtime/Graphics/CGraphics.hpp b/Runtime/Graphics/CGraphics.hpp index 5fb227ab9..7710cedc5 100644 --- a/Runtime/Graphics/CGraphics.hpp +++ b/Runtime/Graphics/CGraphics.hpp @@ -15,7 +15,6 @@ #include #include -#include #include using frame_clock = std::chrono::high_resolution_clock; @@ -25,108 +24,108 @@ class CTexture; extern CVar* g_disableLighting; class CTimeProvider; -enum class ERglCullMode : std::underlying_type_t { - None = GX::CULL_NONE, - Front = GX::CULL_FRONT, - Back = GX::CULL_BACK, - All = GX::CULL_ALL, +enum class ERglCullMode : std::underlying_type_t { + None = GX_CULL_NONE, + Front = GX_CULL_FRONT, + Back = GX_CULL_BACK, + All = GX_CULL_ALL, }; -enum class ERglBlendMode : std::underlying_type_t { - None = GX::BM_NONE, - Blend = GX::BM_BLEND, - Logic = GX::BM_LOGIC, - Subtract = GX::BM_SUBTRACT, - Max = GX::MAX_BLENDMODE, +enum class ERglBlendMode : std::underlying_type_t { + None = GX_BM_NONE, + Blend = GX_BM_BLEND, + Logic = GX_BM_LOGIC, + Subtract = GX_BM_SUBTRACT, + Max = GX_MAX_BLENDMODE, }; -enum class ERglBlendFactor : std::underlying_type_t { - Zero = GX::BL_ZERO, - One = GX::BL_ONE, - SrcColor = GX::BL_SRCCLR, - InvSrcColor = GX::BL_INVSRCCLR, - SrcAlpha = GX::BL_SRCALPHA, - InvSrcAlpha = GX::BL_INVSRCALPHA, - DstAlpha = GX::BL_DSTALPHA, - InvDstAlpha = GX::BL_INVDSTALPHA, - DstColor = GX::BL_DSTCLR, - InvDstColor = GX::BL_INVDSTCLR, +enum class ERglBlendFactor : std::underlying_type_t { + Zero = GX_BL_ZERO, + One = GX_BL_ONE, + SrcColor = GX_BL_SRCCLR, + InvSrcColor = GX_BL_INVSRCCLR, + SrcAlpha = GX_BL_SRCALPHA, + InvSrcAlpha = GX_BL_INVSRCALPHA, + DstAlpha = GX_BL_DSTALPHA, + InvDstAlpha = GX_BL_INVDSTALPHA, + DstColor = GX_BL_DSTCLR, + InvDstColor = GX_BL_INVDSTCLR, }; -enum class ERglLogicOp : std::underlying_type_t { - Clear = GX::LO_CLEAR, - And = GX::LO_AND, - RevAnd = GX::LO_REVAND, - Copy = GX::LO_COPY, - InvAnd = GX::LO_INVAND, - NoOp = GX::LO_NOOP, - Xor = GX::LO_XOR, - Or = GX::LO_OR, - Nor = GX::LO_NOR, - Equiv = GX::LO_EQUIV, - Inv = GX::LO_INV, - RevOr = GX::LO_REVOR, - InvCopy = GX::LO_INVCOPY, - InvOr = GX::LO_INVOR, - NAnd = GX::LO_NAND, - Set = GX::LO_SET, +enum class ERglLogicOp : std::underlying_type_t { + Clear = GX_LO_CLEAR, + And = GX_LO_AND, + RevAnd = GX_LO_REVAND, + Copy = GX_LO_COPY, + InvAnd = GX_LO_INVAND, + NoOp = GX_LO_NOOP, + Xor = GX_LO_XOR, + Or = GX_LO_OR, + Nor = GX_LO_NOR, + Equiv = GX_LO_EQUIV, + Inv = GX_LO_INV, + RevOr = GX_LO_REVOR, + InvCopy = GX_LO_INVCOPY, + InvOr = GX_LO_INVOR, + NAnd = GX_LO_NAND, + Set = GX_LO_SET, }; -enum class ERglAlphaFunc : std::underlying_type_t { - Never = GX::NEVER, - Less = GX::LESS, - Equal = GX::EQUAL, - LEqual = GX::LEQUAL, - Greater = GX::GREATER, - NEqual = GX::NEQUAL, - GEqual = GX::GEQUAL, - Always = GX::ALWAYS, +enum class ERglAlphaFunc : std::underlying_type_t { + Never = GX_NEVER, + Less = GX_LESS, + Equal = GX_EQUAL, + LEqual = GX_LEQUAL, + Greater = GX_GREATER, + NEqual = GX_NEQUAL, + GEqual = GX_GEQUAL, + Always = GX_ALWAYS, }; -enum class ERglAlphaOp : std::underlying_type_t { - And = GX::AOP_AND, - Or = GX::AOP_OR, - Xor = GX::AOP_XOR, - XNor = GX::AOP_XNOR, - Max = GX::MAX_ALPHAOP, +enum class ERglAlphaOp : std::underlying_type_t { + And = GX_AOP_AND, + Or = GX_AOP_OR, + Xor = GX_AOP_XOR, + XNor = GX_AOP_XNOR, + Max = GX_MAX_ALPHAOP, }; -enum class ERglEnum : std::underlying_type_t { - Never = GX::NEVER, - Less = GX::LESS, - Equal = GX::EQUAL, - LEqual = GX::LEQUAL, - Greater = GX::GREATER, - NEqual = GX::NEQUAL, - GEqual = GX::GEQUAL, - Always = GX::ALWAYS, +enum class ERglEnum : std::underlying_type_t { + Never = GX_NEVER, + Less = GX_LESS, + Equal = GX_EQUAL, + LEqual = GX_LEQUAL, + Greater = GX_GREATER, + NEqual = GX_NEQUAL, + GEqual = GX_GEQUAL, + Always = GX_ALWAYS, }; using ERglLight = u8; -enum class ERglTexOffset : std::underlying_type_t { - Zero = GX::TO_ZERO, - Sixteenth = GX::TO_SIXTEENTH, - Eighth = GX::TO_EIGHTH, - Fourth = GX::TO_FOURTH, - Half = GX::TO_HALF, - One = GX::TO_ONE, +enum class ERglTexOffset : std::underlying_type_t { + Zero = GX_TO_ZERO, + Sixteenth = GX_TO_SIXTEENTH, + Eighth = GX_TO_EIGHTH, + Fourth = GX_TO_FOURTH, + Half = GX_TO_HALF, + One = GX_TO_ONE, }; -enum class ERglFogMode : std::underlying_type_t { - None = GX::FOG_NONE, +enum class ERglFogMode : std::underlying_type_t { + None = GX_FOG_NONE, - PerspLin = GX::FOG_PERSP_LIN, - PerspExp = GX::FOG_PERSP_EXP, - PerspExp2 = GX::FOG_ORTHO_EXP2, - PerspRevExp = GX::FOG_PERSP_REVEXP, - PerspRevExp2 = GX::FOG_PERSP_REVEXP2, + PerspLin = GX_FOG_PERSP_LIN, + PerspExp = GX_FOG_PERSP_EXP, + PerspExp2 = GX_FOG_ORTHO_EXP2, + PerspRevExp = GX_FOG_PERSP_REVEXP, + PerspRevExp2 = GX_FOG_PERSP_REVEXP2, - OrthoLin = GX::FOG_ORTHO_LIN, - OrthoExp = GX::FOG_ORTHO_EXP, - OrthoExp2 = GX::FOG_ORTHO_EXP2, - OrthoRevExp = GX::FOG_ORTHO_REVEXP, - OrthoRevExp2 = GX::FOG_ORTHO_REVEXP2, + OrthoLin = GX_FOG_ORTHO_LIN, + OrthoExp = GX_FOG_ORTHO_EXP, + OrthoExp2 = GX_FOG_ORTHO_EXP2, + OrthoRevExp = GX_FOG_ORTHO_REVEXP, + OrthoRevExp2 = GX_FOG_ORTHO_REVEXP2, }; struct SViewport { @@ -165,13 +164,13 @@ struct SClipScreenRect { , x20_uvYMin(uvYMin) , x24_uvYMax(uvYMax) {} - SClipScreenRect(const aurora::gfx::ClipRect& rect) { - x4_left = rect.x; - x8_top = rect.y; - xc_width = rect.width; - x10_height = rect.height; - x14_dstWidth = rect.width; - } +// SClipScreenRect(const aurora::gfx::ClipRect& rect) { +// x4_left = rect.x; +// x8_top = rect.y; +// xc_width = rect.width; +// x10_height = rect.height; +// x14_dstWidth = rect.width; +// } SClipScreenRect(const SViewport& vp) { x4_left = vp.x0_left; @@ -214,7 +213,7 @@ public: static bool g_LastFrameUsedAbove; static bool g_InterruptLastFrameUsedAbove; static GX::LightMask g_LightActive; - static std::array g_LightObjs; + static std::array g_LightObjs; static std::array g_LightTypes; static zeus::CTransform g_GXModelView; static zeus::CTransform g_GXModelViewInvXpose; @@ -309,31 +308,33 @@ public: static const std::array skCubeBasisMats; - static void ResolveSpareTexture(const SClipScreenRect& rect, int bindIdx, GX::TextureFormat format, - bool clearDepth = false) { - aurora::gfx::resolve_color({rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height}, bindIdx, format, - clearDepth); + static void ResolveSpareTexture(const SClipScreenRect& rect, int bindIdx, GXTexFmt format, bool clearDepth = false) { + // TODO +// aurora::gfx::resolve_color({rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height}, bindIdx, format, +// clearDepth); } - static void LoadDolphinSpareTexture(int bindIdx, GX::TextureFormat format, GX::TexMapID id) { - GXTexObj obj; - GXInitTexObjResolved(&obj, bindIdx, format, GX_CLAMP, GX_CLAMP, GX_TLUT0); - GXInitTexObjLOD(&obj, GX_NEAR, GX_NEAR, 0.f, 0.f, 0.f, false, false, GX_ANISO_1); - GXLoadTexObj(&obj, id); + static void LoadDolphinSpareTexture(int bindIdx, GXTexFmt format, GXTexMapID id) { + // TODO +// GXTexObj obj; +// GXInitTexObjResolved(&obj, bindIdx, format, GX_CLAMP, GX_CLAMP, GX_TLUT0); +// GXInitTexObjLOD(&obj, GX_NEAR, GX_NEAR, 0.f, 0.f, 0.f, false, false, GX_ANISO_1); +// GXLoadTexObj(&obj, id); } - static void LoadDolphinSpareTexture(int bindIdx, GXCITexFmt format, GXTlut tlut, GX::TexMapID id) { - GXTexObj obj; - GXInitTexObjResolved(&obj, bindIdx, static_cast(format), GX_CLAMP, GX_CLAMP, tlut); - GXInitTexObjLOD(&obj, GX_NEAR, GX_NEAR, 0.f, 0.f, 0.f, false, false, GX_ANISO_1); - GXLoadTexObj(&obj, id); + static void LoadDolphinSpareTexture(int bindIdx, GXCITexFmt format, GXTlut tlut, GXTexMapID id) { + // TODO +// GXTexObj obj; +// GXInitTexObjResolved(&obj, bindIdx, static_cast(format), GX_CLAMP, GX_CLAMP, tlut); +// GXInitTexObjLOD(&obj, GX_NEAR, GX_NEAR, 0.f, 0.f, 0.f, false, false, GX_ANISO_1); +// GXLoadTexObj(&obj, id); } static void ResolveSpareDepth(const SClipScreenRect& rect, int bindIdx = 0) { // aurora::gfx::resolve_depth({rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height}, bindIdx); } static void ResetGfxStates() noexcept; - static void SetTevStates(EStreamFlags flags) noexcept; + static void SetTevStates(u32 flags) noexcept; static void SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass); - static void StreamBegin(GX::Primitive primitive); + static void StreamBegin(GXPrimitive primitive); static void StreamNormal(const zeus::CVector3f& nrm); static void StreamColor(const zeus::CColor& color); static inline void StreamColor(float r, float g, float b, float a) { StreamColor({r, g, b, a}); } @@ -347,7 +348,7 @@ public: static void ResetVertexDataStream(bool end); static void FlushStream(); static void FullRender(); - static void DrawPrimitive(GX::Primitive primitive, const zeus::CVector3f* pos, const zeus::CVector3f& normal, + static void DrawPrimitive(GXPrimitive primitive, const zeus::CVector3f* pos, const zeus::CVector3f& normal, const zeus::CColor& col, s32 numVerts); static void SetLineWidth(float width, ERglTexOffset offs); }; @@ -386,9 +387,13 @@ public: }; #ifdef AURORA_GFX_DEBUG_GROUPS +struct ScopedDebugGroup { + inline ScopedDebugGroup(const char* label) noexcept { push_debug_group(label); } + inline ~ScopedDebugGroup() noexcept { pop_debug_group(); } +}; #define SCOPED_GRAPHICS_DEBUG_GROUP(name, ...) \ OPTICK_EVENT_DYNAMIC(name); \ - aurora::gfx::ScopedDebugGroup _GfxDbg_{name} + ScopedDebugGroup _GfxDbg_ { name } #else #define SCOPED_GRAPHICS_DEBUG_GROUP(name, ...) OPTICK_EVENT_DYNAMIC(name) #endif diff --git a/Runtime/Graphics/CLineRenderer.cpp b/Runtime/Graphics/CLineRenderer.cpp index 9fd344bfd..c1bbff3f0 100644 --- a/Runtime/Graphics/CLineRenderer.cpp +++ b/Runtime/Graphics/CLineRenderer.cpp @@ -20,7 +20,7 @@ void CLineRenderer::Shutdown() { //hecl::VertexBufferPool CLineRenderer::s_vertPoolNoTex = {}; //hecl::UniformBufferPool CLineRenderer::s_uniformPool = {}; -CLineRenderer::CLineRenderer(EPrimitiveMode mode, u32 maxVerts, const aurora::gfx::TextureHandle& texture, +CLineRenderer::CLineRenderer(EPrimitiveMode mode, u32 maxVerts, u32 texture, bool additive, bool zTest, bool zGEqual) : m_mode(mode), m_maxVerts(maxVerts) { OPTICK_EVENT(); diff --git a/Runtime/Graphics/CLineRenderer.hpp b/Runtime/Graphics/CLineRenderer.hpp index 08ea80522..4e87675e8 100644 --- a/Runtime/Graphics/CLineRenderer.hpp +++ b/Runtime/Graphics/CLineRenderer.hpp @@ -51,7 +51,7 @@ public: // hecl::UniformBufferPool::Token m_uniformBuf; // std::array, 2> m_shaderBind; - CLineRenderer(EPrimitiveMode mode, u32 maxVerts, const aurora::gfx::TextureHandle& texture, bool additive, + CLineRenderer(EPrimitiveMode mode, u32 maxVerts, u32 texture, bool additive, bool zTest = false, bool zGEqual = false); CLineRenderer(CLineRenderer&&) = default; diff --git a/Runtime/Graphics/CMetroidModelInstance.cpp b/Runtime/Graphics/CMetroidModelInstance.cpp index c4eb70ff9..db2b0e123 100644 --- a/Runtime/Graphics/CMetroidModelInstance.cpp +++ b/Runtime/Graphics/CMetroidModelInstance.cpp @@ -47,7 +47,7 @@ CMetroidModelInstance::CMetroidModelInstance(std::pair modelHead u32 numTexCoords = texCoords.second / 8; CMemoryInStream stream{texCoords.first, texCoords.second}; for (u32 i = 0; i < numTexCoords; ++i) { - x6c_texCoords.emplace_back(stream.Get()); + x6c_texCoords.emplace_back(stream.Get>()); } } { diff --git a/Runtime/Graphics/CMetroidModelInstance.hpp b/Runtime/Graphics/CMetroidModelInstance.hpp index ae84c19a6..a698bf82e 100644 --- a/Runtime/Graphics/CMetroidModelInstance.hpp +++ b/Runtime/Graphics/CMetroidModelInstance.hpp @@ -9,6 +9,7 @@ #include #include +#include namespace metaforce { class CCubeSurface; @@ -45,5 +46,4 @@ public: [[nodiscard]] const std::vector>* GetTCPointer() const { return &x6c_texCoords; } [[nodiscard]] const std::vector>* GetPackedTCPointer() const { return &x70_packedTexCoords; } }; - } // namespace metaforce diff --git a/Runtime/Graphics/CModel.cpp b/Runtime/Graphics/CModel.cpp index 1f1270bbd..91a58b65a 100644 --- a/Runtime/Graphics/CModel.cpp +++ b/Runtime/Graphics/CModel.cpp @@ -91,7 +91,7 @@ CModel::CModel(std::unique_ptr in, u32 dataLen, IObjectStore* store) u32 numFloatUVs = CBasics::SwapBytes(*secSizeCur) / 8; auto floatUVs = StreamFromPartData(dataCur, secSizeCur); for (u32 i = 0; i < numFloatUVs; ++i) { - m_floatUVs.emplace_back(floatUVs.Get()); + m_floatUVs.emplace_back(floatUVs.Get>()); } if ((flags & 4) != 0) { diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index 5ad4f2efb..a770d0c5d 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -9,6 +9,7 @@ #include "Graphics/CCubeSurface.hpp" #include "Graphics/CTexture.hpp" #include "IObjectStore.hpp" +#include "Flags.hpp" namespace metaforce { class CCubeMaterial; diff --git a/Runtime/Graphics/CMoviePlayer.cpp b/Runtime/Graphics/CMoviePlayer.cpp index 4f72c70b2..1f91127b4 100644 --- a/Runtime/Graphics/CMoviePlayer.cpp +++ b/Runtime/Graphics/CMoviePlayer.cpp @@ -16,18 +16,21 @@ static void MyTHPYuv2RgbTextureSetup(void* dataY, void* dataU, void* dataV, u16 GXTexObj texV; GXTexObj texU; GXTexObj texY; - GXInitTexObj(&texY, dataY, width, height, GX::TF_I8, GX_CLAMP, GX_CLAMP, false); + GXInitTexObj(&texY, dataY, width, height, GX_TF_R8_PC, GX_CLAMP, GX_CLAMP, false); GXInitTexObjLOD(&texY, GX_NEAR, GX_NEAR, 0.0, 0.0, 0.0, false, false, GX_ANISO_1); - GXLoadTexObj(&texY, GX::TEXMAP0); - GXInitTexObj(&texU, dataU, width / 2, height / 2, GX::TF_I8, GX_CLAMP, GX_CLAMP, false); + GXLoadTexObj(&texY, GX_TEXMAP0); + GXInitTexObj(&texU, dataU, width / 2, height / 2, GX_TF_R8_PC, GX_CLAMP, GX_CLAMP, false); GXInitTexObjLOD(&texU, GX_NEAR, GX_NEAR, 0.0, 0.0, 0.0, false, false, GX_ANISO_1); - GXLoadTexObj(&texU, GX::TEXMAP1); - GXInitTexObj(&texV, dataV, width / 2, height / 2, GX::TF_I8, GX_CLAMP, GX_CLAMP, false); + GXLoadTexObj(&texU, GX_TEXMAP1); + GXInitTexObj(&texV, dataV, width / 2, height / 2, GX_TF_R8_PC, GX_CLAMP, GX_CLAMP, false); GXInitTexObjLOD(&texV, GX_NEAR, GX_NEAR, 0.0, 0.0, 0.0, false, false, GX_ANISO_1); - GXLoadTexObj(&texV, GX::TEXMAP2); - CTexture::InvalidateTexMap(GX::TEXMAP0); - CTexture::InvalidateTexMap(GX::TEXMAP1); - CTexture::InvalidateTexMap(GX::TEXMAP2); + GXLoadTexObj(&texV, GX_TEXMAP2); + CTexture::InvalidateTexMap(GX_TEXMAP0); + CTexture::InvalidateTexMap(GX_TEXMAP1); + CTexture::InvalidateTexMap(GX_TEXMAP2); + GXDestroyTexObj(&texV); + GXDestroyTexObj(&texU); + GXDestroyTexObj(&texY); } const std::array InterlaceTex{ @@ -35,85 +38,86 @@ const std::array InterlaceTex{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }; static void MyTHPGXYuv2RgbSetup(bool interlaced2ndFrame, bool fieldFlip) { - CGX::SetZMode(true, GX::ALWAYS, false); - CGX::SetBlendMode(GX::BM_NONE, GX::BL_ONE, GX::BL_ZERO, GX::LO_CLEAR); + CGX::SetZMode(true, GX_ALWAYS, false); + CGX::SetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR); CGX::SetNumChans(0); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); - CGX::SetTexCoordGen(GX::TEXCOORD1, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::SetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); if (!fieldFlip) { CGX::SetNumTexGens(3); - CGX::SetTexCoordGen(GX::TEXCOORD2, GX::TG_MTX2x4, GX::TG_POS, GX::TEXMTX0, false, GX::PTIDENTITY); + CGX::SetTexCoordGen(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_POS, GX_TEXMTX0, false, GX_PTIDENTITY); aurora::Mat4x2 mtx; mtx.m0.x = 0.125f; mtx.m2.y = 0.25f; if (interlaced2ndFrame) { mtx.m3.y = 0.25f; } - GXLoadTexMtxImm(&mtx, GX::TEXMTX0, GX::MTX2x4); + GXLoadTexMtxImm(&mtx, GX_TEXMTX0, GX_MTX2x4); GXTexObj texObj; - GXInitTexObj(&texObj, InterlaceTex.data(), 8, 4, GX::TF_I8, GX_REPEAT, GX_REPEAT, false); + GXInitTexObj(&texObj, InterlaceTex.data(), 8, 4, GX_TF_I8, GX_REPEAT, GX_REPEAT, false); GXInitTexObjLOD(&texObj, GX_NEAR, GX_NEAR, 0.f, 0.f, 0.f, false, false, GX_ANISO_1); - GXLoadTexObj(&texObj, GX::TEXMAP3); - CTexture::InvalidateTexMap(GX::TEXMAP3); - CGX::SetTevOrder(GX::TEVSTAGE4, GX::TEXCOORD2, GX::TEXMAP3, GX::COLOR_NULL); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE4); - CGX::SetTevColorIn(GX::TEVSTAGE4, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_CPREV); - CGX::SetTevAlphaIn(GX::TEVSTAGE4, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_TEXA); - CGX::SetAlphaCompare(GX::LESS, 128, GX::AOP_AND, GX::ALWAYS, 0); + GXLoadTexObj(&texObj, GX_TEXMAP3); + GXDestroyTexObj(&texObj); + CTexture::InvalidateTexMap(GX_TEXMAP3); + CGX::SetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD2, GX_TEXMAP3, GX_COLOR_NULL); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE4); + CGX::SetTevColorIn(GX_TEVSTAGE4, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_CPREV); + CGX::SetTevAlphaIn(GX_TEVSTAGE4, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA); + CGX::SetAlphaCompare(GX_LESS, 128, GX_AOP_AND, GX_ALWAYS, 0); CGX::SetNumTevStages(5); } else { CGX::SetNumTexGens(2); CGX::SetNumTevStages(4); } constexpr std::array vtxDescList{ - GX::VtxDescList{GX::VA_POS, GX::DIRECT}, - GX::VtxDescList{GX::VA_TEX0, GX::DIRECT}, - GX::VtxDescList{}, + GXVtxDescList{GX_VA_POS, GX_DIRECT}, + GXVtxDescList{GX_VA_TEX0, GX_DIRECT}, + GXVtxDescList{GX_VA_NULL, GX_NONE}, }; CGX::SetVtxDescv(vtxDescList.data()); GXSetColorUpdate(true); GXSetAlphaUpdate(false); GXInvalidateTexAll(); - GXSetVtxAttrFmt(GX::VTXFMT7, GX::VA_POS, GX::CLR_RGBA, GX::F32, 0); - GXSetVtxAttrFmt(GX::VTXFMT7, GX::VA_TEX0, GX::CLR_RGBA, GX::RGBX8, 0); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD1, GX::TEXMAP1, GX::COLOR_NULL); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, GX::CC_C0); - CGX::SetTevColorOp(GX::TEVSTAGE0, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, false, GX::TEVPREV); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, GX::CA_A0); - CGX::SetTevAlphaOp(GX::TEVSTAGE0, GX::TEV_SUB, GX::TB_ZERO, GX::CS_SCALE_1, false, GX::TEVPREV); - CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0); - CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A); - CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD1, GX::TEXMAP2, GX::COLOR_NULL); - CGX::SetTevColorIn(GX::TEVSTAGE1, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, GX::CC_CPREV); - CGX::SetTevColorOp(GX::TEVSTAGE1, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_2, false, GX::TEVPREV); - CGX::SetTevAlphaIn(GX::TEVSTAGE1, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, GX::CA_APREV); - CGX::SetTevAlphaOp(GX::TEVSTAGE1, GX::TEV_SUB, GX::TB_ZERO, GX::CS_SCALE_1, false, GX::TEVPREV); - CGX::SetTevKColorSel(GX::TEVSTAGE1, GX::TEV_KCSEL_K1); - CGX::SetTevKAlphaSel(GX::TEVSTAGE1, GX::TEV_KASEL_K1_A); - CGX::SetTevOrder(GX::TEVSTAGE2, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); - CGX::SetTevColorIn(GX::TEVSTAGE2, GX::CC_ZERO, GX::CC_TEXC, GX::CC_ONE, GX::CC_CPREV); - CGX::SetTevColorOp(GX::TEVSTAGE2, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); - CGX::SetTevAlphaIn(GX::TEVSTAGE2, GX::CA_TEXA, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV); - CGX::SetTevAlphaOp(GX::TEVSTAGE2, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); - CGX::SetTevOrder(GX::TEVSTAGE3, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL); - CGX::SetTevColorIn(GX::TEVSTAGE3, GX::CC_APREV, GX::CC_CPREV, GX::CC_KONST, GX::CC_ZERO); - CGX::SetTevColorOp(GX::TEVSTAGE3, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); - CGX::SetTevAlphaIn(GX::TEVSTAGE3, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO); - CGX::SetTevAlphaOp(GX::TEVSTAGE3, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); - CGX::SetTevKColorSel(GX::TEVSTAGE3, GX::TEV_KCSEL_K2); - GXSetTevColorS10(GX::TEVREG0, 0xffa60000ff8e0087u); - CGX::SetTevKColor(GX::KCOLOR0, zeus::Comp32(0x0000e258)); - CGX::SetTevKColor(GX::KCOLOR1, zeus::Comp32(0xb30000b6)); - CGX::SetTevKColor(GX::KCOLOR2, zeus::Comp32(0xff00ff80)); + GXSetVtxAttrFmt(GX_VTXFMT7, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT7, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBX8, 0); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR_NULL); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_KONST, GX_CC_C0); + CGX::SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, false, GX_TEVPREV); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_KONST, GX_CA_A0); + CGX::SetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_SUB, GX_TB_ZERO, GX_CS_SCALE_1, false, GX_TEVPREV); + CGX::SetTevKColorSel(GX_TEVSTAGE0, GX_TEV_KCSEL_K0); + CGX::SetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K0_A); + CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP2, GX_COLOR_NULL); + CGX::SetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_TEXC, GX_CC_KONST, GX_CC_CPREV); + CGX::SetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, false, GX_TEVPREV); + CGX::SetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA, GX_CA_KONST, GX_CA_APREV); + CGX::SetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_SUB, GX_TB_ZERO, GX_CS_SCALE_1, false, GX_TEVPREV); + CGX::SetTevKColorSel(GX_TEVSTAGE1, GX_TEV_KCSEL_K1); + CGX::SetTevKAlphaSel(GX_TEVSTAGE1, GX_TEV_KASEL_K1_A); + CGX::SetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + CGX::SetTevColorIn(GX_TEVSTAGE2, GX_CC_ZERO, GX_CC_TEXC, GX_CC_ONE, GX_CC_CPREV); + CGX::SetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + CGX::SetTevAlphaIn(GX_TEVSTAGE2, GX_CA_TEXA, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV); + CGX::SetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + CGX::SetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + CGX::SetTevColorIn(GX_TEVSTAGE3, GX_CC_APREV, GX_CC_CPREV, GX_CC_KONST, GX_CC_ZERO); + CGX::SetTevColorOp(GX_TEVSTAGE3, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + CGX::SetTevAlphaIn(GX_TEVSTAGE3, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + CGX::SetTevAlphaOp(GX_TEVSTAGE3, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + CGX::SetTevKColorSel(GX_TEVSTAGE3, GX_TEV_KCSEL_K2); + GXSetTevColorS10(GX_TEVREG0, GXColorS10{-90, 0, -114, 135}); + CGX::SetTevKColor(GX_KCOLOR0, GXColor{0x00, 0x00, 0xe2, 0x58}); + CGX::SetTevKColor(GX_KCOLOR1, GXColor{0xb3, 0x00, 0x00, 0xb6}); + CGX::SetTevKColor(GX_KCOLOR2, GXColor{0xff, 0x00, 0xff, 0x80}); } static void MyTHPGXRestore() { - CGX::SetZMode(true, GX::ALWAYS, false); - CGX::SetBlendMode(GX::BM_NONE, GX::BL_ONE, GX::BL_ZERO, GX::LO_SET); + CGX::SetZMode(true, GX_ALWAYS, false); + CGX::SetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_SET); CGX::SetNumTexGens(1); CGX::SetNumChans(0); CGX::SetNumTevStages(1); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); - CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_AND, GX::ALWAYS, 0); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + CGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); } /* used in the original to look up fixed-point dividends on a @@ -295,25 +299,28 @@ CMoviePlayer::CMoviePlayer(const char* path, float preLoadSeconds, bool loop, bo x80_textures.reserve(3); for (int i = 0; i < 3; ++i) { CTHPTextureSet& set = x80_textures.emplace_back(); - if (deinterlace) { - /* metaforce addition: this way interlaced THPs don't look horrible */ - set.Y[0] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height / 2, 1, GX::TF_I8, - fmt::format(FMT_STRING("Movie {} Texture Set {} Y[0]"), path, i)); - set.Y[1] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height / 2, 1, GX::TF_I8, - fmt::format(FMT_STRING("Movie {} Texture Set {} Y[1]"), path, i)); - set.U = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, GX::TF_I8, - fmt::format(FMT_STRING("Movie {} Texture Set {} U"), path, i)); - set.V = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, GX::TF_I8, - fmt::format(FMT_STRING("Movie {} Texture Set {} V"), path, i)); - } else { - /* normal progressive presentation */ - set.Y[0] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height, 1, GX::TF_I8, - fmt::format(FMT_STRING("Movie {} Texture Set {} Y"), path, i)); - set.U = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, GX::TF_I8, - fmt::format(FMT_STRING("Movie {} Texture Set {} U"), path, i)); - set.V = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, GX::TF_I8, - fmt::format(FMT_STRING("Movie {} Texture Set {} V"), path, i)); - } + // if (deinterlace) { + // /* metaforce addition: this way interlaced THPs don't look horrible */ + // set.Y[0] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height / 2, 1, GX_TF_I8, + // fmt::format(FMT_STRING("Movie {} Texture Set {} Y[0]"), path, + // i)); + // set.Y[1] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height / 2, 1, GX_TF_I8, + // fmt::format(FMT_STRING("Movie {} Texture Set {} Y[1]"), path, + // i)); + // set.U = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, GX_TF_I8, + // fmt::format(FMT_STRING("Movie {} Texture Set {} U"), path, i)); + // set.V = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, GX_TF_I8, + // fmt::format(FMT_STRING("Movie {} Texture Set {} V"), path, i)); + // } else { + // /* normal progressive presentation */ + // set.Y[0] = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width, x6c_videoInfo.height, 1, GX_TF_I8, + // fmt::format(FMT_STRING("Movie {} Texture Set {} Y"), path, + // i)); + // set.U = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, GX_TF_I8, + // fmt::format(FMT_STRING("Movie {} Texture Set {} U"), path, i)); + // set.V = aurora::gfx::new_dynamic_texture_2d(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, 1, GX_TF_I8, + // fmt::format(FMT_STRING("Movie {} Texture Set {} V"), path, i)); + // } if (xf4_25_hasAudio) set.audioBuf.reset(new s16[x28_thpHead.maxAudioSamples * 2]); } @@ -485,22 +492,22 @@ bool CMoviePlayer::DrawVideo() { const s32 vr = vpLeft + vpWidth + centerX; const s32 vb = vpTop + vpHeight + centerY; const s32 vt = vpTop - centerY; - aurora::Vec3 v1; - aurora::Vec3 v2; - aurora::Vec3 v3; - aurora::Vec3 v4; - v1.x = vl; - v1.y = 0.0; - v1.z = vb; - v2.x = vr; - v2.y = 0.0; - v2.z = vb; - v3.x = vl; - v3.y = 0.0; - v3.z = vt; - v4.x = vr; - v4.y = 0.0; - v4.z = vt; + zeus::CVector3f v1; + zeus::CVector3f v2; + zeus::CVector3f v3; + zeus::CVector3f v4; + v1.x() = vl; + v1.y() = 0.0; + v1.z() = vb; + v2.x() = vr; + v2.y() = 0.0; + v2.z() = vb; + v3.x() = vl; + v3.y() = 0.0; + v3.z() = vt; + v4.x() = vr; + v4.y() = 0.0; + v4.z() = vt; DrawFrame(v1, v2, v3, v4); return true; @@ -525,27 +532,27 @@ void CMoviePlayer::DrawFrame(const zeus::CVector3f& v1, const zeus::CVector3f& v vPad = CGraphics::GetViewportAspect() / 1.33f; } - /* draw appropriate field */ - CTHPTextureSet& tex = x80_textures[xd0_drawTexSlot]; - aurora::gfx::queue_movie_player(tex.Y[m_deinterlace ? (xfc_fieldIndex != 0) : 0], tex.U, tex.V, hPad, vPad); + // /* draw appropriate field */ + // CTHPTextureSet& tex = x80_textures[xd0_drawTexSlot]; + // aurora::gfx::queue_movie_player(tex.Y[m_deinterlace ? (xfc_fieldIndex != 0) : 0], tex.U, tex.V, hPad, vPad); -// MyTHPGXYuv2RgbSetup(CGraphics::g_LastFrameUsedAbove, xf4_26_fieldFlip); -// uintptr_t planeSize = x6c_videoInfo.width * x6c_videoInfo.height; -// uintptr_t planeSizeQuarter = planeSize / 4; -// MyTHPYuv2RgbTextureSetup(m_yuvBuf.get(), m_yuvBuf.get() + planeSize, m_yuvBuf.get() + planeSize + planeSizeQuarter, -// x6c_videoInfo.width, x6c_videoInfo.height); -// -// CGX::Begin(GX::TRIANGLEFAN, GX::VTXFMT7, 4); -// GXPosition3f32(v1); -// GXTexCoord2f32(0.f, 0.f); -// GXPosition3f32(v3); -// GXTexCoord2f32(0.f, 1.f); -// GXPosition3f32(v4); -// GXTexCoord2f32(1.f, 1.f); -// GXPosition3f32(v2); -// GXTexCoord2f32(1.f, 0.f); -// CGX::End(); -// MyTHPGXRestore(); + MyTHPGXYuv2RgbSetup(CGraphics::g_LastFrameUsedAbove, xf4_26_fieldFlip); + uintptr_t planeSize = x6c_videoInfo.width * x6c_videoInfo.height; + uintptr_t planeSizeQuarter = planeSize / 4; + MyTHPYuv2RgbTextureSetup(m_yuvBuf.get(), m_yuvBuf.get() + planeSize, m_yuvBuf.get() + planeSize + planeSizeQuarter, + x6c_videoInfo.width, x6c_videoInfo.height); + + CGX::Begin(GX_TRIANGLEFAN, GX_VTXFMT7, 4); + GXPosition3f32(v1); + GXTexCoord2f32(0.f, 0.f); + GXPosition3f32(v3); + GXTexCoord2f32(0.f, 1.f); + GXPosition3f32(v4); + GXTexCoord2f32(1.f, 1.f); + GXPosition3f32(v2); + GXTexCoord2f32(1.f, 0.f); + CGX::End(); + MyTHPGXRestore(); /* ensure second field is being displayed by VI to signal advance * (faked in metaforce with continuous xor) */ @@ -659,25 +666,25 @@ void CMoviePlayer::DecodeFromRead(const void* data) { uintptr_t planeSizeHalf = planeSize / 2; uintptr_t planeSizeQuarter = planeSizeHalf / 2; - if (m_deinterlace) { - /* Deinterlace into 2 discrete 60-fps half-res textures */ - auto buffer = std::make_unique(planeSizeHalf); - for (unsigned y = 0; y < x6c_videoInfo.height / 2; ++y) { - memcpy(buffer.get() + x6c_videoInfo.width * y, m_yuvBuf.get() + x6c_videoInfo.width * (y * 2), - x6c_videoInfo.width); - } - aurora::gfx::write_texture(*tex.Y[0], {buffer.get(), planeSizeHalf}); - for (unsigned y = 0; y < x6c_videoInfo.height / 2; ++y) { - memcpy(buffer.get() + x6c_videoInfo.width * y, m_yuvBuf.get() + x6c_videoInfo.width * (y * 2 + 1), - x6c_videoInfo.width); - } - aurora::gfx::write_texture(*tex.Y[1], {buffer.get(), planeSizeHalf}); - } else { - /* Direct planar load */ - aurora::gfx::write_texture(*tex.Y[0], {m_yuvBuf.get(), planeSize}); - } - aurora::gfx::write_texture(*tex.U, {m_yuvBuf.get() + planeSize, planeSizeQuarter}); - aurora::gfx::write_texture(*tex.V, {m_yuvBuf.get() + planeSize + planeSizeQuarter, planeSizeQuarter}); + // if (m_deinterlace) { + // /* Deinterlace into 2 discrete 60-fps half-res textures */ + // auto buffer = std::make_unique(planeSizeHalf); + // for (unsigned y = 0; y < x6c_videoInfo.height / 2; ++y) { + // memcpy(buffer.get() + x6c_videoInfo.width * y, m_yuvBuf.get() + x6c_videoInfo.width * (y * 2), + // x6c_videoInfo.width); + // } + // aurora::gfx::write_texture(*tex.Y[0], {buffer.get(), planeSizeHalf}); + // for (unsigned y = 0; y < x6c_videoInfo.height / 2; ++y) { + // memcpy(buffer.get() + x6c_videoInfo.width * y, m_yuvBuf.get() + x6c_videoInfo.width * (y * 2 + 1), + // x6c_videoInfo.width); + // } + // aurora::gfx::write_texture(*tex.Y[1], {buffer.get(), planeSizeHalf}); + // } else { + // /* Direct planar load */ + // aurora::gfx::write_texture(*tex.Y[0], {m_yuvBuf.get(), planeSize}); + // } + // aurora::gfx::write_texture(*tex.U, {m_yuvBuf.get() + planeSize, planeSizeQuarter}); + // aurora::gfx::write_texture(*tex.V, {m_yuvBuf.get() + planeSize + planeSizeQuarter, planeSizeQuarter}); break; } diff --git a/Runtime/Graphics/CMoviePlayer.hpp b/Runtime/Graphics/CMoviePlayer.hpp index 0e18fe3de..dceebc65b 100644 --- a/Runtime/Graphics/CMoviePlayer.hpp +++ b/Runtime/Graphics/CMoviePlayer.hpp @@ -69,9 +69,9 @@ private: }; struct CTHPTextureSet { - std::array Y; - aurora::gfx::TextureHandle U; - aurora::gfx::TextureHandle V; + std::array Y; + GXTexObj U; + GXTexObj V; u32 playedSamples = 0; u32 audioSamples = 0; std::unique_ptr audioBuf; diff --git a/Runtime/Graphics/CSimpleShadow.cpp b/Runtime/Graphics/CSimpleShadow.cpp index cc3ae221d..7347e7dd9 100644 --- a/Runtime/Graphics/CSimpleShadow.cpp +++ b/Runtime/Graphics/CSimpleShadow.cpp @@ -32,7 +32,7 @@ void CSimpleShadow::Render(TLockedToken& tex) { CGraphics::DisableAllLights(); CGraphics::SetModelMatrix(x0_xf); - tex->Load(GX::TEXMAP0, EClampMode::Repeat); + tex->Load(GX_TEXMAP0, EClampMode::Repeat); CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc); CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); @@ -40,7 +40,7 @@ void CSimpleShadow::Render(TLockedToken& tex) { CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false); CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear); - CGraphics::StreamBegin(GX::QUADS); + CGraphics::StreamBegin(GX_QUADS); float radius = x34_radius * x30_scale; CGraphics::StreamColor(zeus::CColor{1.f, x3c_heightAlpha * x38_userAlpha}); CGraphics::StreamTexcoord(0.f, 0.f); diff --git a/Runtime/Graphics/CTevCombiners.cpp b/Runtime/Graphics/CTevCombiners.cpp index ea37d601c..9787881bc 100644 --- a/Runtime/Graphics/CTevCombiners.cpp +++ b/Runtime/Graphics/CTevCombiners.cpp @@ -6,15 +6,15 @@ namespace metaforce::CTevCombiners { u32 CTevPass::sNextUniquePass = 0; void CTevPass::Execute(ERglTevStage stage) const { - const auto stageId = GX::TevStageID(stage); + const auto stageId = GXTevStageID(stage); CGX::SetTevColorIn(stageId, x4_colorPass.x0_a, x4_colorPass.x4_b, x4_colorPass.x8_c, x4_colorPass.xc_d); CGX::SetTevAlphaIn(stageId, x14_alphaPass.x0_a, x14_alphaPass.x4_b, x14_alphaPass.x8_c, x14_alphaPass.xc_d); CGX::SetTevColorOp(stageId, x24_colorOp.x4_op, x24_colorOp.x8_bias, x24_colorOp.xc_scale, x24_colorOp.x0_clamp, x24_colorOp.x10_regId); CGX::SetTevAlphaOp(stageId, x38_alphaOp.x4_op, x38_alphaOp.x8_bias, x38_alphaOp.xc_scale, x38_alphaOp.x0_clamp, x38_alphaOp.x10_regId); - CGX::SetTevKColorSel(stageId, GX::TevKColorSel::TEV_KCSEL_8_8); - CGX::SetTevKAlphaSel(stageId, GX::TevKAlphaSel::TEV_KASEL_8_8); + CGX::SetTevKColorSel(stageId, GX_TEV_KCSEL_8_8); + CGX::SetTevKAlphaSel(stageId, GX_TEV_KASEL_8_8); } constexpr u32 maxTevPasses = 2; @@ -22,52 +22,52 @@ static u32 sNumEnabledPasses; static std::array sValidPasses; const CTevPass skPassThru{ - {GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA}, + {GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC}, + {GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA}, }; const CTevPass sTevPass804bfcc0{ - {GX::TevColorArg::CC_C0, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA}, + {GX_CC_C0, GX_CC_TEXC, GX_CC_RASC, GX_CC_ZERO}, + {GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA}, }; const CTevPass sTevPass804bfe68{ - {GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_CPREV, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_APREV, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO}, + {GX_CC_ZERO, GX_CC_CPREV, GX_CC_RASC, GX_CC_ZERO}, + {GX_CA_ZERO, GX_CA_APREV, GX_CA_RASA, GX_CA_ZERO}, }; const CTevPass sTevPass805a5698{ - {GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_C0, GX::TevColorArg::CC_ZERO}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_A0, GX::TevAlphaArg::CA_ZERO}, + {GX_CC_ZERO, GX_CC_RASC, GX_CC_C0, GX_CC_ZERO}, + {GX_CA_ZERO, GX_CA_RASA, GX_CA_A0, GX_CA_ZERO}, }; const CTevPass sTevPass805a5e70{ - {GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_C0}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_A0}, + {GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0}, + {GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0}, }; const CTevPass sTevPass805a5ebc{ - {GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_ZERO}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_ZERO}, + {GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO}, + {GX_CA_ZERO, GX_CA_RASA, GX_CA_TEXA, GX_CA_ZERO}, }; const CTevPass sTevPass805a5f08{ - {GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_TEXA, GX::TevColorArg::CC_ZERO}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA}, + {GX_CC_RASC, GX_CC_TEXC, GX_CC_TEXA, GX_CC_ZERO}, + {GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA}, }; const CTevPass sTevPass805a5f54{ - {GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ONE, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_ZERO}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO}, + {GX_CC_RASC, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO}, + {GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO}, }; const CTevPass sTevPass805a5fa0{ - {GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_TEXC}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA}, + {GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC}, + {GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA}, }; const CTevPass sTevPass805a5fec{ - {GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO}, + {GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC}, + {GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO}, }; const CTevPass sTevPass805a6038{ - {GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_KONST, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO}, + {GX_CC_ZERO, GX_CC_TEXC, GX_CC_RASC, GX_CC_ZERO}, + {GX_CA_ZERO, GX_CA_KONST, GX_CA_RASA, GX_CA_ZERO}, }; const CTevPass sTevPass805a6084{ - {GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_CPREV, GX::TevColorArg::CC_APREV, GX::TevColorArg::CC_ZERO}, - {GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_APREV}, + {GX_CC_ZERO, GX_CC_CPREV, GX_CC_APREV, GX_CC_ZERO}, + {GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV}, }; void Init() { diff --git a/Runtime/Graphics/CTevCombiners.hpp b/Runtime/Graphics/CTevCombiners.hpp index 3abea61d2..f83a85a1f 100644 --- a/Runtime/Graphics/CTevCombiners.hpp +++ b/Runtime/Graphics/CTevCombiners.hpp @@ -4,78 +4,77 @@ #include "RetroTypes.hpp" namespace metaforce { -enum class ERglTevStage : std::underlying_type_t { - Stage0 = GX::TEVSTAGE0, - Stage1 = GX::TEVSTAGE1, - Stage2 = GX::TEVSTAGE2, - Stage3 = GX::TEVSTAGE3, - Stage4 = GX::TEVSTAGE4, - Stage5 = GX::TEVSTAGE5, - Stage6 = GX::TEVSTAGE6, - Stage7 = GX::TEVSTAGE7, - Stage8 = GX::TEVSTAGE8, - Stage9 = GX::TEVSTAGE9, - Stage10 = GX::TEVSTAGE10, - Stage11 = GX::TEVSTAGE11, - Stage12 = GX::TEVSTAGE12, - Stage13 = GX::TEVSTAGE13, - Stage14 = GX::TEVSTAGE14, - Stage15 = GX::TEVSTAGE15, - Max = GX::MAX_TEVSTAGE, - None = GX::NULL_STAGE, +enum class ERglTevStage : std::underlying_type_t { + Stage0 = GX_TEVSTAGE0, + Stage1 = GX_TEVSTAGE1, + Stage2 = GX_TEVSTAGE2, + Stage3 = GX_TEVSTAGE3, + Stage4 = GX_TEVSTAGE4, + Stage5 = GX_TEVSTAGE5, + Stage6 = GX_TEVSTAGE6, + Stage7 = GX_TEVSTAGE7, + Stage8 = GX_TEVSTAGE8, + Stage9 = GX_TEVSTAGE9, + Stage10 = GX_TEVSTAGE10, + Stage11 = GX_TEVSTAGE11, + Stage12 = GX_TEVSTAGE12, + Stage13 = GX_TEVSTAGE13, + Stage14 = GX_TEVSTAGE14, + Stage15 = GX_TEVSTAGE15, + Max = GX_MAX_TEVSTAGE, }; namespace CTevCombiners { struct CTevOp { bool x0_clamp = true; - GX::TevOp x4_op = GX::TevOp::TEV_ADD; - GX::TevBias x8_bias = GX::TevBias::TB_ZERO; - GX::TevScale xc_scale = GX::TevScale::CS_SCALE_1; - GX::TevRegID x10_regId = GX::TevRegID::TEVPREV; + GXTevOp x4_op = GX_TEV_ADD; + GXTevBias x8_bias = GX_TB_ZERO; + GXTevScale xc_scale = GX_CS_SCALE_1; + GXTevRegID x10_regId = GX_TEVPREV; constexpr CTevOp() = default; - constexpr CTevOp(bool clamp, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, GX::TevRegID regId) + constexpr CTevOp(bool clamp, GXTevOp op, GXTevBias bias, GXTevScale scale, GXTevRegID regId) : x0_clamp(clamp), x4_op(op), x8_bias(bias), xc_scale(scale), x10_regId(regId) {} constexpr CTevOp(u32 compressedDesc) : x0_clamp((compressedDesc >> 8 & 1) != 0) - , x4_op(static_cast(compressedDesc & 0xF)) - , x8_bias(static_cast(compressedDesc >> 4 & 3)) - , xc_scale(static_cast(compressedDesc >> 6 & 3)) - , x10_regId(static_cast(compressedDesc >> 9 & 3)) {} + , x4_op(static_cast(compressedDesc & 0xF)) + , x8_bias(static_cast(compressedDesc >> 4 & 3)) + , xc_scale(static_cast(compressedDesc >> 6 & 3)) + , x10_regId(static_cast(compressedDesc >> 9 & 3)) {} bool operator==(const CTevOp& rhs) const { return x0_clamp == rhs.x0_clamp && x4_op == rhs.x4_op && x8_bias == rhs.x8_bias && xc_scale == rhs.xc_scale; } }; struct ColorPass { - GX::TevColorArg x0_a; - GX::TevColorArg x4_b; - GX::TevColorArg x8_c; - GX::TevColorArg xc_d; + GXTevColorArg x0_a; + GXTevColorArg x4_b; + GXTevColorArg x8_c; + GXTevColorArg xc_d; - constexpr ColorPass(GX::TevColorArg a, GX::TevColorArg b, GX::TevColorArg c, GX::TevColorArg d) + constexpr ColorPass(GXTevColorArg a, GXTevColorArg b, GXTevColorArg c, GXTevColorArg d) : x0_a(a), x4_b(b), x8_c(c), xc_d(d) {} constexpr ColorPass(u32 compressedDesc) - : x0_a(static_cast(compressedDesc & 0x1F)) - , x4_b(static_cast(compressedDesc >> 5 & 0x1F)) - , x8_c(static_cast(compressedDesc >> 10 & 0x1F)) - , xc_d(static_cast(compressedDesc >> 15 & 0x1F)) {} + : x0_a(static_cast(compressedDesc & 0x1F)) + , x4_b(static_cast(compressedDesc >> 5 & 0x1F)) + , x8_c(static_cast(compressedDesc >> 10 & 0x1F)) + , xc_d(static_cast(compressedDesc >> 15 & 0x1F)) {} bool operator==(const ColorPass& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } }; struct AlphaPass { - GX::TevAlphaArg x0_a; - GX::TevAlphaArg x4_b; - GX::TevAlphaArg x8_c; - GX::TevAlphaArg xc_d; + GXTevAlphaArg x0_a; + GXTevAlphaArg x4_b; + GXTevAlphaArg x8_c; + GXTevAlphaArg xc_d; - constexpr AlphaPass(GX::TevAlphaArg a, GX::TevAlphaArg b, GX::TevAlphaArg c, GX::TevAlphaArg d) + constexpr AlphaPass(GXTevAlphaArg a, GXTevAlphaArg b, GXTevAlphaArg c, GXTevAlphaArg d) : x0_a(a), x4_b(b), x8_c(c), xc_d(d) {} constexpr AlphaPass(u32 compressedDesc) - : x0_a(static_cast(compressedDesc & 0x1F)) - , x4_b(static_cast(compressedDesc >> 5 & 0x1F)) - , x8_c(static_cast(compressedDesc >> 10 & 0x1F)) - , xc_d(static_cast(compressedDesc >> 15 & 0x1F)) {} + : x0_a(static_cast(compressedDesc & 0x1F)) + , x4_b(static_cast(compressedDesc >> 5 & 0x1F)) + , x8_c(static_cast(compressedDesc >> 10 & 0x1F)) + , xc_d(static_cast(compressedDesc >> 15 & 0x1F)) {} bool operator==(const AlphaPass& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } }; diff --git a/Runtime/Graphics/CTexture.cpp b/Runtime/Graphics/CTexture.cpp index d4d2accbe..5f05d77b1 100644 --- a/Runtime/Graphics/CTexture.cpp +++ b/Runtime/Graphics/CTexture.cpp @@ -6,7 +6,7 @@ #include namespace metaforce { -static std::array sLoadedTextures{}; +static std::array sLoadedTextures{}; CTexture::CTexture(ETexelFormat fmt, u16 w, u16 h, s32 mips, std::string_view label) : x0_fmt(fmt) @@ -21,7 +21,7 @@ CTexture::CTexture(ETexelFormat fmt, u16 w, u16 h, s32 mips, std::string_view la } CTexture::CTexture(CInputStream& in, std::string_view label, EAutoMipmap automip, EBlackKey blackKey) -: x0_fmt(ETexelFormat(in.ReadLong())) +: x0_fmt(static_cast(in.ReadLong())) , x4_w(in.ReadShort()) , x6_h(in.ReadShort()) , x8_mips(in.ReadLong()) @@ -64,6 +64,8 @@ CTexture::CTexture(CInputStream& in, std::string_view label, EAutoMipmap automip InitTextureObjs(); } +CTexture::~CTexture() { GXDestroyTexObj(&x20_texObj); } + u8* CTexture::Lock() { xa_24_locked = true; return GetBitMapData(0); @@ -78,7 +80,7 @@ void CTexture::UnLock() { m_needsTexObjDataLoad = true; } -void CTexture::Load(GX::TexMapID id, EClampMode clamp) { +void CTexture::Load(GXTexMapID id, EClampMode clamp) { if (sLoadedTextures[id] != this || xa_29_canLoadObj) { auto* data = /*x44_aramToken.GetMRAMSafe() */ x44_aramToken_x4_buff.get(); CountMemory(); @@ -104,7 +106,7 @@ void CTexture::Load(GX::TexMapID id, EClampMode clamp) { } } -void CTexture::LoadMipLevel(float lod, GX::TexMapID id, EClampMode clamp) { +void CTexture::LoadMipLevel(float lod, GXTexMapID id, EClampMode clamp) { // auto image_ptr = /*x44_aramToken.GetMRAMSafe() */ x44_aramToken_x4_buff.get(); // u32 width = x4_w; // u32 height = x6_h; @@ -154,16 +156,16 @@ u8* CTexture::GetBitMapData(s32 mip) const { return const_cast(GetConstBitM void CTexture::InitBitmapBuffers(ETexelFormat fmt, u16 width, u16 height, s32 mips) { switch (fmt) { case ETexelFormat::I4: - x18_gxFormat = GX::TF_I4; + x18_gxFormat = GX_TF_I4; break; case ETexelFormat::I8: - x18_gxFormat = GX::TF_I8; + x18_gxFormat = GX_TF_I8; break; case ETexelFormat::IA4: - x18_gxFormat = GX::TF_IA4; + x18_gxFormat = GX_TF_IA4; break; case ETexelFormat::IA8: - x18_gxFormat = GX::TF_IA8; + x18_gxFormat = GX_TF_IA8; break; case ETexelFormat::C4: x1c_gxCIFormat = GX_TF_C4; @@ -175,16 +177,23 @@ void CTexture::InitBitmapBuffers(ETexelFormat fmt, u16 width, u16 height, s32 mi x1c_gxCIFormat = GX_TF_C14X2; break; case ETexelFormat::RGB565: - x18_gxFormat = GX::TF_RGB565; + x18_gxFormat = GX_TF_RGB565; break; case ETexelFormat::RGB5A3: - x18_gxFormat = GX::TF_RGB5A3; + x18_gxFormat = GX_TF_RGB5A3; break; case ETexelFormat::RGBA8: - x18_gxFormat = GX::TF_RGBA8; + x18_gxFormat = GX_TF_RGBA8; break; case ETexelFormat::CMPR: - x18_gxFormat = GX::TF_CMPR; + x18_gxFormat = GX_TF_CMPR; + break; + // Metaforce additions + case ETexelFormat::R8PC: + x18_gxFormat = GX_TF_R8_PC; + break; + case ETexelFormat::RGBA8PC: + x18_gxFormat = GX_TF_RGBA8_PC; break; default: break; @@ -192,7 +201,7 @@ void CTexture::InitBitmapBuffers(ETexelFormat fmt, u16 width, u16 height, s32 mi u32 format = (x0_fmt == ETexelFormat::C4 || x0_fmt == ETexelFormat::C8 || x0_fmt == ETexelFormat::C14X2) ? u32(x1c_gxCIFormat) - : u32(x18_gxFormat); + : x18_gxFormat; xc_memoryAllocated = GXGetTexBufferSize(width, height, format, mips > 1, mips > 1 ? 11 : 0); x44_aramToken_x4_buff = std::make_unique(xc_memoryAllocated); /*x44_aramToken.PostConstruct(buf, xc_memoryAllocated, 1);*/ @@ -268,8 +277,7 @@ bool CTexture::sMangleMips = false; u32 CTexture::sCurrentFrameCount = 0; u32 CTexture::sTotalAllocatedMemory = 0; -void CTexture::InvalidateTexMap(GX::TexMapID id) { - // TODO: can we unbind in GX? +void CTexture::InvalidateTexMap(GXTexMapID id) { sLoadedTextures[id] = nullptr; } diff --git a/Runtime/Graphics/CTexture.hpp b/Runtime/Graphics/CTexture.hpp index 972844bfd..6c6d87955 100644 --- a/Runtime/Graphics/CTexture.hpp +++ b/Runtime/Graphics/CTexture.hpp @@ -9,6 +9,24 @@ #include "GX.hpp" namespace metaforce { +enum class ETexelFormat { + Invalid = -1, + I4 = 0, + I8 = 1, + IA4 = 2, + IA8 = 3, + C4 = 4, + C8 = 5, + C14X2 = 6, + RGB565 = 7, + RGB5A3 = 8, + RGBA8 = 9, + CMPR = 10, + // Metaforce addition: non-converting formats + RGBA8PC = 11, + R8PC = 12, +}; + enum class EClampMode : std::underlying_type_t { Clamp = GX_CLAMP, Repeat = GX_REPEAT, @@ -63,7 +81,7 @@ private: u32 xc_memoryAllocated = 0; std::unique_ptr x10_graphicsPalette; std::unique_ptr x14_bitmapReloader; - GX::TextureFormat x18_gxFormat = GX::TF_RGB565; + u32 x18_gxFormat = GX_TF_RGB565; GXCITexFmt x1c_gxCIFormat = GX_TF_C8; GXTexObj x20_texObj; EClampMode x40_clampMode = EClampMode::Repeat; @@ -86,6 +104,7 @@ public: CTexture(ETexelFormat fmt, u16 w, u16 h, s32 mips, std::string_view label); CTexture(CInputStream& in, std::string_view label, EAutoMipmap automip = EAutoMipmap::Zero, EBlackKey blackKey = EBlackKey::Zero); + ~CTexture(); [[nodiscard]] ETexelFormat GetTextureFormat() const { return x0_fmt; } [[nodiscard]] u16 GetWidth() const { return x4_w; } @@ -97,8 +116,8 @@ public: [[nodiscard]] bool HasPalette() const { return x10_graphicsPalette != nullptr; } [[nodiscard]] u8* Lock(); void UnLock(); - void Load(GX::TexMapID id, EClampMode clamp); - void LoadMipLevel(float lod, GX::TexMapID id, EClampMode clamp); // was an s32 mip parameter, adjusted to use lod + void Load(GXTexMapID id, EClampMode clamp); + void LoadMipLevel(float lod, GXTexMapID id, EClampMode clamp); // was an s32 mip parameter, adjusted to use lod // void UnloadBitmapData(u32) const; // void TryReloadBitmapData(CResFactory&) const; // void LoadToMRAM() const; @@ -112,7 +131,7 @@ public: return x0_fmt == ETexelFormat::C4 || x0_fmt == ETexelFormat::C8 || x0_fmt == ETexelFormat::C14X2; } - static void InvalidateTexMap(GX::TexMapID id); + static void InvalidateTexMap(GXTexMapID id); static void SetMangleMips(bool b) { sMangleMips = b; } static void SetCurrentFrameCount(u32 frameCount) { sCurrentFrameCount = frameCount; } }; diff --git a/Runtime/Graphics/GX.hpp b/Runtime/Graphics/GX.hpp index a6668c869..a66c7f9c3 100644 --- a/Runtime/Graphics/GX.hpp +++ b/Runtime/Graphics/GX.hpp @@ -1,985 +1,43 @@ #pragma once -#ifndef GX_IS_WII -#define GX_IS_WII 0 -#endif +#include -#include "../GCNTypes.hpp" - -#include #include -#include #include -#include -#include +#include namespace GX { -#if GX_IS_WII -constexpr float LARGE_NUMBER = -1.0e+18f; -#else -constexpr float LARGE_NUMBER = -1048576.0f; -#endif - -enum Attr { - VA_PNMTXIDX = 0x0, - VA_TEX0MTXIDX = 0x1, - VA_TEX1MTXIDX = 0x2, - VA_TEX2MTXIDX = 0x3, - VA_TEX3MTXIDX = 0x4, - VA_TEX4MTXIDX = 0x5, - VA_TEX5MTXIDX = 0x6, - VA_TEX6MTXIDX = 0x7, - VA_TEX7MTXIDX = 0x8, - VA_POS = 0x9, - VA_NRM = 0xa, - VA_CLR0 = 0xb, - VA_CLR1 = 0xc, - VA_TEX0 = 0xd, - VA_TEX1 = 0xe, - VA_TEX2 = 0xf, - VA_TEX3 = 0x10, - VA_TEX4 = 0x11, - VA_TEX5 = 0x12, - VA_TEX6 = 0x13, - VA_TEX7 = 0x14, - POS_MTX_ARRAY = 0x15, - NRM_MTX_ARRAY = 0x16, - TEX_MTX_ARRAY = 0x17, - LIGHT_ARRAY = 0x18, - VA_NBT = 0x19, - VA_MAX_ATTR = 0x1a, - VA_NULL = 0xff, -}; - -enum AttrType { - NONE, - DIRECT, - INDEX8, - INDEX16, -}; - -struct VtxDescList { - Attr attr = GX::VA_NULL; - AttrType type = GX::NONE; - operator bool() const { return attr != GX::VA_NULL; } -}; - -enum VtxFmt { - VTXFMT0 = 0, - VTXFMT1, - VTXFMT2, - VTXFMT3, - VTXFMT4, - VTXFMT5, - VTXFMT6, - VTXFMT7, - MAX_VTXFMT, -}; - -enum TevColorArg { - CC_CPREV = 0, - CC_APREV = 1, - CC_C0 = 2, - CC_A0 = 3, - CC_C1 = 4, - CC_A1 = 5, - CC_C2 = 6, - CC_A2 = 7, - CC_TEXC = 8, - CC_TEXA = 9, - CC_RASC = 10, - CC_RASA = 11, - CC_ONE = 12, - CC_HALF = 13, - CC_KONST = 14, - CC_ZERO = 15, -}; - -enum TevAlphaArg { - CA_APREV = 0, - CA_A0 = 1, - CA_A1 = 2, - CA_A2 = 3, - CA_TEXA = 4, - CA_RASA = 5, - CA_KONST = 6, - CA_ZERO = 7, -}; - -enum TevKColorID { - KCOLOR0 = 0, - KCOLOR1, - KCOLOR2, - KCOLOR3, - MAX_KCOLOR, -}; - -enum TevKColorSel { - TEV_KCSEL_8_8 = 0x00, - TEV_KCSEL_7_8 = 0x01, - TEV_KCSEL_6_8 = 0x02, - TEV_KCSEL_5_8 = 0x03, - TEV_KCSEL_4_8 = 0x04, - TEV_KCSEL_3_8 = 0x05, - TEV_KCSEL_2_8 = 0x06, - TEV_KCSEL_1_8 = 0x07, - - TEV_KCSEL_1 = TEV_KCSEL_8_8, - TEV_KCSEL_3_4 = TEV_KCSEL_6_8, - TEV_KCSEL_1_2 = TEV_KCSEL_4_8, - TEV_KCSEL_1_4 = TEV_KCSEL_2_8, - - TEV_KCSEL_K0 = 0x0C, - TEV_KCSEL_K1 = 0x0D, - TEV_KCSEL_K2 = 0x0E, - TEV_KCSEL_K3 = 0x0F, - TEV_KCSEL_K0_R = 0x10, - TEV_KCSEL_K1_R = 0x11, - TEV_KCSEL_K2_R = 0x12, - TEV_KCSEL_K3_R = 0x13, - TEV_KCSEL_K0_G = 0x14, - TEV_KCSEL_K1_G = 0x15, - TEV_KCSEL_K2_G = 0x16, - TEV_KCSEL_K3_G = 0x17, - TEV_KCSEL_K0_B = 0x18, - TEV_KCSEL_K1_B = 0x19, - TEV_KCSEL_K2_B = 0x1A, - TEV_KCSEL_K3_B = 0x1B, - TEV_KCSEL_K0_A = 0x1C, - TEV_KCSEL_K1_A = 0x1D, - TEV_KCSEL_K2_A = 0x1E, - TEV_KCSEL_K3_A = 0x1F, - INVALID_KCSEL = 0xFF -}; - -enum TevKAlphaSel { - TEV_KASEL_8_8 = 0x00, - TEV_KASEL_7_8 = 0x01, - TEV_KASEL_6_8 = 0x02, - TEV_KASEL_5_8 = 0x03, - TEV_KASEL_4_8 = 0x04, - TEV_KASEL_3_8 = 0x05, - TEV_KASEL_2_8 = 0x06, - TEV_KASEL_1_8 = 0x07, - - TEV_KASEL_1 = TEV_KASEL_8_8, - TEV_KASEL_3_4 = TEV_KASEL_6_8, - TEV_KASEL_1_2 = TEV_KASEL_4_8, - TEV_KASEL_1_4 = TEV_KASEL_2_8, - - TEV_KASEL_K0_R = 0x10, - TEV_KASEL_K1_R = 0x11, - TEV_KASEL_K2_R = 0x12, - TEV_KASEL_K3_R = 0x13, - TEV_KASEL_K0_G = 0x14, - TEV_KASEL_K1_G = 0x15, - TEV_KASEL_K2_G = 0x16, - TEV_KASEL_K3_G = 0x17, - TEV_KASEL_K0_B = 0x18, - TEV_KASEL_K1_B = 0x19, - TEV_KASEL_K2_B = 0x1A, - TEV_KASEL_K3_B = 0x1B, - TEV_KASEL_K0_A = 0x1C, - TEV_KASEL_K1_A = 0x1D, - TEV_KASEL_K2_A = 0x1E, - TEV_KASEL_K3_A = 0x1F, - INVALID_KASEL = 0xFF -}; - -enum TevOp { - TEV_ADD = 0, - TEV_SUB = 1, - TEV_COMP_R8_GT = 8, - TEV_COMP_R8_EQ = 9, - TEV_COMP_GR16_GT = 10, - TEV_COMP_GR16_EQ = 11, - TEV_COMP_BGR24_GT = 12, - TEV_COMP_BGR24_EQ = 13, - TEV_COMP_RGB8_GT = 14, - TEV_COMP_RGB8_EQ = 15, - TEV_COMP_A8_GT = TEV_COMP_RGB8_GT, - TEV_COMP_A8_EQ = TEV_COMP_RGB8_EQ -}; - -enum TevBias { - TB_ZERO = 0, - TB_ADDHALF = 1, - TB_SUBHALF = 2, -}; - -enum TevScale { - CS_SCALE_1 = 0, - CS_SCALE_2 = 1, - CS_SCALE_4 = 2, - CS_DIVIDE_2 = 3, -}; - -enum TexOffset { - TO_ZERO, - TO_SIXTEENTH, - TO_EIGHTH, - TO_FOURTH, - TO_HALF, - TO_ONE, - MAX_TEXOFFSET, -}; - -enum TexGenType { - TG_MTX3x4 = 0, - TG_MTX2x4, - TG_BUMP0, - TG_BUMP1, - TG_BUMP2, - TG_BUMP3, - TG_BUMP4, - TG_BUMP5, - TG_BUMP6, - TG_BUMP7, - TG_SRTG -}; - -enum TexGenSrc { - TG_POS = 0, - TG_NRM, - TG_BINRM, - TG_TANGENT, - TG_TEX0, - TG_TEX1, - TG_TEX2, - TG_TEX3, - TG_TEX4, - TG_TEX5, - TG_TEX6, - TG_TEX7, - TG_TEXCOORD0, - TG_TEXCOORD1, - TG_TEXCOORD2, - TG_TEXCOORD3, - TG_TEXCOORD4, - TG_TEXCOORD5, - TG_TEXCOORD6, - TG_COLOR0, - TG_COLOR1, - MAX_TEXGENSRC = 0xFF, -}; - -enum TexMtx { - TEXMTX0 = 30, - TEXMTX1 = 33, - TEXMTX2 = 36, - TEXMTX3 = 39, - TEXMTX4 = 42, - TEXMTX5 = 45, - TEXMTX6 = 48, - TEXMTX7 = 51, - TEXMTX8 = 54, - TEXMTX9 = 57, - IDENTITY = 60 -}; - -enum PTTexMtx { - PTTEXMTX0 = 64, - PTTEXMTX1 = 67, - PTTEXMTX2 = 70, - PTTEXMTX3 = 73, - PTTEXMTX4 = 76, - PTTEXMTX5 = 79, - PTTEXMTX6 = 82, - PTTEXMTX7 = 85, - PTTEXMTX8 = 88, - PTTEXMTX9 = 91, - PTTEXMTX10 = 94, - PTTEXMTX11 = 97, - PTTEXMTX12 = 100, - PTTEXMTX13 = 103, - PTTEXMTX14 = 106, - PTTEXMTX15 = 109, - PTTEXMTX16 = 112, - PTTEXMTX17 = 115, - PTTEXMTX18 = 118, - PTTEXMTX19 = 121, - PTIDENTITY = 125 -}; - -enum TexCoordID { - TEXCOORD0 = 0x0, - TEXCOORD1, - TEXCOORD2, - TEXCOORD3, - TEXCOORD4, - TEXCOORD5, - TEXCOORD6, - TEXCOORD7, - MAX_TEXCOORD = 8, - TEXCOORD_NULL = 0xff -}; - -enum TevSwapSel { - TEV_SWAP0 = 0x0, - TEV_SWAP1 = 0x1, - TEV_SWAP2 = 0x2, - TEV_SWAP3 = 0x3, - MAX_TEVSWAP = 0x4, -}; - -enum TevColorChan { - CH_RED = 0x0, - CH_GREEN = 0x1, - CH_BLUE = 0x2, - CH_ALPHA = 0x3, -}; - -enum TevRegID { - TEVPREV = 0, - TEVREG0 = 1, - TEVREG1 = 2, - TEVREG2 = 3, - TEVLAZY = 5, -}; - -enum DiffuseFn { - DF_NONE = 0, - DF_SIGN = 1, - DF_CLAMP = 2, -}; - -enum AttnFn { - AF_SPEC = 0, - AF_SPOT = 1, - AF_NONE = 2, -}; - -enum Primitive { - POINTS = 0xb8, - LINES = 0xa8, - LINESTRIP = 0xb0, - TRIANGLES = 0x90, - TRIANGLESTRIP = 0x98, - TRIANGLEFAN = 0xa0, - QUADS = 0x80 -}; - -enum ChannelID { - COLOR0, - COLOR1, - ALPHA0, - ALPHA1, - COLOR0A0, - COLOR1A1, - COLOR_ZERO, - ALPHA_BUMP, - ALPHA_BUMPN, - COLOR_NULL = 0xff -}; - -enum BlendMode { - BM_NONE, - BM_BLEND, - BM_LOGIC, - BM_SUBTRACT, - MAX_BLENDMODE, -}; - -enum LogicOp { - LO_CLEAR, - LO_AND, - LO_REVAND, - LO_COPY, - LO_INVAND, - LO_NOOP, - LO_XOR, - LO_OR, - LO_NOR, - LO_EQUIV, - LO_INV, - LO_REVOR, - LO_INVCOPY, - LO_INVOR, - LO_NAND, - LO_SET -}; - -enum AlphaOp { - AOP_AND, - AOP_OR, - AOP_XOR, - AOP_XNOR, - MAX_ALPHAOP, -}; - -enum ZTexOp { - ZT_DISABLE, - ZT_ADD, - ZT_REPLACE, - MAX_ZTEXOP, -}; - -enum Compare { - NEVER, - LESS, - EQUAL, - LEQUAL, - GREATER, - NEQUAL, - GEQUAL, - ALWAYS, -}; - -enum BlendFactor { - BL_ZERO, - BL_ONE, - BL_SRCCLR, - BL_INVSRCCLR, - BL_SRCALPHA, - BL_INVSRCALPHA, - BL_DSTALPHA, - BL_INVDSTALPHA, - BL_DSTCLR, - BL_INVDSTCLR, -}; - -enum CullMode { - CULL_NONE, - CULL_FRONT, - CULL_BACK, - CULL_ALL, -}; - -enum TextureFormat { - TF_I4 = 0x0, - TF_I8 = 0x1, - TF_IA4 = 0x2, - TF_IA8 = 0x3, - TF_RGB565 = 0x4, - TF_RGB5A3 = 0x5, - TF_RGBA8 = 0x6, - TF_C4 = 0x8, - TF_C8 = 0x9, - TF_C14X2 = 0xa, - TF_CMPR = 0xE, - TF_Z8 = 0x11, - TF_Z16 = 0x13, - TF_Z24X8 = 0x16, - CTF_R4 = 0x20, - CTF_RA4 = 0x22, - CTF_RA8 = 0x23, - CTF_YUVA8 = 0x26, - CTF_A8 = 0x27, - CTF_R8 = 0x28, - CTF_G8 = 0x29, - CTF_B8 = 0x2a, - CTF_RG8 = 0x2b, - CTF_GB8 = 0x2c, - CTF_Z4 = 0x30, - CTF_Z8M = 0x39, - CTF_Z8L = 0x3a, - CTF_Z16L = 0x3c, -}; - -enum TexMapID { - TEXMAP0, - TEXMAP1, - TEXMAP2, - TEXMAP3, - TEXMAP4, - TEXMAP5, - TEXMAP6, - TEXMAP7, - MAX_TEXMAP, - TEXMAP_NULL = 0xFF, - TEX_DISABLE = 0x100, -}; - -enum TevStageID { - TEVSTAGE0, - TEVSTAGE1, - TEVSTAGE2, - TEVSTAGE3, - TEVSTAGE4, - TEVSTAGE5, - TEVSTAGE6, - TEVSTAGE7, - TEVSTAGE8, - TEVSTAGE9, - TEVSTAGE10, - TEVSTAGE11, - TEVSTAGE12, - TEVSTAGE13, - TEVSTAGE14, - TEVSTAGE15, - MAX_TEVSTAGE, - NULL_STAGE = -1, -}; - -enum IndTexFormat { - ITF_8, - ITF_5, - ITF_4, - ITF_3, - MAX_ITFORMAT, -}; - -enum IndTexBiasSel { - ITB_NONE, - ITB_S, - ITB_T, - ITB_ST, - ITB_U, - ITB_SU, - ITB_TU, - ITB_STU, - MAX_ITBIAS, -}; - -enum IndTexWrap { - ITW_OFF, - ITW_256, - ITW_128, - ITW_64, - ITW_32, - ITW_16, - ITW_0, - MAX_ITWRAP, -}; - -enum IndTexAlphaSel { - ITBA_OFF, - ITBA_S, - ITBA_T, - ITBA_U, - MAX_ITBALPHA, -}; - -enum IndTexStageID { - INDTEXSTAGE0, - INDTEXSTAGE1, - INDTEXSTAGE2, - INDTEXSTAGE3, - MAX_INDTEXSTAGE, -}; - -enum IndTexScale { - ITS_1, - ITS_2, - ITS_4, - ITS_8, - ITS_16, - ITS_32, - ITS_64, - ITS_128, - ITS_256, - MAX_ITSCALE, -}; - -enum IndTexMtxID { - ITM_OFF, - ITM_0, - ITM_1, - ITM_2, - ITM_S0 = 5, - ITM_S1, - ITM_S2, - ITM_T0 = 9, - ITM_T1, - ITM_T2, -}; - -enum TexMtxType { - MTX3x4 = 0, - MTX2x4, -}; - -struct Color { - union { - uint8_t color[4]; - uint32_t num = 0; - }; - Color() = default; - Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) { - color[0] = r; - color[1] = g; - color[2] = b; - color[3] = a; - } - - Color(float r, float g, float b, float a = 1.f) { - color[0] = r * 255; - color[1] = g * 255; - color[2] = b * 255; - color[3] = a * 255; - } - - Color& operator=(uint8_t val) { - color[0] = val; - color[1] = val; - color[2] = val; - color[3] = val; - return *this; - } - - explicit Color(uint32_t val) { *this = val; } - bool operator==(const Color& other) const { return num == other.num; } - bool operator!=(const Color& other) const { return num != other.num; } - uint8_t operator[](size_t idx) const { return color[idx]; } - uint8_t& operator[](size_t idx) { return color[idx]; } -}; - -enum ColorSrc { - SRC_REG = 0, - SRC_VTX, -}; - -enum LightID : u32 { - LIGHT0 = 0x001, - LIGHT1 = 0x002, - LIGHT2 = 0x004, - LIGHT3 = 0x008, - LIGHT4 = 0x010, - LIGHT5 = 0x020, - LIGHT6 = 0x040, - LIGHT7 = 0x080, - MAX_LIGHT = 0x100, - LIGHT_NULL = 0x000, -}; constexpr u8 MaxLights = 8; using LightMask = std::bitset; - -enum FogType { - FOG_NONE = 0x00, - FOG_PERSP_LIN = 0x02, - FOG_PERSP_EXP = 0x04, - FOG_PERSP_EXP2 = 0x05, - FOG_PERSP_REVEXP = 0x06, - FOG_PERSP_REVEXP2 = 0x07, - FOG_ORTHO_LIN = 0x0A, - FOG_ORTHO_EXP = 0x0C, - FOG_ORTHO_EXP2 = 0x0D, - FOG_ORTHO_REVEXP = 0x0E, - FOG_ORTHO_REVEXP2 = 0x0F, -}; - -enum PosNrmMtx { - PNMTX0, - PNMTX1, - PNMTX2, - PNMTX3, - PNMTX4, - PNMTX5, - PNMTX6, - PNMTX7, - PNMTX8, - PNMTX9, -}; - -enum ProjectionType { - PERSPECTIVE, - ORTHOGRAPHIC, -}; - -enum CompCnt { - CLR_RGB = 0, - POS_XY = 0, - TEX_S = 0, - NRM_XYZ = 0, - CLR_RGBA = 1, - POS_XYZ = 1, - NRM_NBT = 1, - TEX_ST = 1, - NRM_NBT3 = 2, -}; - -enum CompType { - RGB565 = 0, - U8 = 0, - RGB8 = 1, - S8 = 1, - U16 = 2, - RGBX8 = 2, - S16 = 3, - RGBA4 = 3, - F32 = 4, - RGBA6 = 4, - RGBA8 = 5, -}; - -struct LightObj { - u32 __padding[3]; - GX::Color color; - float a0 = 1.f; - float a1 = 0.f; - float a2 = 0.f; - float k0 = 1.f; - float k1 = 0.f; - float k2 = 0.f; - float px = 0.f; - float py = 0.f; - float pz = 0.f; - float nx = 0.f; - float ny = 0.f; - float nz = 0.f; -}; - -enum SpotFn { - SP_OFF, - SP_FLAT, - SP_COS, - SP_COS2, - SP_SHARP, - SP_RING1, - SP_RING2, -}; - -enum DistAttnFn { - DA_OFF, - DA_GENTLE, - DA_MEDIUM, - DA_STEEP, -}; } // namespace GX -using GXColor = zeus::CColor; -using GXBool = bool; +constexpr GXColor GX_BLACK{0, 0, 0, 255}; +constexpr GXColor GX_WHITE{255, 255, 255, 255}; +constexpr GXColor GX_CLEAR{0, 0, 0, 0}; -struct GXColorS10 { - s16 r; - s16 g; - s16 b; - s16 a; - - constexpr GXColorS10(u64 c) noexcept - : r(static_cast((c >> 48) & 0xFFFF)) - , g(static_cast((c >> 32) & 0xFFFF)) - , b(static_cast((c >> 16) & 0xFFFF)) - , a(static_cast(c & 0xFFFF)) {} -}; - -enum GXTlutFmt { - GX_TL_IA8 = 0x0, - GX_TL_RGB565 = 0x1, - GX_TL_RGB5A3 = 0x2, - GX_MAX_TLUTFMT = 0x3, -}; - -namespace aurora::gfx { -struct TextureRef; -} // namespace aurora::gfx -struct GXTlutObj { - std::shared_ptr ref; -}; - -enum GXTlut { - GX_TLUT0 = 0, - GX_TLUT1 = 1, - GX_TLUT2 = 2, - GX_TLUT3 = 3, - GX_TLUT4 = 4, - GX_TLUT5 = 5, - GX_TLUT6 = 6, - GX_TLUT7 = 7, - GX_TLUT8 = 8, - GX_TLUT9 = 9, - GX_TLUT10 = 10, - GX_TLUT11 = 11, - GX_TLUT12 = 12, - GX_TLUT13 = 13, - GX_TLUT14 = 14, - GX_TLUT15 = 15, - GX_BIGTLUT0 = 16, - GX_BIGTLUT1 = 17, - GX_BIGTLUT2 = 18, - GX_BIGTLUT3 = 19, -}; - -enum GXTexWrapMode { - GX_CLAMP = 0, - GX_REPEAT = 1, - GX_MIRROR = 2, - GX_MAX_TEXWRAPMODE = 3, -}; - -enum GXTexFilter { - GX_NEAR, - GX_LINEAR, - GX_NEAR_MIP_NEAR, - GX_LIN_MIP_NEAR, - GX_NEAR_MIP_LIN, - GX_LIN_MIP_LIN, -}; - -enum GXAnisotropy { - GX_ANISO_1, - GX_ANISO_2, - GX_ANISO_4, - GX_MAX_ANISOTROPY, -}; - -enum GXCITexFmt { - GX_TF_C4 = GX::TF_C4, - GX_TF_C8 = GX::TF_C8, - GX_TF_C14X2 = GX::TF_C14X2, -}; - -struct GXTexObj { - std::shared_ptr ref; - const void* data; - u32 dataSize; - u16 width; - u16 height; - GX::TextureFormat fmt; - GXTexWrapMode wrapS; - GXTexWrapMode wrapT; - GXBool hasMips; - GXTexFilter minFilter; - GXTexFilter magFilter; - float minLod; - float maxLod; - float lodBias; - GXBool biasClamp; - GXBool doEdgeLod; - GXAnisotropy maxAniso; - GXTlut tlut; - bool dataInvalidated; -}; - -void GXSetNumChans(u8 num) noexcept; -void GXSetNumIndStages(u8 num) noexcept; -void GXSetNumTevStages(u8 num) noexcept; -void GXSetNumTexGens(u8 num) noexcept; -void GXSetTevAlphaIn(GX::TevStageID stageId, GX::TevAlphaArg a, GX::TevAlphaArg b, GX::TevAlphaArg c, - GX::TevAlphaArg d) noexcept; -void GXSetTevAlphaOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, GXBool clamp, - GX::TevRegID outReg) noexcept; -void GXSetTevColorIn(GX::TevStageID stageId, GX::TevColorArg a, GX::TevColorArg b, GX::TevColorArg c, - GX::TevColorArg d) noexcept; -void GXSetTevColorOp(GX::TevStageID stageId, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, GXBool clamp, - GX::TevRegID outReg) noexcept; -void GXSetCullMode(GX::CullMode mode) noexcept; -void GXSetBlendMode(GX::BlendMode mode, GX::BlendFactor src, GX::BlendFactor dst, GX::LogicOp op) noexcept; -void GXSetZMode(GXBool compare_enable, GX::Compare func, GXBool update_enable) noexcept; -void GXSetTevColor(GX::TevRegID id, const GXColor& color) noexcept; -void GXSetTevColorS10(GX::TevRegID id, const GXColorS10& color) noexcept; -void GXSetTevKColor(GX::TevKColorID id, const GXColor& color) noexcept; -void GXSetColorUpdate(GXBool enabled) noexcept; -void GXSetAlphaUpdate(GXBool enabled) noexcept; -void GXSetDstAlpha(GXBool enabled, u8 value) noexcept; -void GXSetCopyClear(const GXColor& color, float depth) noexcept; -void GXSetTevOrder(GX::TevStageID id, GX::TexCoordID tcid, GX::TexMapID tmid, GX::ChannelID cid) noexcept; -void GXSetTevKColorSel(GX::TevStageID id, GX::TevKColorSel sel) noexcept; -void GXSetTevKAlphaSel(GX::TevStageID id, GX::TevKAlphaSel sel) noexcept; -void GXSetChanAmbColor(GX::ChannelID id, const GXColor& color) noexcept; -void GXSetChanMatColor(GX::ChannelID id, const GXColor& color) noexcept; -void GXSetChanCtrl(GX::ChannelID id, GXBool lightingEnabled, GX::ColorSrc ambSrc, GX::ColorSrc matSrc, - GX::LightMask lightState, GX::DiffuseFn diffFn, GX::AttnFn attnFn) noexcept; -void GXSetAlphaCompare(GX::Compare comp0, u8 ref0, GX::AlphaOp op, GX::Compare comp1, u8 ref1) noexcept; -void GXSetVtxDesc(GX::Attr attr, GX::AttrType type) noexcept; -void GXSetVtxDescv(GX::VtxDescList* list) noexcept; -void GXClearVtxDesc() noexcept; -void GXSetArray(GX::Attr attr, const void* data, u8 stride) noexcept; -void GXSetFog(GX::FogType type, float startZ, float endZ, float nearZ, float farZ, const GXColor& color) noexcept; -void GXSetFogColor(const GXColor& color) noexcept; -void GXCallDisplayList(const void* data, u32 nbytes) noexcept; -void GXSetTexCoordGen2(GX::TexCoordID dst, GX::TexGenType type, GX::TexGenSrc src, GX::TexMtx mtx, GXBool normalize, - GX::PTTexMtx postMtx) noexcept; -void GXLoadTexMtxImm(const void* data, u32 id /* GX::TexMtx or GX::PTTexMtx */, GX::TexMtxType type) noexcept; -void GXLoadPosMtxImm(const zeus::CTransform& xf, GX::PosNrmMtx id) noexcept; -void GXLoadNrmMtxImm(const zeus::CTransform& xf, GX::PosNrmMtx id) noexcept; -void GXSetProjection(const zeus::CMatrix4f& mtx, GX::ProjectionType type) noexcept; -void GXSetViewport(float left, float top, float width, float height, float nearZ, float farZ) noexcept; -void GXSetScissor(u32 left, u32 top, u32 width, u32 height) noexcept; -// Unneeded, all attributes are expected to be full floats -static inline void GXSetVtxAttrFmt(GX::VtxFmt vtxfmt, GX::Attr attr, GX::CompCnt cnt, GX::CompType type, - u8 frac) noexcept {} -// Streaming -void GXBegin(GX::Primitive primitive, GX::VtxFmt vtxFmt, u16 nVerts) noexcept; -void GXMatrixIndex1u8(u8 idx) noexcept; -void GXPosition3f32(const zeus::CVector3f& pos) noexcept; -static inline void GXPosition3f32(float x, float y, float z) noexcept { GXPosition3f32({x, y, z}); } -void GXNormal3f32(const zeus::CVector3f& nrm) noexcept; -static inline void GXNormal3f32(float x, float y, float z) noexcept { GXNormal3f32({x, y, z}); } -void GXColor4f32(const zeus::CColor& color) noexcept; -static inline void GXColor4f32(float r, float g, float b, float a) noexcept { GXColor4f32({r, g, b, a}); } -void GXTexCoord2f32(const zeus::CVector2f& uv) noexcept; -static inline void GXTexCoord2f32(float u, float v) noexcept { GXTexCoord2f32({u, v}); } -void GXEnd() noexcept; -// End streaming -void GXSetTevSwapModeTable(GX::TevSwapSel id, GX::TevColorChan red, GX::TevColorChan green, GX::TevColorChan blue, - GX::TevColorChan alpha) noexcept; -void GXSetTevSwapMode(GX::TevStageID stage, GX::TevSwapSel rasSel, GX::TevSwapSel texSel) noexcept; -void GXSetLineWidth(u8 width, GX::TexOffset texOffset) noexcept; -void GXInitTlutObj(GXTlutObj* obj, const void* data, GXTlutFmt format, u16 entries) noexcept; -void GXLoadTlut(const GXTlutObj* obj, GXTlut idx) noexcept; -void GXInitTexObj(GXTexObj* obj, const void* data, u16 width, u16 height, GX::TextureFormat format, GXTexWrapMode wrapS, - GXTexWrapMode wrapT, GXBool mipmap) noexcept; -// Addition for binding render textures -void GXInitTexObjResolved(GXTexObj* obj, u32 bindIdx, GX::TextureFormat format, GXTexWrapMode wrapS, - GXTexWrapMode wrapT, GXTlut tlut); -void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter minFilt, GXTexFilter magFilt, float minLod, float maxLod, float lodBias, - GXBool biasClamp, GXBool doEdgeLod, GXAnisotropy maxAniso) noexcept; -void GXInitTexObjCI(GXTexObj* obj, void* data, u16 width, u16 height, GXCITexFmt format, GXTexWrapMode wrapS, - GXTexWrapMode wrapT, GXBool mipmap, u32 tlut) noexcept; -void GXInitTexObjData(GXTexObj* obj, void* data) noexcept; -void GXInitTexObjWrapMode(GXTexObj* obj, GXTexWrapMode wrapS, GXTexWrapMode wrapT) noexcept; -void GXInitTexObjTlut(GXTexObj* obj, u32 tlut) noexcept; -void GXLoadTexObj(GXTexObj* obj, GX::TexMapID id) noexcept; -void GXSetTexCopySrc(u16 x, u16 y, u16 w, u16 h) noexcept; -void GXSetTexCopyDst(u16 wd, u16 ht, GX::TextureFormat fmt, GXBool mipmap) noexcept; -u32 GXGetTexBufferSize(u16 width, u16 height, u32 fmt, GXBool mips, u8 maxLod) noexcept; -void GXCopyTex(void* dest, GXBool clear) noexcept; -static inline void GXPixModeSync() noexcept {} // no-op -void GXInvalidateTexAll() noexcept; -void GXSetIndTexMtx(GX::IndTexMtxID id, const void* mtx /* Mat4x2 */, s8 scaleExp) noexcept; -void GXSetTevIndirect(GX::TevStageID tevStage, GX::IndTexStageID indStage, GX::IndTexFormat fmt, - GX::IndTexBiasSel biasSel, GX::IndTexMtxID matrixSel, GX::IndTexWrap wrapS, GX::IndTexWrap wrapT, - GXBool addPrev, GXBool indLod, GX::IndTexAlphaSel alphaSel) noexcept; -static inline void GXSetTevDirect(GX::TevStageID stageId) noexcept { - GXSetTevIndirect(stageId, GX::INDTEXSTAGE0, GX::ITF_8, GX::ITB_NONE, GX::ITM_OFF, GX::ITW_OFF, GX::ITW_OFF, false, - false, GX::ITBA_OFF); -} -static inline void GXSetTevIndWarp(GX::TevStageID tevStage, GX::IndTexStageID indStage, GXBool signedOffsets, - GXBool replaceMode, GX::IndTexMtxID matrixSel) noexcept { - const auto wrap = replaceMode ? GX::ITW_0 : GX::ITW_OFF; - const auto biasSel = signedOffsets ? GX::ITB_STU : GX::ITB_NONE; - GXSetTevIndirect(tevStage, indStage, GX::ITF_8, biasSel, matrixSel, wrap, wrap, false, false, GX::ITBA_OFF); -} -void GXSetIndTexOrder(GX::IndTexStageID indStage, GX::TexCoordID texCoord, GX::TexMapID texMap) noexcept; -void GXSetIndTexCoordScale(GX::IndTexStageID indStage, GX::IndTexScale scaleS, GX::IndTexScale scaleT) noexcept; - -// Lighting -void GXInitLightAttn(GX::LightObj* light, float a0, float a1, float a2, float k0, float k1, float k2) noexcept; -void GXInitLightAttnA(GX::LightObj* light, float a0, float a1, float a2) noexcept; -void GXInitLightAttnK(GX::LightObj* light, float k0, float k1, float k2) noexcept; -void GXInitLightSpot(GX::LightObj* light, float cutoff, GX::SpotFn spotFn) noexcept; -void GXInitLightDistAttn(GX::LightObj* light, float refDistance, float refBrightness, GX::DistAttnFn distFunc) noexcept; -static inline void GXInitLightShininess(GX::LightObj* light, float shininess) noexcept { - GXInitLightAttn(light, 0.f, 0.f, 1.f, (shininess) / 2.f, 0.f, 1.f - (shininess) / 2.f); -} -void GXInitLightPos(GX::LightObj* light, float x, float y, float z) noexcept; -static inline void GXInitLightPosv(GX::LightObj* light, float vec[3]) noexcept { - GXInitLightPos(light, vec[0], vec[1], vec[2]); -} -void GXInitLightDir(GX::LightObj* light, float nx, float ny, float nz) noexcept; -static inline void GXInitLightDirv(GX::LightObj* light, float vec[3]) noexcept { - GXInitLightDir(light, vec[0], vec[1], vec[2]); -} -void GXInitSpecularDir(GX::LightObj* light, float nx, float ny, float nz) noexcept; -void GXInitSpecularDirHA(GX::LightObj* light, float nx, float ny, float nz, float hx, float hy, float hz) noexcept; -static inline void GXInitLightSpecularDirHAv(GX::LightObj* light, float vecn[3], float vech[3]) noexcept { - GXInitSpecularDirHA(light, vecn[0], vecn[1], vecn[2], vech[0], vech[1], vech[2]); -} -void GXInitLightColor(GX::LightObj* light, GX::Color col) noexcept; -void GXLoadLightObjImm(const GX::LightObj* light, GX::LightID id) noexcept; -void GXLoadLightObjIndx(u32 index, GX::LightID) noexcept; - -void GXGetLightAttnA(const GX::LightObj* light, float* a0, float* a1, float* a2) noexcept; -void GXGetLightAttnK(const GX::LightObj* light, float* k0, float* k1, float* k2) noexcept; -void GXGetLightPos(const GX::LightObj* light, float* x, float* y, float* z) noexcept; -static inline void GXGetLightPosv(const GX::LightObj* light, float* vec[3]) noexcept { - GXGetLightPos(light, vec[0], vec[1], vec[2]); -} -void GXGetLightDir(const GX::LightObj* light, float* nx, float* ny, float* nz) noexcept; -static inline void GXGetLightDirv(const GX::LightObj* light, float* vec[3]) noexcept { - GXGetLightDir(light, vec[0], vec[1], vec[2]); +inline bool operator==(const GXColor& lhs, const GXColor& rhs) noexcept { + return lhs.r == rhs.r && lhs.g == rhs.g && lhs.b == rhs.b && lhs.a == rhs.a; } -void GXGetLightColor(const GX::LightObj* light, GX::Color* col) noexcept; +static inline void GXPosition3f32(const zeus::CVector3f& v) { GXPosition3f32(v.x(), v.y(), v.z()); } +static inline void GXNormal3f32(const zeus::CVector3f& v) { GXNormal3f32(v.x(), v.y(), v.z()); } +static inline void GXTexCoord2f32(const zeus::CVector2f& v) { GXTexCoord2f32(v.x(), v.y()); } +static inline void GXColor4f32(const zeus::CColor& v) { GXColor4f32(v.r(), v.g(), v.b(), v.a()); } + +static inline GXColor to_gx_color(const zeus::CColor& color) { + return { + static_cast(color.r() * 255.f), + static_cast(color.g() * 255.f), + static_cast(color.b() * 255.f), + static_cast(color.a() * 255.f), + }; +} +static inline zeus::CColor from_gx_color(GXColor color) { + return { + static_cast(color.r) / 255.f, + static_cast(color.g) / 255.f, + static_cast(color.b) / 255.f, + static_cast(color.a) / 255.f, + }; +} diff --git a/Runtime/Graphics/IRenderer.hpp b/Runtime/Graphics/IRenderer.hpp index 897ab85df..b1f238dfb 100644 --- a/Runtime/Graphics/IRenderer.hpp +++ b/Runtime/Graphics/IRenderer.hpp @@ -33,11 +33,11 @@ public: enum class EDrawableSorting { SortedCallback, UnsortedCallback }; enum class EDebugOption { Invalid = -1, PVSMode, PVSState, FogDisabled }; enum class EPrimitiveType { - Triangles = GX::TRIANGLES, - TriangleFan = GX::TRIANGLEFAN, - TriangleStrip = GX::TRIANGLESTRIP, - Lines = GX::LINES, - LineStrip = GX::LINESTRIP, + Triangles = GX_TRIANGLES, + TriangleFan = GX_TRIANGLEFAN, + TriangleStrip = GX_TRIANGLESTRIP, + Lines = GX_LINES, + LineStrip = GX_LINESTRIP, }; virtual ~IRenderer() = default; diff --git a/Runtime/Graphics/Shaders/CColoredStripShader.cpp b/Runtime/Graphics/Shaders/CColoredStripShader.cpp index 71dc722b8..10c12f780 100644 --- a/Runtime/Graphics/Shaders/CColoredStripShader.cpp +++ b/Runtime/Graphics/Shaders/CColoredStripShader.cpp @@ -61,7 +61,7 @@ void CColoredStripShader::Shutdown() { // stages.data(), nullptr, nullptr, texs.size(), texs.data(), nullptr, nullptr); //} -CColoredStripShader::CColoredStripShader(size_t maxVerts, Mode mode, aurora::gfx::TextureHandle tex) { +CColoredStripShader::CColoredStripShader(size_t maxVerts, Mode mode, CTexture& tex) { // CGraphics::CommitResources([this, maxVerts, mode, tex](boo::IGraphicsDataFactory::Context& ctx) { // BuildResources(ctx, maxVerts, mode, tex); // return true; diff --git a/Runtime/Graphics/Shaders/CColoredStripShader.hpp b/Runtime/Graphics/Shaders/CColoredStripShader.hpp index 02f1ef514..ee0f356d5 100644 --- a/Runtime/Graphics/Shaders/CColoredStripShader.hpp +++ b/Runtime/Graphics/Shaders/CColoredStripShader.hpp @@ -32,7 +32,7 @@ public: }; static void Initialize(); static void Shutdown(); - CColoredStripShader(size_t maxVerts, Mode mode, aurora::gfx::TextureHandle tex); + CColoredStripShader(size_t maxVerts, Mode mode, CTexture& tex); void draw(const zeus::CColor& color, size_t numVerts, const Vert* verts); }; diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp b/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp index 02add179d..3dd8b1477 100644 --- a/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp +++ b/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp @@ -198,7 +198,7 @@ CFluidPlaneShader::CFluidPlaneShader(EFluidType type, const TLockedToken& patternTex2, const TLockedToken& colorTex, const TLockedToken& bumpMap, const TLockedToken& envMap, const TLockedToken& envBumpMap, const TLockedToken& lightmap, - const aurora::gfx::TextureHandle& rippleMap, bool doubleLightmapBlend, + CTexture& rippleMap, bool doubleLightmapBlend, bool additive, u32 maxVertCount) : m_patternTex1(patternTex1) , m_patternTex2(patternTex2) @@ -207,10 +207,11 @@ CFluidPlaneShader::CFluidPlaneShader(EFluidType type, const TLockedToken m_envMap; TLockedToken m_envBumpMap; TLockedToken m_lightmap; - aurora::gfx::TextureHandle m_rippleMap; +// aurora::gfx::TextureHandle m_rippleMap; // boo::ObjToken m_vbo; // boo::ObjToken m_pvbo; // boo::ObjToken m_uniBuf; @@ -145,7 +145,7 @@ public: const TLockedToken& patternTex2, const TLockedToken& colorTex, const TLockedToken& bumpMap, const TLockedToken& envMap, const TLockedToken& envBumpMap, const TLockedToken& lightmap, - const aurora::gfx::TextureHandle& rippleMap, bool doubleLightmapBlend, bool additive, + CTexture& rippleMap, bool doubleLightmapBlend, bool additive, u32 maxVertCount); CFluidPlaneShader(const TLockedToken& patternTex1, const TLockedToken& patternTex2, const TLockedToken& colorTex, u32 maxVertCount); diff --git a/Runtime/Graphics/Shaders/CLineRendererShaders.cpp b/Runtime/Graphics/Shaders/CLineRendererShaders.cpp index 4abf5c8ea..01f699abb 100644 --- a/Runtime/Graphics/Shaders/CLineRendererShaders.cpp +++ b/Runtime/Graphics/Shaders/CLineRendererShaders.cpp @@ -54,7 +54,7 @@ void CLineRendererShaders::Shutdown() { } void CLineRendererShaders::BuildShaderDataBinding(CLineRenderer& renderer, - const aurora::gfx::TextureHandle& texture, bool additive, + CTexture& texture, bool additive, bool zTest, bool zGEqual) { // std::array, 2>* pipeline = nullptr; // diff --git a/Runtime/Graphics/Shaders/CLineRendererShaders.hpp b/Runtime/Graphics/Shaders/CLineRendererShaders.hpp index 2d1a2f994..758e15e97 100644 --- a/Runtime/Graphics/Shaders/CLineRendererShaders.hpp +++ b/Runtime/Graphics/Shaders/CLineRendererShaders.hpp @@ -26,7 +26,7 @@ public: static void Initialize(); static void Shutdown(); static void BuildShaderDataBinding(CLineRenderer& renderer, - const aurora::gfx::TextureHandle& texture, bool additive, bool zTest, + CTexture& texture, bool additive, bool zTest, bool zGEqual); }; diff --git a/Runtime/Graphics/Shaders/CMapSurfaceShader.cpp b/Runtime/Graphics/Shaders/CMapSurfaceShader.cpp index 175fd0d19..3d43a79ca 100644 --- a/Runtime/Graphics/Shaders/CMapSurfaceShader.cpp +++ b/Runtime/Graphics/Shaders/CMapSurfaceShader.cpp @@ -18,8 +18,8 @@ void CMapSurfaceShader::Shutdown() { // s_Pipeline.reset(); } -CMapSurfaceShader::CMapSurfaceShader(aurora::ArrayRef vbo, - aurora::ArrayRef ibo) +CMapSurfaceShader::CMapSurfaceShader(std::vector vbo, + std::vector ibo) //: m_vbo(vbo), m_ibo(ibo) { // m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); diff --git a/Runtime/Graphics/Shaders/CMapSurfaceShader.hpp b/Runtime/Graphics/Shaders/CMapSurfaceShader.hpp index 46d8fab3b..bb77cabaf 100644 --- a/Runtime/Graphics/Shaders/CMapSurfaceShader.hpp +++ b/Runtime/Graphics/Shaders/CMapSurfaceShader.hpp @@ -22,8 +22,8 @@ class CMapSurfaceShader { public: static void Initialize(); static void Shutdown(); - CMapSurfaceShader(aurora::ArrayRef vbo, - aurora::ArrayRef ibo); + CMapSurfaceShader(std::vector vbo, + std::vector ibo); void draw(const zeus::CColor& color, u32 start, u32 count); }; diff --git a/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp b/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp index eb68db077..0a8dcee46 100644 --- a/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp +++ b/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp @@ -35,39 +35,38 @@ void CSpaceWarpFilter::GenerateWarpRampTex() { data[y][x][0] = data[y][x][1] = data[y][x][2]; } } - m_warpTex = aurora::gfx::new_static_texture_2d( - WARP_RAMP_RES + 1, WARP_RAMP_RES + 1, 1, GX::TF_RGBA8, - {reinterpret_cast(data.data()), (WARP_RAMP_RES + 1) * (WARP_RAMP_RES + 1) * 4}, "Warp Ramp"); + m_warpTex.emplace(ETexelFormat::RGBA8PC, WARP_RAMP_RES + 1, WARP_RAMP_RES + 1, 1, "Warp Ramp"); } CSpaceWarpFilter::CSpaceWarpFilter() { -// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { -// GenerateWarpRampTex(ctx); -// -// struct Vert { -// zeus::CVector2f m_pos; -// zeus::CVector2f m_uv; -// }; -// const std::array verts{{ -// {{-1.f, -1.f}, {0.f, 0.f}}, -// {{-1.f, 1.f}, {0.f, 1.f}}, -// {{1.f, -1.f}, {1.f, 0.f}}, -// {{1.f, 1.f}, {1.f, 1.f}}, -// }}; -// -// m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts.data(), 32, verts.size()); -// m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); -// -// const std::array, 1> bufs{m_uniBuf.get()}; -// constexpr std::array stages{boo::PipelineStage::Vertex}; -// const std::array, 2> texs{ -// CGraphics::g_SpareTexture.get(), -// m_warpTex.get(), -// }; -// m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, bufs.size(), bufs.data(), -// stages.data(), nullptr, nullptr, texs.size(), texs.data(), nullptr, nullptr); -// return true; -// } BooTrace); + // CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + // GenerateWarpRampTex(ctx); + // + // struct Vert { + // zeus::CVector2f m_pos; + // zeus::CVector2f m_uv; + // }; + // const std::array verts{{ + // {{-1.f, -1.f}, {0.f, 0.f}}, + // {{-1.f, 1.f}, {0.f, 1.f}}, + // {{1.f, -1.f}, {1.f, 0.f}}, + // {{1.f, 1.f}, {1.f, 1.f}}, + // }}; + // + // m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts.data(), 32, verts.size()); + // m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + // + // const std::array, 1> bufs{m_uniBuf.get()}; + // constexpr std::array stages{boo::PipelineStage::Vertex}; + // const std::array, 2> texs{ + // CGraphics::g_SpareTexture.get(), + // m_warpTex.get(), + // }; + // m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, bufs.size(), bufs.data(), + // stages.data(), nullptr, nullptr, texs.size(), texs.data(), nullptr, + // nullptr); + // return true; + // } BooTrace); } void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) { @@ -132,15 +131,15 @@ void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) { m_uniform.m_matrix[1][1] = clipRect.x10_height / vp.y(); m_uniform.m_matrix[3][0] = pt.x() + (1.f / vp.x()); m_uniform.m_matrix[3][1] = pt.y() + (1.f / vp.y()); -// if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) { -// m_uniform.m_matrix[3][2] = pt.z() * 2.f - 1.f; -// } else if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::Vulkan) { -// m_uniform.m_matrix[1][1] *= -1.f; -// m_uniform.m_matrix[3][1] *= -1.f; -// m_uniform.m_matrix[3][2] = pt.z(); -// } else { -// m_uniform.m_matrix[3][2] = pt.z(); -// } + // if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) { + // m_uniform.m_matrix[3][2] = pt.z() * 2.f - 1.f; + // } else if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::Vulkan) { + // m_uniform.m_matrix[1][1] *= -1.f; + // m_uniform.m_matrix[3][1] *= -1.f; + // m_uniform.m_matrix[3][2] = pt.z(); + // } else { + // m_uniform.m_matrix[3][2] = pt.z(); + // } if (clipRect.x4_left) { clipRect.x4_left -= 1; @@ -158,15 +157,15 @@ void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) { clipRect.x4_left += CGraphics::g_CroppedViewport.x4_left; clipRect.x8_top += CGraphics::g_CroppedViewport.x8_top; clipRect.x8_top = CGraphics::GetViewportHeight() - clipRect.x10_height - clipRect.x8_top; -// CGraphics::ResolveSpareTexture(clipRect); + // CGraphics::ResolveSpareTexture(clipRect); m_uniform.m_strength.x() = m_uniform.m_matrix[0][0] * m_strength * 0.5f * (clipRect.x10_height / float(clipRect.xc_width)); m_uniform.m_strength.y() = m_uniform.m_matrix[1][1] * m_strength * 0.5f; -// m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + // m_uniBuf->load(&m_uniform, sizeof(m_uniform)); -// CGraphics::SetShaderDataBinding(m_dataBind); -// CGraphics::DrawArray(0, 4); + // CGraphics::SetShaderDataBinding(m_dataBind); + // CGraphics::DrawArray(0, 4); } } // namespace metaforce diff --git a/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp b/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp index 42eda912c..a7c18a2b6 100644 --- a/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp +++ b/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp @@ -4,6 +4,7 @@ #include "Runtime/GCNTypes.hpp" #include "Runtime/Graphics/CGraphics.hpp" +#include "Runtime/Graphics/CTexture.hpp" #include #include @@ -17,7 +18,7 @@ class CSpaceWarpFilter { zeus::CVector3f m_strength; }; std::array, 8>, 4> m_shiftTexture{}; - aurora::gfx::TextureHandle m_warpTex; + std::optional m_warpTex; // boo::ObjToken m_vbo; // boo::ObjToken m_uniBuf; // boo::ObjToken m_dataBind; diff --git a/Runtime/Graphics/Shaders/CXRayBlurFilter.hpp b/Runtime/Graphics/Shaders/CXRayBlurFilter.hpp index 9fe6b3de2..86928529d 100644 --- a/Runtime/Graphics/Shaders/CXRayBlurFilter.hpp +++ b/Runtime/Graphics/Shaders/CXRayBlurFilter.hpp @@ -15,7 +15,7 @@ class CXRayBlurFilter { std::array m_uv; }; TLockedToken m_paletteTex; - aurora::gfx::TextureHandle m_booTex; +// aurora::gfx::TextureHandle m_booTex; // boo::ObjToken m_vbo; // boo::ObjToken m_uniBuf; // boo::ObjToken m_dataBind; diff --git a/Runtime/GuiSys/CAuiEnergyBarT01.cpp b/Runtime/GuiSys/CAuiEnergyBarT01.cpp index 661e4dc53..4d3a16fdc 100644 --- a/Runtime/GuiSys/CAuiEnergyBarT01.cpp +++ b/Runtime/GuiSys/CAuiEnergyBarT01.cpp @@ -112,8 +112,8 @@ void CAuiEnergyBarT01::Draw(const CGuiWidgetDrawParms& drawParms) { if (barOffT != barMaxT) { CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc); CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); - xbc_tex->Load(GX::TEXMAP0, EClampMode::Repeat); - CGraphics::StreamBegin(GX::TRIANGLESTRIP); + xbc_tex->Load(GX_TEXMAP0, EClampMode::Repeat); + CGraphics::StreamBegin(GX_TRIANGLESTRIP); CGraphics::StreamColor(useCol); auto coords = xd8_coordFunc(barOffT); while (barOffT < barMaxT) { diff --git a/Runtime/GuiSys/CAuiImagePane.cpp b/Runtime/GuiSys/CAuiImagePane.cpp index d8c00049a..0dc8a11c8 100644 --- a/Runtime/GuiSys/CAuiImagePane.cpp +++ b/Runtime/GuiSys/CAuiImagePane.cpp @@ -80,8 +80,8 @@ void CAuiImagePane::DoDrawImagePane(const zeus::CColor& color, CTexture& tex, in if ((x14c_deResFactor == 0.f && alpha == 1.f) || tex.GetNumberOfMipMaps() == 1) { CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc); CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); - tex.LoadMipLevel(0.f, GX::TEXMAP0, EClampMode::Repeat); - CGraphics::StreamBegin(GX::TRIANGLESTRIP); + tex.LoadMipLevel(0.f, GX_TEXMAP0, EClampMode::Repeat); + CGraphics::StreamBegin(GX_TRIANGLESTRIP); CGraphics::StreamColor(useColor); for (u32 i = 0; i < useUVs->size(); ++i) { CGraphics::StreamTexcoord((*useUVs)[i] + xd0_uvBias0); @@ -101,41 +101,41 @@ void CAuiImagePane::DoDrawImagePane(const zeus::CColor& color, CTexture& tex, in float rgba1 = (fadeFactor - static_cast(mip1)); float rgba2 = 1.f - rgba1; - tex.LoadMipLevel(mip1, GX::TexMapID::TEXMAP0, EClampMode::Repeat); - tex.LoadMipLevel(mip2, GX::TexMapID::TEXMAP1, EClampMode::Repeat); - std::array list{{ - {GX::VA_POS, GX::DIRECT}, - {GX::VA_TEX0, GX::DIRECT}, - GX::VtxDescList{}, + tex.LoadMipLevel(mip1, GX_TEXMAP0, EClampMode::Repeat); + tex.LoadMipLevel(mip2, GX_TEXMAP1, EClampMode::Repeat); + std::array list{{ + {GX_VA_POS, GX_DIRECT}, + {GX_VA_TEX0, GX_DIRECT}, + {GX_VA_NULL, GX_NONE}, }}; CGX::SetVtxDescv(list.data()); CGX::SetNumChans(0); CGX::SetNumTexGens(2); CGX::SetNumTevStages(2); - GX::TevStageID stage = GX::TEVSTAGE0; - while (stage < GX::TEVSTAGE2) { - GX::TevColorArg colorD = stage == GX::TEVSTAGE0 ? GX::CC_ZERO : GX::CC_CPREV; - CGX::SetTevColorIn(stage, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, colorD); - GX::TevAlphaArg alphaD = stage == GX::TEVSTAGE0 ? GX::CA_ZERO : GX::CA_APREV; - CGX::SetTevAlphaIn(stage, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, alphaD); - CGX::SetTevColorOp(stage, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); - CGX::SetTevAlphaOp(stage, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); - stage = static_cast(stage + GX::TEVSTAGE1); + GXTevStageID stage = GX_TEVSTAGE0; + while (stage < GX_TEVSTAGE2) { + GXTevColorArg colorD = stage == GX_TEVSTAGE0 ? GX_CC_ZERO : GX_CC_CPREV; + CGX::SetTevColorIn(stage, GX_CC_ZERO, GX_CC_TEXC, GX_CC_KONST, colorD); + GXTevAlphaArg alphaD = stage == GX_TEVSTAGE0 ? GX_CA_ZERO : GX_CA_APREV; + CGX::SetTevAlphaIn(stage, GX_CA_ZERO, GX_CA_TEXA, GX_CA_KONST, alphaD); + CGX::SetTevColorOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + CGX::SetTevAlphaOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + stage = static_cast(stage + GX_TEVSTAGE1); } - CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A); - CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0); - CGX::SetTevKAlphaSel(GX::TEVSTAGE1, GX::TEV_KASEL_K1_A); - CGX::SetTevKColorSel(GX::TEVSTAGE1, GX::TEV_KCSEL_K1); + CGX::SetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K0_A); + CGX::SetTevKColorSel(GX_TEVSTAGE0, GX_TEV_KCSEL_K0); + CGX::SetTevKAlphaSel(GX_TEVSTAGE1, GX_TEV_KASEL_K1_A); + CGX::SetTevKColorSel(GX_TEVSTAGE1, GX_TEV_KCSEL_K1); zeus::CColor col1 = useColor * zeus::CColor(rgba2, rgba2, rgba2, rgba2); zeus::CColor col2 = useColor * zeus::CColor(rgba1, rgba1, rgba1, rgba1); - CGX::SetTevKColor(GX::KCOLOR0, col1); - CGX::SetTevKColor(GX::KCOLOR1, col2); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); - CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD1, GX::TEXMAP1, GX::COLOR_NULL); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); - CGX::SetTexCoordGen(GX::TEXCOORD1, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); - CGX::Begin(GX::Primitive::TRIANGLESTRIP, GX::VTXFMT0, 4); + CGX::SetTevKColor(GX_KCOLOR0, col1); + CGX::SetTevKColor(GX_KCOLOR1, col2); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR_NULL); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::SetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 4); for (u32 idx = 0; const auto& coord : xe0_coords) { GXPosition3f32(coord); GXTexCoord2f32((*useUVs)[idx] + xd0_uvBias0); @@ -146,8 +146,8 @@ void CAuiImagePane::DoDrawImagePane(const zeus::CColor& color, CTexture& tex, in } else { CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5fec); CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); - tex.Load(GX::TEXMAP0, EClampMode::Repeat); - CGraphics::StreamBegin(GX::TRIANGLESTRIP); + tex.Load(GX_TEXMAP0, EClampMode::Repeat); + CGraphics::StreamBegin(GX_TRIANGLESTRIP); CGraphics::StreamColor(useColor); for (u32 i = 0; i < useUVs->size(); ++i) { CGraphics::StreamTexcoord((*useUVs)[i]); diff --git a/Runtime/GuiSys/CCompoundTargetReticle.cpp b/Runtime/GuiSys/CCompoundTargetReticle.cpp index 099e70603..f19fbb48b 100644 --- a/Runtime/GuiSys/CCompoundTargetReticle.cpp +++ b/Runtime/GuiSys/CCompoundTargetReticle.cpp @@ -71,12 +71,12 @@ CCompoundTargetReticle::CCompoundTargetReticle(const CStateManager& mgr) CCompoundTargetReticle::SScanReticuleRenderer::SScanReticuleRenderer() { // CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { - for (size_t i = 0; i < m_lineRenderers.size(); ++i) { - m_lineRenderers[i].emplace(CLineRenderer::EPrimitiveMode::Lines, 8, aurora::gfx::TextureHandle{}, true, true); - for (auto& stripRenderer : m_stripRenderers[i]) { - stripRenderer.emplace(CLineRenderer::EPrimitiveMode::LineStrip, 4, aurora::gfx::TextureHandle{}, true, true); - } - } +// for (size_t i = 0; i < m_lineRenderers.size(); ++i) { +// m_lineRenderers[i].emplace(CLineRenderer::EPrimitiveMode::Lines, 8, {}, true, true); +// for (auto& stripRenderer : m_stripRenderers[i]) { +// stripRenderer.emplace(CLineRenderer::EPrimitiveMode::LineStrip, 4, {}, true, true); +// } +// } // return true; // } BooTrace); } diff --git a/Runtime/GuiSys/CGuiPane.cpp b/Runtime/GuiSys/CGuiPane.cpp index ef8896c21..06e1aa4ae 100644 --- a/Runtime/GuiSys/CGuiPane.cpp +++ b/Runtime/GuiSys/CGuiPane.cpp @@ -17,7 +17,7 @@ void CGuiPane::Draw(const CGuiWidgetDrawParms& parms) { col.a() = parms.x0_alphaMod * xa8_color2.a(); CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassThru); - CGraphics::DrawPrimitive(GX::Primitive::TRIANGLESTRIP, xc0_verts.data(), skDefaultNormal, col, xc0_verts.size()); + CGraphics::DrawPrimitive(GX_TRIANGLESTRIP, xc0_verts.data(), skDefaultNormal, col, xc0_verts.size()); } CGuiWidget::Draw(parms); } diff --git a/Runtime/GuiSys/CGuiTableGroup.cpp b/Runtime/GuiSys/CGuiTableGroup.cpp index d35d0626b..4bb4593bb 100644 --- a/Runtime/GuiSys/CGuiTableGroup.cpp +++ b/Runtime/GuiSys/CGuiTableGroup.cpp @@ -32,9 +32,9 @@ CGuiTableGroup::CGuiTableGroup(const CGuiWidgetParms& parms, int elementCount, i , xd0_selectWraparound(selectWraparound) {} void CGuiTableGroup::ProcessUserInput(const CFinalInput& input) { - if (input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter)) { + if (input.PA() || input.PSpecialKey(ESpecialKey::Enter)) { DoAdvance(); - } else if (input.PB() || input.PSpecialKey(aurora::SpecialKey::Esc)) { + } else if (input.PB() || input.PSpecialKey(ESpecialKey::Esc)) { DoCancel(); } else { bool decrement; diff --git a/Runtime/GuiSys/CHudRadarInterface.cpp b/Runtime/GuiSys/CHudRadarInterface.cpp index 99fb46c88..027610aa1 100644 --- a/Runtime/GuiSys/CHudRadarInterface.cpp +++ b/Runtime/GuiSys/CHudRadarInterface.cpp @@ -29,7 +29,7 @@ CHudRadarInterface::CHudRadarInterface(CGuiFrame& baseHud, CStateManager& stateM void CHudRadarInterface::DoDrawRadarPaint(float radius) { radius *= 4.f; - CGraphics::StreamBegin(GX::TRIANGLESTRIP); + CGraphics::StreamBegin(GX_TRIANGLESTRIP); CGraphics::StreamTexcoord(0.f, 1.f); CGraphics::StreamVertex(-radius, 0.f, radius); CGraphics::StreamTexcoord(0.f, 0.f); @@ -124,7 +124,7 @@ void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) { g_Renderer->SetModelMatrix(drawParms.x3c_postTranslate); g_Renderer->SetBlendMode_AdditiveAlpha(); - x0_txtrRadarPaint->Load(GX::TEXMAP0, EClampMode::Repeat); + x0_txtrRadarPaint->Load(GX_TEXMAP0, EClampMode::Repeat); CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc); g_Renderer->SetDepthReadWrite(false, false); zeus::CColor playerColor = g_tweakGuiColors->GetRadarPlayerPaintColor(); diff --git a/Runtime/GuiSys/CRasterFont.cpp b/Runtime/GuiSys/CRasterFont.cpp index a9902fa38..ca46e667c 100644 --- a/Runtime/GuiSys/CRasterFont.cpp +++ b/Runtime/GuiSys/CRasterFont.cpp @@ -210,26 +210,26 @@ bool CRasterFont::IsFinishedLoading() const { } void CRasterFont::SetupRenderState() { - static const GX::VtxDescList skDescList[3] = { - {GX::VA_POS, GX::DIRECT}, - {GX::VA_TEX0, GX::DIRECT}, - {GX::VA_NULL, GX::NONE} + constexpr std::array skDescList = { + GXVtxDescList{GX_VA_POS, GX_DIRECT}, + GXVtxDescList{GX_VA_TEX0, GX_DIRECT}, + GXVtxDescList{GX_VA_NULL, GX_NONE}, }; - x80_texture->Load(GX::TEXMAP0, EClampMode::Clamp); - CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A); - CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, GX::CC_ZERO); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, GX::CA_ZERO); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); - CGX::SetTevDirect(GX::TEVSTAGE0); - CGX::SetVtxDescv(skDescList); + x80_texture->Load(GX_TEXMAP0, EClampMode::Clamp); + CGX::SetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K0_A); + CGX::SetTevKColorSel(GX_TEVSTAGE0, GX_TEV_KCSEL_K0); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_KONST, GX_CC_ZERO); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_KONST, GX_CA_ZERO); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); + CGX::SetTevDirect(GX_TEVSTAGE0); + CGX::SetVtxDescv(skDescList.data()); CGX::SetNumChans(0); CGX::SetNumTexGens(1); CGX::SetNumTevStages(1); CGX::SetNumIndStages(0); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); } std::unique_ptr FRasterFontFactory([[maybe_unused]] const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, [[maybe_unused]] CObjectReference* selfRef) { diff --git a/Runtime/GuiSys/CScanDisplay.cpp b/Runtime/GuiSys/CScanDisplay.cpp index 24d0a28e5..82cc167f5 100644 --- a/Runtime/GuiSys/CScanDisplay.cpp +++ b/Runtime/GuiSys/CScanDisplay.cpp @@ -42,7 +42,7 @@ void CScanDisplay::CDataDot::Draw(const zeus::CColor& col, float radius) { const zeus::CTransform xf = zeus::CTransform::Translate(xc_curPos.x(), 0.f, xc_curPos.y()); g_Renderer->SetModelMatrix(xf); - CGraphics::StreamBegin(GX::TRIANGLESTRIP); + CGraphics::StreamBegin(GX_TRIANGLESTRIP); zeus::CColor useColor = col; useColor.a() *= x24_alpha; CGraphics::StreamColor(useColor); @@ -84,7 +84,7 @@ void CScanDisplay::ProcessInput(const CFinalInput& input) { return; if (xc_state == EScanState::DownloadComplete && x1a4_xAlpha == 0.f) { - if (input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) { + if (input.PA() || input.PSpecialKey(ESpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) { if (xa8_message->TextSupport().GetCurTime() < xa8_message->TextSupport().GetTotalAnimationTime()) { xa8_message->TextSupport().SetCurTime(xa8_message->TextSupport().GetTotalAnimationTime()); } else { @@ -96,7 +96,7 @@ void CScanDisplay::ProcessInput(const CFinalInput& input) { } else if (xc_state == EScanState::ViewingScan) { int oldCounter = x1ac_pageCounter; int totalPages = xac_scrollMessage->TextSupport().GetTotalPageCount(); - if ((input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) && + if ((input.PA() || input.PSpecialKey(ESpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) && totalPages != -1) { CGuiTextSupport& supp = !x1ac_pageCounter ? xa8_message->TextSupport() : xac_scrollMessage->TextSupport(); if (supp.GetCurTime() < supp.GetTotalAnimationTime()) @@ -452,7 +452,7 @@ void CScanDisplay::Draw() { g_Renderer->SetViewportOrtho(true, -4096.f, 4096.f); g_Renderer->SetBlendMode_AdditiveAlpha(); CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc); - x0_dataDot->Load(GX::TEXMAP0, EClampMode::Repeat); + x0_dataDot->Load(GX_TEXMAP0, EClampMode::Repeat); const float vpRatio = CGraphics::GetViewportHeight() / 480.f; for (CDataDot& dot : xbc_dataDots) { diff --git a/Runtime/GuiSys/CSplashScreen.cpp b/Runtime/GuiSys/CSplashScreen.cpp index b39d36cfe..23f9761f5 100644 --- a/Runtime/GuiSys/CSplashScreen.cpp +++ b/Runtime/GuiSys/CSplashScreen.cpp @@ -72,13 +72,13 @@ void CSplashScreen::Draw() { auto& tex = *x28_texture.GetObj(); const auto width = tex.GetWidth(); const auto height = tex.GetHeight(); - tex.Load(GX::TEXMAP0, EClampMode::Clamp); + tex.Load(GX_TEXMAP0, EClampMode::Clamp); if (x14_which == ESplashScreen::Nintendo || x14_which == ESplashScreen::Retro) { const auto x = static_cast(133 - (width - 376) / 2); const auto y = static_cast(170 - (height - 104) / 2); CGraphics::SetOrtho(-10.f, 650.f, -5.5f, 484.5f, -1.f, 1.f); CGraphics::SetCullMode(ERglCullMode::None); - CGraphics::StreamBegin(GX::TRIANGLESTRIP); + CGraphics::StreamBegin(GX_TRIANGLESTRIP); CGraphics::StreamColor(color); CGraphics::StreamTexcoord(0.f, 0.f); CGraphics::StreamVertex({x, 0.f, y + static_cast(height)}); diff --git a/Runtime/GuiSys/CTextRenderBuffer.cpp b/Runtime/GuiSys/CTextRenderBuffer.cpp index 47a83970d..8b300d31d 100644 --- a/Runtime/GuiSys/CTextRenderBuffer.cpp +++ b/Runtime/GuiSys/CTextRenderBuffer.cpp @@ -130,8 +130,8 @@ void CTextRenderBuffer::Render(const zeus::CColor& color, float time) { auto font = x4_fonts[x4c_activeFont]; if (font && font->GetGlyph(chr) != nullptr) { const auto* glyph = font->GetGlyph(chr); - CGX::SetTevKColor(GX::KCOLOR0, chrColor * color); - CGX::Begin(GX::TRIANGLESTRIP, GX::VTXFMT0, 4); + CGX::SetTevKColor(GX_KCOLOR0, chrColor * color); + CGX::Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 4); { GXPosition3f32(offX, 0.f, offY); GXTexCoord2f32(glyph->GetStartU(), glyph->GetStartV()); @@ -153,30 +153,30 @@ void CTextRenderBuffer::Render(const zeus::CColor& color, float time) { auto imageDef = x14_images[imageIdx]; auto tex = imageDef.x4_texs[static_cast(time * imageDef.x0_fps) % imageDef.x4_texs.size()]; if (tex) { - tex->Load(GX::TEXMAP0, EClampMode::Clamp); + tex->Load(GX_TEXMAP0, EClampMode::Clamp); float width = imageDef.x4_texs.front()->GetWidth() * imageDef.x14_cropFactor.x(); float height = imageDef.x4_texs.front()->GetHeight() * imageDef.x14_cropFactor.y(); float cropXHalf = imageDef.x14_cropFactor.x() * 0.5f; float cropYHalf = imageDef.x14_cropFactor.y() * 0.5f; - CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A); - CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, GX::CC_ZERO); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, GX::CA_ZERO); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); + CGX::SetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K0_A); + CGX::SetTevKColorSel(GX_TEVSTAGE0, GX_TEV_KCSEL_K0); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_KONST, GX_CC_ZERO); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_KONST, GX_CA_ZERO); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); constexpr std::array skVtxDesc{ - GX::VtxDescList{GX::VA_POS, GX::DIRECT}, - GX::VtxDescList{GX::VA_TEX0, GX::DIRECT}, - GX::VtxDescList{}, + GXVtxDescList{GX_VA_POS, GX_DIRECT}, + GXVtxDescList{GX_VA_TEX0, GX_DIRECT}, + GXVtxDescList{GX_VA_NULL, GX_NONE}, }; CGX::SetVtxDescv(skVtxDesc.data()); CGX::SetNumChans(0); CGX::SetNumTexGens(1); CGX::SetNumTevStages(1); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); - CGX::SetTevKColor(GX::KCOLOR0, imageColor * color); - CGX::Begin(GX::TRIANGLESTRIP, GX::VTXFMT0, 4); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::SetTevKColor(GX_KCOLOR0, imageColor * color); + CGX::Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 4); { GXPosition3f32(offX, 0.f, offY); GXTexCoord2f32(0.5f - cropXHalf, 0.5f + cropYHalf); diff --git a/Runtime/IMain.hpp b/Runtime/IMain.hpp index aaef24cab..f0ba12ea6 100644 --- a/Runtime/IMain.hpp +++ b/Runtime/IMain.hpp @@ -37,8 +37,8 @@ enum class EGameplayResult { None, Win, Lose, Playing }; class IMain { public: virtual ~IMain() = default; - virtual std::string Init(const FileStoreManager& storeMgr, CVarManager* cvarMgr, boo::IAudioVoiceEngine* voiceEngine, - amuse::IBackendVoiceAllocator& backend) = 0; + virtual std::string Init(int argc, char** argv, const FileStoreManager& storeMgr, CVarManager* cvarMgr, + boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend) = 0; virtual void Draw() = 0; virtual bool Proc(float dt) = 0; virtual void Shutdown() = 0; diff --git a/Runtime/ImGuiConsole.cpp b/Runtime/ImGuiConsole.cpp index b8d118862..140ec88a5 100644 --- a/Runtime/ImGuiConsole.cpp +++ b/Runtime/ImGuiConsole.cpp @@ -1,3 +1,10 @@ +#include +#define IM_VEC2_CLASS_EXTRA \ + ImVec2(const zeus::CVector2f& v) { \ + x = v.x(); \ + y = v.y(); \ + } \ + operator zeus::CVector2f() const { return zeus::CVector2f{x, y}; } #include "ImGuiConsole.hpp" #include "../version.h" @@ -26,6 +33,8 @@ namespace aurora::gfx { extern std::atomic_uint32_t queuedPipelines; extern std::atomic_uint32_t createdPipelines; +extern size_t g_drawCallCount; +extern size_t g_mergedDrawCallCount; extern size_t g_lastVertSize; extern size_t g_lastUniformSize; extern size_t g_lastIndexSize; @@ -139,6 +148,8 @@ static void Warp(const CAssetId worldId, TAreaId aId) { } } +static inline float GetScale() { return ImGui::GetIO().DisplayFramebufferScale.x; } + void ImGuiConsole::ShowMenuGame() { if (g_Main != nullptr) { m_paused = g_Main->IsPaused(); @@ -273,7 +284,7 @@ static void RenderEntityColumns(const ImGuiEntityEntry& entry) { } void ImGuiConsole::ShowInspectWindow(bool* isOpen) { - float initialWindowSize = 400.f * aurora::get_window_size().scale; + float initialWindowSize = 400.f * GetScale(); ImGui::SetNextWindowSize(ImVec2{initialWindowSize, initialWindowSize * 1.5f}, ImGuiCond_FirstUseEver); if (ImGui::Begin("Inspect", isOpen)) { @@ -393,7 +404,7 @@ bool ImGuiConsole::ShowEntityInfoWindow(TUniqueId uid) { void ImGuiConsole::ShowConsoleVariablesWindow() { // For some reason the window shows up tiny without this - float initialWindowSize = 350.f * aurora::get_window_size().scale; + float initialWindowSize = 350.f * GetScale(); ImGui::SetNextWindowSize(ImVec2{initialWindowSize, initialWindowSize}, ImGuiCond_FirstUseEver); if (ImGui::Begin("Console Variables", &m_showConsoleVariablesWindow)) { if (ImGui::Button("Clear")) { @@ -663,7 +674,7 @@ void ImGuiConsole::ShowAboutWindow(bool preLaunch) { open = &m_showAboutWindow; } if (ImGui::Begin("About", open, flags)) { - float iconSize = 128.f * aurora::get_window_size().scale; + float iconSize = 128.f * GetScale(); ImGui::SameLine(ImGui::GetWindowSize().x / 2 - iconSize + (iconSize / 2)); ImGui::Image(ImGuiEngine::metaforceIcon, ImVec2{iconSize, iconSize}); ImGui::PushFont(ImGuiEngine::fontLarge); @@ -794,7 +805,7 @@ static std::string BytesToString(size_t bytes) { void ImGuiConsole::ShowDebugOverlay() { if (!m_frameCounter && !m_frameRate && !m_inGameTime && !m_roomTimer && !m_playerInfo && !m_areaInfo && - !m_worldInfo && !m_randomStats && !m_resourceStats && !m_pipelineInfo) { + !m_worldInfo && !m_randomStats && !m_resourceStats && !m_pipelineInfo && !m_drawCallInfo && !m_bufferInfo) { return; } ImGuiIO& io = ImGui::GetIO(); @@ -957,17 +968,33 @@ void ImGuiConsole::ShowDebugOverlay() { } hasPrevious = true; - ImGuiStringViewText(fmt::format(FMT_STRING("Queued pipelines: {}\n"), aurora::gfx::queuedPipelines)); - ImGuiStringViewText(fmt::format(FMT_STRING("Done pipelines: {}\n"), aurora::gfx::createdPipelines)); + ImGuiStringViewText(fmt::format(FMT_STRING("Queued pipelines: {}\n"), aurora::gfx::queuedPipelines)); + ImGuiStringViewText(fmt::format(FMT_STRING("Done pipelines: {}\n"), aurora::gfx::createdPipelines)); + } + if (m_drawCallInfo && m_developer) { + if (hasPrevious) { + ImGui::Separator(); + } + hasPrevious = true; + + ImGuiStringViewText(fmt::format(FMT_STRING("Draw call count: {}\n"), aurora::gfx::g_drawCallCount)); + ImGuiStringViewText(fmt::format(FMT_STRING("Merged draw calls: {}\n"), aurora::gfx::g_mergedDrawCallCount)); + } + if (m_bufferInfo && m_developer) { + if (hasPrevious) { + ImGui::Separator(); + } + hasPrevious = true; + ImGuiStringViewText( - fmt::format(FMT_STRING("Vertex size: {}\n"), BytesToString(aurora::gfx::g_lastVertSize))); + fmt::format(FMT_STRING("Vertex size: {}\n"), BytesToString(aurora::gfx::g_lastVertSize))); ImGuiStringViewText( - fmt::format(FMT_STRING("Uniform size: {}\n"), BytesToString(aurora::gfx::g_lastUniformSize))); + fmt::format(FMT_STRING("Uniform size: {}\n"), BytesToString(aurora::gfx::g_lastUniformSize))); ImGuiStringViewText( - fmt::format(FMT_STRING("Index size: {}\n"), BytesToString(aurora::gfx::g_lastIndexSize))); + fmt::format(FMT_STRING("Index size: {}\n"), BytesToString(aurora::gfx::g_lastIndexSize))); ImGuiStringViewText( - fmt::format(FMT_STRING("Storage size: {}\n"), BytesToString(aurora::gfx::g_lastStorageSize))); - ImGuiStringViewText(fmt::format(FMT_STRING("Total: {}\n"), + fmt::format(FMT_STRING("Storage size: {}\n"), BytesToString(aurora::gfx::g_lastStorageSize))); + ImGuiStringViewText(fmt::format(FMT_STRING("Total: {}\n"), BytesToString(aurora::gfx::g_lastVertSize + aurora::gfx::g_lastUniformSize + aurora::gfx::g_lastIndexSize + aurora::gfx::g_lastStorageSize))); } @@ -993,10 +1020,13 @@ void ImGuiConsole::ShowInputViewer() { return; } - u32 thisWhich = aurora::get_which_controller_for_player(input.ControllerIdx()); + u32 thisWhich = input.ControllerIdx(); if (m_whichController != thisWhich) { - m_controllerName = static_cast(aurora::get_controller_name(thisWhich)); - m_whichController = thisWhich; + const char* name = PADGetName(thisWhich); + if (name != nullptr) { + m_controllerName = name; + m_whichController = thisWhich; + } } // Code -stolen- borrowed from Practice Mod @@ -1009,7 +1039,7 @@ void ImGuiConsole::ShowInputViewer() { } ImGui::SetNextWindowBgAlpha(0.65f); if (ImGui::Begin("Input Overlay", nullptr, windowFlags)) { - float scale = aurora::get_window_size().scale; + float scale = GetScale(); if (!m_controllerName.empty()) { TextCenter(m_controllerName); ImGui::Separator(); @@ -1614,7 +1644,7 @@ void ImGuiConsole::ShowItemsWindow() { void ImGuiConsole::ShowLayersWindow() { // For some reason the window shows up tiny without this - float initialWindowSize = 350.f * aurora::get_window_size().scale; + float initialWindowSize = 350.f * GetScale(); ImGui::SetNextWindowSize(ImVec2{initialWindowSize, initialWindowSize}, ImGuiCond_FirstUseEver); if (ImGui::Begin("Layers", &m_showLayersWindow)) { @@ -1856,26 +1886,28 @@ void ImGuiConsole::ShowPreLaunchSettingsWindow() { if (ImGui::Begin("Settings", &m_showPreLaunchSettingsWindow, ImGuiWindowFlags_AlwaysAutoResize)) { if (ImGui::BeginTabBar("Settings")) { if (ImGui::BeginTabItem("Graphics")) { - static auto AvailableBackends = aurora::get_available_backends(); - ImGuiStringViewText(fmt::format(FMT_STRING("Current backend: {}"), aurora::get_backend_string())); - auto desiredBackend = static_cast(aurora::Backend::Invalid); - if (auto* cvar = m_cvarMgr.findCVar("graphicsApi")) { - bool valid = false; - const auto name = cvar->toLiteral(&valid); - if (valid) { - desiredBackend = static_cast(aurora::backend_from_string(name)); - } - } - bool modified = false; - modified = ImGui::RadioButton("Auto", &desiredBackend, static_cast(aurora::Backend::Invalid)); - for (const auto& item : AvailableBackends) { - modified = ImGui::RadioButton(magic_enum::enum_name(item).data(), &desiredBackend, static_cast(item)) || - modified; - } - if (modified) { - m_cvarCommons.m_graphicsApi->fromLiteral( - aurora::backend_to_string(static_cast(desiredBackend))); - } + // TODO + // static auto AvailableBackends = aurora::get_available_backends(); + // ImGuiStringViewText(fmt::format(FMT_STRING("Current backend: {}"), aurora::get_backend_string())); + // auto desiredBackend = static_cast(aurora::Backend::Invalid); + // if (auto* cvar = m_cvarMgr.findCVar("graphicsApi")) { + // bool valid = false; + // const auto name = cvar->toLiteral(&valid); + // if (valid) { + // desiredBackend = static_cast(aurora::backend_from_string(name)); + // } + // } + // bool modified = false; + // modified = ImGui::RadioButton("Auto", &desiredBackend, static_cast(aurora::Backend::Invalid)); + // for (const auto& item : AvailableBackends) { + // modified = ImGui::RadioButton(magic_enum::enum_name(item).data(), &desiredBackend, + // static_cast(item)) || + // modified; + // } + // if (modified) { + // m_cvarCommons.m_graphicsApi->fromLiteral( + // aurora::backend_to_string(static_cast(desiredBackend))); + // } ImGuiCVarCheckbox(m_cvarMgr, "fullscreen", "Fullscreen"); ImGui::EndTabItem(); } diff --git a/Runtime/ImGuiConsole.hpp b/Runtime/ImGuiConsole.hpp index 3afaab3be..ad6ecd617 100644 --- a/Runtime/ImGuiConsole.hpp +++ b/Runtime/ImGuiConsole.hpp @@ -116,8 +116,12 @@ private: bool m_drawLighting = m_cvarCommons.m_debugToolDrawLighting->toBoolean(); #if TARGET_OS_IOS bool m_pipelineInfo = false; + bool m_drawCallInfo = false; + bool m_bufferInfo = false; #else bool m_pipelineInfo = true; // TODO cvar + bool m_drawCallInfo = true; // TODO cvar + bool m_bufferInfo = true; // TODO cvar #endif bool m_developer = m_cvarMgr.findCVar("developer")->toBoolean(); bool m_cheats = m_cvarMgr.findCVar("cheats")->toBoolean(); diff --git a/Runtime/ImGuiControllerConfig.cpp b/Runtime/ImGuiControllerConfig.cpp index c40e80606..39a564942 100644 --- a/Runtime/ImGuiControllerConfig.cpp +++ b/Runtime/ImGuiControllerConfig.cpp @@ -1,12 +1,10 @@ #include "Runtime/ImGuiControllerConfig.hpp" +#include "Runtime/RetroTypes.hpp" #include "Runtime/Streams/CFileOutStream.hpp" #include "Runtime/Streams/ContainerReaders.hpp" #include "Runtime/Streams/ContainerWriters.hpp" -#include "aurora/pad.hpp" -#include "aurora/aurora.hpp" - #include namespace metaforce { diff --git a/Runtime/ImGuiControllerConfig.hpp b/Runtime/ImGuiControllerConfig.hpp index 60994b399..8d04ab066 100644 --- a/Runtime/ImGuiControllerConfig.hpp +++ b/Runtime/ImGuiControllerConfig.hpp @@ -3,7 +3,7 @@ #include "Runtime/GCNTypes.hpp" #include "Runtime/Streams/CInputStream.hpp" #include "Runtime/Streams/COutputStream.hpp" -#include "aurora/pad.hpp" +#include #include #include @@ -52,4 +52,4 @@ private: ControllerAtlas* m_currentAtlas = nullptr; std::vector m_controllerAtlases; }; -} // namespace metaforce \ No newline at end of file +} // namespace metaforce diff --git a/Runtime/Input/CDolphinController.cpp b/Runtime/Input/CDolphinController.cpp index 471255a45..24bfc24cd 100644 --- a/Runtime/Input/CDolphinController.cpp +++ b/Runtime/Input/CDolphinController.cpp @@ -1,5 +1,7 @@ #include "Runtime/Input/CDolphinController.hpp" +#include + namespace metaforce { CDolphinController::CDolphinController() { static bool sIsInitialized = false; @@ -31,35 +33,35 @@ float CDolphinController::GetAnalogStickMaxValue(EJoyAxis axis) { void CDolphinController::ReadDevices() { std::array status{}; PADRead(status.data()); - if (status[0].xa_err == PAD::ERR_NONE) { + if (status[0].err == PAD_ERR_NONE) { PADClamp(status.data()); x4_status = status; } else { - x4_status[0].xa_err = status[0].xa_err; - x4_status[1].xa_err = status[1].xa_err; - x4_status[2].xa_err = status[2].xa_err; - x4_status[3].xa_err = status[3].xa_err; + x4_status[0].err = status[0].err; + x4_status[1].err = status[1].err; + x4_status[2].err = status[2].err; + x4_status[3].err = status[3].err; } for (u32 i = 0; i < 4; ++i) { - if (x4_status[i].xa_err != PAD::ERR_NOT_READY) { - if (x4_status[i].xa_err == PAD::ERR_NONE) { + if (x4_status[i].err != PAD_ERR_NOT_READY) { + if (x4_status[i].err == PAD_ERR_NONE) { x34_gamepadStates[i].SetDeviceIsPresent(true); - } else if (x4_status[i].xa_err == PAD::ERR_NO_CONTROLLER) { - x1c8_invalidControllers |= PAD::CHAN0_BIT >> i; + } else if (x4_status[i].err == PAD_ERR_NO_CONTROLLER) { + x1c8_invalidControllers |= PAD_CHAN0_BIT >> i; x34_gamepadStates[i].SetDeviceIsPresent(false); } } if (x1b4_controllerTypePollTime[i] == 0) { const auto type = SIProbe(i); - if ((type & (SI::ERROR_NO_RESPONSE | SI::ERROR_UNKNOWN | SI::ERROR_BUSY)) == 0) { + if ((type & (SI_ERROR_NO_RESPONSE | SI_ERROR_UNKNOWN | SI_ERROR_BUSY)) == 0) { x1b4_controllerTypePollTime[i] = 0x3c; - if (type == SI::GC_WIRELESS) { + if (type == SI_GC_WIRELESS) { x1a4_controllerTypes[i] = skTypeWavebird; - } else if (type == SI::GBA) { /* here for completeness, the GameCube adapter does not support GBA */ + } else if (type == SI_GBA) { /* here for completeness, the GameCube adapter does not support GBA */ x1a4_controllerTypes[i] = skTypeGBA; - } else if (type == SI::GC_STANDARD) { + } else if (type == SI_GC_STANDARD) { x1a4_controllerTypes[i] = skTypeStandard; } } else { @@ -94,13 +96,13 @@ void CDolphinController::ProcessAxis(u32 controller, EJoyAxis axis) { float axisValue = 0.f; if (axis == EJoyAxis::LeftX) { - axisValue = x4_status[controller].x2_stickX; + axisValue = x4_status[controller].stickX; } else if (axis == EJoyAxis::LeftY) { - axisValue = x4_status[controller].x3_stickY; + axisValue = x4_status[controller].stickY; } else if (axis == EJoyAxis::RightX) { - axisValue = x4_status[controller].x4_substickX; + axisValue = x4_status[controller].substickX; } else if (axis == EJoyAxis::RightY) { - axisValue = x4_status[controller].x5_substickY; + axisValue = x4_status[controller].substickY; } axisValue *= 1.f / maxAxisValue; float absolute = zeus::clamp(kAbsoluteMinimum, axisValue, kAbsoluteMaximum); @@ -110,8 +112,8 @@ void CDolphinController::ProcessAxis(u32 controller, EJoyAxis axis) { } static constexpr std::array mButtonMapping{ - PAD::BUTTON_A, PAD::BUTTON_B, PAD::BUTTON_X, PAD::BUTTON_Y, PAD::BUTTON_START, PAD::TRIGGER_Z, - PAD::BUTTON_UP, PAD::BUTTON_RIGHT, PAD::BUTTON_DOWN, PAD::BUTTON_LEFT, PAD::TRIGGER_L, PAD::TRIGGER_R, + PAD_BUTTON_A, PAD_BUTTON_B, PAD_BUTTON_X, PAD_BUTTON_Y, PAD_BUTTON_START, PAD_TRIGGER_Z, + PAD_BUTTON_UP, PAD_BUTTON_RIGHT, PAD_BUTTON_DOWN, PAD_BUTTON_LEFT, PAD_TRIGGER_L, PAD_TRIGGER_R, }; void CDolphinController::ProcessButtons(u32 controller) { @@ -119,17 +121,19 @@ void CDolphinController::ProcessButtons(u32 controller) { ProcessDigitalButton(controller, x34_gamepadStates[controller].GetButton(EButton(i)), mButtonMapping[i]); } - ProcessAnalogButton(x4_status[controller].x6_triggerL, + ProcessAnalogButton(x4_status[controller].triggerL, x34_gamepadStates[controller].GetAnalogButton(EAnalogButton::Left)); - ProcessAnalogButton(x4_status[controller].x7_triggerR, + ProcessAnalogButton(x4_status[controller].triggerR, x34_gamepadStates[controller].GetAnalogButton(EAnalogButton::Right)); } + void CDolphinController::ProcessDigitalButton(u32 controller, CControllerButton& button, u16 mapping) { - bool btnPressed = (x4_status[controller].x0_buttons & mapping) != 0; + bool btnPressed = (x4_status[controller].button & mapping) != 0; button.SetPressEvent(PADButtonDown(button.GetIsPressed(), btnPressed)); button.SetReleaseEvent(PADButtonUp(button.GetIsPressed(), btnPressed)); button.SetIsPressed(btnPressed); } + void CDolphinController::ProcessAnalogButton(float value, CControllerAxis& axis) { float absolute = value * (1 / 150.f); if (value * (1 / 150.f) > kAbsoluteMaximum) { @@ -168,4 +172,4 @@ bool CDolphinController::Initialize() { Poll(); return true; } -} // namespace metaforce \ No newline at end of file +} // namespace metaforce diff --git a/Runtime/Input/CDolphinController.hpp b/Runtime/Input/CDolphinController.hpp index 5a6882bb5..694e082d9 100644 --- a/Runtime/Input/CDolphinController.hpp +++ b/Runtime/Input/CDolphinController.hpp @@ -1,7 +1,7 @@ #pragma once #include "Runtime/Input/IController.hpp" - +#include "Runtime/RetroTypes.hpp" namespace metaforce { @@ -40,4 +40,4 @@ private: void ProcessDigitalButton(u32 controller, CControllerButton& button, u16 mapping); void ProcessAnalogButton(float value, CControllerAxis& axis); }; -} // namespace metaforce \ No newline at end of file +} // namespace metaforce diff --git a/Runtime/Input/CFinalInput.cpp b/Runtime/Input/CFinalInput.cpp index ebe134ccd..77a659c4b 100644 --- a/Runtime/Input/CFinalInput.cpp +++ b/Runtime/Input/CFinalInput.cpp @@ -56,10 +56,10 @@ CFinalInput::CFinalInput(int cIdx, float dt, const CKeyboardMouseControllerData& , x23_enableAnaRightYP(DRAUp() && !prevInput.DRAUp()) , x24_anaLeftTriggerP(DLTrigger() && !prevInput.DLTrigger()) , x28_anaRightTriggerP(DRTrigger() && !prevInput.DRTrigger()) -, x2c_b31_DPUp(data.m_specialKeys[size_t(aurora::SpecialKey::Up)]) -, x2d_b24_DPRight(data.m_specialKeys[size_t(aurora::SpecialKey::Right)]) -, x2d_b25_DPDown(data.m_specialKeys[size_t(aurora::SpecialKey::Down)]) -, x2d_b26_DPLeft(data.m_specialKeys[size_t(aurora::SpecialKey::Left)]) +, x2c_b31_DPUp(data.m_specialKeys[size_t(ESpecialKey::Up)]) +, x2d_b24_DPRight(data.m_specialKeys[size_t(ESpecialKey::Right)]) +, x2d_b25_DPDown(data.m_specialKeys[size_t(ESpecialKey::Down)]) +, x2d_b26_DPLeft(data.m_specialKeys[size_t(ESpecialKey::Left)]) , x2d_b28_PA(DA() && !prevInput.DA()) , x2d_b29_PB(DB() && !prevInput.DB()) , x2d_b30_PX(DX() && !prevInput.DX()) @@ -316,11 +316,11 @@ static void pad_clamptrigger(int16_t& trigger) { } void SAuroraControllerState::clamp() { - pad_clampstick(m_axes[size_t(aurora::ControllerAxis::LeftX)], m_axes[size_t(aurora::ControllerAxis::LeftY)], + pad_clampstick(m_axes[size_t(EControllerAxis::LeftX)], m_axes[size_t(EControllerAxis::LeftY)], pad_clampregion[3], pad_clampregion[4], pad_clampregion[2]); - pad_clampstick(m_axes[size_t(aurora::ControllerAxis::RightX)], m_axes[size_t(aurora::ControllerAxis::RightY)], + pad_clampstick(m_axes[size_t(EControllerAxis::RightX)], m_axes[size_t(EControllerAxis::RightY)], pad_clampregion[6], pad_clampregion[7], pad_clampregion[5]); - pad_clamptrigger(m_axes[size_t(aurora::ControllerAxis::TriggerLeft)]); - pad_clamptrigger(m_axes[size_t(aurora::ControllerAxis::TriggerRight)]); + pad_clamptrigger(m_axes[size_t(EControllerAxis::TriggerLeft)]); + pad_clamptrigger(m_axes[size_t(EControllerAxis::TriggerRight)]); } } // namespace metaforce diff --git a/Runtime/Input/CFinalInput.hpp b/Runtime/Input/CFinalInput.hpp index ea3a342e5..d0b59e4b7 100644 --- a/Runtime/Input/CFinalInput.hpp +++ b/Runtime/Input/CFinalInput.hpp @@ -12,8 +12,8 @@ struct SAuroraControllerState { u32 m_which = -1; bool m_isGamecube = false; bool m_hasRumble = false; - std::array m_axes{}; - std::bitset m_btns{}; + std::array m_axes{}; + std::bitset m_btns{}; SAuroraControllerState() = default; SAuroraControllerState(uint32_t which, bool isGamecube, bool hasRumble) @@ -68,7 +68,7 @@ struct CFinalInput { std::optional m_kbm; std::array m_PCharKeys{}; - std::array m_PSpecialKeys{}; + std::array m_PSpecialKeys{}; std::array m_PMouseButtons{}; @@ -162,13 +162,13 @@ struct CFinalInput { void InitializeAnalog(float leftDiv, float rightDiv); bool PKey(char k) const { return m_kbm && m_PCharKeys[size_t(k)]; } - bool PSpecialKey(aurora::SpecialKey k) const { return m_kbm && m_PSpecialKeys[size_t(k)]; } + bool PSpecialKey(ESpecialKey k) const { return m_kbm && m_PSpecialKeys[size_t(k)]; } bool PMouseButton(EMouseButton k) const { return m_kbm && m_PMouseButtons[size_t(k)]; } bool DKey(char k) const { return m_kbm && m_kbm->m_charKeys[size_t(k)]; } - bool DSpecialKey(aurora::SpecialKey k) const { return m_kbm && m_kbm->m_specialKeys[size_t(k)]; } + bool DSpecialKey(ESpecialKey k) const { return m_kbm && m_kbm->m_specialKeys[size_t(k)]; } bool DMouseButton(EMouseButton k) const { return m_kbm && m_kbm->m_mouseButtons[size_t(k)]; } float AKey(char k) const { return DKey(k) ? 1.f : 0.f; } - float ASpecialKey(aurora::SpecialKey k) const { return DSpecialKey(k) ? 1.f : 0.f; } + float ASpecialKey(ESpecialKey k) const { return DSpecialKey(k) ? 1.f : 0.f; } float AMouseButton(EMouseButton k) const { return DMouseButton(k) ? 1.f : 0.f; } const std::optional& GetKBM() const { return m_kbm; } diff --git a/Runtime/Input/CInputGenerator.cpp.old b/Runtime/Input/CInputGenerator.cpp.old index a1c0dd047..099b34e30 100644 --- a/Runtime/Input/CInputGenerator.cpp.old +++ b/Runtime/Input/CInputGenerator.cpp.old @@ -69,7 +69,7 @@ void CInputGenerator::controllerRemoved(uint32_t which) noexcept { (*it) = SAuroraControllerState(); } -void CInputGenerator::controllerButton(uint32_t which, aurora::ControllerButton button, bool pressed) noexcept { +void CInputGenerator::controllerButton(uint32_t which, EControllerButton button, bool pressed) noexcept { s32 player = aurora::get_controller_player_index(which); if (player < 0) { return; @@ -77,24 +77,24 @@ void CInputGenerator::controllerButton(uint32_t which, aurora::ControllerButton m_state[player].m_btns.set(size_t(button), pressed); } -void CInputGenerator::controllerAxis(uint32_t which, aurora::ControllerAxis axis, int16_t value) noexcept { +void CInputGenerator::controllerAxis(uint32_t which, EControllerAxis axis, int16_t value) noexcept { s32 player = aurora::get_controller_player_index(which); if (player < 0) { return; } switch (axis) { - case aurora::ControllerAxis::LeftY: - case aurora::ControllerAxis::RightY: + case EControllerAxis::LeftY: + case EControllerAxis::RightY: /* Value is inverted compared to what we expect on the Y axis */ value = int16_t(-(value + 1)); [[fallthrough]]; - case aurora::ControllerAxis::LeftX: - case aurora::ControllerAxis::RightX: + case EControllerAxis::LeftX: + case EControllerAxis::RightX: value /= int16_t(256); break; - case aurora::ControllerAxis::TriggerLeft: - case aurora::ControllerAxis::TriggerRight: + case EControllerAxis::TriggerLeft: + case EControllerAxis::TriggerRight: value /= int16_t(128); break; default: diff --git a/Runtime/Input/CInputGenerator.hpp.old b/Runtime/Input/CInputGenerator.hpp.old index be1328dc8..7c7958b68 100644 --- a/Runtime/Input/CInputGenerator.hpp.old +++ b/Runtime/Input/CInputGenerator.hpp.old @@ -42,9 +42,9 @@ public: void controllerRemoved(uint32_t which) noexcept; - void controllerButton(uint32_t which, aurora::ControllerButton button, bool pressed) noexcept; + void controllerButton(uint32_t which, EControllerButton button, bool pressed) noexcept; - void controllerAxis(uint32_t which, aurora::ControllerAxis axis, int16_t value) noexcept; + void controllerAxis(uint32_t which, EControllerAxis axis, int16_t value) noexcept; /* Keyboard and mouse events are delivered on the main game @@ -74,8 +74,8 @@ public: return; m_data.m_charKeys[charCode] = false; } - void specialKeyDown(aurora::SpecialKey key, aurora::ModifierKey, bool) { m_data.m_specialKeys[size_t(key)] = true; } - void specialKeyUp(aurora::SpecialKey key, aurora::ModifierKey) { m_data.m_specialKeys[size_t(key)] = false; } + void specialKeyDown(ESpecialKey key, aurora::ModifierKey, bool) { m_data.m_specialKeys[size_t(key)] = true; } + void specialKeyUp(ESpecialKey key, aurora::ModifierKey) { m_data.m_specialKeys[size_t(key)] = false; } void modKeyDown(aurora::ModifierKey mod, bool) { m_data.m_modMask = m_data.m_modMask | mod; } void modKeyUp(aurora::ModifierKey mod) { m_data.m_modMask = m_data.m_modMask & ~mod; } diff --git a/Runtime/Input/CKeyboardMouseController.hpp b/Runtime/Input/CKeyboardMouseController.hpp index cd06ce18c..e07021b8e 100644 --- a/Runtime/Input/CKeyboardMouseController.hpp +++ b/Runtime/Input/CKeyboardMouseController.hpp @@ -2,12 +2,119 @@ #include -#include +#include +#include "GCNTypes.hpp" namespace metaforce { - -// TODO: copied from boo; should be rewritten and included from from aurora +// TODO: copied from boo; should be rewritten +enum class EControllerButton : uint8_t { + A, + B, + X, + Y, + Back, + Guide, + Start, + LeftStick, + RightStick, + LeftShoulder, + RightShoulder, + DPadUp, + DPadDown, + DPadLeft, + DPadRight, + Other, + MAX, +}; +enum class EControllerAxis : uint8_t { + LeftX, + LeftY, + RightX, + RightY, + TriggerLeft, + TriggerRight, + MAX, +}; enum class EMouseButton { None = 0, Primary = 1, Secondary = 2, Middle = 3, Aux1 = 4, Aux2 = 5 }; +enum class ESpecialKey : uint8_t { + None = 0, + F1 = 1, + F2 = 2, + F3 = 3, + F4 = 4, + F5 = 5, + F6 = 6, + F7 = 7, + F8 = 8, + F9 = 9, + F10 = 10, + F11 = 11, + F12 = 12, + F13 = 13, + F14 = 14, + F15 = 15, + F16 = 16, + F17 = 17, + F18 = 18, + F19 = 19, + F20 = 20, + F21 = 21, + F22 = 22, + F23 = 23, + F24 = 24, + Esc = 25, + Enter = 26, + Backspace = 27, + Insert = 28, + Delete = 29, + Home = 30, + End = 31, + PgUp = 32, + PgDown = 33, + Left = 34, + Right = 35, + Up = 36, + Down = 37, + Tab = 38, + PrintScreen = 39, + ScrollLock = 40, + Pause = 41, + NumLockClear = 42, + KpDivide = 43, + KpMultiply = 44, + KpMinus = 45, + KpPlus = 46, + KpEnter = 47, + KpNum0 = 48, + KpNum1 = 49, + KpNum2 = 50, + KpNum3 = 51, + KpNum4 = 52, + KpNum5 = 53, + KpNum6 = 54, + KpNum7 = 55, + KpNum8 = 56, + KpNum9 = 57, + KpPercent = 58, + KpPeriod = 59, + KpComma = 60, + KpEquals = 61, + Application = 62, + Power = 63, + Execute = 64, + Help = 65, + Menu = 66, + Select = 67, + Stop = 68, + Again = 69, + Undo = 70, + Cut = 71, + Paste = 72, + Find = 73, + VolumeUp = 74, + VolumeDown = 75, + MAX, +}; enum class EModifierKey { None = 0, Ctrl = 1 << 0, @@ -56,9 +163,9 @@ struct SScrollDelta { struct CKeyboardMouseControllerData { std::array m_charKeys{}; - std::array(aurora::SpecialKey::MAX)> m_specialKeys{}; + std::array(ESpecialKey::MAX)> m_specialKeys{}; std::array m_mouseButtons{}; - aurora::ModifierKey m_modMask = aurora::ModifierKey::None; + EModifierKey m_modMask = EModifierKey::None; SWindowCoord m_mouseCoord; SScrollDelta m_accumScroll; }; diff --git a/Runtime/Input/CMakeLists.txt b/Runtime/Input/CMakeLists.txt index fbe376aab..d5c325173 100644 --- a/Runtime/Input/CMakeLists.txt +++ b/Runtime/Input/CMakeLists.txt @@ -1,5 +1,4 @@ set(INPUT_SOURCES - PAD.hpp IController.hpp DolphinIController.cpp CControllerAxis.hpp CControllerButton.hpp diff --git a/Runtime/Input/ControlMapper.cpp b/Runtime/Input/ControlMapper.cpp index 3e1e60557..b5e438f03 100644 --- a/Runtime/Input/ControlMapper.cpp +++ b/Runtime/Input/ControlMapper.cpp @@ -145,75 +145,75 @@ constexpr std::array skAnalogFuncs{ }; constexpr std::array skKBMMapping{ - ControlMapper::EKBMFunctionList::KeyPress + 'w', // Forward, - ControlMapper::EKBMFunctionList::KeyPress + 's', // Backward, - ControlMapper::EKBMFunctionList::KeyPress + 'a', // TurnLeft, - ControlMapper::EKBMFunctionList::KeyPress + 'd', // TurnRight, - ControlMapper::EKBMFunctionList::KeyPress + 'a', // StrafeLeft, - ControlMapper::EKBMFunctionList::KeyPress + 'd', // StrafeRight, - ControlMapper::EKBMFunctionList::KeyPress + 'a', // LookLeft, - ControlMapper::EKBMFunctionList::KeyPress + 'd', // LookRight, - ControlMapper::EKBMFunctionList::KeyPress + 's', // LookUp, - ControlMapper::EKBMFunctionList::KeyPress + 'w', // LookDown, - ControlMapper::EKBMFunctionList::KeyPress + ' ', // JumpOrBoost = 10, - ControlMapper::EKBMFunctionList::MousePress + EMouseButton::Primary, // FireOrBomb = 11, - ControlMapper::EKBMFunctionList::MousePress + EMouseButton::Secondary, // MissileOrPowerBomb = 12, - ControlMapper::EKBMFunctionList::KeyPress + 'c', // Morph, - ControlMapper::EKBMFunctionList::None, // AimUp, - ControlMapper::EKBMFunctionList::None, // AimDown, - ControlMapper::EKBMFunctionList::None, // CycleBeamUp, - ControlMapper::EKBMFunctionList::None, // CycleBeamDown, - ControlMapper::EKBMFunctionList::None, // CycleItem, - ControlMapper::EKBMFunctionList::KeyPress + '1', // PowerBeam, - ControlMapper::EKBMFunctionList::KeyPress + '3', // IceBeam, - ControlMapper::EKBMFunctionList::KeyPress + '2', // WaveBeam, - ControlMapper::EKBMFunctionList::KeyPress + '4', // PlasmaBeam, - ControlMapper::EKBMFunctionList::None, // ToggleHolster = 23, - ControlMapper::EKBMFunctionList::None, // OrbitClose, - ControlMapper::EKBMFunctionList::KeyPress + 'q', // OrbitFar, - ControlMapper::EKBMFunctionList::KeyPress + 'q', // OrbitObject, - ControlMapper::EKBMFunctionList::None, // OrbitSelect, - ControlMapper::EKBMFunctionList::None, // OrbitConfirm, - ControlMapper::EKBMFunctionList::KeyPress + 'a', // OrbitLeft, - ControlMapper::EKBMFunctionList::KeyPress + 'd', // OrbitRight, - ControlMapper::EKBMFunctionList::KeyPress + 'w', // OrbitUp, - ControlMapper::EKBMFunctionList::KeyPress + 's', // OrbitDown, - ControlMapper::EKBMFunctionList::KeyPress + 'e', // LookHold1, - ControlMapper::EKBMFunctionList::None, // LookHold2, - ControlMapper::EKBMFunctionList::None, // LookZoomIn, - ControlMapper::EKBMFunctionList::None, // LookZoomOut, - ControlMapper::EKBMFunctionList::None, // AimHold, - ControlMapper::EKBMFunctionList::KeyPress + 's', // MapCircleUp, - ControlMapper::EKBMFunctionList::KeyPress + 'w', // MapCircleDown, - ControlMapper::EKBMFunctionList::KeyPress + 'a', // MapCircleLeft, - ControlMapper::EKBMFunctionList::KeyPress + 'd', // MapCircleRight, - ControlMapper::EKBMFunctionList::SpecialKeyPress + aurora::SpecialKey::Up, // MapMoveForward, - ControlMapper::EKBMFunctionList::SpecialKeyPress + aurora::SpecialKey::Down, // MapMoveBack, - ControlMapper::EKBMFunctionList::SpecialKeyPress + aurora::SpecialKey::Left, // MapMoveLeft, - ControlMapper::EKBMFunctionList::SpecialKeyPress + aurora::SpecialKey::Right, // MapMoveRight, - ControlMapper::EKBMFunctionList::KeyPress + 'e', // MapZoomIn, - ControlMapper::EKBMFunctionList::KeyPress + 'q', // MapZoomOut, - ControlMapper::EKBMFunctionList::KeyPress + 'e', // SpiderBall, - ControlMapper::EKBMFunctionList::KeyPress + 'q', // ChaseCamera, - ControlMapper::EKBMFunctionList::SpecialKeyPress + aurora::SpecialKey::Right, // XrayVisor = 50, - ControlMapper::EKBMFunctionList::SpecialKeyPress + aurora::SpecialKey::Down, // ThermoVisor = 51, - ControlMapper::EKBMFunctionList::SpecialKeyPress + aurora::SpecialKey::Left, // InviroVisor = 52, - ControlMapper::EKBMFunctionList::SpecialKeyPress + aurora::SpecialKey::Up, // NoVisor = 53, - ControlMapper::EKBMFunctionList::None, // VisorMenu, - ControlMapper::EKBMFunctionList::None, // VisorUp, - ControlMapper::EKBMFunctionList::None, // VisorDown, - ControlMapper::EKBMFunctionList::KeyPress + 'e', // ShowCrosshairs, - ControlMapper::EKBMFunctionList::None, // UNKNOWN - ControlMapper::EKBMFunctionList::None, // UseSheild = 0x3B, - ControlMapper::EKBMFunctionList::KeyPress + 'q', // ScanItem = 0x3C, - ControlMapper::EKBMFunctionList::None, // UNKNOWN - ControlMapper::EKBMFunctionList::None, // UNKNOWN - ControlMapper::EKBMFunctionList::None, // UNKNOWN - ControlMapper::EKBMFunctionList::None, // UNKNOWN - ControlMapper::EKBMFunctionList::KeyPress + 'q', // PreviousPauseScreen = 0x41, - ControlMapper::EKBMFunctionList::KeyPress + 'e', // NextPauseScreen = 0x42, - ControlMapper::EKBMFunctionList::None, // UNKNOWN, - ControlMapper::EKBMFunctionList::None, // None, + ControlMapper::EKBMFunctionList::KeyPress + 'w', // Forward, + ControlMapper::EKBMFunctionList::KeyPress + 's', // Backward, + ControlMapper::EKBMFunctionList::KeyPress + 'a', // TurnLeft, + ControlMapper::EKBMFunctionList::KeyPress + 'd', // TurnRight, + ControlMapper::EKBMFunctionList::KeyPress + 'a', // StrafeLeft, + ControlMapper::EKBMFunctionList::KeyPress + 'd', // StrafeRight, + ControlMapper::EKBMFunctionList::KeyPress + 'a', // LookLeft, + ControlMapper::EKBMFunctionList::KeyPress + 'd', // LookRight, + ControlMapper::EKBMFunctionList::KeyPress + 's', // LookUp, + ControlMapper::EKBMFunctionList::KeyPress + 'w', // LookDown, + ControlMapper::EKBMFunctionList::KeyPress + ' ', // JumpOrBoost = 10, + ControlMapper::EKBMFunctionList::MousePress + EMouseButton::Primary, // FireOrBomb = 11, + ControlMapper::EKBMFunctionList::MousePress + EMouseButton::Secondary, // MissileOrPowerBomb = 12, + ControlMapper::EKBMFunctionList::KeyPress + 'c', // Morph, + ControlMapper::EKBMFunctionList::None, // AimUp, + ControlMapper::EKBMFunctionList::None, // AimDown, + ControlMapper::EKBMFunctionList::None, // CycleBeamUp, + ControlMapper::EKBMFunctionList::None, // CycleBeamDown, + ControlMapper::EKBMFunctionList::None, // CycleItem, + ControlMapper::EKBMFunctionList::KeyPress + '1', // PowerBeam, + ControlMapper::EKBMFunctionList::KeyPress + '3', // IceBeam, + ControlMapper::EKBMFunctionList::KeyPress + '2', // WaveBeam, + ControlMapper::EKBMFunctionList::KeyPress + '4', // PlasmaBeam, + ControlMapper::EKBMFunctionList::None, // ToggleHolster = 23, + ControlMapper::EKBMFunctionList::None, // OrbitClose, + ControlMapper::EKBMFunctionList::KeyPress + 'q', // OrbitFar, + ControlMapper::EKBMFunctionList::KeyPress + 'q', // OrbitObject, + ControlMapper::EKBMFunctionList::None, // OrbitSelect, + ControlMapper::EKBMFunctionList::None, // OrbitConfirm, + ControlMapper::EKBMFunctionList::KeyPress + 'a', // OrbitLeft, + ControlMapper::EKBMFunctionList::KeyPress + 'd', // OrbitRight, + ControlMapper::EKBMFunctionList::KeyPress + 'w', // OrbitUp, + ControlMapper::EKBMFunctionList::KeyPress + 's', // OrbitDown, + ControlMapper::EKBMFunctionList::KeyPress + 'e', // LookHold1, + ControlMapper::EKBMFunctionList::None, // LookHold2, + ControlMapper::EKBMFunctionList::None, // LookZoomIn, + ControlMapper::EKBMFunctionList::None, // LookZoomOut, + ControlMapper::EKBMFunctionList::None, // AimHold, + ControlMapper::EKBMFunctionList::KeyPress + 's', // MapCircleUp, + ControlMapper::EKBMFunctionList::KeyPress + 'w', // MapCircleDown, + ControlMapper::EKBMFunctionList::KeyPress + 'a', // MapCircleLeft, + ControlMapper::EKBMFunctionList::KeyPress + 'd', // MapCircleRight, + ControlMapper::EKBMFunctionList::SpecialKeyPress + ESpecialKey::Up, // MapMoveForward, + ControlMapper::EKBMFunctionList::SpecialKeyPress + ESpecialKey::Down, // MapMoveBack, + ControlMapper::EKBMFunctionList::SpecialKeyPress + ESpecialKey::Left, // MapMoveLeft, + ControlMapper::EKBMFunctionList::SpecialKeyPress + ESpecialKey::Right, // MapMoveRight, + ControlMapper::EKBMFunctionList::KeyPress + 'e', // MapZoomIn, + ControlMapper::EKBMFunctionList::KeyPress + 'q', // MapZoomOut, + ControlMapper::EKBMFunctionList::KeyPress + 'e', // SpiderBall, + ControlMapper::EKBMFunctionList::KeyPress + 'q', // ChaseCamera, + ControlMapper::EKBMFunctionList::SpecialKeyPress + ESpecialKey::Right, // XrayVisor = 50, + ControlMapper::EKBMFunctionList::SpecialKeyPress + ESpecialKey::Down, // ThermoVisor = 51, + ControlMapper::EKBMFunctionList::SpecialKeyPress + ESpecialKey::Left, // InviroVisor = 52, + ControlMapper::EKBMFunctionList::SpecialKeyPress + ESpecialKey::Up, // NoVisor = 53, + ControlMapper::EKBMFunctionList::None, // VisorMenu, + ControlMapper::EKBMFunctionList::None, // VisorUp, + ControlMapper::EKBMFunctionList::None, // VisorDown, + ControlMapper::EKBMFunctionList::KeyPress + 'e', // ShowCrosshairs, + ControlMapper::EKBMFunctionList::None, // UNKNOWN + ControlMapper::EKBMFunctionList::None, // UseSheild = 0x3B, + ControlMapper::EKBMFunctionList::KeyPress + 'q', // ScanItem = 0x3C, + ControlMapper::EKBMFunctionList::None, // UNKNOWN + ControlMapper::EKBMFunctionList::None, // UNKNOWN + ControlMapper::EKBMFunctionList::None, // UNKNOWN + ControlMapper::EKBMFunctionList::None, // UNKNOWN + ControlMapper::EKBMFunctionList::KeyPress + 'q', // PreviousPauseScreen = 0x41, + ControlMapper::EKBMFunctionList::KeyPress + 'e', // NextPauseScreen = 0x42, + ControlMapper::EKBMFunctionList::None, // UNKNOWN, + ControlMapper::EKBMFunctionList::None, // None, ControlMapper::EKBMFunctionList::None, }; @@ -307,10 +307,10 @@ static float KBToWASDY(const CKeyboardMouseControllerData& data) { static float KBToArrowsX(const CKeyboardMouseControllerData& data) { float retval = 0.0; - if (data.m_specialKeys[size_t(aurora::SpecialKey::Left)]) { + if (data.m_specialKeys[size_t(ESpecialKey::Left)]) { retval -= 1.0; } - if (data.m_specialKeys[size_t(aurora::SpecialKey::Right)]) { + if (data.m_specialKeys[size_t(ESpecialKey::Right)]) { retval += 1.0; } return retval; @@ -318,10 +318,10 @@ static float KBToArrowsX(const CKeyboardMouseControllerData& data) { static float KBToArrowsY(const CKeyboardMouseControllerData& data) { float retval = 0.0; - if (data.m_specialKeys[size_t(aurora::SpecialKey::Down)]) { + if (data.m_specialKeys[size_t(ESpecialKey::Down)]) { retval -= 1.0; } - if (data.m_specialKeys[size_t(aurora::SpecialKey::Up)]) { + if (data.m_specialKeys[size_t(ESpecialKey::Up)]) { retval += 1.0; } return retval; diff --git a/Runtime/Input/ControlMapper.hpp b/Runtime/Input/ControlMapper.hpp index 30f81bbab..59643045a 100644 --- a/Runtime/Input/ControlMapper.hpp +++ b/Runtime/Input/ControlMapper.hpp @@ -126,7 +126,7 @@ constexpr ControlMapper::EKBMFunctionList operator+(ControlMapper::EKBMFunctionL return ControlMapper::EKBMFunctionList(static_cast(a) + static_cast(b)); } -constexpr ControlMapper::EKBMFunctionList operator+(ControlMapper::EKBMFunctionList a, aurora::SpecialKey b) { +constexpr ControlMapper::EKBMFunctionList operator+(ControlMapper::EKBMFunctionList a, ESpecialKey b) { using T = std::underlying_type_t; return ControlMapper::EKBMFunctionList(static_cast(a) + static_cast(b)); } diff --git a/Runtime/Input/InputTypes.hpp b/Runtime/Input/InputTypes.hpp index f21cecb54..40883e904 100644 --- a/Runtime/Input/InputTypes.hpp +++ b/Runtime/Input/InputTypes.hpp @@ -1,18 +1,17 @@ #pragma once -#include "Runtime/Input/PAD.hpp" - +#include namespace metaforce { enum class EIOPort { - Player1, - Player2, - Player3, - Player4, + Player1 = PAD_CHAN0, + Player2 = PAD_CHAN1, + Player3 = PAD_CHAN2, + Player4 = PAD_CHAN3, }; enum class EMotorState { - Stop = 0, - Rumble = 1, - StopHard = 2, + Stop = PAD_MOTOR_STOP, + Rumble = PAD_MOTOR_RUMBLE, + StopHard = PAD_MOTOR_STOP_HARD, }; -} // namespace metaforce \ No newline at end of file +} // namespace metaforce diff --git a/Runtime/Input/PAD.hpp b/Runtime/Input/PAD.hpp deleted file mode 100644 index aaa52518e..000000000 --- a/Runtime/Input/PAD.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "aurora/pad.hpp" - -using PADStatus = PAD::Status; -using PADButton = PAD::BUTTON; \ No newline at end of file diff --git a/Runtime/MP1/CFrontEndUI.cpp b/Runtime/MP1/CFrontEndUI.cpp index a55ec99be..0be525c11 100644 --- a/Runtime/MP1/CFrontEndUI.cpp +++ b/Runtime/MP1/CFrontEndUI.cpp @@ -782,10 +782,10 @@ CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::ProcessUserInput(const CFinalInpu case EUIType::LinkFailed: case EUIType::LinkCompleteOrLinking: case EUIType::TurnOffGBA: - if (input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) { + if (input.PA() || input.PSpecialKey(ESpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) { PlayAdvanceSfx(); SetUIText(NextLinkUI[size_t(x0_uiType)]); - } else if (input.PB() || input.PSpecialKey(aurora::SpecialKey::Esc)) { + } else if (input.PB() || input.PSpecialKey(ESpecialKey::Esc)) { const EUIType prevUi = PrevLinkUI[size_t(x0_uiType)]; if (prevUi == EUIType::Empty) { break; @@ -981,7 +981,7 @@ CFrontEndUI::SFusionBonusFrame::EAction CFrontEndUI::SFusionBonusFrame::ProcessU } } else if (x24_loadedFrame) { CFinalInput useInput = input; - if (input.PZ() || input.PSpecialKey(aurora::SpecialKey::Tab)) { + if (input.PZ() || input.PSpecialKey(ESpecialKey::Tab)) { useInput.x2d_b28_PA = true; m_gbaOverride = true; } @@ -1238,7 +1238,7 @@ void CFrontEndUI::SNesEmulatorFrame::ProcessUserInput(const CFinalInput& input, switch (x0_mode) { case EMode::Emulator: x4_nesEmu->ProcessUserInput(input, 4); - if ((input.ControllerIdx() == 0 && input.PL()) || input.PSpecialKey(aurora::SpecialKey::Esc)) + if ((input.ControllerIdx() == 0 && input.PL()) || input.PSpecialKey(ESpecialKey::Esc)) SetMode(EMode::QuitNESMetroid); break; case EMode::SaveProgress: @@ -1577,7 +1577,7 @@ bool CFrontEndUI::SOptionsFrontEndFrame::ProcessUserInput(const CFinalInput& inp if (sui) sui->ProcessUserInput(input); if (x1c_loadedFrame && x134_24_visible) { - if ((input.PB() || input.PSpecialKey(aurora::SpecialKey::Esc)) && x24_tablegroup_leftmenu->GetIsActive()) { + if ((input.PB() || input.PSpecialKey(ESpecialKey::Esc)) && x24_tablegroup_leftmenu->GetIsActive()) { x134_25_exitOptions = true; CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); } else { @@ -1966,16 +1966,16 @@ void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue& if (x50_curScreen != x54_nextScreen) { if (x54_nextScreen == EScreen::AttractMovie && - (input.PStart() || input.PA() || input.PSpecialKey(aurora::SpecialKey::Esc) || - input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary))) { + (input.PStart() || input.PA() || input.PSpecialKey(ESpecialKey::Esc) || + input.PSpecialKey(ESpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary))) { /* Player wants to return to opening credits from attract movie */ SetFadeBlackTimer(std::min(1.f, x58_fadeBlackTimer)); PlayAdvanceSfx(); return; } - if (input.PA() || input.PStart() || input.PSpecialKey(aurora::SpecialKey::Esc) || - input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) { + if (input.PA() || input.PStart() || input.PSpecialKey(ESpecialKey::Esc) || + input.PSpecialKey(ESpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) { if (x50_curScreen == EScreen::OpenCredits && x54_nextScreen == EScreen::Title && x58_fadeBlackTimer > 1.f) { /* Player is too impatient to view opening credits */ xd0_playerSkipToTitle = true; @@ -1985,8 +1985,8 @@ void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue& } } else { if (x50_curScreen == EScreen::Title) { - if (input.PStart() || input.PA() || input.PSpecialKey(aurora::SpecialKey::Esc) || - input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) { + if (input.PStart() || input.PA() || input.PSpecialKey(ESpecialKey::Esc) || + input.PSpecialKey(ESpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary)) { if (x58_fadeBlackTimer < 30.f - g_tweakGame->GetPressStartDelay()) { /* Proceed to file select UI */ CSfxManager::SfxStart(FETransitionBackSFX[x18_rndA][0], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); diff --git a/Runtime/MP1/CInGameGuiManager.cpp b/Runtime/MP1/CInGameGuiManager.cpp index 3cd57af90..de9838343 100644 --- a/Runtime/MP1/CInGameGuiManager.cpp +++ b/Runtime/MP1/CInGameGuiManager.cpp @@ -596,7 +596,7 @@ void CInGameGuiManager::Draw(CStateManager& stateMgr) { float xT = 1.f - zeus::clamp(0.f, (stateMgr.GetPlayer().GetDeathTime() - xStart) / 0.5f, 1.f); float colT = 1.f - zeus::clamp(0.f, (stateMgr.GetPlayer().GetDeathTime() - colStart) / 0.5f, 1.f); SClipScreenRect rect(CGraphics::g_Viewport); - CGraphics::ResolveSpareTexture(rect, 0, GX::TF_RGB565); + CGraphics::ResolveSpareTexture(rect, 0, GX_TF_RGB565); CCameraFilterPass::DrawFilter(EFilterType::Blend, EFilterShape::Fullscreen, zeus::skBlack, nullptr, 1.f); float z = 0.5f * (zT * zT * zT * zT * zT * (CGraphics::GetViewportHeight() - 12.f) + 12.f); float x = 0.5f * (xT * (CGraphics::GetViewportWidth() - 12.f) + 12.f); diff --git a/Runtime/MP1/CInventoryScreen.cpp b/Runtime/MP1/CInventoryScreen.cpp index 1a5fda10c..1363a2a96 100644 --- a/Runtime/MP1/CInventoryScreen.cpp +++ b/Runtime/MP1/CInventoryScreen.cpp @@ -141,7 +141,7 @@ void CInventoryScreen::ProcessControllerInput(const CFinalInput& input) { if (input.PStart()) { x19c_samusDoll->BeginViewInterpolate(false); x198_26_exitPauseScreen = true; - } else if (input.PB() || input.PSpecialKey(aurora::SpecialKey::Esc)) { + } else if (input.PB() || input.PSpecialKey(ESpecialKey::Esc)) { x19c_samusDoll->BeginViewInterpolate(false); } } @@ -220,7 +220,7 @@ void CInventoryScreen::ProcessControllerInput(const CFinalInput& input) { if (input.PLAUp() || m_bodyUpClicked) newPage = std::max(oldPage - 1, 0); else if (input.PLADown() || m_bodyDownClicked || - ((input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter) || m_bodyClicked) && !lastPage)) + ((input.PA() || input.PSpecialKey(ESpecialKey::Enter) || m_bodyClicked) && !lastPage)) newPage = std::min(oldPage + 1, totalCount - 1); x174_textpane_body->TextSupport().SetPage(newPage); if (oldPage != newPage) @@ -233,8 +233,8 @@ void CInventoryScreen::ProcessControllerInput(const CFinalInput& input) { } if (!x1ac_textLeaveRequested) x1ac_textLeaveRequested = - input.PB() || input.PSpecialKey(aurora::SpecialKey::Esc) || - ((input.PA() || m_bodyClicked || input.PSpecialKey(aurora::SpecialKey::Enter)) && lastPage); + input.PB() || input.PSpecialKey(ESpecialKey::Esc) || + ((input.PA() || m_bodyClicked || input.PSpecialKey(ESpecialKey::Enter)) && lastPage); x1ad_textViewing = !x1ac_textLeaveRequested; } else { x198_29_pulseTextArrowBottom = false; diff --git a/Runtime/MP1/CLogBookScreen.cpp b/Runtime/MP1/CLogBookScreen.cpp index 8de7c2c04..d8fe325f7 100644 --- a/Runtime/MP1/CLogBookScreen.cpp +++ b/Runtime/MP1/CLogBookScreen.cpp @@ -338,7 +338,7 @@ void CLogBookScreen::ProcessControllerInput(const CFinalInput& input) { if (input.PLAUp() || m_bodyUpClicked) newPage = std::max(oldPage - 1, 0); else if (input.PLADown() || m_bodyDownClicked || - ((input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter) || m_bodyClicked) && !lastPage)) + ((input.PA() || input.PSpecialKey(ESpecialKey::Enter) || m_bodyClicked) && !lastPage)) newPage = std::min(oldPage + 1, pageCount - 1); x174_textpane_body->TextSupport().SetPage(newPage); if (oldPage != newPage) @@ -352,8 +352,8 @@ void CLogBookScreen::ProcessControllerInput(const CFinalInput& input) { if (!x260_26_exitTextScroll) x260_26_exitTextScroll = - input.PB() || input.PSpecialKey(aurora::SpecialKey::Esc) || - ((input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter) || m_bodyClicked) && lastPage); + input.PB() || input.PSpecialKey(ESpecialKey::Esc) || + ((input.PA() || input.PSpecialKey(ESpecialKey::Enter) || m_bodyClicked) && lastPage); if (g_tweakGui->GetLatchArticleText()) x260_25_inTextScroll = !x260_26_exitTextScroll; diff --git a/Runtime/MP1/CMFGame.cpp b/Runtime/MP1/CMFGame.cpp index 6e1da4576..8dc213422 100644 --- a/Runtime/MP1/CMFGame.cpp +++ b/Runtime/MP1/CMFGame.cpp @@ -125,7 +125,7 @@ CIOWin::EMessageReturn CMFGame::OnMessage(const CArchitectureMessage& msg, CArch if (input.ControllerIdx() == 0) { const CEntity* cam = x14_stateManager->GetCameraManager()->GetCurrentCamera(*x14_stateManager); TCastToConstPtr cineCam = cam; - if (input.PStart() || input.PSpecialKey(aurora::SpecialKey::Esc)) { + if (input.PStart() || input.PSpecialKey(ESpecialKey::Esc)) { if (cineCam && x14_stateManager->GetSkipCinematicSpecialFunction() != kInvalidUniqueId) { CMidiManager::StopAll(); x28_skippedCineCam = cineCam->GetUniqueId(); @@ -134,7 +134,7 @@ CIOWin::EMessageReturn CMFGame::OnMessage(const CArchitectureMessage& msg, CArch } else if (!cineCam) { x14_stateManager->DeferStateTransition(EStateManagerTransition::PauseGame); } - } else if ((input.PZ() || input.PSpecialKey(aurora::SpecialKey::Tab)) && !cineCam && + } else if ((input.PZ() || input.PSpecialKey(ESpecialKey::Tab)) && !cineCam && x14_stateManager->CanShowMapScreen()) { x14_stateManager->DeferStateTransition(EStateManagerTransition::MapScreen); } diff --git a/Runtime/MP1/CMessageScreen.cpp b/Runtime/MP1/CMessageScreen.cpp index 459ce2c92..62215cf70 100644 --- a/Runtime/MP1/CMessageScreen.cpp +++ b/Runtime/MP1/CMessageScreen.cpp @@ -18,7 +18,7 @@ CMessageScreen::CMessageScreen(CAssetId msg, float delayTime) : x74_delayTime(de void CMessageScreen::ProcessControllerInput(const CFinalInput& input) { if (!x18_loadedMsgScreen || x74_delayTime > 0.f || - !(input.PA() || input.PSpecialKey(aurora::SpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary))) + !(input.PA() || input.PSpecialKey(ESpecialKey::Enter) || input.PMouseButton(EMouseButton::Primary))) return; if (x1c_textpane_message->TextSupport().GetCurTime() < x1c_textpane_message->TextSupport().GetTotalAnimationTime()) { diff --git a/Runtime/MP1/COptionsScreen.cpp b/Runtime/MP1/COptionsScreen.cpp index 9b990c27c..2348c25de 100644 --- a/Runtime/MP1/COptionsScreen.cpp +++ b/Runtime/MP1/COptionsScreen.cpp @@ -153,7 +153,7 @@ void COptionsScreen::ProcessControllerInput(const CFinalInput& input) { CGameOptions::TryRestoreDefaults(input, x70_tablegroup_leftlog->GetUserSelection(), x1c_rightSel, false, rightClicked); if (x70_tablegroup_leftlog->GetUserSelection() == 4 && - (input.PA() || leftClicked || input.PSpecialKey(aurora::SpecialKey::Enter))) + (input.PA() || leftClicked || input.PSpecialKey(ESpecialKey::Enter))) x19c_quitGame = std::make_unique(EQuitType::QuitGame); } else { CPauseScreenBase::ResetMouseState(); diff --git a/Runtime/MP1/CPauseScreen.cpp b/Runtime/MP1/CPauseScreen.cpp index a09a572d4..50a39ba0c 100644 --- a/Runtime/MP1/CPauseScreen.cpp +++ b/Runtime/MP1/CPauseScreen.cpp @@ -202,7 +202,7 @@ void CPauseScreen::ProcessControllerInput(const CStateManager& mgr, const CFinal if (InputEnabled()) { bool invalid = x8_curSubscreen == ESubScreen::ToGame; - if (useInput.PStart() || ((useInput.PB() || useInput.PSpecialKey(aurora::SpecialKey::Esc)) && bExits) || + if (useInput.PStart() || ((useInput.PB() || useInput.PSpecialKey(ESpecialKey::Esc)) && bExits) || (x7c_screens[x78_activeIdx] && x7c_screens[x78_activeIdx]->ShouldExitPauseScreen())) { CSfxManager::SfxStart(SFXui_pause_screen_exit, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); StartTransition(0.5f, mgr, ESubScreen::ToGame, 2); diff --git a/Runtime/MP1/CPlayerVisor.cpp b/Runtime/MP1/CPlayerVisor.cpp index 55c41e070..84596e4f8 100644 --- a/Runtime/MP1/CPlayerVisor.cpp +++ b/Runtime/MP1/CPlayerVisor.cpp @@ -353,7 +353,7 @@ void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, CTargetingManager* t rect.x8_top = int((CGraphics::GetViewportHeight() - vpH) / 2.f); rect.xc_width = int(vpW); rect.x10_height = int(vpH); - CGraphics::ResolveSpareTexture(rect, 0, GX::TF_RGB565); + CGraphics::ResolveSpareTexture(rect, 0, GX_TF_RGB565); { SCOPED_GRAPHICS_DEBUG_GROUP("x64_scanDim Draw", zeus::skMagenta); @@ -366,7 +366,7 @@ void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, CTargetingManager* t const zeus::CTransform seventeenScale = zeus::CTransform::Scale(17.f * vpScale, 1.f, 17.f * vpScale); const zeus::CTransform mm = seventeenScale * windowScale; g_Renderer->SetModelMatrix(mm); - CGraphics::LoadDolphinSpareTexture(0, GX::TF_RGB565, GX::TEXMAP0); + CGraphics::LoadDolphinSpareTexture(0, GX_TF_RGB565, GX_TEXMAP0); if (x108_newScanPane) { SCOPED_GRAPHICS_DEBUG_GROUP("x108_newScanPane Draw", zeus::skMagenta); diff --git a/Runtime/MP1/CQuitGameScreen.cpp b/Runtime/MP1/CQuitGameScreen.cpp index 79883ddc3..83ad9ae81 100644 --- a/Runtime/MP1/CQuitGameScreen.cpp +++ b/Runtime/MP1/CQuitGameScreen.cpp @@ -106,7 +106,7 @@ void CQuitGameScreen::ProcessUserInput(const CFinalInput& input) { x10_loadedFrame->ProcessMouseInput( input, CGuiWidgetDrawParms{1.f, zeus::CVector3f{0.f, 0.f, VerticalOffsets[size_t(x0_type)]}}); x10_loadedFrame->ProcessUserInput(input); - if ((input.PB() || input.PSpecialKey(aurora::SpecialKey::Esc)) && x0_type != EQuitType::ContinueFromLastSave) { + if ((input.PB() || input.PSpecialKey(ESpecialKey::Esc)) && x0_type != EQuitType::ContinueFromLastSave) { x18_action = EQuitAction::No; } } diff --git a/Runtime/MP1/CSamusDoll.cpp b/Runtime/MP1/CSamusDoll.cpp index 0b20c34a3..9533b4b46 100644 --- a/Runtime/MP1/CSamusDoll.cpp +++ b/Runtime/MP1/CSamusDoll.cpp @@ -332,7 +332,7 @@ void CSamusDoll::Draw(const CStateManager& mgr, float alpha) { bool phazonSuit = x44_suit == CPlayerState::EPlayerSuit::Phazon; if (phazonSuit) { - GXSetDstAlpha(true, 1.f); + GXSetDstAlpha(true, 255); } for (size_t i = 0; i <= x118_suitModel1and2.size(); ++i) { diff --git a/Runtime/MP1/MP1.cpp b/Runtime/MP1/MP1.cpp index c2aa5e431..2ecb04145 100644 --- a/Runtime/MP1/MP1.cpp +++ b/Runtime/MP1/MP1.cpp @@ -222,18 +222,6 @@ CGameArchitectureSupport::~CGameArchitectureSupport() { CStreamAudioManager::Shutdown(); } -void CGameArchitectureSupport::charKeyDown(uint8_t charCode, aurora::ModifierKey mods, bool isRepeat) { - // x30_inputGenerator.charKeyDown(charCode, mods, isRepeat); -} - -void CGameArchitectureSupport::specialKeyDown(aurora::SpecialKey key, aurora::ModifierKey mods, bool isRepeat) { - // x30_inputGenerator.specialKeyDown(key, mods, isRepeat); -} - -void CGameArchitectureSupport::specialKeyUp(aurora::SpecialKey key, aurora::ModifierKey mods) { - // x30_inputGenerator.specialKeyUp(key, mods); -} - CMain::CMain(IFactory* resFactory, CSimplePool* resStore) : xe4_gameplayResult(EGameplayResult::Playing) , x128_globalObjects(std::make_unique(resFactory, resStore)) { @@ -518,8 +506,8 @@ void CMain::HandleDiscordErrored(int errorCode, const char* message) { DiscordLog.report(logvisor::Error, FMT_STRING("Discord Error: {}"), message); } -std::string CMain::Init(const FileStoreManager& storeMgr, CVarManager* cvarMgr, boo::IAudioVoiceEngine* voiceEngine, - amuse::IBackendVoiceAllocator& backend) { +std::string CMain::Init(int argc, char** argv, const FileStoreManager& storeMgr, CVarManager* cvarMgr, + boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend) { m_cvarMgr = cvarMgr; { @@ -607,11 +595,11 @@ std::string CMain::Init(const FileStoreManager& storeMgr, CVarManager* cvarMgr, x70_tweaks.RegisterResourceTweaks(m_cvarMgr); AddWorldPaks(); - auto args = aurora::get_args(); - for (auto it = args.begin(); it != args.end(); ++it) { - if (*it == "--warp" && args.end() - it >= 3) { - const char* worldIdxStr = (*(it + 1)).c_str(); - const char* areaIdxStr = (*(it + 2)).c_str(); + for (int i = 1; i < argc; ++i) { + std::string arg = argv[i]; + if (arg == "--warp" && i < argc - 2) { + const char* worldIdxStr = argv[i + 1]; + const char* areaIdxStr = argv[i + 2]; char* endptr = nullptr; m_warpWorldIdx = TAreaId(strtoul(worldIdxStr, &endptr, 0)); @@ -636,8 +624,8 @@ std::string CMain::Init(const FileStoreManager& storeMgr, CVarManager* cvarMgr, break; } - while (args.end() - it >= 4) { - const char* layerStr = (*(it + 3)).c_str(); + while (i < argc - 3) { + const char* layerStr = argv[i + 3]; if (!(layerStr[0] == '0' && layerStr[1] == 'x') && (layerStr[0] == '0' || layerStr[0] == '1')) { for (const auto* cur = layerStr; *cur != '\0'; ++cur) if (*cur == '1') @@ -645,7 +633,7 @@ std::string CMain::Init(const FileStoreManager& storeMgr, CVarManager* cvarMgr, } else if (layerStr[0] == '0' && layerStr[1] == 'x') { m_warpMemoryRelays.emplace_back(TAreaId(strtoul(layerStr + 2, nullptr, 16))); } - ++it; + ++i; } SetFlowState(EClientFlowStates::StateSetter); diff --git a/Runtime/MP1/MP1.hpp b/Runtime/MP1/MP1.hpp index b14c7ea32..520cc49e6 100644 --- a/Runtime/MP1/MP1.hpp +++ b/Runtime/MP1/MP1.hpp @@ -90,6 +90,7 @@ public: g_SimplePool = xcc_simplePool; g_CharFactoryBuilder = &xec_charFactoryBuilder; g_AiFuncMap = &x110_aiFuncMap; + CGraphics::Startup(); // TODO CGraphicsSys x134_gameState = std::make_unique(); g_GameState = x134_gameState.get(); g_TweakManager = &x150_tweakManager; @@ -124,46 +125,12 @@ class CGameArchitectureSupport { EAudioLoadStatus x88_audioLoadStatus = EAudioLoadStatus::Uninitialized; std::vector> x8c_pendingAudioGroups; - aurora::WindowSize m_windowRect; - bool m_rectIsDirty = false; - void destroyed() { x4_archQueue.Push(MakeMsg::CreateRemoveAllIOWins(EArchMsgTarget::IOWinManager)); } - void resized(const aurora::WindowSize& rect) { - m_windowRect = rect; - m_rectIsDirty = true; - } - public: CGameArchitectureSupport(CMain& parent, boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend); ~CGameArchitectureSupport(); - void mouseDown(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) { - // x30_inputGenerator.mouseDown(coord, button, mods); - } - void mouseUp(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) { - // x30_inputGenerator.mouseUp(coord, button, mods); - } - void mouseMove(const SWindowCoord& coord) { - // x30_inputGenerator.mouseMove(coord); - } - void scroll(const SWindowCoord& coord, const SScrollDelta& scroll) { - // x30_inputGenerator.scroll(coord, scroll); - } - void charKeyDown(uint8_t charCode, aurora::ModifierKey mods, bool isRepeat); - void charKeyUp(uint8_t charCode, aurora::ModifierKey mods) { - // x30_inputGenerator.charKeyUp(charCode, mods); - } - void specialKeyDown(aurora::SpecialKey key, aurora::ModifierKey mods, bool isRepeat); - - void specialKeyUp(aurora::SpecialKey key, aurora::ModifierKey mods); - void modKeyDown(aurora::ModifierKey mod, bool isRepeat) { - // x30_inputGenerator.modKeyDown(mod, isRepeat); - } - void modKeyUp(aurora::ModifierKey mod) { - // x30_inputGenerator.modKeyUp(mod); - } - void PreloadAudio(); bool LoadAudio(); void UnloadAudio(); @@ -171,12 +138,6 @@ public: void Update(float dt); void Draw(); - bool isRectDirty() const { return m_rectIsDirty; } - const aurora::WindowSize& getWindowRect() { - m_rectIsDirty = false; - return m_windowRect; - } - CIOWinManager& GetIOWinManager() { return x58_ioWinManager; } }; @@ -252,12 +213,11 @@ public: // int RsMain(int argc, char** argv, boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& // backend); - std::string Init(const FileStoreManager& storeMgr, CVarManager* cvarManager, boo::IAudioVoiceEngine* voiceEngine, - amuse::IBackendVoiceAllocator& backend) override; + std::string Init(int argc, char** argv, const FileStoreManager& storeMgr, CVarManager* cvarManager, + boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend) override; bool Proc(float dt) override; void Draw() override; void Shutdown() override; - // boo::IWindow* GetMainWindow() const override; void MemoryCardInitializePump(); diff --git a/Runtime/MP1/World/COmegaPirate.cpp b/Runtime/MP1/World/COmegaPirate.cpp index 0e6d4c32b..c1c6b5ad1 100644 --- a/Runtime/MP1/World/COmegaPirate.cpp +++ b/Runtime/MP1/World/COmegaPirate.cpp @@ -91,11 +91,11 @@ void COmegaPirate::CFlash::Render(CStateManager& mgr) { if (xf0_thermalSpot == nullptr || !xe8_thermalSpotToken) { return; } - xf0_thermalSpot->Load(GX::TEXMAP0, EClampMode::Repeat); + xf0_thermalSpot->Load(GX_TEXMAP0, EClampMode::Repeat); float sizeMul = 35.f; if (visor == CPlayerState::EPlayerVisor::XRay) { - CGX::SetBlendMode(GX::BM_SUBTRACT, GX::BL_ONE, GX::BL_ZERO, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_SUBTRACT, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR); sizeMul = 60.f; } else { CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear); @@ -111,7 +111,7 @@ void COmegaPirate::CFlash::Render(CStateManager& mgr) { CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); CGraphics::SetDepthWriteMode(false, ERglEnum::Always, false); CGraphics::StreamColor(zeus::CColor{1.f, std::min(1.f, size)}); - CGraphics::StreamBegin(GX::TRIANGLEFAN); + CGraphics::StreamBegin(GX_TRIANGLEFAN); CGraphics::StreamTexcoord(0.f, 0.f); CGraphics::StreamVertex(rvS + upVec); CGraphics::StreamTexcoord(1.f, 0.f); diff --git a/Runtime/MP1/World/CThardus.cpp b/Runtime/MP1/World/CThardus.cpp index eb82b3033..1d04fcf91 100644 --- a/Runtime/MP1/World/CThardus.cpp +++ b/Runtime/MP1/World/CThardus.cpp @@ -1386,7 +1386,7 @@ void CThardus::RenderFlare(const CStateManager& mgr, float t) { if (!x91c_flareTexture) { return; } - x91c_flareTexture->Load(GX::TEXMAP0, EClampMode::Repeat); + x91c_flareTexture->Load(GX_TEXMAP0, EClampMode::Repeat); const float scale = 30.f * t; zeus::CVector3f offset = scale * CGraphics::g_ViewMatrix.basis[2]; @@ -1398,7 +1398,7 @@ void CThardus::RenderFlare(const CStateManager& mgr, float t) { CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); CGraphics::SetDepthWriteMode(false, ERglEnum::Always, false); CGraphics::StreamColor({t, t}); - CGraphics::StreamBegin(GX::TRIANGLEFAN); + CGraphics::StreamBegin(GX_TRIANGLEFAN); CGraphics::StreamTexcoord(0.f, 0.f); CGraphics::StreamVertex(min + offset); CGraphics::StreamTexcoord(1.f, 0.f); diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp index 35a139e8b..88d123c1c 100644 --- a/Runtime/Particle/CElementGen.cpp +++ b/Runtime/Particle/CElementGen.cpp @@ -913,27 +913,27 @@ void CElementGen::RenderModels() { CParticle& target = x30_particles[0]; int partFrame = x74_curFrame - target.x28_startFrame; cachedTex = texr->GetValueTexture(partFrame).GetObj(); - cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat); + cachedTex->Load(GX_TEXMAP0, EClampMode::Repeat); CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc); if (moveRedToAlphaBuffer) { - CGX::SetTevColorIn(GX::TEVSTAGE1, GX::CC_ZERO, GX::CC_CPREV, GX::CC_APREV, GX::CC_ZERO); - CGX::SetTevAlphaIn(GX::TEVSTAGE1, GX::CA_ZERO, GX::CA_TEXA, GX::CA_APREV, GX::CA_ZERO); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE1); - CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); - GXSetTevSwapMode(GX::TEVSTAGE1, GX::TEV_SWAP0, GX::TEV_SWAP1); + CGX::SetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_CPREV, GX_CC_APREV, GX_CC_ZERO); + CGX::SetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE1); + CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP1); CGX::SetNumTevStages(2); constexpr std::array vtxDescList{ - GX::VtxDescList{GX::VA_POS, GX::DIRECT}, - GX::VtxDescList{GX::VA_CLR0, GX::DIRECT}, - GX::VtxDescList{GX::VA_TEX0, GX::DIRECT}, - GX::VtxDescList{}, + GXVtxDescList{GX_VA_POS, GX_DIRECT}, + GXVtxDescList{GX_VA_CLR0, GX_DIRECT}, + GXVtxDescList{GX_VA_TEX0, GX_DIRECT}, + GXVtxDescList{GX_VA_NULL, GX_NONE}, }; CGX::SetVtxDescv(vtxDescList.data()); CGX::SetChanCtrl(CGX::EChannelId::Channel0, {}); CGX::SetNumChans(1); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR0A0); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); CGX::SetNumTexGens(1); } else { CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); @@ -1036,7 +1036,7 @@ void CElementGen::RenderModels() { if (desc->x45_24_x31_26_PMUS) { if (moveRedToAlphaBuffer) { - CGX::Begin(GX::QUADS, GX::VTXFMT0, 4); + CGX::Begin(GX_QUADS, GX_VTXFMT0, 4); GXPosition3f32(0.5f, 0.f, 0.5f); GXColor4f32(col); GXTexCoord2f32(uvs.xMax, uvs.yMax); @@ -1051,7 +1051,7 @@ void CElementGen::RenderModels() { GXTexCoord2f32(uvs.xMax, uvs.yMin); CGX::End(); } else { - CGraphics::StreamBegin(GX::QUADS); + CGraphics::StreamBegin(GX_QUADS); CGraphics::StreamColor(col); CGraphics::StreamTexcoord(uvs.xMax, uvs.yMax); CGraphics::StreamVertex(0.5f, 0.f, 0.5f); @@ -1087,7 +1087,7 @@ void CElementGen::RenderModels() { CGraphics::SetCullMode(ERglCullMode::Front); CTevCombiners::ResetStates(); if (moveRedToAlphaBuffer) { - GXSetTevSwapMode(GX::TEVSTAGE1, GX::TEV_SWAP0, GX::TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0); } CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); } @@ -1132,7 +1132,7 @@ void CElementGen::RenderLines() { CParticle& target = x30_particles[0]; int partFrame = x74_curFrame - target.x28_startFrame; cachedTex = texr->GetValueTexture(partFrame).GetObj(); - cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat); + cachedTex->Load(GX_TEXMAP0, EClampMode::Repeat); /* Set TEXC * RASC */ @@ -1162,7 +1162,7 @@ void CElementGen::RenderLines() { if (!constTexr) { CTexture* tex = texr->GetValueTexture(partFrame).GetObj(); if (tex != cachedTex) { - tex->Load(GX::TEXMAP0, EClampMode::Repeat); + tex->Load(GX_TEXMAP0, EClampMode::Repeat); cachedTex = tex; } } @@ -1253,7 +1253,7 @@ void CElementGen::RenderParticles() { CParticle& target = x30_particles[0]; int partFrame = x74_curFrame - target.x28_startFrame; cachedTex = texr->GetValueTexture(partFrame).GetObj(); - cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat); + cachedTex->Load(GX_TEXMAP0, EClampMode::Repeat); CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc); if (hasModuColor) { @@ -1271,46 +1271,46 @@ void CElementGen::RenderParticles() { } constexpr std::array vtxDescList{ - GX::VtxDescList{GX::VA_POS, GX::DIRECT}, - GX::VtxDescList{GX::VA_CLR0, GX::DIRECT}, - GX::VtxDescList{GX::VA_TEX0, GX::DIRECT}, - GX::VtxDescList{}, + GXVtxDescList{GX_VA_POS, GX_DIRECT}, + GXVtxDescList{GX_VA_CLR0, GX_DIRECT}, + GXVtxDescList{GX_VA_TEX0, GX_DIRECT}, + GXVtxDescList{GX_VA_NULL, GX_NONE}, }; CGX::SetVtxDescv(vtxDescList.data()); - GX::TevStageID nextStage; + GXTevStageID nextStage; if (hasModuColor) { CGX::SetNumChans(2); - nextStage = GX::TEVSTAGE2; - CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR1A1); + nextStage = GX_TEVSTAGE2; + CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR1A1); CGX::SetChanAmbColor(CGX::EChannelId::Channel1, zeus::skBlack); CGX::SetChanMatColor(CGX::EChannelId::Channel1, x338_moduColor); CGX::SetChanCtrl(CGX::EChannelId::Channel1, {}); } else { CGX::SetNumChans(1); - nextStage = GX::TEVSTAGE1; + nextStage = GX_TEVSTAGE1; } bool moveRedToAlphaBuffer = sMoveRedToAlphaBuffer; if (g_subtractBlend) { CGraphics::SetDepthWriteMode(x26c_28_zTest, ERglEnum::LEqual, false); - CGX::SetBlendMode(GX::BM_SUBTRACT, GX::BL_ONE, GX::BL_ZERO, GX::LO_CLEAR); + CGX::SetBlendMode(GX_BM_SUBTRACT, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR); if (moveRedToAlphaBuffer) { - CGX::SetTevColorIn(nextStage, GX::CC_ZERO, GX::CC_CPREV, GX::CC_APREV, GX::CC_ZERO); - CGX::SetTevAlphaIn(nextStage, GX::CA_ZERO, GX::CA_TEXA, GX::CA_APREV, GX::CA_ZERO); + CGX::SetTevColorIn(nextStage, GX_CC_ZERO, GX_CC_CPREV, GX_CC_APREV, GX_CC_ZERO); + CGX::SetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO); CGX::SetStandardTevColorAlphaOp(nextStage); - CGX::SetTevOrder(nextStage, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); - GXSetTevSwapMode(nextStage, GX::TEV_SWAP0, GX::TEV_SWAP1); - nextStage = GX::TevStageID(nextStage + 1); + CGX::SetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevSwapMode(nextStage, GX_TEV_SWAP0, GX_TEV_SWAP1); + nextStage = GXTevStageID(nextStage + 1); } } else if (moveRedToAlphaBuffer) { CGraphics::SetDepthWriteMode(x26c_28_zTest, ERglEnum::LEqual, false); CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear); - CGX::SetTevColorIn(nextStage, GX::CC_ZERO, GX::CC_CPREV, GX::CC_APREV, GX::CC_ZERO); - CGX::SetTevAlphaIn(nextStage, GX::CA_ZERO, GX::CA_TEXA, GX::CA_APREV, GX::CA_ZERO); + CGX::SetTevColorIn(nextStage, GX_CC_ZERO, GX_CC_CPREV, GX_CC_APREV, GX_CC_ZERO); + CGX::SetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO); CGX::SetStandardTevColorAlphaOp(nextStage); - CGX::SetTevOrder(nextStage, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); - GXSetTevSwapMode(nextStage, GX::TEV_SWAP0, GX::TEV_SWAP1); - nextStage = GX::TevStageID(nextStage + 1); + CGX::SetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevSwapMode(nextStage, GX_TEV_SWAP0, GX_TEV_SWAP1); + nextStage = GXTevStageID(nextStage + 1); } else if (x26c_26_AAPH) { CGraphics::SetDepthWriteMode(x26c_28_zTest, ERglEnum::LEqual, false); CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear); @@ -1321,22 +1321,22 @@ void CElementGen::RenderParticles() { } CGX::SetNumTevStages(nextStage); CGX::SetNumTexGens(1); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR0A0); - CGX::SetChanCtrl(CGX::EChannelId::Channel0, false, GX::SRC_REG, GX::SRC_VTX, {}, GX::DF_NONE, GX::AF_NONE); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); - GXSetVtxAttrFmt(GX::VTXFMT6, GX::VA_POS, GX::POS_XYZ, GX::F32, 0); - GXSetVtxAttrFmt(GX::VTXFMT6, GX::VA_CLR0, GX::CLR_RGBA, GX::RGBA8, 0); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + CGX::SetChanCtrl(CGX::EChannelId::Channel0, false, GX_SRC_REG, GX_SRC_VTX, {}, GX_DF_NONE, GX_AF_NONE); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); + GXSetVtxAttrFmt(GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT6, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); if (constUVs) { - GXSetVtxAttrFmt(GX::VTXFMT6, GX::VA_TEX0, GX::TEX_ST, GX::RGBA8, 1); + GXSetVtxAttrFmt(GX_VTXFMT6, GX_VA_TEX0, GX_TEX_ST, GX_RGBA8, 1); } else { - GXSetVtxAttrFmt(GX::VTXFMT6, GX::VA_TEX0, GX::TEX_ST, GX::F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT6, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); } int mbspVal = std::max(1, x270_MBSP); if (x26c_30_MBLR) { - CGX::Begin(GX::QUADS, GX::VTXFMT6, mbspVal * x30_particles.size() * 4); + CGX::Begin(GX_QUADS, GX_VTXFMT6, mbspVal * x30_particles.size() * 4); } else { - CGX::Begin(GX::QUADS, GX::VTXFMT6, mbspVal * 4); + CGX::Begin(GX_QUADS, GX_VTXFMT6, mbspVal * 4); } std::vector sortItems; @@ -1629,7 +1629,7 @@ void CElementGen::RenderParticles() { CGX::End(); if (moveRedToAlphaBuffer) { - GXSetTevSwapMode(GX::TevStageID(nextStage - 1), GX::TEV_SWAP0, GX::TEV_SWAP0); + GXSetTevSwapMode(GXTevStageID(nextStage - 1), GX_TEV_SWAP0, GX_TEV_SWAP0); } CGraphics::SetCullMode(ERglCullMode::Front); CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); @@ -1668,7 +1668,7 @@ void CElementGen::RenderParticlesIndirectTexture() { CParticle& firstParticle = x30_particles[0]; int partFrame = x74_curFrame - firstParticle.x28_startFrame; CTexture* cachedTex = texr->GetValueTexture(partFrame).GetObj(); - cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat); + cachedTex->Load(GX_TEXMAP0, EClampMode::Repeat); SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f}; bool constTexr = texr->HasConstantTexture(); @@ -1677,7 +1677,7 @@ void CElementGen::RenderParticlesIndirectTexture() { CUVElement* tind = desc->x58_x44_TIND.get(); CTexture* cachedIndTex = tind->GetValueTexture(partFrame).GetObj(); - cachedIndTex->Load(GX::TEXMAP2, EClampMode::Repeat); + cachedIndTex->Load(GX_TEXMAP2, EClampMode::Repeat); SUVElementSet uvsInd = {0.f, 0.f, 1.f, 1.f}; bool constIndTexr = tind->HasConstantTexture(); @@ -1724,7 +1724,7 @@ void CElementGen::RenderParticlesIndirectTexture() { if (!constTexr) { CTexture* tex = texr->GetValueTexture(thisPartFrame).GetObj(); if (tex != cachedTex) { - tex->Load(GX::TEXMAP0, EClampMode::Repeat); + tex->Load(GX_TEXMAP0, EClampMode::Repeat); cachedTex = tex; } } @@ -1732,7 +1732,7 @@ void CElementGen::RenderParticlesIndirectTexture() { if (!constIndTexr) { CTexture* tex = tind->GetValueTexture(thisPartFrame).GetObj(); if (tex != cachedIndTex) { - tex->Load(GX::TEXMAP2, EClampMode::Repeat); + tex->Load(GX_TEXMAP2, EClampMode::Repeat); cachedIndTex = tex; } } diff --git a/Runtime/Particle/CParticleElectric.cpp b/Runtime/Particle/CParticleElectric.cpp index 33a210705..db69fec33 100644 --- a/Runtime/Particle/CParticleElectric.cpp +++ b/Runtime/Particle/CParticleElectric.cpp @@ -93,22 +93,22 @@ void CParticleElectric::SetupLineGXMaterial() { void CParticleElectric::DrawLineStrip(const std::vector& verts, float width, const zeus::CColor& color) { - const size_t useIdx = m_nextLineRenderer; - if (++m_nextLineRenderer > m_lineRenderers.size()) { - m_lineRenderers.resize(m_nextLineRenderer); - } - if (!m_lineRenderers[useIdx]) { - m_lineRenderers[useIdx] = std::make_unique(CLineRenderer::EPrimitiveMode::LineStrip, x150_SSEG, - aurora::gfx::TextureHandle{}, true, true); - } - CLineRenderer& renderer = *m_lineRenderers[useIdx]; - const zeus::CColor useColor = x1b8_moduColor * color; - - renderer.Reset(); - for (const zeus::CVector3f& vert : verts) { - renderer.AddVertex(vert, useColor, width); - } - renderer.Render(); // g_Renderer->IsThermalVisorHotPass() +// const size_t useIdx = m_nextLineRenderer; +// if (++m_nextLineRenderer > m_lineRenderers.size()) { +// m_lineRenderers.resize(m_nextLineRenderer); +// } +// if (!m_lineRenderers[useIdx]) { +// m_lineRenderers[useIdx] = std::make_unique(CLineRenderer::EPrimitiveMode::LineStrip, x150_SSEG, +// aurora::gfx::TextureHandle{}, true, true); +// } +// CLineRenderer& renderer = *m_lineRenderers[useIdx]; +// const zeus::CColor useColor = x1b8_moduColor * color; +// +// renderer.Reset(); +// for (const zeus::CVector3f& vert : verts) { +// renderer.AddVertex(vert, useColor, width); +// } +// renderer.Render(); // g_Renderer->IsThermalVisorHotPass() } void CParticleElectric::RenderLines() { diff --git a/Runtime/Particle/CParticleSwoosh.cpp b/Runtime/Particle/CParticleSwoosh.cpp index 3f589088c..854d58809 100644 --- a/Runtime/Particle/CParticleSwoosh.cpp +++ b/Runtime/Particle/CParticleSwoosh.cpp @@ -306,10 +306,10 @@ int CParticleSwoosh::WrapIndex(int i) const { void CParticleSwoosh::RenderNSidedSpline() { if (x1c_desc->x44_29_WIRE) { - x1bc_prim = GX::LINES; + x1bc_prim = GX_LINES; m_lineRenderer->Reset(); } else { - x1bc_prim = GX::QUADS; + x1bc_prim = GX_QUADS; } bool cros = x1c_desc->x44_25_CROS; @@ -444,7 +444,7 @@ void CParticleSwoosh::RenderNSidedSpline() { const auto v2 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t1); const auto v3 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t1); - if (x1bc_prim == GX::LINES) { + if (x1bc_prim == GX_LINES) { m_lineRenderer->AddVertex(v0, color, 1.f); m_lineRenderer->AddVertex(v1, color, 1.f); m_lineRenderer->AddVertex(v1, color, 1.f); @@ -457,7 +457,7 @@ void CParticleSwoosh::RenderNSidedSpline() { m_lineRenderer->AddVertex(v3, color, 1.f); m_lineRenderer->AddVertex(v3, color, 1.f); m_lineRenderer->AddVertex(v0, color, 1.f); - } else if (x1bc_prim == GX::QUADS) { + } else if (x1bc_prim == GX_QUADS) { m_cachedVerts.push_back({v0, {x1d4_uvs.xMin, x1d4_uvs.yMin}, color}); m_cachedVerts.push_back({v1, {x1d4_uvs.xMin, x1d4_uvs.yMax}, color}); m_cachedVerts.push_back({v2, {x1d4_uvs.xMax, x1d4_uvs.yMin}, color}); @@ -478,7 +478,7 @@ void CParticleSwoosh::RenderNSidedSpline() { } } - if (x1bc_prim == GX::LINES) { + if (x1bc_prim == GX_LINES) { // m_lineRenderer->Render(g_Renderer->IsThermalVisorHotPass()); } } diff --git a/Runtime/Particle/CParticleSwoosh.hpp b/Runtime/Particle/CParticleSwoosh.hpp index 958246a7e..89fd56527 100644 --- a/Runtime/Particle/CParticleSwoosh.hpp +++ b/Runtime/Particle/CParticleSwoosh.hpp @@ -78,7 +78,7 @@ private: int x1b0_SPLN = 0; int x1b4_LENG = 0; int x1b8_SIDE = 0; - GX::Primitive x1bc_prim{}; + GXPrimitive x1bc_prim{}; CRandom16 x1c0_rand; float x1c4_ = 0.f; float x1c8_ = 0.f; diff --git a/Runtime/Weapon/CPlasmaProjectile.cpp b/Runtime/Weapon/CPlasmaProjectile.cpp index 1ba10e1bc..c26dd4747 100644 --- a/Runtime/Weapon/CPlasmaProjectile.cpp +++ b/Runtime/Weapon/CPlasmaProjectile.cpp @@ -12,16 +12,16 @@ namespace metaforce { -CPlasmaProjectile::RenderObjects::RenderObjects(aurora::gfx::TextureHandle tex, aurora::gfx::TextureHandle glowTex) -: m_beamStrip1(8, CColoredStripShader::Mode::Additive, {}) -, m_beamStrip2(10, CColoredStripShader::Mode::FullAdditive, tex) -, m_beamStrip3(18, CColoredStripShader::Mode::FullAdditive, tex) -, m_beamStrip4(14, CColoredStripShader::Mode::Additive, glowTex) -, m_beamStrip1Sub(8, CColoredStripShader::Mode::Subtractive, {}) -, m_beamStrip2Sub(10, CColoredStripShader::Mode::Subtractive, tex) -, m_beamStrip3Sub(18, CColoredStripShader::Mode::Subtractive, tex) -, m_beamStrip4Sub(14, CColoredStripShader::Mode::Subtractive, glowTex) -, m_motionBlurStrip(16, CColoredStripShader::Mode::Alpha, {}) {} +//CPlasmaProjectile::RenderObjects::RenderObjects(aurora::gfx::TextureHandle tex, aurora::gfx::TextureHandle glowTex) +//: m_beamStrip1(8, CColoredStripShader::Mode::Additive, {}) +//, m_beamStrip2(10, CColoredStripShader::Mode::FullAdditive, tex) +//, m_beamStrip3(18, CColoredStripShader::Mode::FullAdditive, tex) +//, m_beamStrip4(14, CColoredStripShader::Mode::Additive, glowTex) +//, m_beamStrip1Sub(8, CColoredStripShader::Mode::Subtractive, {}) +//, m_beamStrip2Sub(10, CColoredStripShader::Mode::Subtractive, tex) +//, m_beamStrip3Sub(18, CColoredStripShader::Mode::Subtractive, tex) +//, m_beamStrip4Sub(14, CColoredStripShader::Mode::Subtractive, glowTex) +//, m_motionBlurStrip(16, CColoredStripShader::Mode::Alpha, {}) {} CPlasmaProjectile::CPlasmaProjectile(const TToken& wDesc, std::string_view name, EWeaponType wType, const CBeamInfo& bInfo, const zeus::CTransform& xf, EMaterialTypes matType, @@ -148,7 +148,7 @@ void CPlasmaProjectile::RenderMotionBlur() { v2.m_pos = GetPointCache()[i]; v2.m_color = v1.m_color; } - m_renderObjs->m_motionBlurStrip.draw(zeus::skWhite, verts.size(), verts.data()); +// m_renderObjs->m_motionBlurStrip.draw(zeus::skWhite, verts.size(), verts.data()); } void CPlasmaProjectile::RenderBeam(s32 subdivs, float width, const zeus::CColor& color, s32 flags, @@ -401,6 +401,8 @@ void CPlasmaProjectile::AddToRenderer(const zeus::CFrustum& frustum, CStateManag void CPlasmaProjectile::Render(CStateManager& mgr) { if (!GetActive()) return; + + // TODO SCOPED_GRAPHICS_DEBUG_GROUP("CPlasmaProjectile::Render", zeus::skOrange); zeus::CTransform xf = GetBeamTransform(); @@ -418,23 +420,23 @@ void CPlasmaProjectile::Render(CStateManager& mgr) { // Pass1: alpha-controlled additive CGraphics::SetModelMatrix(xf); - RenderBeam(3, 0.25f * x4b8_beamWidth, zeus::CColor(1.f, 0.3f), flags | 0x4, - (flags & 0x10) ? m_renderObjs->m_beamStrip1Sub : m_renderObjs->m_beamStrip1); +// RenderBeam(3, 0.25f * x4b8_beamWidth, zeus::CColor(1.f, 0.3f), flags | 0x4, +// (flags & 0x10) ? m_renderObjs->m_beamStrip1Sub : m_renderObjs->m_beamStrip1); // Pass2: textured CGraphics::SetModelMatrix(xf * zeus::CTransform::RotateY(zeus::degToRad(x4c8_beamAngle))); - RenderBeam(4, 0.5f * x4b8_beamWidth, x490_innerColor, flags | 0x1, - (flags & 0x10) ? m_renderObjs->m_beamStrip2Sub : m_renderObjs->m_beamStrip2); +// RenderBeam(4, 0.5f * x4b8_beamWidth, x490_innerColor, flags | 0x1, +// (flags & 0x10) ? m_renderObjs->m_beamStrip2Sub : m_renderObjs->m_beamStrip2); // Pass3: textured | length-controlled UVY CGraphics::SetModelMatrix(xf * zeus::CTransform::RotateY(zeus::degToRad(-x4c8_beamAngle))); - RenderBeam(8, x4b8_beamWidth, x494_outerColor, flags | 0x3, - (flags & 0x10) ? m_renderObjs->m_beamStrip3Sub : m_renderObjs->m_beamStrip3); +// RenderBeam(8, x4b8_beamWidth, x494_outerColor, flags | 0x3, +// (flags & 0x10) ? m_renderObjs->m_beamStrip3Sub : m_renderObjs->m_beamStrip3); // Pass4: textured | alpha-controlled additive | glow texture CGraphics::SetModelMatrix(xf); - RenderBeam(6, 1.25f * x4b8_beamWidth, x494_outerColor, flags | 0xd, - (flags & 0x10) ? m_renderObjs->m_beamStrip4Sub : m_renderObjs->m_beamStrip4); +// RenderBeam(6, 1.25f * x4b8_beamWidth, x494_outerColor, flags | 0xd, +// (flags & 0x10) ? m_renderObjs->m_beamStrip4Sub : m_renderObjs->m_beamStrip4); } } // namespace metaforce diff --git a/Runtime/Weapon/CPlasmaProjectile.hpp b/Runtime/Weapon/CPlasmaProjectile.hpp index 36082353a..f492273fd 100644 --- a/Runtime/Weapon/CPlasmaProjectile.hpp +++ b/Runtime/Weapon/CPlasmaProjectile.hpp @@ -81,19 +81,19 @@ private: bool x548_28_drawOwnerFirst : 1; bool x548_29_activePlayerPhazon : 1 = false; - struct RenderObjects { - CColoredStripShader m_beamStrip1; - CColoredStripShader m_beamStrip2; - CColoredStripShader m_beamStrip3; - CColoredStripShader m_beamStrip4; - CColoredStripShader m_beamStrip1Sub; - CColoredStripShader m_beamStrip2Sub; - CColoredStripShader m_beamStrip3Sub; - CColoredStripShader m_beamStrip4Sub; - CColoredStripShader m_motionBlurStrip; - RenderObjects(aurora::gfx::TextureHandle tex, aurora::gfx::TextureHandle glowTex); - }; - std::optional m_renderObjs; +// struct RenderObjects { +// CColoredStripShader m_beamStrip1; +// CColoredStripShader m_beamStrip2; +// CColoredStripShader m_beamStrip3; +// CColoredStripShader m_beamStrip4; +// CColoredStripShader m_beamStrip1Sub; +// CColoredStripShader m_beamStrip2Sub; +// CColoredStripShader m_beamStrip3Sub; +// CColoredStripShader m_beamStrip4Sub; +// CColoredStripShader m_motionBlurStrip; +// RenderObjects(CTexture& tex, CTexture& glowTex); +// }; +// std::optional m_renderObjs; void SetLightsActive(bool active, CStateManager& mgr); void CreatePlasmaLights(u32 sourceId, const CLight& l, CStateManager& mgr); diff --git a/Runtime/Weapon/CPlayerGun.cpp b/Runtime/Weapon/CPlayerGun.cpp index 569b27e3a..6c05ce5e5 100644 --- a/Runtime/Weapon/CPlayerGun.cpp +++ b/Runtime/Weapon/CPlayerGun.cpp @@ -2134,7 +2134,7 @@ zeus::CVector3f CPlayerGun::ConvertToScreenSpace(const zeus::CVector3f& pos, con void CPlayerGun::CopyScreenTex() { // Copy lower right quadrant to gpCopyTexBuf as RGBA8 // GXSetTexCopySrc(320, 224, 320, 224); - // GXSetTexCopyDst(320, 224, GX::TF_RGBA8, false); + // GXSetTexCopyDst(320, 224, GX_TF_RGBA8, false); // GXCopyTex(sSpareTextureData, false); // GXPixModeSync(); SViewport viewport = CGraphics::g_Viewport; @@ -2144,7 +2144,7 @@ void CPlayerGun::CopyScreenTex() { viewport.x4_top = viewport.xc_height; viewport.x10_halfWidth *= 0.5f; viewport.x14_halfHeight *= 0.5f; - CGraphics::ResolveSpareTexture(viewport, 2, GX::TF_RGBA8, false); + CGraphics::ResolveSpareTexture(viewport, 2, GX_TF_RGBA8, false); } void CPlayerGun::DrawScreenTex(float z) { @@ -2156,19 +2156,19 @@ void CPlayerGun::DrawScreenTex(float z) { g_Renderer->SetViewportOrtho(false, -1.f, 1.f); g_Renderer->SetBlendMode_AlphaBlended(); CGraphics::SetDepthWriteMode(true, ERglEnum::GEqual, true); - CGraphics::LoadDolphinSpareTexture(2, GX::TF_RGBA8, GX::TEXMAP7); + CGraphics::LoadDolphinSpareTexture(2, GX_TF_RGBA8, GX_TEXMAP7); constexpr std::array vtxDescList{ - GX::VtxDescList{GX::VA_POS, GX::DIRECT}, - GX::VtxDescList{GX::VA_TEX0, GX::DIRECT}, - GX::VtxDescList{}, + GXVtxDescList{GX_VA_POS, GX_DIRECT}, + GXVtxDescList{GX_VA_TEX0, GX_DIRECT}, + GXVtxDescList{GX_VA_NULL, GX_NONE}, }; CGX::SetVtxDescv(vtxDescList.data()); CGX::SetNumChans(0); CGX::SetNumTexGens(1); CGX::SetNumTevStages(1); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP7, GX::COLOR_NULL); - CGX::SetChanCtrl(CGX::EChannelId::Channel0, false, GX::SRC_REG, GX::SRC_REG, {}, GX::DF_NONE, GX::AF_NONE); - CGX::Begin(GX::TRIANGLESTRIP, GX::VTXFMT0, 4); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP7, GX_COLOR_NULL); + CGX::SetChanCtrl(CGX::EChannelId::Channel0, false, GX_SRC_REG, GX_SRC_REG, {}, GX_DF_NONE, GX_AF_NONE); + CGX::Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 4); GXPosition3f32(CGraphics::g_Viewport.x10_halfWidth, z, 0.f); GXTexCoord2f32(0.f, 1.f); GXPosition3f32(CGraphics::g_Viewport.x8_width, z, 0.f); diff --git a/Runtime/World/CActor.hpp b/Runtime/World/CActor.hpp index f828d2700..0f364e2c8 100644 --- a/Runtime/World/CActor.hpp +++ b/Runtime/World/CActor.hpp @@ -75,7 +75,7 @@ protected: bool xe7_30_doTargetDistanceTest : 1 = true; bool xe7_31_targetable : 1 = true; - aurora::gfx::TextureHandle m_reflectionCube; + GXTexObj m_reflectionCube; zeus::CColor m_debugAddColor = zeus::skClear; float m_debugAddColorTime = 0.f; diff --git a/Runtime/World/CFluidPlaneCPU.cpp b/Runtime/World/CFluidPlaneCPU.cpp index 1e4dd4045..e5bf24c76 100644 --- a/Runtime/World/CFluidPlaneCPU.cpp +++ b/Runtime/World/CFluidPlaneCPU.cpp @@ -269,10 +269,10 @@ CFluidPlaneShader::RenderSetupInfo CFluidPlaneCPU::RenderSetup(const CStateManag m_cachedAdditive != (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot)) { m_cachedDoubleLightmapBlend = doubleLightmapBlend; m_cachedAdditive = mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot; - m_shader.emplace(x44_fluidType, x10_texPattern1, x20_texPattern2, x30_texColor, xb0_bumpMap, xc0_envMap, - xd0_envBumpMap, xe0_lightmap, - m_tessellation ? CFluidPlaneManager::RippleMapTex : aurora::gfx::TextureHandle{}, - m_cachedDoubleLightmapBlend, m_cachedAdditive, m_maxVertCount); +// m_shader.emplace(x44_fluidType, x10_texPattern1, x20_texPattern2, x30_texColor, xb0_bumpMap, xc0_envMap, +// xd0_envBumpMap, xe0_lightmap, +// m_tessellation ? CFluidPlaneManager::RippleMapTex : aurora::gfx::TextureHandle{}, +// m_cachedDoubleLightmapBlend, m_cachedAdditive, m_maxVertCount); } return out; diff --git a/Runtime/World/CFluidPlaneManager.cpp b/Runtime/World/CFluidPlaneManager.cpp index 6eb3eb516..b5b1964f7 100644 --- a/Runtime/World/CFluidPlaneManager.cpp +++ b/Runtime/World/CFluidPlaneManager.cpp @@ -81,7 +81,7 @@ static bool g_RippleMapSetup = false; std::array, 64> CFluidPlaneManager::RippleValues{}; std::array CFluidPlaneManager::RippleMins{}; std::array CFluidPlaneManager::RippleMaxs{}; -aurora::gfx::TextureHandle CFluidPlaneManager::RippleMapTex; +GXTexObj CFluidPlaneManager::RippleMapTex; void CFluidPlaneManager::SetupRippleMap() { if (g_RippleMapSetup) { @@ -135,13 +135,9 @@ void CFluidPlaneManager::SetupRippleMap() { curX += (1.f / 63.f); } - RippleMapTex = aurora::gfx::new_static_texture_2d(64, 64, 1, GX::TF_I8, - {reinterpret_cast(RippleValues.data()), 64 * 64}, - "Ripple Map"); + GXInitTexObj(&RippleMapTex, RippleValues.data(), 64, 64, GX_TF_R8_PC, GX_REPEAT, GX_REPEAT, false); } -void CFluidPlaneManager::Shutdown() { - RippleMapTex.reset(); -} +void CFluidPlaneManager::Shutdown() { GXDestroyTexObj(&RippleMapTex); } } // namespace metaforce diff --git a/Runtime/World/CFluidPlaneManager.hpp b/Runtime/World/CFluidPlaneManager.hpp index fae754e1c..e2e92a4db 100644 --- a/Runtime/World/CFluidPlaneManager.hpp +++ b/Runtime/World/CFluidPlaneManager.hpp @@ -46,7 +46,7 @@ public: static std::array, 64> RippleValues; static std::array RippleMins; static std::array RippleMaxs; - static aurora::gfx::TextureHandle RippleMapTex; + static GXTexObj RippleMapTex; CFluidPlaneManager(); void StartFrame(bool); diff --git a/Runtime/World/CVisorFlare.cpp b/Runtime/World/CVisorFlare.cpp index 2d340f67a..70b60b375 100644 --- a/Runtime/World/CVisorFlare.cpp +++ b/Runtime/World/CVisorFlare.cpp @@ -128,7 +128,7 @@ void CVisorFlare::Render(const zeus::CVector3f& pos, const CStateManager& mgr) c } } if (item.GetTexture()) { - item.GetTexture()->Load(GX::TEXMAP0, EClampMode::Repeat); + item.GetTexture()->Load(GX_TEXMAP0, EClampMode::Repeat); float f1; if (zeus::close_enough(acos, 0.f)) { f1 = 0.f; @@ -149,31 +149,31 @@ void CVisorFlare::Render(const zeus::CVector3f& pos, const CStateManager& mgr) c void CVisorFlare::SetupRenderState(const CStateManager& mgr) const { if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot) { - CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ONE, GX::BL_ONE, GX::LO_CLEAR); - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); - CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); - CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_OR, GX::ALWAYS, 0); - GXSetTevSwapMode(GX::TEVSTAGE0, GX::TEV_SWAP0, GX::TEV_SWAP1); - CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0_A); - CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A); - CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, GX::CC_ZERO); - CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, GX::CA_ZERO); + CGX::SetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + CGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP1); + CGX::SetTevKColorSel(GX_TEVSTAGE0, GX_TEV_KCSEL_K0_A); + CGX::SetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K0_A); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_KONST, GX_CC_ZERO); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_KONST, GX_CA_ZERO); CGX::SetNumTexGens(1); CGX::SetNumChans(0); - CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY); if (x0_blendMode == EBlendMode::Blend) { - CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE1); - CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); - CGX::SetTevColorIn(GX::TEVSTAGE1, GX::CC_ZERO, GX::CC_TEXA, GX::CC_CPREV, GX::CC_ZERO); - CGX::SetTevAlphaIn(GX::TEVSTAGE1, GX::CA_ZERO, GX::CA_TEXA, GX::CA_APREV, GX::CA_ZERO); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE1); + CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + CGX::SetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_TEXA, GX_CC_CPREV, GX_CC_ZERO); + CGX::SetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO); CGX::SetNumTevStages(2); } else if (x0_blendMode == EBlendMode::Additive) { CGX::SetNumTevStages(1); } constexpr std::array vtxDescList{ - GX::VtxDescList{GX::VA_POS, GX::DIRECT}, - GX::VtxDescList{GX::VA_TEX0, GX::DIRECT}, - GX::VtxDescList{}, + GXVtxDescList{GX_VA_POS, GX_DIRECT}, + GXVtxDescList{GX_VA_TEX0, GX_DIRECT}, + GXVtxDescList{GX_VA_NULL, GX_NONE}, }; CGX::SetVtxDescv(vtxDescList.data()); } else { @@ -189,15 +189,15 @@ void CVisorFlare::SetupRenderState(const CStateManager& mgr) const { void CVisorFlare::ResetTevSwapMode(const CStateManager& mgr) const { if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot) { - GXSetTevSwapMode(GX::TEVSTAGE0, GX::TEV_SWAP0, GX::TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); } } void CVisorFlare::DrawDirect(const zeus::CColor& color, float f1, float f2) const { zeus::CColor kcolor = color; - kcolor.a() *= x24_; - CGX::SetTevKColor(GX::KCOLOR0, kcolor); - CGX::Begin(GX::TRIANGLESTRIP, GX::VTXFMT0, 4); + kcolor.a() *= x24_; // TODO i think this is wrong + CGX::SetTevKColor(GX_KCOLOR0, kcolor); + CGX::Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 4); GXPosition3f32(f1 - f2, 0.f, f2 + f1); GXTexCoord2f32(0.f, 1.f); GXPosition3f32(f2 + f1, 0.f, f2 - f1); @@ -210,7 +210,7 @@ void CVisorFlare::DrawDirect(const zeus::CColor& color, float f1, float f2) cons } void CVisorFlare::DrawStreamed(const zeus::CColor& color, float f1, float f2) const { - CGraphics::StreamBegin(GX::TRIANGLESTRIP); + CGraphics::StreamBegin(GX_TRIANGLESTRIP); zeus::CColor kcolor = color; kcolor.a() *= x24_; CGraphics::StreamColor(kcolor); diff --git a/Runtime/World/CWorldShadow.cpp b/Runtime/World/CWorldShadow.cpp index 55c372bab..c15525254 100644 --- a/Runtime/World/CWorldShadow.cpp +++ b/Runtime/World/CWorldShadow.cpp @@ -99,7 +99,7 @@ void CWorldShadow::BuildLightShadowTexture(const CStateManager& mgr, TAreaId aid ERglLogicOp::Clear); CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassThru); CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); - CGraphics::StreamBegin(GX::TRIANGLESTRIP); + CGraphics::StreamBegin(GX_TRIANGLESTRIP); CGraphics::StreamColor(1.f, 1.f, 1.f, 0.25f); CGraphics::StreamVertex(-extent, 0.f, extent); CGraphics::StreamVertex(extent, 0.f, extent); diff --git a/aurora/CMakeLists.txt b/aurora/CMakeLists.txt deleted file mode 100644 index 40498711c..000000000 --- a/aurora/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -add_library(aurora STATIC - lib/aurora.cpp - lib/gpu.cpp - lib/imgui.cpp - lib/input.cpp - lib/dawn/BackendBinding.cpp - lib/gfx/common.cpp - lib/gfx/texture.cpp - lib/gfx/stream.cpp - lib/gfx/gx.cpp - lib/gfx/gx_shader.cpp - lib/gfx/texture_convert.cpp - lib/gfx/movie_player/shader.cpp - lib/gfx/stream/shader.cpp - lib/gfx/model/shader.cpp - ) -target_compile_definitions(aurora PRIVATE IMGUI_USER_CONFIG="imconfig_user.h") # IMGUI_USE_WCHAR32 -target_include_directories(aurora PUBLIC include ../) -target_include_directories(aurora PRIVATE ../imgui ../extern/imgui) -if(NOT TARGET SDL2::SDL2-static) - find_package(SDL2 REQUIRED) -endif() -target_link_libraries(aurora PRIVATE dawn_native dawncpp webgpu_dawn zeus logvisor SDL2::SDL2-static xxhash - absl::btree absl::flat_hash_map) -if (DAWN_ENABLE_VULKAN) - target_compile_definitions(aurora PRIVATE DAWN_ENABLE_BACKEND_VULKAN) - target_sources(aurora PRIVATE lib/dawn/VulkanBinding.cpp) -endif () -if (DAWN_ENABLE_METAL) - target_compile_definitions(aurora PRIVATE DAWN_ENABLE_BACKEND_METAL) - target_sources(aurora PRIVATE lib/dawn/MetalBinding.mm) - set_source_files_properties(lib/dawn/MetalBinding.mm PROPERTIES COMPILE_FLAGS -fobjc-arc) -endif () -if (DAWN_ENABLE_D3D12) - target_compile_definitions(aurora PRIVATE DAWN_ENABLE_BACKEND_D3D12) - target_sources(aurora PRIVATE lib/dawn/D3D12Binding.cpp) -endif () -if (DAWN_ENABLE_DESKTOP_GL) - target_compile_definitions(aurora PRIVATE DAWN_ENABLE_BACKEND_OPENGL DAWN_ENABLE_BACKEND_DESKTOP_GL) - target_sources(aurora PRIVATE lib/dawn/OpenGLBinding.cpp) -endif () -if (DAWN_ENABLE_NULL) - target_compile_definitions(aurora PRIVATE DAWN_ENABLE_BACKEND_NULL) - target_sources(aurora PRIVATE lib/dawn/NullBinding.cpp) -endif () diff --git a/aurora/include/aurora/aurora.hpp b/aurora/include/aurora/aurora.hpp deleted file mode 100644 index 609e4c2a4..000000000 --- a/aurora/include/aurora/aurora.hpp +++ /dev/null @@ -1,271 +0,0 @@ -#pragma once - -#include "common.hpp" - -#include -#include -#include -#include -#include -#ifndef ENABLE_BITWISE_ENUM -#define ENABLE_BITWISE_ENUM(type) \ - constexpr type operator|(type a, type b) noexcept { \ - using T = std::underlying_type_t; \ - return type(static_cast(a) | static_cast(b)); \ - } \ - constexpr type operator&(type a, type b) noexcept { \ - using T = std::underlying_type_t; \ - return type(static_cast(a) & static_cast(b)); \ - } \ - constexpr type& operator|=(type& a, type b) noexcept { \ - using T = std::underlying_type_t; \ - a = type(static_cast(a) | static_cast(b)); \ - return a; \ - } \ - constexpr type& operator&=(type& a, type b) noexcept { \ - using T = std::underlying_type_t; \ - a = type(static_cast(a) & static_cast(b)); \ - return a; \ - } \ - constexpr type operator~(type key) noexcept { \ - using T = std::underlying_type_t; \ - return type(~static_cast(key)); \ - } \ - constexpr bool True(type key) noexcept { \ - using T = std::underlying_type_t; \ - return static_cast(key) != 0; \ - } \ - constexpr bool False(type key) noexcept { \ - using T = std::underlying_type_t; \ - return static_cast(key) == 0; \ - } -#endif - -namespace aurora { -enum class SpecialKey : uint8_t { - None = 0, - F1 = 1, - F2 = 2, - F3 = 3, - F4 = 4, - F5 = 5, - F6 = 6, - F7 = 7, - F8 = 8, - F9 = 9, - F10 = 10, - F11 = 11, - F12 = 12, - F13 = 13, - F14 = 14, - F15 = 15, - F16 = 16, - F17 = 17, - F18 = 18, - F19 = 19, - F20 = 20, - F21 = 21, - F22 = 22, - F23 = 23, - F24 = 24, - Esc = 25, - Enter = 26, - Backspace = 27, - Insert = 28, - Delete = 29, - Home = 30, - End = 31, - PgUp = 32, - PgDown = 33, - Left = 34, - Right = 35, - Up = 36, - Down = 37, - Tab = 38, - PrintScreen = 39, - ScrollLock = 40, - Pause = 41, - NumLockClear = 42, - KpDivide = 43, - KpMultiply = 44, - KpMinus = 45, - KpPlus = 46, - KpEnter = 47, - KpNum0 = 48, - KpNum1 = 49, - KpNum2 = 50, - KpNum3 = 51, - KpNum4 = 52, - KpNum5 = 53, - KpNum6 = 54, - KpNum7 = 55, - KpNum8 = 56, - KpNum9 = 57, - KpPercent = 58, - KpPeriod = 59, - KpComma = 60, - KpEquals = 61, - Application = 62, - Power = 63, - Execute = 64, - Help = 65, - Menu = 66, - Select = 67, - Stop = 68, - Again = 69, - Undo = 70, - Cut = 71, - Paste = 72, - Find = 73, - VolumeUp = 74, - VolumeDown = 75, - MAX, -}; -enum class ModifierKey : uint16_t { - None = 0, - LeftShift = 1 << 0, - RightShift = 1 << 1, - LeftControl = 1 << 2, - RightControl = 1 << 3, - LeftAlt = 1 << 3, - RightAlt = 1 << 4, - LeftGui = 1 << 5, - RightGui = 1 << 6, - Num = 1 << 7, - Caps = 1 << 8, - Mode = 1 << 9, - // SDL has a reserved value we don't need -}; -ENABLE_BITWISE_ENUM(ModifierKey); - -enum class ControllerButton : uint8_t { - A, - B, - X, - Y, - Back, - Guide, - Start, - LeftStick, - RightStick, - LeftShoulder, - RightShoulder, - DPadUp, - DPadDown, - DPadLeft, - DPadRight, - Other, - MAX, -}; -enum class ControllerAxis : uint8_t { - LeftX, - LeftY, - RightX, - RightY, - TriggerLeft, - TriggerRight, - MAX, -}; -struct Icon { - std::unique_ptr data; - uint32_t width; - uint32_t height; -}; -struct WindowSize { - uint32_t width; - uint32_t height; - uint32_t fb_width; - uint32_t fb_height; - float scale; - - bool operator==(const WindowSize& rhs) const { - return width == rhs.width && height == rhs.height && fb_width == rhs.fb_width && fb_height == rhs.fb_height && - scale == rhs.scale; - } -}; -enum class MouseButton { - None = 0, - Primary = 1 << 0, - Middle = 1 << 1, - Secondary = 1 << 2, - Aux1 = 1 << 3, - Aux2 = 1 << 4, -}; -ENABLE_BITWISE_ENUM(MouseButton); - -enum class Backend : uint8_t { - Null, - WebGPU, - D3D11, - D3D12, - Metal, - Vulkan, - OpenGL, - OpenGLES, - Invalid = 0xFF, -}; - -struct AppDelegate { - AppDelegate() = default; - virtual ~AppDelegate() noexcept = default; - AppDelegate(const AppDelegate&) = delete; - AppDelegate& operator=(const AppDelegate&) = delete; - AppDelegate(AppDelegate&&) = delete; - AppDelegate& operator=(AppDelegate&&) = delete; - - virtual void onAppLaunched() noexcept = 0; - virtual bool onAppIdle(float dt) noexcept = 0; - virtual void onAppDraw() noexcept = 0; - virtual void onAppPostDraw() noexcept = 0; - virtual void onAppWindowResized(const WindowSize& size) noexcept = 0; - virtual void onAppWindowMoved(int32_t x, int32_t y) noexcept = 0; - virtual void onAppDisplayScaleChanged(float scale) noexcept = 0; - virtual void onAppExiting() noexcept = 0; - - // ImGui - virtual void onImGuiInit(float scale) noexcept = 0; - virtual void onImGuiAddTextures() noexcept = 0; - - // Input - virtual void onCharKeyDown(uint8_t charCode, ModifierKey mods, bool isRepeat) noexcept = 0; - virtual void onCharKeyUp(uint8_t charCode, ModifierKey mods) noexcept = 0; - virtual void onSpecialKeyDown(SpecialKey key, ModifierKey mods, bool isRepeat) noexcept = 0; - virtual void onSpecialKeyUp(SpecialKey key, ModifierKey mods) noexcept = 0; - virtual void onModifierKeyDown(ModifierKey mods, bool isRepeat) noexcept = 0; - virtual void onModifierKeyUp(ModifierKey mods) noexcept = 0; - virtual void onTextInput(const std::string& input) noexcept = 0; - virtual void onMouseMove(int32_t x, int32_t y, int32_t xrel, int32_t yrel, MouseButton state) noexcept = 0; - virtual void onMouseButtonDown(int32_t x, int32_t y, MouseButton button, int32_t clicks) noexcept = 0; - virtual void onMouseButtonUp(int32_t x, int32_t y, MouseButton button) noexcept = 0; - - // Controller - virtual void onControllerAdded(uint32_t which) noexcept = 0; - virtual void onControllerRemoved(uint32_t which) noexcept = 0; - virtual void onControllerButton(uint32_t which, ControllerButton button, bool pressed) noexcept = 0; - virtual void onControllerAxis(uint32_t which, ControllerAxis axis, int16_t value) noexcept = 0; -}; - -void app_run(std::unique_ptr app, Icon icon, int argc, char** argv, std::string_view configPath, - Backend desiredBackend = Backend::Invalid, uint32_t msaa = 1, uint16_t aniso = 16, - bool fullscreen = false) noexcept; -[[nodiscard]] std::vector get_args() noexcept; -[[nodiscard]] WindowSize get_window_size() noexcept; -void set_window_title(zstring_view title) noexcept; -[[nodiscard]] Backend get_backend() noexcept; -[[nodiscard]] std::vector get_available_backends() noexcept; -[[nodiscard]] std::string_view get_backend_string() noexcept; -[[nodiscard]] Backend backend_from_string(std::string_view name); -[[nodiscard]] std::string_view backend_to_string(Backend backend); -void set_fullscreen(bool fullscreen) noexcept; -bool is_fullscreen() noexcept; -[[nodiscard]] uint32_t get_which_controller_for_player(int32_t index) noexcept; -[[nodiscard]] int32_t get_controller_player_index(uint32_t which) noexcept; -void set_controller_player_index(uint32_t which, int32_t index) noexcept; -[[nodiscard]] bool is_controller_gamecube(uint32_t which) noexcept; -[[nodiscard]] bool controller_has_rumble(uint32_t which) noexcept; -void controller_rumble(uint32_t which, uint16_t low_freq_intensity, uint16_t high_freq_intensity, - uint32_t duration_ms = 0) noexcept; - -uint32_t get_controller_count() noexcept; -[[nodiscard]] std::string get_controller_name(uint32_t which) noexcept; -} // namespace aurora diff --git a/aurora/include/aurora/common.hpp b/aurora/include/aurora/common.hpp deleted file mode 100644 index 9710ac543..000000000 --- a/aurora/include/aurora/common.hpp +++ /dev/null @@ -1,549 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "Runtime/RetroTypes.hpp" - -#include - -namespace aurora { -template -struct Vec2 { - T x{}; - T y{}; - - constexpr Vec2() = default; - constexpr Vec2(T x, T y) : x(x), y(y) {} - constexpr Vec2(const zeus::CVector2f& vec) : x(vec.x()), y(vec.y()) {} - - bool operator==(const Vec2& rhs) const { return x == rhs.x && y == rhs.y; } -}; -template -struct Vec3 { - T x{}; - T y{}; - T z{}; - - constexpr Vec3() = default; - constexpr Vec3(T x, T y, T z) : x(x), y(y), z(z) {} - constexpr Vec3(const zeus::CVector3f& vec) : x(vec.x()), y(vec.y()), z(vec.z()) {} - operator zeus::CVector3f() const { return {x, y, z}; } - - bool operator==(const Vec3& rhs) const { return x == rhs.x && y == rhs.y && z == rhs.z; } -}; -template -struct Vec4 { - T x{}; - T y{}; - T z{}; - T w{}; - - constexpr Vec4() = default; - constexpr Vec4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {} - constexpr Vec4(const zeus::CVector4f& vec) : x(vec.x()), y(vec.y()), z(vec.z()), w(vec.w()) {} - constexpr Vec4(const zeus::CColor& color) : x(color.r()), y(color.g()), z(color.b()), w(color.a()) {} - - bool operator==(const Vec4& rhs) const { return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; } -}; -template -struct Mat3x2 { - Vec2 m0{}; - Vec2 m1{}; - Vec2 m2{}; - - constexpr Mat3x2() = default; - constexpr Mat3x2(const Vec2& m0, const Vec2& m1, const Vec2& m2) : m0(m0), m1(m1), m2(m2) {} - - bool operator==(const Mat3x2& rhs) const { return m0 == rhs.m0 && m1 == rhs.m1 && m2 == rhs.m2; } -}; -template -struct Mat4x2 { - Vec2 m0{}; - Vec2 m1{}; - Vec2 m2{}; - Vec2 m3{}; - - constexpr Mat4x2() = default; - constexpr Mat4x2(const Vec2& m0, const Vec2& m1, const Vec2& m2, const Vec2& m3) - : m0(m0), m1(m1), m2(m2), m3(m3) {} - - bool operator==(const Mat4x2& rhs) const { return m0 == rhs.m0 && m1 == rhs.m1 && m2 == rhs.m2 && m3 == rhs.m3; } -}; -template -struct Mat4x4 { - Vec4 m0{}; - Vec4 m1{}; - Vec4 m2{}; - Vec4 m3{}; - - constexpr Mat4x4() = default; - constexpr Mat4x4(const Vec4& m0, const Vec4& m1, const Vec4& m2, const Vec4& m3) - : m0(m0), m1(m1), m2(m2), m3(m3) {} - constexpr Mat4x4(const zeus::CMatrix4f& m) : m0(m[0]), m1(m[1]), m2(m[2]), m3(m[3]) {} - constexpr Mat4x4(const zeus::CTransform& m) : Mat4x4(m.toMatrix4f()) {} - - bool operator==(const Mat4x4& rhs) const { return m0 == rhs.m0 && m1 == rhs.m1 && m2 == rhs.m2 && m3 == rhs.m3; } -}; -constexpr Mat4x4 Mat4x4_Identity{ - Vec4{1.f, 0.f, 0.f, 0.f}, - Vec4{0.f, 1.f, 0.f, 0.f}, - Vec4{0.f, 0.f, 1.f, 0.f}, - Vec4{0.f, 0.f, 0.f, 1.f}, -}; - -template -class ArrayRef { -public: - using value_type = std::remove_cvref_t; - using pointer = value_type*; - using const_pointer = const value_type*; - using reference = value_type&; - using const_reference = const value_type&; - using iterator = const_pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - - ArrayRef() = default; - explicit ArrayRef(const T& one) : ptr(&one), length(1) {} - ArrayRef(const T* data, size_t length) : ptr(data), length(length) {} - ArrayRef(const T* begin, const T* end) : ptr(begin), length(end - begin) {} - template - constexpr ArrayRef(const T (&arr)[N]) : ptr(arr), length(N) {} - template - constexpr ArrayRef(const std::array& arr) : ptr(arr.data()), length(arr.size()) {} - ArrayRef(const std::vector& vec) : ptr(vec.data()), length(vec.size()) {} - template - ArrayRef(const rstl::reserved_vector& vec) : ptr(vec.data()), length(vec.size()) {} - - const T* data() const { return ptr; } - size_t size() const { return length; } - bool empty() const { return length == 0; } - - const T& front() const { - assert(!empty()); - return ptr[0]; - } - const T& back() const { - assert(!empty()); - return ptr[length - 1]; - } - const T& operator[](size_t i) const { - assert(i < length && "Invalid index!"); - return ptr[i]; - } - - iterator begin() const { return ptr; } - iterator end() const { return ptr + length; } - - reverse_iterator rbegin() const { return reverse_iterator(end()); } - reverse_iterator rend() const { return reverse_iterator(begin()); } - - /// Disallow accidental assignment from a temporary. - template - std::enable_if_t::value, ArrayRef>& operator=(U&& Temporary) = delete; - - /// Disallow accidental assignment from a temporary. - template - std::enable_if_t::value, ArrayRef>& operator=(std::initializer_list) = delete; - -private: - const T* ptr = nullptr; - size_t length = 0; -}; - -template > -class basic_zstring_view; - -using zstring_view = basic_zstring_view; -using wzstring_view = basic_zstring_view; -using u16zstring_view = basic_zstring_view; -using u32zstring_view = basic_zstring_view; - -template -class basic_zstring_view { -public: - using underlying_type = std::basic_string_view; - - using traits_type = typename underlying_type::traits_type; - using value_type = typename underlying_type::value_type; - using pointer = typename underlying_type::pointer; - using const_pointer = typename underlying_type::const_pointer; - using reference = typename underlying_type::reference; - using const_reference = typename underlying_type::const_reference; - using const_iterator = typename underlying_type::const_iterator; - using iterator = typename underlying_type::iterator; - using const_reverse_iterator = typename underlying_type::const_reverse_iterator; - using reverse_iterator = typename underlying_type::reverse_iterator; - using size_type = typename underlying_type::size_type; - using difference_type = typename underlying_type::difference_type; - - static constexpr size_type npos = -1; - - constexpr basic_zstring_view() noexcept = default; - constexpr basic_zstring_view(const basic_zstring_view& other) noexcept = default; - constexpr basic_zstring_view(const CharT* s) : m_view{s} {} - constexpr basic_zstring_view(const std::string& str) : m_view{str.c_str()} {} - - // Needed as a workaround for gcc bug #61648 - // Allows non-friend string literal operators the ability to indirectly call the private constructor - // Safe calling of this requires *certainty* that s[count] is a null character - // Has to be public thusly, but don't call this - static constexpr basic_zstring_view _INTERNAL_unsafe_make_from_string_range(const CharT* s, size_type count) { - return {s, count}; - } - - constexpr basic_zstring_view& operator=(const basic_zstring_view& view) noexcept = default; - - constexpr const_iterator begin() const noexcept { return m_view.begin(); } - - constexpr const_iterator cbegin() const noexcept { return m_view.cbegin(); } - - constexpr const_iterator end() const noexcept { return m_view.end(); } - - constexpr const_iterator cend() const noexcept { return m_view.cend(); } - - constexpr const_reverse_iterator rbegin() const noexcept { return m_view.rbegin(); } - - constexpr const_reverse_iterator crbegin() const noexcept { return m_view.crbegin(); } - - constexpr const_reverse_iterator rend() const noexcept { return m_view.rend(); } - - constexpr const_reverse_iterator crend() const noexcept { return m_view.crend(); } - - constexpr const_reference operator[](size_type pos) const { return m_view[pos]; } - - constexpr const_reference at(size_type pos) const { return m_view.at(pos); } - - constexpr const_reference front() const { return m_view.front(); } - - constexpr const_reference back() const { return m_view.back(); } - - constexpr const_pointer data() const noexcept { return m_view.data(); } - - // Additional function - constexpr const_pointer c_str() const noexcept { return m_view.data(); } - - constexpr size_type size() const noexcept { return m_view.size(); } - - constexpr size_type length() const noexcept { return m_view.length(); } - - constexpr size_type max_size() const noexcept { return m_view.max_size(); } - - constexpr bool empty() const noexcept { return m_view.empty(); } - - constexpr void remove_prefix(size_type n) { m_view.remove_prefix(n); } - - constexpr void swap(basic_zstring_view& v) noexcept { swap(m_view, v.m_view); } - - size_type copy(CharT* dest, size_type count, size_type pos = 0) const { return m_view.copy(dest, count, pos); } - - constexpr underlying_type substr(size_type pos = 0, size_type count = npos) const { - return m_view.substr(pos, count); - } - - // Additional function - constexpr basic_zstring_view suffix(size_type start = 0) const { - return basic_zstring_view{m_view.substr(start, npos)}; - } - - constexpr int compare(underlying_type v) const noexcept { return m_view.compare(v); } - - constexpr int compare(size_type pos1, size_type count1, underlying_type v) const { - return m_view.compare(pos1, count1, v); - } - - constexpr int compare(size_type pos1, size_type count1, underlying_type v, size_type pos2, size_type count2) const { - return m_view.compare(pos1, count1, v, pos2, count2); - } - - constexpr int compare(const CharT* s) const { return m_view.compare(s); } - - constexpr int compare(size_type pos1, size_type count1, const CharT* s, size_type count2) const { - return m_view.compare(pos1, count1, s, count2); - } - - constexpr bool starts_with(underlying_type x) const noexcept { return m_view.starts_with(x); } - - constexpr bool starts_with(CharT x) const noexcept { return m_view.starts_with(x); } - - constexpr bool starts_with(const CharT* x) const { return m_view.starts_with(x); } - - constexpr bool ends_with(underlying_type x) const noexcept { return m_view.ends_with(x); } - - constexpr bool ends_with(CharT x) const noexcept { return m_view.ends_with(x); } - - constexpr bool ends_with(const CharT* x) const { return m_view.ends_with(x); } - - constexpr size_type find(underlying_type v, size_type pos = 0) const noexcept { return m_view.find(v, pos); } - - constexpr size_type find(CharT ch, size_type pos = 0) const noexcept { return m_view.find(ch, pos); } - - constexpr size_type find(const CharT* s, size_type pos, size_type count) const { return m_view.find(s, pos, count); } - - constexpr size_type find(const CharT* s, size_type pos = 0) const { return m_view.find(s, pos); } - - constexpr size_type rfind(underlying_type v, size_type pos = npos) const noexcept { return m_view.rfind(v, pos); } - - constexpr size_type rfind(CharT ch, size_type pos = npos) const noexcept { return m_view.rfind(ch, pos); } - - constexpr size_type rfind(const CharT* s, size_type pos, size_type count) const { - return m_view.rfind(s, pos, count); - } - - constexpr size_type rfind(const CharT* s, size_type pos = npos) const { return m_view.rfind(s, pos); } - - constexpr size_type find_first_of(underlying_type v, size_type pos = 0) const noexcept { - return m_view.find_first_of(v, pos); - } - - constexpr size_type find_first_of(CharT c, size_type pos = 0) const noexcept { return m_view.find_first_of(c, pos); } - - constexpr size_type find_first_of(const CharT* s, size_type pos, size_type count) const { - return m_view.find_first_of(s, pos, count); - } - - constexpr size_type find_first_of(const CharT* s, size_type pos = 0) const { return m_view.find_first_of(s, pos); } - - constexpr size_type find_last_of(underlying_type v, size_type pos = npos) const noexcept { - return m_view.find_last_of(v, pos); - } - - constexpr size_type find_last_of(CharT c, size_type pos = npos) const noexcept { return m_view.find_last_of(c, pos); } - - constexpr size_type find_last_of(const CharT* s, size_type pos, size_type count) const { - return m_view.find_last_of(s, pos, count); - } - - constexpr size_type find_last_of(const CharT* s, size_type pos = npos) const { return m_view.find_last_of(s, pos); } - - constexpr size_type find_first_not_of(underlying_type v, size_type pos = 0) const noexcept { - return m_view.find_first_not_of(v, pos); - } - - constexpr size_type find_first_not_of(CharT c, size_type pos = 0) const noexcept { - return m_view.find_first_not_of(c, pos); - } - - constexpr size_type find_first_not_of(const CharT* s, size_type pos, size_type count) const { - return m_view.find_first_not_of(s, pos, count); - } - - constexpr size_type find_first_not_of(const CharT* s, size_type pos = 0) const { - return m_view.find_first_not_of(s, pos); - } - - constexpr size_type find_last_not_of(underlying_type v, size_type pos = npos) const noexcept { - return m_view.find_last_not_of(v, pos); - } - - constexpr size_type find_last_not_of(CharT c, size_type pos = npos) const noexcept { - return m_view.find_last_not_of(c, pos); - } - - constexpr size_type find_last_not_of(const CharT* s, size_type pos, size_type count) const { - return m_view.find_last_not_of(s, pos, count); - } - - constexpr size_type find_last_not_of(const CharT* s, size_type pos = npos) const { - return m_view.find_last_not_of(s, pos); - } - - constexpr const underlying_type& view() const noexcept { return m_view; } - - constexpr operator underlying_type() const noexcept { return m_view; } - -private: - // Private constructor, called by the string literal operators - constexpr basic_zstring_view(const CharT* s, size_type count) : m_view{s, count} {} - - // Private constructor, needed by suffix() - explicit constexpr basic_zstring_view(const underlying_type& v) noexcept : m_view{v} {} - - underlying_type m_view; -}; - -template -constexpr bool operator==(basic_zstring_view lhs, basic_zstring_view rhs) noexcept { - return lhs.view() == rhs.view(); -} - -template -constexpr bool operator==(basic_zstring_view lhs, std::basic_string_view rhs) noexcept { - return lhs.view() == rhs; -} - -template -constexpr bool operator==(std::basic_string_view lhs, basic_zstring_view rhs) noexcept { - return lhs == rhs.view(); -} - -template -constexpr bool operator!=(basic_zstring_view lhs, basic_zstring_view rhs) noexcept { - return lhs.view() != rhs.view(); -} - -template -constexpr bool operator!=(basic_zstring_view lhs, std::basic_string_view rhs) noexcept { - return lhs.view() != rhs; -} - -template -constexpr bool operator!=(std::basic_string_view lhs, basic_zstring_view rhs) noexcept { - return lhs != rhs.view(); -} - -template -constexpr bool operator<(basic_zstring_view lhs, basic_zstring_view rhs) noexcept { - return lhs.view() < rhs.view(); -} - -template -constexpr bool operator<(basic_zstring_view lhs, std::basic_string_view rhs) noexcept { - return lhs.view() < rhs; -} - -template -constexpr bool operator<(std::basic_string_view lhs, basic_zstring_view rhs) noexcept { - return lhs < rhs.view(); -} - -template -constexpr bool operator<=(basic_zstring_view lhs, basic_zstring_view rhs) noexcept { - return lhs.view() <= rhs.view(); -} - -template -constexpr bool operator<=(basic_zstring_view lhs, std::basic_string_view rhs) noexcept { - return lhs.view() <= rhs; -} - -template -constexpr bool operator<=(std::basic_string_view lhs, basic_zstring_view rhs) noexcept { - return lhs <= rhs.view(); -} - -template -constexpr bool operator>(basic_zstring_view lhs, basic_zstring_view rhs) noexcept { - return lhs.view() > rhs.view(); -} - -template -constexpr bool operator>(basic_zstring_view lhs, std::basic_string_view rhs) noexcept { - return lhs.view() > rhs; -} - -template -constexpr bool operator>(std::basic_string_view lhs, basic_zstring_view rhs) noexcept { - return lhs > rhs.view(); -} - -template -constexpr bool operator>=(basic_zstring_view lhs, basic_zstring_view rhs) noexcept { - return lhs.view() >= rhs.view(); -} - -template -constexpr bool operator>=(basic_zstring_view lhs, std::basic_string_view rhs) noexcept { - return lhs.view() >= rhs; -} - -template -constexpr bool operator>=(std::basic_string_view lhs, basic_zstring_view rhs) noexcept { - return lhs >= rhs.view(); -} - -template -auto operator<<(std::basic_ostream& os, basic_zstring_view v) -> decltype(os) { - return os << v.view(); -} - -inline namespace literals { -inline namespace zstring_view_literals { -constexpr zstring_view operator""_zsv(const char* str, std::size_t len) noexcept { - return zstring_view::_INTERNAL_unsafe_make_from_string_range(str, len); -} - -constexpr u16zstring_view operator""_zsv(const char16_t* str, std::size_t len) noexcept { - return u16zstring_view::_INTERNAL_unsafe_make_from_string_range(str, len); -} - -constexpr u32zstring_view operator""_zsv(const char32_t* str, std::size_t len) noexcept { - return u32zstring_view::_INTERNAL_unsafe_make_from_string_range(str, len); -} - -constexpr wzstring_view operator""_zsv(const wchar_t* str, std::size_t len) noexcept { - return wzstring_view::_INTERNAL_unsafe_make_from_string_range(str, len); -} -} // namespace zstring_view_literals -} // namespace literals -} // namespace aurora - -template -class Flags { -public: - using MaskType = typename std::underlying_type::type; - - // constructors - constexpr Flags() noexcept : m_mask(0) {} - - constexpr Flags(BitType bit) noexcept : m_mask(static_cast(bit)) {} - - constexpr Flags(Flags const& rhs) noexcept : m_mask(rhs.m_mask) {} - - constexpr explicit Flags(MaskType flags) noexcept : m_mask(flags) {} - - [[nodiscard]] constexpr bool IsSet(Flags const bit) const noexcept { return bool(*this & bit); } - - // relational operators - bool operator==(Flags const& rhs) const noexcept { return m_mask == rhs.m_mask; } - - // logical operator - constexpr bool operator!() const noexcept { return !m_mask; } - - // bitwise operators - constexpr Flags operator&(Flags const& rhs) const noexcept { - return Flags(m_mask & rhs.m_mask); - } - - constexpr Flags operator|(Flags const& rhs) const noexcept { - return Flags(m_mask | rhs.m_mask); - } - - constexpr Flags operator^(Flags const& rhs) const noexcept { - return Flags(m_mask ^ rhs.m_mask); - } - - // assignment operators - constexpr Flags& operator=(Flags const& rhs) noexcept { - m_mask = rhs.m_mask; - return *this; - } - - constexpr Flags& operator|=(Flags const& rhs) noexcept { - m_mask |= rhs.m_mask; - return *this; - } - - constexpr Flags& operator&=(Flags const& rhs) noexcept { - m_mask &= rhs.m_mask; - return *this; - } - - constexpr Flags& operator^=(Flags const& rhs) noexcept { - m_mask ^= rhs.m_mask; - return *this; - } - - // cast operators - explicit constexpr operator bool() const noexcept { return m_mask != 0; } - - explicit constexpr operator MaskType() const noexcept { return m_mask; } - -private: - MaskType m_mask; -}; diff --git a/aurora/include/aurora/gfx.hpp b/aurora/include/aurora/gfx.hpp deleted file mode 100644 index efbbba7d0..000000000 --- a/aurora/include/aurora/gfx.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include "common.hpp" - -// TODO make this shared? -#include "../../../Runtime/Graphics/GX.hpp" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace metaforce { -enum class ETexelFormat { - Invalid = -1, - I4 = 0, - I8 = 1, - IA4 = 2, - IA8 = 3, - C4 = 4, - C8 = 5, - C14X2 = 6, - RGB565 = 7, - RGB5A3 = 8, - RGBA8 = 9, - CMPR = 10, - // Metaforce addition: non-converting formats - RGBA8PC = 11, - R8PC = 12, -}; - -enum class EStreamFlagBits : u8 { - fHasNormal = 0x1, - fHasColor = 0x2, - fHasTexture = 0x4, -}; -using EStreamFlags = Flags; -} // namespace metaforce - -namespace aurora::gfx { -struct TextureRef; -using TextureHandle = std::shared_ptr; - -struct ClipRect { - int32_t x; - int32_t y; - int32_t width; - int32_t height; -}; - -struct Light { - zeus::CVector3f pos{0.f, 0.f, 0.f}; - zeus::CVector3f dir{0.f, 0.f, -1.f}; - zeus::CColor color{0.f, 1.f}; - zeus::CVector3f cosAtt{1.f, 0.f, 0.f}; - zeus::CVector3f distAtt{1.f, 0.f, 0.f}; -}; - -#ifndef NDEBUG -#define AURORA_GFX_DEBUG_GROUPS -#endif -void push_debug_group(zstring_view label) noexcept; -void pop_debug_group() noexcept; -struct ScopedDebugGroup { - inline ScopedDebugGroup(zstring_view label) noexcept { push_debug_group(label); } - inline ~ScopedDebugGroup() noexcept { pop_debug_group(); } -}; - -void set_viewport(float left, float top, float width, float height, float znear, float zfar) noexcept; -void set_scissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) noexcept; - -void resolve_color(const ClipRect& rect, uint32_t bindIdx, GX::TextureFormat fmt, bool clear_depth) noexcept; -void resolve_depth(const ClipRect& rect, uint32_t bindIdx, GX::TextureFormat fmt) noexcept; - -void queue_movie_player(const TextureHandle& tex_y, const TextureHandle& tex_u, const TextureHandle& tex_v, float h_pad, - float v_pad) noexcept; - -TextureHandle new_static_texture_2d(uint32_t width, uint32_t height, uint32_t mips, GX::TextureFormat format, - ArrayRef data, zstring_view label) noexcept; -TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t mips, GX::TextureFormat format, - zstring_view label) noexcept; -TextureHandle new_render_texture(uint32_t width, uint32_t height, GX::TextureFormat fmt, zstring_view label) noexcept; -void write_texture(const TextureRef& handle, ArrayRef data) noexcept; -} // namespace aurora::gfx diff --git a/aurora/include/aurora/imgui.hpp b/aurora/include/aurora/imgui.hpp deleted file mode 100644 index 5795c71ee..000000000 --- a/aurora/include/aurora/imgui.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "common.hpp" - -#include - -namespace aurora::imgui { -ImTextureID add_texture(uint32_t width, uint32_t height, ArrayRef data) noexcept; -} // namespace aurora::imgui diff --git a/aurora/include/aurora/model.hpp b/aurora/include/aurora/model.hpp deleted file mode 100644 index 152661cf0..000000000 --- a/aurora/include/aurora/model.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "common.hpp" - -namespace aurora::gfx::model { -void set_vtx_desc_compressed(u32 vtxDesc) noexcept; -} // namespace aurora::gfx::model diff --git a/aurora/include/aurora/pad.hpp b/aurora/include/aurora/pad.hpp deleted file mode 100644 index 1623bf6b6..000000000 --- a/aurora/include/aurora/pad.hpp +++ /dev/null @@ -1,119 +0,0 @@ -#pragma once -#include "aurora/common.hpp" - -namespace PAD { -struct Status { - u16 x0_buttons; - s8 x2_stickX; - s8 x3_stickY; - s8 x4_substickX; - s8 x5_substickY; - u8 x6_triggerL; - u8 x7_triggerR; - u8 x8_analogA; - u8 x9_analogB; - s8 xa_err; -}; - -enum BUTTON : u16 { - BUTTON_LEFT = 0x0001, - BUTTON_RIGHT = 0x0002, - BUTTON_DOWN = 0x0004, - BUTTON_UP = 0x0008, - TRIGGER_Z = 0x0010, - TRIGGER_R = 0x0020, - TRIGGER_L = 0x0040, - BUTTON_A = 0x0100, - BUTTON_B = 0x0200, - BUTTON_X = 0x0400, - BUTTON_Y = 0x0800, - BUTTON_START = 0x1000, -}; - -enum ERROR : s8 { - ERR_NONE = 0, - ERR_NO_CONTROLLER = -1, - ERR_NOT_READY = -2, - ERR_TRANSFER = -3, -}; - -enum MOTOR : u32 { - MOTOR_STOP = 0, - MOTOR_RUMBLE = 1, - MOTOR_STOP_HARD = 2, -}; -enum CHAN : u32 { - CHAN0_BIT = 0x80000000, - CHAN1_BIT = 0x40000000, - CHAN2_BIT = 0x20000000, - CHAN3_BIT = 0x10000000, -}; -} // namespace PAD - -namespace SI { -constexpr u32 ERROR_UNKNOWN = 0x0040; -constexpr u32 ERROR_BUSY = 0x0080; -constexpr u32 ERROR_NO_RESPONSE = 0x0008; -constexpr u32 TYPE_GC = 0x08000000; -constexpr u32 GBA = 0x00040000; -constexpr u32 GC_STANDARD = 0x01000000; -constexpr u32 GC_WIRELESS = 0x80000000; -constexpr u32 WIRELESS_STATE = 0x02000000; -constexpr u32 WIRELESS_FIX_ID = 0x00100000; -constexpr u32 GC_CONTROLLER = (TYPE_GC | GC_STANDARD); -constexpr u32 GC_RECEIVER = (TYPE_GC | GC_WIRELESS); -constexpr u32 GC_WAVEBIRD = (TYPE_GC | GC_WIRELESS | GC_STANDARD | WIRELESS_STATE | WIRELESS_FIX_ID); -} // namespace SI - -using PADSamplingCallback = void (*)(void); -constexpr bool PADButtonDown(bool lastButton, bool button) { return ((lastButton ^ button) & button) != 0; } -constexpr bool PADButtonUp(bool lastButton, bool button) { return ((lastButton ^ button) & lastButton) != 0; } -void PADClamp(PAD::Status* status); -void PADClampCircle(PAD::Status* status); -void PADInit(); -bool PADIsBarrel(s32 chan); -u32 PADRead(PAD::Status* status); -static bool PADRecalibrate(u32 mask) { return true; } -static bool PADReset(u32 mask) { return true; } -void PADSetAnalog(u32 mode); -void PADSetSpec(s32 spec); -void PADSetSamplingCallback(PADSamplingCallback callback); -void PADControlAllMotors(const u32* commands); - -u32 SIProbe(s32 chan); - -/* New API to facilitate controller interactions */ -struct PADDeadZones { - bool emulateTriggers = true; - bool useDeadzones = true; - u16 stickDeadZone = 8000; - u16 substickDeadZone = 8000; - u16 leftTriggerActivationZone = 31150; - u16 rightTriggerActivationZone = 31150; -}; - -struct PADButtonMapping { - u32 nativeButton; - PAD::BUTTON padButton; -}; - -/* Returns the total number of controllers */ -u32 PADCount(); -/* Returns the controller name for the given index into the controller map */ -const char* PADGetNameForControllerIndex(u32 idx); -void PADSetPortForIndex(u32 index, s32 port); -s32 PADGetIndexForPort(u32 port); -void PADGetVidPid(u32 port, u32* vid, u32* pid); -void PADClearPort(u32 port); -const char* PADGetName(u32 port); -void PADSetButtonMapping(u32 port, PADButtonMapping mapping); -void PADSetAllButtonMappings(u32 port, PADButtonMapping buttons[12]); -PADButtonMapping* PADGetButtonMappings(u32 port, u32* buttonCount); -void PADSerializeMappings(); -PADDeadZones* PADGetDeadZones(u32 port); -const char* PADGetButtonName(PAD::BUTTON); -const char* PADGetNativeButtonName(u32 button); -/* Returns any pressed native button */ -s32 PADGetNativeButtonPressed(u32 port); -void PADRestoreDefaultMapping(u32 port); -void PADBlockInput(bool block); diff --git a/aurora/lib/aurora.cpp b/aurora/lib/aurora.cpp deleted file mode 100644 index 2fa6d137c..000000000 --- a/aurora/lib/aurora.cpp +++ /dev/null @@ -1,595 +0,0 @@ -#include - -#include "gfx/common.hpp" -#include "gfx/gx.hpp" -#include "gpu.hpp" -#include "input.hpp" -#include "imgui.hpp" - -#include -#include -#include -#include -#include - -namespace aurora { -static logvisor::Module Log("aurora"); - -// TODO: Move global state to a class/struct? -static std::unique_ptr g_AppDelegate; -static std::vector g_Args; -std::string g_configPath; - -// SDL -static SDL_Window* g_window; -WindowSize g_windowSize; - -// GPU -using gpu::g_depthBuffer; -using gpu::g_device; -using gpu::g_frameBuffer; -using gpu::g_frameBufferResolved; -using gpu::g_queue; -using gpu::g_swapChain; - -static void set_window_icon(Icon icon) noexcept { - SDL_Surface* iconSurface = SDL_CreateRGBSurfaceFrom(icon.data.get(), icon.width, icon.height, 32, 4 * icon.width, -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff -#else - 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 -#endif - ); - if (iconSurface == nullptr) { - Log.report(logvisor::Fatal, FMT_STRING("Failed to create icon surface: {}"), SDL_GetError()); - unreachable(); - } - SDL_SetWindowIcon(g_window, iconSurface); - SDL_FreeSurface(iconSurface); -} - -static bool g_paused = false; - -static void resize_swapchain(bool force) noexcept { - const auto size = get_window_size(); - if (!force && size == g_windowSize) { - return; - } - if (size.scale != g_windowSize.scale) { - if (g_windowSize.scale > 0.f) { - Log.report(logvisor::Info, FMT_STRING("Display scale changed to {}"), size.scale); - } - g_AppDelegate->onAppDisplayScaleChanged(size.scale); - } - g_windowSize = size; - gpu::resize_swapchain(size.fb_width, size.fb_height); - g_AppDelegate->onAppWindowResized(size); -} - -static bool poll_events() noexcept { - SDL_Event event; - while (SDL_PollEvent(&event) != 0) { - imgui::process_event(event); - - switch (event.type) { - case SDL_WINDOWEVENT: { - switch (event.window.event) { - case SDL_WINDOWEVENT_MINIMIZED: { - // Android/iOS: Application backgrounded - g_paused = true; - break; - } - case SDL_WINDOWEVENT_RESTORED: { - // Android/iOS: Application focused - g_paused = false; - break; - } - case SDL_WINDOWEVENT_MOVED: { - g_AppDelegate->onAppWindowMoved(event.window.data1, event.window.data2); - break; - } - case SDL_WINDOWEVENT_SIZE_CHANGED: { - resize_swapchain(false); - break; - } - } - break; - } - case SDL_CONTROLLERDEVICEADDED: { - auto instance = input::add_controller(event.cdevice.which); - if (instance != -1) { - g_AppDelegate->onControllerAdded(instance); - } - break; - } - case SDL_CONTROLLERDEVICEREMOVED: { - input::remove_controller(event.cdevice.which); - break; - } - case SDL_CONTROLLERBUTTONUP: - case SDL_CONTROLLERBUTTONDOWN: { - g_AppDelegate->onControllerButton( - event.cbutton.which, - input::translate_controller_button(static_cast(event.cbutton.button)), - event.cbutton.state == SDL_PRESSED); - break; - } - case SDL_CONTROLLERAXISMOTION: { - if (event.caxis.value > 8000 || event.caxis.value < -8000) { - g_AppDelegate->onControllerAxis( - event.caxis.which, input::translate_controller_axis(static_cast(event.caxis.axis)), - event.caxis.value); - } else { - g_AppDelegate->onControllerAxis( - event.caxis.which, input::translate_controller_axis(static_cast(event.caxis.axis)), - 0); - } - break; - } - case SDL_KEYDOWN: { - // ALT+ENTER for fullscreen toggle - if (event.key.repeat == 0u && event.key.keysym.scancode == SDL_SCANCODE_RETURN && - (event.key.keysym.mod & (KMOD_RALT | KMOD_LALT)) != 0u) { - set_fullscreen(!is_fullscreen()); - break; - } - if (!ImGui::GetIO().WantCaptureKeyboard) { - SpecialKey specialKey{}; - ModifierKey modifierKey{}; - char chr = input::translate_key(event.key.keysym, specialKey, modifierKey); - if (chr != 0) { - modifierKey = input::translate_modifiers(event.key.keysym.mod); - g_AppDelegate->onCharKeyDown(chr, modifierKey, event.key.repeat != 0u); - } else if (specialKey != SpecialKey::None) { - modifierKey = input::translate_modifiers(event.key.keysym.mod); - g_AppDelegate->onSpecialKeyDown(specialKey, modifierKey, event.key.repeat != 0u); - } else if (modifierKey != ModifierKey::None) { - g_AppDelegate->onModifierKeyDown(modifierKey, event.key.repeat != 0u); - } - } - break; - } - case SDL_KEYUP: { - if (!ImGui::GetIO().WantCaptureKeyboard) { - SpecialKey specialKey{}; - ModifierKey modifierKey{}; - char chr = input::translate_key(event.key.keysym, specialKey, modifierKey); - if (chr != 0) { - modifierKey = input::translate_modifiers(event.key.keysym.mod); - g_AppDelegate->onCharKeyUp(chr, modifierKey); - } else if (specialKey != SpecialKey::None) { - modifierKey = input::translate_modifiers(event.key.keysym.mod); - g_AppDelegate->onSpecialKeyUp(specialKey, modifierKey); - } else if (modifierKey != ModifierKey::None) { - g_AppDelegate->onModifierKeyUp(modifierKey); - } - } - break; - } - case SDL_TEXTINPUT: { - if (!ImGui::GetIO().WantCaptureKeyboard) { - std::string str; - str.assign(&event.text.text[0], SDL_TEXTINPUTEVENT_TEXT_SIZE); - g_AppDelegate->onTextInput(str); - } - break; - } - case SDL_MOUSEBUTTONDOWN: { - if (!ImGui::GetIO().WantCaptureMouse) { - g_AppDelegate->onMouseButtonDown(event.button.x, event.button.y, - input::translate_mouse_button(event.button.button), event.button.clicks); - } - break; - } - case SDL_MOUSEBUTTONUP: { - if (!ImGui::GetIO().WantCaptureMouse) { - g_AppDelegate->onMouseButtonUp(event.button.x, event.button.y, - input::translate_mouse_button(event.button.button)); - } - break; - } - case SDL_MOUSEMOTION: { - if (!ImGui::GetIO().WantCaptureMouse) { - g_AppDelegate->onMouseMove(event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel, - input::translate_mouse_button_state(event.motion.state)); - } - break; - } - case SDL_QUIT: - return false; - } - // Log.report(logvisor::Info, FMT_STRING("Received SDL event: {}"), event.type); - } - return true; -} - -static SDL_Window* create_window(wgpu::BackendType type, bool fullscreen) { - Uint32 flags = SDL_WINDOW_ALLOW_HIGHDPI; -#if TARGET_OS_IOS || TARGET_OS_TV - flags |= SDL_WINDOW_FULLSCREEN; -#else - flags |= SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE; - if (fullscreen) { - flags |= SDL_WINDOW_FULLSCREEN; - } -#endif - switch (type) { -#ifdef DAWN_ENABLE_BACKEND_VULKAN - case wgpu::BackendType::Vulkan: - flags |= SDL_WINDOW_VULKAN; - break; -#endif -#ifdef DAWN_ENABLE_BACKEND_METAL - case wgpu::BackendType::Metal: - flags |= SDL_WINDOW_METAL; - break; -#endif -#ifdef DAWN_ENABLE_BACKEND_OPENGL - case wgpu::BackendType::OpenGL: - flags |= SDL_WINDOW_OPENGL; - break; -#endif - default: - break; - } - return SDL_CreateWindow("Metaforce", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, -#ifdef __SWITCH__ - 720, -#else - 960, -#endif - flags); -} - -wgpu::BackendType to_wgpu_backend(Backend backend) { - switch (backend) { - case Backend::WebGPU: - return wgpu::BackendType::WebGPU; - case Backend::D3D11: - return wgpu::BackendType::D3D11; - case Backend::D3D12: - return wgpu::BackendType::D3D12; - case Backend::Metal: - return wgpu::BackendType::Metal; - case Backend::Vulkan: - return wgpu::BackendType::Vulkan; - case Backend::OpenGL: - return wgpu::BackendType::OpenGL; - case Backend::OpenGLES: - return wgpu::BackendType::OpenGLES; - default: - return wgpu::BackendType::Null; - } -} -void app_run(std::unique_ptr app, Icon icon, int argc, char** argv, std::string_view configPath, - Backend desiredBackend, uint32_t msaa, uint16_t aniso, bool fullscreen) noexcept { - g_AppDelegate = std::move(app); - /* Lets gather arguments skipping the program filename */ - for (size_t i = 1; i < argc; ++i) { - g_Args.emplace_back(argv[i]); - } - g_configPath = configPath; - - if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { - Log.report(logvisor::Fatal, FMT_STRING("Error initializing SDL: {}"), SDL_GetError()); - unreachable(); - } - -#if !defined(_WIN32) && !defined(__APPLE__) - SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); -#endif -#if SDL_VERSION_ATLEAST(2, 0, 18) - SDL_SetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME, "Metaforce"); -#endif -#ifdef SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE - SDL_SetHint(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE, "1"); -#endif - - SDL_DisableScreenSaver(); - /* TODO: Make this an option rather than hard coding it */ - SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); - - /* Attempt to create a window using the calling application's desired backend */ - if (desiredBackend != Backend::Invalid) { - auto wgpuBackend = to_wgpu_backend(desiredBackend); - g_window = create_window(wgpuBackend, fullscreen); - if (g_window != nullptr && !gpu::initialize(g_window, wgpuBackend, msaa, aniso)) { - g_window = nullptr; - SDL_DestroyWindow(g_window); - } - } - - if (g_window == nullptr) { - for (const auto backendType : gpu::PreferredBackendOrder) { - auto* window = create_window(backendType, fullscreen); - if (window == nullptr) { - continue; - } - g_window = window; - if (gpu::initialize(window, backendType, msaa, aniso)) { - break; - } - g_window = nullptr; - SDL_DestroyWindow(window); - } - } - - if (g_window == nullptr) { - Log.report(logvisor::Fatal, FMT_STRING("Error creating window: {}"), SDL_GetError()); - unreachable(); - } - set_window_icon(std::move(icon)); - - // Initialize SDL_Renderer for ImGui when we can't use a Dawn backend - SDL_Renderer* renderer = nullptr; - if (gpu::g_backendType == wgpu::BackendType::Null) { - const auto flags = SDL_RENDERER_PRESENTVSYNC; - renderer = SDL_CreateRenderer(g_window, -1, flags | SDL_RENDERER_ACCELERATED); - if (renderer == nullptr) { - // Attempt fallback to SW renderer - renderer = SDL_CreateRenderer(g_window, -1, flags); - } - if (renderer == nullptr) { - Log.report(logvisor::Fatal, FMT_STRING("Failed to initialize SDL renderer: {}"), SDL_GetError()); - unreachable(); - } - } - - SDL_ShowWindow(g_window); - gfx::initialize(); - - imgui::create_context(); - const auto size = get_window_size(); - Log.report(logvisor::Info, FMT_STRING("Using framebuffer size {}x{} scale {}"), size.fb_width, size.fb_height, - size.scale); - g_AppDelegate->onImGuiInit(size.scale); - imgui::initialize(g_window, renderer); - g_AppDelegate->onImGuiAddTextures(); - - g_AppDelegate->onAppLaunched(); - g_AppDelegate->onAppWindowResized(size); - - while (poll_events()) { - if (g_paused) { - continue; - } - - imgui::new_frame(g_windowSize); - if (!g_AppDelegate->onAppIdle(ImGui::GetIO().DeltaTime)) { - break; - } - - const wgpu::TextureView view = g_swapChain.GetCurrentTextureView(); - if (!view) { - ImGui::EndFrame(); - // Force swapchain recreation - resize_swapchain(true); - continue; - } - gfx::begin_frame(); - g_AppDelegate->onAppDraw(); - - const auto encoderDescriptor = wgpu::CommandEncoderDescriptor{ - .label = "Redraw encoder", - }; - auto encoder = g_device.CreateCommandEncoder(&encoderDescriptor); - gfx::end_frame(encoder); - gfx::render(encoder); - { - const std::array attachments{ - wgpu::RenderPassColorAttachment{ - .view = view, - .loadOp = wgpu::LoadOp::Clear, - .storeOp = wgpu::StoreOp::Store, - }, - }; - auto renderPassDescriptor = wgpu::RenderPassDescriptor{ - .label = "Post render pass", - .colorAttachmentCount = attachments.size(), - .colorAttachments = attachments.data(), - }; - auto pass = encoder.BeginRenderPass(&renderPassDescriptor); - // Copy EFB -> XFB (swapchain) - pass.SetPipeline(gpu::g_CopyPipeline); - pass.SetBindGroup(0, gpu::g_CopyBindGroup); - pass.Draw(3); - // Render ImGui - imgui::render(pass); - pass.End(); - } - const auto buffer = encoder.Finish(); - g_queue.Submit(1, &buffer); - g_swapChain.Present(); - - g_AppDelegate->onAppPostDraw(); - - ImGui::EndFrame(); - } - - Log.report(logvisor::Info, FMT_STRING("Application exiting")); - g_AppDelegate->onAppExiting(); - - imgui::shutdown(); - gfx::shutdown(); - gpu::shutdown(); - if (renderer != nullptr) { - SDL_DestroyRenderer(renderer); - } - SDL_DestroyWindow(g_window); - g_window = nullptr; - SDL_EnableScreenSaver(); - SDL_Quit(); -} - -std::vector get_args() noexcept { return g_Args; } - -WindowSize get_window_size() noexcept { - int width, height, fb_w, fb_h; - SDL_GetWindowSize(g_window, &width, &height); -#if DAWN_ENABLE_BACKEND_METAL - SDL_Metal_GetDrawableSize(g_window, &fb_w, &fb_h); -#else - SDL_GL_GetDrawableSize(g_window, &fb_w, &fb_h); -#endif - float scale = static_cast(fb_w) / static_cast(width); -#ifndef __APPLE__ - if (SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(g_window), nullptr, &scale, nullptr) == 0) { - scale /= 96.f; - } -#endif - return { - .width = static_cast(width), - .height = static_cast(height), - .fb_width = static_cast(fb_w), - .fb_height = static_cast(fb_h), - .scale = scale, - }; -} - -void set_window_title(zstring_view title) noexcept { SDL_SetWindowTitle(g_window, title.c_str()); } - -Backend get_backend() noexcept { - switch (gpu::g_backendType) { - case wgpu::BackendType::WebGPU: - return Backend::WebGPU; - case wgpu::BackendType::D3D11: - return Backend::D3D11; - case wgpu::BackendType::D3D12: - return Backend::D3D12; - case wgpu::BackendType::Metal: - return Backend::Metal; - case wgpu::BackendType::Vulkan: - return Backend::Vulkan; - case wgpu::BackendType::OpenGL: - return Backend::OpenGL; - case wgpu::BackendType::OpenGLES: - return Backend::OpenGLES; - case wgpu::BackendType::Null: - return Backend::Null; - default: - return Backend::Invalid; - } -} - -std::vector get_available_backends() noexcept { - return { -#ifdef DAWN_ENABLE_BACKEND_D3D12 - Backend::D3D12, -#endif -#ifdef DAWN_ENABLE_BACKEND_METAL - Backend::Metal, -#endif -#ifdef DAWN_ENABLE_BACKEND_VULKAN - Backend::Vulkan, -#endif -#ifdef DAWN_ENABLE_BACKEND_DESKTOP_GL - Backend::OpenGL, -#endif -#ifdef DAWN_ENABLE_BACKEND_OPENGLES - Backend::OpenGLES, -#endif -#ifdef DAWN_ENABLE_BACKEND_NULL - Backend::Null, -#endif - }; -} - -std::string_view get_backend_string() noexcept { return magic_enum::enum_name(gpu::g_backendType); } - -Backend backend_from_string(std::string_view backend) { - if (backend.empty()) { - return Backend::Invalid; - } - std::string tmp = backend.data(); - std::transform(tmp.begin(), tmp.end(), tmp.begin(), [](unsigned char c) { return std::tolower(c); }); -#if DAWN_ENABLE_BACKEND_WEBGPU - if (tmp == "webgpu" || tmp == "wgpu") { - return Backend::WebGPU; - } -#endif -#if DAWN_ENABLE_BACKEND_D3D11 - if (tmp == "d3d11") { - return Backend::D3D11; - } -#endif -#if DAWN_ENABLE_BACKEND_D3D12 - if (tmp == "d3d12") { - return Backend::D3D12; - } -#endif -#if DAWN_ENABLE_BACKEND_METAL - if (tmp == "metal") { - return Backend::Metal; - } -#endif -#if DAWN_ENABLE_BACKEND_DESKTOP_GL || DAWN_ENABLE_BACKEND_OPENGL - if (tmp == "gl" || tmp == "opengl") { - return Backend::OpenGL; - } -#endif -#if DAWN_ENABLE_BACKEND_OPENGLES - if (tmp == "gles" || tmp == "opengles") { - return Backend::OpenGLES; - } -#endif -#if DAWN_ENABLE_BACKEND_VULKAN - if (tmp == "vulkan") { - return Backend::Vulkan; - } -#endif -#if DAWN_ENABLE_BACKEND_NULL - if (tmp == "null") { - return Backend::Null; - } -#endif - return Backend::Invalid; -} - -std::string_view backend_to_string(Backend backend) { - switch (backend) { - case Backend::Null: - return "null"sv; - case Backend::WebGPU: - return "webgpu"sv; - case Backend::D3D11: - return "d3d11"sv; - case Backend::D3D12: - return "d3d12"sv; - case Backend::Metal: - return "metal"sv; - case Backend::Vulkan: - return "vulkan"sv; - case Backend::OpenGL: - return "opengl"sv; - case Backend::OpenGLES: - return "opengles"sv; - case Backend::Invalid: - return "auto"; - } -} - -void set_fullscreen(bool fullscreen) noexcept { - SDL_SetWindowFullscreen(g_window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0); -} - -bool is_fullscreen() noexcept { return (SDL_GetWindowFlags(g_window) & SDL_WINDOW_FULLSCREEN) != 0u; } - -uint32_t get_which_controller_for_player(int32_t index) noexcept { return input::get_instance_for_player(index); } -int32_t get_controller_player_index(uint32_t instance) noexcept { return input::player_index(instance); } - -void set_controller_player_index(uint32_t instance, int32_t index) noexcept { - input::set_player_index(instance, index); -} - -bool is_controller_gamecube(uint32_t instance) noexcept { return input::is_gamecube(instance); } - -bool controller_has_rumble(uint32_t instance) noexcept { return input::controller_has_rumble(instance); } - -void controller_rumble(uint32_t instance, uint16_t low_freq_intensity, uint16_t high_freq_intensity, - uint32_t duration_ms) noexcept { - input::controller_rumble(instance, low_freq_intensity, high_freq_intensity, duration_ms); -} - -uint32_t get_controller_count() noexcept { return input::controller_count(); } -std::string get_controller_name(uint32_t instance) noexcept { return input::controller_name(instance); } -} // namespace aurora diff --git a/aurora/lib/dawn/BackendBinding.cpp b/aurora/lib/dawn/BackendBinding.cpp deleted file mode 100644 index 9a6f7e0ad..000000000 --- a/aurora/lib/dawn/BackendBinding.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "BackendBinding.hpp" - -#if defined(DAWN_ENABLE_BACKEND_D3D12) -#include -#endif -#if defined(DAWN_ENABLE_BACKEND_METAL) -#include -#endif -#if defined(DAWN_ENABLE_BACKEND_VULKAN) -#include -#endif -#if defined(DAWN_ENABLE_BACKEND_OPENGL) -#include -#include -#endif -#if defined(DAWN_ENABLE_BACKEND_NULL) -#include -#endif - -namespace aurora::gpu::utils { - -#if defined(DAWN_ENABLE_BACKEND_D3D12) -BackendBinding* CreateD3D12Binding(SDL_Window* window, WGPUDevice device); -#endif -#if defined(DAWN_ENABLE_BACKEND_METAL) -BackendBinding* CreateMetalBinding(SDL_Window* window, WGPUDevice device); -#endif -#if defined(DAWN_ENABLE_BACKEND_NULL) -BackendBinding* CreateNullBinding(SDL_Window* window, WGPUDevice device); -#endif -#if defined(DAWN_ENABLE_BACKEND_OPENGL) -BackendBinding* CreateOpenGLBinding(SDL_Window* window, WGPUDevice device); -#endif -#if defined(DAWN_ENABLE_BACKEND_VULKAN) -BackendBinding* CreateVulkanBinding(SDL_Window* window, WGPUDevice device); -#endif - -BackendBinding::BackendBinding(SDL_Window* window, WGPUDevice device) : m_window(window), m_device(device) {} - -bool DiscoverAdapter(dawn::native::Instance* instance, SDL_Window* window, wgpu::BackendType type) { - switch (type) { -#if defined(DAWN_ENABLE_BACKEND_D3D12) - case wgpu::BackendType::D3D12: { - dawn::native::d3d12::AdapterDiscoveryOptions options; - return instance->DiscoverAdapters(&options); - } -#endif -#if defined(DAWN_ENABLE_BACKEND_METAL) - case wgpu::BackendType::Metal: { - dawn::native::metal::AdapterDiscoveryOptions options; - return instance->DiscoverAdapters(&options); - } -#endif -#if defined(DAWN_ENABLE_BACKEND_VULKAN) - case wgpu::BackendType::Vulkan: { - dawn::native::vulkan::AdapterDiscoveryOptions options; - return instance->DiscoverAdapters(&options); - } -#endif -#if defined(DAWN_ENABLE_BACKEND_OPENGL) - case wgpu::BackendType::OpenGL: - case wgpu::BackendType::OpenGLES: { - SDL_GL_CreateContext(window); - auto getProc = reinterpret_cast(SDL_GL_GetProcAddress); - if (type == wgpu::BackendType::OpenGL) { - dawn::native::opengl::AdapterDiscoveryOptions adapterOptions; - adapterOptions.getProc = getProc; - return instance->DiscoverAdapters(&adapterOptions); - } else { - dawn::native::opengl::AdapterDiscoveryOptionsES adapterOptions; - adapterOptions.getProc = getProc; - return instance->DiscoverAdapters(&adapterOptions); - } - } -#endif -#if defined(DAWN_ENABLE_BACKEND_NULL) - case wgpu::BackendType::Null: - instance->DiscoverDefaultAdapters(); - return true; -#endif - default: - return false; - } -} - -BackendBinding* CreateBinding(wgpu::BackendType type, SDL_Window* window, WGPUDevice device) { - switch (type) { -#if defined(DAWN_ENABLE_BACKEND_D3D12) - case wgpu::BackendType::D3D12: - return CreateD3D12Binding(window, device); -#endif -#if defined(DAWN_ENABLE_BACKEND_METAL) - case wgpu::BackendType::Metal: - return CreateMetalBinding(window, device); -#endif -#if defined(DAWN_ENABLE_BACKEND_NULL) - case wgpu::BackendType::Null: - return CreateNullBinding(window, device); -#endif -#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) - case wgpu::BackendType::OpenGL: - return CreateOpenGLBinding(window, device); -#endif -#if defined(DAWN_ENABLE_BACKEND_OPENGLES) - case wgpu::BackendType::OpenGLES: - return CreateOpenGLBinding(window, device); -#endif -#if defined(DAWN_ENABLE_BACKEND_VULKAN) - case wgpu::BackendType::Vulkan: - return CreateVulkanBinding(window, device); -#endif - default: - return nullptr; - } -} - -} // namespace aurora::gpu::utils diff --git a/aurora/lib/dawn/BackendBinding.hpp b/aurora/lib/dawn/BackendBinding.hpp deleted file mode 100644 index 268e8b298..000000000 --- a/aurora/lib/dawn/BackendBinding.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include - -struct SDL_Window; - -namespace aurora::gpu::utils { - -class BackendBinding { -public: - virtual ~BackendBinding() = default; - - virtual uint64_t GetSwapChainImplementation() = 0; - virtual WGPUTextureFormat GetPreferredSwapChainTextureFormat() = 0; - -protected: - BackendBinding(SDL_Window* window, WGPUDevice device); - - SDL_Window* m_window = nullptr; - WGPUDevice m_device = nullptr; -}; - -bool DiscoverAdapter(dawn::native::Instance* instance, SDL_Window* window, wgpu::BackendType type); -BackendBinding* CreateBinding(wgpu::BackendType type, SDL_Window* window, WGPUDevice device); - -} // namespace aurora::gpu::utils diff --git a/aurora/lib/dawn/D3D12Binding.cpp b/aurora/lib/dawn/D3D12Binding.cpp deleted file mode 100644 index bc347e8f4..000000000 --- a/aurora/lib/dawn/D3D12Binding.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "BackendBinding.hpp" - -#include -#include - -namespace aurora::gpu::utils { -class D3D12Binding : public BackendBinding { -public: - D3D12Binding(SDL_Window* window, WGPUDevice device) : BackendBinding(window, device) {} - - uint64_t GetSwapChainImplementation() override { - if (m_swapChainImpl.userData == nullptr) { - CreateSwapChainImpl(); - } - return reinterpret_cast(&m_swapChainImpl); - } - - WGPUTextureFormat GetPreferredSwapChainTextureFormat() override { - if (m_swapChainImpl.userData == nullptr) { - CreateSwapChainImpl(); - } - return dawn::native::d3d12::GetNativeSwapChainPreferredFormat(&m_swapChainImpl); - } - -private: - DawnSwapChainImplementation m_swapChainImpl{}; - - void CreateSwapChainImpl() { - SDL_SysWMinfo wmInfo; - SDL_VERSION(&wmInfo.version); - SDL_GetWindowWMInfo(m_window, &wmInfo); - m_swapChainImpl = dawn::native::d3d12::CreateNativeSwapChainImpl(m_device, wmInfo.info.win.window); - } -}; - -BackendBinding* CreateD3D12Binding(SDL_Window* window, WGPUDevice device) { return new D3D12Binding(window, device); } -} // namespace aurora::gpu::utils diff --git a/aurora/lib/dawn/MetalBinding.mm b/aurora/lib/dawn/MetalBinding.mm deleted file mode 100644 index e48f3be14..000000000 --- a/aurora/lib/dawn/MetalBinding.mm +++ /dev/null @@ -1,108 +0,0 @@ -#include "BackendBinding.hpp" - -#include -#include - -#import - -template DawnSwapChainImplementation CreateSwapChainImplementation(T *swapChain) { - DawnSwapChainImplementation impl = {}; - impl.userData = swapChain; - impl.Init = [](void *userData, void *wsiContext) { - auto *ctx = static_cast(wsiContext); - reinterpret_cast(userData)->Init(ctx); - }; - impl.Destroy = [](void *userData) { delete reinterpret_cast(userData); }; - impl.Configure = [](void *userData, WGPUTextureFormat format, WGPUTextureUsage allowedUsage, uint32_t width, - uint32_t height) { - return static_cast(userData)->Configure(format, allowedUsage, width, height); - }; - impl.GetNextTexture = [](void *userData, DawnSwapChainNextTexture *nextTexture) { - return static_cast(userData)->GetNextTexture(nextTexture); - }; - impl.Present = [](void *userData) { return static_cast(userData)->Present(); }; - return impl; -} - -namespace aurora::gpu::utils { -class SwapChainImplMTL { -public: - using WSIContext = DawnWSIContextMetal; - - explicit SwapChainImplMTL(SDL_Window *window) : m_view(SDL_Metal_CreateView(window)) {} - - ~SwapChainImplMTL() { SDL_Metal_DestroyView(m_view); } - - void Init(DawnWSIContextMetal *ctx) { - mMtlDevice = ctx->device; - mCommandQueue = ctx->queue; - } - - DawnSwapChainError Configure(WGPUTextureFormat format, WGPUTextureUsage usage, uint32_t width, uint32_t height) { - if (format != WGPUTextureFormat_BGRA8Unorm) { - return "unsupported format"; - } - assert(width > 0); - assert(height > 0); - - CGSize size = {}; - size.width = width; - size.height = height; - - mLayer = (__bridge CAMetalLayer *)(SDL_Metal_GetLayer(m_view)); - [mLayer setDevice:mMtlDevice]; - [mLayer setPixelFormat:MTLPixelFormatBGRA8Unorm]; - [mLayer setDrawableSize:size]; - - constexpr uint32_t kFramebufferOnlyTextureUsages = WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_Present; - bool hasOnlyFramebufferUsages = (usage & (~kFramebufferOnlyTextureUsages)) == 0u; - if (hasOnlyFramebufferUsages) { - [mLayer setFramebufferOnly:YES]; - } - - return DAWN_SWAP_CHAIN_NO_ERROR; - } - - DawnSwapChainError GetNextTexture(DawnSwapChainNextTexture *nextTexture) { - mCurrentDrawable = [mLayer nextDrawable]; - mCurrentTexture = mCurrentDrawable.texture; - nextTexture->texture.ptr = (__bridge void *)(mCurrentTexture); - return DAWN_SWAP_CHAIN_NO_ERROR; - } - - DawnSwapChainError Present() { - id commandBuffer = [mCommandQueue commandBuffer]; - [commandBuffer presentDrawable:mCurrentDrawable]; - [commandBuffer commit]; - return DAWN_SWAP_CHAIN_NO_ERROR; - } - -private: - SDL_MetalView m_view = nil; - id mMtlDevice = nil; - id mCommandQueue = nil; - - CAMetalLayer *mLayer = nullptr; - id mCurrentDrawable = nil; - id mCurrentTexture = nil; -}; - -class MetalBinding : public BackendBinding { -public: - MetalBinding(SDL_Window *window, WGPUDevice device) : BackendBinding(window, device) {} - - uint64_t GetSwapChainImplementation() override { - if (m_swapChainImpl.userData == nullptr) { - m_swapChainImpl = CreateSwapChainImplementation(new SwapChainImplMTL(m_window)); - } - return reinterpret_cast(&m_swapChainImpl); - } - - WGPUTextureFormat GetPreferredSwapChainTextureFormat() override { return WGPUTextureFormat_BGRA8Unorm; } - -private: - DawnSwapChainImplementation m_swapChainImpl{}; -}; - -BackendBinding *CreateMetalBinding(SDL_Window *window, WGPUDevice device) { return new MetalBinding(window, device); } -} // namespace aurora::gpu::utils diff --git a/aurora/lib/dawn/NullBinding.cpp b/aurora/lib/dawn/NullBinding.cpp deleted file mode 100644 index 7db94102e..000000000 --- a/aurora/lib/dawn/NullBinding.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "BackendBinding.hpp" - -#include -#include - -namespace aurora::gpu::utils { -class NullBinding : public BackendBinding { -public: - NullBinding(SDL_Window* window, WGPUDevice device) : BackendBinding(window, device) {} - - uint64_t GetSwapChainImplementation() override { - if (m_swapChainImpl.userData == nullptr) { - m_swapChainImpl = dawn::native::null::CreateNativeSwapChainImpl(); - } - return reinterpret_cast(&m_swapChainImpl); - } - - WGPUTextureFormat GetPreferredSwapChainTextureFormat() override { - return WGPUTextureFormat_RGBA8Unorm; - } - -private: - DawnSwapChainImplementation m_swapChainImpl{}; -}; - -BackendBinding* CreateNullBinding(SDL_Window* window, WGPUDevice device) { return new NullBinding(window, device); } -} // namespace aurora::gpu::utils diff --git a/aurora/lib/dawn/OpenGLBinding.cpp b/aurora/lib/dawn/OpenGLBinding.cpp deleted file mode 100644 index 41c379b15..000000000 --- a/aurora/lib/dawn/OpenGLBinding.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "BackendBinding.hpp" - -#include -#include - -namespace aurora::gpu::utils { -class OpenGLBinding : public BackendBinding { -public: - OpenGLBinding(SDL_Window* window, WGPUDevice device) : BackendBinding(window, device) {} - - uint64_t GetSwapChainImplementation() override { - if (m_swapChainImpl.userData == nullptr) { - CreateSwapChainImpl(); - } - return reinterpret_cast(&m_swapChainImpl); - } - - WGPUTextureFormat GetPreferredSwapChainTextureFormat() override { - if (m_swapChainImpl.userData == nullptr) { - CreateSwapChainImpl(); - } - return dawn::native::opengl::GetNativeSwapChainPreferredFormat(&m_swapChainImpl); - } - -private: - DawnSwapChainImplementation m_swapChainImpl{}; - - void CreateSwapChainImpl() { - m_swapChainImpl = dawn::native::opengl::CreateNativeSwapChainImpl( - m_device, [](void* userdata) { SDL_GL_SwapWindow(static_cast(userdata)); }, m_window); - } -}; - -BackendBinding* CreateOpenGLBinding(SDL_Window* window, WGPUDevice device) { return new OpenGLBinding(window, device); } -} // namespace aurora::gpu::utils diff --git a/aurora/lib/dawn/VulkanBinding.cpp b/aurora/lib/dawn/VulkanBinding.cpp deleted file mode 100644 index eef46ffcb..000000000 --- a/aurora/lib/dawn/VulkanBinding.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "BackendBinding.hpp" - -#include -#include -#include - -#include - -namespace aurora::gpu::utils { -static logvisor::Module Log("aurora::gpu::utils::VulkanBinding"); - -class VulkanBinding : public BackendBinding { -public: - VulkanBinding(SDL_Window* window, WGPUDevice device) : BackendBinding(window, device) {} - - uint64_t GetSwapChainImplementation() override { - if (m_swapChainImpl.userData == nullptr) { - CreateSwapChainImpl(); - } - return reinterpret_cast(&m_swapChainImpl); - } - - WGPUTextureFormat GetPreferredSwapChainTextureFormat() override { - if (m_swapChainImpl.userData == nullptr) { - CreateSwapChainImpl(); - } - return dawn::native::vulkan::GetNativeSwapChainPreferredFormat(&m_swapChainImpl); - } - -private: - DawnSwapChainImplementation m_swapChainImpl{}; - - void CreateSwapChainImpl() { - VkSurfaceKHR surface = VK_NULL_HANDLE; - if (SDL_Vulkan_CreateSurface(m_window, dawn::native::vulkan::GetInstance(m_device), &surface) != SDL_TRUE) { - Log.report(logvisor::Fatal, FMT_STRING("Failed to create Vulkan surface: {}"), SDL_GetError()); - } - m_swapChainImpl = dawn::native::vulkan::CreateNativeSwapChainImpl(m_device, surface); - } -}; - -BackendBinding* CreateVulkanBinding(SDL_Window* window, WGPUDevice device) { return new VulkanBinding(window, device); } -} // namespace aurora::gpu::utils diff --git a/aurora/lib/gfx/common.cpp b/aurora/lib/gfx/common.cpp deleted file mode 100644 index 791dc25ab..000000000 --- a/aurora/lib/gfx/common.cpp +++ /dev/null @@ -1,797 +0,0 @@ -#include "common.hpp" - -#include "../gpu.hpp" -#include "model/shader.hpp" -#include "movie_player/shader.hpp" -#include "stream/shader.hpp" - -#include -#include -#include -#include -#include -#include - -namespace aurora { -extern std::string g_configPath; -} // namespace aurora - -namespace aurora::gfx { -static logvisor::Module Log("aurora::gfx"); - -using gpu::g_device; -using gpu::g_queue; - -#ifdef AURORA_GFX_DEBUG_GROUPS -std::vector g_debugGroupStack; -#endif - -constexpr uint64_t UniformBufferSize = 3145728; // 3mb -constexpr uint64_t VertexBufferSize = 3145728; // 3mb -constexpr uint64_t IndexBufferSize = 1048576; // 1mb -constexpr uint64_t StorageBufferSize = 8388608; // 8mb -constexpr uint64_t TextureUploadSize = 25165824; // 24mb - -constexpr uint64_t StagingBufferSize = - UniformBufferSize + VertexBufferSize + IndexBufferSize + StorageBufferSize + TextureUploadSize; - -struct ShaderState { - movie_player::State moviePlayer; - stream::State stream; - model::State model; -}; -struct ShaderDrawCommand { - ShaderType type; - union { - movie_player::DrawData moviePlayer; - stream::DrawData stream; - model::DrawData model; - }; -}; -enum class CommandType { - SetViewport, - SetScissor, - Draw, -}; -struct Command { - CommandType type; -#ifdef AURORA_GFX_DEBUG_GROUPS - std::vector debugGroupStack; -#endif - union Data { - struct SetViewportCommand { - float left; - float top; - float width; - float height; - float znear; - float zfar; - - bool operator==(const SetViewportCommand& rhs) const { - return left == rhs.left && top == rhs.top && width == rhs.width && height == rhs.height && znear == rhs.znear && - zfar == rhs.zfar; - } - bool operator!=(const SetViewportCommand& rhs) const { return !(*this == rhs); } - } setViewport; - struct SetScissorCommand { - uint32_t x; - uint32_t y; - uint32_t w; - uint32_t h; - - bool operator==(const SetScissorCommand& rhs) const { - return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h; - } - bool operator!=(const SetScissorCommand& rhs) const { return !(*this == rhs); } - } setScissor; - ShaderDrawCommand draw; - } data; -}; -} // namespace aurora::gfx - -namespace aurora { -// For types that we can't ensure are safe to hash with has_unique_object_representations, -// we create specialized methods to handle them. Note that these are highly dependent on -// the structure definition, which could easily change with Dawn updates. -template <> -inline XXH64_hash_t xxh3_hash(const wgpu::BindGroupDescriptor& input, XXH64_hash_t seed) { - constexpr auto offset = sizeof(void*) * 2; // skip nextInChain, label - const auto hash = xxh3_hash_s(reinterpret_cast(&input) + offset, - sizeof(wgpu::BindGroupDescriptor) - offset - sizeof(void*) /* skip entries */, seed); - return xxh3_hash_s(input.entries, sizeof(wgpu::BindGroupEntry) * input.entryCount, hash); -} -template <> -inline XXH64_hash_t xxh3_hash(const wgpu::SamplerDescriptor& input, XXH64_hash_t seed) { - constexpr auto offset = sizeof(void*) * 2; // skip nextInChain, label - return xxh3_hash_s(reinterpret_cast(&input) + offset, - sizeof(wgpu::SamplerDescriptor) - offset - 2 /* skip padding */, seed); -} -} // namespace aurora - -namespace aurora::gfx { -using NewPipelineCallback = std::function; -std::mutex g_pipelineMutex; -static bool g_hasPipelineThread = false; -static std::thread g_pipelineThread; -static std::atomic_bool g_pipelineThreadEnd; -static std::condition_variable g_pipelineCv; -static absl::flat_hash_map g_pipelines; -static std::deque> g_queuedPipelines; -static absl::flat_hash_map g_cachedBindGroups; -static absl::flat_hash_map g_cachedSamplers; -std::atomic_uint32_t queuedPipelines; -std::atomic_uint32_t createdPipelines; - -static ByteBuffer g_verts; -static ByteBuffer g_uniforms; -static ByteBuffer g_indices; -static ByteBuffer g_storage; -static ByteBuffer g_staticStorage; -static ByteBuffer g_textureUpload; -wgpu::Buffer g_vertexBuffer; -wgpu::Buffer g_uniformBuffer; -wgpu::Buffer g_indexBuffer; -wgpu::Buffer g_storageBuffer; -size_t g_staticStorageLastSize = 0; -static std::array g_stagingBuffers; -static wgpu::SupportedLimits g_cachedLimits; - -static ShaderState g_state; -static PipelineRef g_currentPipeline; - -using CommandList = std::vector; -struct RenderPass { - u32 resolveTarget = UINT32_MAX; - ClipRect resolveRect; - zeus::CColor clearColor{0.f, 0.f}; - CommandList commands; - bool clear = true; -}; -static std::vector g_renderPasses; -static u32 g_currentRenderPass; -std::vector g_resolvedTextures; -std::vector g_textureUploads; - -static ByteBuffer g_serializedPipelines{}; -static u32 g_serializedPipelineCount = 0; - -template -static void serialize_pipeline_config(ShaderType type, const PipelineConfig& config) { - static_assert(std::has_unique_object_representations_v); - g_serializedPipelines.append(&type, sizeof(type)); - const u32 configSize = sizeof(config); - g_serializedPipelines.append(&configSize, sizeof(configSize)); - g_serializedPipelines.append(&config, configSize); - ++g_serializedPipelineCount; -} - -template -static PipelineRef find_pipeline(ShaderType type, const PipelineConfig& config, NewPipelineCallback&& cb, - bool serialize = true) { - PipelineRef hash = xxh3_hash(config, static_cast(type)); - bool found = false; - { - std::scoped_lock guard{g_pipelineMutex}; - found = g_pipelines.contains(hash); - if (!found) { - if (g_hasPipelineThread) { - const auto ref = - std::find_if(g_queuedPipelines.begin(), g_queuedPipelines.end(), [=](auto v) { return v.first == hash; }); - if (ref != g_queuedPipelines.end()) { - found = true; - } - } else { - g_pipelines.try_emplace(hash, cb()); - if (serialize) { - serialize_pipeline_config(type, config); - } - found = true; - } - } - if (!found) { - g_queuedPipelines.emplace_back(std::pair{hash, std::move(cb)}); - if (serialize) { - serialize_pipeline_config(type, config); - } - } - } - if (!found) { - g_pipelineCv.notify_one(); - queuedPipelines++; - } - return hash; -} - -static inline void push_command(CommandType type, const Command::Data& data) { - g_renderPasses[g_currentRenderPass].commands.push_back({ - .type = type, -#ifdef AURORA_GFX_DEBUG_GROUPS - .debugGroupStack = g_debugGroupStack, -#endif - .data = data, - }); -} - -static void push_draw_command(ShaderDrawCommand data) { push_command(CommandType::Draw, Command::Data{.draw = data}); } - -static Command::Data::SetViewportCommand g_cachedViewport; -void set_viewport(float left, float top, float width, float height, float znear, float zfar) noexcept { - Command::Data::SetViewportCommand cmd{left, top, width, height, znear, zfar}; - if (cmd != g_cachedViewport) { - push_command(CommandType::SetViewport, Command::Data{.setViewport = cmd}); - g_cachedViewport = cmd; - } -} -static Command::Data::SetScissorCommand g_cachedScissor; -void set_scissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) noexcept { - Command::Data::SetScissorCommand cmd{x, y, w, h}; - if (cmd != g_cachedScissor) { - push_command(CommandType::SetScissor, Command::Data{.setScissor = cmd}); - g_cachedScissor = cmd; - } -} - -static inline bool operator==(const wgpu::Extent3D& lhs, const wgpu::Extent3D& rhs) { - return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depthOrArrayLayers == rhs.depthOrArrayLayers; -} -static inline bool operator!=(const wgpu::Extent3D& lhs, const wgpu::Extent3D& rhs) { - return !(lhs == rhs); -} - -void resolve_color(const ClipRect& rect, uint32_t bind, GX::TextureFormat fmt, bool clear_depth) noexcept { - if (g_resolvedTextures.size() < bind + 1) { - g_resolvedTextures.resize(bind + 1); - } - const wgpu::Extent3D size{ - .width = static_cast(rect.width), - .height = static_cast(rect.height), - }; - if (!g_resolvedTextures[bind] || g_resolvedTextures[bind]->size != size) { - g_resolvedTextures[bind] = new_render_texture(rect.width, rect.height, fmt, "Resolved Texture"); - } - auto& currentPass = g_renderPasses[g_currentRenderPass]; - currentPass.resolveTarget = bind; - currentPass.resolveRect = rect; - auto& newPass = g_renderPasses.emplace_back(); - newPass.clearColor = gx::g_gxState.clearColor; - newPass.clear = false; // TODO - ++g_currentRenderPass; -} -void resolve_depth(const ClipRect& rect, uint32_t bind, GX::TextureFormat fmt) noexcept { - // TODO -} - -void queue_movie_player(const TextureHandle& tex_y, const TextureHandle& tex_u, const TextureHandle& tex_v, float h_pad, - float v_pad) noexcept { - auto data = movie_player::make_draw_data(g_state.moviePlayer, tex_y, tex_u, tex_v, h_pad, v_pad); - push_draw_command({.type = ShaderType::MoviePlayer, .moviePlayer = data}); -} -template <> -PipelineRef pipeline_ref(movie_player::PipelineConfig config) { - return find_pipeline(ShaderType::MoviePlayer, config, [=]() { return create_pipeline(g_state.moviePlayer, config); }); -} - -template <> -const stream::State& get_state() { - return g_state.stream; -} -template <> -void push_draw_command(stream::DrawData data) { - push_draw_command(ShaderDrawCommand{.type = ShaderType::Stream, .stream = data}); -} -template <> -PipelineRef pipeline_ref(stream::PipelineConfig config) { - return find_pipeline(ShaderType::Stream, config, [=]() { return create_pipeline(g_state.stream, config); }); -} - -template <> -void push_draw_command(model::DrawData data) { - push_draw_command(ShaderDrawCommand{.type = ShaderType::Model, .model = data}); -} -template <> -PipelineRef pipeline_ref(model::PipelineConfig config) { - return find_pipeline(ShaderType::Model, config, [=]() { return create_pipeline(g_state.model, config); }); -} - -static void pipeline_worker() { - bool hasMore = false; - while (true) { - std::pair cb; - { - std::unique_lock lock{g_pipelineMutex}; - if (!hasMore) { - g_pipelineCv.wait(lock, [] { return !g_queuedPipelines.empty() || g_pipelineThreadEnd; }); - } - if (g_pipelineThreadEnd) { - break; - } - cb = std::move(g_queuedPipelines.front()); - } - auto result = cb.second(); - // std::this_thread::sleep_for(std::chrono::milliseconds{1500}); - { - std::scoped_lock lock{g_pipelineMutex}; - if (!g_pipelines.try_emplace(cb.first, std::move(result)).second) { - Log.report(logvisor::Fatal, FMT_STRING("Duplicate pipeline {}"), cb.first); - unreachable(); - } - g_queuedPipelines.pop_front(); - hasMore = !g_queuedPipelines.empty(); - } - createdPipelines++; - queuedPipelines--; - } -} - -void initialize() { - // No async pipelines for OpenGL (ES) - if (gpu::g_backendType == wgpu::BackendType::OpenGL || gpu::g_backendType == wgpu::BackendType::OpenGLES) { - g_hasPipelineThread = false; - } else { - g_pipelineThreadEnd = false; - g_pipelineThread = std::thread(pipeline_worker); - g_hasPipelineThread = true; - } - - // For uniform & storage buffer offset alignments - g_device.GetLimits(&g_cachedLimits); - - const auto createBuffer = [](wgpu::Buffer& out, wgpu::BufferUsage usage, uint64_t size, const char* label) { - const wgpu::BufferDescriptor descriptor{ - .label = label, - .usage = usage, - .size = size, - }; - out = g_device.CreateBuffer(&descriptor); - }; - createBuffer(g_uniformBuffer, wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst, UniformBufferSize, - "Shared Uniform Buffer"); - createBuffer(g_vertexBuffer, wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst, VertexBufferSize, - "Shared Vertex Buffer"); - createBuffer(g_indexBuffer, wgpu::BufferUsage::Index | wgpu::BufferUsage::CopyDst, IndexBufferSize, - "Shared Index Buffer"); - createBuffer(g_storageBuffer, wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopyDst, StorageBufferSize, - "Shared Storage Buffer"); - for (int i = 0; i < g_stagingBuffers.size(); ++i) { - const auto label = fmt::format(FMT_STRING("Staging Buffer {}"), i); - createBuffer(g_stagingBuffers[i], wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, StagingBufferSize, - label.c_str()); - } - map_staging_buffer(); - - g_state.moviePlayer = movie_player::construct_state(); - g_state.stream = stream::construct_state(); - g_state.model = model::construct_state(); - - { - // Load serialized pipeline cache - std::string path = g_configPath + "pipeline_cache.bin"; - std::ifstream file(path, std::ios::in | std::ios::binary | std::ios::ate); - if (file) { - const size_t size = file.tellg(); - file.seekg(0, std::ios::beg); - constexpr size_t headerSize = sizeof(g_serializedPipelineCount); - if (size != -1 && size > headerSize) { - g_serializedPipelines.append_zeroes(size - headerSize); - file.read(reinterpret_cast(&g_serializedPipelineCount), headerSize); - file.read(reinterpret_cast(g_serializedPipelines.data()), size - headerSize); - } - } - } - if (g_serializedPipelineCount > 0) { - size_t offset = 0; - while (offset < g_serializedPipelines.size()) { - ShaderType type = *reinterpret_cast(g_serializedPipelines.data() + offset); - offset += sizeof(ShaderType); - u32 size = *reinterpret_cast(g_serializedPipelines.data() + offset); - offset += sizeof(u32); - switch (type) { - case ShaderType::MoviePlayer: { - if (size != sizeof(movie_player::PipelineConfig)) { - break; - } - const auto config = - *reinterpret_cast(g_serializedPipelines.data() + offset); - find_pipeline( - type, config, [=]() { return movie_player::create_pipeline(g_state.moviePlayer, config); }, false); - } break; - case ShaderType::Stream: { - if (size != sizeof(stream::PipelineConfig)) { - break; - } - const auto config = *reinterpret_cast(g_serializedPipelines.data() + offset); - if (config.version != gx::GXPipelineConfigVersion) { - break; - } - find_pipeline( - type, config, [=]() { return stream::create_pipeline(g_state.stream, config); }, false); - } break; - case ShaderType::Model: { - if (size != sizeof(model::PipelineConfig)) { - break; - } - const auto config = *reinterpret_cast(g_serializedPipelines.data() + offset); - if (config.version != gx::GXPipelineConfigVersion) { - break; - } - find_pipeline( - type, config, [=]() { return model::create_pipeline(g_state.model, config); }, false); - } break; - default: - Log.report(logvisor::Warning, FMT_STRING("Unknown pipeline type {}"), type); - break; - } - offset += size; - } - } -} - -void shutdown() { - if (g_hasPipelineThread) { - g_pipelineThreadEnd = true; - g_pipelineCv.notify_all(); - g_pipelineThread.join(); - } - - { - // Write serialized pipelines to file - std::ofstream file(g_configPath + "pipeline_cache.bin", std::ios::out | std::ios::trunc | std::ios::binary); - if (file) { - file.write(reinterpret_cast(&g_serializedPipelineCount), sizeof(g_serializedPipelineCount)); - file.write(reinterpret_cast(g_serializedPipelines.data()), g_serializedPipelines.size()); - } - g_serializedPipelines.clear(); - g_serializedPipelineCount = 0; - } - - gx::shutdown(); - - g_resolvedTextures.clear(); - g_textureUploads.clear(); - g_cachedBindGroups.clear(); - g_cachedSamplers.clear(); - g_pipelines.clear(); - g_queuedPipelines.clear(); - g_vertexBuffer = {}; - g_uniformBuffer = {}; - g_indexBuffer = {}; - g_storageBuffer = {}; - g_stagingBuffers.fill({}); - g_renderPasses.clear(); - g_currentRenderPass = 0; - - g_state = {}; - - queuedPipelines = 0; - createdPipelines = 0; -} - -static size_t currentStagingBuffer = 0; -static bool bufferMapped = false; -void map_staging_buffer() { - bufferMapped = false; - g_stagingBuffers[currentStagingBuffer].MapAsync( - wgpu::MapMode::Write, 0, StagingBufferSize, - [](WGPUBufferMapAsyncStatus status, void* userdata) { - if (status == WGPUBufferMapAsyncStatus_DestroyedBeforeCallback) { - return; - } else if (status != WGPUBufferMapAsyncStatus_Success) { - Log.report(logvisor::Fatal, FMT_STRING("Buffer mapping failed: {}"), status); - unreachable(); - } - *static_cast(userdata) = true; - }, - &bufferMapped); -} - -void begin_frame() { - while (!bufferMapped) { - g_device.Tick(); - } - size_t bufferOffset = 0; - auto& stagingBuf = g_stagingBuffers[currentStagingBuffer]; - const auto mapBuffer = [&](ByteBuffer& buf, uint64_t size) { - buf = ByteBuffer{static_cast(stagingBuf.GetMappedRange(bufferOffset, size)), size}; - bufferOffset += size; - }; - mapBuffer(g_verts, VertexBufferSize); - mapBuffer(g_uniforms, UniformBufferSize); - mapBuffer(g_indices, IndexBufferSize); - mapBuffer(g_storage, StorageBufferSize); - mapBuffer(g_textureUpload, TextureUploadSize); - - g_renderPasses.emplace_back(); - g_currentRenderPass = 0; -} - -// for imgui debug -size_t g_lastVertSize; -size_t g_lastUniformSize; -size_t g_lastIndexSize; -size_t g_lastStorageSize; - -void end_frame(const wgpu::CommandEncoder& cmd) { - uint64_t bufferOffset = 0; - const auto writeBuffer = [&](ByteBuffer& buf, wgpu::Buffer& out, uint64_t size, std::string_view label) { - const auto writeSize = buf.size(); // Only need to copy this many bytes - if (writeSize > 0) { - cmd.CopyBufferToBuffer(g_stagingBuffers[currentStagingBuffer], bufferOffset, out, 0, writeSize); - buf.clear(); - } - bufferOffset += size; - return writeSize; - }; - g_stagingBuffers[currentStagingBuffer].Unmap(); - g_lastVertSize = writeBuffer(g_verts, g_vertexBuffer, VertexBufferSize, "Vertex"); - g_lastUniformSize = writeBuffer(g_uniforms, g_uniformBuffer, UniformBufferSize, "Uniform"); - g_lastIndexSize = writeBuffer(g_indices, g_indexBuffer, IndexBufferSize, "Index"); - g_lastStorageSize = writeBuffer(g_storage, g_storageBuffer, StorageBufferSize, "Storage"); - { - // Perform texture copies - for (const auto& item : g_textureUploads) { - const wgpu::ImageCopyBuffer buf{ - .layout = - wgpu::TextureDataLayout{ - .offset = item.layout.offset + bufferOffset, - .bytesPerRow = ALIGN(item.layout.bytesPerRow, 256), - .rowsPerImage = item.layout.rowsPerImage, - }, - .buffer = g_stagingBuffers[currentStagingBuffer], - }; - cmd.CopyBufferToTexture(&buf, &item.tex, &item.size); - } - g_textureUploads.clear(); - g_textureUpload.clear(); - } - currentStagingBuffer = (currentStagingBuffer + 1) % g_stagingBuffers.size(); - map_staging_buffer(); -} - -void render(wgpu::CommandEncoder& cmd) { - for (u32 i = 0; i < g_renderPasses.size(); ++i) { - const auto& passInfo = g_renderPasses[i]; - bool finalPass = i == g_renderPasses.size() - 1; - if (finalPass && passInfo.resolveTarget != UINT32_MAX) { - Log.report(logvisor::Fatal, FMT_STRING("Final render pass must not have resolve target")); - unreachable(); - } - const std::array attachments{ - wgpu::RenderPassColorAttachment{ - .view = gpu::g_frameBuffer.view, - .resolveTarget = gpu::g_graphicsConfig.msaaSamples > 1 ? gpu::g_frameBufferResolved.view : nullptr, - .loadOp = passInfo.clear ? wgpu::LoadOp::Clear : wgpu::LoadOp::Load, - .storeOp = wgpu::StoreOp::Store, - .clearValue = - { - .r = passInfo.clearColor.r(), - .g = passInfo.clearColor.g(), - .b = passInfo.clearColor.b(), - .a = passInfo.clearColor.a(), - }, - }, - }; - const wgpu::RenderPassDepthStencilAttachment depthStencilAttachment{ - .view = gpu::g_depthBuffer.view, - .depthLoadOp = passInfo.clear ? wgpu::LoadOp::Clear : wgpu::LoadOp::Load, - .depthStoreOp = wgpu::StoreOp::Store, - .depthClearValue = 1.f, - }; - const auto label = fmt::format(FMT_STRING("Render pass {}"), i); - const wgpu::RenderPassDescriptor renderPassDescriptor{ - .label = label.c_str(), - .colorAttachmentCount = attachments.size(), - .colorAttachments = attachments.data(), - .depthStencilAttachment = &depthStencilAttachment, - }; - auto pass = cmd.BeginRenderPass(&renderPassDescriptor); - render_pass(pass, i); - pass.End(); - - if (passInfo.resolveTarget != UINT32_MAX) { - wgpu::ImageCopyTexture src{ - .origin = - wgpu::Origin3D{ - .x = static_cast(passInfo.resolveRect.x), - .y = static_cast(passInfo.resolveRect.y), - }, - }; - if (gpu::g_graphicsConfig.msaaSamples > 1) { - src.texture = gpu::g_frameBufferResolved.texture; - } else { - src.texture = gpu::g_frameBuffer.texture; - } - auto& target = g_resolvedTextures[passInfo.resolveTarget]; - const wgpu::ImageCopyTexture dst{ - .texture = target->texture, - }; - const wgpu::Extent3D size{ - .width = static_cast(passInfo.resolveRect.width), - .height = static_cast(passInfo.resolveRect.height), - }; - cmd.CopyTextureToTexture(&src, &dst, &size); - } - } - g_renderPasses.clear(); -} - -void render_pass(const wgpu::RenderPassEncoder& pass, u32 idx) { - g_currentPipeline = UINT64_MAX; -#ifdef AURORA_GFX_DEBUG_GROUPS - std::vector lastDebugGroupStack; -#endif - - for (const auto& cmd : g_renderPasses[idx].commands) { -#ifdef AURORA_GFX_DEBUG_GROUPS - { - size_t firstDiff = lastDebugGroupStack.size(); - for (size_t i = 0; i < lastDebugGroupStack.size(); ++i) { - if (i >= cmd.debugGroupStack.size() || cmd.debugGroupStack[i] != lastDebugGroupStack[i]) { - firstDiff = i; - break; - } - } - for (size_t i = firstDiff; i < lastDebugGroupStack.size(); ++i) { - pass.PopDebugGroup(); - } - for (size_t i = firstDiff; i < cmd.debugGroupStack.size(); ++i) { - pass.PushDebugGroup(cmd.debugGroupStack[i].c_str()); - } - lastDebugGroupStack = cmd.debugGroupStack; - } -#endif - switch (cmd.type) { - case CommandType::SetViewport: { - const auto& vp = cmd.data.setViewport; - pass.SetViewport(vp.left, vp.top, vp.width, vp.height, vp.znear, vp.zfar); - } break; - case CommandType::SetScissor: { - const auto& sc = cmd.data.setScissor; - pass.SetScissorRect(sc.x, sc.y, sc.w, sc.h); - } break; - case CommandType::Draw: { - const auto& draw = cmd.data.draw; - switch (draw.type) { - case ShaderType::MoviePlayer: - movie_player::render(g_state.moviePlayer, draw.moviePlayer, pass); - break; - case ShaderType::Stream: - stream::render(g_state.stream, draw.stream, pass); - break; - case ShaderType::Model: - model::render(g_state.model, draw.model, pass); - break; - } - } break; - } - } - -#ifdef AURORA_GFX_DEBUG_GROUPS - for (size_t i = 0; i < lastDebugGroupStack.size(); ++i) { - pass.PopDebugGroup(); - } -#endif -} - -bool bind_pipeline(PipelineRef ref, const wgpu::RenderPassEncoder& pass) { - if (ref == g_currentPipeline) { - return true; - } - std::lock_guard guard{g_pipelineMutex}; - const auto it = g_pipelines.find(ref); - if (it == g_pipelines.end()) { - return false; - } - pass.SetPipeline(it->second); - g_currentPipeline = ref; - return true; -} - -static inline Range push(ByteBuffer& target, const uint8_t* data, size_t length, size_t alignment) { - size_t padding = 0; - if (alignment != 0) { - padding = alignment - length % alignment; - } - auto begin = target.size(); - if (length == 0) { - length = alignment; - target.append_zeroes(alignment); - } else { - target.append(data, length); - if (padding > 0) { - target.append_zeroes(padding); - } - } - return {static_cast(begin), static_cast(length + padding)}; -} -static inline Range map(ByteBuffer& target, size_t length, size_t alignment) { - size_t padding = 0; - if (alignment != 0) { - padding = alignment - length % alignment; - } - if (length == 0) { - length = alignment; - } - auto begin = target.size(); - target.append_zeroes(length + padding); - return {static_cast(begin), static_cast(length + padding)}; -} -Range push_verts(const uint8_t* data, size_t length) { return push(g_verts, data, length, 4); } -Range push_indices(const uint8_t* data, size_t length) { return push(g_indices, data, length, 4); } -Range push_uniform(const uint8_t* data, size_t length) { - return push(g_uniforms, data, length, g_cachedLimits.limits.minUniformBufferOffsetAlignment); -} -Range push_storage(const uint8_t* data, size_t length) { - return push(g_storage, data, length, g_cachedLimits.limits.minStorageBufferOffsetAlignment); -} -Range push_static_storage(const uint8_t* data, size_t length) { - auto range = push(g_staticStorage, data, length, g_cachedLimits.limits.minStorageBufferOffsetAlignment); - range.isStatic = true; - return range; -} -Range push_texture_data(const uint8_t* data, size_t length, u32 bytesPerRow, u32 rowsPerImage) { - // For CopyBufferToTexture, we need an alignment of 256 per row (see Dawn kTextureBytesPerRowAlignment) - const auto copyBytesPerRow = ALIGN(bytesPerRow, 256); - const auto range = map(g_textureUpload, copyBytesPerRow * rowsPerImage, 0); - u8* dst = g_textureUpload.data() + range.offset; - for (u32 i = 0; i < rowsPerImage; ++i) { - memcpy(dst, data, bytesPerRow); - data += bytesPerRow; - dst += copyBytesPerRow; - } - return range; -} -std::pair map_verts(size_t length) { - const auto range = map(g_verts, length, 4); - return {ByteBuffer{g_verts.data() + range.offset, range.size}, range}; -} -std::pair map_indices(size_t length) { - const auto range = map(g_indices, length, 4); - return {ByteBuffer{g_indices.data() + range.offset, range.size}, range}; -} -std::pair map_uniform(size_t length) { - const auto range = map(g_uniforms, length, g_cachedLimits.limits.minUniformBufferOffsetAlignment); - return {ByteBuffer{g_uniforms.data() + range.offset, range.size}, range}; -} -std::pair map_storage(size_t length) { - const auto range = map(g_storage, length, g_cachedLimits.limits.minStorageBufferOffsetAlignment); - return {ByteBuffer{g_storage.data() + range.offset, range.size}, range}; -} - -BindGroupRef bind_group_ref(const wgpu::BindGroupDescriptor& descriptor) { - const auto id = xxh3_hash(descriptor); - if (!g_cachedBindGroups.contains(id)) { - g_cachedBindGroups.try_emplace(id, g_device.CreateBindGroup(&descriptor)); - } - return id; -} -const wgpu::BindGroup& find_bind_group(BindGroupRef id) { - const auto it = g_cachedBindGroups.find(id); - if (it == g_cachedBindGroups.end()) { - Log.report(logvisor::Fatal, FMT_STRING("get_bind_group: failed to locate {}"), id); - unreachable(); - } - return it->second; -} - -const wgpu::Sampler& sampler_ref(const wgpu::SamplerDescriptor& descriptor) { - const auto id = xxh3_hash(descriptor); - auto it = g_cachedSamplers.find(id); - if (it == g_cachedSamplers.end()) { - it = g_cachedSamplers.try_emplace(id, g_device.CreateSampler(&descriptor)).first; - } - return it->second; -} - -uint32_t align_uniform(uint32_t value) { return ALIGN(value, g_cachedLimits.limits.minUniformBufferOffsetAlignment); } - -void push_debug_group(zstring_view label) noexcept { -#ifdef AURORA_GFX_DEBUG_GROUPS - g_debugGroupStack.emplace_back(label); -#endif -} -void pop_debug_group() noexcept { -#ifdef AURORA_GFX_DEBUG_GROUPS - g_debugGroupStack.pop_back(); -#endif -} -} // namespace aurora::gfx diff --git a/aurora/lib/gfx/common.hpp b/aurora/lib/gfx/common.hpp deleted file mode 100644 index a6694fc5f..000000000 --- a/aurora/lib/gfx/common.hpp +++ /dev/null @@ -1,243 +0,0 @@ -#pragma once -#include - -#include -#include - -#include -#include - -#ifndef ALIGN -#define ALIGN(x, a) (((x) + ((a)-1)) & ~((a)-1)) -#endif - -namespace aurora { -static inline XXH64_hash_t xxh3_hash_s(const void* input, size_t len, XXH64_hash_t seed = 0) { - return XXH3_64bits_withSeed(input, len, seed); -} -template -static inline XXH64_hash_t xxh3_hash(const T& input, XXH64_hash_t seed = 0) { - // Validate that the type has no padding bytes, which can easily cause - // hash mismatches. This also disallows floats, but that's okay for us. - static_assert(std::has_unique_object_representations_v); - return xxh3_hash_s(&input, sizeof(T), seed); -} - -class ByteBuffer { -public: - ByteBuffer() noexcept = default; - explicit ByteBuffer(size_t size) noexcept - : m_data(static_cast(calloc(1, size))), m_length(size), m_capacity(size) {} - explicit ByteBuffer(uint8_t* data, size_t size) noexcept - : m_data(data), m_length(0), m_capacity(size), m_owned(false) {} - ~ByteBuffer() noexcept { - if (m_data != nullptr && m_owned) { - free(m_data); - } - } - ByteBuffer(ByteBuffer&& rhs) noexcept - : m_data(rhs.m_data), m_length(rhs.m_length), m_capacity(rhs.m_capacity), m_owned(rhs.m_owned) { - rhs.m_data = nullptr; - rhs.m_length = 0; - rhs.m_capacity = 0; - rhs.m_owned = true; - } - ByteBuffer& operator=(ByteBuffer&& rhs) noexcept { - if (m_data != nullptr && m_owned) { - free(m_data); - } - m_data = rhs.m_data; - m_length = rhs.m_length; - m_capacity = rhs.m_capacity; - m_owned = rhs.m_owned; - rhs.m_data = nullptr; - rhs.m_length = 0; - rhs.m_capacity = 0; - rhs.m_owned = true; - return *this; - } - ByteBuffer(ByteBuffer const&) = delete; - ByteBuffer& operator=(ByteBuffer const&) = delete; - - [[nodiscard]] uint8_t* data() noexcept { return m_data; } - [[nodiscard]] const uint8_t* data() const noexcept { return m_data; } - [[nodiscard]] size_t size() const noexcept { return m_length; } - [[nodiscard]] bool empty() const noexcept { return m_length == 0; } - - void append(const void* data, size_t size) { - resize(m_length + size, false); - memcpy(m_data + m_length, data, size); - m_length += size; - } - - void append_zeroes(size_t size) { - resize(m_length + size, true); - m_length += size; - } - - void clear() { - if (m_data != nullptr && m_owned) { - free(m_data); - } - m_data = nullptr; - m_length = 0; - m_capacity = 0; - m_owned = true; - } - - void reserve_extra(size_t size) { resize(m_length + size, true); } - -private: - uint8_t* m_data = nullptr; - size_t m_length = 0; - size_t m_capacity = 0; - bool m_owned = true; - - void resize(size_t size, bool zeroed) { - if (size == 0) { - clear(); - } else if (m_data == nullptr) { - if (zeroed) { - m_data = static_cast(calloc(1, size)); - } else { - m_data = static_cast(malloc(size)); - } - m_owned = true; - } else if (size > m_capacity) { - if (!m_owned) { - abort(); - } - m_data = static_cast(realloc(m_data, size)); - if (zeroed) { - memset(m_data + m_capacity, 0, size - m_capacity); - } - } else { - return; - } - m_capacity = size; - } -}; -} // namespace aurora - -namespace aurora::gfx { -extern wgpu::Buffer g_vertexBuffer; -extern wgpu::Buffer g_uniformBuffer; -extern wgpu::Buffer g_indexBuffer; -extern wgpu::Buffer g_storageBuffer; -extern size_t g_staticStorageLastSize; -struct TextureUpload { - wgpu::TextureDataLayout layout; - wgpu::ImageCopyTexture tex; - wgpu::Extent3D size; - - TextureUpload(wgpu::TextureDataLayout layout, wgpu::ImageCopyTexture tex, wgpu::Extent3D size) noexcept - : layout(std::move(layout)), tex(std::move(tex)), size(std::move(size)) {} -}; -extern std::vector g_textureUploads; -// TODO this is a bad place for this... -extern std::vector g_resolvedTextures; - -constexpr GX::TextureFormat InvalidTextureFormat = static_cast(-1); -struct TextureRef { - wgpu::Texture texture; - wgpu::TextureView view; - wgpu::Extent3D size; - wgpu::TextureFormat format; - uint32_t mipCount; - GX::TextureFormat gxFormat; - bool isRenderTexture; // :shrug: for now - - TextureRef(wgpu::Texture&& texture, wgpu::TextureView&& view, wgpu::Extent3D size, wgpu::TextureFormat format, - uint32_t mipCount, GX::TextureFormat gxFormat, bool isRenderTexture) - : texture(std::move(texture)) - , view(std::move(view)) - , size(size) - , format(format) - , mipCount(mipCount) - , gxFormat(gxFormat) - , isRenderTexture(isRenderTexture) {} -}; - -using BindGroupRef = uint64_t; -using PipelineRef = uint64_t; -using SamplerRef = uint64_t; -using ShaderRef = uint64_t; -struct Range { - uint32_t offset; - uint32_t size; - bool isStatic; -}; -static inline uint32_t storage_offset(Range range) { - return range.isStatic ? range.offset : range.offset + g_staticStorageLastSize; -} - -enum class ShaderType { - MoviePlayer, - Stream, - Model, -}; - -void initialize(); -void shutdown(); - -void begin_frame(); -void end_frame(const wgpu::CommandEncoder& cmd); -void render(wgpu::CommandEncoder& cmd); -void render_pass(const wgpu::RenderPassEncoder& pass, u32 idx); -void map_staging_buffer(); - -Range push_verts(const uint8_t* data, size_t length); -template -static inline Range push_verts(ArrayRef data) { - return push_verts(reinterpret_cast(data.data()), data.size() * sizeof(T)); -} -Range push_indices(const uint8_t* data, size_t length); -template -static inline Range push_indices(ArrayRef data) { - return push_indices(reinterpret_cast(data.data()), data.size() * sizeof(T)); -} -Range push_uniform(const uint8_t* data, size_t length); -template -static inline Range push_uniform(const T& data) { - return push_uniform(reinterpret_cast(&data), sizeof(T)); -} -Range push_storage(const uint8_t* data, size_t length); -template -static inline Range push_storage(ArrayRef data) { - return push_storage(reinterpret_cast(data.data()), data.size() * sizeof(T)); -} -template -static inline Range push_storage(const T& data) { - return push_storage(reinterpret_cast(&data), sizeof(T)); -} -Range push_static_storage(const uint8_t* data, size_t length); -template -static inline Range push_static_storage(ArrayRef data) { - return push_static_storage(reinterpret_cast(data.data()), data.size() * sizeof(T)); -} -template -static inline Range push_static_storage(const T& data) { - return push_static_storage(reinterpret_cast(&data), sizeof(T)); -} -Range push_texture_data(const uint8_t* data, size_t length, u32 bytesPerRow, u32 rowsPerImage); -std::pair map_verts(size_t length); -std::pair map_indices(size_t length); -std::pair map_uniform(size_t length); -std::pair map_storage(size_t length); - -template -const State& get_state(); -template -void push_draw_command(DrawData data); - -template -PipelineRef pipeline_ref(PipelineConfig config); -bool bind_pipeline(PipelineRef ref, const wgpu::RenderPassEncoder& pass); - -BindGroupRef bind_group_ref(const wgpu::BindGroupDescriptor& descriptor); -const wgpu::BindGroup& find_bind_group(BindGroupRef id); - -const wgpu::Sampler& sampler_ref(const wgpu::SamplerDescriptor& descriptor); - -uint32_t align_uniform(uint32_t value); -} // namespace aurora::gfx diff --git a/aurora/lib/gfx/gx.cpp b/aurora/lib/gfx/gx.cpp deleted file mode 100644 index ab1766bf2..000000000 --- a/aurora/lib/gfx/gx.cpp +++ /dev/null @@ -1,1368 +0,0 @@ -#include "gx.hpp" - -#include "../gpu.hpp" -#include "Runtime/Graphics/GX.hpp" -#include "common.hpp" - -#include - -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::TEVPREV || id > GX::TEVREG2) { - Log.report(logvisor::Fatal, FMT_STRING("bad tevreg {}"), id); - unreachable(); - } - g_gxState.colorRegs[id] = 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, u8 value) noexcept { - if (enabled) { - g_gxState.dstAlpha = value; - } else { - g_gxState.dstAlpha = UINT32_MAX; - } -} -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(); - } - u32 idx = id - GX::COLOR0A0; - auto& chan = g_gxState.colorChannelConfig[idx]; - chan.lightingEnabled = lightingEnabled; - chan.ambSrc = ambSrc; - chan.matSrc = matSrc; - chan.diffFn = diffFn; - chan.attnFn = attnFn; - g_gxState.colorChannelState[idx].lightState = lightState; -} -void GXSetAlphaCompare(GX::Compare comp0, u8 ref0, GX::AlphaOp op, GX::Compare comp1, u8 ref1) noexcept { - g_gxState.alphaCompare = {comp0, ref0, op, comp1, ref1}; -} -void GXSetTexCoordGen2(GX::TexCoordID dst, GX::TexGenType type, GX::TexGenSrc src, GX::TexMtx mtx, GXBool normalize, - GX::PTTexMtx postMtx) noexcept { - if (dst < GX::TEXCOORD0 || dst > GX::TEXCOORD7) { - Log.report(logvisor::Fatal, FMT_STRING("invalid tex coord {}"), dst); - unreachable(); - } - g_gxState.tcgs[dst] = {type, src, mtx, postMtx, normalize}; -} -void GXLoadTexMtxImm(const void* data, u32 id, GX::TexMtxType type) noexcept { - if ((id < GX::TEXMTX0 || id > GX::IDENTITY) && (id < GX::PTTEXMTX0 || id > GX::PTIDENTITY)) { - Log.report(logvisor::Fatal, FMT_STRING("invalid tex mtx {}"), id); - unreachable(); - } - if (id >= GX::PTTEXMTX0) { - if (type != GX::MTX3x4) { - Log.report(logvisor::Fatal, FMT_STRING("invalid pt mtx type {}"), type); - unreachable(); - } - const auto idx = (id - GX::PTTEXMTX0) / 3; - g_gxState.ptTexMtxs[idx] = *static_cast(data); - } else { - const auto idx = (id - GX::TEXMTX0) / 3; - switch (type) { - case GX::MTX3x4: - g_gxState.texMtxs[idx] = aurora::Mat4x4{*static_cast(data)}; - break; - case GX::MTX2x4: - g_gxState.texMtxs[idx] = *static_cast*>(data); - break; - } - } -} -void GXLoadPosMtxImm(const zeus::CTransform& xf, GX::PosNrmMtx id) noexcept { - if (id != GX::PNMTX0) { - Log.report(logvisor::Fatal, FMT_STRING("invalid pn mtx {}"), id); - unreachable(); - } - g_gxState.mv = xf.toMatrix4f(); -} -void GXLoadNrmMtxImm(const zeus::CTransform& xf, GX::PosNrmMtx id) noexcept { - if (id != GX::PNMTX0) { - Log.report(logvisor::Fatal, FMT_STRING("invalid pn mtx {}"), id); - unreachable(); - } - g_gxState.mvInv = xf.toMatrix4f(); -} -constexpr zeus::CMatrix4f DepthCorrect{ - // clang-format off - 1.f, 0.f, 0.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 0.5f, 0.5f, - 0.f, 0.f, 0.f, 1.f, - // clang-format on -}; -void GXSetProjection(const zeus::CMatrix4f& mtx, GX::ProjectionType type) noexcept { - if (type == GX::PERSPECTIVE) { - g_gxState.proj = DepthCorrect * mtx; - } else { - g_gxState.proj = mtx; - } -} -void GXSetViewport(float left, float top, float width, float height, float nearZ, float farZ) noexcept { - aurora::gfx::set_viewport(left, top, width, height, nearZ, farZ); -} -void GXSetScissor(u32 left, u32 top, u32 width, u32 height) noexcept { - aurora::gfx::set_scissor(left, top, width, height); -} -void GXSetFog(GX::FogType type, float startZ, float endZ, float nearZ, float farZ, const GXColor& color) noexcept { - g_gxState.fog = {type, startZ, endZ, nearZ, farZ, color}; -} -void GXSetFogColor(const GXColor& color) noexcept { g_gxState.fog.color = color; } -void GXSetVtxDesc(GX::Attr attr, GX::AttrType type) noexcept { g_gxState.vtxDesc[attr] = type; } -void GXSetVtxDescv(GX::VtxDescList* list) noexcept { - g_gxState.vtxDesc.fill({}); - while (*list) { - g_gxState.vtxDesc[list->attr] = list->type; - ++list; - } -} -void GXClearVtxDesc() noexcept { g_gxState.vtxDesc.fill({}); } -void GXSetTevSwapModeTable(GX::TevSwapSel id, GX::TevColorChan red, GX::TevColorChan green, GX::TevColorChan blue, - GX::TevColorChan alpha) noexcept { - if (id < GX::TEV_SWAP0 || id >= GX::MAX_TEVSWAP) { - Log.report(logvisor::Fatal, FMT_STRING("invalid tev swap sel {}"), id); - unreachable(); - } - g_gxState.tevSwapTable[id] = {red, green, blue, alpha}; -} -void GXSetTevSwapMode(GX::TevStageID stageId, GX::TevSwapSel rasSel, GX::TevSwapSel texSel) noexcept { - auto& stage = g_gxState.tevStages[stageId]; - stage.tevSwapRas = rasSel; - stage.tevSwapTex = texSel; -} -void GXSetLineWidth(u8 width, GX::TexOffset offs) noexcept { - // TODO -} - -u32 GXGetTexBufferSize(u16 width, u16 height, u32 fmt, GXBool mips, u8 maxLod) noexcept { - s32 shiftX = 0; - s32 shiftY = 0; - switch (fmt) { - case GX::TF_I4: - case GX::TF_C4: - case GX::TF_CMPR: - case GX::CTF_R4: - case GX::CTF_Z4: - shiftX = 3; - shiftY = 3; - break; - case GX::TF_I8: - case GX::TF_IA4: - case GX::TF_C8: - case GX::TF_Z8: - case GX::CTF_RA4: - case GX::CTF_A8: - case GX::CTF_R8: - case GX::CTF_G8: - case GX::CTF_B8: - case GX::CTF_Z8M: - case GX::CTF_Z8L: - shiftX = 3; - shiftY = 2; - break; - case GX::TF_IA8: - case GX::TF_RGB565: - case GX::TF_RGB5A3: - case GX::TF_RGBA8: - case GX::TF_C14X2: - case GX::TF_Z16: - case GX::TF_Z24X8: - case GX::CTF_RA8: - case GX::CTF_RG8: - case GX::CTF_GB8: - case GX::CTF_Z16L: - shiftX = 2; - shiftY = 2; - break; - default: - break; - } - u32 bitSize = fmt == GX::TF_RGBA8 || fmt == GX::TF_Z24X8 ? 64 : 32; - u32 bufLen = 0; - if (mips) { - while (maxLod != 0) { - const u32 tileX = ((width + (1 << shiftX) - 1) >> shiftX); - const u32 tileY = ((height + (1 << shiftY) - 1) >> shiftY); - bufLen += bitSize * tileX * tileY; - - if (width == 1 && height == 1) { - return bufLen; - } - - width = (width < 2) ? 1 : width / 2; - height = (height < 2) ? 1 : height / 2; - --maxLod; - }; - } else { - const u32 tileX = ((width + (1 << shiftX) - 1) >> shiftX); - const u32 tileY = ((height + (1 << shiftY) - 1) >> shiftY); - bufLen = bitSize * tileX * tileY; - } - - return bufLen; -} - -// Lighting -void GXInitLightAttn(GX::LightObj* light, float a0, float a1, float a2, float k0, float k1, float k2) noexcept { - light->a0 = a0; - light->a1 = a1; - light->a2 = a2; - light->k0 = k0; - light->k1 = k1; - light->k2 = k2; -} - -void GXInitLightAttnA(GX::LightObj* light, float a0, float a1, float a2) noexcept { - light->a0 = a0; - light->a1 = a1; - light->a2 = a2; -} - -void GXInitLightAttnK(GX::LightObj* light, float k0, float k1, float k2) noexcept { - light->k0 = k0; - light->k1 = k1; - light->k2 = k2; -} - -void GXInitLightSpot(GX::LightObj* light, float cutoff, GX::SpotFn spotFn) noexcept { - if (cutoff <= 0.f || cutoff > 90.f) { - spotFn = GX::SP_OFF; - } - - float cr = std::cos((cutoff * M_PIF) / 180.f); - float a0 = 1.f; - float a1 = 0.f; - float a2 = 0.f; - switch (spotFn) { - default: - break; - case GX::SP_FLAT: - a0 = -1000.f * cr; - a1 = 1000.f; - a2 = 0.f; - break; - case GX::SP_COS: - a0 = -cr / (1.f - cr); - a1 = 1.f / (1.f - cr); - a2 = 0.f; - break; - case GX::SP_COS2: - a0 = 0.f; - a1 = -cr / (1.f - cr); - a2 = 1.f / (1.f - cr); - break; - case GX::SP_SHARP: { - const float d = (1.f - cr) * (1.f - cr); - a0 = cr * (cr - 2.f); - a1 = 2.f / d; - a2 = -1.f / d; - break; - } - case GX::SP_RING1: { - const float d = (1.f - cr) * (1.f - cr); - a0 = 4.f * cr / d; - a1 = 4.f * (1.f + cr) / d; - a2 = -4.f / d; - break; - } - case GX::SP_RING2: { - const float d = (1.f - cr) * (1.f - cr); - a0 = 1.f - 2.f * cr * cr / d; - a1 = 4.f * cr / d; - a2 = -2.f / d; - break; - } - } - - light->a0 = a0; - light->a1 = a1; - light->a2 = a2; -} - -void GXInitLightDistAttn(GX::LightObj* light, float refDistance, float refBrightness, - GX::DistAttnFn distFunc) noexcept { - if (refDistance < 0.f || refBrightness < 0.f || refBrightness >= 1.f) { - distFunc = GX::DA_OFF; - } - float k0 = 1.f; - float k1 = 0.f; - float k2 = 0.f; - switch (distFunc) { - case GX::DA_GENTLE: - k0 = 1.0f; - k1 = (1.0f - refBrightness) / (refBrightness * refDistance); - k2 = 0.0f; - break; - case GX::DA_MEDIUM: - k0 = 1.0f; - k1 = 0.5f * (1.0f - refBrightness) / (refBrightness * refDistance); - k2 = 0.5f * (1.0f - refBrightness) / (refBrightness * refDistance * refDistance); - break; - case GX::DA_STEEP: - k0 = 1.0f; - k1 = 0.0f; - k2 = (1.0f - refBrightness) / (refBrightness * refDistance * refDistance); - break; - case GX::DA_OFF: - k0 = 1.0f; - k1 = 0.0f; - k2 = 0.0f; - break; - } - - light->k0 = k0; - light->k1 = k1; - light->k2 = k2; -} - -void GXInitLightPos(GX::LightObj* light, float x, float y, float z) noexcept { - light->px = x; - light->py = y; - light->pz = z; -} - -void GXInitLightDir(GX::LightObj* light, float nx, float ny, float nz) noexcept { - light->nx = -nx; - light->ny = -ny; - light->nz = -nz; -} - -void GXInitSpecularDir(GX::LightObj* light, float nx, float ny, float nz) noexcept { - float hx = -nx; - float hy = -ny; - float hz = (-nz + 1.0f); - float mag = ((hx * hx) + (hy * hy) + (hz * hz)); - if (mag != 0.0f) { - mag = 1.0f / sqrtf(mag); - } - light->px = (nx * GX::LARGE_NUMBER); - light->py = (ny * GX::LARGE_NUMBER); - light->pz = (nz * GX::LARGE_NUMBER); - light->nx = hx * mag; - light->ny = hy * mag; - light->nz = hz * mag; -} - -void GXInitSpecularDirHA(GX::LightObj* light, float nx, float ny, float nz, float hx, float hy, float hz) noexcept { - light->px = (nx * GX::LARGE_NUMBER); - light->py = (ny * GX::LARGE_NUMBER); - light->pz = (nz * GX::LARGE_NUMBER); - light->nx = hx; - light->ny = hy; - light->nz = hz; -} - -void GXInitLightColor(GX::LightObj* light, GX::Color col) noexcept { light->color = col; } - -void GXLoadLightObjImm(const GX::LightObj* light, GX::LightID id) noexcept { - u32 idx = std::log2(id); - aurora::gfx::Light realLight; - realLight.pos.assign(light->px, light->py, light->pz); - realLight.dir.assign(light->nx, light->ny, light->nz); - realLight.cosAtt.assign(light->a0, light->a1, light->a2); - realLight.distAtt.assign(light->k0, light->k1, light->k2); - realLight.color.fromRGBA8(light->color.color[0], light->color.color[1], light->color.color[2], light->color.color[3]); - g_gxState.lights[idx] = realLight; -} - -/* TODO Figure out a way to implement this, requires GXSetArray */ -void GXLoadLightObjIndx(u32 index, GX::LightID) noexcept {} - -void GXGetLightAttnA(const GX::LightObj* light, float* a0, float* a1, float* a2) noexcept { - *a0 = light->a0; - *a1 = light->a1; - *a2 = light->a2; -} - -void GXGetLightAttnK(const GX::LightObj* light, float* k0, float* k1, float* k2) noexcept { - *k0 = light->k0; - *k1 = light->k1; - *k2 = light->k2; -} - -void GXGetLightPos(const GX::LightObj* light, float* x, float* y, float* z) noexcept { - *x = light->px; - *z = light->py; - *z = light->pz; -} - -void GXGetLightDir(const GX::LightObj* light, float* nx, float* ny, float* nz) noexcept { - *nx = -light->nx; - *ny = -light->ny; - *nz = -light->nz; -} - -void GXGetLightColor(const GX::LightObj* light, GX::Color* col) noexcept { *col = light->color; } - -// Indirect Texturing -void GXSetTevIndirect(GX::TevStageID tevStage, GX::IndTexStageID indStage, GX::IndTexFormat fmt, - GX::IndTexBiasSel biasSel, GX::IndTexMtxID matrixSel, GX::IndTexWrap wrapS, GX::IndTexWrap wrapT, - GXBool addPrev, GXBool indLod, GX::IndTexAlphaSel alphaSel) noexcept { - auto& stage = g_gxState.tevStages[tevStage]; - stage.indTexStage = indStage; - stage.indTexFormat = fmt; - stage.indTexBiasSel = biasSel; - stage.indTexAlphaSel = alphaSel; - stage.indTexMtxId = matrixSel; - stage.indTexWrapS = wrapS; - stage.indTexWrapT = wrapT; - stage.indTexAddPrev = addPrev; - stage.indTexUseOrigLOD = indLod; -} -void GXSetIndTexOrder(GX::IndTexStageID indStage, GX::TexCoordID texCoord, GX::TexMapID texMap) noexcept { - auto& stage = g_gxState.indStages[indStage]; - stage.texCoordId = texCoord; - stage.texMapId = texMap; -} -void GXSetIndTexCoordScale(GX::IndTexStageID indStage, GX::IndTexScale scaleS, GX::IndTexScale scaleT) noexcept { - auto& stage = g_gxState.indStages[indStage]; - stage.scaleS = scaleS; - stage.scaleT = scaleT; -} -void GXSetIndTexMtx(GX::IndTexMtxID id, const void* mtx, s8 scaleExp) noexcept { - if (id < GX::ITM_0 || id > GX::ITM_2) { - Log.report(logvisor::Fatal, FMT_STRING("invalid ind tex mtx ID {}"), id); - } - g_gxState.indTexMtxs[id - 1] = {*static_cast*>(mtx), scaleExp}; -} - -void GXInitTexObj(GXTexObj* obj, const void* data, u16 width, u16 height, GX::TextureFormat format, GXTexWrapMode wrapS, - GXTexWrapMode wrapT, GXBool mipmap) noexcept { - obj->data = data; - obj->width = width; - obj->height = height; - obj->fmt = format; - obj->wrapS = wrapS; - obj->wrapT = wrapT; - obj->hasMips = mipmap; - // TODO default values? - obj->minFilter = GX_LINEAR; - obj->magFilter = GX_LINEAR; - obj->minLod = 0.f; - obj->maxLod = 0.f; - obj->lodBias = 0.f; - obj->biasClamp = false; - obj->doEdgeLod = false; - obj->maxAniso = GX_ANISO_4; - obj->tlut = GX_TLUT0; - obj->dataInvalidated = true; -} -void GXInitTexObjResolved(GXTexObj* obj, u32 bindIdx, GX::TextureFormat format, GXTexWrapMode wrapS, - GXTexWrapMode wrapT, GXTlut tlut) { - const auto& ref = aurora::gfx::g_resolvedTextures[bindIdx]; - obj->ref = ref; - obj->data = nullptr; - obj->dataSize = 0; - obj->width = ref->size.width; - obj->height = ref->size.height; - obj->fmt = format; - obj->wrapS = wrapS; - obj->wrapT = wrapT; - obj->hasMips = false; - obj->tlut = tlut; - // TODO default values? - obj->minFilter = GX_LINEAR; - obj->magFilter = GX_LINEAR; - obj->minLod = 0.f; - obj->maxLod = 0.f; - obj->lodBias = 0.f; - obj->biasClamp = false; - obj->doEdgeLod = false; - obj->maxAniso = GX_ANISO_4; - obj->dataInvalidated = false; -} -void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter minFilt, GXTexFilter magFilt, float minLod, float maxLod, float lodBias, - GXBool biasClamp, GXBool doEdgeLod, GXAnisotropy maxAniso) noexcept { - obj->minFilter = minFilt; - obj->magFilter = magFilt; - obj->minLod = minLod; - obj->maxLod = maxLod; - obj->lodBias = lodBias; - obj->biasClamp = biasClamp; - obj->doEdgeLod = doEdgeLod; - obj->maxAniso = maxAniso; -} -void GXInitTexObjCI(GXTexObj* obj, void* data, u16 width, u16 height, GXCITexFmt format, GXTexWrapMode wrapS, - GXTexWrapMode wrapT, GXBool mipmap, u32 tlut) noexcept { - obj->data = data; - obj->width = width; - obj->height = height; - obj->fmt = static_cast(format); - obj->wrapS = wrapS; - obj->wrapT = wrapT; - obj->hasMips = mipmap; - obj->tlut = static_cast(tlut); - // TODO default values? - obj->minFilter = GX_LINEAR; - obj->magFilter = GX_LINEAR; - obj->minLod = 0.f; - obj->maxLod = 0.f; - obj->lodBias = 0.f; - obj->biasClamp = false; - obj->doEdgeLod = false; - obj->maxAniso = GX_ANISO_4; - obj->dataInvalidated = true; -} -void GXInitTexObjData(GXTexObj* obj, void* data) noexcept { - obj->data = data; - obj->dataInvalidated = true; -} -void GXInitTexObjWrapMode(GXTexObj* obj, GXTexWrapMode wrapS, GXTexWrapMode wrapT) noexcept { - obj->wrapS = wrapS; - obj->wrapT = wrapT; -} -void GXInitTexObjTlut(GXTexObj* obj, u32 tlut) noexcept { obj->tlut = static_cast(tlut); } -void GXLoadTexObj(GXTexObj* obj, GX::TexMapID id) noexcept { - if (!obj->ref) { - obj->ref = - aurora::gfx::new_dynamic_texture_2d(obj->width, obj->height, u32(obj->minLod) + 1, obj->fmt, "GXLoadTexObj"); - } - if (obj->dataInvalidated) { - aurora::gfx::write_texture(*obj->ref, {static_cast(obj->data), UINT32_MAX /* TODO */}); - obj->dataInvalidated = false; - } - g_gxState.textures[id] = {*obj}; -} - -void GXInitTlutObj(GXTlutObj* obj, const void* data, GXTlutFmt format, u16 entries) noexcept { - GX::TextureFormat texFmt; - switch (format) { - case GX_TL_IA8: - texFmt = GX::TF_IA8; - break; - case GX_TL_RGB565: - texFmt = GX::TF_RGB565; - break; - case GX_TL_RGB5A3: - texFmt = GX::TF_RGB5A3; - break; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid tlut format {}"), format); - unreachable(); - } - obj->ref = aurora::gfx::new_static_texture_2d( - entries, 1, 1, texFmt, aurora::ArrayRef{static_cast(data), static_cast(entries) * 2}, - "GXInitTlutObj"); -} -void GXLoadTlut(const GXTlutObj* obj, GXTlut idx) noexcept { g_gxState.tluts[idx] = *obj; } -void GXSetColorUpdate(GXBool enabled) noexcept { g_gxState.colorUpdate = enabled; } -void GXSetTevColorS10(GX::TevRegID id, const GXColorS10& color) noexcept { - g_gxState.colorRegs[id] = zeus::CColor{ - static_cast(color.r) / 1023.f, - static_cast(color.g) / 1023.f, - static_cast(color.b) / 1023.f, - static_cast(color.a) / 1023.f, - }; -} -void GXInvalidateTexAll() noexcept { - // no-op? -} - -namespace aurora::gfx { -static logvisor::Module Log("aurora::gfx::gx"); - -namespace gx { -using gpu::g_device; -using gpu::g_graphicsConfig; - -GXState g_gxState; - -const TextureBind& get_texture(GX::TexMapID id) noexcept { return g_gxState.textures[static_cast(id)]; } - -static inline wgpu::BlendFactor to_blend_factor(GX::BlendFactor fac) { - switch (fac) { - case GX::BL_ZERO: - return wgpu::BlendFactor::Zero; - case GX::BL_ONE: - return wgpu::BlendFactor::One; - case GX::BL_SRCCLR: - return wgpu::BlendFactor::Src; - case GX::BL_INVSRCCLR: - return wgpu::BlendFactor::OneMinusSrc; - case GX::BL_SRCALPHA: - return wgpu::BlendFactor::SrcAlpha; - case GX::BL_INVSRCALPHA: - return wgpu::BlendFactor::OneMinusSrcAlpha; - case GX::BL_DSTALPHA: - return wgpu::BlendFactor::DstAlpha; - case GX::BL_INVDSTALPHA: - return wgpu::BlendFactor::OneMinusDstAlpha; - case GX::BL_DSTCLR: - return wgpu::BlendFactor::Dst; - case GX::BL_INVDSTCLR: - return wgpu::BlendFactor::OneMinusDst; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid blend factor {}"), fac); - unreachable(); - } -} - -static inline wgpu::CompareFunction to_compare_function(GX::Compare func) { - switch (func) { - case GX::NEVER: - return wgpu::CompareFunction::Never; - case GX::LESS: - return wgpu::CompareFunction::Less; - case GX::EQUAL: - return wgpu::CompareFunction::Equal; - case GX::LEQUAL: - return wgpu::CompareFunction::LessEqual; - case GX::GREATER: - return wgpu::CompareFunction::Greater; - case GX::NEQUAL: - return wgpu::CompareFunction::NotEqual; - case GX::GEQUAL: - return wgpu::CompareFunction::GreaterEqual; - case GX::ALWAYS: - return wgpu::CompareFunction::Always; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid depth fn {}"), func); - unreachable(); - } -} - -static inline wgpu::BlendState to_blend_state(GX::BlendMode mode, GX::BlendFactor srcFac, GX::BlendFactor dstFac, - GX::LogicOp op, u32 dstAlpha) { - wgpu::BlendComponent colorBlendComponent; - switch (mode) { - case GX::BM_NONE: - colorBlendComponent = { - .operation = wgpu::BlendOperation::Add, - .srcFactor = wgpu::BlendFactor::One, - .dstFactor = wgpu::BlendFactor::Zero, - }; - break; - case GX::BM_BLEND: - colorBlendComponent = { - .operation = wgpu::BlendOperation::Add, - .srcFactor = to_blend_factor(srcFac), - .dstFactor = to_blend_factor(dstFac), - }; - break; - case GX::BM_SUBTRACT: - colorBlendComponent = { - .operation = wgpu::BlendOperation::ReverseSubtract, - .srcFactor = wgpu::BlendFactor::One, - .dstFactor = wgpu::BlendFactor::One, - }; - break; - case GX::BM_LOGIC: - switch (op) { - case GX::LO_CLEAR: - colorBlendComponent = { - .operation = wgpu::BlendOperation::Add, - .srcFactor = wgpu::BlendFactor::Zero, - .dstFactor = wgpu::BlendFactor::Zero, - }; - break; - case GX::LO_COPY: - colorBlendComponent = { - .operation = wgpu::BlendOperation::Add, - .srcFactor = wgpu::BlendFactor::One, - .dstFactor = wgpu::BlendFactor::Zero, - }; - break; - case GX::LO_NOOP: - colorBlendComponent = { - .operation = wgpu::BlendOperation::Add, - .srcFactor = wgpu::BlendFactor::Zero, - .dstFactor = wgpu::BlendFactor::One, - }; - break; - default: - Log.report(logvisor::Fatal, FMT_STRING("unsupported logic op {}"), op); - unreachable(); - } - break; - default: - Log.report(logvisor::Fatal, FMT_STRING("unsupported blend mode {}"), mode); - unreachable(); - } - wgpu::BlendComponent alphaBlendComponent{ - .operation = wgpu::BlendOperation::Add, - .srcFactor = wgpu::BlendFactor::One, - .dstFactor = wgpu::BlendFactor::Zero, - }; - if (dstAlpha != UINT32_MAX) { - alphaBlendComponent = wgpu::BlendComponent{ - .operation = wgpu::BlendOperation::Add, - .srcFactor = wgpu::BlendFactor::Constant, - .dstFactor = wgpu::BlendFactor::Zero, - }; - } - return { - .color = colorBlendComponent, - .alpha = alphaBlendComponent, - }; -} - -static inline wgpu::ColorWriteMask to_write_mask(bool colorUpdate, bool alphaUpdate) { - auto writeMask = wgpu::ColorWriteMask::None; - if (colorUpdate) { - writeMask |= wgpu::ColorWriteMask::Red | wgpu::ColorWriteMask::Green | wgpu::ColorWriteMask::Blue; - } - if (alphaUpdate) { - writeMask |= wgpu::ColorWriteMask::Alpha; - } - return writeMask; -} - -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: - break; - case GX::TRIANGLESTRIP: - primitive = wgpu::PrimitiveTopology::TriangleStrip; - break; - default: - Log.report(logvisor::Fatal, FMT_STRING("Unsupported primitive type {}"), gx_prim); - unreachable(); - } - wgpu::CullMode cullMode = wgpu::CullMode::None; - switch (gx_cullMode) { - case GX::CULL_FRONT: - cullMode = wgpu::CullMode::Front; - break; - case GX::CULL_BACK: - cullMode = wgpu::CullMode::Back; - break; - case GX::CULL_NONE: - break; - default: - Log.report(logvisor::Fatal, FMT_STRING("Unsupported cull mode {}"), gx_cullMode); - unreachable(); - } - return { - .topology = primitive, - .frontFace = wgpu::FrontFace::CW, - .cullMode = cullMode, - }; -} - -wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderInfo& info, - ArrayRef vtxBuffers, wgpu::ShaderModule shader, - zstring_view label) noexcept { - const auto depthStencil = wgpu::DepthStencilState{ - .format = g_graphicsConfig.depthFormat, - .depthWriteEnabled = config.depthUpdate, - .depthCompare = to_compare_function(config.depthFunc), - }; - const auto blendState = - to_blend_state(config.blendMode, config.blendFacSrc, config.blendFacDst, config.blendOp, config.dstAlpha); - const std::array colorTargets{wgpu::ColorTargetState{ - .format = g_graphicsConfig.colorFormat, - .blend = &blendState, - .writeMask = to_write_mask(config.colorUpdate, config.alphaUpdate), - }}; - const auto fragmentState = wgpu::FragmentState{ - .module = shader, - .entryPoint = "fs_main", - .targetCount = colorTargets.size(), - .targets = colorTargets.data(), - }; - auto layouts = build_bind_group_layouts(info, config.shaderConfig); - const std::array bindGroupLayouts{ - std::move(layouts.uniformLayout), - std::move(layouts.samplerLayout), - std::move(layouts.textureLayout), - }; - const auto pipelineLayoutDescriptor = wgpu::PipelineLayoutDescriptor{ - .label = "GX Pipeline Layout", - .bindGroupLayoutCount = static_cast(info.sampledTextures.any() ? bindGroupLayouts.size() : 1), - .bindGroupLayouts = bindGroupLayouts.data(), - }; - auto pipelineLayout = g_device.CreatePipelineLayout(&pipelineLayoutDescriptor); - const auto descriptor = wgpu::RenderPipelineDescriptor{ - .label = label.c_str(), - .layout = std::move(pipelineLayout), - .vertex = - { - .module = std::move(shader), - .entryPoint = "vs_main", - .bufferCount = static_cast(vtxBuffers.size()), - .buffers = vtxBuffers.data(), - }, - .primitive = to_primitive_state(config.primitive, config.cullMode), - .depthStencil = &depthStencil, - .multisample = - wgpu::MultisampleState{ - .count = g_graphicsConfig.msaaSamples, - }, - .fragment = &fragmentState, - }; - return g_device.CreateRenderPipeline(&descriptor); -} - -void populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive) noexcept { - config.shaderConfig.fogType = g_gxState.fog.type; - config.shaderConfig.vtxAttrs = g_gxState.vtxDesc; - config.shaderConfig.tevSwapTable = g_gxState.tevSwapTable; - for (u8 i = 0; i < g_gxState.numTevStages; ++i) { - config.shaderConfig.tevStages[i] = g_gxState.tevStages[i]; - } - config.shaderConfig.tevStageCount = g_gxState.numTevStages; - for (u8 i = 0; i < g_gxState.numChans; ++i) { - const auto& cc = g_gxState.colorChannelConfig[i]; - if (g_gxState.colorChannelState[i].lightState.any() && cc.lightingEnabled) { - config.shaderConfig.colorChannels[i] = cc; - } else { - // Only matSrc matters when lighting disabled - config.shaderConfig.colorChannels[i] = { - .matSrc = cc.matSrc, - }; - } - } - for (u8 i = 0; i < g_gxState.numTexGens; ++i) { - config.shaderConfig.tcgs[i] = g_gxState.tcgs[i]; - } - if (g_gxState.alphaCompare) { - config.shaderConfig.alphaCompare = g_gxState.alphaCompare; - } - config.shaderConfig.indexedAttributeCount = - std::count_if(config.shaderConfig.vtxAttrs.begin(), config.shaderConfig.vtxAttrs.end(), - [](const auto type) { return type == GX::INDEX8 || type == GX::INDEX16; }); - for (u8 i = 0; i < MaxTextures; ++i) { - const auto& bind = g_gxState.textures[i]; - TextureConfig texConfig{}; - if (bind.texObj.ref) { - if (requires_copy_conversion(bind.texObj)) { - texConfig.copyFmt = bind.texObj.ref->gxFormat; - } - if (requires_load_conversion(bind.texObj)) { - texConfig.loadFmt = bind.texObj.fmt; - } - texConfig.renderTex = bind.texObj.ref->isRenderTexture; - } - config.shaderConfig.textureConfig[i] = texConfig; - } - config = { - .shaderConfig = config.shaderConfig, - .primitive = primitive, - .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, - .colorUpdate = g_gxState.colorUpdate, - }; -} - -Range build_uniform(const ShaderInfo& info) noexcept { - auto [buf, range] = map_uniform(info.uniformSize); - { - buf.append(&g_gxState.mv, 64); - buf.append(&g_gxState.mvInv, 64); - buf.append(&g_gxState.proj, 64); - } - for (int i = 0; i < info.loadsTevReg.size(); ++i) { - if (!info.loadsTevReg.test(i)) { - continue; - } - 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_gxState.colorChannelState[i].ambColor, 16); - buf.append(&g_gxState.colorChannelState[i].matColor, 16); - - if (g_gxState.colorChannelConfig[i].lightingEnabled) { - int addedLights = 0; - const auto& lightState = g_gxState.colorChannelState[i].lightState; - u32 state = lightState.to_ulong(); - buf.append(&lightState, sizeof(u32)); - buf.append_zeroes(12); // alignment - for (int li = 0; li < lightState.size(); ++li) { - if (!lightState.test(li)) { - continue; - } - const auto& light = g_gxState.lights[li]; - static_assert(sizeof(Light) == 80); - buf.append(&light, sizeof(Light)); - ++addedLights; - } - constexpr Light emptyLight{}; - for (int li = addedLights; li < GX::MaxLights; ++li) { - buf.append(&emptyLight, sizeof(Light)); - } - } - } - for (int i = 0; i < info.sampledKColors.size(); ++i) { - if (!info.sampledKColors.test(i)) { - continue; - } - buf.append(&g_gxState.kcolors[i], 16); - } - for (int i = 0; i < info.usesTexMtx.size(); ++i) { - if (!info.usesTexMtx.test(i)) { - continue; - } - switch (info.texMtxTypes[i]) { - case GX::TG_MTX2x4: - if (std::holds_alternative>(g_gxState.texMtxs[i])) { - buf.append(&std::get>(g_gxState.texMtxs[i]), 32); - } else { - Log.report(logvisor::Fatal, FMT_STRING("expected 2x4 mtx in idx {}"), i); - unreachable(); - } - break; - case GX::TG_MTX3x4: - if (std::holds_alternative>(g_gxState.texMtxs[i])) { - const auto& mat = std::get>(g_gxState.texMtxs[i]); - buf.append(&mat, 64); - } else { - Log.report(logvisor::Fatal, FMT_STRING("expected 3x4 mtx in idx {}"), i); - buf.append(&Mat4x4_Identity, 64); - } - break; - default: - Log.report(logvisor::Fatal, FMT_STRING("unhandled tex mtx type {}"), info.texMtxTypes[i]); - unreachable(); - } - } - for (int i = 0; i < info.usesPTTexMtx.size(); ++i) { - if (!info.usesPTTexMtx.test(i)) { - continue; - } - buf.append(&g_gxState.ptTexMtxs[i], 64); - } - if (info.usesFog) { - const auto& state = g_gxState.fog; - struct Fog { - zeus::CColor color = state.color; - float a = 0.f; - float b = 0.5f; - float c = 0.f; - float pad = FLT_MAX; - } fog{}; - static_assert(sizeof(Fog) == 32); - if (state.nearZ != state.farZ && state.startZ != state.endZ) { - const float depthRange = state.farZ - state.nearZ; - const float fogRange = state.endZ - state.startZ; - fog.a = (state.farZ * state.nearZ) / (depthRange * fogRange); - fog.b = state.farZ / depthRange; - fog.c = state.startZ / fogRange; - } - buf.append(&fog, 32); - } - for (int i = 0; i < info.sampledTextures.size(); ++i) { - if (!info.sampledTextures.test(i)) { - continue; - } - const auto& tex = get_texture(static_cast(i)); - if (!tex) { - Log.report(logvisor::Fatal, FMT_STRING("unbound texture {}"), i); - unreachable(); - } - buf.append(&tex.texObj.lodBias, 4); - } - return range; -} - -static absl::flat_hash_map sUniformBindGroupLayouts; -static absl::flat_hash_map> sTextureBindGroupLayouts; - -GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& config, - const BindGroupRanges& ranges) noexcept { - const auto layouts = build_bind_group_layouts(info, config); - - const std::array uniformEntries{ - wgpu::BindGroupEntry{ - .binding = 0, - .buffer = g_uniformBuffer, - .size = info.uniformSize, - }, - // Vertices - wgpu::BindGroupEntry{ - .binding = 1, - .buffer = g_storageBuffer, - .size = ranges.vtxDataRange.size, - }, - // Normals - wgpu::BindGroupEntry{ - .binding = 2, - .buffer = g_storageBuffer, - .size = ranges.nrmDataRange.size, - }, - // Packed UVs - wgpu::BindGroupEntry{ - .binding = 3, - .buffer = g_storageBuffer, - .size = ranges.packedTcDataRange.size, - }, - // UVs - wgpu::BindGroupEntry{ - .binding = 4, - .buffer = g_storageBuffer, - .size = ranges.tcDataRange.size, - }, - }; - std::array samplerEntries; - std::array textureEntries; - u32 samplerCount = 0; - u32 textureCount = 0; - for (u32 i = 0; i < info.sampledTextures.size(); ++i) { - if (!info.sampledTextures.test(i)) { - continue; - } - const auto& tex = g_gxState.textures[i]; - if (!tex) { - Log.report(logvisor::Fatal, FMT_STRING("unbound texture {}"), i); - unreachable(); - } - samplerEntries[samplerCount] = { - .binding = samplerCount, - .sampler = sampler_ref(tex.get_descriptor()), - }; - ++samplerCount; - textureEntries[textureCount] = { - .binding = textureCount, - .textureView = tex.texObj.ref->view, - }; - ++textureCount; - // Load palette - const auto& texConfig = config.textureConfig[i]; - if (is_palette_format(texConfig.loadFmt)) { - u32 tlut = tex.texObj.tlut; - if (tlut < GX_TLUT0 || tlut > GX_TLUT7) { - Log.report(logvisor::Fatal, FMT_STRING("tlut out of bounds {}"), tlut); - unreachable(); - } else if (!g_gxState.tluts[tlut].ref) { - Log.report(logvisor::Fatal, FMT_STRING("tlut unbound {}"), tlut); - unreachable(); - } - textureEntries[textureCount] = { - .binding = textureCount, - .textureView = g_gxState.tluts[tlut].ref->view, - }; - ++textureCount; - } - } - return { - .uniformBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{ - .label = "GX Uniform Bind Group", - .layout = layouts.uniformLayout, - .entryCount = static_cast(config.indexedAttributeCount > 0 ? uniformEntries.size() : 1), - .entries = uniformEntries.data(), - }), - .samplerBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{ - .label = "GX Sampler Bind Group", - .layout = layouts.samplerLayout, - .entryCount = samplerCount, - .entries = samplerEntries.data(), - }), - .textureBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{ - .label = "GX Texture Bind Group", - .layout = layouts.textureLayout, - .entryCount = textureCount, - .entries = textureEntries.data(), - }), - }; -} - -GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info, const ShaderConfig& config) noexcept { - GXBindGroupLayouts out; - u32 uniformSizeKey = info.uniformSize + (config.indexedAttributeCount > 0 ? 1 : 0); - const auto uniformIt = sUniformBindGroupLayouts.find(uniformSizeKey); - if (uniformIt != sUniformBindGroupLayouts.end()) { - out.uniformLayout = uniformIt->second; - } else { - const std::array uniformLayoutEntries{ - wgpu::BindGroupLayoutEntry{ - .binding = 0, - .visibility = wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment, - .buffer = - wgpu::BufferBindingLayout{ - .type = wgpu::BufferBindingType::Uniform, - .hasDynamicOffset = true, - .minBindingSize = info.uniformSize, - }, - }, - wgpu::BindGroupLayoutEntry{ - .binding = 1, - .visibility = wgpu::ShaderStage::Vertex, - .buffer = - { - .type = wgpu::BufferBindingType::ReadOnlyStorage, - .hasDynamicOffset = true, - }, - }, - wgpu::BindGroupLayoutEntry{ - .binding = 2, - .visibility = wgpu::ShaderStage::Vertex, - .buffer = - { - .type = wgpu::BufferBindingType::ReadOnlyStorage, - .hasDynamicOffset = true, - }, - }, - wgpu::BindGroupLayoutEntry{ - .binding = 3, - .visibility = wgpu::ShaderStage::Vertex, - .buffer = - { - .type = wgpu::BufferBindingType::ReadOnlyStorage, - .hasDynamicOffset = true, - }, - }, - wgpu::BindGroupLayoutEntry{ - .binding = 4, - .visibility = wgpu::ShaderStage::Vertex, - .buffer = - { - .type = wgpu::BufferBindingType::ReadOnlyStorage, - .hasDynamicOffset = true, - }, - }, - }; - const auto uniformLayoutDescriptor = wgpu::BindGroupLayoutDescriptor{ - .label = "GX Uniform Bind Group Layout", - .entryCount = static_cast(config.indexedAttributeCount > 0 ? uniformLayoutEntries.size() : 1), - .entries = uniformLayoutEntries.data(), - }; - out.uniformLayout = g_device.CreateBindGroupLayout(&uniformLayoutDescriptor); - sUniformBindGroupLayouts.try_emplace(uniformSizeKey, out.uniformLayout); - } - - // u32 textureCount = info.sampledTextures.count(); - // const auto textureIt = sTextureBindGroupLayouts.find(textureCount); - // if (textureIt != sTextureBindGroupLayouts.end()) { - // const auto& [sl, tl] = textureIt->second; - // out.samplerLayout = sl; - // out.textureLayout = tl; - // } else { - u32 numSamplers = 0; - u32 numTextures = 0; - std::array samplerEntries; - std::array textureEntries; - for (u32 i = 0; i < info.sampledTextures.size(); ++i) { - if (!info.sampledTextures.test(i)) { - continue; - } - const auto& texConfig = config.textureConfig[i]; - bool copyAsPalette = is_palette_format(texConfig.copyFmt); - bool loadAsPalette = is_palette_format(texConfig.loadFmt); - samplerEntries[numSamplers] = { - .binding = numSamplers, - .visibility = wgpu::ShaderStage::Fragment, - .sampler = {.type = copyAsPalette && loadAsPalette ? wgpu::SamplerBindingType::NonFiltering - : wgpu::SamplerBindingType::Filtering}, - }; - ++numSamplers; - if (loadAsPalette) { - textureEntries[numTextures] = { - .binding = numTextures, - .visibility = wgpu::ShaderStage::Fragment, - .texture = - { - .sampleType = copyAsPalette ? wgpu::TextureSampleType::Sint : wgpu::TextureSampleType::Float, - .viewDimension = wgpu::TextureViewDimension::e2D, - }, - }; - ++numTextures; - textureEntries[numTextures] = { - .binding = numTextures, - .visibility = wgpu::ShaderStage::Fragment, - .texture = - { - .sampleType = wgpu::TextureSampleType::Float, - .viewDimension = wgpu::TextureViewDimension::e2D, - }, - }; - ++numTextures; - } else { - textureEntries[numTextures] = { - .binding = numTextures, - .visibility = wgpu::ShaderStage::Fragment, - .texture = - { - .sampleType = wgpu::TextureSampleType::Float, - .viewDimension = wgpu::TextureViewDimension::e2D, - }, - }; - ++numTextures; - } - } - { - const wgpu::BindGroupLayoutDescriptor descriptor{ - .label = "GX Sampler Bind Group Layout", - .entryCount = numSamplers, - .entries = samplerEntries.data(), - }; - out.samplerLayout = g_device.CreateBindGroupLayout(&descriptor); - } - { - const wgpu::BindGroupLayoutDescriptor descriptor{ - .label = "GX Texture Bind Group Layout", - .entryCount = numTextures, - .entries = textureEntries.data(), - }; - out.textureLayout = g_device.CreateBindGroupLayout(&descriptor); - } - // sTextureBindGroupLayouts.try_emplace(textureCount, out.samplerLayout, out.textureLayout); - // } - return out; -} - -// TODO this is awkward -extern absl::flat_hash_map> g_gxCachedShaders; -void shutdown() noexcept { - // TODO we should probably store this all in g_state.gx instead - sUniformBindGroupLayouts.clear(); - sTextureBindGroupLayouts.clear(); - for (auto& item : g_gxState.textures) { - item.texObj.ref.reset(); - } - for (auto& item : g_gxState.tluts) { - item.ref.reset(); - } - g_gxCachedShaders.clear(); -} - -static wgpu::AddressMode wgpu_address_mode(GXTexWrapMode mode) { - switch (mode) { - case GX_CLAMP: - return wgpu::AddressMode::ClampToEdge; - case GX_REPEAT: - return wgpu::AddressMode::Repeat; - case GX_MIRROR: - return wgpu::AddressMode::MirrorRepeat; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid wrap mode {}"), mode); - unreachable(); - } -} -static std::pair wgpu_filter_mode(GXTexFilter filter) { - switch (filter) { - case GX_NEAR: - return {wgpu::FilterMode::Nearest, wgpu::FilterMode::Linear}; - case GX_LINEAR: - return {wgpu::FilterMode::Linear, wgpu::FilterMode::Linear}; - case GX_NEAR_MIP_NEAR: - return {wgpu::FilterMode::Nearest, wgpu::FilterMode::Nearest}; - case GX_LIN_MIP_NEAR: - return {wgpu::FilterMode::Linear, wgpu::FilterMode::Nearest}; - case GX_NEAR_MIP_LIN: - return {wgpu::FilterMode::Nearest, wgpu::FilterMode::Linear}; - case GX_LIN_MIP_LIN: - return {wgpu::FilterMode::Linear, wgpu::FilterMode::Linear}; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid filter mode {}"), filter); - unreachable(); - } -} -static u16 wgpu_aniso(GXAnisotropy aniso) { - switch (aniso) { - case GX_ANISO_1: - return 1; - case GX_ANISO_2: - return std::max(g_graphicsConfig.textureAnisotropy / 2, 1); - case GX_ANISO_4: - return std::max(g_graphicsConfig.textureAnisotropy, 1); - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid aniso mode {}"), aniso); - unreachable(); - } -} -wgpu::SamplerDescriptor TextureBind::get_descriptor() const noexcept { - if (requires_copy_conversion(texObj) && is_palette_format(texObj.ref->gxFormat)) { - return { - .label = "Generated Non-Filtering Sampler", - .addressModeU = wgpu_address_mode(texObj.wrapS), - .addressModeV = wgpu_address_mode(texObj.wrapT), - .addressModeW = wgpu::AddressMode::Repeat, - .magFilter = wgpu::FilterMode::Nearest, - .minFilter = wgpu::FilterMode::Nearest, - .mipmapFilter = wgpu::FilterMode::Nearest, - .maxAnisotropy = 1, - }; - } - const auto [minFilter, mipFilter] = wgpu_filter_mode(texObj.minFilter); - const auto [magFilter, _] = wgpu_filter_mode(texObj.magFilter); - return { - .label = "Generated Filtering Sampler", - .addressModeU = wgpu_address_mode(texObj.wrapS), - .addressModeV = wgpu_address_mode(texObj.wrapT), - .addressModeW = wgpu::AddressMode::Repeat, - .magFilter = magFilter, - .minFilter = minFilter, - .mipmapFilter = mipFilter, - .maxAnisotropy = wgpu_aniso(texObj.maxAniso), - }; -} -} // namespace gx -} // namespace aurora::gfx diff --git a/aurora/lib/gfx/gx.hpp b/aurora/lib/gfx/gx.hpp deleted file mode 100644 index 1b3df6e9b..000000000 --- a/aurora/lib/gfx/gx.hpp +++ /dev/null @@ -1,336 +0,0 @@ -#pragma once - -#include "common.hpp" - -#include -#include -#include - -namespace aurora::gfx::gx { -constexpr u32 MaxTextures = GX::MAX_TEXMAP; -constexpr u32 MaxTevStages = GX::MAX_TEVSTAGE; -constexpr u32 MaxColorChannels = 2; // COLOR0A0, COLOR1A1 -constexpr u32 MaxTevRegs = 4; // TEVPREV, TEVREG0-2 -constexpr u32 MaxKColors = GX::MAX_KCOLOR; -constexpr u32 MaxTexMtx = 10; -constexpr u32 MaxPTTexMtx = 20; -constexpr u32 MaxTexCoord = GX::MAX_TEXCOORD; -constexpr u32 MaxVtxAttr = GX::VA_MAX_ATTR; -constexpr u32 MaxTevSwap = GX::MAX_TEVSWAP; -constexpr u32 MaxIndStages = GX::MAX_INDTEXSTAGE; -constexpr u32 MaxIndTexMtxs = 3; - -template -struct TevPass { - Arg a = Default; - Arg b = Default; - Arg c = Default; - Arg d = Default; - - bool operator==(const TevPass& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } -}; -static_assert(std::has_unique_object_representations_v>); -static_assert(std::has_unique_object_representations_v>); -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; - u8 _p1 = 0; - u8 _p2 = 0; - u8 _p3 = 0; - - bool operator==(const TevOp& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } -}; -static_assert(std::has_unique_object_representations_v); -struct TevStage { - TevPass colorPass; - TevPass 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; - GX::TevSwapSel tevSwapRas = GX::TEV_SWAP0; - GX::TevSwapSel tevSwapTex = GX::TEV_SWAP0; - GX::IndTexStageID indTexStage = GX::INDTEXSTAGE0; - GX::IndTexFormat indTexFormat = GX::ITF_8; - GX::IndTexBiasSel indTexBiasSel = GX::ITB_NONE; - GX::IndTexAlphaSel indTexAlphaSel = GX::ITBA_OFF; - GX::IndTexMtxID indTexMtxId = GX::ITM_OFF; - GX::IndTexWrap indTexWrapS = GX::ITW_OFF; - GX::IndTexWrap indTexWrapT = GX::ITW_OFF; - bool indTexUseOrigLOD = false; - bool indTexAddPrev = false; - u8 _p1 = 0; - u8 _p2 = 0; - - bool operator==(const TevStage& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } -}; -static_assert(std::has_unique_object_representations_v); -struct IndStage { - GX::TexCoordID texCoordId; - GX::TexMapID texMapId; - GX::IndTexScale scaleS; - GX::IndTexScale scaleT; -}; -static_assert(std::has_unique_object_representations_v); -struct TextureBind { - GXTexObj texObj; - - TextureBind() noexcept = default; - TextureBind(GXTexObj obj) noexcept : texObj(std::move(obj)) {} - void reset() noexcept { texObj.ref.reset(); }; - [[nodiscard]] wgpu::SamplerDescriptor get_descriptor() const noexcept; - operator bool() const noexcept { return texObj.ref.operator bool(); } -}; -// For shader generation -struct ColorChannelConfig { - GX::ColorSrc matSrc = GX::SRC_REG; - GX::ColorSrc ambSrc = GX::SRC_REG; - GX::DiffuseFn diffFn = GX::DF_NONE; - GX::AttnFn attnFn = GX::AF_NONE; - bool lightingEnabled = false; - u8 _p1 = 0; - u8 _p2 = 0; - u8 _p3 = 0; - - bool operator==(const ColorChannelConfig& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } -}; -static_assert(std::has_unique_object_representations_v); -// For uniform generation -struct ColorChannelState { - zeus::CColor matColor; - zeus::CColor ambColor; - GX::LightMask lightState; -}; -using LightVariant = std::variant; -// Mat4x4 used instead of Mat4x3 for padding purposes -using TexMtxVariant = std::variant, Mat4x4>; -struct TcgConfig { - GX::TexGenType type = GX::TG_MTX2x4; - GX::TexGenSrc src = GX::MAX_TEXGENSRC; - GX::TexMtx mtx = GX::IDENTITY; - GX::PTTexMtx postMtx = GX::PTIDENTITY; - bool normalize = false; - u8 _p1 = 0; - u8 _p2 = 0; - u8 _p3 = 0; - - bool operator==(const TcgConfig& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } -}; -static_assert(std::has_unique_object_representations_v); -struct FogState { - GX::FogType type = GX::FOG_NONE; - float startZ = 0.f; - float endZ = 0.f; - float nearZ = 0.f; - float farZ = 0.f; - zeus::CColor color; - - bool operator==(const FogState& rhs) const { - return type == rhs.type && startZ == rhs.startZ && endZ == rhs.endZ && nearZ == rhs.nearZ && farZ == rhs.farZ && - color == rhs.color; - } -}; -struct TevSwap { - GX::TevColorChan red = GX::CH_RED; - GX::TevColorChan green = GX::CH_GREEN; - GX::TevColorChan blue = GX::CH_BLUE; - GX::TevColorChan alpha = GX::CH_ALPHA; - - bool operator==(const TevSwap& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } - explicit operator bool() const { return !(*this == TevSwap{}); } -}; -static_assert(std::has_unique_object_representations_v); -struct AlphaCompare { - GX::Compare comp0 = GX::ALWAYS; - u32 ref0; // would be u8 but extended to avoid padding bytes - GX::AlphaOp op = GX::AOP_AND; - GX::Compare comp1 = GX::ALWAYS; - u32 ref1; - - bool operator==(const AlphaCompare& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } - explicit operator bool() const { return comp0 != GX::ALWAYS || comp1 != GX::ALWAYS; } -}; -static_assert(std::has_unique_object_representations_v); -struct IndTexMtxInfo { - aurora::Mat3x2 mtx; - s8 scaleExp; -}; - -struct GXState { - zeus::CMatrix4f mv; - zeus::CMatrix4f mvInv; - zeus::CMatrix4f proj; - FogState fog; - 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; - u32 dstAlpha; // u8; UINT32_MAX = disabled - AlphaCompare alphaCompare; - std::array colorRegs; - std::array kcolors; - std::array colorChannelConfig; - std::array colorChannelState; - std::array lights; - std::array tevStages; - std::array textures; - std::array tluts; - std::array texMtxs; - std::array, MaxPTTexMtx> ptTexMtxs; - std::array tcgs; - std::array vtxDesc; - std::array tevSwapTable{ - TevSwap{}, - TevSwap{GX::CH_RED, GX::CH_RED, GX::CH_RED, GX::CH_ALPHA}, - TevSwap{GX::CH_GREEN, GX::CH_GREEN, GX::CH_GREEN, GX::CH_ALPHA}, - TevSwap{GX::CH_BLUE, GX::CH_BLUE, GX::CH_BLUE, GX::CH_ALPHA}, - }; - std::array indStages; - std::array indTexMtxs; - bool depthCompare = true; - bool depthUpdate = true; - bool colorUpdate = true; - bool alphaUpdate = true; - u8 numChans = 0; - u8 numIndStages = 0; - u8 numTevStages = 0; - u8 numTexGens = 0; -}; -extern GXState g_gxState; - -static inline Mat4x4 get_combined_matrix() noexcept { return g_gxState.proj * g_gxState.mv; } - -void shutdown() noexcept; -const TextureBind& get_texture(GX::TexMapID id) noexcept; - -static inline bool requires_copy_conversion(const GXTexObj& obj) { - if (!obj.ref) { - return false; - } - if (obj.ref->isRenderTexture) { - return true; - } - switch (obj.ref->gxFormat) { - // case GX::TF_RGB565: - // case GX::TF_I4: - // case GX::TF_I8: - case GX::TF_C4: - case GX::TF_C8: - case GX::TF_C14X2: - return true; - default: - return false; - } -} -static inline bool requires_load_conversion(const GXTexObj& obj) { - if (!obj.ref) { - return false; - } - switch (obj.fmt) { - case GX::TF_I4: - case GX::TF_I8: - case GX::TF_C4: - case GX::TF_C8: - case GX::TF_C14X2: - return true; - default: - return false; - } -} -static inline bool is_palette_format(GX::TextureFormat fmt) { - return fmt == GX::TF_C4 || fmt == GX::TF_C8 || fmt == GX::TF_C14X2; -} - -struct TextureConfig { - GX::TextureFormat copyFmt = InvalidTextureFormat; // Underlying texture format - GX::TextureFormat loadFmt = InvalidTextureFormat; // Texture format being bound - bool renderTex = false; // Perform conversion - u8 _p1 = 0; - u8 _p2 = 0; - u8 _p3 = 0; - - bool operator==(const TextureConfig& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } -}; -static_assert(std::has_unique_object_representations_v); -struct ShaderConfig { - GX::FogType fogType; - std::array vtxAttrs; - std::array tevSwapTable; - std::array tevStages; - u32 tevStageCount = 0; - std::array colorChannels; - std::array tcgs; - AlphaCompare alphaCompare; - u32 indexedAttributeCount = 0; - std::array textureConfig; - - bool operator==(const ShaderConfig& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } -}; -static_assert(std::has_unique_object_representations_v); - -constexpr u32 GXPipelineConfigVersion = 4; -struct PipelineConfig { - u32 version = GXPipelineConfigVersion; - ShaderConfig shaderConfig; - GX::Primitive primitive; - GX::Compare depthFunc; - GX::CullMode cullMode; - GX::BlendMode blendMode; - GX::BlendFactor blendFacSrc, blendFacDst; - GX::LogicOp blendOp; - u32 dstAlpha; - bool depthCompare, depthUpdate, alphaUpdate, colorUpdate; -}; -static_assert(std::has_unique_object_representations_v); - -struct GXBindGroupLayouts { - wgpu::BindGroupLayout uniformLayout; - wgpu::BindGroupLayout samplerLayout; - wgpu::BindGroupLayout textureLayout; -}; -struct GXBindGroups { - BindGroupRef uniformBindGroup; - BindGroupRef samplerBindGroup; - BindGroupRef textureBindGroup; -}; -// Output info from shader generation -struct ShaderInfo { - std::bitset sampledTexCoords; - std::bitset sampledTextures; - std::bitset sampledKColors; - std::bitset sampledColorChannels; - std::bitset loadsTevReg; - std::bitset writesTevReg; - std::bitset usesTexMtx; - std::bitset usesPTTexMtx; - std::array texMtxTypes{}; - u32 uniformSize = 0; - bool usesFog : 1 = false; -}; -struct BindGroupRanges { - Range vtxDataRange; - Range nrmDataRange; - Range tcDataRange; - Range packedTcDataRange; -}; -void populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive) noexcept; -wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderInfo& info, - ArrayRef vtxBuffers, wgpu::ShaderModule shader, - zstring_view label) noexcept; -ShaderInfo build_shader_info(const ShaderConfig& config) noexcept; -wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& info) noexcept; -// Range build_vertex_buffer(const GXShaderInfo& info) noexcept; -Range build_uniform(const ShaderInfo& info) noexcept; -GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info, const ShaderConfig& config) noexcept; -GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& config, - const BindGroupRanges& ranges) noexcept; -} // namespace aurora::gfx::gx diff --git a/aurora/lib/gfx/gx_shader.cpp b/aurora/lib/gfx/gx_shader.cpp deleted file mode 100644 index a0872e4a4..000000000 --- a/aurora/lib/gfx/gx_shader.cpp +++ /dev/null @@ -1,1320 +0,0 @@ -#include "common.hpp" - -#include "../gpu.hpp" -#include "gx.hpp" - -#include - -constexpr bool EnableNormalVisualization = false; -constexpr bool EnableDebugPrints = false; -constexpr bool UsePerPixelLighting = true; - -namespace aurora::gfx::gx { -using namespace fmt::literals; - -static logvisor::Module Log("aurora::gfx::gx"); - -absl::flat_hash_map> g_gxCachedShaders; -#ifndef NDEBUG -static absl::flat_hash_map g_gxCachedShaderConfigs; -#endif - -static inline std::string_view chan_comp(GX::TevColorChan chan) noexcept { - switch (chan) { - case GX::CH_RED: - return "r"; - case GX::CH_GREEN: - return "g"; - case GX::CH_BLUE: - return "b"; - case GX::CH_ALPHA: - return "a"; - default: - return "?"; - } -} - -static void color_arg_reg_info(GX::TevColorArg arg, const TevStage& stage, ShaderInfo& info) { - switch (arg) { - case GX::CC_CPREV: - case GX::CC_APREV: - if (!info.writesTevReg.test(GX::TEVPREV)) { - info.loadsTevReg.set(GX::TEVPREV); - } - break; - case GX::CC_C0: - case GX::CC_A0: - if (!info.writesTevReg.test(GX::TEVREG0)) { - info.loadsTevReg.set(GX::TEVREG0); - } - break; - case GX::CC_C1: - case GX::CC_A1: - if (!info.writesTevReg.test(GX::TEVREG1)) { - info.loadsTevReg.set(GX::TEVREG1); - } - break; - case GX::CC_C2: - case GX::CC_A2: - if (!info.writesTevReg.test(GX::TEVREG2)) { - info.loadsTevReg.set(GX::TEVREG2); - } - break; - case GX::CC_TEXC: - case GX::CC_TEXA: - if (stage.texCoordId == GX::TEXCOORD_NULL) { - Log.report(logvisor::Fatal, FMT_STRING("texCoord not bound")); - } - if (stage.texMapId == GX::TEXMAP_NULL) { - Log.report(logvisor::Fatal, FMT_STRING("texMap not bound")); - } - info.sampledTexCoords.set(stage.texCoordId); - info.sampledTextures.set(stage.texMapId); - break; - case GX::CC_RASC: - case GX::CC_RASA: - if (stage.channelId >= GX::COLOR0A0 && stage.channelId <= GX::COLOR1A1) { - info.sampledColorChannels.set(stage.channelId - GX::COLOR0A0); - } - break; - case GX::CC_KONST: - switch (stage.kcSel) { - case GX::TEV_KCSEL_K0: - case GX::TEV_KCSEL_K0_R: - case GX::TEV_KCSEL_K0_G: - case GX::TEV_KCSEL_K0_B: - case GX::TEV_KCSEL_K0_A: - info.sampledKColors.set(0); - break; - case GX::TEV_KCSEL_K1: - case GX::TEV_KCSEL_K1_R: - case GX::TEV_KCSEL_K1_G: - case GX::TEV_KCSEL_K1_B: - case GX::TEV_KCSEL_K1_A: - info.sampledKColors.set(1); - break; - case GX::TEV_KCSEL_K2: - case GX::TEV_KCSEL_K2_R: - case GX::TEV_KCSEL_K2_G: - case GX::TEV_KCSEL_K2_B: - case GX::TEV_KCSEL_K2_A: - info.sampledKColors.set(2); - break; - case GX::TEV_KCSEL_K3: - case GX::TEV_KCSEL_K3_R: - case GX::TEV_KCSEL_K3_G: - case GX::TEV_KCSEL_K3_B: - case GX::TEV_KCSEL_K3_A: - info.sampledKColors.set(3); - break; - default: - break; - } - break; - default: - break; - } -} - -static bool formatHasAlpha(GX::TextureFormat format) { - switch (format) { - case GX::TF_IA4: - case GX::TF_IA8: - case GX::TF_RGB5A3: - case GX::TF_RGBA8: - case GX::TF_CMPR: - case GX::CTF_RA4: - case GX::CTF_RA8: - case GX::CTF_YUVA8: - case GX::CTF_A8: - return true; - default: - return false; - } -} - -static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const ShaderConfig& config, - const TevStage& stage) { - switch (arg) { - case GX::CC_CPREV: - return "prev.rgb"; - case GX::CC_APREV: - return "vec3(prev.a)"; - case GX::CC_C0: - return "tevreg0.rgb"; - case GX::CC_A0: - return "vec3(tevreg0.a)"; - case GX::CC_C1: - return "tevreg1.rgb"; - case GX::CC_A1: - return "vec3(tevreg1.a)"; - case GX::CC_C2: - return "tevreg2.rgb"; - case GX::CC_A2: - return "vec3(tevreg2.a)"; - case GX::CC_TEXC: { - if (stage.texMapId == GX::TEXMAP_NULL) { - Log.report(logvisor::Fatal, FMT_STRING("unmapped texture for stage {}"), stageIdx); - unreachable(); - } else if (stage.texMapId < GX::TEXMAP0 || stage.texMapId > GX::TEXMAP7) { - Log.report(logvisor::Fatal, FMT_STRING("invalid texture {} for stage {}"), stage.texMapId, stageIdx); - unreachable(); - } - const auto& swap = config.tevSwapTable[stage.tevSwapTex]; - return fmt::format(FMT_STRING("sampled{}.{}{}{}"), stageIdx, chan_comp(swap.red), chan_comp(swap.green), - chan_comp(swap.blue)); - } - case GX::CC_TEXA: { - if (stage.texMapId == GX::TEXMAP_NULL) { - Log.report(logvisor::Fatal, FMT_STRING("unmapped texture for stage {}"), stageIdx); - unreachable(); - } else if (stage.texMapId < GX::TEXMAP0 || stage.texMapId > GX::TEXMAP7) { - Log.report(logvisor::Fatal, FMT_STRING("invalid texture {} for stage {}"), stage.texMapId, stageIdx); - unreachable(); - } - const auto& swap = config.tevSwapTable[stage.tevSwapTex]; - return fmt::format(FMT_STRING("vec3(sampled{}.{})"), stageIdx, chan_comp(swap.alpha)); - } - case GX::CC_RASC: { - if (stage.channelId == GX::COLOR_NULL) { - Log.report(logvisor::Fatal, FMT_STRING("unmapped color channel for stage {}"), stageIdx); - unreachable(); - } else if (stage.channelId == GX::COLOR_ZERO) { - return "vec3(0.0)"; - } else if (stage.channelId < GX::COLOR0A0 || stage.channelId > GX::COLOR1A1) { - Log.report(logvisor::Fatal, FMT_STRING("invalid color channel {} for stage {}"), stage.channelId, stageIdx); - unreachable(); - } - u32 idx = stage.channelId - GX::COLOR0A0; - const auto& swap = config.tevSwapTable[stage.tevSwapRas]; - return fmt::format(FMT_STRING("rast{}.{}{}{}"), idx, chan_comp(swap.red), chan_comp(swap.green), - chan_comp(swap.blue)); - } - case GX::CC_RASA: { - if (stage.channelId == GX::COLOR_NULL) { - Log.report(logvisor::Fatal, FMT_STRING("unmapped color channel for stage {}"), stageIdx); - unreachable(); - } else if (stage.channelId == GX::COLOR_ZERO) { - return "vec3(0.0)"; - } else if (stage.channelId < GX::COLOR0A0 || stage.channelId > GX::COLOR1A1) { - Log.report(logvisor::Fatal, FMT_STRING("invalid color channel {} for stage {}"), stage.channelId, stageIdx); - unreachable(); - } - u32 idx = stage.channelId - GX::COLOR0A0; - const auto& swap = config.tevSwapTable[stage.tevSwapRas]; - return fmt::format(FMT_STRING("vec3(rast{}.{})"), idx, chan_comp(swap.alpha)); - } - case GX::CC_ONE: - return "vec3(1.0)"; - case GX::CC_HALF: - return "vec3(0.5)"; - case GX::CC_KONST: { - switch (stage.kcSel) { - case GX::TEV_KCSEL_8_8: - return "vec3(1.0)"; - case GX::TEV_KCSEL_7_8: - return "vec3(7.0/8.0)"; - case GX::TEV_KCSEL_6_8: - return "vec3(6.0/8.0)"; - case GX::TEV_KCSEL_5_8: - return "vec3(5.0/8.0)"; - case GX::TEV_KCSEL_4_8: - return "vec3(4.0/8.0)"; - case GX::TEV_KCSEL_3_8: - return "vec3(3.0/8.0)"; - case GX::TEV_KCSEL_2_8: - return "vec3(2.0/8.0)"; - case GX::TEV_KCSEL_1_8: - return "vec3(1.0/8.0)"; - case GX::TEV_KCSEL_K0: - return "ubuf.kcolor0.rgb"; - case GX::TEV_KCSEL_K1: - return "ubuf.kcolor1.rgb"; - case GX::TEV_KCSEL_K2: - return "ubuf.kcolor2.rgb"; - case GX::TEV_KCSEL_K3: - return "ubuf.kcolor3.rgb"; - case GX::TEV_KCSEL_K0_R: - return "vec3(ubuf.kcolor0.r)"; - case GX::TEV_KCSEL_K1_R: - return "vec3(ubuf.kcolor1.r)"; - case GX::TEV_KCSEL_K2_R: - return "vec3(ubuf.kcolor2.r)"; - case GX::TEV_KCSEL_K3_R: - return "vec3(ubuf.kcolor3.r)"; - case GX::TEV_KCSEL_K0_G: - return "vec3(ubuf.kcolor0.g)"; - case GX::TEV_KCSEL_K1_G: - return "vec3(ubuf.kcolor1.g)"; - case GX::TEV_KCSEL_K2_G: - return "vec3(ubuf.kcolor2.g)"; - case GX::TEV_KCSEL_K3_G: - return "vec3(ubuf.kcolor3.g)"; - case GX::TEV_KCSEL_K0_B: - return "vec3(ubuf.kcolor0.b)"; - case GX::TEV_KCSEL_K1_B: - return "vec3(ubuf.kcolor1.b)"; - case GX::TEV_KCSEL_K2_B: - return "vec3(ubuf.kcolor2.b)"; - case GX::TEV_KCSEL_K3_B: - return "vec3(ubuf.kcolor3.b)"; - case GX::TEV_KCSEL_K0_A: - return "vec3(ubuf.kcolor0.a)"; - case GX::TEV_KCSEL_K1_A: - return "vec3(ubuf.kcolor1.a)"; - case GX::TEV_KCSEL_K2_A: - return "vec3(ubuf.kcolor2.a)"; - case GX::TEV_KCSEL_K3_A: - return "vec3(ubuf.kcolor3.a)"; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid kcSel {}"), stage.kcSel); - unreachable(); - } - } - case GX::CC_ZERO: - return "vec3(0.0)"; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid color arg {}"), arg); - unreachable(); - } -} - -static void alpha_arg_reg_info(GX::TevAlphaArg arg, const TevStage& stage, ShaderInfo& info) { - switch (arg) { - case GX::CA_APREV: - if (!info.writesTevReg.test(GX::TEVPREV)) { - info.loadsTevReg.set(GX::TEVPREV); - } - break; - case GX::CA_A0: - if (!info.writesTevReg.test(GX::TEVREG0)) { - info.loadsTevReg.set(GX::TEVREG0); - } - break; - case GX::CA_A1: - if (!info.writesTevReg.test(GX::TEVREG1)) { - info.loadsTevReg.set(GX::TEVREG1); - } - break; - case GX::CA_A2: - if (!info.writesTevReg.test(GX::TEVREG2)) { - info.loadsTevReg.set(GX::TEVREG2); - } - break; - case GX::CA_TEXA: - if (stage.texCoordId == GX::TEXCOORD_NULL) { - Log.report(logvisor::Fatal, FMT_STRING("texCoord not bound")); - } - if (stage.texMapId == GX::TEXMAP_NULL) { - Log.report(logvisor::Fatal, FMT_STRING("texMap not bound")); - } - info.sampledTexCoords.set(stage.texCoordId); - info.sampledTextures.set(stage.texMapId); - break; - case GX::CA_RASA: - if (stage.channelId >= GX::COLOR0A0 && stage.channelId <= GX::COLOR1A1) { - info.sampledColorChannels.set(stage.channelId - GX::COLOR0A0); - } - break; - case GX::CA_KONST: - switch (stage.kaSel) { - case GX::TEV_KASEL_K0_R: - case GX::TEV_KASEL_K0_G: - case GX::TEV_KASEL_K0_B: - case GX::TEV_KASEL_K0_A: - info.sampledKColors.set(0); - break; - case GX::TEV_KASEL_K1_R: - case GX::TEV_KASEL_K1_G: - case GX::TEV_KASEL_K1_B: - case GX::TEV_KASEL_K1_A: - info.sampledKColors.set(1); - break; - case GX::TEV_KASEL_K2_R: - case GX::TEV_KASEL_K2_G: - case GX::TEV_KASEL_K2_B: - case GX::TEV_KASEL_K2_A: - info.sampledKColors.set(2); - break; - case GX::TEV_KASEL_K3_R: - case GX::TEV_KASEL_K3_G: - case GX::TEV_KASEL_K3_B: - case GX::TEV_KASEL_K3_A: - info.sampledKColors.set(3); - break; - default: - break; - } - break; - default: - break; - } -} - -static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const ShaderConfig& config, - const TevStage& stage) { - switch (arg) { - case GX::CA_APREV: - return "prev.a"; - case GX::CA_A0: - return "tevreg0.a"; - case GX::CA_A1: - return "tevreg1.a"; - case GX::CA_A2: - return "tevreg2.a"; - case GX::CA_TEXA: { - if (stage.texMapId == GX::TEXMAP_NULL) { - Log.report(logvisor::Fatal, FMT_STRING("unmapped texture for stage {}"), stageIdx); - unreachable(); - } else if (stage.texMapId < GX::TEXMAP0 || stage.texMapId > GX::TEXMAP7) { - Log.report(logvisor::Fatal, FMT_STRING("invalid texture {} for stage {}"), stage.texMapId, stageIdx); - unreachable(); - } - const auto& swap = config.tevSwapTable[stage.tevSwapTex]; - return fmt::format(FMT_STRING("sampled{}.{}"), stageIdx, chan_comp(swap.alpha)); - } - case GX::CA_RASA: { - if (stage.channelId == GX::COLOR_NULL) { - Log.report(logvisor::Fatal, FMT_STRING("unmapped color channel for stage {}"), stageIdx); - unreachable(); - } else if (stage.channelId == GX::COLOR_ZERO) { - return "0.0"; - } else if (stage.channelId < GX::COLOR0A0 || stage.channelId > GX::COLOR1A1) { - Log.report(logvisor::Fatal, FMT_STRING("invalid color channel {} for stage {}"), stage.channelId, stageIdx); - unreachable(); - } - u32 idx = stage.channelId - GX::COLOR0A0; - const auto& swap = config.tevSwapTable[stage.tevSwapRas]; - return fmt::format(FMT_STRING("rast{}.{}"), idx, chan_comp(swap.alpha)); - } - case GX::CA_KONST: { - switch (stage.kaSel) { - case GX::TEV_KASEL_8_8: - return "1.0"; - case GX::TEV_KASEL_7_8: - return "(7.0/8.0)"; - case GX::TEV_KASEL_6_8: - return "(6.0/8.0)"; - case GX::TEV_KASEL_5_8: - return "(5.0/8.0)"; - case GX::TEV_KASEL_4_8: - return "(4.0/8.0)"; - case GX::TEV_KASEL_3_8: - return "(3.0/8.0)"; - case GX::TEV_KASEL_2_8: - return "(2.0/8.0)"; - case GX::TEV_KASEL_1_8: - return "(1.0/8.0)"; - case GX::TEV_KASEL_K0_R: - return "ubuf.kcolor0.r"; - case GX::TEV_KASEL_K1_R: - return "ubuf.kcolor1.r"; - case GX::TEV_KASEL_K2_R: - return "ubuf.kcolor2.r"; - case GX::TEV_KASEL_K3_R: - return "ubuf.kcolor3.r"; - case GX::TEV_KASEL_K0_G: - return "ubuf.kcolor0.g"; - case GX::TEV_KASEL_K1_G: - return "ubuf.kcolor1.g"; - case GX::TEV_KASEL_K2_G: - return "ubuf.kcolor2.g"; - case GX::TEV_KASEL_K3_G: - return "ubuf.kcolor3.g"; - case GX::TEV_KASEL_K0_B: - return "ubuf.kcolor0.b"; - case GX::TEV_KASEL_K1_B: - return "ubuf.kcolor1.b"; - case GX::TEV_KASEL_K2_B: - return "ubuf.kcolor2.b"; - case GX::TEV_KASEL_K3_B: - return "ubuf.kcolor3.b"; - case GX::TEV_KASEL_K0_A: - return "ubuf.kcolor0.a"; - case GX::TEV_KASEL_K1_A: - return "ubuf.kcolor1.a"; - case GX::TEV_KASEL_K2_A: - return "ubuf.kcolor2.a"; - case GX::TEV_KASEL_K3_A: - return "ubuf.kcolor3.a"; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid kaSel {}"), stage.kaSel); - unreachable(); - } - } - case GX::CA_ZERO: - return "0.0"; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid alpha arg {}"), arg); - unreachable(); - } -} - -static std::string_view tev_op(GX::TevOp op) { - switch (op) { - case GX::TEV_ADD: - return ""sv; - case GX::TEV_SUB: - return "-"sv; - default: - Log.report(logvisor::Fatal, FMT_STRING("TODO {}"), op); - unreachable(); - } -} - -static std::string_view tev_bias(GX::TevBias bias) { - switch (bias) { - case GX::TB_ZERO: - return ""sv; - case GX::TB_ADDHALF: - return " + 0.5"sv; - case GX::TB_SUBHALF: - return " - 0.5"sv; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid bias {}"), bias); - unreachable(); - } -} - -static std::string alpha_compare(GX::Compare comp, u8 ref, bool& valid) { - const float fref = ref / 255.f; - switch (comp) { - case GX::NEVER: - return "false"s; - case GX::LESS: - return fmt::format(FMT_STRING("(prev.a < {}f)"), fref); - case GX::LEQUAL: - return fmt::format(FMT_STRING("(prev.a <= {}f)"), fref); - case GX::EQUAL: - return fmt::format(FMT_STRING("(prev.a == {}f)"), fref); - case GX::NEQUAL: - return fmt::format(FMT_STRING("(prev.a != {}f)"), fref); - case GX::GEQUAL: - return fmt::format(FMT_STRING("(prev.a >= {}f)"), fref); - case GX::GREATER: - return fmt::format(FMT_STRING("(prev.a > {}f)"), fref); - case GX::ALWAYS: - valid = false; - return "true"s; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid compare {}"), comp); - unreachable(); - } -} - -static std::string_view tev_scale(GX::TevScale scale) { - switch (scale) { - case GX::CS_SCALE_1: - return ""sv; - case GX::CS_SCALE_2: - return " * 2.0"sv; - case GX::CS_SCALE_4: - return " * 4.0"sv; - case GX::CS_DIVIDE_2: - return " / 2.0"sv; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid scale {}"), scale); - unreachable(); - } -} - -static inline std::string vtx_attr(const ShaderConfig& config, GX::Attr attr) { - const auto type = config.vtxAttrs[attr]; - if (type == GX::NONE) { - if (attr == GX::VA_NRM) { - // Default normal - return "vec3(1.0, 0.0, 0.0)"s; - } - Log.report(logvisor::Fatal, FMT_STRING("unmapped attr {}"), attr); - unreachable(); - } - if (attr == GX::VA_POS) { - return "in_pos"s; - } - if (attr == GX::VA_NRM) { - return "in_nrm"s; - } - if (attr == GX::VA_CLR0 || attr == GX::VA_CLR1) { - const auto idx = attr - GX::VA_CLR0; - return fmt::format(FMT_STRING("in_clr{}"), idx); - } - if (attr >= GX::VA_TEX0 && attr <= GX::VA_TEX7) { - const auto idx = attr - GX::VA_TEX0; - return fmt::format(FMT_STRING("in_tex{}_uv"), idx); - } - Log.report(logvisor::Fatal, FMT_STRING("unhandled attr {}"), attr); - unreachable(); -} - -static inline std::string texture_conversion(const TextureConfig& tex, u32 stageIdx, u32 texMapId) { - std::string out; - if (tex.renderTex) - switch (tex.copyFmt) { - default: - break; - case GX::TF_RGB565: - // Set alpha channel to 1.0 - out += fmt::format(FMT_STRING("\n sampled{0}.a = 1.0;"), stageIdx); - break; - case GX::TF_I4: - case GX::TF_I8: - // FIXME HACK - if (!is_palette_format(tex.loadFmt)) { - // Perform intensity conversion - out += fmt::format(FMT_STRING("\n sampled{0} = vec4(intensityF32(sampled{0}.rgb), 0.f, 0.f, 1.f);"), - stageIdx); - } - break; - } - switch (tex.loadFmt) { - default: - break; - case GX::TF_I4: - case GX::TF_I8: - // Splat R to RGBA - out += fmt::format(FMT_STRING("\n sampled{0} = vec4(sampled{0}.r);"), stageIdx); - break; - } - return out; -} - -constexpr std::array TevColorArgNames{ - "CPREV"sv, "APREV"sv, "C0"sv, "A0"sv, "C1"sv, "A1"sv, "C2"sv, "A2"sv, - "TEXC"sv, "TEXA"sv, "RASC"sv, "RASA"sv, "ONE"sv, "HALF"sv, "KONST"sv, "ZERO"sv, -}; -constexpr std::array TevAlphaArgNames{ - "APREV"sv, "A0"sv, "A1"sv, "A2"sv, "TEXA"sv, "RASA"sv, "KONST"sv, "ZERO"sv, -}; - -constexpr std::array VtxAttributeNames{ - "pn_mtx", "tex0_mtx", "tex1_mtx", "tex2_mtx", "tex3_mtx", "tex4_mtx", "tex5_mtx", - "tex6_mtx", "tex7_mtx", "pos", "nrm", "clr0", "clr1", "tex0_uv", - "tex1_uv", "tex2_uv", "tex3_uv", "tex4_uv", "tex5_uv", "tex6_uv", "tex7_uv", - "pos_mtx_array", "nrm_mtx_array", "tex_mtx_array", "light_array", "nbt", -}; - -ShaderInfo build_shader_info(const ShaderConfig& config) noexcept { - // const auto hash = xxh3_hash(config); - // const auto it = g_gxCachedShaders.find(hash); - // if (it != g_gxCachedShaders.end()) { - // return it->second.second; - // } - - ShaderInfo info{ - .uniformSize = 64 * 3, // mv, mvInv, proj - }; - for (int i = 0; i < config.tevStageCount; ++i) { - const auto& stage = config.tevStages[i]; - // Color pass - color_arg_reg_info(stage.colorPass.a, stage, info); - color_arg_reg_info(stage.colorPass.b, stage, info); - color_arg_reg_info(stage.colorPass.c, stage, info); - color_arg_reg_info(stage.colorPass.d, stage, info); - info.writesTevReg.set(stage.colorOp.outReg); - - // Alpha pass - alpha_arg_reg_info(stage.alphaPass.a, stage, info); - alpha_arg_reg_info(stage.alphaPass.b, stage, info); - alpha_arg_reg_info(stage.alphaPass.c, stage, info); - alpha_arg_reg_info(stage.alphaPass.d, stage, info); - if (!info.writesTevReg.test(stage.alphaOp.outReg)) { - // If we're writing alpha to a register that's not been - // written to in the shader, load from uniform buffer - info.loadsTevReg.set(stage.alphaOp.outReg); - info.writesTevReg.set(stage.alphaOp.outReg); - } - } - info.uniformSize += info.loadsTevReg.count() * 16; - for (int i = 0; i < info.sampledColorChannels.size(); ++i) { - if (info.sampledColorChannels.test(i)) { - info.uniformSize += 32; - if (config.colorChannels[i].lightingEnabled) { - info.uniformSize += 16 + (80 * GX::MaxLights); - } - } - } - info.uniformSize += info.sampledKColors.count() * 16; - for (int i = 0; i < info.sampledTexCoords.size(); ++i) { - if (!info.sampledTexCoords.test(i)) { - continue; - } - const auto& tcg = config.tcgs[i]; - if (tcg.mtx != GX::IDENTITY) { - u32 texMtxIdx = (tcg.mtx - GX::TEXMTX0) / 3; - info.usesTexMtx.set(texMtxIdx); - info.texMtxTypes[texMtxIdx] = tcg.type; - } - if (tcg.postMtx != GX::PTIDENTITY) { - u32 postMtxIdx = (tcg.postMtx - GX::PTTEXMTX0) / 3; - info.usesPTTexMtx.set(postMtxIdx); - } - } - for (int i = 0; i < info.usesTexMtx.size(); ++i) { - if (info.usesTexMtx.test(i)) { - switch (info.texMtxTypes[i]) { - case GX::TG_MTX2x4: - info.uniformSize += 32; - break; - case GX::TG_MTX3x4: - info.uniformSize += 64; - break; - default: - break; - } - } - } - info.uniformSize += info.usesPTTexMtx.count() * 64; - if (config.fogType != GX::FOG_NONE) { - info.usesFog = true; - info.uniformSize += 32; - } - info.uniformSize += info.sampledTextures.count() * 4; - info.uniformSize = align_uniform(info.uniformSize); - return info; -} - -wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& info) noexcept { - const auto hash = xxh3_hash(config); - const auto it = g_gxCachedShaders.find(hash); - if (it != g_gxCachedShaders.end()) { -#ifndef NDEBUG - if (g_gxCachedShaderConfigs[hash] != config) { - Log.report(logvisor::Fatal, FMT_STRING("Shader collision!")); - unreachable(); - } -#endif - return it->second.first; - } - - if (EnableDebugPrints) { - Log.report(logvisor::Info, FMT_STRING("Shader config (hash {:x}):"), hash); - { - for (int i = 0; i < config.tevStageCount; ++i) { - const auto& stage = config.tevStages[i]; - Log.report(logvisor::Info, FMT_STRING(" tevStages[{}]:"), i); - Log.report(logvisor::Info, FMT_STRING(" color_a: {}"), TevColorArgNames[stage.colorPass.a]); - Log.report(logvisor::Info, FMT_STRING(" color_b: {}"), TevColorArgNames[stage.colorPass.b]); - Log.report(logvisor::Info, FMT_STRING(" color_c: {}"), TevColorArgNames[stage.colorPass.c]); - Log.report(logvisor::Info, FMT_STRING(" color_d: {}"), TevColorArgNames[stage.colorPass.d]); - Log.report(logvisor::Info, FMT_STRING(" alpha_a: {}"), TevAlphaArgNames[stage.alphaPass.a]); - Log.report(logvisor::Info, FMT_STRING(" alpha_b: {}"), TevAlphaArgNames[stage.alphaPass.b]); - Log.report(logvisor::Info, FMT_STRING(" alpha_c: {}"), TevAlphaArgNames[stage.alphaPass.c]); - Log.report(logvisor::Info, FMT_STRING(" alpha_d: {}"), TevAlphaArgNames[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.colorChannels.size(); ++i) { - const auto& chan = config.colorChannels[i]; - Log.report(logvisor::Info, FMT_STRING(" colorChannels[{}]: enabled {} mat {} amb {}"), i, chan.lightingEnabled, - chan.matSrc, chan.ambSrc); - } - for (int i = 0; i < config.tcgs.size(); ++i) { - const auto& tcg = config.tcgs[i]; - if (tcg.src != GX::MAX_TEXGENSRC) { - Log.report(logvisor::Info, FMT_STRING(" tcg[{}]: src {} mtx {} post {} type {} norm {}"), i, tcg.src, - tcg.mtx, tcg.postMtx, tcg.type, tcg.normalize); - } - } - Log.report(logvisor::Info, FMT_STRING(" alphaCompare: comp0 {} ref0 {} op {} comp1 {} ref1 {}"), - config.alphaCompare.comp0, config.alphaCompare.ref0, config.alphaCompare.op, config.alphaCompare.comp1, - config.alphaCompare.ref1); - Log.report(logvisor::Info, FMT_STRING(" indexedAttributeCount: {}"), config.indexedAttributeCount); - Log.report(logvisor::Info, FMT_STRING(" fogType: {}"), config.fogType); - } - } - - std::string uniformPre; - std::string uniBufAttrs; - std::string uniformBindings; - std::string sampBindings; - std::string texBindings; - std::string vtxOutAttrs; - std::string vtxInAttrs; - std::string vtxXfrAttrsPre; - std::string vtxXfrAttrs; - size_t locIdx = 0; - size_t vtxOutIdx = 0; - size_t uniBindingIdx = 1; - if (config.indexedAttributeCount > 0) { - // Display list attributes - int currAttrIdx = 0; - bool addedTex1Uv = false; - for (GX::Attr attr{}; attr < MaxVtxAttr; attr = GX::Attr(attr + 1)) { - // Indexed attributes - if (config.vtxAttrs[attr] != GX::INDEX8 && config.vtxAttrs[attr] != GX::INDEX16) { - continue; - } - const auto [div, rem] = std::div(currAttrIdx, 4); - std::string_view attrName; - bool addUniformBinding = true; - // TODO: this is a hack to only have to bind tex0_uv and tex1_uv for MP - // should figure out a more generic approach - if (attr >= GX::VA_TEX1 && attr <= GX::VA_TEX7) { - attrName = VtxAttributeNames[GX::VA_TEX1]; - addUniformBinding = !addedTex1Uv; - addedTex1Uv = true; - } else { - attrName = VtxAttributeNames[attr]; - } - vtxXfrAttrsPre += - fmt::format(FMT_STRING("\n var {} = v_arr_{}[in_dl{}[{}]];"), vtx_attr(config, attr), attrName, div, rem); - if (addUniformBinding) { - std::string_view arrType; - if (attr == GX::VA_POS || attr == GX::VA_NRM) { - arrType = "vec3"; - } else if (attr >= GX::VA_TEX0 && attr <= GX::VA_TEX7) { - arrType = "vec2"; - } - uniformBindings += fmt::format(FMT_STRING("\n@group(0) @binding({})" - "\nvar v_arr_{}: array<{}>;"), - uniBindingIdx++, attrName, arrType); - } - ++currAttrIdx; - } - auto [num4xAttrArrays, rem] = std::div(currAttrIdx, 4); - u32 num2xAttrArrays = 0; - if (rem > 2) { - ++num4xAttrArrays; - } else if (rem > 0) { - num2xAttrArrays = 1; - } - for (u32 i = 0; i < num4xAttrArrays; ++i) { - if (locIdx > 0) { - vtxInAttrs += "\n , "; - } else { - vtxInAttrs += "\n "; - } - vtxInAttrs += fmt::format(FMT_STRING("@location({}) in_dl{}: vec4"), locIdx++, i); - } - for (u32 i = 0; i < num2xAttrArrays; ++i) { - if (locIdx > 0) { - vtxInAttrs += "\n , "; - } else { - vtxInAttrs += "\n "; - } - vtxInAttrs += fmt::format(FMT_STRING("@location({}) in_dl{}: vec2"), locIdx++, num4xAttrArrays + i); - } - } - for (GX::Attr attr{}; attr < MaxVtxAttr; attr = GX::Attr(attr + 1)) { - // Direct attributes - if (config.vtxAttrs[attr] != GX::DIRECT) { - continue; - } - if (locIdx > 0) { - vtxInAttrs += "\n , "; - } else { - vtxInAttrs += "\n "; - } - if (attr == GX::VA_POS) { - vtxInAttrs += fmt::format(FMT_STRING("@location({}) in_pos: vec3"), locIdx++); - } else if (attr == GX::VA_NRM) { - vtxInAttrs += fmt::format(FMT_STRING("@location({}) in_nrm: vec3"), locIdx++); - } else if (attr == GX::VA_CLR0 || attr == GX::VA_CLR1) { - vtxInAttrs += fmt::format(FMT_STRING("@location({}) in_clr{}: vec4"), locIdx++, attr - GX::VA_CLR0); - } else if (attr >= GX::VA_TEX0 && attr <= GX::VA_TEX7) { - vtxInAttrs += fmt::format(FMT_STRING("@location({}) in_tex{}_uv: vec2"), locIdx++, attr - GX::VA_TEX0); - } - } - vtxXfrAttrsPre += fmt::format(FMT_STRING("\n var mv_pos = ubuf.pos_mtx * vec4({}, 1.0);" - "\n var mv_nrm = ubuf.nrm_mtx * vec4({}, 0.0);" - "\n out.pos = ubuf.proj * vec4(mv_pos, 1.0);"), - vtx_attr(config, GX::VA_POS), vtx_attr(config, GX::VA_NRM)); - if constexpr (EnableNormalVisualization) { - vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) nrm: vec3,"), vtxOutIdx++); - vtxXfrAttrsPre += "\n out.nrm = mv_nrm;"; - } - - std::string fragmentFnPre; - std::string fragmentFn; - for (u32 idx = 0; idx < config.tevStageCount; ++idx) { - const auto& stage = config.tevStages[idx]; - { - std::string outReg; - switch (stage.colorOp.outReg) { - case GX::TEVPREV: - outReg = "prev"; - break; - case GX::TEVREG0: - outReg = "tevreg0"; - break; - case GX::TEVREG1: - outReg = "tevreg1"; - break; - case GX::TEVREG2: - outReg = "tevreg2"; - break; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid colorOp outReg {}"), stage.colorOp.outReg); - } - std::string op = fmt::format( - FMT_STRING("(({4}mix({0}, {1}, {2}) + {3}){5}){6}"), color_arg_reg(stage.colorPass.a, idx, config, stage), - color_arg_reg(stage.colorPass.b, idx, config, stage), color_arg_reg(stage.colorPass.c, idx, config, stage), - color_arg_reg(stage.colorPass.d, idx, config, stage), 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(0.0), vec3(1.0))"), op); - } - fragmentFn += - fmt::format(FMT_STRING("\n // TEV stage {2}\n {0} = vec4({1}, {0}.a);"), outReg, op, idx); - } - { - std::string outReg; - switch (stage.alphaOp.outReg) { - case GX::TEVPREV: - outReg = "prev.a"; - break; - case GX::TEVREG0: - outReg = "tevreg0.a"; - break; - case GX::TEVREG1: - outReg = "tevreg1.a"; - break; - case GX::TEVREG2: - outReg = "tevreg2.a"; - break; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid alphaOp outReg {}"), stage.alphaOp.outReg); - } - std::string op = fmt::format( - FMT_STRING("(({4}mix({0}, {1}, {2}) + {3}){5}){6}"), alpha_arg_reg(stage.alphaPass.a, idx, config, stage), - alpha_arg_reg(stage.alphaPass.b, idx, config, stage), alpha_arg_reg(stage.alphaPass.c, idx, config, stage), - alpha_arg_reg(stage.alphaPass.d, idx, config, stage), 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); - } - } - if (info.loadsTevReg.test(0)) { - uniBufAttrs += "\n tevprev: vec4,"; - fragmentFnPre += "\n var prev = ubuf.tevprev;"; - } else { - fragmentFnPre += "\n var prev: vec4;"; - } - for (int i = 1 /* Skip TEVPREV */; i < info.loadsTevReg.size(); ++i) { - if (info.loadsTevReg.test(i)) { - uniBufAttrs += fmt::format(FMT_STRING("\n tevreg{}: vec4,"), i - 1); - fragmentFnPre += fmt::format(FMT_STRING("\n var tevreg{0} = ubuf.tevreg{0};"), i - 1); - } else if (info.writesTevReg.test(i)) { - fragmentFnPre += fmt::format(FMT_STRING("\n var tevreg{0}: vec4;"), i - 1); - } - } - bool addedLightStruct = false; - for (int i = 0; i < info.sampledColorChannels.size(); ++i) { - if (!info.sampledColorChannels.test(i)) { - continue; - } - - uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_amb: vec4,"), i); - uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_mat: vec4,"), i); - - const auto& cc = config.colorChannels[i]; - if (cc.lightingEnabled) { - if (!addedLightStruct) { - uniformPre += - "\n" - "struct Light {\n" - " pos: vec3,\n" - " dir: vec3,\n" - " color: vec4,\n" - " cos_att: vec3,\n" - " dist_att: vec3,\n" - "};"; - if (UsePerPixelLighting) { - vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) mv_pos: vec3,"), vtxOutIdx++); - vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) mv_nrm: vec3,"), vtxOutIdx++); - vtxXfrAttrs += fmt::format(FMT_STRING(R"""( - out.mv_pos = mv_pos; - out.mv_nrm = mv_nrm;)""")); - } - addedLightStruct = true; - } - - uniBufAttrs += fmt::format(FMT_STRING("\n lightState{}: u32,"), i); - uniBufAttrs += fmt::format(FMT_STRING("\n lights{}: array,"), i, GX::MaxLights); - - std::string ambSrc, matSrc, lightAttnFn, lightDiffFn; - if (cc.ambSrc == GX::SRC_VTX) { - ambSrc = vtx_attr(config, static_cast(GX::VA_CLR0 + i)); - } else if (cc.ambSrc == GX::SRC_REG) { - ambSrc = fmt::format(FMT_STRING("ubuf.cc{0}_amb"), i); - } - if (cc.matSrc == GX::SRC_VTX) { - matSrc = vtx_attr(config, static_cast(GX::VA_CLR0 + i)); - } else if (cc.matSrc == GX::SRC_REG) { - matSrc = fmt::format(FMT_STRING("ubuf.cc{0}_mat"), i); - } - GX::DiffuseFn diffFn = cc.diffFn; - if (cc.attnFn == GX::AF_NONE) { - lightAttnFn = "attn = 1.0;"; - } else if (cc.attnFn == GX::AF_SPOT) { - lightAttnFn = fmt::format(FMT_STRING(R"""( - var cosine = max(0.0, dot(ldir, light.dir)); - var cos_attn = dot(light.cos_att, vec3(1.0, cosine, cosine * cosine)); - var dist_attn = dot(light.dist_att, vec3(1.0, dist, dist2)); - attn = max(0.0, cos_attn / dist_attn);)""")); - } else if (cc.attnFn == GX::AF_SPEC) { - diffFn = GX::DF_NONE; - Log.report(logvisor::Fatal, FMT_STRING("AF_SPEC unimplemented")); - } - if (diffFn == GX::DF_NONE) { - lightDiffFn = "1.0"; - } else if (diffFn == GX::DF_SIGN) { - if (UsePerPixelLighting) { - lightDiffFn = "dot(ldir, in.mv_nrm)"; - } else { - lightDiffFn = "dot(ldir, mv_nrm)"; - } - } else if (diffFn == GX::DF_CLAMP) { - if (UsePerPixelLighting) { - lightDiffFn = "max(0.0, dot(ldir, in.mv_nrm))"; - } else { - lightDiffFn = "max(0.0, dot(ldir, mv_nrm))"; - } - } - std::string outVar, posVar; - if (UsePerPixelLighting) { - outVar = fmt::format(FMT_STRING("rast{}"), i); - posVar = "in.mv_pos"; - } else { - outVar = fmt::format(FMT_STRING("out.cc{}"), i); - posVar = "mv_pos"; - } - auto lightFunc = fmt::format(FMT_STRING(R"""( - {{ - var lighting = {5}; - for (var i = 0u; i < {1}u; i++) {{ - if ((ubuf.lightState{0} & (1u << i)) == 0u) {{ continue; }} - var light = ubuf.lights{0}[i]; - var ldir = light.pos - {7}; - var dist2 = dot(ldir, ldir); - var dist = sqrt(dist2); - ldir = ldir / dist; - var attn: f32;{2} - var diff = {3}; - lighting = lighting + (attn * diff * light.color); - }} - {6} = {4} * clamp(lighting, vec4(0.0), vec4(1.0)); - }})"""), - i, GX::MaxLights, lightAttnFn, lightDiffFn, matSrc, ambSrc, outVar, posVar); - if (UsePerPixelLighting) { - fragmentFnPre += fmt::format(FMT_STRING("\n var rast{}: vec4;"), i); - fragmentFnPre += lightFunc; - } else { - vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4,"), vtxOutIdx++, i); - vtxXfrAttrs += lightFunc; - fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i); - } - } else if (cc.matSrc == GX::SRC_VTX) { - vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4,"), vtxOutIdx++, i); - vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = {};"), i, vtx_attr(config, GX::Attr(GX::VA_CLR0 + i))); - fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i); - } 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)) { - uniBufAttrs += fmt::format(FMT_STRING("\n kcolor{}: vec4,"), i); - } - } - for (int i = 0; i < info.sampledTexCoords.size(); ++i) { - if (!info.sampledTexCoords.test(i)) { - continue; - } - const auto& tcg = config.tcgs[i]; - vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2,"), vtxOutIdx++, i); - if (tcg.src >= GX::TG_TEX0 && tcg.src <= GX::TG_TEX7) { - vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4({}, 0.0, 1.0);"), i, - vtx_attr(config, GX::Attr(GX::VA_TEX0 + (tcg.src - GX::TG_TEX0)))); - } else if (tcg.src == GX::TG_POS) { - vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4(in_pos, 1.0);"), i); - } else if (tcg.src == GX::TG_NRM) { - vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4(in_nrm, 1.0);"), i); - } else { - Log.report(logvisor::Fatal, FMT_STRING("unhandled tcg src {} for "), tcg.src); - unreachable(); - } - if (tcg.mtx == GX::IDENTITY) { - vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_tmp = tc{0}.xyz;"), i); - } else { - u32 texMtxIdx = (tcg.mtx - GX::TEXMTX0) / 3; - vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_tmp = ubuf.texmtx{1} * tc{0};"), i, texMtxIdx); - } - if (tcg.normalize) { - vtxXfrAttrs += fmt::format(FMT_STRING("\n tc{0}_tmp = normalize(tc{0}_tmp);"), i); - } - if (tcg.postMtx == GX::PTIDENTITY) { - vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_proj = tc{0}_tmp;"), i); - } else { - u32 postMtxIdx = (tcg.postMtx - GX::PTTEXMTX0) / 3; - vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_proj = ubuf.postmtx{1} * vec4(tc{0}_tmp.xyz, 1.0);"), - i, postMtxIdx); - } - vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{0}_uv = tc{0}_proj.xy;"), i); - } - for (int i = 0; i < config.tevStages.size(); ++i) { - const auto& stage = config.tevStages[i]; - if (stage.texMapId == GX::TEXMAP_NULL || - stage.texCoordId == GX::TEXCOORD_NULL - // TODO should check this per-stage probably - || !info.sampledTextures.test(stage.texMapId)) { - continue; - } - std::string uvIn = fmt::format(FMT_STRING("in.tex{0}_uv"), stage.texCoordId); - const auto& texConfig = config.textureConfig[stage.texMapId]; - if (is_palette_format(texConfig.loadFmt)) { - std::string_view suffix; - if (!is_palette_format(texConfig.copyFmt)) { - switch (texConfig.loadFmt) { - case GX::TF_C4: - suffix = "I4"sv; - break; -// case GX::TF_C8: -// suffix = "I8"; -// break; -// case GX::TF_C14X2: -// suffix = "I14X2"; -// break; - default: - Log.report(logvisor::Fatal, FMT_STRING("Unsupported palette format {}"), texConfig.loadFmt); - unreachable(); - } - } - fragmentFnPre += - fmt::format(FMT_STRING("\n var sampled{0} = textureSamplePalette{3}(tex{1}, tex{1}_samp, {2}, tlut{1});"), - i, stage.texMapId, uvIn, suffix); - } else { - fragmentFnPre += fmt::format( - FMT_STRING("\n var sampled{0} = textureSampleBias(tex{1}, tex{1}_samp, {2}, ubuf.tex{1}_lod);"), i, - stage.texMapId, uvIn); - } - fragmentFnPre += texture_conversion(texConfig, i, stage.texMapId); - } - for (int i = 0; i < info.usesTexMtx.size(); ++i) { - if (info.usesTexMtx.test(i)) { - switch (info.texMtxTypes[i]) { - case GX::TG_MTX2x4: - uniBufAttrs += fmt::format(FMT_STRING("\n texmtx{}: mat4x2,"), i); - break; - case GX::TG_MTX3x4: - uniBufAttrs += fmt::format(FMT_STRING("\n texmtx{}: mat4x3,"), i); - break; - default: - Log.report(logvisor::Fatal, FMT_STRING("unhandled tex mtx type {}"), info.texMtxTypes[i]); - unreachable(); - } - } - } - for (int i = 0; i < info.usesPTTexMtx.size(); ++i) { - if (info.usesPTTexMtx.test(i)) { - uniBufAttrs += fmt::format(FMT_STRING("\n postmtx{}: mat4x3,"), i); - } - } - if (info.usesFog) { - uniformPre += - "\n" - "struct Fog {\n" - " color: vec4,\n" - " a: f32,\n" - " b: f32,\n" - " c: f32,\n" - " pad: f32,\n" - "}"; - uniBufAttrs += "\n fog: Fog,"; - - fragmentFn += "\n // Fog\n var fogF = clamp((ubuf.fog.a / (ubuf.fog.b - in.pos.z)) - ubuf.fog.c, 0.0, 1.0);"; - switch (config.fogType) { - case GX::FOG_PERSP_LIN: - case GX::FOG_ORTHO_LIN: - fragmentFn += "\n var fogZ = fogF;"; - break; - case GX::FOG_PERSP_EXP: - case GX::FOG_ORTHO_EXP: - fragmentFn += "\n var fogZ = 1.0 - exp2(-8.0 * fogF);"; - break; - case GX::FOG_PERSP_EXP2: - case GX::FOG_ORTHO_EXP2: - fragmentFn += "\n var fogZ = 1.0 - exp2(-8.0 * fogF * fogF);"; - break; - case GX::FOG_PERSP_REVEXP: - case GX::FOG_ORTHO_REVEXP: - fragmentFn += "\n var fogZ = exp2(-8.0 * (1.0 - fogF));"; - break; - case GX::FOG_PERSP_REVEXP2: - case GX::FOG_ORTHO_REVEXP2: - fragmentFn += - "\n fogF = 1.0 - fogF;" - "\n var fogZ = exp2(-8.0 * fogF * fogF);"; - break; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid fog type {}"), config.fogType); - unreachable(); - } - fragmentFn += "\n prev = vec4(mix(prev.rgb, ubuf.fog.color.rgb, clamp(fogZ, 0.0, 1.0)), prev.a);"; - } - size_t texBindIdx = 0; - for (int i = 0; i < info.sampledTextures.size(); ++i) { - if (!info.sampledTextures.test(i)) { - continue; - } - uniBufAttrs += fmt::format(FMT_STRING("\n tex{}_lod: f32,"), i); - - sampBindings += fmt::format(FMT_STRING("\n@group(1) @binding({})\n" - "var tex{}_samp: sampler;"), - texBindIdx, i); - - const auto& texConfig = config.textureConfig[i]; - if (is_palette_format(texConfig.loadFmt)) { - texBindings += fmt::format(FMT_STRING("\n@group(2) @binding({})\n" - "var tex{}: texture_2d<{}>;"), - texBindIdx, i, is_palette_format(texConfig.copyFmt) ? "i32"sv : "f32"sv); - ++texBindIdx; - texBindings += fmt::format(FMT_STRING("\n@group(2) @binding({})\n" - "var tlut{}: texture_2d;"), - texBindIdx, i); - } else { - texBindings += fmt::format(FMT_STRING("\n@group(2) @binding({})\n" - "var tex{}: texture_2d;"), - texBindIdx, i); - } - ++texBindIdx; - } - - if (config.alphaCompare) { - bool comp0Valid = true; - bool comp1Valid = true; - std::string comp0 = alpha_compare(config.alphaCompare.comp0, config.alphaCompare.ref0, comp0Valid); - std::string comp1 = alpha_compare(config.alphaCompare.comp1, config.alphaCompare.ref1, comp1Valid); - if (comp0Valid || comp1Valid) { - fragmentFn += "\n // Alpha compare"; - switch (config.alphaCompare.op) { - case GX::AOP_AND: - fragmentFn += fmt::format(FMT_STRING("\n if (!({} && {})) {{ discard; }}"), comp0, comp1); - break; - case GX::AOP_OR: - fragmentFn += fmt::format(FMT_STRING("\n if (!({} || {})) {{ discard; }}"), comp0, comp1); - break; - case GX::AOP_XOR: - fragmentFn += fmt::format(FMT_STRING("\n if (!({} ^^ {})) {{ discard; }}"), comp0, comp1); - break; - case GX::AOP_XNOR: - fragmentFn += fmt::format(FMT_STRING("\n if (({} ^^ {})) {{ discard; }}"), comp0, comp1); - break; - default: - Log.report(logvisor::Fatal, FMT_STRING("invalid alpha compare op {}"), config.alphaCompare.op); - unreachable(); - } - } - } - if constexpr (EnableNormalVisualization) { - fragmentFn += "\n prev = vec4(in.nrm, prev.a);"; - } - - const auto shaderSource = fmt::format(FMT_STRING(R"""({10} -struct Uniform {{ - pos_mtx: mat4x3, - nrm_mtx: mat4x3, - proj: mat4x4,{0} -}}; -@group(0) @binding(0) -var ubuf: Uniform;{3}{1}{2} - -struct VertexOutput {{ - @builtin(position) pos: vec4,{4} -}}; - -fn intensityF32(rgb: vec3) -> f32 {{ - // RGB to intensity conversion - // https://github.com/dolphin-emu/dolphin/blob/4cd48e609c507e65b95bca5afb416b59eaf7f683/Source/Core/VideoCommon/TextureConverterShaderGen.cpp#L237-L241 - return dot(rgb, vec3(0.257, 0.504, 0.098)) + 16.0 / 255.0; -}} -fn intensityI4(rgb: vec3) -> i32 {{ - return i32(intensityF32(rgb) * 16.f); -}} -fn textureSamplePalette(tex: texture_2d, samp: sampler, uv: vec2, tlut: texture_2d) -> vec4 {{ - // Gather index values - var i = textureGather(0, tex, samp, uv); - // Load palette colors - var c0 = textureLoad(tlut, vec2(i[0], 0), 0); - var c1 = textureLoad(tlut, vec2(i[1], 0), 0); - var c2 = textureLoad(tlut, vec2(i[2], 0), 0); - var c3 = textureLoad(tlut, vec2(i[3], 0), 0); - // Perform bilinear filtering - var f = fract(uv * vec2(textureDimensions(tex)) + 0.5); - var t0 = mix(c3, c2, f.x); - var t1 = mix(c0, c1, f.x); - return mix(t0, t1, f.y); -}} -fn textureSamplePaletteI4(tex: texture_2d, samp: sampler, uv: vec2, tlut: texture_2d) -> vec4 {{ - // Gather RGB channels - var iR = textureGather(0, tex, samp, uv); - var iG = textureGather(1, tex, samp, uv); - var iB = textureGather(2, tex, samp, uv); - // Perform intensity conversion - var i0 = intensityI4(vec3(iR[0], iG[0], iB[0])); - var i1 = intensityI4(vec3(iR[1], iG[1], iB[1])); - var i2 = intensityI4(vec3(iR[2], iG[2], iB[2])); - var i3 = intensityI4(vec3(iR[3], iG[3], iB[3])); - // Load palette colors - var c0 = textureLoad(tlut, vec2(i0, 0), 0); - var c1 = textureLoad(tlut, vec2(i1, 0), 0); - var c2 = textureLoad(tlut, vec2(i2, 0), 0); - var c3 = textureLoad(tlut, vec2(i3, 0), 0); - // Perform bilinear filtering - var f = fract(uv * vec2(textureDimensions(tex)) + 0.5); - var t0 = mix(c3, c2, f.x); - var t1 = mix(c0, c1, f.x); - return mix(t0, t1, f.y); -}} - -@stage(vertex) -fn vs_main({5} -) -> VertexOutput {{ - var out: VertexOutput;{9}{6} - return out; -}} - -@stage(fragment) -fn fs_main(in: VertexOutput) -> @location(0) vec4 {{{8}{7} - return prev; -}} -)"""), - uniBufAttrs, sampBindings, texBindings, uniformBindings, vtxOutAttrs, - vtxInAttrs, vtxXfrAttrs, fragmentFn, fragmentFnPre, vtxXfrAttrsPre, uniformPre); - if (EnableDebugPrints) { - Log.report(logvisor::Info, FMT_STRING("Generated shader: {}"), shaderSource); - } - - wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{}; - wgslDescriptor.source = shaderSource.c_str(); - const auto label = fmt::format(FMT_STRING("GX Shader {:x}"), hash); - const auto shaderDescriptor = wgpu::ShaderModuleDescriptor{ - .nextInChain = &wgslDescriptor, - .label = label.c_str(), - }; - auto shader = gpu::g_device.CreateShaderModule(&shaderDescriptor); - - auto pair = std::make_pair(std::move(shader), info); - g_gxCachedShaders.emplace(hash, pair); -#ifndef NDEBUG - g_gxCachedShaderConfigs.emplace(hash, config); -#endif - - return pair.first; -} -} // namespace aurora::gfx::gx diff --git a/aurora/lib/gfx/model/shader.cpp b/aurora/lib/gfx/model/shader.cpp deleted file mode 100644 index 3e300b520..000000000 --- a/aurora/lib/gfx/model/shader.cpp +++ /dev/null @@ -1,303 +0,0 @@ -#include "shader.hpp" - -#include "../../gpu.hpp" -#include "../common.hpp" - -#include -#include - -namespace aurora::gfx::model { -static logvisor::Module Log("aurora::gfx::model"); - -static const std::vector* vtxData; -static const std::vector* nrmData; -static const std::vector>* tex0TcData; -static const std::vector>* tcData; -static std::optional cachedVtxRange; -static std::optional cachedNrmRange; -static std::optional cachedPackedTcRange; -static std::optional cachedTcRange; - -static inline void read_vert(ByteBuffer& out, const u8* data) noexcept { - size_t offset = 0; - for (const auto& type : gx::g_gxState.vtxDesc) { - if (type == GX::INDEX8) { - const auto v = static_cast(data[offset]); // expand to s16 - out.append(&v, 2); - ++offset; - } else if (type == GX::INDEX16) { - const s16 v = metaforce::SBig(*reinterpret_cast(data + offset)); - out.append(&v, 2); - offset += 2; - } - } - constexpr size_t align = 4; // Sint16x2 - if (offset % align != 0) { - out.append_zeroes(align - (offset % align)); - } -} - -static absl::flat_hash_map> sCachedDisplayLists; - -void queue_surface(const u8* dlStart, u32 dlSize) noexcept { - // TODO CElementGen needs fixing - for (const auto& type : gx::g_gxState.vtxDesc) { - if (type == GX::DIRECT) { - Log.report(logvisor::Warning, FMT_STRING("Direct attributes in surface config!")); - return; - } - } - - const auto hash = xxh3_hash_s(dlStart, dlSize, 0); - Range vertRange, idxRange; - u32 numIndices = 0; - auto it = sCachedDisplayLists.find(hash); - if (it != sCachedDisplayLists.end()) { - const auto& [verts, indices] = it->second; - numIndices = indices.size() / 2; - vertRange = push_verts(verts.data(), verts.size()); - idxRange = push_indices(indices.data(), indices.size()); - } else { - ByteBuffer vtxBuf; - ByteBuffer idxBuf; - u8 inVtxSize = 0; - u8 outVtxSize = 0; - for (const auto& type : gx::g_gxState.vtxDesc) { - if (type == GX::DIRECT) { - Log.report(logvisor::Fatal, FMT_STRING("Direct attributes in surface config!")); - unreachable(); - } - if (type == GX::NONE) { - continue; - } - if (type == GX::INDEX8) { - ++inVtxSize; - outVtxSize += 2; - } else if (type == GX::INDEX16) { - inVtxSize += 2; - outVtxSize += 2; - } else { - Log.report(logvisor::Fatal, FMT_STRING("unexpected vtx type {}"), type); - unreachable(); - } - } - outVtxSize = ALIGN(outVtxSize, 4); - - u16 vtxStart = 0; - size_t offset = 0; - while (offset < dlSize - 6) { - const auto header = dlStart[offset]; - const auto primitive = static_cast(header & 0xF8); - const auto dlVtxCount = metaforce::SBig(*reinterpret_cast(dlStart + offset + 1)); - offset += 3; - - if (primitive == 0) { - break; - } - if (primitive != GX::TRIANGLES && primitive != GX::TRIANGLESTRIP && primitive != GX::TRIANGLEFAN) { - Log.report(logvisor::Fatal, FMT_STRING("queue_surface: unsupported primitive type {}"), primitive); - unreachable(); - } - - vtxBuf.reserve_extra(dlVtxCount * outVtxSize); - if (dlVtxCount > 3 && (primitive == GX::TRIANGLEFAN || primitive == GX::TRIANGLESTRIP)) { - idxBuf.reserve_extra(((u32(dlVtxCount) - 3) * 3 + 3) * 2); - } else { - idxBuf.reserve_extra(dlVtxCount * 2); - } - u16 curVert = vtxStart; - for (u16 v = 0; v < dlVtxCount; ++v) { - read_vert(vtxBuf, dlStart + offset); - offset += inVtxSize; - if (primitive == GX::TRIANGLES || v < 3) { - idxBuf.append(&curVert, 2); - ++numIndices; - } else if (primitive == GX::TRIANGLEFAN) { - const std::array idxs{ - vtxStart, - u16(curVert - 1), - curVert, - }; - idxBuf.append(idxs.data(), 6); - numIndices += 3; - } else if (primitive == GX::TRIANGLESTRIP) { - if ((v & 1) == 0) { - const std::array idxs{ - u16(curVert - 2), - u16(curVert - 1), - curVert, - }; - idxBuf.append(idxs.data(), 6); - } else { - const std::array idxs{ - u16(curVert - 1), - u16(curVert - 2), - curVert, - }; - idxBuf.append(idxs.data(), 6); - } - numIndices += 3; - } - ++curVert; - } - vtxStart += dlVtxCount; - } - - vertRange = push_verts(vtxBuf.data(), vtxBuf.size()); - idxRange = push_indices(idxBuf.data(), idxBuf.size()); - sCachedDisplayLists.try_emplace(hash, std::move(vtxBuf), std::move(idxBuf)); - } - - Range sVtxRange, sNrmRange, sTcRange, sPackedTcRange; - if (cachedVtxRange) { - sVtxRange = *cachedVtxRange; - } else { - sVtxRange = push_storage(reinterpret_cast(vtxData->data()), vtxData->size() * 16); - cachedVtxRange = sVtxRange; - } - if (cachedNrmRange) { - sNrmRange = *cachedNrmRange; - } else { - sNrmRange = push_storage(reinterpret_cast(nrmData->data()), nrmData->size() * 16); - cachedNrmRange = sNrmRange; - } - if (cachedTcRange) { - sTcRange = *cachedTcRange; - } else { - sTcRange = push_storage(reinterpret_cast(tcData->data()), tcData->size() * 8); - cachedTcRange = sTcRange; - } - if (cachedPackedTcRange) { - sPackedTcRange = *cachedPackedTcRange; - } else if (tcData == tex0TcData) { - sPackedTcRange = sTcRange; - } else { - sPackedTcRange = push_storage(reinterpret_cast(tex0TcData->data()), tex0TcData->size() * 8); - cachedPackedTcRange = sPackedTcRange; - } - - model::PipelineConfig config{}; - populate_pipeline_config(config, GX::TRIANGLES); - const auto info = gx::build_shader_info(config.shaderConfig); - const gx::BindGroupRanges ranges{ - .vtxDataRange = sVtxRange, - .nrmDataRange = sNrmRange, - .tcDataRange = sTcRange, - .packedTcDataRange = sPackedTcRange, - }; - const auto bindGroups = gx::build_bind_groups(info, config.shaderConfig, ranges); - const auto pipeline = pipeline_ref(config); - - push_draw_command(model::DrawData{ - .pipeline = pipeline, - .vertRange = vertRange, - .idxRange = idxRange, - .dataRanges = ranges, - .uniformRange = build_uniform(info), - .indexCount = numIndices, - .bindGroups = bindGroups, - .dstAlpha = gx::g_gxState.dstAlpha, - }); -} - -State construct_state() { return {}; } - -wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] const PipelineConfig& config) { - const auto info = build_shader_info(config.shaderConfig); // TODO remove - const auto shader = build_shader(config.shaderConfig, info); - - std::array vtxAttrs{}; - auto [num4xAttr, rem] = std::div(config.shaderConfig.indexedAttributeCount, 4); - u32 num2xAttr = 0; - if (rem > 2) { - ++num4xAttr; - } else if (rem > 0) { - ++num2xAttr; - } - u32 offset = 0; - for (u32 i = 0; i < num4xAttr; ++i) { - vtxAttrs[i] = { - .format = wgpu::VertexFormat::Sint16x4, - .offset = offset, - .shaderLocation = i, - }; - offset += 8; - } - for (u32 i = 0; i < num2xAttr; ++i) { - const u32 idx = num4xAttr + i; - vtxAttrs[idx] = { - .format = wgpu::VertexFormat::Sint16x2, - .offset = offset, - .shaderLocation = idx, - }; - offset += 4; - } - const std::array vtxBuffers{wgpu::VertexBufferLayout{ - .arrayStride = offset, - .stepMode = wgpu::VertexStepMode::Vertex, - .attributeCount = num4xAttr + num2xAttr, - .attributes = vtxAttrs.data(), - }}; - - return build_pipeline(config, info, vtxBuffers, shader, "Model Pipeline"); -} - -void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass) { - if (!bind_pipeline(data.pipeline, pass)) { - return; - } - - const std::array offsets{ - data.uniformRange.offset, - storage_offset(data.dataRanges.vtxDataRange), - storage_offset(data.dataRanges.nrmDataRange), - storage_offset(data.dataRanges.packedTcDataRange), - storage_offset(data.dataRanges.tcDataRange), - }; - pass.SetBindGroup(0, find_bind_group(data.bindGroups.uniformBindGroup), offsets.size(), offsets.data()); - if (data.bindGroups.samplerBindGroup && data.bindGroups.textureBindGroup) { - pass.SetBindGroup(1, find_bind_group(data.bindGroups.samplerBindGroup)); - pass.SetBindGroup(2, find_bind_group(data.bindGroups.textureBindGroup)); - } - pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.offset, data.vertRange.size); - pass.SetIndexBuffer(g_indexBuffer, wgpu::IndexFormat::Uint16, data.idxRange.offset, data.idxRange.size); - if (data.dstAlpha != UINT32_MAX) { - const wgpu::Color color{0.f, 0.f, 0.f, data.dstAlpha / 255.f}; - pass.SetBlendConstant(&color); - } - pass.DrawIndexed(data.indexCount); -} -} // namespace aurora::gfx::model - -static absl::flat_hash_map sCachedRanges; -template -static inline void cache_array(const void* data, Vec*& outPtr, std::optional& outRange, u8 stride) { - Vec* vecPtr = static_cast(data); - outPtr = vecPtr; - outRange.reset(); -} - -void GXSetArray(GX::Attr attr, const void* data, u8 stride) noexcept { - using namespace aurora::gfx::model; - switch (attr) { - case GX::VA_POS: - cache_array(data, vtxData, cachedVtxRange, stride); - break; - case GX::VA_NRM: - cache_array(data, nrmData, cachedNrmRange, stride); - break; - case GX::VA_TEX0: - cache_array(data, tex0TcData, cachedPackedTcRange, stride); - break; - case GX::VA_TEX1: - cache_array(data, tcData, cachedTcRange, stride); - break; - default: - 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(data), nbytes); -} diff --git a/aurora/lib/gfx/model/shader.hpp b/aurora/lib/gfx/model/shader.hpp deleted file mode 100644 index b267164b7..000000000 --- a/aurora/lib/gfx/model/shader.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "../common.hpp" -#include "../gx.hpp" - -namespace aurora::gfx::model { -struct DrawData { - PipelineRef pipeline; - Range vertRange; - Range idxRange; - gx::BindGroupRanges dataRanges; - Range uniformRange; - uint32_t indexCount; - gx::GXBindGroups bindGroups; - u32 dstAlpha; -}; - -struct PipelineConfig : gx::PipelineConfig {}; - -struct State {}; - -State construct_state(); -wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] const PipelineConfig& config); -void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass); -} // namespace aurora::gfx::model diff --git a/aurora/lib/gfx/movie_player/shader.cpp b/aurora/lib/gfx/movie_player/shader.cpp deleted file mode 100644 index ec1690e2e..000000000 --- a/aurora/lib/gfx/movie_player/shader.cpp +++ /dev/null @@ -1,245 +0,0 @@ -#include "shader.hpp" - -#include "../../gpu.hpp" - -namespace aurora::gfx::movie_player { -using gpu::g_device; -using gpu::g_graphicsConfig; -using gpu::utils::make_vertex_attributes; -using gpu::utils::make_vertex_buffer_layout; -using gpu::utils::make_vertex_state; - -State construct_state() { - wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{}; - wgslDescriptor.source = R"""( -@group(0) @binding(0) -var tex_sampler: sampler; -@group(1) @binding(0) -var tex_y: texture_2d; -@group(1) @binding(1) -var tex_u: texture_2d; -@group(1) @binding(2) -var tex_v: texture_2d; - -struct VertexOutput { - @builtin(position) pos: vec4; - @location(0) uv: vec2; -}; - -@stage(vertex) -fn vs_main(@location(0) in_pos: vec3, @location(1) in_uv: vec2) -> VertexOutput { - var out: VertexOutput; - out.pos = vec4(in_pos, 1.0); - out.uv = in_uv; - return out; -} - -@stage(fragment) -fn fs_main(in: VertexOutput) -> @location(0) vec4 { - var yuv = vec3( - 1.1643 * (textureSample(tex_y, tex_sampler, in.uv).x - 0.0625), - textureSample(tex_u, tex_sampler, in.uv).x - 0.5, - textureSample(tex_v, tex_sampler, in.uv).x - 0.5 - ); - return vec4( - yuv.x + 1.5958 * yuv.z, - yuv.x - 0.39173 * yuv.y - 0.8129 * yuv.z, - yuv.x + 2.017 * yuv.y, - 1.0 - ); -} -)"""; - const auto shaderDescriptor = wgpu::ShaderModuleDescriptor{ - .nextInChain = &wgslDescriptor, - .label = "Movie Player Shader", - }; - auto shader = g_device.CreateShaderModule(&shaderDescriptor); - - const std::array uniformLayoutEntries{ - wgpu::BindGroupLayoutEntry{ - .binding = 0, - .visibility = wgpu::ShaderStage::Fragment, - .sampler = - wgpu::SamplerBindingLayout{ - .type = wgpu::SamplerBindingType::Filtering, - }, - }, - }; - const auto uniformLayoutDescriptor = wgpu::BindGroupLayoutDescriptor{ - .label = "Movie Player Uniform Bind Group Layout", - .entryCount = uniformLayoutEntries.size(), - .entries = uniformLayoutEntries.data(), - }; - auto uniformLayout = g_device.CreateBindGroupLayout(&uniformLayoutDescriptor); - - const auto samplerDescriptor = wgpu::SamplerDescriptor{ - .addressModeU = wgpu::AddressMode::Repeat, - .addressModeV = wgpu::AddressMode::Repeat, - .addressModeW = wgpu::AddressMode::Repeat, - .magFilter = wgpu::FilterMode::Linear, - .minFilter = wgpu::FilterMode::Linear, - .mipmapFilter = wgpu::FilterMode::Linear, - .maxAnisotropy = 1, - }; - auto sampler = g_device.CreateSampler(&samplerDescriptor); - - const std::array uniformBindGroupEntries{ - wgpu::BindGroupEntry{ - .binding = 0, - .sampler = sampler, - }, - }; - const auto uniformBindGroupDescriptor = wgpu::BindGroupDescriptor{ - .label = "Movie Player Uniform Bind Group", - .layout = uniformLayout, - .entryCount = uniformBindGroupEntries.size(), - .entries = uniformBindGroupEntries.data(), - }; - auto uniformBindGroup = g_device.CreateBindGroup(&uniformBindGroupDescriptor); - - const auto textureBinding = wgpu::TextureBindingLayout{ - .sampleType = wgpu::TextureSampleType::Float, - .viewDimension = wgpu::TextureViewDimension::e2D, - }; - const std::array textureLayoutEntries{ - wgpu::BindGroupLayoutEntry{ - .binding = 0, - .visibility = wgpu::ShaderStage::Fragment, - .texture = textureBinding, - }, - wgpu::BindGroupLayoutEntry{ - .binding = 1, - .visibility = wgpu::ShaderStage::Fragment, - .texture = textureBinding, - }, - wgpu::BindGroupLayoutEntry{ - .binding = 2, - .visibility = wgpu::ShaderStage::Fragment, - .texture = textureBinding, - }, - }; - const auto textureLayoutDescriptor = wgpu::BindGroupLayoutDescriptor{ - .label = "Movie Player Texture Bind Group Layout", - .entryCount = textureLayoutEntries.size(), - .entries = textureLayoutEntries.data(), - }; - auto textureLayout = g_device.CreateBindGroupLayout(&textureLayoutDescriptor); - - const std::array bindGroupLayouts{ - uniformLayout, - textureLayout, - }; - const auto pipelineLayoutDescriptor = wgpu::PipelineLayoutDescriptor{ - .label = "Movie Player Pipeline Layout", - .bindGroupLayoutCount = bindGroupLayouts.size(), - .bindGroupLayouts = bindGroupLayouts.data(), - }; - auto pipelineLayout = g_device.CreatePipelineLayout(&pipelineLayoutDescriptor); - - return { - .shader = shader, - .uniformLayout = uniformLayout, - .uniformBindGroup = uniformBindGroup, - .textureLayout = textureLayout, - .sampler = sampler, - .pipelineLayout = pipelineLayout, - }; -} - -wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] const PipelineConfig& config) { - const auto attributes = - make_vertex_attributes(std::array{wgpu::VertexFormat::Float32x3, wgpu::VertexFormat::Float32x2}); - const std::array vertexBuffers{make_vertex_buffer_layout(sizeof(Vert), attributes)}; - const auto depthStencil = wgpu::DepthStencilState{ - .format = g_graphicsConfig.depthFormat, - }; - const auto blendComponent = wgpu::BlendComponent{ - .srcFactor = wgpu::BlendFactor::SrcAlpha, - .dstFactor = wgpu::BlendFactor::OneMinusSrcAlpha, - }; - const auto blendState = wgpu::BlendState{ - .color = blendComponent, - .alpha = blendComponent, - }; - const std::array colorTargets{ - wgpu::ColorTargetState{ - .format = g_graphicsConfig.colorFormat, - .blend = &blendState, - .writeMask = wgpu::ColorWriteMask::Red | wgpu::ColorWriteMask::Green | wgpu::ColorWriteMask::Blue, - }, - }; - const auto fragmentState = wgpu::FragmentState{ - .module = state.shader, - .entryPoint = "fs_main", - .targetCount = colorTargets.size(), - .targets = colorTargets.data(), - }; - const auto pipelineDescriptor = wgpu::RenderPipelineDescriptor{ - .label = "Movie Player Pipeline", - .layout = state.pipelineLayout, - .vertex = make_vertex_state(state.shader, vertexBuffers), - .primitive = - wgpu::PrimitiveState{ - .topology = wgpu::PrimitiveTopology::TriangleStrip, - }, - .depthStencil = &depthStencil, - .multisample = - wgpu::MultisampleState{ - .count = g_graphicsConfig.msaaSamples, - }, - .fragment = &fragmentState, - }; - return g_device.CreateRenderPipeline(&pipelineDescriptor); -} - -DrawData make_draw_data(const State& state, const TextureHandle& tex_y, const TextureHandle& tex_u, - const TextureHandle& tex_v, float h_pad, float v_pad) { - auto pipeline = pipeline_ref(PipelineConfig{}); - - const std::array verts{ - Vert{{-h_pad, v_pad, 0.f}, {0.0, 0.0}}, - Vert{{-h_pad, -v_pad, 0.f}, {0.0, 1.0}}, - Vert{{h_pad, v_pad, 0.f}, {1.0, 0.0}}, - Vert{{h_pad, -v_pad, 0.f}, {1.0, 1.0}}, - }; - const auto vertRange = push_verts(ArrayRef{verts}); - - const std::array entries{ - wgpu::BindGroupEntry{ - .binding = 0, - .textureView = tex_y->view, - }, - wgpu::BindGroupEntry{ - .binding = 1, - .textureView = tex_u->view, - }, - wgpu::BindGroupEntry{ - .binding = 2, - .textureView = tex_v->view, - }, - }; - const auto textureBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{ - .label = "Movie Player Texture Bind Group", - .layout = state.textureLayout, - .entryCount = entries.size(), - .entries = entries.data(), - }); - - return { - .pipeline = pipeline, - .vertRange = vertRange, - .textureBindGroup = textureBindGroup, - }; -} - -void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass) { - if (!bind_pipeline(data.pipeline, pass)) { - return; - } - - pass.SetBindGroup(0, state.uniformBindGroup); - pass.SetBindGroup(1, find_bind_group(data.textureBindGroup)); - pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.offset, data.vertRange.size); - pass.Draw(4); -} -} // namespace aurora::gfx::movie_player diff --git a/aurora/lib/gfx/movie_player/shader.hpp b/aurora/lib/gfx/movie_player/shader.hpp deleted file mode 100644 index 3fa24ed8d..000000000 --- a/aurora/lib/gfx/movie_player/shader.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "../common.hpp" - -namespace aurora::gfx::movie_player { -struct DrawData { - PipelineRef pipeline; - Range vertRange; - Range uniformRange; - BindGroupRef textureBindGroup; -}; - -struct PipelineConfig { - u32 pad = 0; // empty -}; -static_assert(std::has_unique_object_representations_v); -static const std::array INITIAL_PIPELINES{ - PipelineConfig{}, -}; - -struct State { - wgpu::ShaderModule shader; - wgpu::BindGroupLayout uniformLayout; - wgpu::BindGroup uniformBindGroup; - wgpu::BindGroupLayout textureLayout; - wgpu::Sampler sampler; - wgpu::PipelineLayout pipelineLayout; -}; - -struct alignas(4) Vert { - Vec3 pos; - Vec2 uv; -}; - -State construct_state(); -wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] const PipelineConfig& config); -DrawData make_draw_data(const State& state, const TextureHandle& tex_y, const TextureHandle& tex_u, - const TextureHandle& tex_v, float h_pad, float v_pad); -void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass); -} // namespace aurora::gfx::movie_player diff --git a/aurora/lib/gfx/stream.cpp b/aurora/lib/gfx/stream.cpp deleted file mode 100644 index ffa55a519..000000000 --- a/aurora/lib/gfx/stream.cpp +++ /dev/null @@ -1,160 +0,0 @@ -#include "stream/shader.hpp" - -#include "../gpu.hpp" -#include "common.hpp" -#include "gx.hpp" - -static logvisor::Module Log("aurora::gfx::stream"); - -using aurora::gfx::gx::g_gxState; - -#ifndef NDEBUG -static inline GX::Attr next_attr(size_t begin) { - auto iter = std::find_if(g_gxState.vtxDesc.begin() + begin, g_gxState.vtxDesc.end(), - [](const auto type) { return type != GX::NONE; }); - if (begin > 0 && iter == g_gxState.vtxDesc.end()) { - // wrap around - iter = std::find_if(g_gxState.vtxDesc.begin(), g_gxState.vtxDesc.end(), - [](const auto type) { return type != GX::NONE; }); - } - return GX::Attr(iter - g_gxState.vtxDesc.begin()); -} -#endif - -struct SStreamState { - GX::Primitive primitive; - u16 vertexCount = 0; - aurora::ByteBuffer vertexBuffer; - std::vector indices; -#ifndef NDEBUG - GX::Attr nextAttr; -#endif - - explicit SStreamState(GX::Primitive primitive, u16 numVerts, u16 vertexSize) noexcept : primitive(primitive) { - vertexBuffer.reserve_extra(size_t(numVerts) * vertexSize); - if (numVerts > 3 && (primitive == GX::TRIANGLEFAN || primitive == GX::TRIANGLESTRIP)) { - indices.reserve((u32(numVerts) - 3) * 3 + 3); - } else if (numVerts > 4 && primitive == GX::QUADS) { - indices.reserve(u32(numVerts) / 4 * 6); - } else { - indices.reserve(numVerts); - } -#ifndef NDEBUG - nextAttr = next_attr(0); -#endif - } -}; -static std::optional sStreamState; - -void GXBegin(GX::Primitive primitive, GX::VtxFmt vtxFmt, u16 nVerts) noexcept { -#ifndef NDEBUG - if (sStreamState) { - Log.report(logvisor::Fatal, FMT_STRING("Stream began twice!")); - unreachable(); - } -#endif - uint16_t vertexSize = 0; - for (GX::Attr attr{}; const auto type : g_gxState.vtxDesc) { - if (type == GX::DIRECT) { - if (attr == GX::VA_POS || attr == GX::VA_NRM) { - vertexSize += 12; - } else if (attr == GX::VA_CLR0 || attr == GX::VA_CLR1) { - vertexSize += 16; - } else if (attr >= GX::VA_TEX0 && attr <= GX::VA_TEX7) { - vertexSize += 8; - } else { - Log.report(logvisor::Fatal, FMT_STRING("don't know how to handle attr {}"), attr); - unreachable(); - } - } else if (type == GX::INDEX8 || type == GX::INDEX16) { - vertexSize += 2; - } - attr = GX::Attr(attr + 1); - } - if (vertexSize == 0) { - Log.report(logvisor::Fatal, FMT_STRING("no vtx attributes enabled?")); - unreachable(); - } - sStreamState.emplace(primitive, nVerts, vertexSize); -} -static inline void check_attr_order(GX::Attr attr) noexcept { -#ifndef NDEBUG - if (!sStreamState) { - Log.report(logvisor::Fatal, FMT_STRING("Stream not started!")); - unreachable(); - } - if (sStreamState->nextAttr != attr) { - Log.report(logvisor::Fatal, FMT_STRING("bad attribute order: {}, expected {}"), attr, sStreamState->nextAttr); - unreachable(); - } - sStreamState->nextAttr = next_attr(attr + 1); -#endif -} -void GXPosition3f32(const zeus::CVector3f& pos) noexcept { - check_attr_order(GX::VA_POS); - auto& state = *sStreamState; - state.vertexBuffer.append(&pos, 12); - if (state.primitive == GX::TRIANGLES || state.vertexCount < 3) { - // pass - } else if (state.primitive == GX::TRIANGLEFAN) { - state.indices.push_back(0); - state.indices.push_back(state.vertexCount - 1); - } else if (state.primitive == GX::TRIANGLESTRIP) { - if ((state.vertexCount & 1) == 0) { - state.indices.push_back(state.vertexCount - 2); - state.indices.push_back(state.vertexCount - 1); - } else { - state.indices.push_back(state.vertexCount - 1); - state.indices.push_back(state.vertexCount - 2); - } - } else if (state.primitive == GX::QUADS) { - if ((state.vertexCount & 3) == 3) { - state.indices.push_back(state.vertexCount - 3); - state.indices.push_back(state.vertexCount - 1); - } - } - state.indices.push_back(state.vertexCount); - ++state.vertexCount; -} -void GXNormal3f32(const zeus::CVector3f& nrm) noexcept { - check_attr_order(GX::VA_NRM); - sStreamState->vertexBuffer.append(&nrm, 12); -} -void GXColor4f32(const zeus::CColor& color) noexcept { - check_attr_order(GX::VA_CLR0); - sStreamState->vertexBuffer.append(&color, 16); -} -void GXTexCoord2f32(const zeus::CVector2f& uv) noexcept { - check_attr_order(GX::VA_TEX0); - sStreamState->vertexBuffer.append(&uv, 8); -} -void GXPosition1x16(u16 idx) noexcept { - check_attr_order(GX::VA_POS); - // keep aligned - if (sStreamState->vertexBuffer.size() % 4 != 0) { - sStreamState->vertexBuffer.append_zeroes(4 - (sStreamState->vertexBuffer.size() % 4)); - } - sStreamState->vertexBuffer.append(&idx, 2); -} -void GXEnd() noexcept { - if (sStreamState->vertexCount == 0) { - sStreamState.reset(); - return; - } - const auto vertRange = aurora::gfx::push_verts(sStreamState->vertexBuffer.data(), sStreamState->vertexBuffer.size()); - const auto indexRange = aurora::gfx::push_indices(aurora::ArrayRef{sStreamState->indices}); - aurora::gfx::stream::PipelineConfig config{}; - populate_pipeline_config(config, GX::TRIANGLES); - const auto info = aurora::gfx::gx::build_shader_info(config.shaderConfig); - const auto pipeline = aurora::gfx::pipeline_ref(config); - aurora::gfx::push_draw_command(aurora::gfx::stream::DrawData{ - .pipeline = pipeline, - .vertRange = vertRange, - .uniformRange = build_uniform(info), - .indexRange = indexRange, - .indexCount = static_cast(sStreamState->indices.size()), - .bindGroups = aurora::gfx::gx::build_bind_groups(info, config.shaderConfig, {}), - .dstAlpha = g_gxState.dstAlpha, - }); - sStreamState.reset(); -} diff --git a/aurora/lib/gfx/stream/shader.cpp b/aurora/lib/gfx/stream/shader.cpp deleted file mode 100644 index a31521c2a..000000000 --- a/aurora/lib/gfx/stream/shader.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "shader.hpp" - -#include "../../gpu.hpp" -#include "../common.hpp" - -#include -#include - -namespace aurora::gfx::stream { -static logvisor::Module Log("aurora::gfx::stream"); - -using gpu::g_device; - -wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] const PipelineConfig& config) { - const auto info = build_shader_info(config.shaderConfig); // TODO remove - const auto shader = build_shader(config.shaderConfig, info); - - std::array attributes{}; - attributes[0] = wgpu::VertexAttribute{ - .format = wgpu::VertexFormat::Float32x3, - .offset = 0, - .shaderLocation = 0, - }; - uint64_t offset = 12; - uint32_t shaderLocation = 1; - if (config.shaderConfig.vtxAttrs[GX::VA_NRM] == GX::DIRECT) { - attributes[shaderLocation] = wgpu::VertexAttribute{ - .format = wgpu::VertexFormat::Float32x3, - .offset = offset, - .shaderLocation = shaderLocation, - }; - offset += 12; - shaderLocation++; - } - if (config.shaderConfig.vtxAttrs[GX::VA_CLR0] == GX::DIRECT) { - attributes[shaderLocation] = wgpu::VertexAttribute{ - .format = wgpu::VertexFormat::Float32x4, - .offset = offset, - .shaderLocation = shaderLocation, - }; - offset += 16; - shaderLocation++; - } - for (int i = GX::VA_TEX0; i < GX::VA_TEX7; ++i) { - if (config.shaderConfig.vtxAttrs[i] != GX::DIRECT) { - continue; - } - attributes[shaderLocation] = wgpu::VertexAttribute{ - .format = wgpu::VertexFormat::Float32x2, - .offset = offset, - .shaderLocation = shaderLocation, - }; - offset += 8; - shaderLocation++; - } - const std::array vertexBuffers{wgpu::VertexBufferLayout{ - .arrayStride = offset, - .attributeCount = shaderLocation, - .attributes = attributes.data(), - }}; - - return build_pipeline(config, info, vertexBuffers, shader, "Stream Pipeline"); -} - -State construct_state() { return {}; } - -void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass) { - if (!bind_pipeline(data.pipeline, pass)) { - return; - } - - const std::array offsets{data.uniformRange.offset}; - pass.SetBindGroup(0, find_bind_group(data.bindGroups.uniformBindGroup), offsets.size(), offsets.data()); - if (data.bindGroups.samplerBindGroup && data.bindGroups.textureBindGroup) { - pass.SetBindGroup(1, find_bind_group(data.bindGroups.samplerBindGroup)); - pass.SetBindGroup(2, find_bind_group(data.bindGroups.textureBindGroup)); - } - pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.offset, data.vertRange.size); - pass.SetIndexBuffer(g_indexBuffer, wgpu::IndexFormat::Uint16, data.indexRange.offset, data.indexRange.size); - if (data.dstAlpha != UINT32_MAX) { - const wgpu::Color color{0.f, 0.f, 0.f, data.dstAlpha / 255.f}; - pass.SetBlendConstant(&color); - } - pass.DrawIndexed(data.indexCount); -} -} // namespace aurora::gfx::stream diff --git a/aurora/lib/gfx/stream/shader.hpp b/aurora/lib/gfx/stream/shader.hpp deleted file mode 100644 index ffbde7283..000000000 --- a/aurora/lib/gfx/stream/shader.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "../common.hpp" -#include "../gx.hpp" - -namespace aurora::gfx::stream { -struct DrawData { - PipelineRef pipeline; - Range vertRange; - Range uniformRange; - Range indexRange; - uint32_t indexCount; - gx::GXBindGroups bindGroups; - u32 dstAlpha; -}; - -struct PipelineConfig : public gx::PipelineConfig {}; - -struct State {}; - -State construct_state(); -wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] const PipelineConfig& config); -void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass); -} // namespace aurora::gfx::stream diff --git a/aurora/lib/gfx/texture.cpp b/aurora/lib/gfx/texture.cpp deleted file mode 100644 index e55885e80..000000000 --- a/aurora/lib/gfx/texture.cpp +++ /dev/null @@ -1,202 +0,0 @@ -#include "common.hpp" - -#include "../gpu.hpp" -#include "texture_convert.hpp" - -#include -#include - -namespace aurora::gfx { -static logvisor::Module Log("aurora::gfx"); - -using gpu::g_device; -using gpu::g_queue; - -struct TextureFormatInfo { - uint8_t blockWidth; - uint8_t blockHeight; - uint8_t blockSize; - bool compressed; -}; -static TextureFormatInfo format_info(wgpu::TextureFormat format) { - switch (format) { - case wgpu::TextureFormat::R8Unorm: - return {1, 1, 1, false}; - case wgpu::TextureFormat::R16Sint: - return {1, 1, 2, false}; - case wgpu::TextureFormat::RGBA8Unorm: - case wgpu::TextureFormat::R32Float: - return {1, 1, 4, false}; - case wgpu::TextureFormat::BC1RGBAUnorm: - return {4, 4, 8, true}; - default: - Log.report(logvisor::Fatal, FMT_STRING("format_info: unimplemented format {}"), magic_enum::enum_name(format)); - unreachable(); - } -} -static wgpu::Extent3D physical_size(wgpu::Extent3D size, TextureFormatInfo info) { - const uint32_t width = ((size.width + info.blockWidth - 1) / info.blockWidth) * info.blockWidth; - const uint32_t height = ((size.height + info.blockHeight - 1) / info.blockHeight) * info.blockHeight; - return {width, height, size.depthOrArrayLayers}; -} - -TextureHandle new_static_texture_2d(uint32_t width, uint32_t height, uint32_t mips, GX::TextureFormat format, - ArrayRef data, zstring_view label) noexcept { - auto handle = new_dynamic_texture_2d(width, height, mips, format, label); - const auto& ref = *handle; - - ByteBuffer buffer; - if (ref.gxFormat != InvalidTextureFormat) { - buffer = convert_texture(ref.gxFormat, ref.size.width, ref.size.height, ref.mipCount, data); - if (!buffer.empty()) { - data = {buffer.data(), buffer.size()}; - } - } - - uint32_t offset = 0; - for (uint32_t mip = 0; mip < mips; ++mip) { - const auto mipSize = wgpu::Extent3D{ - .width = std::max(ref.size.width >> mip, 1u), - .height = std::max(ref.size.height >> mip, 1u), - .depthOrArrayLayers = ref.size.depthOrArrayLayers, - }; - const auto info = format_info(ref.format); - const auto physicalSize = physical_size(mipSize, info); - const uint32_t widthBlocks = physicalSize.width / info.blockWidth; - const uint32_t heightBlocks = physicalSize.height / info.blockHeight; - const uint32_t bytesPerRow = widthBlocks * info.blockSize; - const uint32_t dataSize = bytesPerRow * heightBlocks * mipSize.depthOrArrayLayers; - if (offset + dataSize > data.size()) { - Log.report(logvisor::Fatal, FMT_STRING("new_static_texture_2d[{}]: expected at least {} bytes, got {}"), label, - offset + dataSize, data.size()); - unreachable(); - } - auto dstView = wgpu::ImageCopyTexture{ - .texture = ref.texture, - .mipLevel = mip, - }; -// const auto range = push_texture_data(data.data() + offset, dataSize, bytesPerRow, heightBlocks); - const auto dataLayout = wgpu::TextureDataLayout{ -// .offset = range.offset, - .bytesPerRow = bytesPerRow, - .rowsPerImage = heightBlocks, - }; - // TODO -// g_textureUploads.emplace_back(dataLayout, std::move(dstView), physicalSize); - g_queue.WriteTexture(&dstView, data.data() + offset, dataSize, &dataLayout, &physicalSize); - offset += dataSize; - } - if (data.size() != UINT32_MAX && offset < data.size()) { - Log.report(logvisor::Warning, FMT_STRING("new_static_texture_2d[{}]: texture used {} bytes, but given {} bytes"), - label, offset, data.size()); - } - return handle; -} - -TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t mips, GX::TextureFormat format, - zstring_view label) noexcept { - const auto wgpuFormat = to_wgpu(format); - const auto size = wgpu::Extent3D{ - .width = width, - .height = height, - }; - const auto textureDescriptor = wgpu::TextureDescriptor{ - .label = label.c_str(), - .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst, - .size = size, - .format = wgpuFormat, - .mipLevelCount = mips, - }; - const auto viewLabel = fmt::format(FMT_STRING("{} view"), label); - const auto textureViewDescriptor = wgpu::TextureViewDescriptor{ - .label = viewLabel.c_str(), - .format = wgpuFormat, - .dimension = wgpu::TextureViewDimension::e2D, - .mipLevelCount = mips, - }; - auto texture = g_device.CreateTexture(&textureDescriptor); - auto textureView = texture.CreateView(&textureViewDescriptor); - return std::make_shared(std::move(texture), std::move(textureView), size, wgpuFormat, mips, format, - false); -} - -TextureHandle new_render_texture(uint32_t width, uint32_t height, GX::TextureFormat fmt, zstring_view label) noexcept { - const auto wgpuFormat = gpu::g_graphicsConfig.colorFormat; - const auto size = wgpu::Extent3D{ - .width = width, - .height = height, - }; - const auto textureDescriptor = wgpu::TextureDescriptor{ - .label = label.c_str(), - .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst, - .size = size, - .format = wgpuFormat, - .mipLevelCount = 1, - }; - const auto viewLabel = fmt::format(FMT_STRING("{} view"), label); - const auto textureViewDescriptor = wgpu::TextureViewDescriptor{ - .label = viewLabel.c_str(), - .format = wgpuFormat, - .dimension = wgpu::TextureViewDimension::e2D, - .mipLevelCount = 1, - }; - auto texture = g_device.CreateTexture(&textureDescriptor); - auto textureView = texture.CreateView(&textureViewDescriptor); - return std::make_shared(std::move(texture), std::move(textureView), size, wgpuFormat, 1, fmt, true); -} - -void write_texture(const TextureRef& ref, ArrayRef data) noexcept { - ByteBuffer buffer; - if (ref.gxFormat != InvalidTextureFormat) { - buffer = convert_texture(ref.gxFormat, ref.size.width, ref.size.height, ref.mipCount, data); - if (!buffer.empty()) { - data = {buffer.data(), buffer.size()}; - } - } - - uint32_t offset = 0; - for (uint32_t mip = 0; mip < ref.mipCount; ++mip) { - const auto mipSize = wgpu::Extent3D{ - .width = std::max(ref.size.width >> mip, 1u), - .height = std::max(ref.size.height >> mip, 1u), - .depthOrArrayLayers = ref.size.depthOrArrayLayers, - }; - const auto info = format_info(ref.format); - const auto physicalSize = physical_size(mipSize, info); - const uint32_t widthBlocks = physicalSize.width / info.blockWidth; - const uint32_t heightBlocks = physicalSize.height / info.blockHeight; - const uint32_t bytesPerRow = widthBlocks * info.blockSize; - const uint32_t dataSize = bytesPerRow * heightBlocks * mipSize.depthOrArrayLayers; - if (offset + dataSize > data.size()) { - Log.report(logvisor::Fatal, FMT_STRING("write_texture: expected at least {} bytes, got {}"), offset + dataSize, - data.size()); - unreachable(); - } -// auto dstView = wgpu::ImageCopyTexture{ -// .texture = ref.texture, -// .mipLevel = mip, -// }; -// const auto range = push_texture_data(data.data() + offset, dataSize, bytesPerRow, heightBlocks); -// const auto dataLayout = wgpu::TextureDataLayout{ -// .offset = range.offset, -// .bytesPerRow = bytesPerRow, -// .rowsPerImage = heightBlocks, -// }; -// g_textureUploads.emplace_back(dataLayout, std::move(dstView), physicalSize); - const auto dstView = wgpu::ImageCopyTexture{ - .texture = ref.texture, - .mipLevel = mip, - }; - const auto dataLayout = wgpu::TextureDataLayout{ - .bytesPerRow = bytesPerRow, - .rowsPerImage = heightBlocks, - }; - g_queue.WriteTexture(&dstView, data.data() + offset, dataSize, &dataLayout, &physicalSize); - offset += dataSize; - } - if (data.size() != UINT32_MAX && offset < data.size()) { - Log.report(logvisor::Warning, FMT_STRING("write_texture: texture used {} bytes, but given {} bytes"), offset, - data.size()); - } -} -} // namespace aurora::gfx diff --git a/aurora/lib/gfx/texture_convert.cpp b/aurora/lib/gfx/texture_convert.cpp deleted file mode 100644 index 40d78a9be..000000000 --- a/aurora/lib/gfx/texture_convert.cpp +++ /dev/null @@ -1,601 +0,0 @@ -#include "texture_convert.hpp" - -namespace aurora::gfx { -static logvisor::Module Log("aurora::gfx"); - -struct RGBA8 { - u8 r; - u8 g; - u8 b; - u8 a; -}; -struct DXT1Block { - u16 color1; - u16 color2; - std::array lines; -}; - -// http://www.mindcontrol.org/~hplus/graphics/expand-bits.html -template -constexpr u8 ExpandTo8(u8 n) { - if constexpr (v == 3) { - return (n << (8 - 3)) | (n << (8 - 6)) | (n >> (9 - 8)); - } else { - return (n << (8 - v)) | (n >> ((v * 2) - 8)); - } -} - -constexpr u8 S3TCBlend(u32 a, u32 b) { - return static_cast((((a << 1) + a) + ((b << 2) + b)) >> 3); -} - -constexpr u8 HalfBlend(u8 a, u8 b) { return static_cast((static_cast(a) + static_cast(b)) >> 1); } - -static size_t ComputeMippedTexelCount(u32 w, u32 h, u32 mips) { - size_t ret = w * h; - for (u32 i = mips; i > 1; --i) { - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - ret += w * h; - } - return ret; -} - -static size_t ComputeMippedBlockCountDXT1(u32 w, u32 h, u32 mips) { - w /= 4; - h /= 4; - size_t ret = w * h; - for (u32 i = mips; i > 1; --i) { - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - ret += w * h; - } - return ret; -} - -template -constexpr T bswap16(T val) noexcept { -#if __GNUC__ - return __builtin_bswap16(val); -#elif _WIN32 - return _byteswap_ushort(val); -#else - return (val = (val << 8) | ((val >> 8) & 0xFF)); -#endif -} - -static ByteBuffer BuildI4FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef data) { - const size_t texelCount = ComputeMippedTexelCount(width, height, mips); - ByteBuffer buf{texelCount}; - - uint32_t w = width; - uint32_t h = height; - u8* targetMip = buf.data(); - const uint8_t* in = data.data(); - for (uint32_t mip = 0; mip < mips; ++mip) { - const uint32_t bwidth = (w + 7) / 8; - const uint32_t bheight = (h + 7) / 8; - for (uint32_t by = 0; by < bheight; ++by) { - const uint32_t baseY = by * 8; - for (uint32_t bx = 0; bx < bwidth; ++bx) { - const uint32_t baseX = bx * 8; - for (uint32_t y = 0; y < std::min(h, 8u); ++y) { - u8* target = targetMip + (baseY + y) * w + baseX; - for (uint32_t x = 0; x < std::min(w, 8u); ++x) { - target[x] = ExpandTo8<4>(in[x / 2] >> ((x & 1) ? 0 : 4) & 0xf); - } - in += std::min(w / 4, 4); - } - } - } - targetMip += w * h; - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - } - - return buf; -} - -static ByteBuffer BuildI8FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef data) { - const size_t texelCount = ComputeMippedTexelCount(width, height, mips); - ByteBuffer buf{texelCount}; - - uint32_t w = width; - uint32_t h = height; - auto* targetMip = buf.data(); - const uint8_t* in = data.data(); - for (uint32_t mip = 0; mip < mips; ++mip) { - const uint32_t bwidth = (w + 7) / 8; - const uint32_t bheight = (h + 3) / 4; - for (uint32_t by = 0; by < bheight; ++by) { - const uint32_t baseY = by * 4; - for (uint32_t bx = 0; bx < bwidth; ++bx) { - const uint32_t baseX = bx * 8; - for (uint32_t y = 0; y < 4; ++y) { - u8* target = targetMip + (baseY + y) * w + baseX; - const auto n = std::min(w, 8u); - for (size_t x = 0; x < n; ++x) { - target[x] = in[x]; - } - in += n; - } - } - } - targetMip += w * h; - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - } - - return buf; -} - -ByteBuffer BuildIA4FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef data) { - const size_t texelCount = ComputeMippedTexelCount(width, height, mips); - ByteBuffer buf{sizeof(RGBA8) * texelCount}; - - uint32_t w = width; - uint32_t h = height; - RGBA8* targetMip = reinterpret_cast(buf.data()); - const uint8_t* in = data.data(); - for (uint32_t mip = 0; mip < mips; ++mip) { - const uint32_t bwidth = (w + 7) / 8; - const uint32_t bheight = (h + 3) / 4; - for (uint32_t by = 0; by < bheight; ++by) { - const uint32_t baseY = by * 4; - for (uint32_t bx = 0; bx < bwidth; ++bx) { - const uint32_t baseX = bx * 8; - for (uint32_t y = 0; y < 4; ++y) { - RGBA8* target = targetMip + (baseY + y) * w + baseX; - const auto n = std::min(w, 8u); - for (size_t x = 0; x < n; ++x) { - const u8 intensity = ExpandTo8<4>(in[x] & 0xf); - target[x].r = intensity; - target[x].g = intensity; - target[x].b = intensity; - target[x].a = ExpandTo8<4>(in[x] >> 4); - } - in += n; - } - } - } - targetMip += w * h; - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - } - - return buf; -} - -ByteBuffer BuildIA8FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef data) { - const size_t texelCount = ComputeMippedTexelCount(width, height, mips); - ByteBuffer buf{sizeof(RGBA8) * texelCount}; - - uint32_t w = width; - uint32_t h = height; - auto* targetMip = reinterpret_cast(buf.data()); - const auto* in = reinterpret_cast(data.data()); - for (uint32_t mip = 0; mip < mips; ++mip) { - const uint32_t bwidth = (w + 3) / 4; - const uint32_t bheight = (h + 3) / 4; - for (uint32_t by = 0; by < bheight; ++by) { - const uint32_t baseY = by * 4; - for (uint32_t bx = 0; bx < bwidth; ++bx) { - const uint32_t baseX = bx * 4; - for (uint32_t y = 0; y < 4; ++y) { - RGBA8* target = targetMip + (baseY + y) * w + baseX; - for (size_t x = 0; x < 4; ++x) { - const auto texel = bswap16(in[x]); - const u8 intensity = texel >> 8; - target[x].r = intensity; - target[x].g = intensity; - target[x].b = intensity; - target[x].a = texel & 0xff; - } - in += 4; - } - } - } - targetMip += w * h; - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - } - - return buf; -} - -ByteBuffer BuildC4FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef data) { - const size_t texelCount = ComputeMippedTexelCount(width, height, mips); - ByteBuffer buf{texelCount * 2}; - - uint32_t w = width; - uint32_t h = height; - u16* targetMip = reinterpret_cast(buf.data()); - const uint8_t* in = data.data(); - for (uint32_t mip = 0; mip < mips; ++mip) { - const uint32_t bwidth = (w + 7) / 8; - const uint32_t bheight = (h + 7) / 8; - for (uint32_t by = 0; by < bheight; ++by) { - const uint32_t baseY = by * 8; - for (uint32_t bx = 0; bx < bwidth; ++bx) { - const uint32_t baseX = bx * 8; - for (uint32_t y = 0; y < std::min(8u, h); ++y) { - u16* target = targetMip + (baseY + y) * w + baseX; - const auto n = std::min(w, 8u); - for (size_t x = 0; x < n; ++x) { - target[x] = in[x / 2] >> ((x & 1) ? 0 : 4) & 0xf; - } - in += n / 2; - } - } - } - targetMip += w * h; - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - } - - return buf; -} - -ByteBuffer BuildC8FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef data) { - const size_t texelCount = ComputeMippedTexelCount(width, height, mips); - ByteBuffer buf{texelCount * 2}; - - uint32_t w = width; - uint32_t h = height; - u16* targetMip = reinterpret_cast(buf.data()); - const uint8_t* in = data.data(); - for (uint32_t mip = 0; mip < mips; ++mip) { - const uint32_t bwidth = (w + 7) / 8; - const uint32_t bheight = (h + 3) / 4; - for (uint32_t by = 0; by < bheight; ++by) { - const uint32_t baseY = by * 4; - for (uint32_t bx = 0; bx < bwidth; ++bx) { - const uint32_t baseX = bx * 8; - for (uint32_t y = 0; y < 4; ++y) { - u16* target = targetMip + (baseY + y) * w + baseX; - const auto n = std::min(w, 8u); - for (size_t x = 0; x < n; ++x) { - target[x] = in[x]; - } - in += n; - } - } - } - targetMip += w * h; - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - } - - return buf; -} - -ByteBuffer BuildRGB565FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef data) { - const size_t texelCount = ComputeMippedTexelCount(width, height, mips); - ByteBuffer buf{sizeof(RGBA8) * texelCount}; - - uint32_t w = width; - uint32_t h = height; - auto* targetMip = reinterpret_cast(buf.data()); - const auto* in = reinterpret_cast(data.data()); - for (uint32_t mip = 0; mip < mips; ++mip) { - const uint32_t bwidth = (w + 3) / 4; - const uint32_t bheight = (h + 3) / 4; - for (uint32_t by = 0; by < bheight; ++by) { - const uint32_t baseY = by * 4; - for (uint32_t bx = 0; bx < bwidth; ++bx) { - const uint32_t baseX = bx * 4; - for (uint32_t y = 0; y < std::min(4u, h); ++y) { - RGBA8* target = targetMip + (baseY + y) * w + baseX; - for (size_t x = 0; x < std::min(4u, w); ++x) { - const auto texel = bswap16(in[x]); - target[x].r = ExpandTo8<5>(texel >> 11 & 0x1f); - target[x].g = ExpandTo8<6>(texel >> 5 & 0x3f); - target[x].b = ExpandTo8<5>(texel & 0x1f); - target[x].a = 0xff; - } - in += 4; - } - } - } - targetMip += w * h; - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - } - - return buf; -} - -ByteBuffer BuildRGB5A3FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef data) { - size_t texelCount = ComputeMippedTexelCount(width, height, mips); - ByteBuffer buf{sizeof(RGBA8) * texelCount}; - - uint32_t w = width; - uint32_t h = height; - auto* targetMip = reinterpret_cast(buf.data()); - const auto* in = reinterpret_cast(data.data()); - for (uint32_t mip = 0; mip < mips; ++mip) { - const uint32_t bwidth = (w + 3) / 4; - const uint32_t bheight = (h + 3) / 4; - for (uint32_t by = 0; by < bheight; ++by) { - const uint32_t baseY = by * 4; - for (uint32_t bx = 0; bx < bwidth; ++bx) { - const uint32_t baseX = bx * 4; - for (uint32_t y = 0; y < std::min(4u, h); ++y) { - RGBA8* target = targetMip + (baseY + y) * w + baseX; - for (size_t x = 0; x < std::min(4u, w); ++x) { - const auto texel = bswap16(in[x]); - if ((texel & 0x8000) != 0) { - target[x].r = ExpandTo8<5>(texel >> 10 & 0x1f); - target[x].g = ExpandTo8<5>(texel >> 5 & 0x1f); - target[x].b = ExpandTo8<5>(texel & 0x1f); - target[x].a = 0xff; - } else { - target[x].r = ExpandTo8<4>(texel >> 8 & 0xf); - target[x].g = ExpandTo8<4>(texel >> 4 & 0xf); - target[x].b = ExpandTo8<4>(texel & 0xf); - target[x].a = ExpandTo8<3>(texel >> 12 & 0x7); - } - } - in += 4; - } - } - } - targetMip += w * h; - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - } - - return buf; -} - -ByteBuffer BuildRGBA8FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef data) { - const size_t texelCount = ComputeMippedTexelCount(width, height, mips); - ByteBuffer buf{sizeof(RGBA8) * texelCount}; - - uint32_t w = width; - uint32_t h = height; - auto* targetMip = reinterpret_cast(buf.data()); - const uint8_t* in = data.data(); - for (uint32_t mip = 0; mip < mips; ++mip) { - const uint32_t bwidth = (w + 3) / 4; - const uint32_t bheight = (h + 3) / 4; - for (uint32_t by = 0; by < bheight; ++by) { - const uint32_t baseY = by * 4; - for (uint32_t bx = 0; bx < bwidth; ++bx) { - const uint32_t baseX = bx * 4; - for (uint32_t c = 0; c < 2; ++c) { - for (uint32_t y = 0; y < 4; ++y) { - RGBA8* target = targetMip + (baseY + y) * w + baseX; - for (size_t x = 0; x < 4; ++x) { - if (c != 0) { - target[x].g = in[x * 2]; - target[x].b = in[x * 2 + 1]; - } else { - target[x].a = in[x * 2]; - target[x].r = in[x * 2 + 1]; - } - } - in += 8; - } - } - } - } - targetMip += w * h; - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - } - - return buf; -} - -ByteBuffer BuildDXT1FromGCN(uint32_t width, uint32_t height, uint32_t mips, ArrayRef data) { - const size_t blockCount = ComputeMippedBlockCountDXT1(width, height, mips); - ByteBuffer buf{sizeof(DXT1Block) * blockCount}; - - uint32_t w = width / 4; - uint32_t h = height / 4; - auto* targetMip = reinterpret_cast(buf.data()); - const auto* in = reinterpret_cast(data.data()); - for (uint32_t mip = 0; mip < mips; ++mip) { - const uint32_t bwidth = (w + 1) / 2; - const uint32_t bheight = (h + 1) / 2; - for (uint32_t by = 0; by < bheight; ++by) { - const uint32_t baseY = by * 2; - for (uint32_t bx = 0; bx < bwidth; ++bx) { - const uint32_t baseX = bx * 2; - for (uint32_t y = 0; y < 2; ++y) { - DXT1Block* target = targetMip + (baseY + y) * w + baseX; - for (size_t x = 0; x < 2; ++x) { - target[x].color1 = bswap16(in[x].color1); - target[x].color2 = bswap16(in[x].color2); - for (size_t i = 0; i < 4; ++i) { - std::array ind; - const uint8_t packed = in[x].lines[i]; - ind[3] = packed & 0x3; - ind[2] = (packed >> 2) & 0x3; - ind[1] = (packed >> 4) & 0x3; - ind[0] = (packed >> 6) & 0x3; - target[x].lines[i] = ind[0] | (ind[1] << 2) | (ind[2] << 4) | (ind[3] << 6); - } - } - in += 2; - } - } - } - targetMip += w * h; - - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - } - - return buf; -} - -ByteBuffer BuildRGBA8FromCMPR(u32 width, u32 height, u32 mips, ArrayRef data) { - const size_t texelCount = ComputeMippedTexelCount(width, height, mips); - const size_t blockCount = ComputeMippedBlockCountDXT1(width, height, mips); - ByteBuffer buf{sizeof(RGBA8) * texelCount}; - - u32 h = height; - u32 w = width; - u8* dst = buf.data(); - const u8* src = data.data(); - for (u32 mip = 0; mip < mips; ++mip) { - for (u32 yy = 0; yy < h; yy += 8) { - for (u32 xx = 0; xx < w; xx += 8) { - for (u32 yb = 0; yb < 8; yb += 4) { - for (u32 xb = 0; xb < 8; xb += 4) { - // CMPR difference: Big-endian color1/2 - const u16 color1 = bswap16(*reinterpret_cast(src)); - const u16 color2 = bswap16(*reinterpret_cast(src + 2)); - src += 4; - - // Fill in first two colors in color table. - std::array color_table{}; - - color_table[0] = ExpandTo8<5>(static_cast((color1 >> 11) & 0x1F)); - color_table[1] = ExpandTo8<6>(static_cast((color1 >> 5) & 0x3F)); - color_table[2] = ExpandTo8<5>(static_cast(color1 & 0x1F)); - color_table[3] = 0xFF; - - color_table[4] = ExpandTo8<5>(static_cast((color2 >> 11) & 0x1F)); - color_table[5] = ExpandTo8<6>(static_cast((color2 >> 5) & 0x3F)); - color_table[6] = ExpandTo8<5>(static_cast(color2 & 0x1F)); - color_table[7] = 0xFF; - if (color1 > color2) { - // Predict gradients. - color_table[8] = S3TCBlend(color_table[4], color_table[0]); - color_table[9] = S3TCBlend(color_table[5], color_table[1]); - color_table[10] = S3TCBlend(color_table[6], color_table[2]); - color_table[11] = 0xFF; - - color_table[12] = S3TCBlend(color_table[0], color_table[4]); - color_table[13] = S3TCBlend(color_table[1], color_table[5]); - color_table[14] = S3TCBlend(color_table[2], color_table[6]); - color_table[15] = 0xFF; - } else { - color_table[8] = HalfBlend(color_table[0], color_table[4]); - color_table[9] = HalfBlend(color_table[1], color_table[5]); - color_table[10] = HalfBlend(color_table[2], color_table[6]); - color_table[11] = 0xFF; - - // CMPR difference: GX fills with an alpha 0 midway point here. - color_table[12] = color_table[8]; - color_table[13] = color_table[9]; - color_table[14] = color_table[10]; - color_table[15] = 0; - } - - for (u32 y = 0; y < 4; ++y) { - u8 bits = src[y]; - for (u32 x = 0; x < 4; ++x) { - if (xx + xb + x >= w || yy + yb + y >= h) { - continue; - } - u8* dstOffs = dst + ((yy + yb + y) * w + (xx + xb + x)) * 4; - const u8* colorTableOffs = &color_table[static_cast((bits >> 6) & 3) * 4]; - memcpy(dstOffs, colorTableOffs, 4); - bits <<= 2; - } - } - src += 4; - } - } - } - } - dst += w * h * 4; - if (w > 1) { - w /= 2; - } - if (h > 1) { - h /= 2; - } - } - - return buf; -} - -ByteBuffer convert_texture(GX::TextureFormat format, uint32_t width, uint32_t height, uint32_t mips, - ArrayRef data) { - switch (format) { - default: - Log.report(logvisor::Fatal, FMT_STRING("convert_texture: unknown format supplied {}"), format); - unreachable(); - case GX::TF_I4: - return BuildI4FromGCN(width, height, mips, data); - case GX::TF_I8: - return BuildI8FromGCN(width, height, mips, data); - case GX::TF_IA4: - return BuildIA4FromGCN(width, height, mips, data); - case GX::TF_IA8: - return BuildIA8FromGCN(width, height, mips, data); - case GX::TF_C4: - return BuildC4FromGCN(width, height, mips, data); - case GX::TF_C8: - return BuildC8FromGCN(width, height, mips, data); - case GX::TF_C14X2: - Log.report(logvisor::Fatal, FMT_STRING("convert_texture: C14X2 unimplemented")); - unreachable(); - case GX::TF_RGB565: - return BuildRGB565FromGCN(width, height, mips, data); - case GX::TF_RGB5A3: - return BuildRGB5A3FromGCN(width, height, mips, data); - case GX::TF_RGBA8: - return BuildRGBA8FromGCN(width, height, mips, data); - case GX::TF_CMPR: - if (gpu::g_device.HasFeature(wgpu::FeatureName::TextureCompressionBC)) { - return BuildDXT1FromGCN(width, height, mips, data); - } else { - return BuildRGBA8FromCMPR(width, height, mips, data); - } - } -} -} // namespace aurora::gfx diff --git a/aurora/lib/gfx/texture_convert.hpp b/aurora/lib/gfx/texture_convert.hpp deleted file mode 100644 index 54f49270f..000000000 --- a/aurora/lib/gfx/texture_convert.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "common.hpp" - -#include "../gpu.hpp" - -namespace aurora::gfx { -static wgpu::TextureFormat to_wgpu(GX::TextureFormat format) { - switch (format) { - case GX::TF_I4: - case GX::TF_I8: - return wgpu::TextureFormat::R8Unorm; - case GX::TF_C4: - case GX::TF_C8: - case GX::TF_C14X2: - return wgpu::TextureFormat::R16Sint; - case GX::TF_CMPR: - if (gpu::g_device.HasFeature(wgpu::FeatureName::TextureCompressionBC)) { - return wgpu::TextureFormat::BC1RGBAUnorm; - } - [[fallthrough]]; - default: - return wgpu::TextureFormat::RGBA8Unorm; - } -} - -ByteBuffer convert_texture(GX::TextureFormat format, uint32_t width, uint32_t height, uint32_t mips, - ArrayRef data); -} // namespace aurora::gfx diff --git a/aurora/lib/gpu.cpp b/aurora/lib/gpu.cpp deleted file mode 100644 index 62a931c66..000000000 --- a/aurora/lib/gpu.cpp +++ /dev/null @@ -1,407 +0,0 @@ -#include "gpu.hpp" - -#include - -#include -#include -#include -#include -#include -#include - -#include "dawn/BackendBinding.hpp" - -// FIXME hack to avoid crash on Windows -namespace aurora { -extern WindowSize g_windowSize; -} // namespace aurora - -namespace aurora::gpu { -static logvisor::Module Log("aurora::gpu"); - -wgpu::Device g_device; -wgpu::Queue g_queue; -wgpu::SwapChain g_swapChain; -wgpu::BackendType g_backendType; -GraphicsConfig g_graphicsConfig; -TextureWithSampler g_frameBuffer; -TextureWithSampler g_frameBufferResolved; -TextureWithSampler g_depthBuffer; - -// EFB -> XFB copy pipeline -static wgpu::BindGroupLayout g_CopyBindGroupLayout; -wgpu::RenderPipeline g_CopyPipeline; -wgpu::BindGroup g_CopyBindGroup; - -static std::unique_ptr g_Instance; -static dawn::native::Adapter g_Adapter; -static wgpu::AdapterProperties g_AdapterProperties; -static std::unique_ptr g_BackendBinding; - -TextureWithSampler create_render_texture(bool multisampled) { - const auto size = wgpu::Extent3D{ - .width = g_graphicsConfig.width, - .height = g_graphicsConfig.height, - }; - const auto format = g_graphicsConfig.colorFormat; - uint32_t sampleCount = 1; - if (multisampled) { - sampleCount = g_graphicsConfig.msaaSamples; - } - const auto textureDescriptor = wgpu::TextureDescriptor{ - .label = "Render texture", - .usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc | - wgpu::TextureUsage::CopyDst, - .size = size, - .format = format, - .sampleCount = sampleCount, - }; - auto texture = g_device.CreateTexture(&textureDescriptor); - - const auto viewDescriptor = wgpu::TextureViewDescriptor{}; - auto view = texture.CreateView(&viewDescriptor); - - const auto samplerDescriptor = wgpu::SamplerDescriptor{ - .label = "Render sampler", - .magFilter = wgpu::FilterMode::Linear, - .minFilter = wgpu::FilterMode::Linear, - .mipmapFilter = wgpu::FilterMode::Linear, - }; - auto sampler = g_device.CreateSampler(&samplerDescriptor); - - return { - .texture = std::move(texture), - .view = std::move(view), - .size = size, - .format = format, - .sampler = std::move(sampler), - }; -} - -static TextureWithSampler create_depth_texture() { - const auto size = wgpu::Extent3D{ - .width = g_graphicsConfig.width, - .height = g_graphicsConfig.height, - }; - const auto format = g_graphicsConfig.depthFormat; - const auto textureDescriptor = wgpu::TextureDescriptor{ - .label = "Depth texture", - .usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding, - .size = size, - .format = format, - .sampleCount = g_graphicsConfig.msaaSamples, - }; - auto texture = g_device.CreateTexture(&textureDescriptor); - - const auto viewDescriptor = wgpu::TextureViewDescriptor{}; - auto view = texture.CreateView(&viewDescriptor); - - const auto samplerDescriptor = wgpu::SamplerDescriptor{ - .label = "Depth sampler", - .magFilter = wgpu::FilterMode::Linear, - .minFilter = wgpu::FilterMode::Linear, - .mipmapFilter = wgpu::FilterMode::Linear, - }; - auto sampler = g_device.CreateSampler(&samplerDescriptor); - - return { - .texture = std::move(texture), - .view = std::move(view), - .size = size, - .format = format, - .sampler = std::move(sampler), - }; -} - -void create_copy_pipeline() { - wgpu::ShaderModuleWGSLDescriptor sourceDescriptor{}; - sourceDescriptor.source = R"""( -@group(0) @binding(0) -var efb_sampler: sampler; -@group(0) @binding(1) -var efb_texture: texture_2d; - -struct VertexOutput { - @builtin(position) pos: vec4, - @location(0) uv: vec2, -}; - -var pos: array, 3> = array, 3>( - vec2(-1.0, 1.0), - vec2(-1.0, -3.0), - vec2(3.0, 1.0), -); -var uvs: array, 3> = array, 3>( - vec2(0.0, 0.0), - vec2(0.0, 2.0), - vec2(2.0, 0.0), -); - -@stage(vertex) -fn vs_main(@builtin(vertex_index) vtxIdx: u32) -> VertexOutput { - var out: VertexOutput; - out.pos = vec4(pos[vtxIdx], 0.0, 1.0); - out.uv = uvs[vtxIdx]; - return out; -} - -@stage(fragment) -fn fs_main(in: VertexOutput) -> @location(0) vec4 { - return textureSample(efb_texture, efb_sampler, in.uv); -} -)"""; - const wgpu::ShaderModuleDescriptor moduleDescriptor{ - .nextInChain = &sourceDescriptor, - .label = "XFB Copy Module", - }; - auto module = g_device.CreateShaderModule(&moduleDescriptor); - const std::array colorTargets{ - wgpu::ColorTargetState{ - .format = g_graphicsConfig.colorFormat, - }, - }; - const wgpu::FragmentState fragmentState{ - .module = module, - .entryPoint = "fs_main", - .targetCount = colorTargets.size(), - .targets = colorTargets.data(), - }; - const std::array bindGroupLayoutEntries{ - wgpu::BindGroupLayoutEntry{ - .binding = 0, - .visibility = wgpu::ShaderStage::Fragment, - .sampler = - wgpu::SamplerBindingLayout{ - .type = wgpu::SamplerBindingType::Filtering, - }, - }, - wgpu::BindGroupLayoutEntry{ - .binding = 1, - .visibility = wgpu::ShaderStage::Fragment, - .texture = - wgpu::TextureBindingLayout{ - .sampleType = wgpu::TextureSampleType::Float, - .viewDimension = wgpu::TextureViewDimension::e2D, - }, - }, - }; - const wgpu::BindGroupLayoutDescriptor bindGroupLayoutDescriptor{ - .entryCount = bindGroupLayoutEntries.size(), - .entries = bindGroupLayoutEntries.data(), - }; - g_CopyBindGroupLayout = g_device.CreateBindGroupLayout(&bindGroupLayoutDescriptor); - const wgpu::PipelineLayoutDescriptor layoutDescriptor{ - .bindGroupLayoutCount = 1, - .bindGroupLayouts = &g_CopyBindGroupLayout, - }; - auto pipelineLayout = g_device.CreatePipelineLayout(&layoutDescriptor); - const wgpu::RenderPipelineDescriptor pipelineDescriptor{ - .layout = pipelineLayout, - .vertex = - wgpu::VertexState{ - .module = module, - .entryPoint = "vs_main", - }, - .fragment = &fragmentState, - }; - g_CopyPipeline = g_device.CreateRenderPipeline(&pipelineDescriptor); -} - -void create_copy_bind_group() { - const std::array bindGroupEntries{ - wgpu::BindGroupEntry{ - .binding = 0, - .sampler = g_graphicsConfig.msaaSamples > 1 ? gpu::g_frameBufferResolved.sampler : gpu::g_frameBuffer.sampler, - }, - wgpu::BindGroupEntry{ - .binding = 1, - .textureView = g_graphicsConfig.msaaSamples > 1 ? gpu::g_frameBufferResolved.view : gpu::g_frameBuffer.view, - }, - }; - const wgpu::BindGroupDescriptor bindGroupDescriptor{ - .layout = g_CopyBindGroupLayout, - .entryCount = bindGroupEntries.size(), - .entries = bindGroupEntries.data(), - }; - g_CopyBindGroup = g_device.CreateBindGroup(&bindGroupDescriptor); -} - -static void error_callback(WGPUErrorType type, char const* message, void* userdata) { - Log.report(logvisor::Fatal, FMT_STRING("Dawn error {}: {}"), - magic_enum::enum_name(static_cast(type)), message); -} - -static void device_callback(WGPURequestDeviceStatus status, WGPUDevice device, char const* message, void* userdata) { - if (status == WGPURequestDeviceStatus_Success) { - g_device = wgpu::Device::Acquire(device); - } else { - Log.report(logvisor::Warning, FMT_STRING("Device request failed with message: {}"), message); - } - *static_cast(userdata) = true; -} - -bool initialize(SDL_Window* window, wgpu::BackendType backendType, uint32_t msaa, uint16_t aniso) { - if (!g_Instance) { - Log.report(logvisor::Info, FMT_STRING("Creating Dawn instance")); - g_Instance = std::make_unique(); - } - Log.report(logvisor::Info, FMT_STRING("Attempting to initialize {}"), magic_enum::enum_name(backendType)); -#if 0 - // D3D12's debug layer is very slow - g_Instance->EnableBackendValidation(backendType != wgpu::BackendType::D3D12); -#endif - if (!utils::DiscoverAdapter(g_Instance.get(), window, backendType)) { - return false; - } - - { - std::vector adapters = g_Instance->GetAdapters(); - std::sort(adapters.begin(), adapters.end(), [&](const auto& a, const auto& b) { - wgpu::AdapterProperties propertiesA; - wgpu::AdapterProperties propertiesB; - a.GetProperties(&propertiesA); - b.GetProperties(&propertiesB); - constexpr std::array PreferredTypeOrder{ - wgpu::AdapterType::DiscreteGPU, - wgpu::AdapterType::IntegratedGPU, - wgpu::AdapterType::CPU, - }; - const auto typeItA = std::find(PreferredTypeOrder.begin(), PreferredTypeOrder.end(), propertiesA.adapterType); - const auto typeItB = std::find(PreferredTypeOrder.begin(), PreferredTypeOrder.end(), propertiesB.adapterType); - return typeItA < typeItB; - }); - const auto adapterIt = std::find_if(adapters.begin(), adapters.end(), [=](const auto& adapter) -> bool { - wgpu::AdapterProperties properties; - adapter.GetProperties(&properties); - return properties.backendType == backendType; - }); - if (adapterIt == adapters.end()) { - return false; - } - g_Adapter = *adapterIt; - } - g_Adapter.GetProperties(&g_AdapterProperties); - g_backendType = g_AdapterProperties.backendType; - const auto backendName = magic_enum::enum_name(g_backendType); - Log.report(logvisor::Info, FMT_STRING("Graphics adapter information\n API: {}\n Device: {} ({})\n Driver: {}"), - backendName, g_AdapterProperties.name, magic_enum::enum_name(g_AdapterProperties.adapterType), - g_AdapterProperties.driverDescription); - - { - WGPUSupportedLimits supportedLimits{}; - g_Adapter.GetLimits(&supportedLimits); - const wgpu::RequiredLimits requiredLimits{ - .limits = - { - // Use "best" supported alignments - .minUniformBufferOffsetAlignment = supportedLimits.limits.minUniformBufferOffsetAlignment == 0 - ? static_cast(WGPU_LIMIT_U32_UNDEFINED) - : supportedLimits.limits.minUniformBufferOffsetAlignment, - .minStorageBufferOffsetAlignment = supportedLimits.limits.minStorageBufferOffsetAlignment == 0 - ? static_cast(WGPU_LIMIT_U32_UNDEFINED) - : supportedLimits.limits.minStorageBufferOffsetAlignment, - }, - }; - std::vector features; - const auto supportedFeatures = g_Adapter.GetSupportedFeatures(); - for (const auto* const feature : supportedFeatures) { - if (strcmp(feature, "texture-compression-bc") == 0) { - features.push_back(wgpu::FeatureName::TextureCompressionBC); - } - } - const std::array enableToggles { - /* clang-format off */ -#if _WIN32 - "use_dxc", -#endif -#ifdef NDEBUG - "skip_validation", - "disable_robustness", -#endif - "use_user_defined_labels_in_backend", - "disable_symbol_renaming", - /* clang-format on */ - }; - wgpu::DawnTogglesDeviceDescriptor togglesDescriptor{}; - togglesDescriptor.forceEnabledTogglesCount = enableToggles.size(); - togglesDescriptor.forceEnabledToggles = enableToggles.data(); - const auto deviceDescriptor = wgpu::DeviceDescriptor{ - .nextInChain = &togglesDescriptor, - .requiredFeaturesCount = static_cast(features.size()), - .requiredFeatures = features.data(), - .requiredLimits = &requiredLimits, - }; - bool deviceCallbackReceived = false; - g_Adapter.RequestDevice(&deviceDescriptor, &device_callback, &deviceCallbackReceived); - // while (!deviceCallbackReceived) { - // TODO wgpuInstanceProcessEvents - // } - if (!g_device) { - return false; - } - g_device.SetUncapturedErrorCallback(&error_callback, nullptr); - } - g_device.SetDeviceLostCallback(nullptr, nullptr); - g_queue = g_device.GetQueue(); - - g_BackendBinding = - std::unique_ptr(utils::CreateBinding(g_backendType, window, g_device.Get())); - if (!g_BackendBinding) { - return false; - } - - auto swapChainFormat = static_cast(g_BackendBinding->GetPreferredSwapChainTextureFormat()); - if (swapChainFormat == wgpu::TextureFormat::RGBA8UnormSrgb) { - swapChainFormat = wgpu::TextureFormat::RGBA8Unorm; - } else if (swapChainFormat == wgpu::TextureFormat::BGRA8UnormSrgb) { - swapChainFormat = wgpu::TextureFormat::BGRA8Unorm; - } - Log.report(logvisor::Info, FMT_STRING("Using swapchain format {}"), magic_enum::enum_name(swapChainFormat)); - { - const auto descriptor = wgpu::SwapChainDescriptor{ - .format = swapChainFormat, - .implementation = g_BackendBinding->GetSwapChainImplementation(), - }; - g_swapChain = g_device.CreateSwapChain(nullptr, &descriptor); - } - { - const auto size = get_window_size(); - g_graphicsConfig = GraphicsConfig{ - .width = size.fb_width, - .height = size.fb_height, - .colorFormat = swapChainFormat, - .depthFormat = wgpu::TextureFormat::Depth32Float, - .msaaSamples = msaa, - .textureAnisotropy = aniso, - }; - create_copy_pipeline(); - resize_swapchain(size.fb_width, size.fb_height); - g_windowSize = size; - } - return true; -} - -void shutdown() { - g_CopyBindGroupLayout = {}; - g_CopyPipeline = {}; - g_CopyBindGroup = {}; - g_frameBuffer = {}; - g_frameBufferResolved = {}; - g_depthBuffer = {}; - wgpuSwapChainRelease(g_swapChain.Release()); - wgpuQueueRelease(g_queue.Release()); - g_BackendBinding.reset(); - wgpuDeviceRelease(g_device.Release()); - g_Instance.reset(); -} - -void resize_swapchain(uint32_t width, uint32_t height) { - g_graphicsConfig.width = width; - g_graphicsConfig.height = height; - g_swapChain.Configure(g_graphicsConfig.colorFormat, wgpu::TextureUsage::RenderAttachment, width, height); - g_frameBuffer = create_render_texture(true); - g_frameBufferResolved = create_render_texture(false); - g_depthBuffer = create_depth_texture(); - create_copy_bind_group(); -} -} // namespace aurora::gpu diff --git a/aurora/lib/gpu.hpp b/aurora/lib/gpu.hpp deleted file mode 100644 index c26853884..000000000 --- a/aurora/lib/gpu.hpp +++ /dev/null @@ -1,156 +0,0 @@ -#pragma once - -#include -#include -#include - -#ifdef __GNUC__ -[[noreturn]] inline __attribute__((always_inline)) void unreachable() { __builtin_unreachable(); } -#elif defined(_MSC_VER) -[[noreturn]] __forceinline void unreachable() { __assume(false); } -#else -#error Unknown compiler -#endif - -struct SDL_Window; - -namespace aurora::gpu { -struct GraphicsConfig { - uint32_t width; - uint32_t height; - wgpu::TextureFormat colorFormat; - wgpu::TextureFormat depthFormat; - uint32_t msaaSamples; - uint16_t textureAnisotropy; -}; -struct TextureWithSampler { - wgpu::Texture texture; - wgpu::TextureView view; - wgpu::Extent3D size; - wgpu::TextureFormat format; - wgpu::Sampler sampler; -}; - -constexpr std::array PreferredBackendOrder{ -#ifdef DAWN_ENABLE_BACKEND_D3D12 - wgpu::BackendType::D3D12, -#endif -#ifdef DAWN_ENABLE_BACKEND_METAL - wgpu::BackendType::Metal, -#endif -#ifdef DAWN_ENABLE_BACKEND_VULKAN - wgpu::BackendType::Vulkan, -#endif -#ifdef DAWN_ENABLE_BACKEND_DESKTOP_GL - wgpu::BackendType::OpenGL, -#endif -#ifdef DAWN_ENABLE_BACKEND_OPENGLES - wgpu::BackendType::OpenGLES, -#endif -#ifdef DAWN_ENABLE_BACKEND_NULL - wgpu::BackendType::Null, -#endif -}; - -extern wgpu::Device g_device; -extern wgpu::Queue g_queue; -extern wgpu::SwapChain g_swapChain; -extern wgpu::BackendType g_backendType; -extern GraphicsConfig g_graphicsConfig; -extern TextureWithSampler g_frameBuffer; -extern TextureWithSampler g_frameBufferResolved; -extern TextureWithSampler g_depthBuffer; -extern wgpu::RenderPipeline g_CopyPipeline; -extern wgpu::BindGroup g_CopyBindGroup; - -bool initialize(SDL_Window* window, wgpu::BackendType backendType, uint32_t msaa, uint16_t aniso); -void shutdown(); -void resize_swapchain(uint32_t width, uint32_t height); -TextureWithSampler create_render_texture(bool multisampled); -} // namespace aurora::gpu - -namespace aurora::gpu::utils { -template -static std::array -make_vertex_attributes(std::array formats) { - std::array attributes; - uint64_t offset = 0; - for (uint32_t i = 0; i < N; ++i) { - auto format = formats[i]; - attributes[i] = wgpu::VertexAttribute{ - .format = format, - .offset = offset, - .shaderLocation = i, - }; - switch (format) { - case wgpu::VertexFormat::Uint8x2: - case wgpu::VertexFormat::Sint8x2: - case wgpu::VertexFormat::Unorm8x2: - case wgpu::VertexFormat::Snorm8x2: - offset += 2; - break; - case wgpu::VertexFormat::Uint8x4: - case wgpu::VertexFormat::Sint8x4: - case wgpu::VertexFormat::Unorm8x4: - case wgpu::VertexFormat::Snorm8x4: - case wgpu::VertexFormat::Uint16x2: - case wgpu::VertexFormat::Sint16x2: - case wgpu::VertexFormat::Unorm16x2: - case wgpu::VertexFormat::Snorm16x2: - case wgpu::VertexFormat::Float16x2: - case wgpu::VertexFormat::Float32: - case wgpu::VertexFormat::Uint32: - case wgpu::VertexFormat::Sint32: - offset += 4; - break; - case wgpu::VertexFormat::Uint16x4: - case wgpu::VertexFormat::Sint16x4: - case wgpu::VertexFormat::Unorm16x4: - case wgpu::VertexFormat::Snorm16x4: - case wgpu::VertexFormat::Float16x4: - case wgpu::VertexFormat::Float32x2: - case wgpu::VertexFormat::Uint32x2: - case wgpu::VertexFormat::Sint32x2: - offset += 8; - break; - case wgpu::VertexFormat::Float32x3: - case wgpu::VertexFormat::Uint32x3: - case wgpu::VertexFormat::Sint32x3: - offset += 12; - break; - case wgpu::VertexFormat::Float32x4: - case wgpu::VertexFormat::Uint32x4: - case wgpu::VertexFormat::Sint32x4: - offset += 16; - break; - case wgpu::VertexFormat::Undefined: - break; - } - } - return attributes; -} - -template -static inline wgpu::VertexBufferLayout -make_vertex_buffer_layout(uint64_t arrayStride, const std::array& attributes, - wgpu::VertexStepMode stepMode = wgpu::VertexStepMode::Vertex) { - return { - .arrayStride = arrayStride, - .stepMode = stepMode, - .attributeCount = static_cast(attributes.size()), - .attributes = attributes.data(), - }; -} - -template -static inline wgpu::VertexState make_vertex_state(const wgpu::ShaderModule& module, - const std::array& buffers, - const char* entryPoint = "vs_main") { - return { - .module = module, - .entryPoint = entryPoint, - .bufferCount = static_cast(buffers.size()), - .buffers = buffers.data(), - }; -} -} // namespace aurora::gpu::utils diff --git a/aurora/lib/imgui.cpp b/aurora/lib/imgui.cpp deleted file mode 100644 index 24a35bc62..000000000 --- a/aurora/lib/imgui.cpp +++ /dev/null @@ -1,147 +0,0 @@ -#include "imgui.hpp" - -#include "gpu.hpp" - -#include "Runtime/ConsoleVariables/FileStoreManager.hpp" -#include -#include -#include -#include - -#include "../extern/imgui/backends/imgui_impl_sdl.cpp" -#include "../extern/imgui/backends/imgui_impl_sdlrenderer.cpp" -#include "../extern/imgui/backends/imgui_impl_wgpu.cpp" - -namespace aurora::imgui { -using gpu::g_device; -using gpu::g_queue; - -static float g_scale; - -static std::string g_imguiSettings{}; -static std::string g_imguiLog{}; -void create_context() noexcept { - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - g_imguiSettings = std::string(metaforce::FileStoreManager::instance()->getStoreRoot()) + "/imgui.ini"; - g_imguiLog = std::string(metaforce::FileStoreManager::instance()->getStoreRoot()) + "/imgui.log"; - io.IniFilename = g_imguiSettings.c_str(); - io.LogFilename = g_imguiLog.c_str(); -} - -static bool g_useSdlRenderer = false; -void initialize(SDL_Window* window, SDL_Renderer* renderer) noexcept { - ImGui_ImplSDL2_Init(window, renderer); -#ifdef __APPLE__ - // Disable MouseCanUseGlobalState for scaling purposes - ImGui_ImplSDL2_GetBackendData()->MouseCanUseGlobalState = false; -#endif - g_useSdlRenderer = renderer != nullptr; - if (g_useSdlRenderer) { - ImGui_ImplSDLRenderer_Init(renderer); - } else { - ImGui_ImplWGPU_Init(g_device.Get(), 1, static_cast(gpu::g_graphicsConfig.colorFormat)); - } -} - -void shutdown() noexcept { - if (g_useSdlRenderer) { - ImGui_ImplSDLRenderer_Shutdown(); - } else { - ImGui_ImplWGPU_Shutdown(); - } - ImGui_ImplSDL2_Shutdown(); - ImGui::DestroyContext(); -} - -void process_event(const SDL_Event& event) noexcept { -#ifdef __APPLE__ - if (event.type == SDL_MOUSEMOTION) { - auto& io = ImGui::GetIO(); - // Scale up mouse coordinates - io.AddMousePosEvent(static_cast(event.motion.x) * g_scale, static_cast(event.motion.y) * g_scale); - return; - } -#endif - ImGui_ImplSDL2_ProcessEvent(&event); -} - -void new_frame(const WindowSize& size) noexcept { - if (g_useSdlRenderer) { - ImGui_ImplSDLRenderer_NewFrame(); - } else { - if (g_scale != size.scale) { - if (g_scale > 0.f) { - // TODO wgpu backend bug: doesn't clear bind groups on invalidate - g_resources.ImageBindGroups.Clear(); - ImGui_ImplWGPU_CreateDeviceObjects(); - } - g_scale = size.scale; - } - ImGui_ImplWGPU_NewFrame(); - } - ImGui_ImplSDL2_NewFrame(); - - // Render at full DPI - ImGui::GetIO().DisplaySize = {static_cast(size.fb_width), static_cast(size.fb_height)}; - ImGui::NewFrame(); -} - -void render(const wgpu::RenderPassEncoder& pass) noexcept { - ImGui::Render(); - - auto* data = ImGui::GetDrawData(); - // io.DisplayFramebufferScale is informational; we're rendering at full DPI - data->FramebufferScale = {1.f, 1.f}; - if (g_useSdlRenderer) { - SDL_Renderer* renderer = ImGui_ImplSDLRenderer_GetBackendData()->SDLRenderer; - SDL_RenderClear(renderer); - ImGui_ImplSDLRenderer_RenderDrawData(data); - SDL_RenderPresent(renderer); - } else { - ImGui_ImplWGPU_RenderDrawData(data, pass.Get()); - } -} - -ImTextureID add_texture(uint32_t width, uint32_t height, ArrayRef data) noexcept { - if (g_useSdlRenderer) { - SDL_Renderer* renderer = ImGui_ImplSDLRenderer_GetBackendData()->SDLRenderer; - SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, width, height); - SDL_UpdateTexture(texture, nullptr, data.data(), width * 4); - SDL_SetTextureScaleMode(texture, SDL_ScaleModeLinear); - return texture; - } - const auto size = wgpu::Extent3D{ - .width = width, - .height = height, - }; - const auto textureDescriptor = wgpu::TextureDescriptor{ - .label = "imgui texture", - .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst, - .size = size, - .format = wgpu::TextureFormat::RGBA8Unorm, - }; - const auto textureViewDescriptor = wgpu::TextureViewDescriptor{ - .label = "imgui texture view", - .format = wgpu::TextureFormat::RGBA8Unorm, - .dimension = wgpu::TextureViewDimension::e2D, - .mipLevelCount = 1, - .arrayLayerCount = 1, - }; - auto texture = g_device.CreateTexture(&textureDescriptor); - auto textureView = texture.CreateView(&textureViewDescriptor); - { - const auto dstView = wgpu::ImageCopyTexture{ - .texture = texture, - }; - const auto dataLayout = wgpu::TextureDataLayout{ - .bytesPerRow = 4 * width, - .rowsPerImage = height, - }; - g_queue.WriteTexture(&dstView, data.data(), data.size(), &dataLayout, &size); - } - texture.Release(); // leak some memory! - return textureView.Release(); -} -} // namespace aurora::imgui diff --git a/aurora/lib/imgui.hpp b/aurora/lib/imgui.hpp deleted file mode 100644 index dba424277..000000000 --- a/aurora/lib/imgui.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -struct SDL_Renderer; -struct SDL_Window; -union SDL_Event; - -namespace wgpu { -class RenderPassEncoder; -} // namespace wgpu - -namespace aurora { -struct WindowSize; -} // namespace aurora - -namespace aurora::imgui { -void create_context() noexcept; -void initialize(SDL_Window* window, SDL_Renderer* renderer) noexcept; -void shutdown() noexcept; - -void process_event(const SDL_Event& event) noexcept; -void new_frame(const WindowSize& size) noexcept; -void render(const wgpu::RenderPassEncoder& pass) noexcept; -} // namespace aurora::imgui diff --git a/aurora/lib/input.cpp b/aurora/lib/input.cpp deleted file mode 100644 index 527e8da0e..000000000 --- a/aurora/lib/input.cpp +++ /dev/null @@ -1,977 +0,0 @@ -#include "input.hpp" -#include "aurora/pad.hpp" -#include "Runtime/ConsoleVariables/FileStoreManager.hpp" - -#include "magic_enum.hpp" - -#include -#include - -#include -#include -#include -#include - -namespace aurora::input { -static logvisor::Module Log("aurora::input"); - -struct GameController { - SDL_GameController* m_controller = nullptr; - bool m_isGameCube = false; - Sint32 m_index = -1; - bool m_hasRumble = false; - PADDeadZones m_deadZones; - u16 m_vid = 0; - u16 m_pid = 0; - std::array m_mapping{}; - bool m_mappingLoaded = false; - constexpr bool operator==(const GameController& other) const { - return m_controller == other.m_controller && m_index == other.m_index; - } -}; -absl::flat_hash_map g_GameControllers; - -GameController* get_controller_for_player(u32 player) noexcept { - for (auto& [which, controller] : g_GameControllers) { - if (player_index(which) == player) { - return &controller; - } - } - -#if 0 - /* If we don't have a controller assigned to this port use the first unassigned controller */ - if (!g_GameControllers.empty()) { - int32_t availIndex = -1; - GameController* ct = nullptr; - for (auto& controller : g_GameControllers) { - if (player_index(controller.first) == -1) { - availIndex = controller.first; - ct = &controller.second; - break; - } - } - if (availIndex != -1) { - set_player_index(availIndex, player); - return ct; - } - } -#endif - return nullptr; -} - -Sint32 get_instance_for_player(u32 player) noexcept { - for (const auto& [which, controller] : g_GameControllers) { - if (player_index(which) == player) { - return which; - } - } - - return {}; -} - -static std::optional remap_controller_layout(std::string_view mapping) { - std::string newMapping; - newMapping.reserve(mapping.size()); - absl::btree_map entries; - for (size_t idx = 0; const auto value : absl::StrSplit(mapping, ',')) { - if (idx < 2) { - if (idx > 0) { - newMapping.push_back(','); - } - newMapping.append(value); - } else { - const auto split = absl::StrSplit(value, absl::MaxSplits(':', 2)); - auto iter = split.begin(); - entries.emplace(*iter++, *iter); - } - idx++; - } - if (entries.contains("rightshoulder"sv) && !entries.contains("leftshoulder"sv)) { - Log.report(logvisor::Info, FMT_STRING("Remapping GameCube controller layout")); - entries.insert_or_assign("back"sv, entries["rightshoulder"sv]); - // TODO trigger buttons may differ per platform - entries.insert_or_assign("leftshoulder"sv, "b11"sv); - entries.insert_or_assign("rightshoulder"sv, "b10"sv); - } else if (entries.contains("leftshoulder"sv) && entries.contains("rightshoulder"sv) && entries.contains("back"sv)) { - Log.report(logvisor::Info, FMT_STRING("Controller has standard layout")); - auto a = entries["a"sv]; - entries.insert_or_assign("a"sv, entries["b"sv]); - entries.insert_or_assign("b"sv, a); - auto x = entries["x"sv]; - entries.insert_or_assign("x"sv, entries["y"sv]); - entries.insert_or_assign("y"sv, x); - } else { - Log.report(logvisor::Error, FMT_STRING("Controller has unsupported layout: {}"), mapping); - return {}; - } - for (auto [k, v] : entries) { - newMapping.push_back(','); - newMapping.append(k); - newMapping.push_back(':'); - newMapping.append(v); - } - return newMapping; -} - -Sint32 add_controller(Sint32 which) noexcept { - auto* ctrl = SDL_GameControllerOpen(which); - if (ctrl != nullptr) { - { - char* mapping = SDL_GameControllerMapping(ctrl); - if (mapping != nullptr) { - auto newMapping = remap_controller_layout(mapping); - SDL_free(mapping); - if (newMapping) { - if (SDL_GameControllerAddMapping(newMapping->c_str()) == -1) { - Log.report(logvisor::Error, FMT_STRING("Failed to update controller mapping: {}"), SDL_GetError()); - } - } - } else { - Log.report(logvisor::Error, FMT_STRING("Failed to retrieve mapping for controller")); - } - } - GameController controller; - controller.m_controller = ctrl; - controller.m_index = which; - controller.m_vid = SDL_GameControllerGetVendor(ctrl); - controller.m_pid = SDL_GameControllerGetProduct(ctrl); - if (controller.m_vid == 0x05ac /* USB_VENDOR_APPLE */ && controller.m_pid == 3) { - // Ignore Apple TV remote - SDL_GameControllerClose(ctrl); - return -1; - } - controller.m_isGameCube = controller.m_vid == 0x057E && controller.m_pid == 0x0337; -#if SDL_VERSION_ATLEAST(2, 0, 18) - controller.m_hasRumble = (SDL_GameControllerHasRumble(ctrl) != 0u); -#else - controller.m_hasRumble = true; -#endif - Sint32 instance = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ctrl)); - g_GameControllers[instance] = controller; - return instance; - } - - return -1; -} - -void remove_controller(Uint32 instance) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - SDL_GameControllerClose(g_GameControllers[instance].m_controller); - g_GameControllers.erase(instance); - } -} - -bool is_gamecube(Uint32 instance) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - return g_GameControllers[instance].m_isGameCube; - } - return false; -} - -int32_t player_index(Uint32 instance) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - return SDL_GameControllerGetPlayerIndex(g_GameControllers[instance].m_controller); - } - return -1; -} - -void set_player_index(Uint32 instance, Sint32 index) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - SDL_GameControllerSetPlayerIndex(g_GameControllers[instance].m_controller, index); - } -} - -std::string controller_name(Uint32 instance) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - const auto* name = SDL_GameControllerName(g_GameControllers[instance].m_controller); - if (name != nullptr) { - return {name}; - } - } - return {}; -} - -bool controller_has_rumble(Uint32 instance) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - return g_GameControllers[instance].m_hasRumble; - } - - return false; -} - -void controller_rumble(uint32_t instance, uint16_t low_freq_intensity, uint16_t high_freq_intensity, - uint16_t duration_ms) noexcept { - - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - SDL_GameControllerRumble(g_GameControllers[instance].m_controller, low_freq_intensity, high_freq_intensity, - duration_ms); - } -} -ControllerButton translate_controller_button(SDL_GameControllerButton btn) noexcept { - switch (btn) { - case SDL_CONTROLLER_BUTTON_A: - return ControllerButton::A; - case SDL_CONTROLLER_BUTTON_B: - return ControllerButton::B; - case SDL_CONTROLLER_BUTTON_X: - return ControllerButton::X; - case SDL_CONTROLLER_BUTTON_Y: - return ControllerButton::Y; - case SDL_CONTROLLER_BUTTON_BACK: - return ControllerButton::Back; - case SDL_CONTROLLER_BUTTON_GUIDE: - return ControllerButton::Guide; - case SDL_CONTROLLER_BUTTON_START: - return ControllerButton::Start; - case SDL_CONTROLLER_BUTTON_LEFTSTICK: - return ControllerButton::LeftStick; - case SDL_CONTROLLER_BUTTON_RIGHTSTICK: - return ControllerButton::RightStick; - case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: - return ControllerButton::LeftShoulder; - case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: - return ControllerButton::RightShoulder; - case SDL_CONTROLLER_BUTTON_DPAD_UP: - return ControllerButton::DPadUp; - case SDL_CONTROLLER_BUTTON_DPAD_DOWN: - return ControllerButton::DPadDown; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - return ControllerButton::DPadRight; - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: - return ControllerButton::DPadLeft; - default: - return ControllerButton::Other; - } -} - -ControllerAxis translate_controller_axis(SDL_GameControllerAxis axis) noexcept { - switch (axis) { - case SDL_CONTROLLER_AXIS_LEFTX: - return ControllerAxis::LeftX; - case SDL_CONTROLLER_AXIS_LEFTY: - return ControllerAxis::LeftY; - case SDL_CONTROLLER_AXIS_RIGHTX: - return ControllerAxis::RightX; - case SDL_CONTROLLER_AXIS_RIGHTY: - return ControllerAxis::RightY; - case SDL_CONTROLLER_AXIS_TRIGGERLEFT: - return ControllerAxis::TriggerLeft; - case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: - return ControllerAxis::TriggerRight; - default: - return ControllerAxis::MAX; - } -} - -char translate_key(SDL_Keysym sym, SpecialKey& specialSym, ModifierKey& modifierSym) noexcept { - specialSym = SpecialKey::None; - modifierSym = ModifierKey::None; - if (sym.sym >= SDLK_F1 && sym.sym <= SDLK_F12) { - specialSym = SpecialKey(int(SpecialKey::F1) + sym.sym - SDLK_F1); - } else if (sym.sym == SDLK_ESCAPE) { - specialSym = SpecialKey::Esc; - } else if (sym.sym == SDLK_RETURN) { - specialSym = SpecialKey::Enter; - } else if (sym.sym == SDLK_KP_ENTER) { - specialSym = SpecialKey::KpEnter; - } else if (sym.sym == SDLK_BACKSPACE) { - specialSym = SpecialKey::Backspace; - } else if (sym.sym == SDLK_INSERT) { - specialSym = SpecialKey::Insert; - } else if (sym.sym == SDLK_DELETE) { - specialSym = SpecialKey::Delete; - } else if (sym.sym == SDLK_HOME) { - specialSym = SpecialKey::Home; - } else if (sym.sym == SDLK_END) { - specialSym = SpecialKey::End; - } else if (sym.sym == SDLK_PAGEUP) { - specialSym = SpecialKey::PgUp; - } else if (sym.sym == SDLK_PAGEDOWN) { - specialSym = SpecialKey::PgDown; - } else if (sym.sym == SDLK_LEFT) { - specialSym = SpecialKey::Left; - } else if (sym.sym == SDLK_RIGHT) { - specialSym = SpecialKey::Right; - } else if (sym.sym == SDLK_UP) { - specialSym = SpecialKey::Up; - } else if (sym.sym == SDLK_DOWN) { - specialSym = SpecialKey::Down; - } else if (sym.sym == SDLK_TAB) { - specialSym = SpecialKey::Tab; - } else if (sym.sym == SDLK_LSHIFT) { - modifierSym = ModifierKey::LeftShift; - } else if (sym.sym == SDLK_RSHIFT) { - modifierSym = ModifierKey::RightShift; - } else if (sym.sym == SDLK_LCTRL) { - modifierSym = ModifierKey::LeftControl; - } else if (sym.sym == SDLK_RCTRL) { - modifierSym = ModifierKey::RightControl; - } else if (sym.sym == SDLK_LALT) { - modifierSym = ModifierKey::LeftAlt; - } else if (sym.sym == SDLK_RALT) { - modifierSym = ModifierKey::RightAlt; - } else if (sym.sym >= ' ' && sym.sym <= 'z') { - return static_cast(sym.sym); - } - return 0; -} - -ModifierKey translate_modifiers(Uint16 mods) noexcept { - ModifierKey ret = ModifierKey::None; - if ((mods & SDLK_LSHIFT) != 0) { - ret |= ModifierKey::LeftShift; - } - if ((mods & SDLK_RSHIFT) != 0) { - ret |= ModifierKey::RightShift; - } - if ((mods & SDLK_LCTRL) != 0) { - ret |= ModifierKey::LeftControl; - } - if ((mods & SDLK_RCTRL) != 0) { - ret |= ModifierKey::RightControl; - } - if ((mods & SDLK_LALT) != 0) { - ret |= ModifierKey::LeftAlt; - } - if ((mods & SDLK_RALT) != 0) { - ret |= ModifierKey::RightAlt; - } - - return ret; -} - -MouseButton translate_mouse_button(Uint8 button) noexcept { - if (button == 1) { - return MouseButton::Primary; - } - if (button == 2) { - return MouseButton::Middle; - } - if (button == 3) { - return MouseButton::Secondary; - } - if (button == 4) { - return MouseButton::Aux1; - } - if (button == 5) { - return MouseButton::Aux2; - } - - return MouseButton::None; -} - -MouseButton translate_mouse_button_state(Uint8 state) noexcept { - auto ret = MouseButton::None; - if ((state & 0x01) != 0) { - ret |= MouseButton::Primary; - } - if ((state & 0x02) != 0) { - ret |= MouseButton::Middle; - } - if ((state & 0x04) != 0) { - ret |= MouseButton::Secondary; - } - if ((state & 0x08) != 0) { - ret |= MouseButton::Aux1; - } - if ((state & 0x10) != 0) { - ret |= MouseButton::Aux2; - } - - return ret; -} - -uint32_t controller_count() noexcept { return g_GameControllers.size(); } - -} // namespace aurora::input - -static const std::array mDefaultButtons{{ - {SDL_CONTROLLER_BUTTON_A, PAD::BUTTON_A}, - {SDL_CONTROLLER_BUTTON_B, PAD::BUTTON_B}, - {SDL_CONTROLLER_BUTTON_X, PAD::BUTTON_X}, - {SDL_CONTROLLER_BUTTON_Y, PAD::BUTTON_Y}, - {SDL_CONTROLLER_BUTTON_START, PAD::BUTTON_START}, - {SDL_CONTROLLER_BUTTON_BACK, PAD::TRIGGER_Z}, - {SDL_CONTROLLER_BUTTON_LEFTSHOULDER, PAD::TRIGGER_L}, - {SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, PAD::TRIGGER_R}, - {SDL_CONTROLLER_BUTTON_DPAD_UP, PAD::BUTTON_UP}, - {SDL_CONTROLLER_BUTTON_DPAD_DOWN, PAD::BUTTON_DOWN}, - {SDL_CONTROLLER_BUTTON_DPAD_LEFT, PAD::BUTTON_LEFT}, - {SDL_CONTROLLER_BUTTON_DPAD_RIGHT, PAD::BUTTON_RIGHT}, -}}; - -void PADSetSpec(s32 spec) {} -void PADInit() {} - -aurora::input::GameController* __PADGetControllerForIndex(u32 idx) { - if (idx >= aurora::input::g_GameControllers.size()) { - return nullptr; - } - - u32 tmp = 0; - auto iter = aurora::input::g_GameControllers.begin(); - while (tmp < idx) { - ++iter; - ++tmp; - } - if (iter == aurora::input::g_GameControllers.end()) { - return nullptr; - } - - return &iter->second; -} - -u32 PADCount() { return aurora::input::g_GameControllers.size(); } - -const char* PADGetNameForControllerIndex(u32 idx) { - auto* ctrl = __PADGetControllerForIndex(idx); - if (ctrl == nullptr) { - return nullptr; - } - - return SDL_GameControllerName(ctrl->m_controller); -} - -void PADSetPortForIndex(u32 idx, s32 port) { - auto* ctrl = __PADGetControllerForIndex(idx); - auto* dest = aurora::input::get_controller_for_player(port); - if (ctrl == nullptr) { - return; - } - if (dest != nullptr) { - SDL_GameControllerSetPlayerIndex(dest->m_controller, -1); - } - SDL_GameControllerSetPlayerIndex(ctrl->m_controller, port); -} - -s32 PADGetIndexForPort(u32 port) { - auto* ctrl = aurora::input::get_controller_for_player(port); - if (ctrl == nullptr) { - return -1; - } - s32 index = 0; - for (auto iter = aurora::input::g_GameControllers.begin(); iter != aurora::input::g_GameControllers.end(); - ++iter, ++index) { - if (&iter->second == ctrl) { - break; - } - } - - return index; -} - -void PADClearPort(u32 port) { - auto* ctrl = aurora::input::get_controller_for_player(port); - if (ctrl == nullptr) { - return; - } - SDL_GameControllerSetPlayerIndex(ctrl->m_controller, -1); -} - -void __PADLoadMapping(aurora::input::GameController* controller) { - s32 playerIndex = SDL_GameControllerGetPlayerIndex(controller->m_controller); - if (playerIndex == -1) { - return; - } - - std::string basePath = std::string(metaforce::FileStoreManager::instance()->getStoreRoot()); - if (!controller->m_mappingLoaded) { - controller->m_mapping = mDefaultButtons; - } - - controller->m_mappingLoaded = true; - - auto path = fmt::format(FMT_STRING("{}/{}_{:04X}_{:04X}.controller"), basePath, PADGetName(playerIndex), - controller->m_vid, controller->m_pid); - FILE* file = fopen(path.c_str(), "rb"); - if (file == nullptr) { - return; - } - - u32 magic = 0; - fread(&magic, 1, sizeof(u32), file); - if (magic != SBIG('CTRL')) { - fmt::print(FMT_STRING("Invalid controller mapping magic!\n")); - return; - } - - u32 version = 0; - fread(&version, 1, sizeof(u32), file); - if (version != 1) { - fmt::print(FMT_STRING("Invalid controller mapping version!\n")); - return; - } - - bool isGameCube = false; - fread(&isGameCube, 1, 1, file); - fseek(file, (ftell(file) + 31) & ~31, SEEK_SET); - u32 dataStart = ftell(file); - if (isGameCube) { - fseek(file, dataStart + ((sizeof(PADDeadZones) + sizeof(PADButtonMapping)) * playerIndex), SEEK_SET); - } - - fread(&controller->m_deadZones, 1, sizeof(PADDeadZones), file); - fread(&controller->m_mapping, 1, sizeof(PADButtonMapping) * controller->m_mapping.size(), file); - fclose(file); -} - -bool gBlockPAD = false; -u32 PADRead(PAD::Status* status) { - if (gBlockPAD) { - return 0; - } - - u32 rumbleSupport = 0; - for (u32 i = 0; i < 4; ++i) { - memset(&status[i], 0, sizeof(PAD::Status)); - auto controller = aurora::input::get_controller_for_player(i); - if (controller == nullptr) { - status[i].xa_err = PAD::ERR_NO_CONTROLLER; - continue; - } - - if (!controller->m_mappingLoaded) { - __PADLoadMapping(controller); - } - status[i].xa_err = PAD::ERR_NONE; - std::for_each(controller->m_mapping.begin(), controller->m_mapping.end(), - [&controller, &i, &status](const auto& mapping) { - if (SDL_GameControllerGetButton(controller->m_controller, - static_cast(mapping.nativeButton))) { - status[i].x0_buttons |= mapping.padButton; - } - }); - - Sint16 x = SDL_GameControllerGetAxis(controller->m_controller, SDL_CONTROLLER_AXIS_LEFTX); - Sint16 y = SDL_GameControllerGetAxis(controller->m_controller, SDL_CONTROLLER_AXIS_LEFTY); - if (controller->m_deadZones.useDeadzones) { - if (std::abs(x) > controller->m_deadZones.stickDeadZone) { - x /= 256; - } else { - x = 0; - } - if (std::abs(y) > controller->m_deadZones.stickDeadZone) { - y = (-(y + 1u)) / 256u; - } else { - y = 0; - } - } else { - x /= 256; - y = (-(y + 1u)) / 256u; - } - - status[i].x2_stickX = static_cast(x); - status[i].x3_stickY = static_cast(y); - - x = SDL_GameControllerGetAxis(controller->m_controller, SDL_CONTROLLER_AXIS_RIGHTX); - y = SDL_GameControllerGetAxis(controller->m_controller, SDL_CONTROLLER_AXIS_RIGHTY); - if (controller->m_deadZones.useDeadzones) { - if (std::abs(x) > controller->m_deadZones.substickDeadZone) { - x /= 256; - } else { - x = 0; - } - - if (std::abs(y) > controller->m_deadZones.substickDeadZone) { - y = (-(y + 1u)) / 256u; - } else { - y = 0; - } - } else { - x /= 256; - y = (-(y + 1u)) / 256u; - } - - status[i].x4_substickX = static_cast(x); - status[i].x5_substickY = static_cast(y); - - x = SDL_GameControllerGetAxis(controller->m_controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT); - y = SDL_GameControllerGetAxis(controller->m_controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT); - if (/*!controller->m_isGameCube && */ controller->m_deadZones.emulateTriggers) { - if (x > controller->m_deadZones.leftTriggerActivationZone) { - status[i].x0_buttons |= PAD::TRIGGER_L; - } - if (y > controller->m_deadZones.rightTriggerActivationZone) { - status[i].x0_buttons |= PAD::TRIGGER_R; - } - } - x /= 128; - y /= 128; - - status[i].x6_triggerL = static_cast(x); - status[i].x7_triggerR = static_cast(y); - - if (controller->m_hasRumble) { - rumbleSupport |= PAD::CHAN0_BIT >> i; - } - } - return rumbleSupport; -} - -void PADControlAllMotors(const u32* commands) { - for (u32 i = 0; i < 4; ++i) { - auto controller = aurora::input::get_controller_for_player(i); - auto instance = aurora::input::get_instance_for_player(i); - if (controller == nullptr) { - continue; - } - - if (controller->m_isGameCube) { - if (commands[i] == PAD::MOTOR_STOP) { - aurora::input::controller_rumble(instance, 0, 1, 0); - } else if (commands[i] == PAD::MOTOR_RUMBLE) { - aurora::input::controller_rumble(instance, 1, 1, 0); - } else if (commands[i] == PAD::MOTOR_STOP_HARD) { - aurora::input::controller_rumble(instance, 0, 0, 0); - } - } else { - if (commands[i] == PAD::MOTOR_STOP) { - aurora::input::controller_rumble(instance, 0, 0, 1); - } else if (commands[i] == PAD::MOTOR_RUMBLE) { - aurora::input::controller_rumble(instance, 32767, 32767, 0); - } else if (commands[i] == PAD::MOTOR_STOP_HARD) { - aurora::input::controller_rumble(instance, 0, 0, 0); - } - } - } -} - -u32 SIProbe(s32 chan) { - auto* const controller = aurora::input::get_controller_for_player(chan); - if (controller == nullptr) { - return SI::ERROR_NO_RESPONSE; - } - - if (controller->m_isGameCube) { - auto level = SDL_JoystickCurrentPowerLevel(SDL_GameControllerGetJoystick(controller->m_controller)); - if (level == SDL_JOYSTICK_POWER_UNKNOWN) { - return SI::GC_WAVEBIRD; - } - } - - return SI::GC_CONTROLLER; -} - -struct PADCLampRegion { - u8 minTrigger; - u8 maxTrigger; - s8 minStick; - s8 maxStick; - s8 xyStick; - s8 minSubstick; - s8 maxSubstick; - s8 xySubstick; - s8 radStick; - s8 radSubstick; -}; - -static constexpr PADCLampRegion ClampRegion{ - // Triggers - 30, - 180, - - // Left stick - 15, - 72, - 40, - - // Right stick - 15, - 59, - 31, - - // Stick radii - 56, - 44, -}; - -void ClampTrigger(u8* trigger, u8 min, u8 max) { - if (*trigger <= min) { - *trigger = 0; - } else { - if (*trigger > max) { - *trigger = max; - } - *trigger -= min; - } -} - -void ClampCircle(s8* px, s8* py, s8 radius, s8 min) { - int x = *px; - int y = *py; - - if (-min < x && x < min) { - x = 0; - } else if (0 < x) { - x -= min; - } else { - x += min; - } - - if (-min < y && y < min) { - y = 0; - } else if (0 < y) { - y -= min; - } else { - y += min; - } - - int squared = x * x + y * y; - if (radius * radius < squared) { - s32 length = static_cast(std::sqrt(squared)); - x = (x * radius) / length; - y = (y * radius) / length; - } - - *px = static_cast(x); - *py = static_cast(y); -} - -void ClampStick(s8* px, s8* py, s8 max, s8 xy, s8 min) { - s32 x = *px; - s32 y = *py; - - s32 signX = 0; - if (0 <= x) { - signX = 1; - } else { - signX = -1; - x = -x; - } - - s8 signY = 0; - if (0 <= y) { - signY = 1; - } else { - signY = -1; - y = -y; - } - - if (x <= min) { - x = 0; - } else { - x -= min; - } - if (y <= min) { - y = 0; - } else { - y -= min; - } - - if (x == 0 && y == 0) { - *px = *py = 0; - return; - } - - if (xy * y <= xy * x) { - s32 d = xy * x + (max - xy) * y; - if (xy * max < d) { - x = (xy * max * x / d); - y = (xy * max * y / d); - } - } else { - s32 d = xy * y + (max - xy) * x; - if (xy * max < d) { - x = (xy * max * x / d); - y = (xy * max * y / d); - } - } - - *px = (signX * x); - *py = (signY * y); -} - -void PADClamp(PAD::Status* status) { - for (u32 i = 0; i < 4; ++i) { - if (status[i].xa_err != PAD::ERR_NONE) { - continue; - } - - ClampStick(&status[i].x2_stickX, &status[i].x3_stickY, ClampRegion.maxStick, ClampRegion.xyStick, - ClampRegion.minStick); - ClampStick(&status[i].x4_substickX, &status[i].x5_substickY, ClampRegion.maxSubstick, ClampRegion.xySubstick, - ClampRegion.minSubstick); - ClampTrigger(&status[i].x6_triggerL, ClampRegion.minTrigger, ClampRegion.maxTrigger); - ClampTrigger(&status[i].x7_triggerR, ClampRegion.minTrigger, ClampRegion.maxTrigger); - } -} - -void PADClampCircle(PAD::Status* status) { - for (u32 i = 0; i < 4; ++i) { - if (status[i].xa_err != PAD::ERR_NONE) { - continue; - } - - ClampCircle(&status[i].x2_stickX, &status[i].x3_stickY, ClampRegion.radStick, ClampRegion.minStick); - ClampCircle(&status[i].x4_substickX, &status[i].x5_substickY, ClampRegion.radSubstick, ClampRegion.minSubstick); - ClampTrigger(&status[i].x6_triggerL, ClampRegion.minTrigger, ClampRegion.maxTrigger); - ClampTrigger(&status[i].x7_triggerR, ClampRegion.minTrigger, ClampRegion.maxTrigger); - } -} - -void PADGetVidPid(u32 port, u32* vid, u32* pid) { - *vid = 0; - *pid = 0; - auto* controller = aurora::input::get_controller_for_player(port); - if (controller == nullptr) { - return; - } - - *vid = controller->m_vid; - *pid = controller->m_pid; -} - -const char* PADGetName(u32 port) { - auto* controller = aurora::input::get_controller_for_player(port); - if (controller == nullptr) { - return nullptr; - } - - return SDL_GameControllerName(controller->m_controller); -} - -void PADSetButtonMapping(u32 port, PADButtonMapping mapping) { - auto* controller = aurora::input::get_controller_for_player(port); - if (controller == nullptr) { - return; - } - - auto iter = std::find_if(controller->m_mapping.begin(), controller->m_mapping.end(), - [mapping](const auto& pair) { return mapping.padButton == pair.padButton; }); - if (iter == controller->m_mapping.end()) { - return; - } - - *iter = mapping; -} - -void PADSetAllButtonMappings(u32 port, PADButtonMapping buttons[12]) { - for (u32 i = 0; i < 12; ++i) { - PADSetButtonMapping(port, buttons[i]); - } -} - -PADButtonMapping* PADGetButtonMappings(u32 port, u32* buttonCount) { - auto* controller = aurora::input::get_controller_for_player(port); - if (controller == nullptr) { - *buttonCount = 0; - return nullptr; - } - - *buttonCount = controller->m_mapping.size(); - return controller->m_mapping.data(); -} - -void __PADWriteDeadZones(FILE* file, aurora::input::GameController& controller) { - fwrite(&controller.m_deadZones, 1, sizeof(PADDeadZones), file); -} - -void PADSerializeMappings() { - std::string basePath = std::string(metaforce::FileStoreManager::instance()->getStoreRoot()); - - bool wroteGameCubeAlready = false; - for (auto& controller : aurora::input::g_GameControllers) { - if (!controller.second.m_mappingLoaded) { - __PADLoadMapping(&controller.second); - } - FILE* file = fopen(fmt::format(FMT_STRING("{}/{}_{:04X}_{:04X}.controller"), basePath, - aurora::input::controller_name(controller.second.m_index), controller.second.m_vid, - controller.second.m_pid) - .c_str(), - "wbe"); - if (file == nullptr) { - return; - } - - uint32_t magic = SBIG('CTRL'); - uint32_t version = 1; - fwrite(&magic, 1, sizeof(magic), file); - fwrite(&version, 1, sizeof(magic), file); - fwrite(&controller.second.m_isGameCube, 1, 1, file); - fseek(file, (ftell(file) + 31) & ~31, SEEK_SET); - int32_t dataStart = ftell(file); - if (!controller.second.m_isGameCube) { - __PADWriteDeadZones(file, controller.second); - fwrite(controller.second.m_mapping.data(), 1, sizeof(PADButtonMapping) * controller.second.m_mapping.size(), - file); - } else { - if (!wroteGameCubeAlready) { - for (u32 i = 0; i < 4; ++i) { - /* Just use the current controller's configs for this */ - __PADWriteDeadZones(file, controller.second); - fwrite(mDefaultButtons.data(), 1, sizeof(PADButtonMapping) * mDefaultButtons.size(), file); - } - fflush(file); - wroteGameCubeAlready = true; - } - uint32_t port = aurora::input::player_index(controller.second.m_index); - fseek(file, dataStart + ((sizeof(PADDeadZones) + sizeof(PADButtonMapping)) * port), SEEK_SET); - __PADWriteDeadZones(file, controller.second); - fwrite(controller.second.m_mapping.data(), 1, sizeof(PADButtonMapping) * controller.second.m_mapping.size(), - file); - } - fclose(file); - } -} - -PADDeadZones* PADGetDeadZones(u32 port) { - auto* controller = aurora::input::get_controller_for_player(port); - if (controller == nullptr) { - return nullptr; - } - return &controller->m_deadZones; -} - -static constexpr std::array, 12> skButtonNames = {{ - {PAD::BUTTON_LEFT, "Left"sv}, - {PAD::BUTTON_RIGHT, "Right"sv}, - {PAD::BUTTON_DOWN, "Down"sv}, - {PAD::BUTTON_UP, "Up"sv}, - {PAD::TRIGGER_Z, "Z"sv}, - {PAD::TRIGGER_R, "R"sv}, - {PAD::TRIGGER_L, "L"sv}, - {PAD::BUTTON_A, "A"sv}, - {PAD::BUTTON_B, "B"sv}, - {PAD::BUTTON_X, "X"sv}, - {PAD::BUTTON_Y, "Y"sv}, - {PAD::BUTTON_START, "Start"sv}, -}}; - -const char* PADGetButtonName(PAD::BUTTON button) { - auto it = std::find_if(skButtonNames.begin(), skButtonNames.end(), - [&button](const auto& pair) { return button == pair.first; }); - - if (it != skButtonNames.end()) { - return it->second.data(); - } - - return nullptr; -} - -const char* PADGetNativeButtonName(u32 button) { - return SDL_GameControllerGetStringForButton(static_cast(button)); -} - -s32 PADGetNativeButtonPressed(u32 port) { - auto* controller = aurora::input::get_controller_for_player(port); - if (controller == nullptr) { - return -1; - } - - for (u32 i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) { - if (SDL_GameControllerGetButton(controller->m_controller, static_cast(i)) != 0u) { - return i; - } - } - return -1; -} - -void PADRestoreDefaultMapping(u32 port) { - auto* controller = aurora::input::get_controller_for_player(port); - if (controller == nullptr) { - return; - } - controller->m_mapping = mDefaultButtons; -} - -void PADBlockInput(bool block) { gBlockPAD = block; } diff --git a/aurora/lib/input.hpp b/aurora/lib/input.hpp deleted file mode 100644 index a8578d8df..000000000 --- a/aurora/lib/input.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "aurora/aurora.hpp" -#include "SDL_gamecontroller.h" -#include "SDL_keyboard.h" -#include "SDL_keycode.h" -#include "SDL_mouse.h" - -namespace aurora::input { -Sint32 get_instance_for_player(u32 player) noexcept; -Sint32 add_controller(Sint32 which) noexcept; -void remove_controller(Uint32 instance) noexcept; -Sint32 player_index(Uint32 instance) noexcept; -void set_player_index(Uint32 instance, Sint32 index) noexcept; -std::string controller_name(Uint32 instance) noexcept; -bool is_gamecube(Uint32 instance) noexcept; -bool controller_has_rumble(Uint32 instance) noexcept; -void controller_rumble(uint32_t instance, uint16_t low_freq_intensity, uint16_t high_freq_intensity, - uint16_t duration_ms) noexcept; -uint32_t controller_count() noexcept; -ControllerButton translate_controller_button(SDL_GameControllerButton button) noexcept; -ControllerAxis translate_controller_axis(SDL_GameControllerAxis axis) noexcept; -char translate_key(SDL_Keysym sym, SpecialKey& specialSym, ModifierKey& modifierSym) noexcept; -ModifierKey translate_modifiers(Uint16 mods) noexcept; -MouseButton translate_mouse_button(Uint8 button) noexcept; -MouseButton translate_mouse_button_state(Uint8 state) noexcept; -} // namespace aurora::input diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index 72c4c0a3e..8a4d2cffb 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -38,13 +38,12 @@ else () include(athena/atdna/atdnaHelpers.cmake) endif () -if (WIN32) - set(SDL_LIBC ON CACHE BOOL "Use the system C library" FORCE) -endif () -add_subdirectory(../extern/SDL SDL2 EXCLUDE_FROM_ALL) -if (NOT MSVC) - target_compile_options(SDL2-static PRIVATE -Wno-implicit-fallthrough -Wno-shadow) -endif () +# Enable MoltenVK +#if (CMAKE_SYSTEM_NAME STREQUAL Darwin) +# set(DAWN_ENABLE_VULKAN ON CACHE BOOL "Enable compilation of the Vulkan backend" FORCE) +#endif() +set(AURORA_NATIVE_MATRIX ON CACHE BOOL "Assume OpenGL-layout matrices, disables transposing" FORCE) +add_subdirectory(aurora) # boo must come after SDL2 add_subdirectory(boo EXCLUDE_FROM_ALL) @@ -99,29 +98,6 @@ else () message(WARNING "nativefiledialog unsupported for ${CMAKE_SYSTEM_NAME}") endif () -# Enable MoltenVK -#if (CMAKE_SYSTEM_NAME STREQUAL Darwin) -# set(DAWN_ENABLE_VULKAN ON CACHE BOOL "Enable compilation of the Vulkan backend" FORCE) -#endif() -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - set(DAWN_ENABLE_DESKTOP_GL ON CACHE BOOL "Enable compilation of the OpenGL backend" FORCE) -endif () -if (CMAKE_SYSTEM_NAME STREQUAL Linux) - set(DAWN_ENABLE_OPENGLES ON CACHE BOOL "Enable compilation of the OpenGL ES backend" FORCE) -endif () -add_subdirectory(../extern/dawn dawn EXCLUDE_FROM_ALL) -if (DAWN_ENABLE_VULKAN) - target_compile_definitions(dawn_native PRIVATE - DAWN_ENABLE_VULKAN_VALIDATION_LAYERS - DAWN_VK_DATA_DIR="vulkandata") -endif () -if (MSVC) - target_compile_options(dawn_native PRIVATE /bigobj) -else() - target_compile_options(SPIRV-Tools-static PRIVATE -Wno-implicit-fallthrough) - target_compile_options(SPIRV-Tools-opt PRIVATE -Wno-implicit-fallthrough) -endif () - option(OPTICK_ENABLED "Enable profiling with Optick" OFF) set(OPTICK_USE_VULKAN ${DAWN_ENABLE_VULKAN} CACHE BOOL "Built-in support for Vulkan" FORCE) set(OPTICK_INSTALL_TARGETS OFF CACHE BOOL "Should optick be installed? Set to OFF if you use add_subdirectory to include Optick." FORCE) @@ -131,5 +107,4 @@ if (NOT MSVC) endif () add_subdirectory(libjpeg-turbo EXCLUDE_FROM_ALL) -add_subdirectory(xxhash EXCLUDE_FROM_ALL) add_subdirectory(zeus EXCLUDE_FROM_ALL) diff --git a/extern/SDL b/extern/SDL deleted file mode 160000 index af40cb6f0..000000000 --- a/extern/SDL +++ /dev/null @@ -1 +0,0 @@ -Subproject commit af40cb6f006ccdb46f6db1c3f7b0cf6e187f0f0d diff --git a/extern/aurora b/extern/aurora new file mode 160000 index 000000000..928b34ce7 --- /dev/null +++ b/extern/aurora @@ -0,0 +1 @@ +Subproject commit 928b34ce767e160cb4b0d7db1f1f09e10cc64ef3 diff --git a/extern/dawn b/extern/dawn deleted file mode 160000 index 8341499b8..000000000 --- a/extern/dawn +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8341499b8627f9123b14158dbeeeadef9c9e7f4d diff --git a/extern/imgui b/extern/imgui deleted file mode 160000 index dca527be1..000000000 --- a/extern/imgui +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dca527be1b77e38047054196fd6a96e8abdae131 diff --git a/extern/xxhash/CMakeLists.txt b/extern/xxhash/CMakeLists.txt deleted file mode 100644 index 2fa43533e..000000000 --- a/extern/xxhash/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_library(xxhash xxhash_impl.c) -target_include_directories(xxhash PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_compile_definitions(xxhash INTERFACE XXH_STATIC_LINKING_ONLY) diff --git a/extern/xxhash/LICENSE b/extern/xxhash/LICENSE deleted file mode 100644 index e4c5da723..000000000 --- a/extern/xxhash/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -xxHash Library -Copyright (c) 2012-2021 Yann Collet -All rights reserved. - -BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/extern/xxhash/xxh_x86dispatch.c b/extern/xxhash/xxh_x86dispatch.c deleted file mode 100644 index bec93bf9d..000000000 --- a/extern/xxhash/xxh_x86dispatch.c +++ /dev/null @@ -1,770 +0,0 @@ -/* - * xxHash - Extremely Fast Hash algorithm - * Copyright (C) 2020-2021 Yann Collet - * - * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You can contact the author at: - * - xxHash homepage: https://www.xxhash.com - * - xxHash source repository: https://github.com/Cyan4973/xxHash - */ - - -/*! - * @file xxh_x86dispatch.c - * - * Automatic dispatcher code for the @ref XXH3_family on x86-based targets. - * - * Optional add-on. - * - * **Compile this file with the default flags for your target.** Do not compile - * with flags like `-mavx*`, `-march=native`, or `/arch:AVX*`, there will be - * an error. See @ref XXH_X86DISPATCH_ALLOW_AVX for details. - * - * @defgroup dispatch x86 Dispatcher - * @{ - */ - -#if defined (__cplusplus) -extern "C" { -#endif - -#if !(defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64)) -# error "Dispatching is currently only supported on x86 and x86_64." -#endif - -/*! - * @def XXH_X86DISPATCH_ALLOW_AVX - * @brief Disables the AVX sanity check. - * - * Don't compile xxh_x86dispatch.c with options like `-mavx*`, `-march=native`, - * or `/arch:AVX*`. It is intended to be compiled for the minimum target, and - * it selectively enables SSE2, AVX2, and AVX512 when it is needed. - * - * Using this option _globally_ allows this feature, and therefore makes it - * undefined behavior to execute on any CPU without said feature. - * - * Even if the source code isn't directly using AVX intrinsics in a function, - * the compiler can still generate AVX code from autovectorization and by - * "upgrading" SSE2 intrinsics to use the VEX prefixes (a.k.a. AVX128). - * - * Use the same flags that you use to compile the rest of the program; this - * file will safely generate SSE2, AVX2, and AVX512 without these flags. - * - * Define XXH_X86DISPATCH_ALLOW_AVX to ignore this check, and feel free to open - * an issue if there is a target in the future where AVX is a default feature. - */ -#ifdef XXH_DOXYGEN -# define XXH_X86DISPATCH_ALLOW_AVX -#endif - -#if defined(__AVX__) && !defined(XXH_X86DISPATCH_ALLOW_AVX) -# error "Do not compile xxh_x86dispatch.c with AVX enabled! See the comment above." -#endif - -#ifdef __has_include -# define XXH_HAS_INCLUDE(header) __has_include(header) -#else -# define XXH_HAS_INCLUDE(header) 0 -#endif - -/*! - * @def XXH_DISPATCH_SCALAR - * @brief Enables/dispatching the scalar code path. - * - * If this is defined to 0, SSE2 support is assumed. This reduces code size - * when the scalar path is not needed. - * - * This is automatically defined to 0 when... - * - SSE2 support is enabled in the compiler - * - Targeting x86_64 - * - Targeting Android x86 - * - Targeting macOS - */ -#ifndef XXH_DISPATCH_SCALAR -# if defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2) /* SSE2 on by default */ \ - || defined(__x86_64__) || defined(_M_X64) /* x86_64 */ \ - || defined(__ANDROID__) || defined(__APPLEv__) /* Android or macOS */ -# define XXH_DISPATCH_SCALAR 0 /* disable */ -# else -# define XXH_DISPATCH_SCALAR 1 -# endif -#endif -/*! - * @def XXH_DISPATCH_AVX2 - * @brief Enables/disables dispatching for AVX2. - * - * This is automatically detected if it is not defined. - * - GCC 4.7 and later are known to support AVX2, but >4.9 is required for - * to get the AVX2 intrinsics and typedefs without -mavx -mavx2. - * - Visual Studio 2013 Update 2 and later are known to support AVX2. - * - The GCC/Clang internal header `` is detected. While this is - * not allowed to be included directly, it still appears in the builtin - * include path and is detectable with `__has_include`. - * - * @see XXH_AVX2 - */ -#ifndef XXH_DISPATCH_AVX2 -# if (defined(__GNUC__) && (__GNUC__ > 4)) /* GCC 5.0+ */ \ - || (defined(_MSC_VER) && _MSC_VER >= 1900) /* VS 2015+ */ \ - || (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180030501) /* VS 2013 Update 2 */ \ - || XXH_HAS_INCLUDE() /* GCC/Clang internal header */ -# define XXH_DISPATCH_AVX2 1 /* enable dispatch towards AVX2 */ -# else -# define XXH_DISPATCH_AVX2 0 -# endif -#endif /* XXH_DISPATCH_AVX2 */ - -/*! - * @def XXH_DISPATCH_AVX512 - * @brief Enables/disables dispatching for AVX512. - * - * Automatically detected if one of the following conditions is met: - * - GCC 4.9 and later are known to support AVX512. - * - Visual Studio 2017 and later are known to support AVX2. - * - The GCC/Clang internal header `` is detected. While this - * is not allowed to be included directly, it still appears in the builtin - * include path and is detectable with `__has_include`. - * - * @see XXH_AVX512 - */ -#ifndef XXH_DISPATCH_AVX512 -# if (defined(__GNUC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) /* GCC 4.9+ */ \ - || (defined(_MSC_VER) && _MSC_VER >= 1910) /* VS 2017+ */ \ - || XXH_HAS_INCLUDE() /* GCC/Clang internal header */ -# define XXH_DISPATCH_AVX512 1 /* enable dispatch towards AVX512 */ -# else -# define XXH_DISPATCH_AVX512 0 -# endif -#endif /* XXH_DISPATCH_AVX512 */ - -/*! - * @def XXH_TARGET_SSE2 - * @brief Allows a function to be compiled with SSE2 intrinsics. - * - * Uses `__attribute__((__target__("sse2")))` on GCC to allow SSE2 to be used - * even with `-mno-sse2`. - * - * @def XXH_TARGET_AVX2 - * @brief Like @ref XXH_TARGET_SSE2, but for AVX2. - * - * @def XXH_TARGET_AVX512 - * @brief Like @ref XXH_TARGET_SSE2, but for AVX512. - */ -#if defined(__GNUC__) -# include /* SSE2 */ -# if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 -# include /* AVX2, AVX512F */ -# endif -# define XXH_TARGET_SSE2 __attribute__((__target__("sse2"))) -# define XXH_TARGET_AVX2 __attribute__((__target__("avx2"))) -# define XXH_TARGET_AVX512 __attribute__((__target__("avx512f"))) -#elif defined(_MSC_VER) -# include -# define XXH_TARGET_SSE2 -# define XXH_TARGET_AVX2 -# define XXH_TARGET_AVX512 -#else -# error "Dispatching is currently not supported for your compiler." -#endif - -#ifdef XXH_DISPATCH_DEBUG -/* debug logging */ -# include -# define XXH_debugPrint(str) { fprintf(stderr, "DEBUG: xxHash dispatch: %s \n", str); fflush(NULL); } -#else -# define XXH_debugPrint(str) ((void)0) -# undef NDEBUG /* avoid redefinition */ -# define NDEBUG -#endif -#include - -#define XXH_INLINE_ALL -#define XXH_X86DISPATCH -#include "xxhash.h" - -/* - * Support both AT&T and Intel dialects - * - * GCC doesn't convert AT&T syntax to Intel syntax, and will error out if - * compiled with -masm=intel. Instead, it supports dialect switching with - * curly braces: { AT&T syntax | Intel syntax } - * - * Clang's integrated assembler automatically converts AT&T syntax to Intel if - * needed, making the dialect switching useless (it isn't even supported). - * - * Note: Comments are written in the inline assembly itself. - */ -#ifdef __clang__ -# define XXH_I_ATT(intel, att) att "\n\t" -#else -# define XXH_I_ATT(intel, att) "{" att "|" intel "}\n\t" -#endif - -/*! - * @internal - * @brief Runs CPUID. - * - * @param eax , ecx The parameters to pass to CPUID, %eax and %ecx respectively. - * @param abcd The array to store the result in, `{ eax, ebx, ecx, edx }` - */ -static void XXH_cpuid(xxh_u32 eax, xxh_u32 ecx, xxh_u32* abcd) -{ -#if defined(_MSC_VER) - __cpuidex(abcd, eax, ecx); -#else - xxh_u32 ebx, edx; -# if defined(__i386__) && defined(__PIC__) - __asm__( - "# Call CPUID\n\t" - "#\n\t" - "# On 32-bit x86 with PIC enabled, we are not allowed to overwrite\n\t" - "# EBX, so we use EDI instead.\n\t" - XXH_I_ATT("mov edi, ebx", "movl %%ebx, %%edi") - XXH_I_ATT("cpuid", "cpuid" ) - XXH_I_ATT("xchg edi, ebx", "xchgl %%ebx, %%edi") - : "=D" (ebx), -# else - __asm__( - "# Call CPUID\n\t" - XXH_I_ATT("cpuid", "cpuid") - : "=b" (ebx), -# endif - "+a" (eax), "+c" (ecx), "=d" (edx)); - abcd[0] = eax; - abcd[1] = ebx; - abcd[2] = ecx; - abcd[3] = edx; -#endif -} - -/* - * Modified version of Intel's guide - * https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family - */ - -#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 -/*! - * @internal - * @brief Runs `XGETBV`. - * - * While the CPU may support AVX2, the operating system might not properly save - * the full YMM/ZMM registers. - * - * xgetbv is used for detecting this: Any compliant operating system will define - * a set of flags in the xcr0 register indicating how it saves the AVX registers. - * - * You can manually disable this flag on Windows by running, as admin: - * - * bcdedit.exe /set xsavedisable 1 - * - * and rebooting. Run the same command with 0 to re-enable it. - */ -static xxh_u64 XXH_xgetbv(void) -{ -#if defined(_MSC_VER) - return _xgetbv(0); /* min VS2010 SP1 compiler is required */ -#else - xxh_u32 xcr0_lo, xcr0_hi; - __asm__( - "# Call XGETBV\n\t" - "#\n\t" - "# Older assemblers (e.g. macOS's ancient GAS version) don't support\n\t" - "# the XGETBV opcode, so we encode it by hand instead.\n\t" - "# See for details.\n\t" - ".byte 0x0f, 0x01, 0xd0\n\t" - : "=a" (xcr0_lo), "=d" (xcr0_hi) : "c" (0)); - return xcr0_lo | ((xxh_u64)xcr0_hi << 32); -#endif -} -#endif - -#define XXH_SSE2_CPUID_MASK (1 << 26) -#define XXH_OSXSAVE_CPUID_MASK ((1 << 26) | (1 << 27)) -#define XXH_AVX2_CPUID_MASK (1 << 5) -#define XXH_AVX2_XGETBV_MASK ((1 << 2) | (1 << 1)) -#define XXH_AVX512F_CPUID_MASK (1 << 16) -#define XXH_AVX512F_XGETBV_MASK ((7 << 5) | (1 << 2) | (1 << 1)) - -/*! - * @internal - * @brief Returns the best XXH3 implementation. - * - * Runs various CPUID/XGETBV tests to try and determine the best implementation. - * - * @return The best @ref XXH_VECTOR implementation. - * @see XXH_VECTOR_TYPES - */ -static int XXH_featureTest(void) -{ - xxh_u32 abcd[4]; - xxh_u32 max_leaves; - int best = XXH_SCALAR; -#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 - xxh_u64 xgetbv_val; -#endif -#if defined(__GNUC__) && defined(__i386__) - xxh_u32 cpuid_supported; - __asm__( - "# For the sake of ruthless backwards compatibility, check if CPUID\n\t" - "# is supported in the EFLAGS on i386.\n\t" - "# This is not necessary on x86_64 - CPUID is mandatory.\n\t" - "# The ID flag (bit 21) in the EFLAGS register indicates support\n\t" - "# for the CPUID instruction. If a software procedure can set and\n\t" - "# clear this flag, the processor executing the procedure supports\n\t" - "# the CPUID instruction.\n\t" - "# \n\t" - "#\n\t" - "# Routine is from .\n\t" - - "# Save EFLAGS\n\t" - XXH_I_ATT("pushfd", "pushfl" ) - "# Store EFLAGS\n\t" - XXH_I_ATT("pushfd", "pushfl" ) - "# Invert the ID bit in stored EFLAGS\n\t" - XXH_I_ATT("xor dword ptr[esp], 0x200000", "xorl $0x200000, (%%esp)") - "# Load stored EFLAGS (with ID bit inverted)\n\t" - XXH_I_ATT("popfd", "popfl" ) - "# Store EFLAGS again (ID bit may or not be inverted)\n\t" - XXH_I_ATT("pushfd", "pushfl" ) - "# eax = modified EFLAGS (ID bit may or may not be inverted)\n\t" - XXH_I_ATT("pop eax", "popl %%eax" ) - "# eax = whichever bits were changed\n\t" - XXH_I_ATT("xor eax, dword ptr[esp]", "xorl (%%esp), %%eax" ) - "# Restore original EFLAGS\n\t" - XXH_I_ATT("popfd", "popfl" ) - "# eax = zero if ID bit can't be changed, else non-zero\n\t" - XXH_I_ATT("and eax, 0x200000", "andl $0x200000, %%eax" ) - : "=a" (cpuid_supported) :: "cc"); - - if (XXH_unlikely(!cpuid_supported)) { - XXH_debugPrint("CPUID support is not detected!"); - return best; - } - -#endif - /* Check how many CPUID pages we have */ - XXH_cpuid(0, 0, abcd); - max_leaves = abcd[0]; - - /* Shouldn't happen on hardware, but happens on some QEMU configs. */ - if (XXH_unlikely(max_leaves == 0)) { - XXH_debugPrint("Max CPUID leaves == 0!"); - return best; - } - - /* Check for SSE2, OSXSAVE and xgetbv */ - XXH_cpuid(1, 0, abcd); - - /* - * Test for SSE2. The check is redundant on x86_64, but it doesn't hurt. - */ - if (XXH_unlikely((abcd[3] & XXH_SSE2_CPUID_MASK) != XXH_SSE2_CPUID_MASK)) - return best; - - XXH_debugPrint("SSE2 support detected."); - - best = XXH_SSE2; -#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 - /* Make sure we have enough leaves */ - if (XXH_unlikely(max_leaves < 7)) - return best; - - /* Test for OSXSAVE and XGETBV */ - if ((abcd[2] & XXH_OSXSAVE_CPUID_MASK) != XXH_OSXSAVE_CPUID_MASK) - return best; - - /* CPUID check for AVX features */ - XXH_cpuid(7, 0, abcd); - - xgetbv_val = XXH_xgetbv(); -#if XXH_DISPATCH_AVX2 - /* Validate that AVX2 is supported by the CPU */ - if ((abcd[1] & XXH_AVX2_CPUID_MASK) != XXH_AVX2_CPUID_MASK) - return best; - - /* Validate that the OS supports YMM registers */ - if ((xgetbv_val & XXH_AVX2_XGETBV_MASK) != XXH_AVX2_XGETBV_MASK) { - XXH_debugPrint("AVX2 supported by the CPU, but not the OS."); - return best; - } - - /* AVX2 supported */ - XXH_debugPrint("AVX2 support detected."); - best = XXH_AVX2; -#endif -#if XXH_DISPATCH_AVX512 - /* Check if AVX512F is supported by the CPU */ - if ((abcd[1] & XXH_AVX512F_CPUID_MASK) != XXH_AVX512F_CPUID_MASK) { - XXH_debugPrint("AVX512F not supported by CPU"); - return best; - } - - /* Validate that the OS supports ZMM registers */ - if ((xgetbv_val & XXH_AVX512F_XGETBV_MASK) != XXH_AVX512F_XGETBV_MASK) { - XXH_debugPrint("AVX512F supported by the CPU, but not the OS."); - return best; - } - - /* AVX512F supported */ - XXH_debugPrint("AVX512F support detected."); - best = XXH_AVX512; -#endif -#endif - return best; -} - - -/* === Vector implementations === */ - -/*! - * @internal - * @brief Defines the various dispatch functions. - * - * TODO: Consolidate? - * - * @param suffix The suffix for the functions, e.g. sse2 or scalar - * @param target XXH_TARGET_* or empty. - */ -#define XXH_DEFINE_DISPATCH_FUNCS(suffix, target) \ - \ -/* === XXH3, default variants === */ \ - \ -XXH_NO_INLINE target XXH64_hash_t \ -XXHL64_default_##suffix(const void* XXH_RESTRICT input, size_t len) \ -{ \ - return XXH3_hashLong_64b_internal( \ - input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \ - XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix \ - ); \ -} \ - \ -/* === XXH3, Seeded variants === */ \ - \ -XXH_NO_INLINE target XXH64_hash_t \ -XXHL64_seed_##suffix(const void* XXH_RESTRICT input, size_t len, \ - XXH64_hash_t seed) \ -{ \ - return XXH3_hashLong_64b_withSeed_internal( \ - input, len, seed, XXH3_accumulate_512_##suffix, \ - XXH3_scrambleAcc_##suffix, XXH3_initCustomSecret_##suffix \ - ); \ -} \ - \ -/* === XXH3, Secret variants === */ \ - \ -XXH_NO_INLINE target XXH64_hash_t \ -XXHL64_secret_##suffix(const void* XXH_RESTRICT input, size_t len, \ - const void* secret, size_t secretLen) \ -{ \ - return XXH3_hashLong_64b_internal( \ - input, len, secret, secretLen, \ - XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix \ - ); \ -} \ - \ -/* === XXH3 update variants === */ \ - \ -XXH_NO_INLINE target XXH_errorcode \ -XXH3_update_##suffix(XXH3_state_t* state, const void* input, size_t len) \ -{ \ - return XXH3_update(state, (const xxh_u8*)input, len, \ - XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix); \ -} \ - \ -/* === XXH128 default variants === */ \ - \ -XXH_NO_INLINE target XXH128_hash_t \ -XXHL128_default_##suffix(const void* XXH_RESTRICT input, size_t len) \ -{ \ - return XXH3_hashLong_128b_internal( \ - input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \ - XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix \ - ); \ -} \ - \ -/* === XXH128 Secret variants === */ \ - \ -XXH_NO_INLINE target XXH128_hash_t \ -XXHL128_secret_##suffix(const void* XXH_RESTRICT input, size_t len, \ - const void* XXH_RESTRICT secret, size_t secretLen) \ -{ \ - return XXH3_hashLong_128b_internal( \ - input, len, (const xxh_u8*)secret, secretLen, \ - XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix); \ -} \ - \ -/* === XXH128 Seeded variants === */ \ - \ -XXH_NO_INLINE target XXH128_hash_t \ -XXHL128_seed_##suffix(const void* XXH_RESTRICT input, size_t len, \ - XXH64_hash_t seed) \ -{ \ - return XXH3_hashLong_128b_withSeed_internal(input, len, seed, \ - XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix, \ - XXH3_initCustomSecret_##suffix); \ -} - -/* End XXH_DEFINE_DISPATCH_FUNCS */ - -#if XXH_DISPATCH_SCALAR -XXH_DEFINE_DISPATCH_FUNCS(scalar, /* nothing */) -#endif -XXH_DEFINE_DISPATCH_FUNCS(sse2, XXH_TARGET_SSE2) -#if XXH_DISPATCH_AVX2 -XXH_DEFINE_DISPATCH_FUNCS(avx2, XXH_TARGET_AVX2) -#endif -#if XXH_DISPATCH_AVX512 -XXH_DEFINE_DISPATCH_FUNCS(avx512, XXH_TARGET_AVX512) -#endif -#undef XXH_DEFINE_DISPATCH_FUNCS - -/* ==== Dispatchers ==== */ - -typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_default)(const void* XXH_RESTRICT, size_t); - -typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSeed)(const void* XXH_RESTRICT, size_t, XXH64_hash_t); - -typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSecret)(const void* XXH_RESTRICT, size_t, const void* XXH_RESTRICT, size_t); - -typedef XXH_errorcode (*XXH3_dispatchx86_update)(XXH3_state_t*, const void*, size_t); - -typedef struct { - XXH3_dispatchx86_hashLong64_default hashLong64_default; - XXH3_dispatchx86_hashLong64_withSeed hashLong64_seed; - XXH3_dispatchx86_hashLong64_withSecret hashLong64_secret; - XXH3_dispatchx86_update update; -} XXH_dispatchFunctions_s; - -#define XXH_NB_DISPATCHES 4 - -/*! - * @internal - * @brief Table of dispatchers for @ref XXH3_64bits(). - * - * @pre The indices must match @ref XXH_VECTOR_TYPE. - */ -static const XXH_dispatchFunctions_s XXH_kDispatch[XXH_NB_DISPATCHES] = { -#if XXH_DISPATCH_SCALAR - /* Scalar */ { XXHL64_default_scalar, XXHL64_seed_scalar, XXHL64_secret_scalar, XXH3_update_scalar }, -#else - /* Scalar */ { NULL, NULL, NULL, NULL }, -#endif - /* SSE2 */ { XXHL64_default_sse2, XXHL64_seed_sse2, XXHL64_secret_sse2, XXH3_update_sse2 }, -#if XXH_DISPATCH_AVX2 - /* AVX2 */ { XXHL64_default_avx2, XXHL64_seed_avx2, XXHL64_secret_avx2, XXH3_update_avx2 }, -#else - /* AVX2 */ { NULL, NULL, NULL, NULL }, -#endif -#if XXH_DISPATCH_AVX512 - /* AVX512 */ { XXHL64_default_avx512, XXHL64_seed_avx512, XXHL64_secret_avx512, XXH3_update_avx512 } -#else - /* AVX512 */ { NULL, NULL, NULL, NULL } -#endif -}; -/*! - * @internal - * @brief The selected dispatch table for @ref XXH3_64bits(). - */ -static XXH_dispatchFunctions_s XXH_g_dispatch = { NULL, NULL, NULL, NULL }; - - -typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_default)(const void* XXH_RESTRICT, size_t); - -typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSeed)(const void* XXH_RESTRICT, size_t, XXH64_hash_t); - -typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSecret)(const void* XXH_RESTRICT, size_t, const void* XXH_RESTRICT, size_t); - -typedef struct { - XXH3_dispatchx86_hashLong128_default hashLong128_default; - XXH3_dispatchx86_hashLong128_withSeed hashLong128_seed; - XXH3_dispatchx86_hashLong128_withSecret hashLong128_secret; - XXH3_dispatchx86_update update; -} XXH_dispatch128Functions_s; - - -/*! - * @internal - * @brief Table of dispatchers for @ref XXH3_128bits(). - * - * @pre The indices must match @ref XXH_VECTOR_TYPE. - */ -static const XXH_dispatch128Functions_s XXH_kDispatch128[XXH_NB_DISPATCHES] = { -#if XXH_DISPATCH_SCALAR - /* Scalar */ { XXHL128_default_scalar, XXHL128_seed_scalar, XXHL128_secret_scalar, XXH3_update_scalar }, -#else - /* Scalar */ { NULL, NULL, NULL, NULL }, -#endif - /* SSE2 */ { XXHL128_default_sse2, XXHL128_seed_sse2, XXHL128_secret_sse2, XXH3_update_sse2 }, -#if XXH_DISPATCH_AVX2 - /* AVX2 */ { XXHL128_default_avx2, XXHL128_seed_avx2, XXHL128_secret_avx2, XXH3_update_avx2 }, -#else - /* AVX2 */ { NULL, NULL, NULL, NULL }, -#endif -#if XXH_DISPATCH_AVX512 - /* AVX512 */ { XXHL128_default_avx512, XXHL128_seed_avx512, XXHL128_secret_avx512, XXH3_update_avx512 } -#else - /* AVX512 */ { NULL, NULL, NULL, NULL } -#endif -}; - -/*! - * @internal - * @brief The selected dispatch table for @ref XXH3_64bits(). - */ -static XXH_dispatch128Functions_s XXH_g_dispatch128 = { NULL, NULL, NULL, NULL }; - -/*! - * @internal - * @brief Runs a CPUID check and sets the correct dispatch tables. - */ -static void XXH_setDispatch(void) -{ - int vecID = XXH_featureTest(); - XXH_STATIC_ASSERT(XXH_AVX512 == XXH_NB_DISPATCHES-1); - assert(XXH_SCALAR <= vecID && vecID <= XXH_AVX512); -#if !XXH_DISPATCH_SCALAR - assert(vecID != XXH_SCALAR); -#endif -#if !XXH_DISPATCH_AVX512 - assert(vecID != XXH_AVX512); -#endif -#if !XXH_DISPATCH_AVX2 - assert(vecID != XXH_AVX2); -#endif - XXH_g_dispatch = XXH_kDispatch[vecID]; - XXH_g_dispatch128 = XXH_kDispatch128[vecID]; -} - - -/* ==== XXH3 public functions ==== */ - -static XXH64_hash_t -XXH3_hashLong_64b_defaultSecret_selection(const void* input, size_t len, - XXH64_hash_t seed64, const xxh_u8* secret, size_t secretLen) -{ - (void)seed64; (void)secret; (void)secretLen; - if (XXH_g_dispatch.hashLong64_default == NULL) XXH_setDispatch(); - return XXH_g_dispatch.hashLong64_default(input, len); -} - -XXH64_hash_t XXH3_64bits_dispatch(const void* input, size_t len) -{ - return XXH3_64bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_defaultSecret_selection); -} - -static XXH64_hash_t -XXH3_hashLong_64b_withSeed_selection(const void* input, size_t len, - XXH64_hash_t seed64, const xxh_u8* secret, size_t secretLen) -{ - (void)secret; (void)secretLen; - if (XXH_g_dispatch.hashLong64_seed == NULL) XXH_setDispatch(); - return XXH_g_dispatch.hashLong64_seed(input, len, seed64); -} - -XXH64_hash_t XXH3_64bits_withSeed_dispatch(const void* input, size_t len, XXH64_hash_t seed) -{ - return XXH3_64bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed_selection); -} - -static XXH64_hash_t -XXH3_hashLong_64b_withSecret_selection(const void* input, size_t len, - XXH64_hash_t seed64, const xxh_u8* secret, size_t secretLen) -{ - (void)seed64; - if (XXH_g_dispatch.hashLong64_secret == NULL) XXH_setDispatch(); - return XXH_g_dispatch.hashLong64_secret(input, len, secret, secretLen); -} - -XXH64_hash_t XXH3_64bits_withSecret_dispatch(const void* input, size_t len, const void* secret, size_t secretLen) -{ - return XXH3_64bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_64b_withSecret_selection); -} - -XXH_errorcode -XXH3_64bits_update_dispatch(XXH3_state_t* state, const void* input, size_t len) -{ - if (XXH_g_dispatch.update == NULL) XXH_setDispatch(); - return XXH_g_dispatch.update(state, (const xxh_u8*)input, len); -} - - -/* ==== XXH128 public functions ==== */ - -static XXH128_hash_t -XXH3_hashLong_128b_defaultSecret_selection(const void* input, size_t len, - XXH64_hash_t seed64, const void* secret, size_t secretLen) -{ - (void)seed64; (void)secret; (void)secretLen; - if (XXH_g_dispatch128.hashLong128_default == NULL) XXH_setDispatch(); - return XXH_g_dispatch128.hashLong128_default(input, len); -} - -XXH128_hash_t XXH3_128bits_dispatch(const void* input, size_t len) -{ - return XXH3_128bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_defaultSecret_selection); -} - -static XXH128_hash_t -XXH3_hashLong_128b_withSeed_selection(const void* input, size_t len, - XXH64_hash_t seed64, const void* secret, size_t secretLen) -{ - (void)secret; (void)secretLen; - if (XXH_g_dispatch128.hashLong128_seed == NULL) XXH_setDispatch(); - return XXH_g_dispatch128.hashLong128_seed(input, len, seed64); -} - -XXH128_hash_t XXH3_128bits_withSeed_dispatch(const void* input, size_t len, XXH64_hash_t seed) -{ - return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_withSeed_selection); -} - -static XXH128_hash_t -XXH3_hashLong_128b_withSecret_selection(const void* input, size_t len, - XXH64_hash_t seed64, const void* secret, size_t secretLen) -{ - (void)seed64; - if (XXH_g_dispatch128.hashLong128_secret == NULL) XXH_setDispatch(); - return XXH_g_dispatch128.hashLong128_secret(input, len, secret, secretLen); -} - -XXH128_hash_t XXH3_128bits_withSecret_dispatch(const void* input, size_t len, const void* secret, size_t secretLen) -{ - return XXH3_128bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_128b_withSecret_selection); -} - -XXH_errorcode -XXH3_128bits_update_dispatch(XXH3_state_t* state, const void* input, size_t len) -{ - if (XXH_g_dispatch128.update == NULL) XXH_setDispatch(); - return XXH_g_dispatch128.update(state, (const xxh_u8*)input, len); -} - -#if defined (__cplusplus) -} -#endif -/*! @} */ diff --git a/extern/xxhash/xxh_x86dispatch.h b/extern/xxhash/xxh_x86dispatch.h deleted file mode 100644 index 417ef0811..000000000 --- a/extern/xxhash/xxh_x86dispatch.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * xxHash - XXH3 Dispatcher for x86-based targets - * Copyright (C) 2020-2021 Yann Collet - * - * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You can contact the author at: - * - xxHash homepage: https://www.xxhash.com - * - xxHash source repository: https://github.com/Cyan4973/xxHash - */ - -#ifndef XXH_X86DISPATCH_H_13563687684 -#define XXH_X86DISPATCH_H_13563687684 - -#include "xxhash.h" /* XXH64_hash_t, XXH3_state_t */ - -#if defined (__cplusplus) -extern "C" { -#endif - -XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_dispatch(const void* input, size_t len); -XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed_dispatch(const void* input, size_t len, XXH64_hash_t seed); -XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret_dispatch(const void* input, size_t len, const void* secret, size_t secretLen); -XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update_dispatch(XXH3_state_t* state, const void* input, size_t len); - -XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_dispatch(const void* input, size_t len); -XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed_dispatch(const void* input, size_t len, XXH64_hash_t seed); -XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret_dispatch(const void* input, size_t len, const void* secret, size_t secretLen); -XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update_dispatch(XXH3_state_t* state, const void* input, size_t len); - -#if defined (__cplusplus) -} -#endif - - -/* automatic replacement of XXH3 functions. - * can be disabled by setting XXH_DISPATCH_DISABLE_REPLACE */ -#ifndef XXH_DISPATCH_DISABLE_REPLACE - -# undef XXH3_64bits -# define XXH3_64bits XXH3_64bits_dispatch -# undef XXH3_64bits_withSeed -# define XXH3_64bits_withSeed XXH3_64bits_withSeed_dispatch -# undef XXH3_64bits_withSecret -# define XXH3_64bits_withSecret XXH3_64bits_withSecret_dispatch -# undef XXH3_64bits_update -# define XXH3_64bits_update XXH3_64bits_update_dispatch - -# undef XXH128 -# define XXH128 XXH3_128bits_withSeed_dispatch -# undef XXH3_128bits -# define XXH3_128bits XXH3_128bits_dispatch -# undef XXH3_128bits_withSeed -# define XXH3_128bits_withSeed XXH3_128bits_withSeed_dispatch -# undef XXH3_128bits_withSecret -# define XXH3_128bits_withSecret XXH3_128bits_withSecret_dispatch -# undef XXH3_128bits_update -# define XXH3_128bits_update XXH3_128bits_update_dispatch - -#endif /* XXH_DISPATCH_DISABLE_REPLACE */ - -#endif /* XXH_X86DISPATCH_H_13563687684 */ diff --git a/extern/xxhash/xxhash.c b/extern/xxhash/xxhash.c deleted file mode 100644 index 083b039d7..000000000 --- a/extern/xxhash/xxhash.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * xxHash - Extremely Fast Hash algorithm - * Copyright (C) 2012-2021 Yann Collet - * - * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You can contact the author at: - * - xxHash homepage: https://www.xxhash.com - * - xxHash source repository: https://github.com/Cyan4973/xxHash - */ - - -/* - * xxhash.c instantiates functions defined in xxhash.h - */ - -#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */ -#define XXH_IMPLEMENTATION /* access definitions */ - -#include "xxhash.h" diff --git a/extern/xxhash/xxhash.h b/extern/xxhash/xxhash.h deleted file mode 100644 index 9e5a8fd6f..000000000 --- a/extern/xxhash/xxhash.h +++ /dev/null @@ -1,6074 +0,0 @@ -/* - * xxHash - Extremely Fast Hash algorithm - * Header File - * Copyright (C) 2012-2021 Yann Collet - * - * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You can contact the author at: - * - xxHash homepage: https://www.xxhash.com - * - xxHash source repository: https://github.com/Cyan4973/xxHash - */ - -/*! - * @mainpage xxHash - * - * xxHash is an extremely fast non-cryptographic hash algorithm, working at RAM speed - * limits. - * - * It is proposed in four flavors, in three families: - * 1. @ref XXH32_family - * - Classic 32-bit hash function. Simple, compact, and runs on almost all - * 32-bit and 64-bit systems. - * 2. @ref XXH64_family - * - Classic 64-bit adaptation of XXH32. Just as simple, and runs well on most - * 64-bit systems (but _not_ 32-bit systems). - * 3. @ref XXH3_family - * - Modern 64-bit and 128-bit hash function family which features improved - * strength and performance across the board, especially on smaller data. - * It benefits greatly from SIMD and 64-bit without requiring it. - * - * Benchmarks - * --- - * The reference system uses an Intel i7-9700K CPU, and runs Ubuntu x64 20.04. - * The open source benchmark program is compiled with clang v10.0 using -O3 flag. - * - * | Hash Name | ISA ext | Width | Large Data Speed | Small Data Velocity | - * | -------------------- | ------- | ----: | ---------------: | ------------------: | - * | XXH3_64bits() | @b AVX2 | 64 | 59.4 GB/s | 133.1 | - * | MeowHash | AES-NI | 128 | 58.2 GB/s | 52.5 | - * | XXH3_128bits() | @b AVX2 | 128 | 57.9 GB/s | 118.1 | - * | CLHash | PCLMUL | 64 | 37.1 GB/s | 58.1 | - * | XXH3_64bits() | @b SSE2 | 64 | 31.5 GB/s | 133.1 | - * | XXH3_128bits() | @b SSE2 | 128 | 29.6 GB/s | 118.1 | - * | RAM sequential read | | N/A | 28.0 GB/s | N/A | - * | ahash | AES-NI | 64 | 22.5 GB/s | 107.2 | - * | City64 | | 64 | 22.0 GB/s | 76.6 | - * | T1ha2 | | 64 | 22.0 GB/s | 99.0 | - * | City128 | | 128 | 21.7 GB/s | 57.7 | - * | FarmHash | AES-NI | 64 | 21.3 GB/s | 71.9 | - * | XXH64() | | 64 | 19.4 GB/s | 71.0 | - * | SpookyHash | | 64 | 19.3 GB/s | 53.2 | - * | Mum | | 64 | 18.0 GB/s | 67.0 | - * | CRC32C | SSE4.2 | 32 | 13.0 GB/s | 57.9 | - * | XXH32() | | 32 | 9.7 GB/s | 71.9 | - * | City32 | | 32 | 9.1 GB/s | 66.0 | - * | Blake3* | @b AVX2 | 256 | 4.4 GB/s | 8.1 | - * | Murmur3 | | 32 | 3.9 GB/s | 56.1 | - * | SipHash* | | 64 | 3.0 GB/s | 43.2 | - * | Blake3* | @b SSE2 | 256 | 2.4 GB/s | 8.1 | - * | HighwayHash | | 64 | 1.4 GB/s | 6.0 | - * | FNV64 | | 64 | 1.2 GB/s | 62.7 | - * | Blake2* | | 256 | 1.1 GB/s | 5.1 | - * | SHA1* | | 160 | 0.8 GB/s | 5.6 | - * | MD5* | | 128 | 0.6 GB/s | 7.8 | - * @note - * - Hashes which require a specific ISA extension are noted. SSE2 is also noted, - * even though it is mandatory on x64. - * - Hashes with an asterisk are cryptographic. Note that MD5 is non-cryptographic - * by modern standards. - * - Small data velocity is a rough average of algorithm's efficiency for small - * data. For more accurate information, see the wiki. - * - More benchmarks and strength tests are found on the wiki: - * https://github.com/Cyan4973/xxHash/wiki - * - * Usage - * ------ - * All xxHash variants use a similar API. Changing the algorithm is a trivial - * substitution. - * - * @pre - * For functions which take an input and length parameter, the following - * requirements are assumed: - * - The range from [`input`, `input + length`) is valid, readable memory. - * - The only exception is if the `length` is `0`, `input` may be `NULL`. - * - For C++, the objects must have the *TriviallyCopyable* property, as the - * functions access bytes directly as if it was an array of `unsigned char`. - * - * @anchor single_shot_example - * **Single Shot** - * - * These functions are stateless functions which hash a contiguous block of memory, - * immediately returning the result. They are the easiest and usually the fastest - * option. - * - * XXH32(), XXH64(), XXH3_64bits(), XXH3_128bits() - * - * @code{.c} - * #include - * #include "xxhash.h" - * - * // Example for a function which hashes a null terminated string with XXH32(). - * XXH32_hash_t hash_string(const char* string, XXH32_hash_t seed) - * { - * // NULL pointers are only valid if the length is zero - * size_t length = (string == NULL) ? 0 : strlen(string); - * return XXH32(string, length, seed); - * } - * @endcode - * - * @anchor streaming_example - * **Streaming** - * - * These groups of functions allow incremental hashing of unknown size, even - * more than what would fit in a size_t. - * - * XXH32_reset(), XXH64_reset(), XXH3_64bits_reset(), XXH3_128bits_reset() - * - * @code{.c} - * #include - * #include - * #include "xxhash.h" - * // Example for a function which hashes a FILE incrementally with XXH3_64bits(). - * XXH64_hash_t hashFile(FILE* f) - * { - * // Allocate a state struct. Do not just use malloc() or new. - * XXH3_state_t* state = XXH3_createState(); - * assert(state != NULL && "Out of memory!"); - * // Reset the state to start a new hashing session. - * XXH3_64bits_reset(state); - * char buffer[4096]; - * size_t count; - * // Read the file in chunks - * while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0) { - * // Run update() as many times as necessary to process the data - * XXH3_64bits_update(state, buffer, count); - * } - * // Retrieve the finalized hash. This will not change the state. - * XXH64_hash_t result = XXH3_64bits_digest(state); - * // Free the state. Do not use free(). - * XXH3_freeState(state); - * return result; - * } - * @endcode - * - * @file xxhash.h - * xxHash prototypes and implementation - */ - -#if defined (__cplusplus) -extern "C" { -#endif - -/* **************************** - * INLINE mode - ******************************/ -/*! - * @defgroup public Public API - * Contains details on the public xxHash functions. - * @{ - */ -#ifdef XXH_DOXYGEN -/*! - * @brief Exposes the implementation and marks all functions as `inline`. - * - * Use these build macros to inline xxhash into the target unit. - * Inlining improves performance on small inputs, especially when the length is - * expressed as a compile-time constant: - * - * https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html - * - * It also keeps xxHash symbols private to the unit, so they are not exported. - * - * Usage: - * @code{.c} - * #define XXH_INLINE_ALL - * #include "xxhash.h" - * @endcode - * Do not compile and link xxhash.o as a separate object, as it is not useful. - */ -# define XXH_INLINE_ALL -# undef XXH_INLINE_ALL -/*! - * @brief Exposes the implementation without marking functions as inline. - */ -# define XXH_PRIVATE_API -# undef XXH_PRIVATE_API -/*! - * @brief Emulate a namespace by transparently prefixing all symbols. - * - * If you want to include _and expose_ xxHash functions from within your own - * library, but also want to avoid symbol collisions with other libraries which - * may also include xxHash, you can use @ref XXH_NAMESPACE to automatically prefix - * any public symbol from xxhash library with the value of @ref XXH_NAMESPACE - * (therefore, avoid empty or numeric values). - * - * Note that no change is required within the calling program as long as it - * includes `xxhash.h`: Regular symbol names will be automatically translated - * by this header. - */ -# define XXH_NAMESPACE /* YOUR NAME HERE */ -# undef XXH_NAMESPACE -#endif - -#if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \ - && !defined(XXH_INLINE_ALL_31684351384) - /* this section should be traversed only once */ -# define XXH_INLINE_ALL_31684351384 - /* give access to the advanced API, required to compile implementations */ -# undef XXH_STATIC_LINKING_ONLY /* avoid macro redef */ -# define XXH_STATIC_LINKING_ONLY - /* make all functions private */ -# undef XXH_PUBLIC_API -# if defined(__GNUC__) -# define XXH_PUBLIC_API static __inline __attribute__((unused)) -# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -# define XXH_PUBLIC_API static inline -# elif defined(_MSC_VER) -# define XXH_PUBLIC_API static __inline -# else - /* note: this version may generate warnings for unused static functions */ -# define XXH_PUBLIC_API static -# endif - - /* - * This part deals with the special case where a unit wants to inline xxHash, - * but "xxhash.h" has previously been included without XXH_INLINE_ALL, - * such as part of some previously included *.h header file. - * Without further action, the new include would just be ignored, - * and functions would effectively _not_ be inlined (silent failure). - * The following macros solve this situation by prefixing all inlined names, - * avoiding naming collision with previous inclusions. - */ - /* Before that, we unconditionally #undef all symbols, - * in case they were already defined with XXH_NAMESPACE. - * They will then be redefined for XXH_INLINE_ALL - */ -# undef XXH_versionNumber - /* XXH32 */ -# undef XXH32 -# undef XXH32_createState -# undef XXH32_freeState -# undef XXH32_reset -# undef XXH32_update -# undef XXH32_digest -# undef XXH32_copyState -# undef XXH32_canonicalFromHash -# undef XXH32_hashFromCanonical - /* XXH64 */ -# undef XXH64 -# undef XXH64_createState -# undef XXH64_freeState -# undef XXH64_reset -# undef XXH64_update -# undef XXH64_digest -# undef XXH64_copyState -# undef XXH64_canonicalFromHash -# undef XXH64_hashFromCanonical - /* XXH3_64bits */ -# undef XXH3_64bits -# undef XXH3_64bits_withSecret -# undef XXH3_64bits_withSeed -# undef XXH3_64bits_withSecretandSeed -# undef XXH3_createState -# undef XXH3_freeState -# undef XXH3_copyState -# undef XXH3_64bits_reset -# undef XXH3_64bits_reset_withSeed -# undef XXH3_64bits_reset_withSecret -# undef XXH3_64bits_update -# undef XXH3_64bits_digest -# undef XXH3_generateSecret - /* XXH3_128bits */ -# undef XXH128 -# undef XXH3_128bits -# undef XXH3_128bits_withSeed -# undef XXH3_128bits_withSecret -# undef XXH3_128bits_reset -# undef XXH3_128bits_reset_withSeed -# undef XXH3_128bits_reset_withSecret -# undef XXH3_128bits_reset_withSecretandSeed -# undef XXH3_128bits_update -# undef XXH3_128bits_digest -# undef XXH128_isEqual -# undef XXH128_cmp -# undef XXH128_canonicalFromHash -# undef XXH128_hashFromCanonical - /* Finally, free the namespace itself */ -# undef XXH_NAMESPACE - - /* employ the namespace for XXH_INLINE_ALL */ -# define XXH_NAMESPACE XXH_INLINE_ - /* - * Some identifiers (enums, type names) are not symbols, - * but they must nonetheless be renamed to avoid redeclaration. - * Alternative solution: do not redeclare them. - * However, this requires some #ifdefs, and has a more dispersed impact. - * Meanwhile, renaming can be achieved in a single place. - */ -# define XXH_IPREF(Id) XXH_NAMESPACE ## Id -# define XXH_OK XXH_IPREF(XXH_OK) -# define XXH_ERROR XXH_IPREF(XXH_ERROR) -# define XXH_errorcode XXH_IPREF(XXH_errorcode) -# define XXH32_canonical_t XXH_IPREF(XXH32_canonical_t) -# define XXH64_canonical_t XXH_IPREF(XXH64_canonical_t) -# define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t) -# define XXH32_state_s XXH_IPREF(XXH32_state_s) -# define XXH32_state_t XXH_IPREF(XXH32_state_t) -# define XXH64_state_s XXH_IPREF(XXH64_state_s) -# define XXH64_state_t XXH_IPREF(XXH64_state_t) -# define XXH3_state_s XXH_IPREF(XXH3_state_s) -# define XXH3_state_t XXH_IPREF(XXH3_state_t) -# define XXH128_hash_t XXH_IPREF(XXH128_hash_t) - /* Ensure the header is parsed again, even if it was previously included */ -# undef XXHASH_H_5627135585666179 -# undef XXHASH_H_STATIC_13879238742 -#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ - -/* **************************************************************** - * Stable API - *****************************************************************/ -#ifndef XXHASH_H_5627135585666179 -#define XXHASH_H_5627135585666179 1 - -/*! @brief Marks a global symbol. */ -#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) -# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) -# ifdef XXH_EXPORT -# define XXH_PUBLIC_API __declspec(dllexport) -# elif XXH_IMPORT -# define XXH_PUBLIC_API __declspec(dllimport) -# endif -# else -# define XXH_PUBLIC_API /* do nothing */ -# endif -#endif - -#ifdef XXH_NAMESPACE -# define XXH_CAT(A,B) A##B -# define XXH_NAME2(A,B) XXH_CAT(A,B) -# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) -/* XXH32 */ -# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) -# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) -# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) -# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) -# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) -# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) -# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) -# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) -# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) -/* XXH64 */ -# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) -# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) -# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) -# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) -# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) -# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) -# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) -# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) -# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) -/* XXH3_64bits */ -# define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits) -# define XXH3_64bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecret) -# define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed) -# define XXH3_64bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecretandSeed) -# define XXH3_createState XXH_NAME2(XXH_NAMESPACE, XXH3_createState) -# define XXH3_freeState XXH_NAME2(XXH_NAMESPACE, XXH3_freeState) -# define XXH3_copyState XXH_NAME2(XXH_NAMESPACE, XXH3_copyState) -# define XXH3_64bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset) -# define XXH3_64bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSeed) -# define XXH3_64bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecret) -# define XXH3_64bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecretandSeed) -# define XXH3_64bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_update) -# define XXH3_64bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_digest) -# define XXH3_generateSecret XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret) -# define XXH3_generateSecret_fromSeed XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret_fromSeed) -/* XXH3_128bits */ -# define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128) -# define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits) -# define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed) -# define XXH3_128bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecret) -# define XXH3_128bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecretandSeed) -# define XXH3_128bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset) -# define XXH3_128bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSeed) -# define XXH3_128bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecret) -# define XXH3_128bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecretandSeed) -# define XXH3_128bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_update) -# define XXH3_128bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_digest) -# define XXH128_isEqual XXH_NAME2(XXH_NAMESPACE, XXH128_isEqual) -# define XXH128_cmp XXH_NAME2(XXH_NAMESPACE, XXH128_cmp) -# define XXH128_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH128_canonicalFromHash) -# define XXH128_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH128_hashFromCanonical) -#endif - - -/* ************************************* -* Compiler specifics -***************************************/ - -/* specific declaration modes for Windows */ -#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) -# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) -# ifdef XXH_EXPORT -# define XXH_PUBLIC_API __declspec(dllexport) -# elif XXH_IMPORT -# define XXH_PUBLIC_API __declspec(dllimport) -# endif -# else -# define XXH_PUBLIC_API /* do nothing */ -# endif -#endif - -#if defined (__GNUC__) -# define XXH_CONSTF __attribute__((const)) -# define XXH_PUREF __attribute__((pure)) -# define XXH_MALLOCF __attribute__((malloc)) -#else -# define XXH_CONSTF /* disable */ -# define XXH_PUREF -# define XXH_MALLOCF -#endif - -/* ************************************* -* Version -***************************************/ -#define XXH_VERSION_MAJOR 0 -#define XXH_VERSION_MINOR 8 -#define XXH_VERSION_RELEASE 1 -/*! @brief Version number, encoded as two digits each */ -#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) - -/*! - * @brief Obtains the xxHash version. - * - * This is mostly useful when xxHash is compiled as a shared library, - * since the returned value comes from the library, as opposed to header file. - * - * @return @ref XXH_VERSION_NUMBER of the invoked library. - */ -XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void); - - -/* **************************** -* Common basic types -******************************/ -#include /* size_t */ -/*! - * @brief Exit code for the streaming API. - */ -typedef enum { - XXH_OK = 0, /*!< OK */ - XXH_ERROR /*!< Error */ -} XXH_errorcode; - - -/*-********************************************************************** -* 32-bit hash -************************************************************************/ -#if defined(XXH_DOXYGEN) /* Don't show include */ -/*! - * @brief An unsigned 32-bit integer. - * - * Not necessarily defined to `uint32_t` but functionally equivalent. - */ -typedef uint32_t XXH32_hash_t; - -#elif !defined (__VMS) \ - && (defined (__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - typedef uint32_t XXH32_hash_t; - -#else -# include -# if UINT_MAX == 0xFFFFFFFFUL - typedef unsigned int XXH32_hash_t; -# elif ULONG_MAX == 0xFFFFFFFFUL - typedef unsigned long XXH32_hash_t; -# else -# error "unsupported platform: need a 32-bit type" -# endif -#endif - -/*! - * @} - * - * @defgroup XXH32_family XXH32 family - * @ingroup public - * Contains functions used in the classic 32-bit xxHash algorithm. - * - * @note - * XXH32 is useful for older platforms, with no or poor 64-bit performance. - * Note that the @ref XXH3_family provides competitive speed for both 32-bit - * and 64-bit systems, and offers true 64/128 bit hash results. - * - * @see @ref XXH64_family, @ref XXH3_family : Other xxHash families - * @see @ref XXH32_impl for implementation details - * @{ - */ - -/*! - * @brief Calculates the 32-bit hash of @p input using xxHash32. - * - * Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark): 5.4 GB/s - * - * See @ref single_shot_example "Single Shot Example" for an example. - * - * @param input The block of data to be hashed, at least @p length bytes in size. - * @param length The length of @p input, in bytes. - * @param seed The 32-bit seed to alter the hash's output predictably. - * - * @pre - * The memory between @p input and @p input + @p length must be valid, - * readable, contiguous memory. However, if @p length is `0`, @p input may be - * `NULL`. In C++, this also must be *TriviallyCopyable*. - * - * @return The calculated 32-bit hash value. - * - * @see - * XXH64(), XXH3_64bits_withSeed(), XXH3_128bits_withSeed(), XXH128(): - * Direct equivalents for the other variants of xxHash. - * @see - * XXH32_createState(), XXH32_update(), XXH32_digest(): Streaming version. - */ -XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed); - -#ifndef XXH_NO_STREAM -/*! - * Streaming functions generate the xxHash value from an incremental input. - * This method is slower than single-call functions, due to state management. - * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. - * - * An XXH state must first be allocated using `XXH*_createState()`. - * - * Start a new hash by initializing the state with a seed using `XXH*_reset()`. - * - * Then, feed the hash state by calling `XXH*_update()` as many times as necessary. - * - * The function returns an error code, with 0 meaning OK, and any other value - * meaning there is an error. - * - * Finally, a hash value can be produced anytime, by using `XXH*_digest()`. - * This function returns the nn-bits hash as an int or long long. - * - * It's still possible to continue inserting input into the hash state after a - * digest, and generate new hash values later on by invoking `XXH*_digest()`. - * - * When done, release the state using `XXH*_freeState()`. - * - * @see streaming_example at the top of @ref xxhash.h for an example. - */ - -/*! - * @typedef struct XXH32_state_s XXH32_state_t - * @brief The opaque state struct for the XXH32 streaming API. - * - * @see XXH32_state_s for details. - */ -typedef struct XXH32_state_s XXH32_state_t; - -/*! - * @brief Allocates an @ref XXH32_state_t. - * - * Must be freed with XXH32_freeState(). - * @return An allocated XXH32_state_t on success, `NULL` on failure. - */ -XXH_PUBLIC_API XXH_MALLOCF XXH32_state_t* XXH32_createState(void); -/*! - * @brief Frees an @ref XXH32_state_t. - * - * Must be allocated with XXH32_createState(). - * @param statePtr A pointer to an @ref XXH32_state_t allocated with @ref XXH32_createState(). - * @return XXH_OK. - */ -XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); -/*! - * @brief Copies one @ref XXH32_state_t to another. - * - * @param dst_state The state to copy to. - * @param src_state The state to copy from. - * @pre - * @p dst_state and @p src_state must not be `NULL` and must not overlap. - */ -XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); - -/*! - * @brief Resets an @ref XXH32_state_t to begin a new hash. - * - * This function resets and seeds a state. Call it before @ref XXH32_update(). - * - * @param statePtr The state struct to reset. - * @param seed The 32-bit seed to alter the hash result predictably. - * - * @pre - * @p statePtr must not be `NULL`. - * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. - */ -XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, XXH32_hash_t seed); - -/*! - * @brief Consumes a block of @p input to an @ref XXH32_state_t. - * - * Call this to incrementally consume blocks of data. - * - * @param statePtr The state struct to update. - * @param input The block of data to be hashed, at least @p length bytes in size. - * @param length The length of @p input, in bytes. - * - * @pre - * @p statePtr must not be `NULL`. - * @pre - * The memory between @p input and @p input + @p length must be valid, - * readable, contiguous memory. However, if @p length is `0`, @p input may be - * `NULL`. In C++, this also must be *TriviallyCopyable*. - * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. - */ -XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); - -/*! - * @brief Returns the calculated hash value from an @ref XXH32_state_t. - * - * @note - * Calling XXH32_digest() will not affect @p statePtr, so you can update, - * digest, and update again. - * - * @param statePtr The state struct to calculate the hash from. - * - * @pre - * @p statePtr must not be `NULL`. - * - * @return The calculated xxHash32 value from that state. - */ -XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); -#endif /* !XXH_NO_STREAM */ - -/******* Canonical representation *******/ - -/* - * The default return values from XXH functions are unsigned 32 and 64 bit - * integers. - * This the simplest and fastest format for further post-processing. - * - * However, this leaves open the question of what is the order on the byte level, - * since little and big endian conventions will store the same number differently. - * - * The canonical representation settles this issue by mandating big-endian - * convention, the same convention as human-readable numbers (large digits first). - * - * When writing hash values to storage, sending them over a network, or printing - * them, it's highly recommended to use the canonical representation to ensure - * portability across a wider range of systems, present and future. - * - * The following functions allow transformation of hash values to and from - * canonical format. - */ - -/*! - * @brief Canonical (big endian) representation of @ref XXH32_hash_t. - */ -typedef struct { - unsigned char digest[4]; /*!< Hash bytes, big endian */ -} XXH32_canonical_t; - -/*! - * @brief Converts an @ref XXH32_hash_t to a big endian @ref XXH32_canonical_t. - * - * @param dst The @ref XXH32_canonical_t pointer to be stored to. - * @param hash The @ref XXH32_hash_t to be converted. - * - * @pre - * @p dst must not be `NULL`. - */ -XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); - -/*! - * @brief Converts an @ref XXH32_canonical_t to a native @ref XXH32_hash_t. - * - * @param src The @ref XXH32_canonical_t to convert. - * - * @pre - * @p src must not be `NULL`. - * - * @return The converted hash. - */ -XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); - - -#ifdef __has_attribute -# define XXH_HAS_ATTRIBUTE(x) __has_attribute(x) -#else -# define XXH_HAS_ATTRIBUTE(x) 0 -#endif - -/* C-language Attributes are added in C23. */ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute) -# define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) -#else -# define XXH_HAS_C_ATTRIBUTE(x) 0 -#endif - -#if defined(__cplusplus) && defined(__has_cpp_attribute) -# define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) -#else -# define XXH_HAS_CPP_ATTRIBUTE(x) 0 -#endif - -/* - * Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute - * introduced in CPP17 and C23. - * CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough - * C23 : https://en.cppreference.com/w/c/language/attributes/fallthrough - */ -#if XXH_HAS_C_ATTRIBUTE(fallthrough) || XXH_HAS_CPP_ATTRIBUTE(fallthrough) -# define XXH_FALLTHROUGH [[fallthrough]] -#elif XXH_HAS_ATTRIBUTE(__fallthrough__) -# define XXH_FALLTHROUGH __attribute__ ((__fallthrough__)) -#else -# define XXH_FALLTHROUGH /* fallthrough */ -#endif - -/*! - * @} - * @ingroup public - * @{ - */ - -#ifndef XXH_NO_LONG_LONG -/*-********************************************************************** -* 64-bit hash -************************************************************************/ -#if defined(XXH_DOXYGEN) /* don't include */ -/*! - * @brief An unsigned 64-bit integer. - * - * Not necessarily defined to `uint64_t` but functionally equivalent. - */ -typedef uint64_t XXH64_hash_t; -#elif !defined (__VMS) \ - && (defined (__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - typedef uint64_t XXH64_hash_t; -#else -# include -# if defined(__LP64__) && ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL - /* LP64 ABI says uint64_t is unsigned long */ - typedef unsigned long XXH64_hash_t; -# else - /* the following type must have a width of 64-bit */ - typedef unsigned long long XXH64_hash_t; -# endif -#endif - -/*! - * @} - * - * @defgroup XXH64_family XXH64 family - * @ingroup public - * @{ - * Contains functions used in the classic 64-bit xxHash algorithm. - * - * @note - * XXH3 provides competitive speed for both 32-bit and 64-bit systems, - * and offers true 64/128 bit hash results. - * It provides better speed for systems with vector processing capabilities. - */ - -/*! - * @brief Calculates the 64-bit hash of @p input using xxHash64. - * - * This function usually runs faster on 64-bit systems, but slower on 32-bit - * systems (see benchmark). - * - * @param input The block of data to be hashed, at least @p length bytes in size. - * @param length The length of @p input, in bytes. - * @param seed The 64-bit seed to alter the hash's output predictably. - * - * @pre - * The memory between @p input and @p input + @p length must be valid, - * readable, contiguous memory. However, if @p length is `0`, @p input may be - * `NULL`. In C++, this also must be *TriviallyCopyable*. - * - * @return The calculated 64-bit hash. - * - * @see - * XXH32(), XXH3_64bits_withSeed(), XXH3_128bits_withSeed(), XXH128(): - * Direct equivalents for the other variants of xxHash. - * @see - * XXH64_createState(), XXH64_update(), XXH64_digest(): Streaming version. - */ -XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(const void* input, size_t length, XXH64_hash_t seed); - -/******* Streaming *******/ -#ifndef XXH_NO_STREAM -/*! - * @brief The opaque state struct for the XXH64 streaming API. - * - * @see XXH64_state_s for details. - */ -typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ -XXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void); -XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state); - -XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, XXH64_hash_t seed); -XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); -#endif /* !XXH_NO_STREAM */ -/******* Canonical representation *******/ -typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t; -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); -XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); - -#ifndef XXH_NO_XXH3 - -/*! - * @} - * ************************************************************************ - * @defgroup XXH3_family XXH3 family - * @ingroup public - * @{ - * - * XXH3 is a more recent hash algorithm featuring: - * - Improved speed for both small and large inputs - * - True 64-bit and 128-bit outputs - * - SIMD acceleration - * - Improved 32-bit viability - * - * Speed analysis methodology is explained here: - * - * https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html - * - * Compared to XXH64, expect XXH3 to run approximately - * ~2x faster on large inputs and >3x faster on small ones, - * exact differences vary depending on platform. - * - * XXH3's speed benefits greatly from SIMD and 64-bit arithmetic, - * but does not require it. - * Most 32-bit and 64-bit targets that can run XXH32 smoothly can run XXH3 - * at competitive speeds, even without vector support. Further details are - * explained in the implementation. - * - * Optimized implementations are provided for AVX512, AVX2, SSE2, NEON, POWER8, - * ZVector and scalar targets. This can be controlled via the @ref XXH_VECTOR - * macro. For the x86 family, an automatic dispatcher is included separately - * in @ref xxh_x86dispatch.c. - * - * XXH3 implementation is portable: - * it has a generic C90 formulation that can be compiled on any platform, - * all implementations generage exactly the same hash value on all platforms. - * Starting from v0.8.0, it's also labelled "stable", meaning that - * any future version will also generate the same hash value. - * - * XXH3 offers 2 variants, _64bits and _128bits. - * - * When only 64 bits are needed, prefer invoking the _64bits variant, as it - * reduces the amount of mixing, resulting in faster speed on small inputs. - * It's also generally simpler to manipulate a scalar return type than a struct. - * - * The API supports one-shot hashing, streaming mode, and custom secrets. - */ -/*-********************************************************************** -* XXH3 64-bit variant -************************************************************************/ - -/*! - * @brief 64-bit unseeded variant of XXH3. - * - * This is equivalent to @ref XXH3_64bits_withSeed() with a seed of 0, however - * it may have slightly better performance due to constant propagation of the - * defaults. - * - * @see - * XXH32(), XXH64(), XXH3_128bits(): equivalent for the other xxHash algorithms - * @see - * XXH3_64bits_withSeed(), XXH3_64bits_withSecret(): other seeding variants - * @see - * XXH3_64bits_reset(), XXH3_64bits_update(), XXH3_64bits_digest(): Streaming version. - */ -XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(const void* input, size_t length); - -/*! - * @brief 64-bit seeded variant of XXH3 - * - * This variant generates a custom secret on the fly based on default secret - * altered using the `seed` value. - * - * While this operation is decently fast, note that it's not completely free. - * - * @note - * seed == 0 produces the same results as @ref XXH3_64bits(). - * - * @param input The data to hash - * @param length The length - * @param seed The 64-bit seed to alter the state. - */ -XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(const void* input, size_t length, XXH64_hash_t seed); - -/*! - * The bare minimum size for a custom secret. - * - * @see - * XXH3_64bits_withSecret(), XXH3_64bits_reset_withSecret(), - * XXH3_128bits_withSecret(), XXH3_128bits_reset_withSecret(). - */ -#define XXH3_SECRET_SIZE_MIN 136 - -/*! - * @brief 64-bit variant of XXH3 with a custom "secret". - * - * It's possible to provide any blob of bytes as a "secret" to generate the hash. - * This makes it more difficult for an external actor to prepare an intentional collision. - * The main condition is that secretSize *must* be large enough (>= XXH3_SECRET_SIZE_MIN). - * However, the quality of the secret impacts the dispersion of the hash algorithm. - * Therefore, the secret _must_ look like a bunch of random bytes. - * Avoid "trivial" or structured data such as repeated sequences or a text document. - * Whenever in doubt about the "randomness" of the blob of bytes, - * consider employing "XXH3_generateSecret()" instead (see below). - * It will generate a proper high entropy secret derived from the blob of bytes. - * Another advantage of using XXH3_generateSecret() is that - * it guarantees that all bits within the initial blob of bytes - * will impact every bit of the output. - * This is not necessarily the case when using the blob of bytes directly - * because, when hashing _small_ inputs, only a portion of the secret is employed. - */ -XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(const void* data, size_t len, const void* secret, size_t secretSize); - - -/******* Streaming *******/ -#ifndef XXH_NO_STREAM -/* - * Streaming requires state maintenance. - * This operation costs memory and CPU. - * As a consequence, streaming is slower than one-shot hashing. - * For better performance, prefer one-shot functions whenever applicable. - */ - -/*! - * @brief The state struct for the XXH3 streaming API. - * - * @see XXH3_state_s for details. - */ -typedef struct XXH3_state_s XXH3_state_t; -XXH_PUBLIC_API XXH_MALLOCF XXH3_state_t* XXH3_createState(void); -XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr); -XXH_PUBLIC_API void XXH3_copyState(XXH3_state_t* dst_state, const XXH3_state_t* src_state); - -/* - * XXH3_64bits_reset(): - * Initialize with default parameters. - * digest will be equivalent to `XXH3_64bits()`. - */ -XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH3_state_t* statePtr); -/* - * XXH3_64bits_reset_withSeed(): - * Generate a custom secret from `seed`, and store it into `statePtr`. - * digest will be equivalent to `XXH3_64bits_withSeed()`. - */ -XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed); -/*! - * XXH3_64bits_reset_withSecret(): - * `secret` is referenced, it _must outlive_ the hash streaming session. - * Similar to one-shot API, `secretSize` must be >= `XXH3_SECRET_SIZE_MIN`, - * and the quality of produced hash values depends on secret's entropy - * (secret's content should look like a bunch of random bytes). - * When in doubt about the randomness of a candidate `secret`, - * consider employing `XXH3_generateSecret()` instead (see below). - */ -XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize); - -XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH3_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_digest (const XXH3_state_t* statePtr); -#endif /* !XXH_NO_STREAM */ - -/* note : canonical representation of XXH3 is the same as XXH64 - * since they both produce XXH64_hash_t values */ - - -/*-********************************************************************** -* XXH3 128-bit variant -************************************************************************/ - -/*! - * @brief The return value from 128-bit hashes. - * - * Stored in little endian order, although the fields themselves are in native - * endianness. - */ -typedef struct { - XXH64_hash_t low64; /*!< `value & 0xFFFFFFFFFFFFFFFF` */ - XXH64_hash_t high64; /*!< `value >> 64` */ -} XXH128_hash_t; - -/*! - * @brief Unseeded 128-bit variant of XXH3 - * - * The 128-bit variant of XXH3 has more strength, but it has a bit of overhead - * for shorter inputs. - * - * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of 0, however - * it may have slightly better performance due to constant propagation of the - * defaults. - * - * @see - * XXH32(), XXH64(), XXH3_64bits(): equivalent for the other xxHash algorithms - * @see - * XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants - * @see - * XXH3_128bits_reset(), XXH3_128bits_update(), XXH3_128bits_digest(): Streaming version. - */ -XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(const void* data, size_t len); -/*! @brief Seeded 128-bit variant of XXH3. @see XXH3_64bits_withSeed(). */ -XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(const void* data, size_t len, XXH64_hash_t seed); -/*! @brief Custom secret 128-bit variant of XXH3. @see XXH3_64bits_withSecret(). */ -XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(const void* data, size_t len, const void* secret, size_t secretSize); - -/******* Streaming *******/ -#ifndef XXH_NO_STREAM -/* - * Streaming requires state maintenance. - * This operation costs memory and CPU. - * As a consequence, streaming is slower than one-shot hashing. - * For better performance, prefer one-shot functions whenever applicable. - * - * XXH3_128bits uses the same XXH3_state_t as XXH3_64bits(). - * Use already declared XXH3_createState() and XXH3_freeState(). - * - * All reset and streaming functions have same meaning as their 64-bit counterpart. - */ - -XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH3_state_t* statePtr); -XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed); -XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize); - -XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH3_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (const XXH3_state_t* statePtr); -#endif /* !XXH_NO_STREAM */ - -/* Following helper functions make it possible to compare XXH128_hast_t values. - * Since XXH128_hash_t is a structure, this capability is not offered by the language. - * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */ - -/*! - * XXH128_isEqual(): - * Return: 1 if `h1` and `h2` are equal, 0 if they are not. - */ -XXH_PUBLIC_API XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2); - -/*! - * @brief Compares two @ref XXH128_hash_t - * This comparator is compatible with stdlib's `qsort()`/`bsearch()`. - * - * @return: >0 if *h128_1 > *h128_2 - * =0 if *h128_1 == *h128_2 - * <0 if *h128_1 < *h128_2 - */ -XXH_PUBLIC_API XXH_PUREF int XXH128_cmp(const void* h128_1, const void* h128_2); - - -/******* Canonical representation *******/ -typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t; -XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH128_canonical_t* dst, XXH128_hash_t hash); -XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(const XXH128_canonical_t* src); - - -#endif /* !XXH_NO_XXH3 */ -#endif /* XXH_NO_LONG_LONG */ - -/*! - * @} - */ -#endif /* XXHASH_H_5627135585666179 */ - - - -#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) -#define XXHASH_H_STATIC_13879238742 -/* **************************************************************************** - * This section contains declarations which are not guaranteed to remain stable. - * They may change in future versions, becoming incompatible with a different - * version of the library. - * These declarations should only be used with static linking. - * Never use them in association with dynamic linking! - ***************************************************************************** */ - -/* - * These definitions are only present to allow static allocation - * of XXH states, on stack or in a struct, for example. - * Never **ever** access their members directly. - */ - -/*! - * @internal - * @brief Structure for XXH32 streaming API. - * - * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, - * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is - * an opaque type. This allows fields to safely be changed. - * - * Typedef'd to @ref XXH32_state_t. - * Do not access the members of this struct directly. - * @see XXH64_state_s, XXH3_state_s - */ -struct XXH32_state_s { - XXH32_hash_t total_len_32; /*!< Total length hashed, modulo 2^32 */ - XXH32_hash_t large_len; /*!< Whether the hash is >= 16 (handles @ref total_len_32 overflow) */ - XXH32_hash_t v[4]; /*!< Accumulator lanes */ - XXH32_hash_t mem32[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[16]. */ - XXH32_hash_t memsize; /*!< Amount of data in @ref mem32 */ - XXH32_hash_t reserved; /*!< Reserved field. Do not read nor write to it. */ -}; /* typedef'd to XXH32_state_t */ - - -#ifndef XXH_NO_LONG_LONG /* defined when there is no 64-bit support */ - -/*! - * @internal - * @brief Structure for XXH64 streaming API. - * - * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, - * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is - * an opaque type. This allows fields to safely be changed. - * - * Typedef'd to @ref XXH64_state_t. - * Do not access the members of this struct directly. - * @see XXH32_state_s, XXH3_state_s - */ -struct XXH64_state_s { - XXH64_hash_t total_len; /*!< Total length hashed. This is always 64-bit. */ - XXH64_hash_t v[4]; /*!< Accumulator lanes */ - XXH64_hash_t mem64[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */ - XXH32_hash_t memsize; /*!< Amount of data in @ref mem64 */ - XXH32_hash_t reserved32; /*!< Reserved field, needed for padding anyways*/ - XXH64_hash_t reserved64; /*!< Reserved field. Do not read or write to it. */ -}; /* typedef'd to XXH64_state_t */ - -#ifndef XXH_NO_XXH3 - -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* >= C11 */ -# include -# define XXH_ALIGN(n) alignas(n) -#elif defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */ -/* In C++ alignas() is a keyword */ -# define XXH_ALIGN(n) alignas(n) -#elif defined(__GNUC__) -# define XXH_ALIGN(n) __attribute__ ((aligned(n))) -#elif defined(_MSC_VER) -# define XXH_ALIGN(n) __declspec(align(n)) -#else -# define XXH_ALIGN(n) /* disabled */ -#endif - -/* Old GCC versions only accept the attribute after the type in structures. */ -#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) /* C11+ */ \ - && ! (defined(__cplusplus) && (__cplusplus >= 201103L)) /* >= C++11 */ \ - && defined(__GNUC__) -# define XXH_ALIGN_MEMBER(align, type) type XXH_ALIGN(align) -#else -# define XXH_ALIGN_MEMBER(align, type) XXH_ALIGN(align) type -#endif - -/*! - * @brief The size of the internal XXH3 buffer. - * - * This is the optimal update size for incremental hashing. - * - * @see XXH3_64b_update(), XXH3_128b_update(). - */ -#define XXH3_INTERNALBUFFER_SIZE 256 - -/*! - * @brief Default size of the secret buffer (and @ref XXH3_kSecret). - * - * This is the size used in @ref XXH3_kSecret and the seeded functions. - * - * Not to be confused with @ref XXH3_SECRET_SIZE_MIN. - */ -#define XXH3_SECRET_DEFAULT_SIZE 192 - -/*! - * @internal - * @brief Structure for XXH3 streaming API. - * - * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, - * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. - * Otherwise it is an opaque type. - * Never use this definition in combination with dynamic library. - * This allows fields to safely be changed in the future. - * - * @note ** This structure has a strict alignment requirement of 64 bytes!! ** - * Do not allocate this with `malloc()` or `new`, - * it will not be sufficiently aligned. - * Use @ref XXH3_createState() and @ref XXH3_freeState(), or stack allocation. - * - * Typedef'd to @ref XXH3_state_t. - * Do never access the members of this struct directly. - * - * @see XXH3_INITSTATE() for stack initialization. - * @see XXH3_createState(), XXH3_freeState(). - * @see XXH32_state_s, XXH64_state_s - */ -struct XXH3_state_s { - XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]); - /*!< The 8 accumulators. See @ref XXH32_state_s::v and @ref XXH64_state_s::v */ - XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]); - /*!< Used to store a custom secret generated from a seed. */ - XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]); - /*!< The internal buffer. @see XXH32_state_s::mem32 */ - XXH32_hash_t bufferedSize; - /*!< The amount of memory in @ref buffer, @see XXH32_state_s::memsize */ - XXH32_hash_t useSeed; - /*!< Reserved field. Needed for padding on 64-bit. */ - size_t nbStripesSoFar; - /*!< Number or stripes processed. */ - XXH64_hash_t totalLen; - /*!< Total length hashed. 64-bit even on 32-bit targets. */ - size_t nbStripesPerBlock; - /*!< Number of stripes per block. */ - size_t secretLimit; - /*!< Size of @ref customSecret or @ref extSecret */ - XXH64_hash_t seed; - /*!< Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE() */ - XXH64_hash_t reserved64; - /*!< Reserved field. */ - const unsigned char* extSecret; - /*!< Reference to an external secret for the _withSecret variants, NULL - * for other variants. */ - /* note: there may be some padding at the end due to alignment on 64 bytes */ -}; /* typedef'd to XXH3_state_t */ - -#undef XXH_ALIGN_MEMBER - -/*! - * @brief Initializes a stack-allocated `XXH3_state_s`. - * - * When the @ref XXH3_state_t structure is merely emplaced on stack, - * it should be initialized with XXH3_INITSTATE() or a memset() - * in case its first reset uses XXH3_NNbits_reset_withSeed(). - * This init can be omitted if the first reset uses default or _withSecret mode. - * This operation isn't necessary when the state is created with XXH3_createState(). - * Note that this doesn't prepare the state for a streaming operation, - * it's still necessary to use XXH3_NNbits_reset*() afterwards. - */ -#define XXH3_INITSTATE(XXH3_state_ptr) { (XXH3_state_ptr)->seed = 0; } - - -/*! - * simple alias to pre-selected XXH3_128bits variant - */ -XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(const void* data, size_t len, XXH64_hash_t seed); - - -/* === Experimental API === */ -/* Symbols defined below must be considered tied to a specific library version. */ - -/*! - * XXH3_generateSecret(): - * - * Derive a high-entropy secret from any user-defined content, named customSeed. - * The generated secret can be used in combination with `*_withSecret()` functions. - * The `_withSecret()` variants are useful to provide a higher level of protection - * than 64-bit seed, as it becomes much more difficult for an external actor to - * guess how to impact the calculation logic. - * - * The function accepts as input a custom seed of any length and any content, - * and derives from it a high-entropy secret of length @p secretSize into an - * already allocated buffer @p secretBuffer. - * - * The generated secret can then be used with any `*_withSecret()` variant. - * The functions @ref XXH3_128bits_withSecret(), @ref XXH3_64bits_withSecret(), - * @ref XXH3_128bits_reset_withSecret() and @ref XXH3_64bits_reset_withSecret() - * are part of this list. They all accept a `secret` parameter - * which must be large enough for implementation reasons (>= @ref XXH3_SECRET_SIZE_MIN) - * _and_ feature very high entropy (consist of random-looking bytes). - * These conditions can be a high bar to meet, so @ref XXH3_generateSecret() can - * be employed to ensure proper quality. - * - * @p customSeed can be anything. It can have any size, even small ones, - * and its content can be anything, even "poor entropy" sources such as a bunch - * of zeroes. The resulting `secret` will nonetheless provide all required qualities. - * - * @pre - * - @p secretSize must be >= @ref XXH3_SECRET_SIZE_MIN - * - When @p customSeedSize > 0, supplying NULL as customSeed is undefined behavior. - * - * Example code: - * @code{.c} - * #include - * #include - * #include - * #define XXH_STATIC_LINKING_ONLY // expose unstable API - * #include "xxhash.h" - * // Hashes argv[2] using the entropy from argv[1]. - * int main(int argc, char* argv[]) - * { - * char secret[XXH3_SECRET_SIZE_MIN]; - * if (argv != 3) { return 1; } - * XXH3_generateSecret(secret, sizeof(secret), argv[1], strlen(argv[1])); - * XXH64_hash_t h = XXH3_64bits_withSecret( - * argv[2], strlen(argv[2]), - * secret, sizeof(secret) - * ); - * printf("%016llx\n", (unsigned long long) h); - * } - * @endcode - */ -XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(void* secretBuffer, size_t secretSize, const void* customSeed, size_t customSeedSize); - -/*! - * @brief Generate the same secret as the _withSeed() variants. - * - * The generated secret can be used in combination with - *`*_withSecret()` and `_withSecretandSeed()` variants. - * - * Example C++ `std::string` hash class: - * @code{.cpp} - * #include - * #define XXH_STATIC_LINKING_ONLY // expose unstable API - * #include "xxhash.h" - * // Slow, seeds each time - * class HashSlow { - * XXH64_hash_t seed; - * public: - * HashSlow(XXH64_hash_t s) : seed{s} {} - * size_t operator()(const std::string& x) const { - * return size_t{XXH3_64bits_withSeed(x.c_str(), x.length(), seed)}; - * } - * }; - * // Fast, caches the seeded secret for future uses. - * class HashFast { - * unsigned char secret[XXH3_SECRET_SIZE_MIN]; - * public: - * HashFast(XXH64_hash_t s) { - * XXH3_generateSecret_fromSeed(secret, seed); - * } - * size_t operator()(const std::string& x) const { - * return size_t{ - * XXH3_64bits_withSecret(x.c_str(), x.length(), secret, sizeof(secret)) - * }; - * } - * }; - * @endcode - * @param secretBuffer A writable buffer of @ref XXH3_SECRET_SIZE_MIN bytes - * @param seed The seed to seed the state. - */ -XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(void* secretBuffer, XXH64_hash_t seed); - -/*! - * These variants generate hash values using either - * @p seed for "short" keys (< XXH3_MIDSIZE_MAX = 240 bytes) - * or @p secret for "large" keys (>= XXH3_MIDSIZE_MAX). - * - * This generally benefits speed, compared to `_withSeed()` or `_withSecret()`. - * `_withSeed()` has to generate the secret on the fly for "large" keys. - * It's fast, but can be perceptible for "not so large" keys (< 1 KB). - * `_withSecret()` has to generate the masks on the fly for "small" keys, - * which requires more instructions than _withSeed() variants. - * Therefore, _withSecretandSeed variant combines the best of both worlds. - * - * When @p secret has been generated by XXH3_generateSecret_fromSeed(), - * this variant produces *exactly* the same results as `_withSeed()` variant, - * hence offering only a pure speed benefit on "large" input, - * by skipping the need to regenerate the secret for every large input. - * - * Another usage scenario is to hash the secret to a 64-bit hash value, - * for example with XXH3_64bits(), which then becomes the seed, - * and then employ both the seed and the secret in _withSecretandSeed(). - * On top of speed, an added benefit is that each bit in the secret - * has a 50% chance to swap each bit in the output, via its impact to the seed. - * - * This is not guaranteed when using the secret directly in "small data" scenarios, - * because only portions of the secret are employed for small data. - */ -XXH_PUBLIC_API XXH_PUREF XXH64_hash_t -XXH3_64bits_withSecretandSeed(const void* data, size_t len, - const void* secret, size_t secretSize, - XXH64_hash_t seed); -/*! @copydoc XXH3_64bits_withSecretandSeed() */ -XXH_PUBLIC_API XXH_PUREF XXH128_hash_t -XXH3_128bits_withSecretandSeed(const void* input, size_t length, - const void* secret, size_t secretSize, - XXH64_hash_t seed64); -#ifndef XXH_NO_STREAM -/*! @copydoc XXH3_64bits_withSecretandSeed() */ -XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_reset_withSecretandSeed(XXH3_state_t* statePtr, - const void* secret, size_t secretSize, - XXH64_hash_t seed64); -/*! @copydoc XXH3_64bits_withSecretandSeed() */ -XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, - const void* secret, size_t secretSize, - XXH64_hash_t seed64); -#endif /* !XXH_NO_STREAM */ - -#endif /* !XXH_NO_XXH3 */ -#endif /* XXH_NO_LONG_LONG */ -#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) -# define XXH_IMPLEMENTATION -#endif - -#endif /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */ - - -/* ======================================================================== */ -/* ======================================================================== */ -/* ======================================================================== */ - - -/*-********************************************************************** - * xxHash implementation - *-********************************************************************** - * xxHash's implementation used to be hosted inside xxhash.c. - * - * However, inlining requires implementation to be visible to the compiler, - * hence be included alongside the header. - * Previously, implementation was hosted inside xxhash.c, - * which was then #included when inlining was activated. - * This construction created issues with a few build and install systems, - * as it required xxhash.c to be stored in /include directory. - * - * xxHash implementation is now directly integrated within xxhash.h. - * As a consequence, xxhash.c is no longer needed in /include. - * - * xxhash.c is still available and is still useful. - * In a "normal" setup, when xxhash is not inlined, - * xxhash.h only exposes the prototypes and public symbols, - * while xxhash.c can be built into an object file xxhash.o - * which can then be linked into the final binary. - ************************************************************************/ - -#if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \ - || defined(XXH_IMPLEMENTATION) ) && !defined(XXH_IMPLEM_13a8737387) -# define XXH_IMPLEM_13a8737387 - -/* ************************************* -* Tuning parameters -***************************************/ - -/*! - * @defgroup tuning Tuning parameters - * @{ - * - * Various macros to control xxHash's behavior. - */ -#ifdef XXH_DOXYGEN -/*! - * @brief Define this to disable 64-bit code. - * - * Useful if only using the @ref XXH32_family and you have a strict C90 compiler. - */ -# define XXH_NO_LONG_LONG -# undef XXH_NO_LONG_LONG /* don't actually */ -/*! - * @brief Controls how unaligned memory is accessed. - * - * By default, access to unaligned memory is controlled by `memcpy()`, which is - * safe and portable. - * - * Unfortunately, on some target/compiler combinations, the generated assembly - * is sub-optimal. - * - * The below switch allow selection of a different access method - * in the search for improved performance. - * - * @par Possible options: - * - * - `XXH_FORCE_MEMORY_ACCESS=0` (default): `memcpy` - * @par - * Use `memcpy()`. Safe and portable. Note that most modern compilers will - * eliminate the function call and treat it as an unaligned access. - * - * - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((aligned(1)))` - * @par - * Depends on compiler extensions and is therefore not portable. - * This method is safe _if_ your compiler supports it, - * and *generally* as fast or faster than `memcpy`. - * - * - `XXH_FORCE_MEMORY_ACCESS=2`: Direct cast - * @par - * Casts directly and dereferences. This method doesn't depend on the - * compiler, but it violates the C standard as it directly dereferences an - * unaligned pointer. It can generate buggy code on targets which do not - * support unaligned memory accesses, but in some circumstances, it's the - * only known way to get the most performance. - * - * - `XXH_FORCE_MEMORY_ACCESS=3`: Byteshift - * @par - * Also portable. This can generate the best code on old compilers which don't - * inline small `memcpy()` calls, and it might also be faster on big-endian - * systems which lack a native byteswap instruction. However, some compilers - * will emit literal byteshifts even if the target supports unaligned access. - * . - * - * @warning - * Methods 1 and 2 rely on implementation-defined behavior. Use these with - * care, as what works on one compiler/platform/optimization level may cause - * another to read garbage data or even crash. - * - * See http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details. - * - * Prefer these methods in priority order (0 > 3 > 1 > 2) - */ -# define XXH_FORCE_MEMORY_ACCESS 0 - -/*! - * @def XXH_SIZE_OPT - * @brief Controls how much xxHash optimizes for size. - * - * xxHash, when compiled, tends to result in a rather large binary size. This - * is mostly due to heavy usage to forced inlining and constant folding of the - * @ref XXH3_family to increase performance. - * - * However, some developers prefer size over speed. This option can - * significantly reduce the size of the generated code. When using the `-Os` - * or `-Oz` options on GCC or Clang, this is defined to 1 by default, - * otherwise it is defined to 0. - * - * Most of these size optimizations can be controlled manually. - * - * This is a number from 0-2. - * - `XXH_SIZE_OPT` == 0: Default. xxHash makes no size optimizations. Speed - * comes first. - * - `XXH_SIZE_OPT` == 1: Default for `-Os` and `-Oz`. xxHash is more - * conservative and disables hacks that increase code size. It implies the - * options @ref XXH_NO_INLINE_HINTS == 1, @ref XXH_FORCE_ALIGN_CHECK == 0, - * and @ref XXH3_NEON_LANES == 8 if they are not already defined. - * - `XXH_SIZE_OPT` == 2: xxHash tries to make itself as small as possible. - * Performance may cry. For example, the single shot functions just use the - * streaming API. - */ -# define XXH_SIZE_OPT 0 - -/*! - * @def XXH_FORCE_ALIGN_CHECK - * @brief If defined to non-zero, adds a special path for aligned inputs (XXH32() - * and XXH64() only). - * - * This is an important performance trick for architectures without decent - * unaligned memory access performance. - * - * It checks for input alignment, and when conditions are met, uses a "fast - * path" employing direct 32-bit/64-bit reads, resulting in _dramatically - * faster_ read speed. - * - * The check costs one initial branch per hash, which is generally negligible, - * but not zero. - * - * Moreover, it's not useful to generate an additional code path if memory - * access uses the same instruction for both aligned and unaligned - * addresses (e.g. x86 and aarch64). - * - * In these cases, the alignment check can be removed by setting this macro to 0. - * Then the code will always use unaligned memory access. - * Align check is automatically disabled on x86, x64, ARM64, and some ARM chips - * which are platforms known to offer good unaligned memory accesses performance. - * - * It is also disabled by default when @ref XXH_SIZE_OPT >= 1. - * - * This option does not affect XXH3 (only XXH32 and XXH64). - */ -# define XXH_FORCE_ALIGN_CHECK 0 - -/*! - * @def XXH_NO_INLINE_HINTS - * @brief When non-zero, sets all functions to `static`. - * - * By default, xxHash tries to force the compiler to inline almost all internal - * functions. - * - * This can usually improve performance due to reduced jumping and improved - * constant folding, but significantly increases the size of the binary which - * might not be favorable. - * - * Additionally, sometimes the forced inlining can be detrimental to performance, - * depending on the architecture. - * - * XXH_NO_INLINE_HINTS marks all internal functions as static, giving the - * compiler full control on whether to inline or not. - * - * When not optimizing (-O0), using `-fno-inline` with GCC or Clang, or if - * @ref XXH_SIZE_OPT >= 1, this will automatically be defined. - */ -# define XXH_NO_INLINE_HINTS 0 - -/*! - * @def XXH32_ENDJMP - * @brief Whether to use a jump for `XXH32_finalize`. - * - * For performance, `XXH32_finalize` uses multiple branches in the finalizer. - * This is generally preferable for performance, - * but depending on exact architecture, a jmp may be preferable. - * - * This setting is only possibly making a difference for very small inputs. - */ -# define XXH32_ENDJMP 0 - -/*! - * @internal - * @brief Redefines old internal names. - * - * For compatibility with code that uses xxHash's internals before the names - * were changed to improve namespacing. There is no other reason to use this. - */ -# define XXH_OLD_NAMES -# undef XXH_OLD_NAMES /* don't actually use, it is ugly. */ - -/*! - * @def XXH_NO_STREAM - * @brief Disables the streaming API. - * - * When xxHash is not inlined and the streaming functions are not used, disabling - * the streaming functions can improve code size significantly, especially with - * the @ref XXH3_family which tends to make constant folded copies of itself. - */ -# define XXH_NO_STREAM -# undef XXH_NO_STREAM /* don't actually */ -#endif /* XXH_DOXYGEN */ -/*! - * @} - */ - -#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ - /* prefer __packed__ structures (method 1) for GCC - * < ARMv7 with unaligned access (e.g. Raspbian armhf) still uses byte shifting, so we use memcpy - * which for some reason does unaligned loads. */ -# if defined(__GNUC__) && !(defined(__ARM_ARCH) && __ARM_ARCH < 7 && defined(__ARM_FEATURE_UNALIGNED)) -# define XXH_FORCE_MEMORY_ACCESS 1 -# endif -#endif - -#ifndef XXH_SIZE_OPT - /* default to 1 for -Os or -Oz */ -# if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE_SIZE__) -# define XXH_SIZE_OPT 1 -# else -# define XXH_SIZE_OPT 0 -# endif -#endif - -#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ - /* don't check on sizeopt, x86, aarch64, or arm when unaligned access is available */ -# if XXH_SIZE_OPT >= 1 || \ - defined(__i386) || defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_FEATURE_UNALIGNED) \ - || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) || defined(_M_ARM) /* visual */ -# define XXH_FORCE_ALIGN_CHECK 0 -# else -# define XXH_FORCE_ALIGN_CHECK 1 -# endif -#endif - -#ifndef XXH_NO_INLINE_HINTS -# if XXH_SIZE_OPT >= 1 || defined(__NO_INLINE__) /* -O0, -fno-inline */ -# define XXH_NO_INLINE_HINTS 1 -# else -# define XXH_NO_INLINE_HINTS 0 -# endif -#endif - -#ifndef XXH32_ENDJMP -/* generally preferable for performance */ -# define XXH32_ENDJMP 0 -#endif - -/*! - * @defgroup impl Implementation - * @{ - */ - - -/* ************************************* -* Includes & Memory related functions -***************************************/ -#if defined(XXH_NO_STREAM) -/* nothing */ -#elif defined(XXH_NO_STDLIB) - -/* When requesting to disable any mention of stdlib, - * the library loses the ability to invoked malloc / free. - * In practice, it means that functions like `XXH*_createState()` - * will always fail, and return NULL. - * This flag is useful in situations where - * xxhash.h is integrated into some kernel, embedded or limited environment - * without access to dynamic allocation. - */ - -static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; } -static void XXH_free(void* p) { (void)p; } - -#else - -/* - * Modify the local functions below should you wish to use - * different memory routines for malloc() and free() - */ -#include - -/*! - * @internal - * @brief Modify this function to use a different routine than malloc(). - */ -static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); } - -/*! - * @internal - * @brief Modify this function to use a different routine than free(). - */ -static void XXH_free(void* p) { free(p); } - -#endif /* XXH_NO_STDLIB */ - -#include - -/*! - * @internal - * @brief Modify this function to use a different routine than memcpy(). - */ -static void* XXH_memcpy(void* dest, const void* src, size_t size) -{ - return memcpy(dest,src,size); -} - -#include /* ULLONG_MAX */ - - -/* ************************************* -* Compiler Specific Options -***************************************/ -#ifdef _MSC_VER /* Visual Studio warning fix */ -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#endif - -#if XXH_NO_INLINE_HINTS /* disable inlining hints */ -# if defined(__GNUC__) || defined(__clang__) -# define XXH_FORCE_INLINE static __attribute__((unused)) -# else -# define XXH_FORCE_INLINE static -# endif -# define XXH_NO_INLINE static -/* enable inlining hints */ -#elif defined(__GNUC__) || defined(__clang__) -# define XXH_FORCE_INLINE static __inline__ __attribute__((always_inline, unused)) -# define XXH_NO_INLINE static __attribute__((noinline)) -#elif defined(_MSC_VER) /* Visual Studio */ -# define XXH_FORCE_INLINE static __forceinline -# define XXH_NO_INLINE static __declspec(noinline) -#elif defined (__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* C99 */ -# define XXH_FORCE_INLINE static inline -# define XXH_NO_INLINE static -#else -# define XXH_FORCE_INLINE static -# define XXH_NO_INLINE static -#endif - - - -/* ************************************* -* Debug -***************************************/ -/*! - * @ingroup tuning - * @def XXH_DEBUGLEVEL - * @brief Sets the debugging level. - * - * XXH_DEBUGLEVEL is expected to be defined externally, typically via the - * compiler's command line options. The value must be a number. - */ -#ifndef XXH_DEBUGLEVEL -# ifdef DEBUGLEVEL /* backwards compat */ -# define XXH_DEBUGLEVEL DEBUGLEVEL -# else -# define XXH_DEBUGLEVEL 0 -# endif -#endif - -#if (XXH_DEBUGLEVEL>=1) -# include /* note: can still be disabled with NDEBUG */ -# define XXH_ASSERT(c) assert(c) -#else -# define XXH_ASSERT(c) ((void)0) -#endif - -/* note: use after variable declarations */ -#ifndef XXH_STATIC_ASSERT -# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ -# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { _Static_assert((c),m); } while(0) -# elif defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */ -# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { static_assert((c),m); } while(0) -# else -# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct xxh_sa { char x[(c) ? 1 : -1]; }; } while(0) -# endif -# define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c),#c) -#endif - -/*! - * @internal - * @def XXH_COMPILER_GUARD(var) - * @brief Used to prevent unwanted optimizations for @p var. - * - * It uses an empty GCC inline assembly statement with a register constraint - * which forces @p var into a general purpose register (eg eax, ebx, ecx - * on x86) and marks it as modified. - * - * This is used in a few places to avoid unwanted autovectorization (e.g. - * XXH32_round()). All vectorization we want is explicit via intrinsics, - * and _usually_ isn't wanted elsewhere. - * - * We also use it to prevent unwanted constant folding for AArch64 in - * XXH3_initCustomSecret_scalar(). - */ -#if defined(__GNUC__) || defined(__clang__) -# define XXH_COMPILER_GUARD(var) __asm__ __volatile__("" : "+r" (var)) -#else -# define XXH_COMPILER_GUARD(var) ((void)0) -#endif - -/* ************************************* -* Basic Types -***************************************/ -#if !defined (__VMS) \ - && (defined (__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - typedef uint8_t xxh_u8; -#else - typedef unsigned char xxh_u8; -#endif -typedef XXH32_hash_t xxh_u32; - -#ifdef XXH_OLD_NAMES -# define BYTE xxh_u8 -# define U8 xxh_u8 -# define U32 xxh_u32 -#endif - -/* *** Memory access *** */ - -/*! - * @internal - * @fn xxh_u32 XXH_read32(const void* ptr) - * @brief Reads an unaligned 32-bit integer from @p ptr in native endianness. - * - * Affected by @ref XXH_FORCE_MEMORY_ACCESS. - * - * @param ptr The pointer to read from. - * @return The 32-bit native endian integer from the bytes at @p ptr. - */ - -/*! - * @internal - * @fn xxh_u32 XXH_readLE32(const void* ptr) - * @brief Reads an unaligned 32-bit little endian integer from @p ptr. - * - * Affected by @ref XXH_FORCE_MEMORY_ACCESS. - * - * @param ptr The pointer to read from. - * @return The 32-bit little endian integer from the bytes at @p ptr. - */ - -/*! - * @internal - * @fn xxh_u32 XXH_readBE32(const void* ptr) - * @brief Reads an unaligned 32-bit big endian integer from @p ptr. - * - * Affected by @ref XXH_FORCE_MEMORY_ACCESS. - * - * @param ptr The pointer to read from. - * @return The 32-bit big endian integer from the bytes at @p ptr. - */ - -/*! - * @internal - * @fn xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align) - * @brief Like @ref XXH_readLE32(), but has an option for aligned reads. - * - * Affected by @ref XXH_FORCE_MEMORY_ACCESS. - * Note that when @ref XXH_FORCE_ALIGN_CHECK == 0, the @p align parameter is - * always @ref XXH_alignment::XXH_unaligned. - * - * @param ptr The pointer to read from. - * @param align Whether @p ptr is aligned. - * @pre - * If @p align == @ref XXH_alignment::XXH_aligned, @p ptr must be 4 byte - * aligned. - * @return The 32-bit little endian integer from the bytes at @p ptr. - */ - -#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) -/* - * Manual byteshift. Best for old compilers which don't inline memcpy. - * We actually directly use XXH_readLE32 and XXH_readBE32. - */ -#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) - -/* - * Force direct memory access. Only works on CPU which support unaligned memory - * access in hardware. - */ -static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; } - -#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) - -/* - * __attribute__((aligned(1))) is supported by gcc and clang. Originally the - * documentation claimed that it only increased the alignment, but actually it - * can decrease it on gcc, clang, and icc: - * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, - * https://gcc.godbolt.org/z/xYez1j67Y. - */ -#ifdef XXH_OLD_NAMES -typedef union { xxh_u32 u32; } __attribute__((packed)) unalign; -#endif -static xxh_u32 XXH_read32(const void* ptr) -{ - typedef __attribute__((aligned(1))) xxh_u32 xxh_unalign32; - return *((const xxh_unalign32*)ptr); -} - -#else - -/* - * Portable and safe solution. Generally efficient. - * see: http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html - */ -static xxh_u32 XXH_read32(const void* memPtr) -{ - xxh_u32 val; - XXH_memcpy(&val, memPtr, sizeof(val)); - return val; -} - -#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ - - -/* *** Endianness *** */ - -/*! - * @ingroup tuning - * @def XXH_CPU_LITTLE_ENDIAN - * @brief Whether the target is little endian. - * - * Defined to 1 if the target is little endian, or 0 if it is big endian. - * It can be defined externally, for example on the compiler command line. - * - * If it is not defined, - * a runtime check (which is usually constant folded) is used instead. - * - * @note - * This is not necessarily defined to an integer constant. - * - * @see XXH_isLittleEndian() for the runtime check. - */ -#ifndef XXH_CPU_LITTLE_ENDIAN -/* - * Try to detect endianness automatically, to avoid the nonstandard behavior - * in `XXH_isLittleEndian()` - */ -# if defined(_WIN32) /* Windows is always little endian */ \ - || defined(__LITTLE_ENDIAN__) \ - || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) -# define XXH_CPU_LITTLE_ENDIAN 1 -# elif defined(__BIG_ENDIAN__) \ - || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) -# define XXH_CPU_LITTLE_ENDIAN 0 -# else -/*! - * @internal - * @brief Runtime check for @ref XXH_CPU_LITTLE_ENDIAN. - * - * Most compilers will constant fold this. - */ -static int XXH_isLittleEndian(void) -{ - /* - * Portable and well-defined behavior. - * Don't use static: it is detrimental to performance. - */ - const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 }; - return one.c[0]; -} -# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() -# endif -#endif - - - - -/* **************************************** -* Compiler-specific Functions and Macros -******************************************/ -#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) - -#ifdef __has_builtin -# define XXH_HAS_BUILTIN(x) __has_builtin(x) -#else -# define XXH_HAS_BUILTIN(x) 0 -#endif - -/*! - * @internal - * @def XXH_rotl32(x,r) - * @brief 32-bit rotate left. - * - * @param x The 32-bit integer to be rotated. - * @param r The number of bits to rotate. - * @pre - * @p r > 0 && @p r < 32 - * @note - * @p x and @p r may be evaluated multiple times. - * @return The rotated result. - */ -#if !defined(NO_CLANG_BUILTIN) && XXH_HAS_BUILTIN(__builtin_rotateleft32) \ - && XXH_HAS_BUILTIN(__builtin_rotateleft64) -# define XXH_rotl32 __builtin_rotateleft32 -# define XXH_rotl64 __builtin_rotateleft64 -/* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */ -#elif defined(_MSC_VER) -# define XXH_rotl32(x,r) _rotl(x,r) -# define XXH_rotl64(x,r) _rotl64(x,r) -#else -# define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) -# define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r)))) -#endif - -/*! - * @internal - * @fn xxh_u32 XXH_swap32(xxh_u32 x) - * @brief A 32-bit byteswap. - * - * @param x The 32-bit integer to byteswap. - * @return @p x, byteswapped. - */ -#if defined(_MSC_VER) /* Visual Studio */ -# define XXH_swap32 _byteswap_ulong -#elif XXH_GCC_VERSION >= 403 -# define XXH_swap32 __builtin_bswap32 -#else -static xxh_u32 XXH_swap32 (xxh_u32 x) -{ - return ((x << 24) & 0xff000000 ) | - ((x << 8) & 0x00ff0000 ) | - ((x >> 8) & 0x0000ff00 ) | - ((x >> 24) & 0x000000ff ); -} -#endif - - -/* *************************** -* Memory reads -*****************************/ - -/*! - * @internal - * @brief Enum to indicate whether a pointer is aligned. - */ -typedef enum { - XXH_aligned, /*!< Aligned */ - XXH_unaligned /*!< Possibly unaligned */ -} XXH_alignment; - -/* - * XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. - * - * This is ideal for older compilers which don't inline memcpy. - */ -#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) - -XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* memPtr) -{ - const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; - return bytePtr[0] - | ((xxh_u32)bytePtr[1] << 8) - | ((xxh_u32)bytePtr[2] << 16) - | ((xxh_u32)bytePtr[3] << 24); -} - -XXH_FORCE_INLINE xxh_u32 XXH_readBE32(const void* memPtr) -{ - const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; - return bytePtr[3] - | ((xxh_u32)bytePtr[2] << 8) - | ((xxh_u32)bytePtr[1] << 16) - | ((xxh_u32)bytePtr[0] << 24); -} - -#else -XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); -} - -static xxh_u32 XXH_readBE32(const void* ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); -} -#endif - -XXH_FORCE_INLINE xxh_u32 -XXH_readLE32_align(const void* ptr, XXH_alignment align) -{ - if (align==XXH_unaligned) { - return XXH_readLE32(ptr); - } else { - return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr); - } -} - - -/* ************************************* -* Misc -***************************************/ -/*! @ingroup public */ -XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } - - -/* ******************************************************************* -* 32-bit hash functions -*********************************************************************/ -/*! - * @} - * @defgroup XXH32_impl XXH32 implementation - * @ingroup impl - * - * Details on the XXH32 implementation. - * @{ - */ - /* #define instead of static const, to be used as initializers */ -#define XXH_PRIME32_1 0x9E3779B1U /*!< 0b10011110001101110111100110110001 */ -#define XXH_PRIME32_2 0x85EBCA77U /*!< 0b10000101111010111100101001110111 */ -#define XXH_PRIME32_3 0xC2B2AE3DU /*!< 0b11000010101100101010111000111101 */ -#define XXH_PRIME32_4 0x27D4EB2FU /*!< 0b00100111110101001110101100101111 */ -#define XXH_PRIME32_5 0x165667B1U /*!< 0b00010110010101100110011110110001 */ - -#ifdef XXH_OLD_NAMES -# define PRIME32_1 XXH_PRIME32_1 -# define PRIME32_2 XXH_PRIME32_2 -# define PRIME32_3 XXH_PRIME32_3 -# define PRIME32_4 XXH_PRIME32_4 -# define PRIME32_5 XXH_PRIME32_5 -#endif - -/*! - * @internal - * @brief Normal stripe processing routine. - * - * This shuffles the bits so that any bit from @p input impacts several bits in - * @p acc. - * - * @param acc The accumulator lane. - * @param input The stripe of input to mix. - * @return The mixed accumulator lane. - */ -static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input) -{ - acc += input * XXH_PRIME32_2; - acc = XXH_rotl32(acc, 13); - acc *= XXH_PRIME32_1; -#if (defined(__SSE4_1__) || defined(__aarch64__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) - /* - * UGLY HACK: - * A compiler fence is the only thing that prevents GCC and Clang from - * autovectorizing the XXH32 loop (pragmas and attributes don't work for some - * reason) without globally disabling SSE4.1. - * - * The reason we want to avoid vectorization is because despite working on - * 4 integers at a time, there are multiple factors slowing XXH32 down on - * SSE4: - * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on - * newer chips!) making it slightly slower to multiply four integers at - * once compared to four integers independently. Even when pmulld was - * fastest, Sandy/Ivy Bridge, it is still not worth it to go into SSE - * just to multiply unless doing a long operation. - * - * - Four instructions are required to rotate, - * movqda tmp, v // not required with VEX encoding - * pslld tmp, 13 // tmp <<= 13 - * psrld v, 19 // x >>= 19 - * por v, tmp // x |= tmp - * compared to one for scalar: - * roll v, 13 // reliably fast across the board - * shldl v, v, 13 // Sandy Bridge and later prefer this for some reason - * - * - Instruction level parallelism is actually more beneficial here because - * the SIMD actually serializes this operation: While v1 is rotating, v2 - * can load data, while v3 can multiply. SSE forces them to operate - * together. - * - * This is also enabled on AArch64, as Clang autovectorizes it incorrectly - * and it is pointless writing a NEON implementation that is basically the - * same speed as scalar for XXH32. - */ - XXH_COMPILER_GUARD(acc); -#endif - return acc; -} - -/*! - * @internal - * @brief Mixes all bits to finalize the hash. - * - * The final mix ensures that all input bits have a chance to impact any bit in - * the output digest, resulting in an unbiased distribution. - * - * @param hash The hash to avalanche. - * @return The avalanched hash. - */ -static xxh_u32 XXH32_avalanche(xxh_u32 hash) -{ - hash ^= hash >> 15; - hash *= XXH_PRIME32_2; - hash ^= hash >> 13; - hash *= XXH_PRIME32_3; - hash ^= hash >> 16; - return hash; -} - -#define XXH_get32bits(p) XXH_readLE32_align(p, align) - -/*! - * @internal - * @brief Processes the last 0-15 bytes of @p ptr. - * - * There may be up to 15 bytes remaining to consume from the input. - * This final stage will digest them to ensure that all input bytes are present - * in the final mix. - * - * @param hash The hash to finalize. - * @param ptr The pointer to the remaining input. - * @param len The remaining length, modulo 16. - * @param align Whether @p ptr is aligned. - * @return The finalized hash. - * @see XXH64_finalize(). - */ -static XXH_PUREF xxh_u32 -XXH32_finalize(xxh_u32 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) -{ -#define XXH_PROCESS1 do { \ - hash += (*ptr++) * XXH_PRIME32_5; \ - hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1; \ -} while (0) - -#define XXH_PROCESS4 do { \ - hash += XXH_get32bits(ptr) * XXH_PRIME32_3; \ - ptr += 4; \ - hash = XXH_rotl32(hash, 17) * XXH_PRIME32_4; \ -} while (0) - - if (ptr==NULL) XXH_ASSERT(len == 0); - - /* Compact rerolled version; generally faster */ - if (!XXH32_ENDJMP) { - len &= 15; - while (len >= 4) { - XXH_PROCESS4; - len -= 4; - } - while (len > 0) { - XXH_PROCESS1; - --len; - } - return XXH32_avalanche(hash); - } else { - switch(len&15) /* or switch(bEnd - p) */ { - case 12: XXH_PROCESS4; - XXH_FALLTHROUGH; - case 8: XXH_PROCESS4; - XXH_FALLTHROUGH; - case 4: XXH_PROCESS4; - return XXH32_avalanche(hash); - - case 13: XXH_PROCESS4; - XXH_FALLTHROUGH; - case 9: XXH_PROCESS4; - XXH_FALLTHROUGH; - case 5: XXH_PROCESS4; - XXH_PROCESS1; - return XXH32_avalanche(hash); - - case 14: XXH_PROCESS4; - XXH_FALLTHROUGH; - case 10: XXH_PROCESS4; - XXH_FALLTHROUGH; - case 6: XXH_PROCESS4; - XXH_PROCESS1; - XXH_PROCESS1; - return XXH32_avalanche(hash); - - case 15: XXH_PROCESS4; - XXH_FALLTHROUGH; - case 11: XXH_PROCESS4; - XXH_FALLTHROUGH; - case 7: XXH_PROCESS4; - XXH_FALLTHROUGH; - case 3: XXH_PROCESS1; - XXH_FALLTHROUGH; - case 2: XXH_PROCESS1; - XXH_FALLTHROUGH; - case 1: XXH_PROCESS1; - XXH_FALLTHROUGH; - case 0: return XXH32_avalanche(hash); - } - XXH_ASSERT(0); - return hash; /* reaching this point is deemed impossible */ - } -} - -#ifdef XXH_OLD_NAMES -# define PROCESS1 XXH_PROCESS1 -# define PROCESS4 XXH_PROCESS4 -#else -# undef XXH_PROCESS1 -# undef XXH_PROCESS4 -#endif - -/*! - * @internal - * @brief The implementation for @ref XXH32(). - * - * @param input , len , seed Directly passed from @ref XXH32(). - * @param align Whether @p input is aligned. - * @return The calculated hash. - */ -XXH_FORCE_INLINE XXH_PUREF xxh_u32 -XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align) -{ - xxh_u32 h32; - - if (input==NULL) XXH_ASSERT(len == 0); - - if (len>=16) { - const xxh_u8* const bEnd = input + len; - const xxh_u8* const limit = bEnd - 15; - xxh_u32 v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2; - xxh_u32 v2 = seed + XXH_PRIME32_2; - xxh_u32 v3 = seed + 0; - xxh_u32 v4 = seed - XXH_PRIME32_1; - - do { - v1 = XXH32_round(v1, XXH_get32bits(input)); input += 4; - v2 = XXH32_round(v2, XXH_get32bits(input)); input += 4; - v3 = XXH32_round(v3, XXH_get32bits(input)); input += 4; - v4 = XXH32_round(v4, XXH_get32bits(input)); input += 4; - } while (input < limit); - - h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) - + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); - } else { - h32 = seed + XXH_PRIME32_5; - } - - h32 += (xxh_u32)len; - - return XXH32_finalize(h32, input, len&15, align); -} - -/*! @ingroup XXH32_family */ -XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed) -{ -#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH32_state_t state; - XXH32_reset(&state, seed); - XXH32_update(&state, (const xxh_u8*)input, len); - return XXH32_digest(&state); -#else - if (XXH_FORCE_ALIGN_CHECK) { - if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ - return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); - } } - - return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); -#endif -} - - - -/******* Hash streaming *******/ -#ifndef XXH_NO_STREAM -/*! @ingroup XXH32_family */ -XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) -{ - return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); -} -/*! @ingroup XXH32_family */ -XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -} - -/*! @ingroup XXH32_family */ -XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) -{ - XXH_memcpy(dstState, srcState, sizeof(*dstState)); -} - -/*! @ingroup XXH32_family */ -XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed) -{ - XXH_ASSERT(statePtr != NULL); - memset(statePtr, 0, sizeof(*statePtr)); - statePtr->v[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2; - statePtr->v[1] = seed + XXH_PRIME32_2; - statePtr->v[2] = seed + 0; - statePtr->v[3] = seed - XXH_PRIME32_1; - return XXH_OK; -} - - -/*! @ingroup XXH32_family */ -XXH_PUBLIC_API XXH_errorcode -XXH32_update(XXH32_state_t* state, const void* input, size_t len) -{ - if (input==NULL) { - XXH_ASSERT(len == 0); - return XXH_OK; - } - - { const xxh_u8* p = (const xxh_u8*)input; - const xxh_u8* const bEnd = p + len; - - state->total_len_32 += (XXH32_hash_t)len; - state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16)); - - if (state->memsize + len < 16) { /* fill in tmp buffer */ - XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, len); - state->memsize += (XXH32_hash_t)len; - return XXH_OK; - } - - if (state->memsize) { /* some data left from previous update */ - XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, 16-state->memsize); - { const xxh_u32* p32 = state->mem32; - state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p32)); p32++; - state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p32)); p32++; - state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p32)); p32++; - state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p32)); - } - p += 16-state->memsize; - state->memsize = 0; - } - - if (p <= bEnd-16) { - const xxh_u8* const limit = bEnd - 16; - - do { - state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p)); p+=4; - state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p)); p+=4; - state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p)); p+=4; - state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p)); p+=4; - } while (p<=limit); - - } - - if (p < bEnd) { - XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); - } - } - - return XXH_OK; -} - - -/*! @ingroup XXH32_family */ -XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state) -{ - xxh_u32 h32; - - if (state->large_len) { - h32 = XXH_rotl32(state->v[0], 1) - + XXH_rotl32(state->v[1], 7) - + XXH_rotl32(state->v[2], 12) - + XXH_rotl32(state->v[3], 18); - } else { - h32 = state->v[2] /* == seed */ + XXH_PRIME32_5; - } - - h32 += state->total_len_32; - - return XXH32_finalize(h32, (const xxh_u8*)state->mem32, state->memsize, XXH_aligned); -} -#endif /* !XXH_NO_STREAM */ - -/******* Canonical representation *******/ - -/*! - * @ingroup XXH32_family - * The default return values from XXH functions are unsigned 32 and 64 bit - * integers. - * - * The canonical representation uses big endian convention, the same convention - * as human-readable numbers (large digits first). - * - * This way, hash values can be written into a file or buffer, remaining - * comparable across different systems. - * - * The following functions allow transformation of hash values to and from their - * canonical format. - */ -XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); - XXH_memcpy(dst, &hash, sizeof(*dst)); -} -/*! @ingroup XXH32_family */ -XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) -{ - return XXH_readBE32(src); -} - - -#ifndef XXH_NO_LONG_LONG - -/* ******************************************************************* -* 64-bit hash functions -*********************************************************************/ -/*! - * @} - * @ingroup impl - * @{ - */ -/******* Memory access *******/ - -typedef XXH64_hash_t xxh_u64; - -#ifdef XXH_OLD_NAMES -# define U64 xxh_u64 -#endif - -#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) -/* - * Manual byteshift. Best for old compilers which don't inline memcpy. - * We actually directly use XXH_readLE64 and XXH_readBE64. - */ -#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) - -/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ -static xxh_u64 XXH_read64(const void* memPtr) -{ - return *(const xxh_u64*) memPtr; -} - -#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) - -/* - * __attribute__((aligned(1))) is supported by gcc and clang. Originally the - * documentation claimed that it only increased the alignment, but actually it - * can decrease it on gcc, clang, and icc: - * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, - * https://gcc.godbolt.org/z/xYez1j67Y. - */ -#ifdef XXH_OLD_NAMES -typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) unalign64; -#endif -static xxh_u64 XXH_read64(const void* ptr) -{ - typedef __attribute__((aligned(1))) xxh_u64 xxh_unalign64; - return *((const xxh_unalign64*)ptr); -} - -#else - -/* - * Portable and safe solution. Generally efficient. - * see: http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html - */ -static xxh_u64 XXH_read64(const void* memPtr) -{ - xxh_u64 val; - XXH_memcpy(&val, memPtr, sizeof(val)); - return val; -} - -#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ - -#if defined(_MSC_VER) /* Visual Studio */ -# define XXH_swap64 _byteswap_uint64 -#elif XXH_GCC_VERSION >= 403 -# define XXH_swap64 __builtin_bswap64 -#else -static xxh_u64 XXH_swap64(xxh_u64 x) -{ - return ((x << 56) & 0xff00000000000000ULL) | - ((x << 40) & 0x00ff000000000000ULL) | - ((x << 24) & 0x0000ff0000000000ULL) | - ((x << 8) & 0x000000ff00000000ULL) | - ((x >> 8) & 0x00000000ff000000ULL) | - ((x >> 24) & 0x0000000000ff0000ULL) | - ((x >> 40) & 0x000000000000ff00ULL) | - ((x >> 56) & 0x00000000000000ffULL); -} -#endif - - -/* XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. */ -#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) - -XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* memPtr) -{ - const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; - return bytePtr[0] - | ((xxh_u64)bytePtr[1] << 8) - | ((xxh_u64)bytePtr[2] << 16) - | ((xxh_u64)bytePtr[3] << 24) - | ((xxh_u64)bytePtr[4] << 32) - | ((xxh_u64)bytePtr[5] << 40) - | ((xxh_u64)bytePtr[6] << 48) - | ((xxh_u64)bytePtr[7] << 56); -} - -XXH_FORCE_INLINE xxh_u64 XXH_readBE64(const void* memPtr) -{ - const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; - return bytePtr[7] - | ((xxh_u64)bytePtr[6] << 8) - | ((xxh_u64)bytePtr[5] << 16) - | ((xxh_u64)bytePtr[4] << 24) - | ((xxh_u64)bytePtr[3] << 32) - | ((xxh_u64)bytePtr[2] << 40) - | ((xxh_u64)bytePtr[1] << 48) - | ((xxh_u64)bytePtr[0] << 56); -} - -#else -XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); -} - -static xxh_u64 XXH_readBE64(const void* ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); -} -#endif - -XXH_FORCE_INLINE xxh_u64 -XXH_readLE64_align(const void* ptr, XXH_alignment align) -{ - if (align==XXH_unaligned) - return XXH_readLE64(ptr); - else - return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr); -} - - -/******* xxh64 *******/ -/*! - * @} - * @defgroup XXH64_impl XXH64 implementation - * @ingroup impl - * - * Details on the XXH64 implementation. - * @{ - */ -/* #define rather that static const, to be used as initializers */ -#define XXH_PRIME64_1 0x9E3779B185EBCA87ULL /*!< 0b1001111000110111011110011011000110000101111010111100101010000111 */ -#define XXH_PRIME64_2 0xC2B2AE3D27D4EB4FULL /*!< 0b1100001010110010101011100011110100100111110101001110101101001111 */ -#define XXH_PRIME64_3 0x165667B19E3779F9ULL /*!< 0b0001011001010110011001111011000110011110001101110111100111111001 */ -#define XXH_PRIME64_4 0x85EBCA77C2B2AE63ULL /*!< 0b1000010111101011110010100111011111000010101100101010111001100011 */ -#define XXH_PRIME64_5 0x27D4EB2F165667C5ULL /*!< 0b0010011111010100111010110010111100010110010101100110011111000101 */ - -#ifdef XXH_OLD_NAMES -# define PRIME64_1 XXH_PRIME64_1 -# define PRIME64_2 XXH_PRIME64_2 -# define PRIME64_3 XXH_PRIME64_3 -# define PRIME64_4 XXH_PRIME64_4 -# define PRIME64_5 XXH_PRIME64_5 -#endif - -/*! @copydoc XXH32_round */ -static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input) -{ - acc += input * XXH_PRIME64_2; - acc = XXH_rotl64(acc, 31); - acc *= XXH_PRIME64_1; - return acc; -} - -static xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val) -{ - val = XXH64_round(0, val); - acc ^= val; - acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4; - return acc; -} - -/*! @copydoc XXH32_avalanche */ -static xxh_u64 XXH64_avalanche(xxh_u64 hash) -{ - hash ^= hash >> 33; - hash *= XXH_PRIME64_2; - hash ^= hash >> 29; - hash *= XXH_PRIME64_3; - hash ^= hash >> 32; - return hash; -} - - -#define XXH_get64bits(p) XXH_readLE64_align(p, align) - -/*! - * @internal - * @brief Processes the last 0-31 bytes of @p ptr. - * - * There may be up to 31 bytes remaining to consume from the input. - * This final stage will digest them to ensure that all input bytes are present - * in the final mix. - * - * @param hash The hash to finalize. - * @param ptr The pointer to the remaining input. - * @param len The remaining length, modulo 32. - * @param align Whether @p ptr is aligned. - * @return The finalized hash - * @see XXH32_finalize(). - */ -static XXH_PUREF xxh_u64 -XXH64_finalize(xxh_u64 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) -{ - if (ptr==NULL) XXH_ASSERT(len == 0); - len &= 31; - while (len >= 8) { - xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr)); - ptr += 8; - hash ^= k1; - hash = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4; - len -= 8; - } - if (len >= 4) { - hash ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1; - ptr += 4; - hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3; - len -= 4; - } - while (len > 0) { - hash ^= (*ptr++) * XXH_PRIME64_5; - hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1; - --len; - } - return XXH64_avalanche(hash); -} - -#ifdef XXH_OLD_NAMES -# define PROCESS1_64 XXH_PROCESS1_64 -# define PROCESS4_64 XXH_PROCESS4_64 -# define PROCESS8_64 XXH_PROCESS8_64 -#else -# undef XXH_PROCESS1_64 -# undef XXH_PROCESS4_64 -# undef XXH_PROCESS8_64 -#endif - -/*! - * @internal - * @brief The implementation for @ref XXH64(). - * - * @param input , len , seed Directly passed from @ref XXH64(). - * @param align Whether @p input is aligned. - * @return The calculated hash. - */ -XXH_FORCE_INLINE XXH_PUREF xxh_u64 -XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align) -{ - xxh_u64 h64; - if (input==NULL) XXH_ASSERT(len == 0); - - if (len>=32) { - const xxh_u8* const bEnd = input + len; - const xxh_u8* const limit = bEnd - 31; - xxh_u64 v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2; - xxh_u64 v2 = seed + XXH_PRIME64_2; - xxh_u64 v3 = seed + 0; - xxh_u64 v4 = seed - XXH_PRIME64_1; - - do { - v1 = XXH64_round(v1, XXH_get64bits(input)); input+=8; - v2 = XXH64_round(v2, XXH_get64bits(input)); input+=8; - v3 = XXH64_round(v3, XXH_get64bits(input)); input+=8; - v4 = XXH64_round(v4, XXH_get64bits(input)); input+=8; - } while (input= 2 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH64_state_t state; - XXH64_reset(&state, seed); - XXH64_update(&state, (const xxh_u8*)input, len); - return XXH64_digest(&state); -#else - if (XXH_FORCE_ALIGN_CHECK) { - if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ - return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); - } } - - return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); - -#endif -} - -/******* Hash Streaming *******/ -#ifndef XXH_NO_STREAM -/*! @ingroup XXH64_family*/ -XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) -{ - return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); -} -/*! @ingroup XXH64_family */ -XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -} - -/*! @ingroup XXH64_family */ -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState) -{ - XXH_memcpy(dstState, srcState, sizeof(*dstState)); -} - -/*! @ingroup XXH64_family */ -XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, XXH64_hash_t seed) -{ - XXH_ASSERT(statePtr != NULL); - memset(statePtr, 0, sizeof(*statePtr)); - statePtr->v[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2; - statePtr->v[1] = seed + XXH_PRIME64_2; - statePtr->v[2] = seed + 0; - statePtr->v[3] = seed - XXH_PRIME64_1; - return XXH_OK; -} - -/*! @ingroup XXH64_family */ -XXH_PUBLIC_API XXH_errorcode -XXH64_update (XXH64_state_t* state, const void* input, size_t len) -{ - if (input==NULL) { - XXH_ASSERT(len == 0); - return XXH_OK; - } - - { const xxh_u8* p = (const xxh_u8*)input; - const xxh_u8* const bEnd = p + len; - - state->total_len += len; - - if (state->memsize + len < 32) { /* fill in tmp buffer */ - XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, len); - state->memsize += (xxh_u32)len; - return XXH_OK; - } - - if (state->memsize) { /* tmp buffer is full */ - XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, 32-state->memsize); - state->v[0] = XXH64_round(state->v[0], XXH_readLE64(state->mem64+0)); - state->v[1] = XXH64_round(state->v[1], XXH_readLE64(state->mem64+1)); - state->v[2] = XXH64_round(state->v[2], XXH_readLE64(state->mem64+2)); - state->v[3] = XXH64_round(state->v[3], XXH_readLE64(state->mem64+3)); - p += 32 - state->memsize; - state->memsize = 0; - } - - if (p+32 <= bEnd) { - const xxh_u8* const limit = bEnd - 32; - - do { - state->v[0] = XXH64_round(state->v[0], XXH_readLE64(p)); p+=8; - state->v[1] = XXH64_round(state->v[1], XXH_readLE64(p)); p+=8; - state->v[2] = XXH64_round(state->v[2], XXH_readLE64(p)); p+=8; - state->v[3] = XXH64_round(state->v[3], XXH_readLE64(p)); p+=8; - } while (p<=limit); - - } - - if (p < bEnd) { - XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); - } - } - - return XXH_OK; -} - - -/*! @ingroup XXH64_family */ -XXH_PUBLIC_API XXH64_hash_t XXH64_digest(const XXH64_state_t* state) -{ - xxh_u64 h64; - - if (state->total_len >= 32) { - h64 = XXH_rotl64(state->v[0], 1) + XXH_rotl64(state->v[1], 7) + XXH_rotl64(state->v[2], 12) + XXH_rotl64(state->v[3], 18); - h64 = XXH64_mergeRound(h64, state->v[0]); - h64 = XXH64_mergeRound(h64, state->v[1]); - h64 = XXH64_mergeRound(h64, state->v[2]); - h64 = XXH64_mergeRound(h64, state->v[3]); - } else { - h64 = state->v[2] /*seed*/ + XXH_PRIME64_5; - } - - h64 += (xxh_u64) state->total_len; - - return XXH64_finalize(h64, (const xxh_u8*)state->mem64, (size_t)state->total_len, XXH_aligned); -} -#endif /* !XXH_NO_STREAM */ - -/******* Canonical representation *******/ - -/*! @ingroup XXH64_family */ -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); - XXH_memcpy(dst, &hash, sizeof(*dst)); -} - -/*! @ingroup XXH64_family */ -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src) -{ - return XXH_readBE64(src); -} - -#ifndef XXH_NO_XXH3 - -/* ********************************************************************* -* XXH3 -* New generation hash designed for speed on small keys and vectorization -************************************************************************ */ -/*! - * @} - * @defgroup XXH3_impl XXH3 implementation - * @ingroup impl - * @{ - */ - -/* === Compiler specifics === */ - -#if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */ -# define XXH_RESTRICT /* disable */ -#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */ -# define XXH_RESTRICT restrict -#else -/* Note: it might be useful to define __restrict or __restrict__ for some C++ compilers */ -# define XXH_RESTRICT /* disable */ -#endif - -#if (defined(__GNUC__) && (__GNUC__ >= 3)) \ - || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \ - || defined(__clang__) -# define XXH_likely(x) __builtin_expect(x, 1) -# define XXH_unlikely(x) __builtin_expect(x, 0) -#else -# define XXH_likely(x) (x) -# define XXH_unlikely(x) (x) -#endif - -#if defined(__GNUC__) || defined(__clang__) -# if defined(__ARM_NEON__) || defined(__ARM_NEON) \ - || defined(__aarch64__) || defined(_M_ARM) \ - || defined(_M_ARM64) || defined(_M_ARM64EC) -# define inline __inline__ /* circumvent a clang bug */ -# include -# undef inline -# elif defined(__AVX2__) -# include -# elif defined(__SSE2__) -# include -# endif -#endif - -#if defined(_MSC_VER) -# include -#endif - -/* - * One goal of XXH3 is to make it fast on both 32-bit and 64-bit, while - * remaining a true 64-bit/128-bit hash function. - * - * This is done by prioritizing a subset of 64-bit operations that can be - * emulated without too many steps on the average 32-bit machine. - * - * For example, these two lines seem similar, and run equally fast on 64-bit: - * - * xxh_u64 x; - * x ^= (x >> 47); // good - * x ^= (x >> 13); // bad - * - * However, to a 32-bit machine, there is a major difference. - * - * x ^= (x >> 47) looks like this: - * - * x.lo ^= (x.hi >> (47 - 32)); - * - * while x ^= (x >> 13) looks like this: - * - * // note: funnel shifts are not usually cheap. - * x.lo ^= (x.lo >> 13) | (x.hi << (32 - 13)); - * x.hi ^= (x.hi >> 13); - * - * The first one is significantly faster than the second, simply because the - * shift is larger than 32. This means: - * - All the bits we need are in the upper 32 bits, so we can ignore the lower - * 32 bits in the shift. - * - The shift result will always fit in the lower 32 bits, and therefore, - * we can ignore the upper 32 bits in the xor. - * - * Thanks to this optimization, XXH3 only requires these features to be efficient: - * - * - Usable unaligned access - * - A 32-bit or 64-bit ALU - * - If 32-bit, a decent ADC instruction - * - A 32 or 64-bit multiply with a 64-bit result - * - For the 128-bit variant, a decent byteswap helps short inputs. - * - * The first two are already required by XXH32, and almost all 32-bit and 64-bit - * platforms which can run XXH32 can run XXH3 efficiently. - * - * Thumb-1, the classic 16-bit only subset of ARM's instruction set, is one - * notable exception. - * - * First of all, Thumb-1 lacks support for the UMULL instruction which - * performs the important long multiply. This means numerous __aeabi_lmul - * calls. - * - * Second of all, the 8 functional registers are just not enough. - * Setup for __aeabi_lmul, byteshift loads, pointers, and all arithmetic need - * Lo registers, and this shuffling results in thousands more MOVs than A32. - * - * A32 and T32 don't have this limitation. They can access all 14 registers, - * do a 32->64 multiply with UMULL, and the flexible operand allowing free - * shifts is helpful, too. - * - * Therefore, we do a quick sanity check. - * - * If compiling Thumb-1 for a target which supports ARM instructions, we will - * emit a warning, as it is not a "sane" platform to compile for. - * - * Usually, if this happens, it is because of an accident and you probably need - * to specify -march, as you likely meant to compile for a newer architecture. - * - * Credit: large sections of the vectorial and asm source code paths - * have been contributed by @easyaspi314 - */ -#if defined(__thumb__) && !defined(__thumb2__) && defined(__ARM_ARCH_ISA_ARM) -# warning "XXH3 is highly inefficient without ARM or Thumb-2." -#endif - -/* ========================================== - * Vectorization detection - * ========================================== */ - -#ifdef XXH_DOXYGEN -/*! - * @ingroup tuning - * @brief Overrides the vectorization implementation chosen for XXH3. - * - * Can be defined to 0 to disable SIMD or any of the values mentioned in - * @ref XXH_VECTOR_TYPE. - * - * If this is not defined, it uses predefined macros to determine the best - * implementation. - */ -# define XXH_VECTOR XXH_SCALAR -/*! - * @ingroup tuning - * @brief Possible values for @ref XXH_VECTOR. - * - * Note that these are actually implemented as macros. - * - * If this is not defined, it is detected automatically. - * @ref XXH_X86DISPATCH overrides this. - */ -enum XXH_VECTOR_TYPE /* fake enum */ { - XXH_SCALAR = 0, /*!< Portable scalar version */ - XXH_SSE2 = 1, /*!< - * SSE2 for Pentium 4, Opteron, all x86_64. - * - * @note SSE2 is also guaranteed on Windows 10, macOS, and - * Android x86. - */ - XXH_AVX2 = 2, /*!< AVX2 for Haswell and Bulldozer */ - XXH_AVX512 = 3, /*!< AVX512 for Skylake and Icelake */ - XXH_NEON = 4, /*!< NEON for most ARMv7-A and all AArch64 */ - XXH_VSX = 5, /*!< VSX and ZVector for POWER8/z13 (64-bit) */ -}; -/*! - * @ingroup tuning - * @brief Selects the minimum alignment for XXH3's accumulators. - * - * When using SIMD, this should match the alignment reqired for said vector - * type, so, for example, 32 for AVX2. - * - * Default: Auto detected. - */ -# define XXH_ACC_ALIGN 8 -#endif - -/* Actual definition */ -#ifndef XXH_DOXYGEN -# define XXH_SCALAR 0 -# define XXH_SSE2 1 -# define XXH_AVX2 2 -# define XXH_AVX512 3 -# define XXH_NEON 4 -# define XXH_VSX 5 -#endif - -#ifndef XXH_VECTOR /* can be defined on command line */ -# if ( \ - defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \ - || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \ - ) && ( \ - defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \ - || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \ - ) -# define XXH_VECTOR XXH_NEON -# elif defined(__AVX512F__) -# define XXH_VECTOR XXH_AVX512 -# elif defined(__AVX2__) -# define XXH_VECTOR XXH_AVX2 -# elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) -# define XXH_VECTOR XXH_SSE2 -# elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \ - || (defined(__s390x__) && defined(__VEC__)) \ - && defined(__GNUC__) /* TODO: IBM XL */ -# define XXH_VECTOR XXH_VSX -# else -# define XXH_VECTOR XXH_SCALAR -# endif -#endif - -/* - * Controls the alignment of the accumulator, - * for compatibility with aligned vector loads, which are usually faster. - */ -#ifndef XXH_ACC_ALIGN -# if defined(XXH_X86DISPATCH) -# define XXH_ACC_ALIGN 64 /* for compatibility with avx512 */ -# elif XXH_VECTOR == XXH_SCALAR /* scalar */ -# define XXH_ACC_ALIGN 8 -# elif XXH_VECTOR == XXH_SSE2 /* sse2 */ -# define XXH_ACC_ALIGN 16 -# elif XXH_VECTOR == XXH_AVX2 /* avx2 */ -# define XXH_ACC_ALIGN 32 -# elif XXH_VECTOR == XXH_NEON /* neon */ -# define XXH_ACC_ALIGN 16 -# elif XXH_VECTOR == XXH_VSX /* vsx */ -# define XXH_ACC_ALIGN 16 -# elif XXH_VECTOR == XXH_AVX512 /* avx512 */ -# define XXH_ACC_ALIGN 64 -# endif -#endif - -#if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \ - || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512 -# define XXH_SEC_ALIGN XXH_ACC_ALIGN -#else -# define XXH_SEC_ALIGN 8 -#endif - -/* - * UGLY HACK: - * GCC usually generates the best code with -O3 for xxHash. - * - * However, when targeting AVX2, it is overzealous in its unrolling resulting - * in code roughly 3/4 the speed of Clang. - * - * There are other issues, such as GCC splitting _mm256_loadu_si256 into - * _mm_loadu_si128 + _mm256_inserti128_si256. This is an optimization which - * only applies to Sandy and Ivy Bridge... which don't even support AVX2. - * - * That is why when compiling the AVX2 version, it is recommended to use either - * -O2 -mavx2 -march=haswell - * or - * -O2 -mavx2 -mno-avx256-split-unaligned-load - * for decent performance, or to use Clang instead. - * - * Fortunately, we can control the first one with a pragma that forces GCC into - * -O2, but the other one we can't control without "failed to inline always - * inline function due to target mismatch" warnings. - */ -#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \ - && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ - && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */ -# pragma GCC push_options -# pragma GCC optimize("-O2") -#endif - - -#if XXH_VECTOR == XXH_NEON -/* - * NEON's setup for vmlal_u32 is a little more complicated than it is on - * SSE2, AVX2, and VSX. - * - * While PMULUDQ and VMULEUW both perform a mask, VMLAL.U32 performs an upcast. - * - * To do the same operation, the 128-bit 'Q' register needs to be split into - * two 64-bit 'D' registers, performing this operation:: - * - * [ a | b ] - * | '---------. .--------' | - * | x | - * | .---------' '--------. | - * [ a & 0xFFFFFFFF | b & 0xFFFFFFFF ],[ a >> 32 | b >> 32 ] - * - * Due to significant changes in aarch64, the fastest method for aarch64 is - * completely different than the fastest method for ARMv7-A. - * - * ARMv7-A treats D registers as unions overlaying Q registers, so modifying - * D11 will modify the high half of Q5. This is similar to how modifying AH - * will only affect bits 8-15 of AX on x86. - * - * VZIP takes two registers, and puts even lanes in one register and odd lanes - * in the other. - * - * On ARMv7-A, this strangely modifies both parameters in place instead of - * taking the usual 3-operand form. - * - * Therefore, if we want to do this, we can simply use a D-form VZIP.32 on the - * lower and upper halves of the Q register to end up with the high and low - * halves where we want - all in one instruction. - * - * vzip.32 d10, d11 @ d10 = { d10[0], d11[0] }; d11 = { d10[1], d11[1] } - * - * Unfortunately we need inline assembly for this: Instructions modifying two - * registers at once is not possible in GCC or Clang's IR, and they have to - * create a copy. - * - * aarch64 requires a different approach. - * - * In order to make it easier to write a decent compiler for aarch64, many - * quirks were removed, such as conditional execution. - * - * NEON was also affected by this. - * - * aarch64 cannot access the high bits of a Q-form register, and writes to a - * D-form register zero the high bits, similar to how writes to W-form scalar - * registers (or DWORD registers on x86_64) work. - * - * The formerly free vget_high intrinsics now require a vext (with a few - * exceptions) - * - * Additionally, VZIP was replaced by ZIP1 and ZIP2, which are the equivalent - * of PUNPCKL* and PUNPCKH* in SSE, respectively, in order to only modify one - * operand. - * - * The equivalent of the VZIP.32 on the lower and upper halves would be this - * mess: - * - * ext v2.4s, v0.4s, v0.4s, #2 // v2 = { v0[2], v0[3], v0[0], v0[1] } - * zip1 v1.2s, v0.2s, v2.2s // v1 = { v0[0], v2[0] } - * zip2 v0.2s, v0.2s, v1.2s // v0 = { v0[1], v2[1] } - * - * Instead, we use a literal downcast, vmovn_u64 (XTN), and vshrn_n_u64 (SHRN): - * - * shrn v1.2s, v0.2d, #32 // v1 = (uint32x2_t)(v0 >> 32); - * xtn v0.2s, v0.2d // v0 = (uint32x2_t)(v0 & 0xFFFFFFFF); - * - * This is available on ARMv7-A, but is less efficient than a single VZIP.32. - */ - -/*! - * Function-like macro: - * void XXH_SPLIT_IN_PLACE(uint64x2_t &in, uint32x2_t &outLo, uint32x2_t &outHi) - * { - * outLo = (uint32x2_t)(in & 0xFFFFFFFF); - * outHi = (uint32x2_t)(in >> 32); - * in = UNDEFINED; - * } - */ -# if !defined(XXH_NO_VZIP_HACK) /* define to disable */ \ - && (defined(__GNUC__) || defined(__clang__)) \ - && (defined(__arm__) || defined(__thumb__) || defined(_M_ARM)) -# define XXH_SPLIT_IN_PLACE(in, outLo, outHi) \ - do { \ - /* Undocumented GCC/Clang operand modifier: %e0 = lower D half, %f0 = upper D half */ \ - /* https://github.com/gcc-mirror/gcc/blob/38cf91e5/gcc/config/arm/arm.c#L22486 */ \ - /* https://github.com/llvm-mirror/llvm/blob/2c4ca683/lib/Target/ARM/ARMAsmPrinter.cpp#L399 */ \ - __asm__("vzip.32 %e0, %f0" : "+w" (in)); \ - (outLo) = vget_low_u32 (vreinterpretq_u32_u64(in)); \ - (outHi) = vget_high_u32(vreinterpretq_u32_u64(in)); \ - } while (0) -# else -# define XXH_SPLIT_IN_PLACE(in, outLo, outHi) \ - do { \ - (outLo) = vmovn_u64 (in); \ - (outHi) = vshrn_n_u64 ((in), 32); \ - } while (0) -# endif - -/*! - * @internal - * @brief `vld1q_u64` but faster and alignment-safe. - * - * On AArch64, unaligned access is always safe, but on ARMv7-a, it is only - * *conditionally* safe (`vld1` has an alignment bit like `movdq[ua]` in x86). - * - * GCC for AArch64 sees `vld1q_u8` as an intrinsic instead of a load, so it - * prohibits load-store optimizations. Therefore, a direct dereference is used. - * - * Otherwise, `vld1q_u8` is used with `vreinterpretq_u8_u64` to do a safe - * unaligned load. - */ -#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) -XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) /* silence -Wcast-align */ -{ - return *(uint64x2_t const*)ptr; -} -#else -XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) -{ - return vreinterpretq_u64_u8(vld1q_u8((uint8_t const*)ptr)); -} -#endif -/*! - * @ingroup tuning - * @brief Controls the NEON to scalar ratio for XXH3 - * - * On AArch64 when not optimizing for size, XXH3 will run 6 lanes using NEON and - * 2 lanes on scalar by default. - * - * This can be set to 2, 4, 6, or 8. ARMv7 will default to all 8 NEON lanes, as the - * emulated 64-bit arithmetic is too slow. - * - * Modern ARM CPUs are _very_ sensitive to how their pipelines are used. - * - * For example, the Cortex-A73 can dispatch 3 micro-ops per cycle, but it can't - * have more than 2 NEON (F0/F1) micro-ops. If you are only using NEON instructions, - * you are only using 2/3 of the CPU bandwidth. - * - * This is even more noticable on the more advanced cores like the A76 which - * can dispatch 8 micro-ops per cycle, but still only 2 NEON micro-ops at once. - * - * Therefore, @ref XXH3_NEON_LANES lanes will be processed using NEON, and the - * remaining lanes will use scalar instructions. This improves the bandwidth - * and also gives the integer pipelines something to do besides twiddling loop - * counters and pointers. - * - * This change benefits CPUs with large micro-op buffers without negatively affecting - * other CPUs: - * - * | Chipset | Dispatch type | NEON only | 6:2 hybrid | Diff. | - * |:----------------------|:--------------------|----------:|-----------:|------:| - * | Snapdragon 730 (A76) | 2 NEON/8 micro-ops | 8.8 GB/s | 10.1 GB/s | ~16% | - * | Snapdragon 835 (A73) | 2 NEON/3 micro-ops | 5.1 GB/s | 5.3 GB/s | ~5% | - * | Marvell PXA1928 (A53) | In-order dual-issue | 1.9 GB/s | 1.9 GB/s | 0% | - * - * It also seems to fix some bad codegen on GCC, making it almost as fast as clang. - * - * @see XXH3_accumulate_512_neon() - */ -# ifndef XXH3_NEON_LANES -# if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \ - && XXH_SIZE_OPT <= 0 -# define XXH3_NEON_LANES 6 -# else -# define XXH3_NEON_LANES XXH_ACC_NB -# endif -# endif -#endif /* XXH_VECTOR == XXH_NEON */ - -/* - * VSX and Z Vector helpers. - * - * This is very messy, and any pull requests to clean this up are welcome. - * - * There are a lot of problems with supporting VSX and s390x, due to - * inconsistent intrinsics, spotty coverage, and multiple endiannesses. - */ -#if XXH_VECTOR == XXH_VSX -/* Annoyingly, these headers _may_ define three macros: `bool`, `vector`, - * and `pixel`. This is a problem for obvious reasons. - * - * These keywords are unnecessary; the spec literally says they are - * equivalent to `__bool`, `__vector`, and `__pixel` and may be undef'd - * after including the header. - * - * We use pragma push_macro/pop_macro to keep the namespace clean. */ -# pragma push_macro("bool") -# pragma push_macro("vector") -# pragma push_macro("pixel") -/* silence potential macro redefined warnings */ -# undef bool -# undef vector -# undef pixel - -# if defined(__s390x__) -# include -# else -# include -# endif - -/* Restore the original macro values, if applicable. */ -# pragma pop_macro("pixel") -# pragma pop_macro("vector") -# pragma pop_macro("bool") - -typedef __vector unsigned long long xxh_u64x2; -typedef __vector unsigned char xxh_u8x16; -typedef __vector unsigned xxh_u32x4; - -# ifndef XXH_VSX_BE -# if defined(__BIG_ENDIAN__) \ - || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) -# define XXH_VSX_BE 1 -# elif defined(__VEC_ELEMENT_REG_ORDER__) && __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__ -# warning "-maltivec=be is not recommended. Please use native endianness." -# define XXH_VSX_BE 1 -# else -# define XXH_VSX_BE 0 -# endif -# endif /* !defined(XXH_VSX_BE) */ - -# if XXH_VSX_BE -# if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__)) -# define XXH_vec_revb vec_revb -# else -/*! - * A polyfill for POWER9's vec_revb(). - */ -XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val) -{ - xxh_u8x16 const vByteSwap = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; - return vec_perm(val, val, vByteSwap); -} -# endif -# endif /* XXH_VSX_BE */ - -/*! - * Performs an unaligned vector load and byte swaps it on big endian. - */ -XXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr) -{ - xxh_u64x2 ret; - XXH_memcpy(&ret, ptr, sizeof(xxh_u64x2)); -# if XXH_VSX_BE - ret = XXH_vec_revb(ret); -# endif - return ret; -} - -/* - * vec_mulo and vec_mule are very problematic intrinsics on PowerPC - * - * These intrinsics weren't added until GCC 8, despite existing for a while, - * and they are endian dependent. Also, their meaning swap depending on version. - * */ -# if defined(__s390x__) - /* s390x is always big endian, no issue on this platform */ -# define XXH_vec_mulo vec_mulo -# define XXH_vec_mule vec_mule -# elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) -/* Clang has a better way to control this, we can just use the builtin which doesn't swap. */ -# define XXH_vec_mulo __builtin_altivec_vmulouw -# define XXH_vec_mule __builtin_altivec_vmuleuw -# else -/* gcc needs inline assembly */ -/* Adapted from https://github.com/google/highwayhash/blob/master/highwayhash/hh_vsx.h. */ -XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mulo(xxh_u32x4 a, xxh_u32x4 b) -{ - xxh_u64x2 result; - __asm__("vmulouw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); - return result; -} -XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b) -{ - xxh_u64x2 result; - __asm__("vmuleuw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); - return result; -} -# endif /* XXH_vec_mulo, XXH_vec_mule */ -#endif /* XXH_VECTOR == XXH_VSX */ - - -/* prefetch - * can be disabled, by declaring XXH_NO_PREFETCH build macro */ -#if defined(XXH_NO_PREFETCH) -# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ -#else -# if XXH_SIZE_OPT >= 1 -# define XXH_PREFETCH(ptr) (void)(ptr) -# elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() not defined outside of x86/x64 */ -# include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ -# define XXH_PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) -# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) -# define XXH_PREFETCH(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) -# else -# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ -# endif -#endif /* XXH_NO_PREFETCH */ - - -/* ========================================== - * XXH3 default settings - * ========================================== */ - -#define XXH_SECRET_DEFAULT_SIZE 192 /* minimum XXH3_SECRET_SIZE_MIN */ - -#if (XXH_SECRET_DEFAULT_SIZE < XXH3_SECRET_SIZE_MIN) -# error "default keyset is not large enough" -#endif - -/*! Pseudorandom secret taken directly from FARSH. */ -XXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = { - 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c, - 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f, - 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21, - 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c, - 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3, - 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8, - 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d, - 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64, - 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb, - 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e, - 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce, - 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e, -}; - - -#ifdef XXH_OLD_NAMES -# define kSecret XXH3_kSecret -#endif - -#ifdef XXH_DOXYGEN -/*! - * @brief Calculates a 32-bit to 64-bit long multiply. - * - * Implemented as a macro. - * - * Wraps `__emulu` on MSVC x86 because it tends to call `__allmul` when it doesn't - * need to (but it shouldn't need to anyways, it is about 7 instructions to do - * a 64x64 multiply...). Since we know that this will _always_ emit `MULL`, we - * use that instead of the normal method. - * - * If you are compiling for platforms like Thumb-1 and don't have a better option, - * you may also want to write your own long multiply routine here. - * - * @param x, y Numbers to be multiplied - * @return 64-bit product of the low 32 bits of @p x and @p y. - */ -XXH_FORCE_INLINE xxh_u64 -XXH_mult32to64(xxh_u64 x, xxh_u64 y) -{ - return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF); -} -#elif defined(_MSC_VER) && defined(_M_IX86) -# define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y)) -#else -/* - * Downcast + upcast is usually better than masking on older compilers like - * GCC 4.2 (especially 32-bit ones), all without affecting newer compilers. - * - * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both operands - * and perform a full 64x64 multiply -- entirely redundant on 32-bit. - */ -# define XXH_mult32to64(x, y) ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y)) -#endif - -/*! - * @brief Calculates a 64->128-bit long multiply. - * - * Uses `__uint128_t` and `_umul128` if available, otherwise uses a scalar - * version. - * - * @param lhs , rhs The 64-bit integers to be multiplied - * @return The 128-bit result represented in an @ref XXH128_hash_t. - */ -static XXH128_hash_t -XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs) -{ - /* - * GCC/Clang __uint128_t method. - * - * On most 64-bit targets, GCC and Clang define a __uint128_t type. - * This is usually the best way as it usually uses a native long 64-bit - * multiply, such as MULQ on x86_64 or MUL + UMULH on aarch64. - * - * Usually. - * - * Despite being a 32-bit platform, Clang (and emscripten) define this type - * despite not having the arithmetic for it. This results in a laggy - * compiler builtin call which calculates a full 128-bit multiply. - * In that case it is best to use the portable one. - * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677 - */ -#if (defined(__GNUC__) || defined(__clang__)) && !defined(__wasm__) \ - && defined(__SIZEOF_INT128__) \ - || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128) - - __uint128_t const product = (__uint128_t)lhs * (__uint128_t)rhs; - XXH128_hash_t r128; - r128.low64 = (xxh_u64)(product); - r128.high64 = (xxh_u64)(product >> 64); - return r128; - - /* - * MSVC for x64's _umul128 method. - * - * xxh_u64 _umul128(xxh_u64 Multiplier, xxh_u64 Multiplicand, xxh_u64 *HighProduct); - * - * This compiles to single operand MUL on x64. - */ -#elif (defined(_M_X64) || defined(_M_IA64)) && !defined(_M_ARM64EC) - -#ifndef _MSC_VER -# pragma intrinsic(_umul128) -#endif - xxh_u64 product_high; - xxh_u64 const product_low = _umul128(lhs, rhs, &product_high); - XXH128_hash_t r128; - r128.low64 = product_low; - r128.high64 = product_high; - return r128; - - /* - * MSVC for ARM64's __umulh method. - * - * This compiles to the same MUL + UMULH as GCC/Clang's __uint128_t method. - */ -#elif defined(_M_ARM64) || defined(_M_ARM64EC) - -#ifndef _MSC_VER -# pragma intrinsic(__umulh) -#endif - XXH128_hash_t r128; - r128.low64 = lhs * rhs; - r128.high64 = __umulh(lhs, rhs); - return r128; - -#else - /* - * Portable scalar method. Optimized for 32-bit and 64-bit ALUs. - * - * This is a fast and simple grade school multiply, which is shown below - * with base 10 arithmetic instead of base 0x100000000. - * - * 9 3 // D2 lhs = 93 - * x 7 5 // D2 rhs = 75 - * ---------- - * 1 5 // D2 lo_lo = (93 % 10) * (75 % 10) = 15 - * 4 5 | // D2 hi_lo = (93 / 10) * (75 % 10) = 45 - * 2 1 | // D2 lo_hi = (93 % 10) * (75 / 10) = 21 - * + 6 3 | | // D2 hi_hi = (93 / 10) * (75 / 10) = 63 - * --------- - * 2 7 | // D2 cross = (15 / 10) + (45 % 10) + 21 = 27 - * + 6 7 | | // D2 upper = (27 / 10) + (45 / 10) + 63 = 67 - * --------- - * 6 9 7 5 // D4 res = (27 * 10) + (15 % 10) + (67 * 100) = 6975 - * - * The reasons for adding the products like this are: - * 1. It avoids manual carry tracking. Just like how - * (9 * 9) + 9 + 9 = 99, the same applies with this for UINT64_MAX. - * This avoids a lot of complexity. - * - * 2. It hints for, and on Clang, compiles to, the powerful UMAAL - * instruction available in ARM's Digital Signal Processing extension - * in 32-bit ARMv6 and later, which is shown below: - * - * void UMAAL(xxh_u32 *RdLo, xxh_u32 *RdHi, xxh_u32 Rn, xxh_u32 Rm) - * { - * xxh_u64 product = (xxh_u64)*RdLo * (xxh_u64)*RdHi + Rn + Rm; - * *RdLo = (xxh_u32)(product & 0xFFFFFFFF); - * *RdHi = (xxh_u32)(product >> 32); - * } - * - * This instruction was designed for efficient long multiplication, and - * allows this to be calculated in only 4 instructions at speeds - * comparable to some 64-bit ALUs. - * - * 3. It isn't terrible on other platforms. Usually this will be a couple - * of 32-bit ADD/ADCs. - */ - - /* First calculate all of the cross products. */ - xxh_u64 const lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF); - xxh_u64 const hi_lo = XXH_mult32to64(lhs >> 32, rhs & 0xFFFFFFFF); - xxh_u64 const lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32); - xxh_u64 const hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32); - - /* Now add the products together. These will never overflow. */ - xxh_u64 const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi; - xxh_u64 const upper = (hi_lo >> 32) + (cross >> 32) + hi_hi; - xxh_u64 const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF); - - XXH128_hash_t r128; - r128.low64 = lower; - r128.high64 = upper; - return r128; -#endif -} - -/*! - * @brief Calculates a 64-bit to 128-bit multiply, then XOR folds it. - * - * The reason for the separate function is to prevent passing too many structs - * around by value. This will hopefully inline the multiply, but we don't force it. - * - * @param lhs , rhs The 64-bit integers to multiply - * @return The low 64 bits of the product XOR'd by the high 64 bits. - * @see XXH_mult64to128() - */ -static xxh_u64 -XXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs) -{ - XXH128_hash_t product = XXH_mult64to128(lhs, rhs); - return product.low64 ^ product.high64; -} - -/*! Seems to produce slightly better code on GCC for some reason. */ -XXH_FORCE_INLINE XXH_CONSTF xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift) -{ - XXH_ASSERT(0 <= shift && shift < 64); - return v64 ^ (v64 >> shift); -} - -/* - * This is a fast avalanche stage, - * suitable when input bits are already partially mixed - */ -static XXH64_hash_t XXH3_avalanche(xxh_u64 h64) -{ - h64 = XXH_xorshift64(h64, 37); - h64 *= 0x165667919E3779F9ULL; - h64 = XXH_xorshift64(h64, 32); - return h64; -} - -/* - * This is a stronger avalanche, - * inspired by Pelle Evensen's rrmxmx - * preferable when input has not been previously mixed - */ -static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len) -{ - /* this mix is inspired by Pelle Evensen's rrmxmx */ - h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24); - h64 *= 0x9FB21C651E98DF25ULL; - h64 ^= (h64 >> 35) + len ; - h64 *= 0x9FB21C651E98DF25ULL; - return XXH_xorshift64(h64, 28); -} - - -/* ========================================== - * Short keys - * ========================================== - * One of the shortcomings of XXH32 and XXH64 was that their performance was - * sub-optimal on short lengths. It used an iterative algorithm which strongly - * favored lengths that were a multiple of 4 or 8. - * - * Instead of iterating over individual inputs, we use a set of single shot - * functions which piece together a range of lengths and operate in constant time. - * - * Additionally, the number of multiplies has been significantly reduced. This - * reduces latency, especially when emulating 64-bit multiplies on 32-bit. - * - * Depending on the platform, this may or may not be faster than XXH32, but it - * is almost guaranteed to be faster than XXH64. - */ - -/* - * At very short lengths, there isn't enough input to fully hide secrets, or use - * the entire secret. - * - * There is also only a limited amount of mixing we can do before significantly - * impacting performance. - * - * Therefore, we use different sections of the secret and always mix two secret - * samples with an XOR. This should have no effect on performance on the - * seedless or withSeed variants because everything _should_ be constant folded - * by modern compilers. - * - * The XOR mixing hides individual parts of the secret and increases entropy. - * - * This adds an extra layer of strength for custom secrets. - */ -XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t -XXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) -{ - XXH_ASSERT(input != NULL); - XXH_ASSERT(1 <= len && len <= 3); - XXH_ASSERT(secret != NULL); - /* - * len = 1: combined = { input[0], 0x01, input[0], input[0] } - * len = 2: combined = { input[1], 0x02, input[0], input[1] } - * len = 3: combined = { input[2], 0x03, input[0], input[1] } - */ - { xxh_u8 const c1 = input[0]; - xxh_u8 const c2 = input[len >> 1]; - xxh_u8 const c3 = input[len - 1]; - xxh_u32 const combined = ((xxh_u32)c1 << 16) | ((xxh_u32)c2 << 24) - | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); - xxh_u64 const bitflip = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; - xxh_u64 const keyed = (xxh_u64)combined ^ bitflip; - return XXH64_avalanche(keyed); - } -} - -XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t -XXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) -{ - XXH_ASSERT(input != NULL); - XXH_ASSERT(secret != NULL); - XXH_ASSERT(4 <= len && len <= 8); - seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; - { xxh_u32 const input1 = XXH_readLE32(input); - xxh_u32 const input2 = XXH_readLE32(input + len - 4); - xxh_u64 const bitflip = (XXH_readLE64(secret+8) ^ XXH_readLE64(secret+16)) - seed; - xxh_u64 const input64 = input2 + (((xxh_u64)input1) << 32); - xxh_u64 const keyed = input64 ^ bitflip; - return XXH3_rrmxmx(keyed, len); - } -} - -XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t -XXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) -{ - XXH_ASSERT(input != NULL); - XXH_ASSERT(secret != NULL); - XXH_ASSERT(9 <= len && len <= 16); - { xxh_u64 const bitflip1 = (XXH_readLE64(secret+24) ^ XXH_readLE64(secret+32)) + seed; - xxh_u64 const bitflip2 = (XXH_readLE64(secret+40) ^ XXH_readLE64(secret+48)) - seed; - xxh_u64 const input_lo = XXH_readLE64(input) ^ bitflip1; - xxh_u64 const input_hi = XXH_readLE64(input + len - 8) ^ bitflip2; - xxh_u64 const acc = len - + XXH_swap64(input_lo) + input_hi - + XXH3_mul128_fold64(input_lo, input_hi); - return XXH3_avalanche(acc); - } -} - -XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t -XXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) -{ - XXH_ASSERT(len <= 16); - { if (XXH_likely(len > 8)) return XXH3_len_9to16_64b(input, len, secret, seed); - if (XXH_likely(len >= 4)) return XXH3_len_4to8_64b(input, len, secret, seed); - if (len) return XXH3_len_1to3_64b(input, len, secret, seed); - return XXH64_avalanche(seed ^ (XXH_readLE64(secret+56) ^ XXH_readLE64(secret+64))); - } -} - -/* - * DISCLAIMER: There are known *seed-dependent* multicollisions here due to - * multiplication by zero, affecting hashes of lengths 17 to 240. - * - * However, they are very unlikely. - * - * Keep this in mind when using the unseeded XXH3_64bits() variant: As with all - * unseeded non-cryptographic hashes, it does not attempt to defend itself - * against specially crafted inputs, only random inputs. - * - * Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes - * cancelling out the secret is taken an arbitrary number of times (addressed - * in XXH3_accumulate_512), this collision is very unlikely with random inputs - * and/or proper seeding: - * - * This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a - * function that is only called up to 16 times per hash with up to 240 bytes of - * input. - * - * This is not too bad for a non-cryptographic hash function, especially with - * only 64 bit outputs. - * - * The 128-bit variant (which trades some speed for strength) is NOT affected - * by this, although it is always a good idea to use a proper seed if you care - * about strength. - */ -XXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input, - const xxh_u8* XXH_RESTRICT secret, xxh_u64 seed64) -{ -#if defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ - && defined(__i386__) && defined(__SSE2__) /* x86 + SSE2 */ \ - && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable like XXH32 hack */ - /* - * UGLY HACK: - * GCC for x86 tends to autovectorize the 128-bit multiply, resulting in - * slower code. - * - * By forcing seed64 into a register, we disrupt the cost model and - * cause it to scalarize. See `XXH32_round()` - * - * FIXME: Clang's output is still _much_ faster -- On an AMD Ryzen 3600, - * XXH3_64bits @ len=240 runs at 4.6 GB/s with Clang 9, but 3.3 GB/s on - * GCC 9.2, despite both emitting scalar code. - * - * GCC generates much better scalar code than Clang for the rest of XXH3, - * which is why finding a more optimal codepath is an interest. - */ - XXH_COMPILER_GUARD(seed64); -#endif - { xxh_u64 const input_lo = XXH_readLE64(input); - xxh_u64 const input_hi = XXH_readLE64(input+8); - return XXH3_mul128_fold64( - input_lo ^ (XXH_readLE64(secret) + seed64), - input_hi ^ (XXH_readLE64(secret+8) - seed64) - ); - } -} - -/* For mid range keys, XXH3 uses a Mum-hash variant. */ -XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t -XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len, - const xxh_u8* XXH_RESTRICT secret, size_t secretSize, - XXH64_hash_t seed) -{ - XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; - XXH_ASSERT(16 < len && len <= 128); - - { xxh_u64 acc = len * XXH_PRIME64_1; -#if XXH_SIZE_OPT >= 1 - /* Smaller and cleaner, but slightly slower. */ - size_t i = (len - 1) / 32; - do { - acc += XXH3_mix16B(input+16 * i, secret+32*i, seed); - acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed); - } while (i-- != 0); -#else - if (len > 32) { - if (len > 64) { - if (len > 96) { - acc += XXH3_mix16B(input+48, secret+96, seed); - acc += XXH3_mix16B(input+len-64, secret+112, seed); - } - acc += XXH3_mix16B(input+32, secret+64, seed); - acc += XXH3_mix16B(input+len-48, secret+80, seed); - } - acc += XXH3_mix16B(input+16, secret+32, seed); - acc += XXH3_mix16B(input+len-32, secret+48, seed); - } - acc += XXH3_mix16B(input+0, secret+0, seed); - acc += XXH3_mix16B(input+len-16, secret+16, seed); -#endif - return XXH3_avalanche(acc); - } -} - -#define XXH3_MIDSIZE_MAX 240 - -XXH_NO_INLINE XXH_PUREF XXH64_hash_t -XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, - const xxh_u8* XXH_RESTRICT secret, size_t secretSize, - XXH64_hash_t seed) -{ - XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; - XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); - - #define XXH3_MIDSIZE_STARTOFFSET 3 - #define XXH3_MIDSIZE_LASTOFFSET 17 - - { xxh_u64 acc = len * XXH_PRIME64_1; - int const nbRounds = (int)len / 16; - int i; - for (i=0; i<8; i++) { - acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed); - } - acc = XXH3_avalanche(acc); - XXH_ASSERT(nbRounds >= 8); -#if defined(__clang__) /* Clang */ \ - && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ - && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ - /* - * UGLY HACK: - * Clang for ARMv7-A tries to vectorize this loop, similar to GCC x86. - * In everywhere else, it uses scalar code. - * - * For 64->128-bit multiplies, even if the NEON was 100% optimal, it - * would still be slower than UMAAL (see XXH_mult64to128). - * - * Unfortunately, Clang doesn't handle the long multiplies properly and - * converts them to the nonexistent "vmulq_u64" intrinsic, which is then - * scalarized into an ugly mess of VMOV.32 instructions. - * - * This mess is difficult to avoid without turning autovectorization - * off completely, but they are usually relatively minor and/or not - * worth it to fix. - * - * This loop is the easiest to fix, as unlike XXH32, this pragma - * _actually works_ because it is a loop vectorization instead of an - * SLP vectorization. - */ - #pragma clang loop vectorize(disable) -#endif - for (i=8 ; i < nbRounds; i++) { - acc += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed); - } - /* last bytes */ - acc += XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed); - return XXH3_avalanche(acc); - } -} - - -/* ======= Long Keys ======= */ - -#define XXH_STRIPE_LEN 64 -#define XXH_SECRET_CONSUME_RATE 8 /* nb of secret bytes consumed at each accumulation */ -#define XXH_ACC_NB (XXH_STRIPE_LEN / sizeof(xxh_u64)) - -#ifdef XXH_OLD_NAMES -# define STRIPE_LEN XXH_STRIPE_LEN -# define ACC_NB XXH_ACC_NB -#endif - -XXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64) -{ - if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64); - XXH_memcpy(dst, &v64, sizeof(v64)); -} - -/* Several intrinsic functions below are supposed to accept __int64 as argument, - * as documented in https://software.intel.com/sites/landingpage/IntrinsicsGuide/ . - * However, several environments do not define __int64 type, - * requiring a workaround. - */ -#if !defined (__VMS) \ - && (defined (__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) - typedef int64_t xxh_i64; -#else - /* the following type must have a width of 64-bit */ - typedef long long xxh_i64; -#endif - - -/* - * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized. - * - * It is a hardened version of UMAC, based off of FARSH's implementation. - * - * This was chosen because it adapts quite well to 32-bit, 64-bit, and SIMD - * implementations, and it is ridiculously fast. - * - * We harden it by mixing the original input to the accumulators as well as the product. - * - * This means that in the (relatively likely) case of a multiply by zero, the - * original input is preserved. - * - * On 128-bit inputs, we swap 64-bit pairs when we add the input to improve - * cross-pollination, as otherwise the upper and lower halves would be - * essentially independent. - * - * This doesn't matter on 64-bit hashes since they all get merged together in - * the end, so we skip the extra step. - * - * Both XXH3_64bits and XXH3_128bits use this subroutine. - */ - -#if (XXH_VECTOR == XXH_AVX512) \ - || (defined(XXH_DISPATCH_AVX512) && XXH_DISPATCH_AVX512 != 0) - -#ifndef XXH_TARGET_AVX512 -# define XXH_TARGET_AVX512 /* disable attribute target */ -#endif - -XXH_FORCE_INLINE XXH_TARGET_AVX512 void -XXH3_accumulate_512_avx512(void* XXH_RESTRICT acc, - const void* XXH_RESTRICT input, - const void* XXH_RESTRICT secret) -{ - __m512i* const xacc = (__m512i *) acc; - XXH_ASSERT((((size_t)acc) & 63) == 0); - XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); - - { - /* data_vec = input[0]; */ - __m512i const data_vec = _mm512_loadu_si512 (input); - /* key_vec = secret[0]; */ - __m512i const key_vec = _mm512_loadu_si512 (secret); - /* data_key = data_vec ^ key_vec; */ - __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec); - /* data_key_lo = data_key >> 32; */ - __m512i const data_key_lo = _mm512_shuffle_epi32 (data_key, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 3, 0, 1)); - /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ - __m512i const product = _mm512_mul_epu32 (data_key, data_key_lo); - /* xacc[0] += swap(data_vec); */ - __m512i const data_swap = _mm512_shuffle_epi32(data_vec, (_MM_PERM_ENUM)_MM_SHUFFLE(1, 0, 3, 2)); - __m512i const sum = _mm512_add_epi64(*xacc, data_swap); - /* xacc[0] += product; */ - *xacc = _mm512_add_epi64(product, sum); - } -} - -/* - * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing. - * - * Multiplication isn't perfect, as explained by Google in HighwayHash: - * - * // Multiplication mixes/scrambles bytes 0-7 of the 64-bit result to - * // varying degrees. In descending order of goodness, bytes - * // 3 4 2 5 1 6 0 7 have quality 228 224 164 160 100 96 36 32. - * // As expected, the upper and lower bytes are much worse. - * - * Source: https://github.com/google/highwayhash/blob/0aaf66b/highwayhash/hh_avx2.h#L291 - * - * Since our algorithm uses a pseudorandom secret to add some variance into the - * mix, we don't need to (or want to) mix as often or as much as HighwayHash does. - * - * This isn't as tight as XXH3_accumulate, but still written in SIMD to avoid - * extraction. - * - * Both XXH3_64bits and XXH3_128bits use this subroutine. - */ - -XXH_FORCE_INLINE XXH_TARGET_AVX512 void -XXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) -{ - XXH_ASSERT((((size_t)acc) & 63) == 0); - XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); - { __m512i* const xacc = (__m512i*) acc; - const __m512i prime32 = _mm512_set1_epi32((int)XXH_PRIME32_1); - - /* xacc[0] ^= (xacc[0] >> 47) */ - __m512i const acc_vec = *xacc; - __m512i const shifted = _mm512_srli_epi64 (acc_vec, 47); - __m512i const data_vec = _mm512_xor_si512 (acc_vec, shifted); - /* xacc[0] ^= secret; */ - __m512i const key_vec = _mm512_loadu_si512 (secret); - __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec); - - /* xacc[0] *= XXH_PRIME32_1; */ - __m512i const data_key_hi = _mm512_shuffle_epi32 (data_key, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 3, 0, 1)); - __m512i const prod_lo = _mm512_mul_epu32 (data_key, prime32); - __m512i const prod_hi = _mm512_mul_epu32 (data_key_hi, prime32); - *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32)); - } -} - -XXH_FORCE_INLINE XXH_TARGET_AVX512 void -XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64) -{ - XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0); - XXH_STATIC_ASSERT(XXH_SEC_ALIGN == 64); - XXH_ASSERT(((size_t)customSecret & 63) == 0); - (void)(&XXH_writeLE64); - { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i); - __m512i const seed = _mm512_mask_set1_epi64(_mm512_set1_epi64((xxh_i64)seed64), 0xAA, (xxh_i64)(0U - seed64)); - - const __m512i* const src = (const __m512i*) ((const void*) XXH3_kSecret); - __m512i* const dest = ( __m512i*) customSecret; - int i; - XXH_ASSERT(((size_t)src & 63) == 0); /* control alignment */ - XXH_ASSERT(((size_t)dest & 63) == 0); - for (i=0; i < nbRounds; ++i) { - /* GCC has a bug, _mm512_stream_load_si512 accepts 'void*', not 'void const*', - * this will warn "discards 'const' qualifier". */ - union { - const __m512i* cp; - void* p; - } remote_const_void; - remote_const_void.cp = src + i; - dest[i] = _mm512_add_epi64(_mm512_stream_load_si512(remote_const_void.p), seed); - } } -} - -#endif - -#if (XXH_VECTOR == XXH_AVX2) \ - || (defined(XXH_DISPATCH_AVX2) && XXH_DISPATCH_AVX2 != 0) - -#ifndef XXH_TARGET_AVX2 -# define XXH_TARGET_AVX2 /* disable attribute target */ -#endif - -XXH_FORCE_INLINE XXH_TARGET_AVX2 void -XXH3_accumulate_512_avx2( void* XXH_RESTRICT acc, - const void* XXH_RESTRICT input, - const void* XXH_RESTRICT secret) -{ - XXH_ASSERT((((size_t)acc) & 31) == 0); - { __m256i* const xacc = (__m256i *) acc; - /* Unaligned. This is mainly for pointer arithmetic, and because - * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ - const __m256i* const xinput = (const __m256i *) input; - /* Unaligned. This is mainly for pointer arithmetic, and because - * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ - const __m256i* const xsecret = (const __m256i *) secret; - - size_t i; - for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { - /* data_vec = xinput[i]; */ - __m256i const data_vec = _mm256_loadu_si256 (xinput+i); - /* key_vec = xsecret[i]; */ - __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); - /* data_key = data_vec ^ key_vec; */ - __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); - /* data_key_lo = data_key >> 32; */ - __m256i const data_key_lo = _mm256_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); - /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ - __m256i const product = _mm256_mul_epu32 (data_key, data_key_lo); - /* xacc[i] += swap(data_vec); */ - __m256i const data_swap = _mm256_shuffle_epi32(data_vec, _MM_SHUFFLE(1, 0, 3, 2)); - __m256i const sum = _mm256_add_epi64(xacc[i], data_swap); - /* xacc[i] += product; */ - xacc[i] = _mm256_add_epi64(product, sum); - } } -} - -XXH_FORCE_INLINE XXH_TARGET_AVX2 void -XXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) -{ - XXH_ASSERT((((size_t)acc) & 31) == 0); - { __m256i* const xacc = (__m256i*) acc; - /* Unaligned. This is mainly for pointer arithmetic, and because - * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ - const __m256i* const xsecret = (const __m256i *) secret; - const __m256i prime32 = _mm256_set1_epi32((int)XXH_PRIME32_1); - - size_t i; - for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { - /* xacc[i] ^= (xacc[i] >> 47) */ - __m256i const acc_vec = xacc[i]; - __m256i const shifted = _mm256_srli_epi64 (acc_vec, 47); - __m256i const data_vec = _mm256_xor_si256 (acc_vec, shifted); - /* xacc[i] ^= xsecret; */ - __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); - __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); - - /* xacc[i] *= XXH_PRIME32_1; */ - __m256i const data_key_hi = _mm256_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); - __m256i const prod_lo = _mm256_mul_epu32 (data_key, prime32); - __m256i const prod_hi = _mm256_mul_epu32 (data_key_hi, prime32); - xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32)); - } - } -} - -XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) -{ - XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 31) == 0); - XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE / sizeof(__m256i)) == 6); - XXH_STATIC_ASSERT(XXH_SEC_ALIGN <= 64); - (void)(&XXH_writeLE64); - XXH_PREFETCH(customSecret); - { __m256i const seed = _mm256_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64, (xxh_i64)(0U - seed64), (xxh_i64)seed64); - - const __m256i* const src = (const __m256i*) ((const void*) XXH3_kSecret); - __m256i* dest = ( __m256i*) customSecret; - -# if defined(__GNUC__) || defined(__clang__) - /* - * On GCC & Clang, marking 'dest' as modified will cause the compiler: - * - do not extract the secret from sse registers in the internal loop - * - use less common registers, and avoid pushing these reg into stack - */ - XXH_COMPILER_GUARD(dest); -# endif - XXH_ASSERT(((size_t)src & 31) == 0); /* control alignment */ - XXH_ASSERT(((size_t)dest & 31) == 0); - - /* GCC -O2 need unroll loop manually */ - dest[0] = _mm256_add_epi64(_mm256_stream_load_si256(src+0), seed); - dest[1] = _mm256_add_epi64(_mm256_stream_load_si256(src+1), seed); - dest[2] = _mm256_add_epi64(_mm256_stream_load_si256(src+2), seed); - dest[3] = _mm256_add_epi64(_mm256_stream_load_si256(src+3), seed); - dest[4] = _mm256_add_epi64(_mm256_stream_load_si256(src+4), seed); - dest[5] = _mm256_add_epi64(_mm256_stream_load_si256(src+5), seed); - } -} - -#endif - -/* x86dispatch always generates SSE2 */ -#if (XXH_VECTOR == XXH_SSE2) || defined(XXH_X86DISPATCH) - -#ifndef XXH_TARGET_SSE2 -# define XXH_TARGET_SSE2 /* disable attribute target */ -#endif - -XXH_FORCE_INLINE XXH_TARGET_SSE2 void -XXH3_accumulate_512_sse2( void* XXH_RESTRICT acc, - const void* XXH_RESTRICT input, - const void* XXH_RESTRICT secret) -{ - /* SSE2 is just a half-scale version of the AVX2 version. */ - XXH_ASSERT((((size_t)acc) & 15) == 0); - { __m128i* const xacc = (__m128i *) acc; - /* Unaligned. This is mainly for pointer arithmetic, and because - * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ - const __m128i* const xinput = (const __m128i *) input; - /* Unaligned. This is mainly for pointer arithmetic, and because - * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ - const __m128i* const xsecret = (const __m128i *) secret; - - size_t i; - for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { - /* data_vec = xinput[i]; */ - __m128i const data_vec = _mm_loadu_si128 (xinput+i); - /* key_vec = xsecret[i]; */ - __m128i const key_vec = _mm_loadu_si128 (xsecret+i); - /* data_key = data_vec ^ key_vec; */ - __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); - /* data_key_lo = data_key >> 32; */ - __m128i const data_key_lo = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); - /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ - __m128i const product = _mm_mul_epu32 (data_key, data_key_lo); - /* xacc[i] += swap(data_vec); */ - __m128i const data_swap = _mm_shuffle_epi32(data_vec, _MM_SHUFFLE(1,0,3,2)); - __m128i const sum = _mm_add_epi64(xacc[i], data_swap); - /* xacc[i] += product; */ - xacc[i] = _mm_add_epi64(product, sum); - } } -} - -XXH_FORCE_INLINE XXH_TARGET_SSE2 void -XXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) -{ - XXH_ASSERT((((size_t)acc) & 15) == 0); - { __m128i* const xacc = (__m128i*) acc; - /* Unaligned. This is mainly for pointer arithmetic, and because - * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ - const __m128i* const xsecret = (const __m128i *) secret; - const __m128i prime32 = _mm_set1_epi32((int)XXH_PRIME32_1); - - size_t i; - for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { - /* xacc[i] ^= (xacc[i] >> 47) */ - __m128i const acc_vec = xacc[i]; - __m128i const shifted = _mm_srli_epi64 (acc_vec, 47); - __m128i const data_vec = _mm_xor_si128 (acc_vec, shifted); - /* xacc[i] ^= xsecret[i]; */ - __m128i const key_vec = _mm_loadu_si128 (xsecret+i); - __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); - - /* xacc[i] *= XXH_PRIME32_1; */ - __m128i const data_key_hi = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); - __m128i const prod_lo = _mm_mul_epu32 (data_key, prime32); - __m128i const prod_hi = _mm_mul_epu32 (data_key_hi, prime32); - xacc[i] = _mm_add_epi64(prod_lo, _mm_slli_epi64(prod_hi, 32)); - } - } -} - -XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) -{ - XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); - (void)(&XXH_writeLE64); - { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m128i); - -# if defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER < 1900 - /* MSVC 32bit mode does not support _mm_set_epi64x before 2015 */ - XXH_ALIGN(16) const xxh_i64 seed64x2[2] = { (xxh_i64)seed64, (xxh_i64)(0U - seed64) }; - __m128i const seed = _mm_load_si128((__m128i const*)seed64x2); -# else - __m128i const seed = _mm_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64); -# endif - int i; - - const void* const src16 = XXH3_kSecret; - __m128i* dst16 = (__m128i*) customSecret; -# if defined(__GNUC__) || defined(__clang__) - /* - * On GCC & Clang, marking 'dest' as modified will cause the compiler: - * - do not extract the secret from sse registers in the internal loop - * - use less common registers, and avoid pushing these reg into stack - */ - XXH_COMPILER_GUARD(dst16); -# endif - XXH_ASSERT(((size_t)src16 & 15) == 0); /* control alignment */ - XXH_ASSERT(((size_t)dst16 & 15) == 0); - - for (i=0; i < nbRounds; ++i) { - dst16[i] = _mm_add_epi64(_mm_load_si128((const __m128i *)src16+i), seed); - } } -} - -#endif - -#if (XXH_VECTOR == XXH_NEON) - -/* forward declarations for the scalar routines */ -XXH_FORCE_INLINE void -XXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input, - void const* XXH_RESTRICT secret, size_t lane); - -XXH_FORCE_INLINE void -XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, - void const* XXH_RESTRICT secret, size_t lane); - -/*! - * @internal - * @brief The bulk processing loop for NEON. - * - * The NEON code path is actually partially scalar when running on AArch64. This - * is to optimize the pipelining and can have up to 15% speedup depending on the - * CPU, and it also mitigates some GCC codegen issues. - * - * @see XXH3_NEON_LANES for configuring this and details about this optimization. - */ -XXH_FORCE_INLINE void -XXH3_accumulate_512_neon( void* XXH_RESTRICT acc, - const void* XXH_RESTRICT input, - const void* XXH_RESTRICT secret) -{ - XXH_ASSERT((((size_t)acc) & 15) == 0); - XXH_STATIC_ASSERT(XXH3_NEON_LANES > 0 && XXH3_NEON_LANES <= XXH_ACC_NB && XXH3_NEON_LANES % 2 == 0); - { - uint64x2_t* const xacc = (uint64x2_t *) acc; - /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */ - uint8_t const* const xinput = (const uint8_t *) input; - uint8_t const* const xsecret = (const uint8_t *) secret; - - size_t i; - /* AArch64 uses both scalar and neon at the same time */ - for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { - XXH3_scalarRound(acc, input, secret, i); - } - for (i=0; i < XXH3_NEON_LANES / 2; i++) { - uint64x2_t acc_vec = xacc[i]; - /* data_vec = xinput[i]; */ - uint64x2_t data_vec = XXH_vld1q_u64(xinput + (i * 16)); - /* key_vec = xsecret[i]; */ - uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); - uint64x2_t data_key; - uint32x2_t data_key_lo, data_key_hi; - /* acc_vec_2 = swap(data_vec) */ - uint64x2_t acc_vec_2 = vextq_u64(data_vec, data_vec, 1); - /* data_key = data_vec ^ key_vec; */ - data_key = veorq_u64(data_vec, key_vec); - /* data_key_lo = (uint32x2_t) (data_key & 0xFFFFFFFF); - * data_key_hi = (uint32x2_t) (data_key >> 32); - * data_key = UNDEFINED; */ - XXH_SPLIT_IN_PLACE(data_key, data_key_lo, data_key_hi); - /* acc_vec_2 += (uint64x2_t) data_key_lo * (uint64x2_t) data_key_hi; */ - acc_vec_2 = vmlal_u32 (acc_vec_2, data_key_lo, data_key_hi); - /* xacc[i] += acc_vec_2; */ - acc_vec = vaddq_u64 (acc_vec, acc_vec_2); - xacc[i] = acc_vec; - } - - } -} - -XXH_FORCE_INLINE void -XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) -{ - XXH_ASSERT((((size_t)acc) & 15) == 0); - - { uint64x2_t* xacc = (uint64x2_t*) acc; - uint8_t const* xsecret = (uint8_t const*) secret; - uint32x2_t prime = vdup_n_u32 (XXH_PRIME32_1); - - size_t i; - /* AArch64 uses both scalar and neon at the same time */ - for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { - XXH3_scalarScrambleRound(acc, secret, i); - } - for (i=0; i < XXH3_NEON_LANES / 2; i++) { - /* xacc[i] ^= (xacc[i] >> 47); */ - uint64x2_t acc_vec = xacc[i]; - uint64x2_t shifted = vshrq_n_u64 (acc_vec, 47); - uint64x2_t data_vec = veorq_u64 (acc_vec, shifted); - - /* xacc[i] ^= xsecret[i]; */ - uint64x2_t key_vec = XXH_vld1q_u64 (xsecret + (i * 16)); - uint64x2_t data_key = veorq_u64 (data_vec, key_vec); - - /* xacc[i] *= XXH_PRIME32_1 */ - uint32x2_t data_key_lo, data_key_hi; - /* data_key_lo = (uint32x2_t) (xacc[i] & 0xFFFFFFFF); - * data_key_hi = (uint32x2_t) (xacc[i] >> 32); - * xacc[i] = UNDEFINED; */ - XXH_SPLIT_IN_PLACE(data_key, data_key_lo, data_key_hi); - { /* - * prod_hi = (data_key >> 32) * XXH_PRIME32_1; - * - * Avoid vmul_u32 + vshll_n_u32 since Clang 6 and 7 will - * incorrectly "optimize" this: - * tmp = vmul_u32(vmovn_u64(a), vmovn_u64(b)); - * shifted = vshll_n_u32(tmp, 32); - * to this: - * tmp = "vmulq_u64"(a, b); // no such thing! - * shifted = vshlq_n_u64(tmp, 32); - * - * However, unlike SSE, Clang lacks a 64-bit multiply routine - * for NEON, and it scalarizes two 64-bit multiplies instead. - * - * vmull_u32 has the same timing as vmul_u32, and it avoids - * this bug completely. - * See https://bugs.llvm.org/show_bug.cgi?id=39967 - */ - uint64x2_t prod_hi = vmull_u32 (data_key_hi, prime); - /* xacc[i] = prod_hi << 32; */ - prod_hi = vshlq_n_u64(prod_hi, 32); - /* xacc[i] += (prod_hi & 0xFFFFFFFF) * XXH_PRIME32_1; */ - xacc[i] = vmlal_u32(prod_hi, data_key_lo, prime); - } - } - } -} - -#endif - -#if (XXH_VECTOR == XXH_VSX) - -XXH_FORCE_INLINE void -XXH3_accumulate_512_vsx( void* XXH_RESTRICT acc, - const void* XXH_RESTRICT input, - const void* XXH_RESTRICT secret) -{ - /* presumed aligned */ - unsigned int* const xacc = (unsigned int*) acc; - xxh_u64x2 const* const xinput = (xxh_u64x2 const*) input; /* no alignment restriction */ - xxh_u64x2 const* const xsecret = (xxh_u64x2 const*) secret; /* no alignment restriction */ - xxh_u64x2 const v32 = { 32, 32 }; - size_t i; - for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { - /* data_vec = xinput[i]; */ - xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + i); - /* key_vec = xsecret[i]; */ - xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + i); - xxh_u64x2 const data_key = data_vec ^ key_vec; - /* shuffled = (data_key << 32) | (data_key >> 32); */ - xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32); - /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */ - xxh_u64x2 const product = XXH_vec_mulo((xxh_u32x4)data_key, shuffled); - /* acc_vec = xacc[i]; */ - xxh_u64x2 acc_vec = (xxh_u64x2)vec_xl(0, xacc + 4 * i); - acc_vec += product; - - /* swap high and low halves */ -#ifdef __s390x__ - acc_vec += vec_permi(data_vec, data_vec, 2); -#else - acc_vec += vec_xxpermdi(data_vec, data_vec, 2); -#endif - /* xacc[i] = acc_vec; */ - vec_xst((xxh_u32x4)acc_vec, 0, xacc + 4 * i); - } -} - -XXH_FORCE_INLINE void -XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) -{ - XXH_ASSERT((((size_t)acc) & 15) == 0); - - { xxh_u64x2* const xacc = (xxh_u64x2*) acc; - const xxh_u64x2* const xsecret = (const xxh_u64x2*) secret; - /* constants */ - xxh_u64x2 const v32 = { 32, 32 }; - xxh_u64x2 const v47 = { 47, 47 }; - xxh_u32x4 const prime = { XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1 }; - size_t i; - for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { - /* xacc[i] ^= (xacc[i] >> 47); */ - xxh_u64x2 const acc_vec = xacc[i]; - xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47); - - /* xacc[i] ^= xsecret[i]; */ - xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + i); - xxh_u64x2 const data_key = data_vec ^ key_vec; - - /* xacc[i] *= XXH_PRIME32_1 */ - /* prod_lo = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)prime & 0xFFFFFFFF); */ - xxh_u64x2 const prod_even = XXH_vec_mule((xxh_u32x4)data_key, prime); - /* prod_hi = ((xxh_u64x2)data_key >> 32) * ((xxh_u64x2)prime >> 32); */ - xxh_u64x2 const prod_odd = XXH_vec_mulo((xxh_u32x4)data_key, prime); - xacc[i] = prod_odd + (prod_even << v32); - } } -} - -#endif - -/* scalar variants - universal */ - -/*! - * @internal - * @brief Scalar round for @ref XXH3_accumulate_512_scalar(). - * - * This is extracted to its own function because the NEON path uses a combination - * of NEON and scalar. - */ -XXH_FORCE_INLINE void -XXH3_scalarRound(void* XXH_RESTRICT acc, - void const* XXH_RESTRICT input, - void const* XXH_RESTRICT secret, - size_t lane) -{ - xxh_u64* xacc = (xxh_u64*) acc; - xxh_u8 const* xinput = (xxh_u8 const*) input; - xxh_u8 const* xsecret = (xxh_u8 const*) secret; - XXH_ASSERT(lane < XXH_ACC_NB); - XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0); - { - xxh_u64 const data_val = XXH_readLE64(xinput + lane * 8); - xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + lane * 8); - xacc[lane ^ 1] += data_val; /* swap adjacent lanes */ - xacc[lane] += XXH_mult32to64(data_key & 0xFFFFFFFF, data_key >> 32); - } -} - -/*! - * @internal - * @brief Processes a 64 byte block of data using the scalar path. - */ -XXH_FORCE_INLINE void -XXH3_accumulate_512_scalar(void* XXH_RESTRICT acc, - const void* XXH_RESTRICT input, - const void* XXH_RESTRICT secret) -{ - size_t i; - /* ARM GCC refuses to unroll this loop, resulting in a 24% slowdown on ARMv6. */ -#if defined(__GNUC__) && !defined(__clang__) \ - && (defined(__arm__) || defined(__thumb2__)) \ - && defined(__ARM_FEATURE_UNALIGNED) /* no unaligned access just wastes bytes */ \ - && XXH_SIZE_OPT <= 0 -# pragma GCC unroll 8 -#endif - for (i=0; i < XXH_ACC_NB; i++) { - XXH3_scalarRound(acc, input, secret, i); - } -} - -/*! - * @internal - * @brief Scalar scramble step for @ref XXH3_scrambleAcc_scalar(). - * - * This is extracted to its own function because the NEON path uses a combination - * of NEON and scalar. - */ -XXH_FORCE_INLINE void -XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, - void const* XXH_RESTRICT secret, - size_t lane) -{ - xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */ - const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */ - XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0); - XXH_ASSERT(lane < XXH_ACC_NB); - { - xxh_u64 const key64 = XXH_readLE64(xsecret + lane * 8); - xxh_u64 acc64 = xacc[lane]; - acc64 = XXH_xorshift64(acc64, 47); - acc64 ^= key64; - acc64 *= XXH_PRIME32_1; - xacc[lane] = acc64; - } -} - -/*! - * @internal - * @brief Scrambles the accumulators after a large chunk has been read - */ -XXH_FORCE_INLINE void -XXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) -{ - size_t i; - for (i=0; i < XXH_ACC_NB; i++) { - XXH3_scalarScrambleRound(acc, secret, i); - } -} - -XXH_FORCE_INLINE void -XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64) -{ - /* - * We need a separate pointer for the hack below, - * which requires a non-const pointer. - * Any decent compiler will optimize this out otherwise. - */ - const xxh_u8* kSecretPtr = XXH3_kSecret; - XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); - -#if defined(__clang__) && defined(__aarch64__) - /* - * UGLY HACK: - * Clang generates a bunch of MOV/MOVK pairs for aarch64, and they are - * placed sequentially, in order, at the top of the unrolled loop. - * - * While MOVK is great for generating constants (2 cycles for a 64-bit - * constant compared to 4 cycles for LDR), it fights for bandwidth with - * the arithmetic instructions. - * - * I L S - * MOVK - * MOVK - * MOVK - * MOVK - * ADD - * SUB STR - * STR - * By forcing loads from memory (as the asm line causes Clang to assume - * that XXH3_kSecretPtr has been changed), the pipelines are used more - * efficiently: - * I L S - * LDR - * ADD LDR - * SUB STR - * STR - * - * See XXH3_NEON_LANES for details on the pipsline. - * - * XXH3_64bits_withSeed, len == 256, Snapdragon 835 - * without hack: 2654.4 MB/s - * with hack: 3202.9 MB/s - */ - XXH_COMPILER_GUARD(kSecretPtr); -#endif - /* - * Note: in debug mode, this overrides the asm optimization - * and Clang will emit MOVK chains again. - */ - XXH_ASSERT(kSecretPtr == XXH3_kSecret); - - { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16; - int i; - for (i=0; i < nbRounds; i++) { - /* - * The asm hack causes Clang to assume that kSecretPtr aliases with - * customSecret, and on aarch64, this prevented LDP from merging two - * loads together for free. Putting the loads together before the stores - * properly generates LDP. - */ - xxh_u64 lo = XXH_readLE64(kSecretPtr + 16*i) + seed64; - xxh_u64 hi = XXH_readLE64(kSecretPtr + 16*i + 8) - seed64; - XXH_writeLE64((xxh_u8*)customSecret + 16*i, lo); - XXH_writeLE64((xxh_u8*)customSecret + 16*i + 8, hi); - } } -} - - -typedef void (*XXH3_f_accumulate_512)(void* XXH_RESTRICT, const void*, const void*); -typedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*); -typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64); - - -#if (XXH_VECTOR == XXH_AVX512) - -#define XXH3_accumulate_512 XXH3_accumulate_512_avx512 -#define XXH3_scrambleAcc XXH3_scrambleAcc_avx512 -#define XXH3_initCustomSecret XXH3_initCustomSecret_avx512 - -#elif (XXH_VECTOR == XXH_AVX2) - -#define XXH3_accumulate_512 XXH3_accumulate_512_avx2 -#define XXH3_scrambleAcc XXH3_scrambleAcc_avx2 -#define XXH3_initCustomSecret XXH3_initCustomSecret_avx2 - -#elif (XXH_VECTOR == XXH_SSE2) - -#define XXH3_accumulate_512 XXH3_accumulate_512_sse2 -#define XXH3_scrambleAcc XXH3_scrambleAcc_sse2 -#define XXH3_initCustomSecret XXH3_initCustomSecret_sse2 - -#elif (XXH_VECTOR == XXH_NEON) - -#define XXH3_accumulate_512 XXH3_accumulate_512_neon -#define XXH3_scrambleAcc XXH3_scrambleAcc_neon -#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar - -#elif (XXH_VECTOR == XXH_VSX) - -#define XXH3_accumulate_512 XXH3_accumulate_512_vsx -#define XXH3_scrambleAcc XXH3_scrambleAcc_vsx -#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar - -#else /* scalar */ - -#define XXH3_accumulate_512 XXH3_accumulate_512_scalar -#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar -#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar - -#endif - -#if XXH_SIZE_OPT >= 1 /* don't do SIMD for initialization */ -# undef XXH3_initCustomSecret -# define XXH3_initCustomSecret XXH3_initCustomSecret_scalar -#endif - -#ifndef XXH_PREFETCH_DIST -# ifdef __clang__ -# define XXH_PREFETCH_DIST 320 -# else -# if (XXH_VECTOR == XXH_AVX512) -# define XXH_PREFETCH_DIST 512 -# else -# define XXH_PREFETCH_DIST 384 -# endif -# endif /* __clang__ */ -#endif /* XXH_PREFETCH_DIST */ - -/* - * XXH3_accumulate() - * Loops over XXH3_accumulate_512(). - * Assumption: nbStripes will not overflow the secret size - */ -XXH_FORCE_INLINE void -XXH3_accumulate( xxh_u64* XXH_RESTRICT acc, - const xxh_u8* XXH_RESTRICT input, - const xxh_u8* XXH_RESTRICT secret, - size_t nbStripes, - XXH3_f_accumulate_512 f_acc512) -{ - size_t n; - for (n = 0; n < nbStripes; n++ ) { - const xxh_u8* const in = input + n*XXH_STRIPE_LEN; - XXH_PREFETCH(in + XXH_PREFETCH_DIST); - f_acc512(acc, - in, - secret + n*XXH_SECRET_CONSUME_RATE); - } -} - -XXH_FORCE_INLINE void -XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc, - const xxh_u8* XXH_RESTRICT input, size_t len, - const xxh_u8* XXH_RESTRICT secret, size_t secretSize, - XXH3_f_accumulate_512 f_acc512, - XXH3_f_scrambleAcc f_scramble) -{ - size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE; - size_t const block_len = XXH_STRIPE_LEN * nbStripesPerBlock; - size_t const nb_blocks = (len - 1) / block_len; - - size_t n; - - XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); - - for (n = 0; n < nb_blocks; n++) { - XXH3_accumulate(acc, input + n*block_len, secret, nbStripesPerBlock, f_acc512); - f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN); - } - - /* last partial block */ - XXH_ASSERT(len > XXH_STRIPE_LEN); - { size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN; - XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE)); - XXH3_accumulate(acc, input + nb_blocks*block_len, secret, nbStripes, f_acc512); - - /* last stripe */ - { const xxh_u8* const p = input + len - XXH_STRIPE_LEN; -#define XXH_SECRET_LASTACC_START 7 /* not aligned on 8, last secret is different from acc & scrambler */ - f_acc512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START); - } } -} - -XXH_FORCE_INLINE xxh_u64 -XXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret) -{ - return XXH3_mul128_fold64( - acc[0] ^ XXH_readLE64(secret), - acc[1] ^ XXH_readLE64(secret+8) ); -} - -static XXH64_hash_t -XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start) -{ - xxh_u64 result64 = start; - size_t i = 0; - - for (i = 0; i < 4; i++) { - result64 += XXH3_mix2Accs(acc+2*i, secret + 16*i); -#if defined(__clang__) /* Clang */ \ - && (defined(__arm__) || defined(__thumb__)) /* ARMv7 */ \ - && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ - && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ - /* - * UGLY HACK: - * Prevent autovectorization on Clang ARMv7-a. Exact same problem as - * the one in XXH3_len_129to240_64b. Speeds up shorter keys > 240b. - * XXH3_64bits, len == 256, Snapdragon 835: - * without hack: 2063.7 MB/s - * with hack: 2560.7 MB/s - */ - XXH_COMPILER_GUARD(result64); -#endif - } - - return XXH3_avalanche(result64); -} - -#define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \ - XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 } - -XXH_FORCE_INLINE XXH64_hash_t -XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len, - const void* XXH_RESTRICT secret, size_t secretSize, - XXH3_f_accumulate_512 f_acc512, - XXH3_f_scrambleAcc f_scramble) -{ - XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; - - XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc512, f_scramble); - - /* converge into final hash */ - XXH_STATIC_ASSERT(sizeof(acc) == 64); - /* do not align on 8, so that the secret is different from the accumulator */ -#define XXH_SECRET_MERGEACCS_START 11 - XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); - return XXH3_mergeAccs(acc, (const xxh_u8*)secret + XXH_SECRET_MERGEACCS_START, (xxh_u64)len * XXH_PRIME64_1); -} - -/* - * It's important for performance to transmit secret's size (when it's static) - * so that the compiler can properly optimize the vectorized loop. - * This makes a big performance difference for "medium" keys (<1 KB) when using AVX instruction set. - */ -XXH_FORCE_INLINE XXH64_hash_t -XXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len, - XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) -{ - (void)seed64; - return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate_512, XXH3_scrambleAcc); -} - -/* - * It's preferable for performance that XXH3_hashLong is not inlined, - * as it results in a smaller function for small data, easier to the instruction cache. - * Note that inside this no_inline function, we do inline the internal loop, - * and provide a statically defined secret size to allow optimization of vector loop. - */ -XXH_NO_INLINE XXH_PUREF XXH64_hash_t -XXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len, - XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) -{ - (void)seed64; (void)secret; (void)secretLen; - return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate_512, XXH3_scrambleAcc); -} - -/* - * XXH3_hashLong_64b_withSeed(): - * Generate a custom key based on alteration of default XXH3_kSecret with the seed, - * and then use this key for long mode hashing. - * - * This operation is decently fast but nonetheless costs a little bit of time. - * Try to avoid it whenever possible (typically when seed==0). - * - * It's important for performance that XXH3_hashLong is not inlined. Not sure - * why (uop cache maybe?), but the difference is large and easily measurable. - */ -XXH_FORCE_INLINE XXH64_hash_t -XXH3_hashLong_64b_withSeed_internal(const void* input, size_t len, - XXH64_hash_t seed, - XXH3_f_accumulate_512 f_acc512, - XXH3_f_scrambleAcc f_scramble, - XXH3_f_initCustomSecret f_initSec) -{ -#if XXH_SIZE_OPT <= 0 - if (seed == 0) - return XXH3_hashLong_64b_internal(input, len, - XXH3_kSecret, sizeof(XXH3_kSecret), - f_acc512, f_scramble); -#endif - { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; - f_initSec(secret, seed); - return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret), - f_acc512, f_scramble); - } -} - -/* - * It's important for performance that XXH3_hashLong is not inlined. - */ -XXH_NO_INLINE XXH64_hash_t -XXH3_hashLong_64b_withSeed(const void* input, size_t len, - XXH64_hash_t seed, const xxh_u8* secret, size_t secretLen) -{ - (void)secret; (void)secretLen; - return XXH3_hashLong_64b_withSeed_internal(input, len, seed, - XXH3_accumulate_512, XXH3_scrambleAcc, XXH3_initCustomSecret); -} - - -typedef XXH64_hash_t (*XXH3_hashLong64_f)(const void* XXH_RESTRICT, size_t, - XXH64_hash_t, const xxh_u8* XXH_RESTRICT, size_t); - -XXH_FORCE_INLINE XXH64_hash_t -XXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len, - XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, - XXH3_hashLong64_f f_hashLong) -{ - XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); - /* - * If an action is to be taken if `secretLen` condition is not respected, - * it should be done here. - * For now, it's a contract pre-condition. - * Adding a check and a branch here would cost performance at every hash. - * Also, note that function signature doesn't offer room to return an error. - */ - if (len <= 16) - return XXH3_len_0to16_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); - if (len <= 128) - return XXH3_len_17to128_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); - if (len <= XXH3_MIDSIZE_MAX) - return XXH3_len_129to240_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); - return f_hashLong(input, len, seed64, (const xxh_u8*)secret, secretLen); -} - - -/* === Public entry point === */ - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(const void* input, size_t length) -{ - return XXH3_64bits_internal(input, length, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH64_hash_t -XXH3_64bits_withSecret(const void* input, size_t length, const void* secret, size_t secretSize) -{ - return XXH3_64bits_internal(input, length, 0, secret, secretSize, XXH3_hashLong_64b_withSecret); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH64_hash_t -XXH3_64bits_withSeed(const void* input, size_t length, XXH64_hash_t seed) -{ - return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed); -} - -XXH_PUBLIC_API XXH64_hash_t -XXH3_64bits_withSecretandSeed(const void* input, size_t length, const void* secret, size_t secretSize, XXH64_hash_t seed) -{ - if (length <= XXH3_MIDSIZE_MAX) - return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); - return XXH3_hashLong_64b_withSecret(input, length, seed, (const xxh_u8*)secret, secretSize); -} - - -/* === XXH3 streaming === */ -#ifndef XXH_NO_STREAM -/* - * Malloc's a pointer that is always aligned to align. - * - * This must be freed with `XXH_alignedFree()`. - * - * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte - * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2 - * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON. - * - * This underalignment previously caused a rather obvious crash which went - * completely unnoticed due to XXH3_createState() not actually being tested. - * Credit to RedSpah for noticing this bug. - * - * The alignment is done manually: Functions like posix_memalign or _mm_malloc - * are avoided: To maintain portability, we would have to write a fallback - * like this anyways, and besides, testing for the existence of library - * functions without relying on external build tools is impossible. - * - * The method is simple: Overallocate, manually align, and store the offset - * to the original behind the returned pointer. - * - * Align must be a power of 2 and 8 <= align <= 128. - */ -static XXH_MALLOCF void* XXH_alignedMalloc(size_t s, size_t align) -{ - XXH_ASSERT(align <= 128 && align >= 8); /* range check */ - XXH_ASSERT((align & (align-1)) == 0); /* power of 2 */ - XXH_ASSERT(s != 0 && s < (s + align)); /* empty/overflow */ - { /* Overallocate to make room for manual realignment and an offset byte */ - xxh_u8* base = (xxh_u8*)XXH_malloc(s + align); - if (base != NULL) { - /* - * Get the offset needed to align this pointer. - * - * Even if the returned pointer is aligned, there will always be - * at least one byte to store the offset to the original pointer. - */ - size_t offset = align - ((size_t)base & (align - 1)); /* base % align */ - /* Add the offset for the now-aligned pointer */ - xxh_u8* ptr = base + offset; - - XXH_ASSERT((size_t)ptr % align == 0); - - /* Store the offset immediately before the returned pointer. */ - ptr[-1] = (xxh_u8)offset; - return ptr; - } - return NULL; - } -} -/* - * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass - * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout. - */ -static void XXH_alignedFree(void* p) -{ - if (p != NULL) { - xxh_u8* ptr = (xxh_u8*)p; - /* Get the offset byte we added in XXH_malloc. */ - xxh_u8 offset = ptr[-1]; - /* Free the original malloc'd pointer */ - xxh_u8* base = ptr - offset; - XXH_free(base); - } -} -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void) -{ - XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64); - if (state==NULL) return NULL; - XXH3_INITSTATE(state); - return state; -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr) -{ - XXH_alignedFree(statePtr); - return XXH_OK; -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API void -XXH3_copyState(XXH3_state_t* dst_state, const XXH3_state_t* src_state) -{ - XXH_memcpy(dst_state, src_state, sizeof(*dst_state)); -} - -static void -XXH3_reset_internal(XXH3_state_t* statePtr, - XXH64_hash_t seed, - const void* secret, size_t secretSize) -{ - size_t const initStart = offsetof(XXH3_state_t, bufferedSize); - size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart; - XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart); - XXH_ASSERT(statePtr != NULL); - /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */ - memset((char*)statePtr + initStart, 0, initLength); - statePtr->acc[0] = XXH_PRIME32_3; - statePtr->acc[1] = XXH_PRIME64_1; - statePtr->acc[2] = XXH_PRIME64_2; - statePtr->acc[3] = XXH_PRIME64_3; - statePtr->acc[4] = XXH_PRIME64_4; - statePtr->acc[5] = XXH_PRIME32_2; - statePtr->acc[6] = XXH_PRIME64_5; - statePtr->acc[7] = XXH_PRIME32_1; - statePtr->seed = seed; - statePtr->useSeed = (seed != 0); - statePtr->extSecret = (const unsigned char*)secret; - XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); - statePtr->secretLimit = secretSize - XXH_STRIPE_LEN; - statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE; -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_reset(XXH3_state_t* statePtr) -{ - if (statePtr == NULL) return XXH_ERROR; - XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE); - return XXH_OK; -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize) -{ - if (statePtr == NULL) return XXH_ERROR; - XXH3_reset_internal(statePtr, 0, secret, secretSize); - if (secret == NULL) return XXH_ERROR; - if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; - return XXH_OK; -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed) -{ - if (statePtr == NULL) return XXH_ERROR; - if (seed==0) return XXH3_64bits_reset(statePtr); - if ((seed != statePtr->seed) || (statePtr->extSecret != NULL)) - XXH3_initCustomSecret(statePtr->customSecret, seed); - XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE); - return XXH_OK; -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_reset_withSecretandSeed(XXH3_state_t* statePtr, const void* secret, size_t secretSize, XXH64_hash_t seed64) -{ - if (statePtr == NULL) return XXH_ERROR; - if (secret == NULL) return XXH_ERROR; - if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; - XXH3_reset_internal(statePtr, seed64, secret, secretSize); - statePtr->useSeed = 1; /* always, even if seed64==0 */ - return XXH_OK; -} - -/* Note : when XXH3_consumeStripes() is invoked, - * there must be a guarantee that at least one more byte must be consumed from input - * so that the function can blindly consume all stripes using the "normal" secret segment */ -XXH_FORCE_INLINE void -XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc, - size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock, - const xxh_u8* XXH_RESTRICT input, size_t nbStripes, - const xxh_u8* XXH_RESTRICT secret, size_t secretLimit, - XXH3_f_accumulate_512 f_acc512, - XXH3_f_scrambleAcc f_scramble) -{ - XXH_ASSERT(nbStripes <= nbStripesPerBlock); /* can handle max 1 scramble per invocation */ - XXH_ASSERT(*nbStripesSoFarPtr < nbStripesPerBlock); - if (nbStripesPerBlock - *nbStripesSoFarPtr <= nbStripes) { - /* need a scrambling operation */ - size_t const nbStripesToEndofBlock = nbStripesPerBlock - *nbStripesSoFarPtr; - size_t const nbStripesAfterBlock = nbStripes - nbStripesToEndofBlock; - XXH3_accumulate(acc, input, secret + nbStripesSoFarPtr[0] * XXH_SECRET_CONSUME_RATE, nbStripesToEndofBlock, f_acc512); - f_scramble(acc, secret + secretLimit); - XXH3_accumulate(acc, input + nbStripesToEndofBlock * XXH_STRIPE_LEN, secret, nbStripesAfterBlock, f_acc512); - *nbStripesSoFarPtr = nbStripesAfterBlock; - } else { - XXH3_accumulate(acc, input, secret + nbStripesSoFarPtr[0] * XXH_SECRET_CONSUME_RATE, nbStripes, f_acc512); - *nbStripesSoFarPtr += nbStripes; - } -} - -#ifndef XXH3_STREAM_USE_STACK -# if XXH_SIZE_OPT <= 0 && !defined(__clang__) /* clang doesn't need additional stack space */ -# define XXH3_STREAM_USE_STACK 1 -# endif -#endif -/* - * Both XXH3_64bits_update and XXH3_128bits_update use this routine. - */ -XXH_FORCE_INLINE XXH_errorcode -XXH3_update(XXH3_state_t* XXH_RESTRICT const state, - const xxh_u8* XXH_RESTRICT input, size_t len, - XXH3_f_accumulate_512 f_acc512, - XXH3_f_scrambleAcc f_scramble) -{ - if (input==NULL) { - XXH_ASSERT(len == 0); - return XXH_OK; - } - - XXH_ASSERT(state != NULL); - { const xxh_u8* const bEnd = input + len; - const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; -#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 - /* For some reason, gcc and MSVC seem to suffer greatly - * when operating accumulators directly into state. - * Operating into stack space seems to enable proper optimization. - * clang, on the other hand, doesn't seem to need this trick */ - XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8]; memcpy(acc, state->acc, sizeof(acc)); -#else - xxh_u64* XXH_RESTRICT const acc = state->acc; -#endif - state->totalLen += len; - XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE); - - /* small input : just fill in tmp buffer */ - if (state->bufferedSize + len <= XXH3_INTERNALBUFFER_SIZE) { - XXH_memcpy(state->buffer + state->bufferedSize, input, len); - state->bufferedSize += (XXH32_hash_t)len; - return XXH_OK; - } - - /* total input is now > XXH3_INTERNALBUFFER_SIZE */ - #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN) - XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0); /* clean multiple */ - - /* - * Internal buffer is partially filled (always, except at beginning) - * Complete it, then consume it. - */ - if (state->bufferedSize) { - size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize; - XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize); - input += loadSize; - XXH3_consumeStripes(acc, - &state->nbStripesSoFar, state->nbStripesPerBlock, - state->buffer, XXH3_INTERNALBUFFER_STRIPES, - secret, state->secretLimit, - f_acc512, f_scramble); - state->bufferedSize = 0; - } - XXH_ASSERT(input < bEnd); - - /* large input to consume : ingest per full block */ - if ((size_t)(bEnd - input) > state->nbStripesPerBlock * XXH_STRIPE_LEN) { - size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN; - XXH_ASSERT(state->nbStripesPerBlock >= state->nbStripesSoFar); - /* join to current block's end */ - { size_t const nbStripesToEnd = state->nbStripesPerBlock - state->nbStripesSoFar; - XXH_ASSERT(nbStripesToEnd <= nbStripes); - XXH3_accumulate(acc, input, secret + state->nbStripesSoFar * XXH_SECRET_CONSUME_RATE, nbStripesToEnd, f_acc512); - f_scramble(acc, secret + state->secretLimit); - state->nbStripesSoFar = 0; - input += nbStripesToEnd * XXH_STRIPE_LEN; - nbStripes -= nbStripesToEnd; - } - /* consume per entire blocks */ - while(nbStripes >= state->nbStripesPerBlock) { - XXH3_accumulate(acc, input, secret, state->nbStripesPerBlock, f_acc512); - f_scramble(acc, secret + state->secretLimit); - input += state->nbStripesPerBlock * XXH_STRIPE_LEN; - nbStripes -= state->nbStripesPerBlock; - } - /* consume last partial block */ - XXH3_accumulate(acc, input, secret, nbStripes, f_acc512); - input += nbStripes * XXH_STRIPE_LEN; - XXH_ASSERT(input < bEnd); /* at least some bytes left */ - state->nbStripesSoFar = nbStripes; - /* buffer predecessor of last partial stripe */ - XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN); - XXH_ASSERT(bEnd - input <= XXH_STRIPE_LEN); - } else { - /* content to consume <= block size */ - /* Consume input by a multiple of internal buffer size */ - if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) { - const xxh_u8* const limit = bEnd - XXH3_INTERNALBUFFER_SIZE; - do { - XXH3_consumeStripes(acc, - &state->nbStripesSoFar, state->nbStripesPerBlock, - input, XXH3_INTERNALBUFFER_STRIPES, - secret, state->secretLimit, - f_acc512, f_scramble); - input += XXH3_INTERNALBUFFER_SIZE; - } while (inputbuffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN); - } - } - - /* Some remaining input (always) : buffer it */ - XXH_ASSERT(input < bEnd); - XXH_ASSERT(bEnd - input <= XXH3_INTERNALBUFFER_SIZE); - XXH_ASSERT(state->bufferedSize == 0); - XXH_memcpy(state->buffer, input, (size_t)(bEnd-input)); - state->bufferedSize = (XXH32_hash_t)(bEnd-input); -#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 - /* save stack accumulators into state */ - memcpy(state->acc, acc, sizeof(acc)); -#endif - } - - return XXH_OK; -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode -XXH3_64bits_update(XXH3_state_t* state, const void* input, size_t len) -{ - return XXH3_update(state, (const xxh_u8*)input, len, - XXH3_accumulate_512, XXH3_scrambleAcc); -} - - -XXH_FORCE_INLINE void -XXH3_digest_long (XXH64_hash_t* acc, - const XXH3_state_t* state, - const unsigned char* secret) -{ - /* - * Digest on a local copy. This way, the state remains unaltered, and it can - * continue ingesting more input afterwards. - */ - XXH_memcpy(acc, state->acc, sizeof(state->acc)); - if (state->bufferedSize >= XXH_STRIPE_LEN) { - size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN; - size_t nbStripesSoFar = state->nbStripesSoFar; - XXH3_consumeStripes(acc, - &nbStripesSoFar, state->nbStripesPerBlock, - state->buffer, nbStripes, - secret, state->secretLimit, - XXH3_accumulate_512, XXH3_scrambleAcc); - /* last stripe */ - XXH3_accumulate_512(acc, - state->buffer + state->bufferedSize - XXH_STRIPE_LEN, - secret + state->secretLimit - XXH_SECRET_LASTACC_START); - } else { /* bufferedSize < XXH_STRIPE_LEN */ - xxh_u8 lastStripe[XXH_STRIPE_LEN]; - size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize; - XXH_ASSERT(state->bufferedSize > 0); /* there is always some input buffered */ - XXH_memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize); - XXH_memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize); - XXH3_accumulate_512(acc, - lastStripe, - secret + state->secretLimit - XXH_SECRET_LASTACC_START); - } -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (const XXH3_state_t* state) -{ - const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; - if (state->totalLen > XXH3_MIDSIZE_MAX) { - XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; - XXH3_digest_long(acc, state, secret); - return XXH3_mergeAccs(acc, - secret + XXH_SECRET_MERGEACCS_START, - (xxh_u64)state->totalLen * XXH_PRIME64_1); - } - /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */ - if (state->useSeed) - return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); - return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen), - secret, state->secretLimit + XXH_STRIPE_LEN); -} -#endif /* !XXH_NO_STREAM */ - - -/* ========================================== - * XXH3 128 bits (a.k.a XXH128) - * ========================================== - * XXH3's 128-bit variant has better mixing and strength than the 64-bit variant, - * even without counting the significantly larger output size. - * - * For example, extra steps are taken to avoid the seed-dependent collisions - * in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B). - * - * This strength naturally comes at the cost of some speed, especially on short - * lengths. Note that longer hashes are about as fast as the 64-bit version - * due to it using only a slight modification of the 64-bit loop. - * - * XXH128 is also more oriented towards 64-bit machines. It is still extremely - * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64). - */ - -XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t -XXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) -{ - /* A doubled version of 1to3_64b with different constants. */ - XXH_ASSERT(input != NULL); - XXH_ASSERT(1 <= len && len <= 3); - XXH_ASSERT(secret != NULL); - /* - * len = 1: combinedl = { input[0], 0x01, input[0], input[0] } - * len = 2: combinedl = { input[1], 0x02, input[0], input[1] } - * len = 3: combinedl = { input[2], 0x03, input[0], input[1] } - */ - { xxh_u8 const c1 = input[0]; - xxh_u8 const c2 = input[len >> 1]; - xxh_u8 const c3 = input[len - 1]; - xxh_u32 const combinedl = ((xxh_u32)c1 <<16) | ((xxh_u32)c2 << 24) - | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); - xxh_u32 const combinedh = XXH_rotl32(XXH_swap32(combinedl), 13); - xxh_u64 const bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; - xxh_u64 const bitfliph = (XXH_readLE32(secret+8) ^ XXH_readLE32(secret+12)) - seed; - xxh_u64 const keyed_lo = (xxh_u64)combinedl ^ bitflipl; - xxh_u64 const keyed_hi = (xxh_u64)combinedh ^ bitfliph; - XXH128_hash_t h128; - h128.low64 = XXH64_avalanche(keyed_lo); - h128.high64 = XXH64_avalanche(keyed_hi); - return h128; - } -} - -XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t -XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) -{ - XXH_ASSERT(input != NULL); - XXH_ASSERT(secret != NULL); - XXH_ASSERT(4 <= len && len <= 8); - seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; - { xxh_u32 const input_lo = XXH_readLE32(input); - xxh_u32 const input_hi = XXH_readLE32(input + len - 4); - xxh_u64 const input_64 = input_lo + ((xxh_u64)input_hi << 32); - xxh_u64 const bitflip = (XXH_readLE64(secret+16) ^ XXH_readLE64(secret+24)) + seed; - xxh_u64 const keyed = input_64 ^ bitflip; - - /* Shift len to the left to ensure it is even, this avoids even multiplies. */ - XXH128_hash_t m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + (len << 2)); - - m128.high64 += (m128.low64 << 1); - m128.low64 ^= (m128.high64 >> 3); - - m128.low64 = XXH_xorshift64(m128.low64, 35); - m128.low64 *= 0x9FB21C651E98DF25ULL; - m128.low64 = XXH_xorshift64(m128.low64, 28); - m128.high64 = XXH3_avalanche(m128.high64); - return m128; - } -} - -XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t -XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) -{ - XXH_ASSERT(input != NULL); - XXH_ASSERT(secret != NULL); - XXH_ASSERT(9 <= len && len <= 16); - { xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed; - xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed; - xxh_u64 const input_lo = XXH_readLE64(input); - xxh_u64 input_hi = XXH_readLE64(input + len - 8); - XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1); - /* - * Put len in the middle of m128 to ensure that the length gets mixed to - * both the low and high bits in the 128x64 multiply below. - */ - m128.low64 += (xxh_u64)(len - 1) << 54; - input_hi ^= bitfliph; - /* - * Add the high 32 bits of input_hi to the high 32 bits of m128, then - * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to - * the high 64 bits of m128. - * - * The best approach to this operation is different on 32-bit and 64-bit. - */ - if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */ - /* - * 32-bit optimized version, which is more readable. - * - * On 32-bit, it removes an ADC and delays a dependency between the two - * halves of m128.high64, but it generates an extra mask on 64-bit. - */ - m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2); - } else { - /* - * 64-bit optimized (albeit more confusing) version. - * - * Uses some properties of addition and multiplication to remove the mask: - * - * Let: - * a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF) - * b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000) - * c = XXH_PRIME32_2 - * - * a + (b * c) - * Inverse Property: x + y - x == y - * a + (b * (1 + c - 1)) - * Distributive Property: x * (y + z) == (x * y) + (x * z) - * a + (b * 1) + (b * (c - 1)) - * Identity Property: x * 1 == x - * a + b + (b * (c - 1)) - * - * Substitute a, b, and c: - * input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) - * - * Since input_hi.hi + input_hi.lo == input_hi, we get this: - * input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) - */ - m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1); - } - /* m128 ^= XXH_swap64(m128 >> 64); */ - m128.low64 ^= XXH_swap64(m128.high64); - - { /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */ - XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2); - h128.high64 += m128.high64 * XXH_PRIME64_2; - - h128.low64 = XXH3_avalanche(h128.low64); - h128.high64 = XXH3_avalanche(h128.high64); - return h128; - } } -} - -/* - * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN - */ -XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t -XXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) -{ - XXH_ASSERT(len <= 16); - { if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed); - if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed); - if (len) return XXH3_len_1to3_128b(input, len, secret, seed); - { XXH128_hash_t h128; - xxh_u64 const bitflipl = XXH_readLE64(secret+64) ^ XXH_readLE64(secret+72); - xxh_u64 const bitfliph = XXH_readLE64(secret+80) ^ XXH_readLE64(secret+88); - h128.low64 = XXH64_avalanche(seed ^ bitflipl); - h128.high64 = XXH64_avalanche( seed ^ bitfliph); - return h128; - } } -} - -/* - * A bit slower than XXH3_mix16B, but handles multiply by zero better. - */ -XXH_FORCE_INLINE XXH128_hash_t -XXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2, - const xxh_u8* secret, XXH64_hash_t seed) -{ - acc.low64 += XXH3_mix16B (input_1, secret+0, seed); - acc.low64 ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8); - acc.high64 += XXH3_mix16B (input_2, secret+16, seed); - acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8); - return acc; -} - - -XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t -XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len, - const xxh_u8* XXH_RESTRICT secret, size_t secretSize, - XXH64_hash_t seed) -{ - XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; - XXH_ASSERT(16 < len && len <= 128); - - { XXH128_hash_t acc; - acc.low64 = len * XXH_PRIME64_1; - acc.high64 = 0; - -#if XXH_SIZE_OPT >= 1 - { - /* Smaller, but slightly slower. */ - size_t i = (len - 1) / 32; - do { - acc = XXH128_mix32B(acc, input+16*i, input+len-16*(i+1), secret+32*i, seed); - } while (i-- != 0); - } -#else - if (len > 32) { - if (len > 64) { - if (len > 96) { - acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed); - } - acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed); - } - acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed); - } - acc = XXH128_mix32B(acc, input, input+len-16, secret, seed); -#endif - { XXH128_hash_t h128; - h128.low64 = acc.low64 + acc.high64; - h128.high64 = (acc.low64 * XXH_PRIME64_1) - + (acc.high64 * XXH_PRIME64_4) - + ((len - seed) * XXH_PRIME64_2); - h128.low64 = XXH3_avalanche(h128.low64); - h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); - return h128; - } - } -} - -XXH_NO_INLINE XXH_PUREF XXH128_hash_t -XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, - const xxh_u8* XXH_RESTRICT secret, size_t secretSize, - XXH64_hash_t seed) -{ - XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; - XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); - - { XXH128_hash_t acc; - int const nbRounds = (int)len / 32; - int i; - acc.low64 = len * XXH_PRIME64_1; - acc.high64 = 0; - for (i=0; i<4; i++) { - acc = XXH128_mix32B(acc, - input + (32 * i), - input + (32 * i) + 16, - secret + (32 * i), - seed); - } - acc.low64 = XXH3_avalanche(acc.low64); - acc.high64 = XXH3_avalanche(acc.high64); - XXH_ASSERT(nbRounds >= 4); - for (i=4 ; i < nbRounds; i++) { - acc = XXH128_mix32B(acc, - input + (32 * i), - input + (32 * i) + 16, - secret + XXH3_MIDSIZE_STARTOFFSET + (32 * (i - 4)), - seed); - } - /* last bytes */ - acc = XXH128_mix32B(acc, - input + len - 16, - input + len - 32, - secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16, - 0ULL - seed); - - { XXH128_hash_t h128; - h128.low64 = acc.low64 + acc.high64; - h128.high64 = (acc.low64 * XXH_PRIME64_1) - + (acc.high64 * XXH_PRIME64_4) - + ((len - seed) * XXH_PRIME64_2); - h128.low64 = XXH3_avalanche(h128.low64); - h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); - return h128; - } - } -} - -XXH_FORCE_INLINE XXH128_hash_t -XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len, - const xxh_u8* XXH_RESTRICT secret, size_t secretSize, - XXH3_f_accumulate_512 f_acc512, - XXH3_f_scrambleAcc f_scramble) -{ - XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; - - XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc512, f_scramble); - - /* converge into final hash */ - XXH_STATIC_ASSERT(sizeof(acc) == 64); - XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); - { XXH128_hash_t h128; - h128.low64 = XXH3_mergeAccs(acc, - secret + XXH_SECRET_MERGEACCS_START, - (xxh_u64)len * XXH_PRIME64_1); - h128.high64 = XXH3_mergeAccs(acc, - secret + secretSize - - sizeof(acc) - XXH_SECRET_MERGEACCS_START, - ~((xxh_u64)len * XXH_PRIME64_2)); - return h128; - } -} - -/* - * It's important for performance that XXH3_hashLong() is not inlined. - */ -XXH_NO_INLINE XXH_PUREF XXH128_hash_t -XXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len, - XXH64_hash_t seed64, - const void* XXH_RESTRICT secret, size_t secretLen) -{ - (void)seed64; (void)secret; (void)secretLen; - return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), - XXH3_accumulate_512, XXH3_scrambleAcc); -} - -/* - * It's important for performance to pass @p secretLen (when it's static) - * to the compiler, so that it can properly optimize the vectorized loop. - */ -XXH_FORCE_INLINE XXH128_hash_t -XXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len, - XXH64_hash_t seed64, - const void* XXH_RESTRICT secret, size_t secretLen) -{ - (void)seed64; - return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen, - XXH3_accumulate_512, XXH3_scrambleAcc); -} - -XXH_FORCE_INLINE XXH128_hash_t -XXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len, - XXH64_hash_t seed64, - XXH3_f_accumulate_512 f_acc512, - XXH3_f_scrambleAcc f_scramble, - XXH3_f_initCustomSecret f_initSec) -{ - if (seed64 == 0) - return XXH3_hashLong_128b_internal(input, len, - XXH3_kSecret, sizeof(XXH3_kSecret), - f_acc512, f_scramble); - { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; - f_initSec(secret, seed64); - return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret), - f_acc512, f_scramble); - } -} - -/* - * It's important for performance that XXH3_hashLong is not inlined. - */ -XXH_NO_INLINE XXH128_hash_t -XXH3_hashLong_128b_withSeed(const void* input, size_t len, - XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) -{ - (void)secret; (void)secretLen; - return XXH3_hashLong_128b_withSeed_internal(input, len, seed64, - XXH3_accumulate_512, XXH3_scrambleAcc, XXH3_initCustomSecret); -} - -typedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t, - XXH64_hash_t, const void* XXH_RESTRICT, size_t); - -XXH_FORCE_INLINE XXH128_hash_t -XXH3_128bits_internal(const void* input, size_t len, - XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, - XXH3_hashLong128_f f_hl128) -{ - XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); - /* - * If an action is to be taken if `secret` conditions are not respected, - * it should be done here. - * For now, it's a contract pre-condition. - * Adding a check and a branch here would cost performance at every hash. - */ - if (len <= 16) - return XXH3_len_0to16_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); - if (len <= 128) - return XXH3_len_17to128_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); - if (len <= XXH3_MIDSIZE_MAX) - return XXH3_len_129to240_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); - return f_hl128(input, len, seed64, secret, secretLen); -} - - -/* === Public XXH128 API === */ - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(const void* input, size_t len) -{ - return XXH3_128bits_internal(input, len, 0, - XXH3_kSecret, sizeof(XXH3_kSecret), - XXH3_hashLong_128b_default); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH128_hash_t -XXH3_128bits_withSecret(const void* input, size_t len, const void* secret, size_t secretSize) -{ - return XXH3_128bits_internal(input, len, 0, - (const xxh_u8*)secret, secretSize, - XXH3_hashLong_128b_withSecret); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH128_hash_t -XXH3_128bits_withSeed(const void* input, size_t len, XXH64_hash_t seed) -{ - return XXH3_128bits_internal(input, len, seed, - XXH3_kSecret, sizeof(XXH3_kSecret), - XXH3_hashLong_128b_withSeed); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH128_hash_t -XXH3_128bits_withSecretandSeed(const void* input, size_t len, const void* secret, size_t secretSize, XXH64_hash_t seed) -{ - if (len <= XXH3_MIDSIZE_MAX) - return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); - return XXH3_hashLong_128b_withSecret(input, len, seed, secret, secretSize); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH128_hash_t -XXH128(const void* input, size_t len, XXH64_hash_t seed) -{ - return XXH3_128bits_withSeed(input, len, seed); -} - - -/* === XXH3 128-bit streaming === */ -#ifndef XXH_NO_STREAM -/* - * All initialization and update functions are identical to 64-bit streaming variant. - * The only difference is the finalization routine. - */ - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_reset(XXH3_state_t* statePtr) -{ - return XXH3_64bits_reset(statePtr); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize) -{ - return XXH3_64bits_reset_withSecret(statePtr, secret, secretSize); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed) -{ - return XXH3_64bits_reset_withSeed(statePtr, seed); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, const void* secret, size_t secretSize, XXH64_hash_t seed) -{ - return XXH3_64bits_reset_withSecretandSeed(statePtr, secret, secretSize, seed); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode -XXH3_128bits_update(XXH3_state_t* state, const void* input, size_t len) -{ - return XXH3_update(state, (const xxh_u8*)input, len, - XXH3_accumulate_512, XXH3_scrambleAcc); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (const XXH3_state_t* state) -{ - const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; - if (state->totalLen > XXH3_MIDSIZE_MAX) { - XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; - XXH3_digest_long(acc, state, secret); - XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); - { XXH128_hash_t h128; - h128.low64 = XXH3_mergeAccs(acc, - secret + XXH_SECRET_MERGEACCS_START, - (xxh_u64)state->totalLen * XXH_PRIME64_1); - h128.high64 = XXH3_mergeAccs(acc, - secret + state->secretLimit + XXH_STRIPE_LEN - - sizeof(acc) - XXH_SECRET_MERGEACCS_START, - ~((xxh_u64)state->totalLen * XXH_PRIME64_2)); - return h128; - } - } - /* len <= XXH3_MIDSIZE_MAX : short code */ - if (state->seed) - return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); - return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen), - secret, state->secretLimit + XXH_STRIPE_LEN); -} -#endif /* !XXH_NO_STREAM */ -/* 128-bit utility functions */ - -#include /* memcmp, memcpy */ - -/* return : 1 is equal, 0 if different */ -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2) -{ - /* note : XXH128_hash_t is compact, it has no padding byte */ - return !(memcmp(&h1, &h2, sizeof(h1))); -} - -/* This prototype is compatible with stdlib's qsort(). - * @return : >0 if *h128_1 > *h128_2 - * <0 if *h128_1 < *h128_2 - * =0 if *h128_1 == *h128_2 */ -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API int XXH128_cmp(const void* h128_1, const void* h128_2) -{ - XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1; - XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2; - int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64); - /* note : bets that, in most cases, hash values are different */ - if (hcmp) return hcmp; - return (h1.low64 > h2.low64) - (h2.low64 > h1.low64); -} - - -/*====== Canonical representation ======*/ -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API void -XXH128_canonicalFromHash(XXH128_canonical_t* dst, XXH128_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) { - hash.high64 = XXH_swap64(hash.high64); - hash.low64 = XXH_swap64(hash.low64); - } - XXH_memcpy(dst, &hash.high64, sizeof(hash.high64)); - XXH_memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64)); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH128_hash_t -XXH128_hashFromCanonical(const XXH128_canonical_t* src) -{ - XXH128_hash_t h; - h.high64 = XXH_readBE64(src); - h.low64 = XXH_readBE64(src->digest + 8); - return h; -} - - - -/* ========================================== - * Secret generators - * ========================================== - */ -#define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x)) - -XXH_FORCE_INLINE void XXH3_combine16(void* dst, XXH128_hash_t h128) -{ - XXH_writeLE64( dst, XXH_readLE64(dst) ^ h128.low64 ); - XXH_writeLE64( (char*)dst+8, XXH_readLE64((char*)dst+8) ^ h128.high64 ); -} - -/*! @ingroup XXH3_family */ -XXH_PUBLIC_API XXH_errorcode -XXH3_generateSecret(void* secretBuffer, size_t secretSize, const void* customSeed, size_t customSeedSize) -{ -#if (XXH_DEBUGLEVEL >= 1) - XXH_ASSERT(secretBuffer != NULL); - XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); -#else - /* production mode, assert() are disabled */ - if (secretBuffer == NULL) return XXH_ERROR; - if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; -#endif - - if (customSeedSize == 0) { - customSeed = XXH3_kSecret; - customSeedSize = XXH_SECRET_DEFAULT_SIZE; - } -#if (XXH_DEBUGLEVEL >= 1) - XXH_ASSERT(customSeed != NULL); -#else - if (customSeed == NULL) return XXH_ERROR; -#endif - - /* Fill secretBuffer with a copy of customSeed - repeat as needed */ - { size_t pos = 0; - while (pos < secretSize) { - size_t const toCopy = XXH_MIN((secretSize - pos), customSeedSize); - memcpy((char*)secretBuffer + pos, customSeed, toCopy); - pos += toCopy; - } } - - { size_t const nbSeg16 = secretSize / 16; - size_t n; - XXH128_canonical_t scrambler; - XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0)); - for (n=0; n +#include #include "Runtime/Streams/CMemoryInStream.hpp" #include "Runtime/Streams/CZipInputStream.hpp" @@ -150,6 +150,6 @@ Icon GetIcon() { void ImGuiEngine_AddTextures() { auto icon = GetIcon(); - ImGuiEngine::metaforceIcon = aurora::imgui::add_texture(icon.width, icon.height, {icon.data.get(), icon.size}); + ImGuiEngine::metaforceIcon = aurora_imgui_add_texture(icon.width, icon.height, icon.data.get()); } } // namespace metaforce diff --git a/imgui/imconfig_user.h b/imgui/imconfig_user.h deleted file mode 100644 index 100e3277c..000000000 --- a/imgui/imconfig_user.h +++ /dev/null @@ -1,17 +0,0 @@ -#include - -#include - -#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS -#define IMGUI_DISABLE_OBSOLETE_KEYIO - -#ifdef NDEBUG -#define IMGUI_DISABLE_DEMO_WINDOWS -#endif - -#define IM_VEC2_CLASS_EXTRA \ - ImVec2(const zeus::CVector2f& v) { \ - x = v.x(); \ - y = v.y(); \ - } \ - operator zeus::CVector2f() const { return zeus::CVector2f{x, y}; }