1 /*
2  * Copyright 2024 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 "vkprofiles"
19 
20 #ifndef VK_USE_PLATFORM_ANDROID_KHR
21 #define VK_USE_PLATFORM_ANDROID_KHR
22 #endif
23 
24 #include <string>
25 #include <vector>
26 
27 #include <android/log.h>
28 
29 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
30 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
31 
32 #include "generated/vulkan_profiles.h"
33 #include "vkprofiles.h"
34 
35 namespace android::vkprofiles {
36 
37 /* Wrap vkProfileGetSupport in an anonymous namespace.
38  * vkProfileGetSupport only works for profiles that we explicitly add, we don't
39  * want a user of this library to mistakenly call with a profile that we haven't
40  * added.
41  */
42 namespace {
43 
vkProfileGetSupport(const VpProfileProperties * pProfile,const uint32_t minApiVersion)44 std::string vkProfileGetSupport(const VpProfileProperties* pProfile,
45                                 const uint32_t minApiVersion) {
46     VkResult result = VK_SUCCESS;
47     VkBool32 supported = VK_FALSE;
48 
49     result = vpGetInstanceProfileSupport(nullptr, pProfile, &supported);
50     if (result != VK_SUCCESS) {
51         std::string error(
52             "There was a failure from vpGetInstanceProfileSupport,"
53             " check `vkprofiles` in logcat."
54             " result = " +
55             std::to_string(result));
56         return error;
57     }
58     if (supported != VK_TRUE) {
59         std::string error(
60             "There was a failure from vpGetInstanceProfileSupport,"
61             " check `vkprofiles` in logcat."
62             " supported = " +
63             std::to_string(supported));
64         return error;
65     }
66 
67     const VkApplicationInfo appInfo = {
68         VK_STRUCTURE_TYPE_APPLICATION_INFO,
69         nullptr,
70         "vkprofiles",
71         0,
72         "",
73         0,
74         minApiVersion,
75     };
76     VkInstanceCreateInfo instanceCreateInfo = {
77         VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
78         nullptr,
79         0,
80         &appInfo,
81         0,
82         nullptr,
83         0,
84         nullptr,
85     };
86 
87     VpInstanceCreateInfo vpInstanceCreateInfo{};
88     vpInstanceCreateInfo.pCreateInfo = &instanceCreateInfo;
89     vpInstanceCreateInfo.enabledFullProfileCount = 1;
90     vpInstanceCreateInfo.pEnabledFullProfiles = pProfile;
91 
92     VkInstance instance = VK_NULL_HANDLE;
93     result = vpCreateInstance(&vpInstanceCreateInfo, nullptr, &instance);
94     if (result != VK_SUCCESS) {
95         std::string error(
96             "There was a failure from vpCreateInstance,"
97             " check `vkprofiles` in logcat."
98             " result = " +
99             std::to_string(result));
100         return error;
101     }
102 
103     uint32_t count;
104     result = vkEnumeratePhysicalDevices(instance, &count, nullptr);
105     if (result != VK_SUCCESS) {
106         vkDestroyInstance(instance, nullptr);
107         std::string error(
108             "There was a failure from vkEnumeratePhysicalDevices,"
109             " check `vkprofiles` in logcat."
110             " result = " +
111             std::to_string(result));
112         return error;
113     }
114 
115     std::vector<VkPhysicalDevice> devices(count, VK_NULL_HANDLE);
116     result = vkEnumeratePhysicalDevices(instance, &count, devices.data());
117     if (result != VK_SUCCESS) {
118         vkDestroyInstance(instance, nullptr);
119         std::string error(
120             "There was a failure from vkEnumeratePhysicalDevices (2),"
121             " check `vkprofiles` in logcat."
122             " result = " +
123             std::to_string(result));
124         return error;
125     }
126 
127     bool onePhysicalDeviceSupports = false;
128     for (size_t i = 0; i < count; i++) {
129         result = vpGetPhysicalDeviceProfileSupport(instance, devices[i],
130                                                    pProfile, &supported);
131         if (result != VK_SUCCESS) {
132             ALOGD("vpGetPhysicalDeviceProfileSupport fail, result = %d",
133                   result);
134             continue;
135         } else if (supported != VK_TRUE) {
136             ALOGD("vpGetPhysicalDeviceProfileSupport fail, supported = %d",
137                   supported);
138             continue;
139         }
140 
141         onePhysicalDeviceSupports = true;
142     }
143 
144     if (!onePhysicalDeviceSupports) {
145         std::string error(
146             "There was a failure from vpGetPhysicalDeviceProfileSupport,"
147             " check `vkprofiles` in logcat."
148             " No VkPhysicalDevice supports the profile");
149         return error;
150     }
151 
152     return std::string("SUPPORTED");
153 }
154 
155 }  // anonymous namespace
156 
vkAbp2021GetSupport()157 std::string vkAbp2021GetSupport() {
158     VpProfileProperties profile{VP_ANDROID_BASELINE_2021_NAME,
159                                 VP_ANDROID_BASELINE_2021_SPEC_VERSION};
160     return vkProfileGetSupport(&profile,
161                                VP_ANDROID_BASELINE_2021_MIN_API_VERSION);
162 }
163 
vkAbp2021CpuOnlyGetSupport()164 std::string vkAbp2021CpuOnlyGetSupport() {
165     VpProfileProperties profile{VP_ANDROID_BASELINE_2021_CPU_ONLY_NAME,
166                                 VP_ANDROID_BASELINE_2021_CPU_ONLY_SPEC_VERSION};
167     return vkProfileGetSupport(&profile,
168                                VP_ANDROID_BASELINE_2021_MIN_API_VERSION);
169 }
170 
vkAbp2022GetSupport()171 std::string vkAbp2022GetSupport() {
172     VpProfileProperties profile{VP_ANDROID_BASELINE_2022_NAME,
173                                 VP_ANDROID_BASELINE_2022_SPEC_VERSION};
174     return vkProfileGetSupport(&profile,
175                                VP_ANDROID_BASELINE_2022_MIN_API_VERSION);
176 }
177 
vkVpa15GetSupport()178 std::string vkVpa15GetSupport() {
179     VpProfileProperties profile{VP_ANDROID_15_MINIMUMS_NAME,
180                                 VP_ANDROID_15_MINIMUMS_SPEC_VERSION};
181     return vkProfileGetSupport(&profile,
182                                VP_ANDROID_15_MINIMUMS_MIN_API_VERSION);
183 }
184 
vkProfiles()185 std::string vkProfiles() {
186     return "{"
187            "\"" + std::string(VP_ANDROID_BASELINE_2021_NAME) + "\": "
188            "\"" + vkAbp2021GetSupport() + "\","
189            "\"" + std::string(VP_ANDROID_BASELINE_2021_CPU_ONLY_NAME) + "\": "
190            "\"" + vkAbp2021CpuOnlyGetSupport() + "\","
191            "\"" + std::string(VP_ANDROID_BASELINE_2022_NAME) + "\": "
192            "\"" + vkAbp2022GetSupport() + "\","
193            "\"" + std::string(VP_ANDROID_15_MINIMUMS_NAME) + "\": "
194            "\"" + vkVpa15GetSupport() + "\""
195            "}";
196 }
197 
198 }  // namespace android::vkprofiles
199