diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000000..3b1abe06b588 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,12 @@ +# Oboe Audio Bridge Optimizations + +## CPU Affinity Pinning +As of Oboe `main` branch (post-1.9.0), internal headers like `common/Process.h` have been removed. +Do not attempt to include internal Oboe headers for CPU affinity. +Instead, use standard Linux `sched_setaffinity` in `oboe_bridge.cpp` to pin the audio callback thread to high-performance cores (typically the higher-indexed half of available cores in Android big.LITTLE architectures). + +## ADPF Integration +The bridge uses `stream_->reportActualWorkDuration()` within the audio callback. This is critical for the Android Dynamic Performance Framework (ADPF) to adjust CPU frequencies accurately for low-latency audio without underruns. + +## Build Configuration +`OBOE_ENABLE_FLOWGRAPH` is set to `OFF` in `CMakeLists.txt` to minimize binary size, as we perform all mixing in BASS and only use Oboe for final hardware delivery. diff --git a/osu.Android/Native/CMakeLists.txt b/osu.Android/Native/CMakeLists.txt index d6d30ee9ed5e..fb554c3fc338 100644 --- a/osu.Android/Native/CMakeLists.txt +++ b/osu.Android/Native/CMakeLists.txt @@ -46,8 +46,6 @@ add_library(osu_native SHARED vulkan_bridge.cpp ) -# Add Oboe internal headers to include path for Process.h (CPU affinity). -target_include_directories(osu_native PRIVATE ${oboe_SOURCE_DIR}/src) target_link_libraries(osu_native ${OBOE_LIB} diff --git a/osu.Android/Native/oboe_bridge.cpp b/osu.Android/Native/oboe_bridge.cpp index 1dc646825fef..bb39a31af64b 100644 --- a/osu.Android/Native/oboe_bridge.cpp +++ b/osu.Android/Native/oboe_bridge.cpp @@ -4,7 +4,9 @@ #include "oboe_bridge.h" #include #include -#include +#include +#include +#include #include #include #include @@ -205,15 +207,22 @@ oboe::DataCallbackResult OboeBridge::onAudioReady( // Attempt to set CPU affinity to high-performance cores. if (!affinitySet_.load(std::memory_order_relaxed)) { - std::vector exclusiveCores = oboe::Process::getExclusiveCores(); - - if (!exclusiveCores.empty()) { - oboe::Result result = oboe::Process::setThreadAffinity( - oboe::Process::getThreadId(), - exclusiveCores); + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + + int num_cores = sysconf(_SC_NPROCESSORS_CONF); + if (num_cores > 0) { + // Target the "big" cores (higher indexed) for better performance. + // In big.LITTLE, indices 4-7 are typically the high-performance cores. + int start_core = std::max(0, num_cores / 2); + for (int i = start_core; i < num_cores; ++i) { + CPU_SET(i, &cpuset); + } - if (result == oboe::Result::OK) { - LOGI("Oboe audio thread pinned to exclusive cores"); + if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset) == 0) { + LOGI("Oboe audio thread pinned to cores %d-%d", start_core, num_cores - 1); + } else { + LOGE("Failed to set thread affinity: %d", errno); } } affinitySet_.store(true); diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 283824a6868c..5d7c70e8fae0 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -1,6 +1,7 @@  + true net10.0-android Exe osu.Android