From 5cd6ea3be1b7a369fd1d30e9182f5b42e39c83aa Mon Sep 17 00:00:00 2001 From: Xget7 Date: Tue, 20 Oct 2026 01:17:49 -0300 Subject: [PATCH 1/3] Name the Android native test executables after the classes they test The seven splatkit_*_test executables kept the names of the pre-restructure layout (gpu_buffer, world, visibility, radix_sort, ...), so none of them matched the Vulkan class vocabulary the sources and test files now use. Each executable is now splatkit_vulkan__test, with the visibility and frame tests spelled out as visibility_pass and frame_compute, and the two usage strings follow. Nothing outside the CMake file and those strings referenced them. --- .../splatkit-android/tests/CMakeLists.txt | 28 +++++++++---------- .../vulkan/device/VulkanBufferTest.cpp | 2 +- .../device/VulkanUploadPressureTest.cpp | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/splatkit-android/tests/CMakeLists.txt b/packages/splatkit-android/tests/CMakeLists.txt index f25579fb..bc4ccbaf 100644 --- a/packages/splatkit-android/tests/CMakeLists.txt +++ b/packages/splatkit-android/tests/CMakeLists.txt @@ -15,27 +15,27 @@ target_compile_options(splatkit_vulkan_test_support PRIVATE target_link_libraries(splatkit_vulkan_test_support PUBLIC splatkit_engine vk-bootstrap::vk-bootstrap GPUOpen::VulkanMemoryAllocator vulkan android log) -add_executable(splatkit_gpu_buffer_test rendering/vulkan/device/VulkanBufferTest.cpp) -target_link_libraries(splatkit_gpu_buffer_test PRIVATE splatkit_vulkan_test_support) -add_executable(splatkit_gpu_upload_pressure_test rendering/vulkan/device/VulkanUploadPressureTest.cpp) -target_link_libraries(splatkit_gpu_upload_pressure_test PRIVATE splatkit_vulkan_test_support) -add_executable(splatkit_world_test rendering/vulkan/world/VulkanWorldTest.cpp +add_executable(splatkit_vulkan_buffer_test rendering/vulkan/device/VulkanBufferTest.cpp) +target_link_libraries(splatkit_vulkan_buffer_test PRIVATE splatkit_vulkan_test_support) +add_executable(splatkit_vulkan_upload_pressure_test rendering/vulkan/device/VulkanUploadPressureTest.cpp) +target_link_libraries(splatkit_vulkan_upload_pressure_test PRIVATE splatkit_vulkan_test_support) +add_executable(splatkit_vulkan_world_test rendering/vulkan/world/VulkanWorldTest.cpp ${vulkan_source_dir}/world/VulkanWorld.cpp) -target_link_libraries(splatkit_world_test PRIVATE splatkit_vulkan_test_support) -add_executable(splatkit_lod_selection_test rendering/vulkan/selection/VulkanLodSelectionTest.cpp +target_link_libraries(splatkit_vulkan_world_test PRIVATE splatkit_vulkan_test_support) +add_executable(splatkit_vulkan_lod_selection_test rendering/vulkan/selection/VulkanLodSelectionTest.cpp ${vulkan_source_dir}/selection/VulkanLodSelection.cpp) -target_link_libraries(splatkit_lod_selection_test PRIVATE +target_link_libraries(splatkit_vulkan_lod_selection_test PRIVATE splatkit_vulkan_test_support splatkit_shaders) -add_executable(splatkit_visibility_test rendering/vulkan/cull/VulkanVisibilityPassTest.cpp +add_executable(splatkit_vulkan_visibility_pass_test rendering/vulkan/cull/VulkanVisibilityPassTest.cpp ${vulkan_source_dir}/cull/VulkanVisibilityPass.cpp) -target_link_libraries(splatkit_visibility_test PRIVATE +target_link_libraries(splatkit_vulkan_visibility_pass_test PRIVATE splatkit_vulkan_test_support splatkit_shaders) -add_executable(splatkit_vulkan_frame_test rendering/vulkan/frame/VulkanFrameComputeTest.cpp +add_executable(splatkit_vulkan_frame_compute_test rendering/vulkan/frame/VulkanFrameComputeTest.cpp ${vulkan_source_dir}/frame/VulkanFrameCompute.cpp ${vulkan_source_dir}/selection/VulkanLodSelection.cpp ${vulkan_source_dir}/cull/VulkanVisibilityPass.cpp ${vulkan_source_dir}/sort/VulkanRadixSort.cpp) -target_link_libraries(splatkit_vulkan_frame_test PRIVATE +target_link_libraries(splatkit_vulkan_frame_compute_test PRIVATE splatkit_vulkan_test_support splatkit_shaders) -add_executable(splatkit_radix_sort_test rendering/vulkan/sort/VulkanRadixSortTest.cpp +add_executable(splatkit_vulkan_radix_sort_test rendering/vulkan/sort/VulkanRadixSortTest.cpp ${vulkan_source_dir}/sort/VulkanRadixSort.cpp) -target_link_libraries(splatkit_radix_sort_test PRIVATE +target_link_libraries(splatkit_vulkan_radix_sort_test PRIVATE splatkit_vulkan_test_support splatkit_shaders) diff --git a/packages/splatkit-android/tests/rendering/vulkan/device/VulkanBufferTest.cpp b/packages/splatkit-android/tests/rendering/vulkan/device/VulkanBufferTest.cpp index 657ffff7..a16f8265 100644 --- a/packages/splatkit-android/tests/rendering/vulkan/device/VulkanBufferTest.cpp +++ b/packages/splatkit-android/tests/rendering/vulkan/device/VulkanBufferTest.cpp @@ -8,7 +8,7 @@ int main(int argc, char** argv) { using test::require; try { const bool small = argc == 2 && std::strcmp(argv[1], "--small") == 0; - require(argc == 1 || small, "usage: splatkit_gpu_buffer_test [--small]"); + require(argc == 1 || small, "usage: splatkit_vulkan_buffer_test [--small]"); test::VulkanTestContext gpu; std::printf("GPU: %s\n", gpu.context->deviceDescription().c_str()); std::vector expected(small ? 4096 : 16000000); diff --git a/packages/splatkit-android/tests/rendering/vulkan/device/VulkanUploadPressureTest.cpp b/packages/splatkit-android/tests/rendering/vulkan/device/VulkanUploadPressureTest.cpp index 0cb18a2a..c4e3a2e8 100644 --- a/packages/splatkit-android/tests/rendering/vulkan/device/VulkanUploadPressureTest.cpp +++ b/packages/splatkit-android/tests/rendering/vulkan/device/VulkanUploadPressureTest.cpp @@ -11,7 +11,7 @@ int main(int argc, char** argv) { std::setvbuf(stdout, nullptr, _IONBF, 0); try { const bool small = argc == 2 && std::strcmp(argv[1], "--small") == 0; - require(argc == 1 || small, "usage: splatkit_gpu_upload_pressure_test [--small]"); + require(argc == 1 || small, "usage: splatkit_vulkan_upload_pressure_test [--small]"); splatkit::test::VulkanTestContext gpu; const uint32_t capacity = small ? 262145 : 3000000; std::printf("upload-pressure GPU=%s capacity=%u validation=%s\n", From c034c6d49649664d2f6c4e87c708fe75d97b41bb Mon Sep 17 00:00:00 2001 From: Xget7 Date: Tue, 20 Oct 2026 01:17:50 -0300 Subject: [PATCH 2/3] Link every Android native test in the C++ lint job The splatkit_*_test executables were only built on a developer's machine, so a wrong source path or an undefined reference surfaced when the test was pushed to a phone. scripts/lint-cpp.sh already configures the Android tree with SPLATKIT_ANDROID_BUILD_TESTS=ON for clang-tidy, so it now also builds the new splatkit_android_tests aggregate target, which links all seven tests with the NDK toolchain, and prints the build log on failure. Keeping it there leaves one script owning the Android test configuration, and the Android mirror already ships lint.yml and lint-cpp.sh. --- packages/splatkit-android/tests/CMakeLists.txt | 11 +++++++++++ scripts/lint-cpp.sh | 10 +++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/splatkit-android/tests/CMakeLists.txt b/packages/splatkit-android/tests/CMakeLists.txt index bc4ccbaf..19798c0e 100644 --- a/packages/splatkit-android/tests/CMakeLists.txt +++ b/packages/splatkit-android/tests/CMakeLists.txt @@ -39,3 +39,14 @@ add_executable(splatkit_vulkan_radix_sort_test rendering/vulkan/sort/VulkanRadix ${vulkan_source_dir}/sort/VulkanRadixSort.cpp) target_link_libraries(splatkit_vulkan_radix_sort_test PRIVATE splatkit_vulkan_test_support splatkit_shaders) + +# Building this target links every device test; scripts/lint-cpp.sh does so in CI. +add_custom_target(splatkit_android_tests DEPENDS + splatkit_vulkan_buffer_test + splatkit_vulkan_upload_pressure_test + splatkit_vulkan_world_test + splatkit_vulkan_lod_selection_test + splatkit_vulkan_visibility_pass_test + splatkit_vulkan_frame_compute_test + splatkit_vulkan_radix_sort_test +) diff --git a/scripts/lint-cpp.sh b/scripts/lint-cpp.sh index 4ae4ea57..540bb404 100755 --- a/scripts/lint-cpp.sh +++ b/scripts/lint-cpp.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash # Formats and lints every C++ source of the repository with the clang tools the NDK -# ships, so the machine that builds the library is the machine that lints it. +# ships, so the machine that builds the library is the machine that lints it. It also +# links the Android device tests, which nothing else builds in CI. # # scripts/lint-cpp.sh check: exit 1 on a formatting or clang-tidy finding # scripts/lint-cpp.sh --fix rewrite the formatting and apply clang-tidy's fixes @@ -90,6 +91,13 @@ cmake -S "$android" -B "$build/android" "${toolchain[@]}" \ -DSPLATKIT_ANDROID_BUILD_TESTS=ON > /dev/null # The splat pipeline includes the generated shader headers. cmake --build "$build/android" --target splatkit_shaders_generate > /dev/null +# Linking the device tests catches a wrong source path or an undefined reference that +# clang-tidy, which only parses, would let through to a phone. +echo "link splatkit-android tests" +if ! tests_log="$(cmake --build "$build/android" --target splatkit_android_tests 2>&1)"; then + printf '%s\n' "$tests_log" >&2 + exit 1 +fi failed=0 tidy() { # From 519bb6de2ce342576b33e2b41261be13e3768971 Mon Sep 17 00:00:00 2001 From: Xget7 Date: Tue, 20 Oct 2026 01:18:47 -0300 Subject: [PATCH 3/3] Document building and running the Android native tests on a device The splatkit_vulkan_*_test executables had no written recipe, so the configure flags, the target and the adb steps lived only in agent notes. The Android README gets a short "Native tests on a device" section, and CONTRIBUTING.md now says the lint script links the tests while running them on a phone stays a manual step. --- CONTRIBUTING.md | 1 + packages/splatkit-android/README.md | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5b897bc2..469fa722 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -76,6 +76,7 @@ scripts/lint-cpp.sh --fix # rewrite the formatting and apply the fixes clang- Both tools come from the NDK the project pins, so a machine that builds the library can lint it; `.clang-format` and `.clang-tidy` at the root hold the rules. The script configures `splat-core`, `splatkit-engine` and `splatkit-android` for the Android target and lints tests and tools too. +It also links the Android native tests, so a wrong source path or an undefined reference fails CI; [running them on a device](packages/splatkit-android/README.md#native-tests-on-a-device) stays manual. `git config core.hooksPath .githooks` installs a pre-push hook that runs `scripts/lint-cpp.sh --format-only`, the seconds-long formatting half of that check. VS Code's C/C++ extension reads the compile databases it leaves in `build/lint`, as [.vscode/settings.json](.vscode/settings.json) sets up. clang-tidy holds every function to its default cognitive complexity of 25, counting the source as written, so test assertion macros add nothing. diff --git a/packages/splatkit-android/README.md b/packages/splatkit-android/README.md index 0ffb28d7..e57c0f6c 100644 --- a/packages/splatkit-android/README.md +++ b/packages/splatkit-android/README.md @@ -113,6 +113,25 @@ cd apps/android-dev ./gradlew :splatkit:assembleRelease :splatkit:testDebugUnitTest ``` +## Native tests on a device + +The `splatkit_vulkan_*_test` executables need a real Vulkan device and run without a surface. +`scripts/lint-cpp.sh` links all of them in CI; running them is a manual device step. +Build them outside the checkout with the NDK toolchain flags from that script plus `-DSPLATKIT_ANDROID_BUILD_TESTS=ON`. + +```sh +cmake -S packages/splatkit-android/src/main/cpp -B "$BUILD" \ + -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \ + -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-29 -DANDROID_STL=c++_static \ + -DSPLATKIT_ANDROID_BUILD_TESTS=ON +cmake --build "$BUILD" --target splatkit_android_tests +for t in "$BUILD"/tests/splatkit_vulkan_*_test; do + adb push "$t" /data/local/tmp/ && adb shell "/data/local/tmp/$(basename "$t")" +done +``` + +Each test exits 0 on success; `splatkit_vulkan_buffer_test` and `splatkit_vulkan_upload_pressure_test` accept `--small` for a device with little memory, which skips their large cases. + Tests and emulator evidence do not replace physical Adreno/Mali validation or reference-image acceptance. Source builds enable 16 KB ELF alignment; CI checks every packaged shared library and APK ZIP alignment with `scripts/check_android_alignment.py`. Artifact alignment checks do not replace execution on a 16 KB device.