1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 #define LOG_TAG "GpuProfilingData"
19 
20 #include <vector>
21 
22 #include <android/log.h>
23 #include <dlfcn.h>
24 #include <jni.h>
25 #include <string>
26 #include <vulkan/vulkan.h>
27 
28 #define ALOGI(msg, ...)                                                        \
29   __android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__)
30 #define ALOGE(msg, ...)                                                        \
31   __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, (msg), __VA_ARGS__)
32 #define ALOGD(msg, ...)                                                        \
33   __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, (msg), __VA_ARGS__)
34 #define REQUIRE_SUCCESS(fn, name)                                              \
35   do {                                                                         \
36     if (VK_SUCCESS != fn) {                                                    \
37       ALOGE("Vulkan Error in %s", name);                                       \
38       return -1;                                                               \
39     }                                                                          \
40   } while (0)
41 
42 namespace {
43 
44 typedef void (*FN_PTR)(void);
45 
initVulkan()46 int initVulkan() {
47   const VkApplicationInfo appInfo = {
48       VK_STRUCTURE_TYPE_APPLICATION_INFO,
49       nullptr,            // pNext
50       "GpuProfilingData", // app name
51       0,                  // app version
52       nullptr,            // engine name
53       0,                  // engine version
54       VK_API_VERSION_1_0,
55   };
56   const VkInstanceCreateInfo instanceInfo = {
57       VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
58       nullptr, // pNext
59       0,       // flags
60       &appInfo,
61       0,       // layer count
62       nullptr, // layers
63       0,       // extension count
64       nullptr, // extensions
65   };
66   VkInstance instance;
67   REQUIRE_SUCCESS(vkCreateInstance(&instanceInfo, nullptr, &instance),
68                   "vkCreateInstance");
69 
70   VkPhysicalDevice physicalDevice = {};
71   uint32_t nPhysicalDevices;
72   REQUIRE_SUCCESS(
73       vkEnumeratePhysicalDevices(instance, &nPhysicalDevices, nullptr),
74       "vkEnumeratePhysicalDevices");
75   std::vector<VkPhysicalDevice> physicalDevices(nPhysicalDevices);
76 
77   REQUIRE_SUCCESS(vkEnumeratePhysicalDevices(instance, &nPhysicalDevices,
78                                              physicalDevices.data()),
79                   "vkEnumeratePhysicalDevices");
80 
81   uint32_t queueFamilyIndex = static_cast<uint32_t>(-1);
82   uint32_t i;
83   for (i = 0; i < nPhysicalDevices; ++i) {
84     uint32_t nQueueProperties = 0;
85     vkGetPhysicalDeviceQueueFamilyProperties(physicalDevices[i],
86                                              &nQueueProperties, nullptr);
87     std::vector<VkQueueFamilyProperties> queueProperties(nQueueProperties);
88     vkGetPhysicalDeviceQueueFamilyProperties(
89         physicalDevices[i], &nQueueProperties, queueProperties.data());
90     for (uint32_t j = 0; j < nQueueProperties; ++j) {
91       if (queueProperties[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
92         queueFamilyIndex = j;
93         break;
94       }
95     }
96     if (queueFamilyIndex != static_cast<uint32_t>(-1)) {
97       break;
98     }
99   }
100   if (i == nPhysicalDevices) {
101     ALOGE("%s",
102           "Could not find a physical device that supports a graphics queue");
103     return -1;
104   }
105   physicalDevice = physicalDevices[i];
106 
107   float priority = 1.0f;
108   VkDeviceQueueCreateInfo queueCreateInfo{
109       VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
110       nullptr, // pNext
111       0,       // flags
112       queueFamilyIndex,
113       1,
114       &priority,
115   };
116 
117   VkDeviceCreateInfo deviceCreateInfo{
118       VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
119       nullptr, // pNext
120       0,       // flags
121       1,
122       &queueCreateInfo,
123       0,
124       nullptr,
125       0,
126       nullptr,
127       nullptr,
128   };
129 
130   VkDevice device;
131 
132   REQUIRE_SUCCESS(
133       vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device),
134       "vkCreateDevice");
135   return 0;
136 }
137 
android_graphics_cts_GpuProfilingData_nativeInitVulkan(JNIEnv *,jclass)138 jint android_graphics_cts_GpuProfilingData_nativeInitVulkan(JNIEnv * /*env*/,
139                                                             jclass /*clazz*/) {
140   return (jint)initVulkan();
141 }
142 
143 static JNINativeMethod gMethods[] = {
144     {"nativeInitVulkan", "()I",
145      (void *)android_graphics_cts_GpuProfilingData_nativeInitVulkan}};
146 } // anonymous namespace
147 
register_android_gputools_cts_GpuProfilingData(JNIEnv * env)148 int register_android_gputools_cts_GpuProfilingData(JNIEnv *env) {
149   jclass clazz = env->FindClass(
150       "android/graphics/gpuprofiling/app/GpuRenderStagesDeviceActivity");
151   return env->RegisterNatives(clazz, gMethods,
152                               sizeof(gMethods) / sizeof(JNINativeMethod));
153 }