Skip to content

Commit 717e240

Browse files
PixelyIonlordalcol
authored andcommitted
Support standalone executable builds on Android
Only building dEQP as an app on Android is supported. This change allows building dEQP as a standalone executable on Android that can be run from adb shell. This is more convenient for iterative testing during driver development as the command and corresponding output are in one place. VK-GL-CTS issue: 5320 Components: Framework Change-Id: Ibeac5160e058b96f9ece30e0eafb991bef570164
1 parent 89e8855 commit 717e240

File tree

6 files changed

+117
-27
lines changed

6 files changed

+117
-27
lines changed

CMakeLists.txt

+25-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
cmake_minimum_required(VERSION 3.20.0)
66

77
option(GLES_ALLOW_DIRECT_LINK "Allow direct linking to GLES libraries" OFF)
8+
option(DEQP_ANDROID_EXE "Build dEQP modules as executables rather than a library on Android" OFF)
89

910
# Target selection:
1011
# SELECTED_BUILD_TARGETS is a CMake option that can be set to a list of targets
@@ -204,6 +205,22 @@ if (DEFINED DEQP_EGL_LIBRARIES AND GLES_ALLOW_DIRECT_LINK)
204205
add_definitions(-DDEQP_EGL_DIRECT_LINK=1)
205206
endif ()
206207

208+
# Android build variants
209+
if (DE_OS_IS_ANDROID)
210+
if (DEQP_ANDROID_EXE)
211+
message(STATUS "DEQP_ANDROID_BUILD = EXE")
212+
set(DEQP_ANDROID_APP OFF)
213+
else ()
214+
message(STATUS "DEQP_ANDROID_BUILD = APP")
215+
set(DEQP_ANDROID_APP ON)
216+
217+
add_definitions(-DDEQP_IS_ANDROID_APP=1)
218+
endif ()
219+
else ()
220+
set(DEQP_ANDROID_EXE OFF)
221+
set(DEQP_ANDROID_APP OFF)
222+
endif ()
223+
207224
# Legacy APIs that don't support run-time loading
208225
if (DEQP_SUPPORT_GLES1)
209226
add_definitions(-DDEQP_SUPPORT_GLES1=1)
@@ -275,7 +292,7 @@ include_directories(
275292
external/vulkancts/framework/vulkan
276293
)
277294

278-
if (DE_OS_IS_ANDROID OR DE_OS_IS_IOS)
295+
if (DEQP_ANDROID_APP OR DE_OS_IS_IOS)
279296
# On Android deqp modules are compiled as libraries and linked into final .so
280297
set(DEQP_MODULE_LIBRARIES )
281298
set(DEQP_MODULE_ENTRY_POINTS )
@@ -319,7 +336,7 @@ macro (add_deqp_module MODULE_NAME SRCS LIBS EXECLIBS ENTRY)
319336
set(DEQP_MODULE_LIBRARIES ${DEQP_MODULE_LIBRARIES} PARENT_SCOPE)
320337
set(DEQP_MODULE_ENTRY_POINTS ${DEQP_MODULE_ENTRY_POINTS} PARENT_SCOPE)
321338

322-
if (NOT DE_OS_IS_ANDROID AND NOT DE_OS_IS_IOS)
339+
if (NOT DEQP_ANDROID_APP AND NOT DE_OS_IS_IOS)
323340
# Executable target
324341
add_executable(${MODULE_NAME} ${PROJECT_SOURCE_DIR}/framework/platform/tcuMain.cpp ${ENTRY})
325342
target_link_libraries(${MODULE_NAME} PUBLIC "${EXECLIBS}" "${MODULE_NAME}${MODULE_LIB_TARGET_POSTFIX}")
@@ -341,7 +358,7 @@ macro (add_deqp_module_skip_android MODULE_NAME SRCS LIBS EXECLIBS ENTRY)
341358
add_library("${MODULE_NAME}${MODULE_LIB_TARGET_POSTFIX}" STATIC ${SRCS})
342359
target_link_libraries("${MODULE_NAME}${MODULE_LIB_TARGET_POSTFIX}" ${LIBS})
343360

344-
if (NOT DE_OS_IS_ANDROID AND NOT DE_OS_IS_IOS)
361+
if (NOT DEQP_ANDROID_APP AND NOT DE_OS_IS_IOS)
345362
# Executable target
346363
add_executable(${MODULE_NAME} ${PROJECT_SOURCE_DIR}/framework/platform/tcuMain.cpp ${ENTRY})
347364
target_link_libraries(${MODULE_NAME} PUBLIC "${EXECLIBS}" "${MODULE_NAME}${MODULE_LIB_TARGET_POSTFIX}")
@@ -355,10 +372,10 @@ endmacro (add_deqp_module_skip_android)
355372

356373
# Macro for adding data dirs to module
357374
macro (add_data_dir MODULE_NAME SRC_DIR DST_DIR)
358-
if (DE_OS_IS_WIN32 OR DE_OS_IS_UNIX OR DE_OS_IS_OSX OR DE_OS_IS_QNX)
375+
if (DE_OS_IS_WIN32 OR DE_OS_IS_UNIX OR DE_OS_IS_OSX OR DE_OS_IS_QNX OR DEQP_ANDROID_EXE)
359376
add_custom_command(TARGET "${MODULE_NAME}${MODULE_DATA_TARGET_POSTFIX}" POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${DST_DIR})
360377

361-
elseif (DE_OS_IS_ANDROID)
378+
elseif (DEQP_ANDROID_APP)
362379
add_custom_command(TARGET "${MODULE_NAME}${MODULE_DATA_TARGET_POSTFIX}" POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_DIR} ${CMAKE_BINARY_DIR}/assets/${DST_DIR})
363380

364381
elseif (DE_OS_IS_IOS)
@@ -368,10 +385,10 @@ endmacro (add_data_dir)
368385

369386
# Macro for adding individual data files to module
370387
macro (add_data_file MODULE_NAME SRC_FILE DST_FILE)
371-
if (DE_OS_IS_WIN32 OR DE_OS_IS_UNIX OR DE_OS_IS_OSX OR DE_OS_IS_QNX)
388+
if (DE_OS_IS_WIN32 OR DE_OS_IS_UNIX OR DE_OS_IS_OSX OR DE_OS_IS_QNX OR DEQP_ANDROID_EXE)
372389
add_custom_command(TARGET "${MODULE_NAME}${MODULE_DATA_TARGET_POSTFIX}" POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FILE} ${CMAKE_CURRENT_BINARY_DIR}/${DST_FILE})
373390

374-
elseif (DE_OS_IS_ANDROID)
391+
elseif (DEQP_ANDROID_APP)
375392
add_custom_command(TARGET "${MODULE_NAME}${MODULE_DATA_TARGET_POSTFIX}" POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FILE} ${CMAKE_BINARY_DIR}/assets/${DST_FILE})
376393

377394
elseif (DE_OS_IS_IOS)
@@ -393,7 +410,7 @@ add_subdirectory(external/vulkancts/vkscpc ${MAYBE_EXCLUDE_FROM_ALL})
393410
add_subdirectory(external/openglcts ${MAYBE_EXCLUDE_FROM_ALL})
394411

395412
# Single-binary targets
396-
if (DE_OS_IS_ANDROID)
413+
if (DEQP_ANDROID_APP)
397414
include_directories(executor)
398415
include_directories(${PROJECT_BINARY_DIR}/external/vulkancts/framework/vulkan)
399416

external/vulkancts/README.md

+39
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ If building for 32-bit x86 with GCC, you probably also want to add `-msse2
107107

108108
### Android
109109

110+
There's two types of builds for Android:
111+
112+
#### App
113+
114+
This builds an APK that needs to be invoked via `adb shell` and the output needs
115+
to be read via `adb logcat`, it's the preferred way for long-running invocations
116+
on Android since it doesn't depend on an active connection from the host PC.
117+
110118
Following command will build dEQP.apk:
111119

112120
python3 scripts/android/build_apk.py --sdk <path to Android SDK> --ndk <path to Android NDK>
@@ -126,6 +134,28 @@ To pick which ABI to use at _install time_, use the following command instead:
126134

127135
adb install -g --abi <ABI name> <build-root>/package/dEQP.apk
128136

137+
#### Executable
138+
139+
This is identical to the builds on other platforms and is better for iterative
140+
runs of headless tests as CTS can be invoked and the output can be checked from
141+
a single interactive terminal.
142+
143+
This build doesn't support WSI tests and shouldn't be used for conformance
144+
submissions, it also isn't recommended for longer running tests since Android
145+
will terminate this process as soon as the `adb shell` session ends which may
146+
happen due to an unintentional device disconnection.
147+
148+
cmake <path to vulkancts> -GNinja -DCMAKE_BUILD_TYPE=Debug \
149+
-DCMAKE_TOOLCHAIN_FILE=<NDK path>/build/cmake/android.toolchain.cmake \
150+
-DCMAKE_ANDROID_NDK=<NDK path> -DANDROID_ABI=<ABI to build eg: arm64-v8a> \
151+
-DDE_ANDROID_API=<API level> -DDEQP_TARGET_TOOLCHAIN=ndk-modern \
152+
-DDEQP_TARGET=android -DDEQP_ANDROID_EXE=ON
153+
ninja all
154+
155+
The build needs to be transferred to the device via `adb push` to a directory
156+
under `/data/` on the device, such as `/data/local/tmp/` which should be writeable
157+
for non-rooted devices. It should be noted that anywhere on `/sdcard/` won't work
158+
since it's mounted as `noexec`.
129159

130160
Building Mustpass
131161
-----------------
@@ -311,6 +341,8 @@ Test log will be written into TestResults.qpa
311341

312342
### Android
313343

344+
#### App
345+
314346
For Android build using SDK 29 or greater, it is recommended to use `/sdcard/Documents/` instead of `/sdcard/` due to scoped storage.
315347

316348
adb push <vulkancts>/external/vulkancts/mustpass/main/vk-default.txt /sdcard/vk-default.txt
@@ -326,6 +358,13 @@ Test progress will be written to device log and can be displayed with:
326358

327359
Test log will be written into `/sdcard/TestResults.qpa`.
328360

361+
#### Executable
362+
363+
Identical to [Linux](#linux-1), but within `adb shell` instead:
364+
365+
adb shell
366+
> cd <pushed build directory>/external/vulkancts/modules/vulkan
367+
> ./deqp-vk --deqp-caselist-file=...
329368

330369
Conformance Submission Package Requirements
331370
-------------------------------------------

framework/delibs/debase/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,7 @@ endif ()
3838
if (DE_OS_IS_SYMBIAN)
3939
target_link_libraries(debase gcc)
4040
endif()
41+
42+
if (DE_OS_IS_ANDROID)
43+
target_link_libraries(debase log)
44+
endif()

framework/platform/android/tcuAndroidPlatform.cpp

+46-17
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include "tcuFunctionLibrary.hpp"
3434
#include "vkWsiPlatform.hpp"
3535

36+
#include <sys/utsname.h>
37+
3638
// Assume no call translation is needed
3739
#include <android/native_window.h>
3840
struct egl_native_pixmap_t;
@@ -313,38 +315,45 @@ class VulkanDisplay : public vk::wsi::Display
313315
WindowRegistry &m_windowRegistry;
314316
};
315317

316-
static size_t getTotalSystemMemory(ANativeActivity *activity)
318+
static size_t getTotalSystemMemory(NativeActivity *activity)
317319
{
318320
const size_t MiB = (size_t)(1 << 20);
321+
// Use relatively high fallback size to encourage CDD-compliant behavior
322+
const size_t fallbackSize = (sizeof(void *) == sizeof(uint64_t)) ? 2048 * MiB : 1024 * MiB;
319323

320-
try
324+
if (activity)
321325
{
322-
const size_t totalMemory = getTotalAndroidSystemMemory(activity);
323-
print("Device has %.2f MiB of system memory\n", static_cast<double>(totalMemory) / static_cast<double>(MiB));
324-
return totalMemory;
326+
try
327+
{
328+
const size_t totalMemory = getTotalAndroidSystemMemory(activity->getNativeActivity());
329+
print("Device has %.2f MiB of system memory\n",
330+
static_cast<double>(totalMemory) / static_cast<double>(MiB));
331+
return totalMemory;
332+
}
333+
catch (const std::exception &e)
334+
{
335+
print("WARNING: Failed to determine system memory size required by CDD: %s\n", e.what());
336+
print("WARNING: Using fall-back size of %.2f MiB\n", double(fallbackSize) / double(MiB));
337+
}
325338
}
326-
catch (const std::exception &e)
327-
{
328-
// Use relatively high fallback size to encourage CDD-compliant behavior
329-
const size_t fallbackSize = (sizeof(void *) == sizeof(uint64_t)) ? 2048 * MiB : 1024 * MiB;
330339

331-
print("WARNING: Failed to determine system memory size required by CDD: %s\n", e.what());
332-
print("WARNING: Using fall-back size of %.2f MiB\n", double(fallbackSize) / double(MiB));
333-
334-
return fallbackSize;
335-
}
340+
return fallbackSize;
336341
}
337342

338343
// Platform
339344

340345
Platform::Platform(NativeActivity &activity)
341-
: m_activity(activity)
342-
, m_totalSystemMemory(getTotalSystemMemory(activity.getNativeActivity()))
346+
: m_activity(&activity)
347+
, m_totalSystemMemory(getTotalSystemMemory(&activity))
343348
{
344349
m_nativeDisplayFactoryRegistry.registerFactory(new NativeDisplayFactory(m_windowRegistry));
345350
m_contextFactoryRegistry.registerFactory(new eglu::GLContextFactory(m_nativeDisplayFactoryRegistry));
346351
}
347352

353+
Platform::Platform() : m_activity(nullptr), m_totalSystemMemory(getTotalSystemMemory(nullptr))
354+
{
355+
}
356+
348357
Platform::~Platform(void)
349358
{
350359
}
@@ -362,7 +371,22 @@ vk::Library *Platform::createLibrary(const char *libraryPath) const
362371

363372
void Platform::describePlatform(std::ostream &dst) const
364373
{
365-
tcu::Android::describePlatform(m_activity.getNativeActivity(), dst);
374+
if (m_activity)
375+
{
376+
tcu::Android::describePlatform(m_activity->getNativeActivity(), dst);
377+
}
378+
else
379+
{
380+
utsname sysInfo{};
381+
if (uname(&sysInfo) != 0)
382+
{
383+
dst << "OS: Android (Unknown)\n";
384+
return;
385+
}
386+
387+
dst << "OS: Android " << sysInfo.release << " " << sysInfo.version << "\n";
388+
dst << "CPU: " << sysInfo.machine << "\n";
389+
}
366390
}
367391

368392
void Platform::getMemoryLimits(tcu::PlatformMemoryLimits &limits) const
@@ -416,3 +440,8 @@ bool Platform::hasDisplay(vk::wsi::Type wsiType) const
416440

417441
} // namespace Android
418442
} // namespace tcu
443+
444+
tcu::Platform *createPlatform(void)
445+
{
446+
return new tcu::Android::Platform();
447+
}

framework/platform/android/tcuAndroidPlatform.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class Platform : public tcu::Platform, private eglu::Platform, private glu::Plat
4040
{
4141
public:
4242
Platform(NativeActivity &activity);
43+
Platform(void);
4344
virtual ~Platform(void);
4445

4546
virtual bool processEvents(void);
@@ -70,7 +71,7 @@ class Platform : public tcu::Platform, private eglu::Platform, private glu::Plat
7071
bool hasDisplay(vk::wsi::Type wsiType) const;
7172

7273
private:
73-
NativeActivity &m_activity;
74+
NativeActivity *m_activity;
7475
WindowRegistry m_windowRegistry;
7576
const size_t m_totalSystemMemory;
7677
};

framework/qphelper/qpDebugOut.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ void qpDiev(const char *format, va_list args)
9898
}
9999

100100
/* print() implementation. */
101-
#if (DE_OS == DE_OS_ANDROID)
101+
#if defined(DEQP_IS_ANDROID_APP)
102102

103103
#include <android/log.h>
104104

0 commit comments

Comments
 (0)