diff --git a/.gitignore b/.gitignore index f5a66a76bd..1b8b69d245 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ SerialPrograms/bin/ discord_social_sdk_win/ discord_partner_sdk.dll 3rdPartyBinaries/discord_social_sdk_mac/ +3rdPartyBinaries/discord_social_sdk_linux/ 3rdPartyBinaries/onnxruntime-osx-arm64-*/ 3rdPartyBinaries/onnxruntime-osx-x86_64-*/ diff --git a/3rdParty/sdbus-cpp/lib/libsdbus-c++-aarch64.a b/3rdParty/sdbus-cpp/lib/libsdbus-c++-aarch64.a new file mode 100644 index 0000000000..88c2de56f3 Binary files /dev/null and b/3rdParty/sdbus-cpp/lib/libsdbus-c++-aarch64.a differ diff --git a/3rdParty/sdbus-cpp/lib/libsdbus-c++.a b/3rdParty/sdbus-cpp/lib/libsdbus-c++-x86_64.a similarity index 100% rename from 3rdParty/sdbus-cpp/lib/libsdbus-c++.a rename to 3rdParty/sdbus-cpp/lib/libsdbus-c++-x86_64.a diff --git a/Common/Cpp/CpuId/CpuId.h b/Common/Cpp/CpuId/CpuId.h index cb45dcaa7a..5c817ccd11 100644 --- a/Common/Cpp/CpuId/CpuId.h +++ b/Common/Cpp/CpuId/CpuId.h @@ -13,7 +13,7 @@ #elif _M_IX86 || _M_X64 || __i386__ || __x86_64__ #define PA_ARCH_x86 1 #include "CpuId_x86.h" -#elif __arm64__ +#elif __arm64__ || __aarch64__ #define PA_ARCH_arm64 1 #include "CpuId_arm64.h" #else diff --git a/Common/Cpp/CpuId/CpuId_arm64.tpp b/Common/Cpp/CpuId/CpuId_arm64.tpp index ae55e46323..4d19a4a11d 100644 --- a/Common/Cpp/CpuId/CpuId_arm64.tpp +++ b/Common/Cpp/CpuId/CpuId_arm64.tpp @@ -6,7 +6,9 @@ #include +#ifdef __APPLE__ #include +#endif #include #include "CpuId.h" @@ -18,9 +20,10 @@ const char* PA_ARCH_STRING = "arm64"; uint64_t detect_NEON() { +#ifdef __APPLE__ // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics // But this developer webpage may be out of date. - + uint64_t available = 0; size_t size = sizeof(available); @@ -35,6 +38,11 @@ uint64_t detect_NEON() } } return available; +#else + // On Linux aarch64, AdvSIMD (NEON) is part of the mandatory ARMv8-A baseline, + // so it is always available. + return 1; +#endif } CPU_Features& CPU_Features::set_to_current(){ diff --git a/Common/Cpp/Hardware/Hardware.cpp b/Common/Cpp/Hardware/Hardware.cpp index c37ee19ecf..2079ae7d62 100644 --- a/Common/Cpp/Hardware/Hardware.cpp +++ b/Common/Cpp/Hardware/Hardware.cpp @@ -22,9 +22,13 @@ #ifdef PA_ARCH_x86 #include "Hardware_x86_Linux.tpp" #elif PA_ARCH_arm64 +#ifdef __APPLE__ +#include "Hardware_arm64_Mac.tpp" +#else #include "Hardware_arm64_Linux.tpp" #endif #endif +#endif namespace PokemonAutomation{ diff --git a/Common/Cpp/Hardware/Hardware_arm64_Linux.tpp b/Common/Cpp/Hardware/Hardware_arm64_Linux.tpp index 62c8101c28..15fd41a4c9 100644 --- a/Common/Cpp/Hardware/Hardware_arm64_Linux.tpp +++ b/Common/Cpp/Hardware/Hardware_arm64_Linux.tpp @@ -1,51 +1,76 @@ -/* Environment (arm64 Linux) - * - * From: https://github.com/PokemonAutomation/Arduino-Source - * - * Currently only used for M-series Apple environment - */ - - -#include -#include -#include -#include -#include "Hardware.h" - -namespace PokemonAutomation{ - - -uint64_t get_cpu_freq() -{ - uint64_t freq = 0; - size_t size = sizeof(freq); - - if (sysctlbyname("hw.cpufrequency", &freq, &size, NULL, 0) < 0) - { - perror("sysctl"); - } - return freq; -} - -std::string get_processor_name(){ - char name_buffer[100] = ""; - size_t size = 100; - if (sysctlbyname("machdep.cpu.brand_string", name_buffer, &size, NULL, 0) < 0) - { - perror("sysctl"); - } - return name_buffer; -} - - -ProcessorSpecs get_processor_specs(){ - ProcessorSpecs specs; - specs.name = get_processor_name(); - specs.base_frequency = get_cpu_freq(); - specs.threads = std::thread::hardware_concurrency(); - - return specs; -} - - -} +/* Hardware (arm64 Linux) + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + * Used for Linux aarch64 environment. + */ + + +#include +#include +#include +#include +#include +#include +#include "Hardware.h" + +namespace PokemonAutomation{ + + +// Linux: /proc/cpuinfo does not have a "Model name" line on ARM kernels, +// so fall back to the SoC "Hardware" line, and finally the kernel name. + +static std::string cpuinfo_value(const std::string& file_path, const std::string& key){ + std::ifstream file(file_path); + std::string line; + while (std::getline(file, line)){ + if (line.rfind(key, 0) == 0){ + size_t pos = line.find(": "); + if (pos == std::string::npos){ + return ""; + } + return line.substr(pos + 2); + } + } + return ""; +} + +uint64_t get_cpu_freq(){ + // /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq is in kHz. + std::string max_freq = cpuinfo_value("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", ""); + if (!max_freq.empty()){ + return (uint64_t)atoll(max_freq.c_str()) * 1000ULL; + } + + // Fallback: "cpu MHz" in /proc/cpuinfo. + std::string mhz = cpuinfo_value("/proc/cpuinfo", "cpu MHz"); + if (!mhz.empty()){ + return (uint64_t)(atof(mhz.c_str()) * 1000000.); + } + + return 0; +} + +std::string get_processor_name(){ + std::string name = cpuinfo_value("/proc/cpuinfo", "Model name"); + if (name.empty()){ + name = cpuinfo_value("/proc/cpuinfo", "Hardware"); + } + if (name.empty()){ + name = "aarch64"; + } + return name; +} + + +ProcessorSpecs get_processor_specs(){ + ProcessorSpecs specs; + specs.name = get_processor_name(); + specs.base_frequency = get_cpu_freq(); + specs.threads = std::thread::hardware_concurrency(); + + return specs; +} + + +} diff --git a/Common/Cpp/Hardware/Hardware_arm64_Mac.tpp b/Common/Cpp/Hardware/Hardware_arm64_Mac.tpp new file mode 100644 index 0000000000..96e99463aa --- /dev/null +++ b/Common/Cpp/Hardware/Hardware_arm64_Mac.tpp @@ -0,0 +1,51 @@ +/* Hardware (arm64 Mac) + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + * Used for Apple M-series (macOS) environment. + */ + + +#include +#include +#include +#include +#include "Hardware.h" + +namespace PokemonAutomation{ + + +uint64_t get_cpu_freq() +{ + uint64_t freq = 0; + size_t size = sizeof(freq); + + if (sysctlbyname("hw.cpufrequency", &freq, &size, NULL, 0) < 0) + { + perror("sysctl"); + } + return freq; +} + +std::string get_processor_name(){ + char name_buffer[100] = ""; + size_t size = 100; + if (sysctlbyname("machdep.cpu.brand_string", name_buffer, &size, NULL, 0) < 0) + { + perror("sysctl"); + } + return name_buffer; +} + + +ProcessorSpecs get_processor_specs(){ + ProcessorSpecs specs; + specs.name = get_processor_name(); + specs.base_frequency = get_cpu_freq(); + specs.threads = std::thread::hardware_concurrency(); + + return specs; +} + + +} diff --git a/SerialPrograms/BuildInstructions/Build-Ubuntu-ARM64-Qt6.8.3.md b/SerialPrograms/BuildInstructions/Build-Ubuntu-ARM64-Qt6.8.3.md new file mode 100644 index 0000000000..7b2f481b45 --- /dev/null +++ b/SerialPrograms/BuildInstructions/Build-Ubuntu-ARM64-Qt6.8.3.md @@ -0,0 +1,106 @@ +# How to Build (Qt 6.8.3) - Ubuntu 24.04 aarch64 (ARM64) + +This covers building on **Linux ARM64/aarch64**, as opposed to x86\_64 Ubuntu (see `Build-Ubuntu-Qt6.8.2.md` for limited x86\_64 guidance) or macOS (see `CompilingForMac.md`). + +NOTE: This is only for ARM Linux server build testing. There is no GUI testing to guarantee the GUI of the built application works. + +NOTE: The content below in this document is generated by a local AI agent and Claude on Sep 5, 2026 as a build reference. +No humans have followed through the guide to ensure its correctness yet. + +Ubuntu's own Qt6 packages are far too old (Qt 6.4 on 24.04), and Qt does not publish prebuilt Linux ARM64 packages through its online installer, so Qt has to be built from source. Everything else (OpenCV, Tesseract, D-Bus) is available through `apt` on Ubuntu 24.04. + +This was verified with: +- Ubuntu 24.04.4 LTS, kernel 6.17, aarch64 +- Qt 6.8.3 (built from source) +- CMake 3.28, Ninja, GCC (system default) + +## 1. Install build tools and dependencies + +```bash +sudo apt update +sudo apt install build-essential cmake ninja-build git pkg-config + +# Libraries this project links against directly +sudo apt install libopencv-dev libtesseract-dev libleptonica-dev \ + libsystemd-dev libopenexr-dev libgl1-mesa-dev libglx-dev \ + libglu1-mesa-dev + +# Dependencies needed to build Qt itself (xcb platform plugin, fonts, etc.) +sudo apt install libxkbcommon-dev libxkbcommon-x11-dev libxcb-cursor-dev \ + libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev \ + libxcb-render-util0-dev libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev \ + libxcb-xinerama0-dev libxcb-xkb-dev libxcb1-dev libx11-dev libx11-xcb-dev \ + libxext-dev libxfixes-dev libxi-dev libxrender-dev libfontconfig1-dev \ + libfreetype-dev libssl-dev + +# FFmpeg dev libs so Qt Multimedia gets a working webcam/video backend +sudo apt install libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \ + libswresample-dev +``` + +Note: `libopencv-dev` on 24.04 provides OpenCV 4.6, and `libtesseract-dev` provides Tesseract 5.3.4. Both are picked up via `pkg-config` (`opencv4`, `tesseract`) by `SerialPrograms/CMakeLists.txt` — no manual OpenCV build is required on Linux (unlike Windows/Mac, which use prebuilt binaries from the `Packages` repo). + +## 2. Build Qt 6.8.3 from source + +```bash +mkdir -p ~/src && cd ~/src +wget https://download.qt.io/official_releases/qt/6.8/6.8.3/single/qt-everywhere-src-6.8.3.tar.xz +tar xf qt-everywhere-src-6.8.3.tar.xz +cd qt-everywhere-src-6.8.3 + +mkdir build && cd build +../configure -prefix "$HOME/qt/6.8.3" -release -opensource -confirm-license \ + -nomake examples -nomake tests \ + -skip qtwebengine -skip qt3d -skip qtwayland + +cmake --build . --parallel "$(nproc)" +cmake --install . +``` + +This builds the full "everywhere" module set (qtbase, qtdeclarative, qtmultimedia, qtserialport, qtsvg, qttools, qtwebsockets, etc.), which is what this project needs (`Widgets`, `SerialPort`, `Multimedia`, `MultimediaWidgets`, `OpenGLWidgets`, `Qml`, `Quick`, `QuickWidgets`). Expect this step to take a long time (well over an hour on most ARM64 boards) and to need ~20-30 GB of free disk space during the build. + +If you already have a Qt 6.8.x install (e.g. built previously, or via `aqtinstall`/a distro package new enough to include the above modules), you can skip this step — you just need its install prefix for step 4. + +## 3. Get the `Resources` folder (Packages repo) + +`SerialPrograms/CMakeLists.txt` expects a sibling `Packages` checkout next to this repo (i.e. `Arduino-Source/Packages`, not a `Resources` folder copied inside `SerialPrograms/`): + +```bash +cd /path/to/Arduino-Source # the repo root, containing SerialPrograms/, Common/, etc. +git clone https://github.com/PokemonAutomation/Packages +``` + +CMake copies `Packages/Resources` into the build output automatically on first configure/build. + +## 4. Configure and build + +From the repo root: + +```bash +cmake -S SerialPrograms -B build/RelWithDebInfo -G Ninja \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_PREFIX_PATH="$HOME/qt/6.8.3" + +cmake --build build/RelWithDebInfo --parallel "$(nproc)" +``` + +Notes: +- **Discord Social SDK is auto-disabled on Linux ARM64.** Discord doesn't offer a Linux ARM64 build of the Social SDK (per their platform-compatibility docs, Linux support is x86_64-only; Windows ARM64 and macOS ARM64 are both fully supported). `CMakeLists.txt` defaults the `PA_SOCIAL_SDK` option to `OFF` automatically when it detects a non-Apple ARM/aarch64 target, so you don't need to pass anything for this — it's mentioned here only so you know why `Compiling with Discord social SDK integration disabled` shows up during configure. You can still force it on/off explicitly with `-DPA_SOCIAL_SDK=ON` or `=OFF` on any platform. +- **ONNX Runtime** is downloaded automatically for you (aarch64 build, from the official `microsoft/onnxruntime` GitHub releases) if you don't already have one. If you want to point at a pre-downloaded copy instead, pass `-DONNX_ROOT_PATH=/path/to/onnxruntime-linux-aarch64-1.23.0`. +- `DPP` (D++ / Discord bot library) is optional and auto-detected via `pkg-config`; it isn't installed by the apt commands above, so you'll see `Compiling with DPP integration disabled`, which is expected and fine. + +The two binaries are produced at `build/RelWithDebInfo/SerialPrograms` (GUI) and `build/RelWithDebInfo/SerialProgramsCommandLine`. + +## 5. Run + +```bash +./build/RelWithDebInfo/SerialPrograms +``` + +Only the command-line tool and a headless (`QT_QPA_PLATFORM=offscreen`) launch of the GUI binary were exercised while verifying this build — both start up and resolve all shared libraries correctly (checked with `ldd`). Actual on-screen GUI behavior (e.g. the video-preview flicker noted for x86_64 Ubuntu in `Build-Ubuntu-Qt6.8.2.md`) has not been separately verified on ARM64. + +
+ +**Discord Server:** + +[](https://discord.gg/cQ4gWxN) diff --git a/SerialPrograms/CMakeLists.txt b/SerialPrograms/CMakeLists.txt index 26031d441f..012b75b394 100644 --- a/SerialPrograms/CMakeLists.txt +++ b/SerialPrograms/CMakeLists.txt @@ -448,9 +448,13 @@ else() # macOS and Linux target_include_directories(SerialProgramsLib PUBLIC ${ONNXRUNTIME_INCLUDE_DIRS}) target_link_libraries(SerialProgramsLib PUBLIC ${ONNXRUNTIME_LIBRARIES}) - else() + else() # linux, download onnxruntime set(ONNXRUNTIME_VERSION "1.23.0") - set(ONNXRUNTIME_ARCH "x64") + if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^(arm|arm64|aarch64)") + set(ONNXRUNTIME_ARCH "aarch64") + else() + set(ONNXRUNTIME_ARCH "x64") + endif() set(ONNXRUNTIME_DIR_NAME "onnxruntime-linux-${ONNXRUNTIME_ARCH}-${ONNXRUNTIME_VERSION}") set(ONNXRUNTIME_TGZ_NAME "${ONNXRUNTIME_DIR_NAME}.tgz") # build up the URL based on the version and name @@ -517,15 +521,24 @@ else() # macOS and Linux else() message(FATAL_ERROR "Could not find ONNX Runtime headers or library.") endif() - endif () + endif () # end searching or downloading onnx runtime # Systemd DBus Library - message(STATUS "Using bundled sdbus-c++ library.") + # Used for different programs on the same computer to communicate with each other. + # The bundled archive is prebuilt native object code, so it must be picked per-arch + # (a single .a cannot serve both x86_64 and aarch64 Linux). + if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^(arm|arm64|aarch64)") + set(SDBUS_CPP_LIB "${REPO_ROOT_DIR}/3rdParty/sdbus-cpp/lib/libsdbus-c++-aarch64.a") + else() + set(SDBUS_CPP_LIB "${REPO_ROOT_DIR}/3rdParty/sdbus-cpp/lib/libsdbus-c++-x86_64.a") + endif() + message(STATUS "Using bundled sdbus-c++ library: ${SDBUS_CPP_LIB}") + target_include_directories(SerialProgramsLib PRIVATE ${REPO_ROOT_DIR}/3rdParty/sdbus-cpp/include ) target_link_libraries(SerialProgramsLib PRIVATE - ${REPO_ROOT_DIR}/3rdParty/sdbus-cpp/lib/libsdbus-c++.a + ${SDBUS_CPP_LIB} systemd #sdbus-c++ relies on libsystemd, almost all distros should have this ) @@ -533,7 +546,7 @@ else() # macOS and Linux ${REPO_ROOT_DIR}/3rdParty/sdbus-cpp/include ) target_link_libraries(CoreLib PRIVATE - ${REPO_ROOT_DIR}/3rdParty/sdbus-cpp/lib/libsdbus-c++.a + ${SDBUS_CPP_LIB} systemd #sdbus-c++ relies on libsystemd, almost all distros should have this ) endif() # end Linux @@ -571,27 +584,41 @@ else() # macOS and Linux message(NOTICE "Compiling with DPP integration disabled") endif() - if (APPLE) - set(DISCORD_ZIP "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_mac.zip") - set(DISCORD_DIR "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_mac") - set(DISCORD_LIB_RELEASE "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_mac/lib/release/libdiscord_partner_sdk.dylib") + # Discord's Social SDK does not offer a Linux ARM64 build as of 2026 Sep 5, so we set + # CMake option PA_SOCIAL_SDK_DEFAULT to off on ARM64 Linux and on for all other platforms. + # For future development, you can still force on/off explicitly on any platform via + # -DPA_SOCIAL_SDK=ON/OFF. + if (NOT APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm|arm64|aarch64)") + set(PA_SOCIAL_SDK_DEFAULT OFF) else() - set(DISCORD_ZIP "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_linux.zip") - set(DISCORD_DIR "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_linux") - set(DISCORD_LIB_RELEASE "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_linux/lib/release/libdiscord_partner_sdk.so") + set(PA_SOCIAL_SDK_DEFAULT ON) endif() + option(PA_SOCIAL_SDK "Enable Discord social SDK integration" ${PA_SOCIAL_SDK_DEFAULT}) + if (PA_SOCIAL_SDK) + if (APPLE) + set(DISCORD_ZIP "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_mac.zip") + set(DISCORD_DIR "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_mac") + set(DISCORD_LIB_RELEASE "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_mac/lib/release/libdiscord_partner_sdk.dylib") + else() + set(DISCORD_ZIP "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_linux.zip") + set(DISCORD_DIR "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_linux") + set(DISCORD_LIB_RELEASE "${REPO_ROOT_DIR}/3rdPartyBinaries/discord_social_sdk_linux/lib/release/libdiscord_partner_sdk.so") + endif() - if (NOT EXISTS "${DISCORD_DIR}") - message(STATUS "Discord SDK not found, extracting from zip...") - execute_process( - COMMAND ${CMAKE_COMMAND} -E tar xf "${DISCORD_ZIP}" - WORKING_DIRECTORY "${REPO_ROOT_DIR}/3rdPartyBinaries" - ) - endif() + if (NOT EXISTS "${DISCORD_DIR}") + message(STATUS "Discord SDK not found, extracting from zip...") + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xf "${DISCORD_ZIP}" + WORKING_DIRECTORY "${REPO_ROOT_DIR}/3rdPartyBinaries" + ) + endif() - target_compile_definitions(SerialProgramsLib PUBLIC PA_SOCIAL_SDK) - target_include_directories(SerialProgramsLib SYSTEM PRIVATE ../3rdParty/discord_social_sdk/) - target_link_libraries(SerialProgramsLib PRIVATE ${DISCORD_LIB_RELEASE}) + target_compile_definitions(SerialProgramsLib PUBLIC PA_SOCIAL_SDK) + target_include_directories(SerialProgramsLib SYSTEM PRIVATE ../3rdParty/discord_social_sdk/) + target_link_libraries(SerialProgramsLib PRIVATE ${DISCORD_LIB_RELEASE}) + else() + message(NOTICE "Compiling with Discord social SDK integration disabled") + endif() if(APPLE) target_compile_options(SerialProgramsLib PRIVATE -Wall -Wextra -Wpedantic -Werror -Wshorten-64-to-32) @@ -606,8 +633,8 @@ else() # macOS and Linux target_compile_options(CoreLib PRIVATE -Wall -Wextra -Wpedantic -Werror -fno-strict-aliasing) endif() - if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") - # Arm CPU + if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^(arm|arm64|aarch64)") + # Arm CPU (arm64 on macOS, aarch64 on Linux) # Run-time ISA dispatching target_compile_definitions(SerialProgramsLib PRIVATE PA_AutoDispatch_arm64_20_M1) else() diff --git a/SerialPrograms/Source/CommonTools/OCR/OCR_RawTesseractOCR.cpp b/SerialPrograms/Source/CommonTools/OCR/OCR_RawTesseractOCR.cpp index 2c8b341ff4..5b64f08c8b 100644 --- a/SerialPrograms/Source/CommonTools/OCR/OCR_RawTesseractOCR.cpp +++ b/SerialPrograms/Source/CommonTools/OCR/OCR_RawTesseractOCR.cpp @@ -96,7 +96,7 @@ class TesseractPool{ void add_instance(){ // Check for non-ascii characters in path. for (char ch : m_training_data_path){ - if (ch < 0){ + if ((unsigned char)ch > 127){ throw InternalSystemError( nullptr, PA_CURRENT_FUNCTION, "Detected non-ASCII character in Tesseract path. Please move the program to a path with only ASCII characters." diff --git a/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_arm64_NEON.h b/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_arm64_NEON.h index 3edf9f815a..2a5a1c89f7 100644 --- a/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_arm64_NEON.h +++ b/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_arm64_NEON.h @@ -7,6 +7,7 @@ #ifndef PokemonAutomation_Kernels_BinaryImage_BasicFilters_arm64_NEON_H #define PokemonAutomation_Kernels_BinaryImage_BasicFilters_arm64_NEON_H +#include #include "Kernels/PartialWordAccess/Kernels_PartialWordAccess_arm64_NEON.h" // #include @@ -287,6 +288,9 @@ class Compressor_RgbEuclidean_arm64_NEON{ uint32x4_t in_u32 = vld1q_u32(pixel); return convert4(vreinterpretq_u8_u32(in_u32)); } + PA_FORCE_INLINE uint64_t convert4(const uint8x16_t& in_u8) const{ + return convert4(vreinterpretq_u32_u8(in_u8)); + } PA_FORCE_INLINE uint64_t convert4(const uint32x4_t& in_u32) const{ // subtract the expected values uint32x4_t in_dif_u32 = vreinterpretq_u32_u8(vabdq_u8(vreinterpretq_u8_u32(in_u32), m_expected_color_rgb_u8)); diff --git a/SerialPrograms/Source/Kernels/BinaryMatrix/Kernels_BinaryMatrixTile_64x8_arm64_NEON.h b/SerialPrograms/Source/Kernels/BinaryMatrix/Kernels_BinaryMatrixTile_64x8_arm64_NEON.h index 3bb1fb50a1..23068d1f43 100644 --- a/SerialPrograms/Source/Kernels/BinaryMatrix/Kernels_BinaryMatrixTile_64x8_arm64_NEON.h +++ b/SerialPrograms/Source/Kernels/BinaryMatrix/Kernels_BinaryMatrixTile_64x8_arm64_NEON.h @@ -222,13 +222,13 @@ struct BinaryTile_64x8_arm64_NEON{ // The shifted values are first performend a logical OR with the values in `tile` before assigned to `tile`. // In this way it the operation does not damage other un-assigned regions on `tile`. void copy_to_shift_np(BinaryTile_64x8_arm64_NEON& tile, size_t shift_x, size_t shift_y) const{ - uint64x2_t shift_x_u64x2 = vdupq_n_u64(shift_x); + int64x2_t shift_x_s64x2 = vreinterpretq_s64_u64(vdupq_n_u64(shift_x)); const uint64_t* src = (const uint64_t*)&vec; uint64_t* dest = (uint64_t*)&tile.vec; while (shift_y < 7){ uint64x2_t row_64x2 = vld1q_u64(src + shift_y); // left shift - row_64x2 = vshlq_u64(row_64x2, shift_x_u64x2); + row_64x2 = vshlq_u64(row_64x2, shift_x_s64x2); row_64x2 = vorrq_u64(row_64x2, vld1q_u64(dest)); vst1q_u64(dest, row_64x2); dest += 2; @@ -275,7 +275,7 @@ struct BinaryTile_64x8_arm64_NEON{ // The shifted values are first performend a logical OR with the values in `tile` before assigned to `tile`. // In this way it the operation does not damage other un-assigned regions on `tile`. void copy_to_shift_nn(BinaryTile_64x8_arm64_NEON& tile, size_t shift_x, size_t shift_y) const{ - uint64x2_t shift_x_u64x2 = vdupq_n_u64(shift_x); + int64x2_t shift_x_s64x2 = vreinterpretq_s64_u64(vdupq_n_u64(shift_x)); const uint64_t* src = (const uint64_t*)&vec; uint64_t* dest = (uint64_t*)&tile.vec; if (shift_y & 1){ @@ -286,7 +286,7 @@ struct BinaryTile_64x8_arm64_NEON{ while (shift_y < 8){ uint64x2_t row_64x2 = vld1q_u64(src); // left shift - row_64x2 = vshlq_u64(row_64x2, shift_x_u64x2); + row_64x2 = vshlq_u64(row_64x2, shift_x_s64x2); row_64x2 = vorrq_u64(row_64x2, vld1q_u64(dest + shift_y)); vst1q_u64((dest + shift_y), row_64x2); src += 2; diff --git a/SerialPrograms/Source/Kernels/BinaryMatrix/Kernels_BinaryMatrix_Tests.cpp b/SerialPrograms/Source/Kernels/BinaryMatrix/Kernels_BinaryMatrix_Tests.cpp index 6a6f516bac..798f614f56 100644 --- a/SerialPrograms/Source/Kernels/BinaryMatrix/Kernels_BinaryMatrix_Tests.cpp +++ b/SerialPrograms/Source/Kernels/BinaryMatrix/Kernels_BinaryMatrix_Tests.cpp @@ -328,7 +328,7 @@ int test_binary_matrix_tile(){ for (size_t i = 0; i < num_bytes; ++i){ if (x[i] != buffer[i + 16]){ cout << "Error: PartialWordAccess_arm64_NEON(" << num_bytes << ")::store_int_no_past_end(), i = " << i << " is " << int(buffer[i + 16]) - << ", but should be " << int(x[i + 16]) << endl; + << ", but should be " << int(x[i]) << endl; return 1; } } diff --git a/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic_Routines_ARM64_NEON.h b/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic_Routines_ARM64_NEON.h index f8176efa62..652c4899fd 100644 --- a/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic_Routines_ARM64_NEON.h +++ b/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic_Routines_ARM64_NEON.h @@ -5,6 +5,7 @@ */ #include +#include #include "Common/Compiler.h" #include "Kernels/PartialWordAccess/Kernels_PartialWordAccess_arm64_NEON.h" #include "Kernels/Kernels_arm64_NEON.h" diff --git a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_ARM64_NEON.cpp b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_ARM64_NEON.cpp index c8761c17d7..6917c7553f 100644 --- a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_ARM64_NEON.cpp +++ b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_ARM64_NEON.cpp @@ -6,6 +6,7 @@ #ifdef PA_AutoDispatch_arm64_20_M1 +#include #include "Kernels/Kernels_arm64_NEON.h" #include "Kernels_ImageFilter_RGB32_Euclidean.h" #include "Kernels/ImageFilters/Kernels_ImageFilter_Basic_Routines.h" diff --git a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_Range/Kernels_ImageFilter_RGB32_Range_ARM64_NEON.cpp b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_Range/Kernels_ImageFilter_RGB32_Range_ARM64_NEON.cpp index 97c070c8d9..89103c7657 100644 --- a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_Range/Kernels_ImageFilter_RGB32_Range_ARM64_NEON.cpp +++ b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_Range/Kernels_ImageFilter_RGB32_Range_ARM64_NEON.cpp @@ -32,14 +32,14 @@ class PixelTest_Rgb32Range_ARM64_NEON{ ) : m_mins_u8(vreinterpretq_u8_u32(vdupq_n_u32(mins))) , m_maxs_u8(vreinterpretq_u8_u32(vdupq_n_u32(maxs))) - , m_zeros_u8(vreinterpretq_u32_u8(vdupq_n_u8(0))) + , m_zeros_u8(vdupq_n_u8(0)) {} PA_FORCE_INLINE PixelTest_Rgb32Range_ARM64_NEON( const ToBlackWhiteRgb32RangeFilter& filter ) : m_mins_u8(vreinterpretq_u8_u32(vdupq_n_u32(filter.mins))) , m_maxs_u8(vreinterpretq_u8_u32(vdupq_n_u32(filter.maxs))) - , m_zeros_u8(vreinterpretq_u32_u8(vdupq_n_u8(0))) + , m_zeros_u8(vdupq_n_u8(0)) {} // Return a mask indicating which lanes are in range. diff --git a/SerialPrograms/Source/Kernels/ImageScaleBrightness/Kernels_ImageScaleBrightness_arm64_NEON.cpp b/SerialPrograms/Source/Kernels/ImageScaleBrightness/Kernels_ImageScaleBrightness_arm64_NEON.cpp index 96c9549299..c15619b87f 100644 --- a/SerialPrograms/Source/Kernels/ImageScaleBrightness/Kernels_ImageScaleBrightness_arm64_NEON.cpp +++ b/SerialPrograms/Source/Kernels/ImageScaleBrightness/Kernels_ImageScaleBrightness_arm64_NEON.cpp @@ -75,7 +75,7 @@ PA_FORCE_INLINE void scale_brightness_arm64_NEON_four_pixels_per_channel_scale( uint32x4_t gb_u32x4 = vsliq_n_u32(b_u32x4, g_u32x4, 8); // shift r channels left by 16, then combine with gb channels uint32x4_t rgb_u32x4 = vsliq_n_u32(gb_u32x4, r_u32x4, 16); - vec_u32x4 = vorrq_s32(a_u32x4, rgb_u32x4); + vec_u32x4 = vorrq_u32(a_u32x4, rgb_u32x4); vst1q_u32(&image[c], vec_u32x4); } diff --git a/SerialPrograms/Source/Kernels/Kernels_arm64_NEON.h b/SerialPrograms/Source/Kernels/Kernels_arm64_NEON.h index ba4d97c963..3bcc63224c 100644 --- a/SerialPrograms/Source/Kernels/Kernels_arm64_NEON.h +++ b/SerialPrograms/Source/Kernels/Kernels_arm64_NEON.h @@ -90,10 +90,10 @@ PA_FORCE_INLINE uint64_t reduce32_arm64_NEON(uint32x4_t x){ // and one new uint64x2_t vector from the upper half of them. // Assign r0 to the former, r1 to the letter. PA_FORCE_INLINE void transpose_u64_2x2_NEON(uint64x2_t& r0, uint64x2_t& r1){ - int64x1_t r0_l = vget_low_u64(r0); - int64x1_t r1_l = vget_low_u64(r1); - int64x1_t r0_h = vget_high_u64(r0); - int64x1_t r1_h = vget_high_u64(r1); + uint64x1_t r0_l = vget_low_u64(r0); + uint64x1_t r1_l = vget_low_u64(r1); + uint64x1_t r0_h = vget_high_u64(r0); + uint64x1_t r1_h = vget_high_u64(r1); r0 = vcombine_u64(r0_l, r1_l); r1 = vcombine_u64(r0_h, r1_h); diff --git a/SerialPrograms/Source/Kernels/Waterfill/Kernels_Waterfill_Core_64x8_arm64_NEON.h b/SerialPrograms/Source/Kernels/Waterfill/Kernels_Waterfill_Core_64x8_arm64_NEON.h index 97749af917..34c6b4d17d 100644 --- a/SerialPrograms/Source/Kernels/Waterfill/Kernels_Waterfill_Core_64x8_arm64_NEON.h +++ b/SerialPrograms/Source/Kernels/Waterfill/Kernels_Waterfill_Core_64x8_arm64_NEON.h @@ -50,7 +50,7 @@ PA_FORCE_INLINE uint64x2_t bit_reverse(uint64x2_t x){ r1 = vandq_u8(r1, vdupq_n_u8(0xaa)); r1 = vorrq_u8(r0, r1); // a, b, c, d, e, f, g, h - return r1; + return vreinterpretq_u64_u8(r1); }