diff --git a/android/build-all.py b/android/build-all.py
index 9a2df48f..629fa7e4 100644
--- a/android/build-all.py
+++ b/android/build-all.py
@@ -7,6 +7,7 @@ EXAMPLES = [
"bloom",
"computecullandlod",
"computecloth",
+ "computeheadless",
"computenbody",
"computeparticles",
"computeshader",
diff --git a/android/computeheadless/.gitignore b/android/computeheadless/.gitignore
new file mode 100644
index 00000000..7a5d249c
--- /dev/null
+++ b/android/computeheadless/.gitignore
@@ -0,0 +1,10 @@
+/assets/
+/res/
+/bin/
+/libs/
+/obj/
+/build.xml
+/local.properties
+/project.properties
+/proguard-project.txt
+*.apk
\ No newline at end of file
diff --git a/android/computeheadless/AndroidManifest.xml b/android/computeheadless/AndroidManifest.xml
new file mode 100644
index 00000000..eedf7502
--- /dev/null
+++ b/android/computeheadless/AndroidManifest.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/computeheadless/example.json b/android/computeheadless/example.json
new file mode 100644
index 00000000..d1ac654e
--- /dev/null
+++ b/android/computeheadless/example.json
@@ -0,0 +1,8 @@
+{
+ "apkname": "vulkanComputeheadless",
+ "directories": {
+ "shaders": "computeheadless"
+ },
+ "assets": {
+ }
+}
\ No newline at end of file
diff --git a/android/computeheadless/jni/Android.mk b/android/computeheadless/jni/Android.mk
new file mode 100644
index 00000000..0fb2ae4b
--- /dev/null
+++ b/android/computeheadless/jni/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH := $(call my-dir)/../../computeheadless
+
+# vulkan example
+
+DATADIR := $(LOCAL_PATH)/../../data
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := vulkanComputeheadless
+
+PROJECT_FILES := $(wildcard $(LOCAL_PATH)/../../computeheadless/*.cpp)
+PROJECT_FILES += $(wildcard $(LOCAL_PATH)/../../base/VulkanTools.cpp)
+PROJECT_FILES += $(wildcard $(LOCAL_PATH)/../../base/VulkanAndroid.cpp)
+
+LOCAL_CPPFLAGS := -std=c++11
+LOCAL_CPPFLAGS += -D__STDC_LIMIT_MACROS
+LOCAL_CPPFLAGS += -DVK_NO_PROTOTYPES
+LOCAL_CPPFLAGS += -DVK_USE_PLATFORM_ANDROID_KHR
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../external/
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../base/
+
+LOCAL_SRC_FILES := $(PROJECT_FILES)
+
+LOCAL_LDLIBS := -landroid -llog -lz
+
+LOCAL_DISABLE_FORMAT_STRING_CHECKS := true
+LOCAL_DISABLE_FATAL_LINKER_WARNINGS := true
+
+LOCAL_STATIC_LIBRARIES += android_native_app_glue
+LOCAL_STATIC_LIBRARIES += cpufeatures
+
+include $(BUILD_SHARED_LIBRARY)
+
+$(call import-module, android/native_app_glue)
+$(call import-module, android/cpufeatures)
diff --git a/android/computeheadless/jni/Application.mk b/android/computeheadless/jni/Application.mk
new file mode 100644
index 00000000..62020feb
--- /dev/null
+++ b/android/computeheadless/jni/Application.mk
@@ -0,0 +1,5 @@
+APP_PLATFORM := android-19
+APP_ABI := armeabi-v7a
+APP_STL := c++_static
+APP_CPPFLAGS := -std=c++11
+NDK_TOOLCHAIN_VERSION := clang
diff --git a/computeheadless/computeheadless.cpp b/computeheadless/computeheadless.cpp
index e6ac68dc..b3d212fb 100644
--- a/computeheadless/computeheadless.cpp
+++ b/computeheadless/computeheadless.cpp
@@ -10,6 +10,12 @@
#if defined(_WIN32)
#pragma comment(linker, "/subsystem:console")
+#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
+#include
+#include
+#include
+#include
+#include "VulkanAndroid.h"
#endif
#include
@@ -23,10 +29,20 @@
#include
#include "VulkanTools.h"
+#if defined(VK_USE_PLATFORM_ANDROID_KHR)
+android_app* androidapp;
+#endif
+
#define DEBUG (!NDEBUG)
#define BUFFER_ELEMENTS 32
+#if defined(VK_USE_PLATFORM_ANDROID_KHR)
+#define LOG(...) ((void)__android_log_print(ANDROID_LOG_INFO, "vulkanExample", __VA_ARGS__))
+#else
+#define LOG(...) printf(__VA_ARGS__)
+#endif
+
static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(
VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType,
@@ -37,7 +53,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(
const char* pMessage,
void* pUserData)
{
- std::cout << "[VALIDATION]:" << pLayerPrefix << ":" << pMessage << std::endl;
+ LOG("[VALIDATION]: %s - %s\n", pLayerPrefix, pMessage);
return VK_FALSE;
}
@@ -103,7 +119,12 @@ public:
VulkanExample()
{
- std::cout << "Running headless example" << std::endl;
+ LOG("Running headless compute example\n");
+
+#if defined(VK_USE_PLATFORM_ANDROID_KHR)
+ LOG("loading vulkan lib");
+ vks::android::loadVulkanLibrary();
+#endif
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
@@ -117,22 +138,32 @@ public:
VkInstanceCreateInfo instanceCreateInfo = {};
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pApplicationInfo = &appInfo;
-#if defined(DEBUG)
- // TODO: Explicit layer names on Android
+
+ uint32_t layerCount = 0;
+#if defined(VK_USE_PLATFORM_ANDROID_KHR)
+ const char* validationlayers[] = { "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker","VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_swapchain", "VK_LAYER_GOOGLE_unique_objects" };
+ layerCount = 6;
+#else
const char* validationlayers[] = { "VK_LAYER_LUNARG_standard_validation" };
- const char* validationExt = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
- instanceCreateInfo.enabledLayerCount = 1;
+ layerCount = 1;
+#endif
+#if DEBUG
instanceCreateInfo.ppEnabledLayerNames = validationlayers;
+ const char* validationExt = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
+ instanceCreateInfo.enabledLayerCount = layerCount;
instanceCreateInfo.enabledExtensionCount = 1;
instanceCreateInfo.ppEnabledExtensionNames = &validationExt;
#endif
VK_CHECK_RESULT(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
-#if defined(DEBUG)
+#if defined(VK_USE_PLATFORM_ANDROID_KHR)
+ vks::android::loadVulkanFunctions(instance);
+#endif
+#if DEBUG
VkDebugReportCallbackCreateInfoEXT debugReportCreateInfo = {};
debugReportCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
debugReportCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
- debugReportCreateInfo.pfnCallback = &debugMessageCallback;
+ debugReportCreateInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT)debugMessageCallback;
// We have to explicitly load this function.
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"));
@@ -150,6 +181,10 @@ public:
VK_CHECK_RESULT(vkEnumeratePhysicalDevices(instance, &deviceCount, physicalDevices.data()));
physicalDevice = physicalDevices[0];
+ VkPhysicalDeviceProperties deviceProperties;
+ vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
+ LOG("GPU: %s\n", deviceProperties.deviceName);
+
// Request a single compute queue
const float defaultQueuePriority(0.0f);
VkDeviceQueueCreateInfo queueCreateInfo = {};
@@ -297,7 +332,7 @@ public:
shaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
- shaderStage.module = vks::tools::loadShader(androidApp->activity->assetManager, fileName.c_str(), device);
+ shaderStage.module = vks::tools::loadShader(androidapp->activity->assetManager, ASSET_PATH "shaders/computeheadless/headless.comp.spv", device);
#else
shaderStage.module = vks::tools::loadShader(ASSET_PATH "shaders/computeheadless/headless.comp.spv", device);
#endif
@@ -415,15 +450,15 @@ public:
vkQueueWaitIdle(queue);
// Output buffer contents
- std::cout << "Compute input: " << std::endl;
+ LOG("Compute input:\n");
for (auto v : computeInput) {
- std::cout << v << "\t";
+ LOG("%d \t", v);
}
std::cout << std::endl;
- std::cout << "Compute output: " << std::endl;
+ LOG("Compute output:\n");
for (auto v : computeOutput) {
- std::cout << v << "\t";
+ LOG("%d \t", v);
}
std::cout << std::endl;
@@ -433,7 +468,7 @@ public:
vkDestroyBuffer(device, hostBuffer, nullptr);
vkFreeMemory(device, hostMemory, nullptr);
-#if defined(DEBUG)
+#if DEBUG
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallback = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT"));
assert(vkDestroyDebugReportCallback);
vkDestroyDebugReportCallback(instance, debugReportCallback, nullptr);
@@ -451,15 +486,28 @@ public:
}
};
-#if defined(__ANDROID__)
-// Android entry point
-// A note on app_dummy(): This is required as the compiler may otherwise remove the main entry point of the application
-VulkanExample *vulkanExample;
+#if defined(VK_USE_PLATFORM_ANDROID_KHR)
+void handleAppCommand(android_app * app, int32_t cmd) {
+ if (cmd == APP_CMD_INIT_WINDOW) {
+ VulkanExample *vulkanExample = new VulkanExample();
+ delete(vulkanExample);
+ ANativeActivity_finish(app->activity);
+ }
+}
void android_main(android_app* state) {
app_dummy();
- VulkanExample *vulkanExample = new VulkanExample();
- state->userData = vulkanExample;
- delete(vulkanExample);
+ androidapp = state;
+ androidapp->onAppCmd = handleAppCommand;
+ int ident, events;
+ struct android_poll_source* source;
+ while ((ident = ALooper_pollAll(-1, NULL, &events, (void**)&source)) >= 0) {
+ if (source != NULL) {
+ source->process(androidapp, source);
+ }
+ if (androidapp->destroyRequested != 0) {
+ break;
+ }
+ }
}
#else
int main() {