Merge "Revert "EGL: Ensure surfaces are disconnected when destroyed"" into nyc-dev
diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp
index 6892b57..917c813 100644
--- a/cmds/bugreport/bugreport.cpp
+++ b/cmds/bugreport/bugreport.cpp
@@ -28,6 +28,11 @@
// output. All of the dumpstate output is written to stdout, including
// any errors encountered while reading/writing the output.
int main() {
+
+ fprintf(stderr, "=============================================================================\n");
+ fprintf(stderr, "WARNING: flat bugreports are deprecated, use adb bugreport <zip_file> instead\n");
+ fprintf(stderr, "=============================================================================\n\n\n");
+
// Start the dumpstate service.
property_set("ctl.start", "dumpstate");
diff --git a/cmds/bugreportz/Android.mk b/cmds/bugreportz/Android.mk
new file mode 100644
index 0000000..14ba225
--- /dev/null
+++ b/cmds/bugreportz/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= bugreportz.cpp
+
+LOCAL_MODULE:= bugreportz
+
+LOCAL_CFLAGS := -Wall
+
+LOCAL_SHARED_LIBRARIES := libcutils
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/bugreportz/bugreportz.cpp b/cmds/bugreportz/bugreportz.cpp
new file mode 100644
index 0000000..19d2d64
--- /dev/null
+++ b/cmds/bugreportz/bugreportz.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+
+static constexpr char VERSION[] = "1.0";
+
+static void show_usage() {
+ fprintf(stderr,
+ "usage: bugreportz [-h | -v]\n"
+ " -h: to display this help message\n"
+ " -v: to display the version\n"
+ " or no arguments to generate a zipped bugreport\n");
+}
+
+static void show_version() {
+ fprintf(stderr, "%s\n", VERSION);
+}
+
+int main(int argc, char *argv[]) {
+
+ if (argc > 1) {
+ /* parse arguments */
+ int c;
+ while ((c = getopt(argc, argv, "vh")) != -1) {
+ switch (c) {
+ case 'h':
+ show_usage();
+ return EXIT_SUCCESS;
+ case 'v':
+ show_version();
+ return EXIT_SUCCESS;
+ default:
+ show_usage();
+ return EXIT_FAILURE;
+ }
+ }
+ // passed an argument not starting with -
+ if (optind > 1 || argv[optind] != nullptr) {
+ show_usage();
+ return EXIT_FAILURE;
+ }
+ }
+
+ // TODO: code below was copy-and-pasted from bugreport.cpp (except by the timeout value);
+ // should be reused instead.
+
+ // Start the dumpstatez service.
+ property_set("ctl.start", "dumpstatez");
+
+ // Socket will not be available until service starts.
+ int s;
+ for (int i = 0; i < 20; i++) {
+ s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+ if (s >= 0)
+ break;
+ // Try again in 1 second.
+ sleep(1);
+ }
+
+ if (s == -1) {
+ printf("Failed to connect to dumpstatez service: %s\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ // Set a timeout so that if nothing is read in 10 minutes, we'll stop
+ // reading and quit. No timeout in dumpstate is longer than 60 seconds,
+ // so this gives lots of leeway in case of unforeseen time outs.
+ struct timeval tv;
+ tv.tv_sec = 10 * 60;
+ tv.tv_usec = 0;
+ if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
+ printf("WARNING: Cannot set socket timeout: %s\n", strerror(errno));
+ }
+
+ while (1) {
+ char buffer[65536];
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(
+ read(s, buffer, sizeof(buffer)));
+ if (bytes_read == 0) {
+ break;
+ } else if (bytes_read == -1) {
+ // EAGAIN really means time out, so change the errno.
+ if (errno == EAGAIN) {
+ errno = ETIMEDOUT;
+ }
+ printf("\nBugreport read terminated abnormally (%s).\n",
+ strerror(errno));
+ break;
+ }
+
+ ssize_t bytes_to_send = bytes_read;
+ ssize_t bytes_written;
+ do {
+ bytes_written = TEMP_FAILURE_RETRY(
+ write(STDOUT_FILENO, buffer + bytes_read - bytes_to_send,
+ bytes_to_send));
+ if (bytes_written == -1) {
+ printf(
+ "Failed to write data to stdout: read %zd, trying to send %zd (%s)\n",
+ bytes_read, bytes_to_send, strerror(errno));
+ return EXIT_FAILURE;
+ }
+ bytes_to_send -= bytes_written;
+ } while (bytes_written != 0 && bytes_to_send > 0);
+ }
+
+ close(s);
+ return EXIT_SUCCESS;
+}
diff --git a/cmds/bugreportz/readme.md b/cmds/bugreportz/readme.md
new file mode 100644
index 0000000..85aafce
--- /dev/null
+++ b/cmds/bugreportz/readme.md
@@ -0,0 +1,12 @@
+# bugreportz protocol
+
+`bugreportz` is used to generate a zippped bugreport whose path is passed back to `adb`, using
+the simple protocol defined below.
+
+
+## Version 1.0
+On version 1.0, `bugreportz` does not generate any output on `stdout` until the bugreport is
+finished, when it then prints one line with the result:
+
+- `OK:<path_to_bugreport_file>` in case of success.
+- `FAIL:<error message>` in case of failure.
diff --git a/cmds/dumpstate/bugreport-format.md b/cmds/dumpstate/bugreport-format.md
index 484f97f..d7837ae 100644
--- a/cmds/dumpstate/bugreport-format.md
+++ b/cmds/dumpstate/bugreport-format.md
@@ -26,16 +26,16 @@
is a failure, in which case it reverts to the flat file that is zipped by
**Shell** and hence the end result is the _v0_ format).
-The zip file is by default called _bugreport-DATE.zip_ and it contains a
-_bugreport-DATE.txt_ entry, although the end user can change the name (through
-**Shell**), in which case they would be called _bugreport-NEW_NAME.zip_ and
-_bugreport-NEW_NAME.txt_ respectively.
+The zip file is by default called _bugreport-BUILD_ID-DATE.zip_ and it contains a
+_bugreport-BUILD_ID-DATE.txt_ entry, although the end user can change the name (through
+**Shell**), in which case they would be called _bugreport-BUILD_ID-NEW_NAME.zip_ and
+_bugreport-BUILD_ID-NEW_NAME.txt_ respectively.
The zip file also contains 2 metadata entries generated by `dumpstate`:
- `version.txt`: whose value is **v1**.
- `main-entry.txt`: whose value is the name of the flat text entry (i.e.,
- _bugreport-DATE.txt_ or _bugreport-NEW_NAME.txt_).
+ _bugreport-BUILD_ID-DATE.txt_ or _bugreport-NEW_NAME.txt_).
`dumpstate` can also copy files from the device’s filesystem into the zip file
under the `FS` folder. For example, a `/dirA/dirB/fileC` file in the device
@@ -62,9 +62,9 @@
For example, the initial version during _Android N_ development was
**v1-dev1**. When `dumpsys` was split in 2 sections but not all tools were
-ready to parse that format, the version was named **v1-dev1-dumpsys-split**,
+ready to parse that format, the version was named **v1-dev2**,
which had to be passed do `dumpsys` explicitly (i.e., trhough a
-`-V v1-dev1-dumpsys-split` argument). Once that format became stable and tools
+`-V v1-dev2` argument). Once that format became stable and tools
knew how to parse it, the default version became **v1-dev2**.
Similarly, if changes in the file format are made after the initial release of
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 30ddec3..ea14c66 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -63,12 +63,14 @@
void add_mountinfo();
static bool add_zip_entry(const std::string& entry_name, const std::string& entry_path);
static bool add_zip_entry_from_fd(const std::string& entry_name, int fd);
+static int control_socket_fd;
#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
#define RAFT_DIR "/data/misc/raft/"
#define RECOVERY_DIR "/cache/recovery"
#define RECOVERY_DATA_DIR "/data/misc/recovery"
+#define LOGPERSIST_DATA_DIR "/data/misc/logd"
#define TOMBSTONE_DIR "/data/tombstones"
#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
/* Can accomodate a tombstone number up to 9999. */
@@ -91,7 +93,7 @@
* See bugreport-format.txt for more info.
*/
// TODO: change to "v1" before final N build
-static std::string VERSION_DEFAULT = "v1-dev3";
+static std::string VERSION_DEFAULT = "v1-dev4";
/* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
* otherwise gets just those modified in the last half an hour. */
@@ -169,11 +171,15 @@
closedir(d);
}
-static void dump_systrace() {
+static void dump_systrace(const std::string& systrace_path) {
if (!zip_writer) {
MYLOGD("Not dumping systrace because zip_writer is not set\n");
return;
}
+ if (systrace_path.empty()) {
+ MYLOGE("Not dumping systrace because path is empty\n");
+ return;
+ }
const char* path = "/sys/kernel/debug/tracing/tracing_on";
long int is_tracing;
if (read_file_as_long(path, &is_tracing)) {
@@ -184,28 +190,24 @@
return;
}
- DurationReporter duration_reporter("SYSTRACE", nullptr);
- // systrace output can be many MBs, so we need to redirect its stdout straight to the zip file
- // by forking and using a pipe.
- int pipefd[2];
- pipe(pipefd);
- if (fork() == 0) {
- close(pipefd[0]); // close reading end in the child
- dup2(pipefd[1], STDOUT_FILENO); // send stdout to the pipe
- dup2(pipefd[1], STDERR_FILENO); // send stderr to the pipe
- close(pipefd[1]); // this descriptor is no longer needed
-
- // TODO: ideally it should use run_command, but it doesn't work well with pipes.
- // The drawback of calling execl directly is that we're not timing out if it hangs.
- MYLOGD("Running '/system/bin/atrace --async_dump', which can take several seconds");
- execl("/system/bin/atrace", "/system/bin/atrace", "--async_dump", nullptr);
- // execl should never return, but if it did, we need to exit.
- MYLOGD("execl on '/system/bin/atrace --async_dump' failed: %s", strerror(errno));
- // Must call _exit (instead of exit), otherwise it will corrupt the zip file.
- _exit(EXIT_FAILURE);
+ MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
+ systrace_path.c_str());
+ if (run_command("SYSTRACE", 120, "/system/bin/atrace", "--async_dump", "-o",
+ systrace_path.c_str(), NULL)) {
+ MYLOGE("systrace timed out, its zip entry will be incomplete\n");
+ // TODO: run_command tries to kill the process, but atrace doesn't die peacefully; ideally,
+ // we should call strace to stop itself, but there is no such option yet (just a
+ // --async_stop, which stops and dump
+ // if (run_command("SYSTRACE", 10, "/system/bin/atrace", "--kill", NULL)) {
+ // MYLOGE("could not stop systrace ");
+ // }
+ }
+ if (!add_zip_entry("systrace.txt", systrace_path)) {
+ MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
} else {
- close(pipefd[1]); // close the write end of the pipe in the parent
- add_zip_entry_from_fd("systrace.txt", pipefd[0]); // write output to zip file
+ if (remove(systrace_path.c_str())) {
+ MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
+ }
}
}
@@ -927,20 +929,26 @@
}
static void usage() {
- fprintf(stderr, "usage: dumpstate [-b soundfile] [-e soundfile] [-o file [-d] [-p] [-z]] [-s] [-q] [-B] [-P] [-R] [-V version]\n"
- " -b: play sound file instead of vibrate, at beginning of job\n"
- " -e: play sound file instead of vibrate, at end of job\n"
- " -o: write to file (instead of stdout)\n"
- " -d: append date to filename (requires -o)\n"
- " -p: capture screenshot to filename.png (requires -o)\n"
- " -z: generates zipped file (requires -o)\n"
- " -s: write output to control socket (for init)\n"
- " -q: disable vibrate\n"
- " -B: send broadcast when finished (requires -o)\n"
- " -P: send broadcast when started and update system properties on progress (requires -o and -B)\n"
- " -R: take bugreport in remote mode (requires -o, -z, -d and -B, shouldn't be used with -P)\n"
- " -V: sets the bugreport format version (valid values: %s)\n",
- VERSION_DEFAULT.c_str());
+ fprintf(stderr,
+ "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
+ "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
+ " -h: display this help message\n"
+ " -b: play sound file instead of vibrate, at beginning of job\n"
+ " -e: play sound file instead of vibrate, at end of job\n"
+ " -o: write to file (instead of stdout)\n"
+ " -d: append date to filename (requires -o)\n"
+ " -p: capture screenshot to filename.png (requires -o)\n"
+ " -z: generate zipped file (requires -o)\n"
+ " -s: write output to control socket (for init)\n"
+ " -S: write file location to control socket (for init; requires -o and -z)"
+ " -q: disable vibrate\n"
+ " -B: send broadcast when finished (requires -o)\n"
+ " -P: send broadcast when started and update system properties on "
+ "progress (requires -o and -B)\n"
+ " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
+ "shouldn't be used with -P)\n"
+ " -V: sets the bugreport format version (valid values: %s)\n",
+ VERSION_DEFAULT.c_str());
}
static void sigpipe_handler(int n) {
@@ -1012,6 +1020,7 @@
int do_vibrate = 1;
char* use_outfile = 0;
int use_socket = 0;
+ int use_control_socket = 0;
int do_fb = 0;
int do_broadcast = 0;
int do_early_screenshot = 0;
@@ -1020,15 +1029,6 @@
now = time(NULL);
- if (getuid() != 0) {
- // Old versions of the adb client would call the
- // dumpstate command directly. Newer clients
- // call /system/bin/bugreport instead. If we detect
- // we're being called incorrectly, then exec the
- // correct program.
- return execl("/system/bin/bugreport", "/system/bin/bugreport", NULL);
- }
-
MYLOGI("begin\n");
/* gets the sequential id */
@@ -1057,12 +1057,13 @@
format_args(argc, const_cast<const char **>(argv), &args);
MYLOGD("Dumpstate command line: %s\n", args.c_str());
int c;
- while ((c = getopt(argc, argv, "dho:svqzpPBRV:")) != -1) {
+ while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
switch (c) {
case 'd': do_add_date = 1; break;
case 'z': do_zip_file = 1; break;
case 'o': use_outfile = optarg; break;
case 's': use_socket = 1; break;
+ case 'S': use_control_socket = 1; break;
case 'v': break; // compatibility no-op
case 'q': do_vibrate = 0; break;
case 'p': do_fb = 1; break;
@@ -1082,6 +1083,11 @@
exit(1);
}
+ if (use_control_socket && !do_zip_file) {
+ usage();
+ exit(1);
+ }
+
if (do_update_progress && !do_broadcast) {
usage();
exit(1);
@@ -1093,8 +1099,8 @@
}
if (version != VERSION_DEFAULT) {
- usage();
- exit(1);
+ usage();
+ exit(1);
}
MYLOGI("bugreport format version: %s\n", version.c_str());
@@ -1107,6 +1113,11 @@
redirect_to_socket(stdout, "dumpstate");
}
+ if (use_control_socket) {
+ MYLOGD("Opening control socket\n");
+ control_socket_fd = open_socket("dumpstate");
+ }
+
/* full path of the directory where the bugreport files will be written */
std::string bugreport_dir;
@@ -1116,6 +1127,9 @@
/* full path of the file containing the dumpstate logs*/
std::string log_path;
+ /* full path of the systrace file, when enabled */
+ std::string systrace_path;
+
/* full path of the temporary file containing the screenshot (when requested) */
std::string screenshot_path;
@@ -1145,6 +1159,9 @@
} else {
suffix = "undated";
}
+ char build_id[PROPERTY_VALUE_MAX];
+ property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
+ base_name = base_name + "-" + build_id;
if (do_fb) {
// TODO: if dumpstate was an object, the paths could be internal variables and then
// we could have a function to calculate the derived values, such as:
@@ -1154,6 +1171,7 @@
tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
+ std::to_string(getpid()) + ".txt";
+ systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
MYLOGD("Bugreport dir: %s\n"
"Base name: %s\n"
@@ -1248,7 +1266,7 @@
print_header(version);
// Dumps systrace right away, otherwise it will be filled with unnecessary events.
- dump_systrace();
+ dump_systrace(systrace_path);
// Invoking the following dumpsys calls before dump_traces() to try and
// keep the system stats as close to its initial state as possible.
@@ -1262,6 +1280,7 @@
get_tombstone_fds(tombstone_data);
add_dir(RECOVERY_DIR, true);
add_dir(RECOVERY_DATA_DIR, true);
+ add_dir(LOGPERSIST_DATA_DIR, false);
add_mountinfo();
if (!drop_root_user()) {
@@ -1338,6 +1357,14 @@
path.clear();
}
}
+ if (use_control_socket) {
+ if (do_text_file) {
+ dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
+ "for more details\n", log_path.c_str());
+ } else {
+ dprintf(control_socket_fd, "OK:%s\n", path.c_str());
+ }
+ }
}
/* vibrate a few but shortly times to let user know it's finished */
@@ -1385,5 +1412,10 @@
fclose(stderr);
}
+ if (use_control_socket && control_socket_fd >= 0) {
+ MYLOGD("Closing control socket\n");
+ close(control_socket_fd);
+ }
+
return 0;
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 943f38e..c51c79a 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -109,10 +109,14 @@
int run_command_as_shell(const char *title, int timeout_seconds, const char *command, ...);
int run_command(const char *title, int timeout_seconds, const char *command, ...);
+enum RootMode { DROP_ROOT, DONT_DROP_ROOT };
+enum StdoutMode { NORMAL_STDOUT, REDIRECT_TO_STDERR };
+
/* forks a command and waits for it to finish
first element of args is the command, and last must be NULL.
command is always ran, even when _DUMPSTATE_DRY_RUN_ is defined. */
-int run_command_always(const char *title, bool drop_root, int timeout_seconds, const char *args[]);
+int run_command_always(const char *title, RootMode root_mode, StdoutMode stdout_mode,
+ int timeout_seconds, const char *args[]);
/* switch to non-root user and group */
bool drop_root_user();
@@ -126,6 +130,9 @@
/* prints all the system properties */
void print_properties();
+/** opens a socket and returns its file descriptor */
+int open_socket(const char *service);
+
/* redirect output to a service control socket */
void redirect_to_socket(FILE *redirect, const char *service);
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index 96232c4..1f56d21 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -9,6 +9,15 @@
disabled
oneshot
+# dumpstatez generates a zipped bugreport but also uses a socket to print the file location once
+# it is finished.
+service dumpstatez /system/bin/dumpstate -S -d -z \
+ -o /data/user_de/0/com.android.shell/files/bugreports/bugreport
+ socket dumpstate stream 0660 shell log
+ class main
+ disabled
+ oneshot
+
# bugreportplus is an enhanced version of bugreport that provides a better
# user interface (like displaying progress and allowing user to enter details).
# It's typically triggered by the power button or developer settings.
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 8c0e840..f1a1ed6 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -51,10 +51,14 @@
static const int64_t NANOS_PER_SEC = 1000000000;
/* list of native processes to include in the native dumps */
+// This matches the /proc/pid/exe link instead of /proc/pid/cmdline.
static const char* native_processes_to_dump[] = {
"/system/bin/audioserver",
"/system/bin/cameraserver",
"/system/bin/drmserver",
+ "/system/bin/mediacodec", // media.codec
+ "/system/bin/mediadrmserver",
+ "/system/bin/mediaextractor", // media.extractor
"/system/bin/mediaserver",
"/system/bin/sdcard",
"/system/bin/surfaceflinger",
@@ -664,7 +668,7 @@
ON_DRY_RUN({ update_progress(timeout_seconds); va_end(ap); return 0; });
- int status = run_command_always(title, false, timeout_seconds, args);
+ int status = run_command_always(title, DONT_DROP_ROOT, NORMAL_STDOUT, timeout_seconds, args);
va_end(ap);
return status;
}
@@ -701,13 +705,15 @@
ON_DRY_RUN({ update_progress(timeout_seconds); va_end(ap); return 0; });
- int status = run_command_always(title, true, timeout_seconds, args);
+ int status = run_command_always(title, DROP_ROOT, NORMAL_STDOUT, timeout_seconds, args);
va_end(ap);
return status;
}
/* forks a command and waits for it to finish */
-int run_command_always(const char *title, bool drop_root, int timeout_seconds, const char *args[]) {
+int run_command_always(const char *title, RootMode root_mode, StdoutMode stdout_mode,
+ int timeout_seconds, const char *args[]) {
+ bool silent = (stdout_mode == REDIRECT_TO_STDERR);
// TODO: need to check if args is null-terminated, otherwise execvp will crash dumpstate
/* TODO: for now we're simplifying the progress calculation by using the timeout as the weight.
@@ -721,17 +727,25 @@
/* handle error case */
if (pid < 0) {
- printf("*** fork: %s\n", strerror(errno));
+ if (!silent) printf("*** fork: %s\n", strerror(errno));
+ MYLOGE("*** fork: %s\n", strerror(errno));
return pid;
}
/* handle child case */
if (pid == 0) {
- if (drop_root && !drop_root_user()) {
- printf("*** could not drop root before running %s: %s\n", command, strerror(errno));
+ if (root_mode == DROP_ROOT && !drop_root_user()) {
+ if (!silent) printf("*** fail todrop root before running %s: %s\n", command,
+ strerror(errno));
+ MYLOGE("*** could not drop root before running %s: %s\n", command, strerror(errno));
return -1;
}
+ if (silent) {
+ // Redirect stderr to stdout
+ dup2(STDERR_FILENO, STDOUT_FILENO);
+ }
+
/* make sure the child dies when dumpstate dies */
prctl(PR_SET_PDEATHSIG, SIGKILL);
@@ -758,14 +772,14 @@
if (!ret) {
if (errno == ETIMEDOUT) {
format_args(command, args, &cmd);
- printf("*** command '%s' timed out after %.3fs (killing pid %d)\n", cmd.c_str(),
- (float) elapsed / NANOS_PER_SEC, pid);
+ if (!silent) printf("*** command '%s' timed out after %.3fs (killing pid %d)\n",
+ cmd.c_str(), (float) elapsed / NANOS_PER_SEC, pid);
MYLOGE("command '%s' timed out after %.3fs (killing pid %d)\n", cmd.c_str(),
(float) elapsed / NANOS_PER_SEC, pid);
} else {
format_args(command, args, &cmd);
- printf("*** command '%s': Error after %.4fs (killing pid %d)\n", cmd.c_str(),
- (float) elapsed / NANOS_PER_SEC, pid);
+ if (!silent) printf("*** command '%s': Error after %.4fs (killing pid %d)\n",
+ cmd.c_str(), (float) elapsed / NANOS_PER_SEC, pid);
MYLOGE("command '%s': Error after %.4fs (killing pid %d)\n", cmd.c_str(),
(float) elapsed / NANOS_PER_SEC, pid);
}
@@ -773,22 +787,25 @@
if (!waitpid_with_timeout(pid, 5, NULL)) {
kill(pid, SIGKILL);
if (!waitpid_with_timeout(pid, 5, NULL)) {
- printf("couldn not kill command '%s' (pid %d) even with SIGKILL.\n", command, pid);
- MYLOGE("couldn not kill command '%s' (pid %d) even with SIGKILL.\n", command, pid);
+ if (!silent) printf("could not kill command '%s' (pid %d) even with SIGKILL.\n",
+ command, pid);
+ MYLOGE("could not kill command '%s' (pid %d) even with SIGKILL.\n", command, pid);
}
}
return -1;
} else if (status) {
format_args(command, args, &cmd);
- printf("*** command '%s' failed: %s\n", cmd.c_str(), strerror(errno));
+ if (!silent) printf("*** command '%s' failed: %s\n", cmd.c_str(), strerror(errno));
MYLOGE("command '%s' failed: %s\n", cmd.c_str(), strerror(errno));
return -2;
}
if (WIFSIGNALED(status)) {
- printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
+ if (!silent) printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
+ MYLOGE("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
} else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
- printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
+ if (!silent) printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
+ MYLOGE("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
}
if (weight > 0) {
@@ -859,7 +876,7 @@
std::string args_string;
format_args(am_index + 1, am_args, &args_string);
MYLOGD("send_broadcast command: %s\n", args_string.c_str());
- run_command_always(NULL, true, 20, am_args);
+ run_command_always(NULL, DROP_ROOT, REDIRECT_TO_STDERR, 20, am_args);
}
size_t num_props = 0;
@@ -896,8 +913,7 @@
printf("\n");
}
-/* redirect output to a service control socket */
-void redirect_to_socket(FILE *redirect, const char *service) {
+int open_socket(const char *service) {
int s = android_get_control_socket(service);
if (s < 0) {
MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
@@ -917,11 +933,18 @@
exit(1);
}
+ return fd;
+}
+
+/* redirect output to a service control socket */
+void redirect_to_socket(FILE *redirect, const char *service) {
+ int fd = open_socket(service);
fflush(redirect);
dup2(fd, fileno(redirect));
close(fd);
}
+// TODO: should call is_valid_output_file and/or be merged into it.
void create_parent_dirs(const char *path) {
char *chp = const_cast<char *> (path);
@@ -1198,7 +1221,7 @@
void take_screenshot(const std::string& path) {
const char *args[] = { "/system/bin/screencap", "-p", path.c_str(), NULL };
- run_command_always(NULL, false, 10, args);
+ run_command_always(NULL, DONT_DROP_ROOT, REDIRECT_TO_STDERR, 10, args);
}
void vibrate(FILE* vibrator, int ms) {
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 95bc4b9..f4d894b 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -30,6 +30,7 @@
#include <android-base/stringprintf.h>
#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
#include <cutils/fs.h>
#include <cutils/log.h> // TODO: Move everything to base/logging.
#include <cutils/sched_policy.h>
@@ -73,7 +74,7 @@
uid_t uid = multiuser_get_uid(userid, appid);
int target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
if (flags & FLAG_STORAGE_CE) {
- auto path = create_data_user_package_path(uuid, userid, pkgname);
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
PLOG(ERROR) << "Failed to prepare " << path;
return -1;
@@ -123,7 +124,7 @@
// consistent location. This only works on non-FBE devices, since we
// never want to risk exposing data on a device with real CE/DE storage.
- auto ce_path = create_data_user_package_path(uuid, userid, pkgname);
+ auto ce_path = create_data_user_ce_package_path(uuid, userid, pkgname);
auto de_path = create_data_user_de_package_path(uuid, userid, pkgname);
// If neither directory is marked as default, assume CE is default
@@ -162,8 +163,8 @@
}
static bool clear_profile(const std::string& profile) {
- fd_t fd = open(profile.c_str(), O_WRONLY | O_NOFOLLOW);
- if (fd < 0) {
+ base::unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
+ if (ufd.get() < 0) {
if (errno != ENOENT) {
PLOG(WARNING) << "Could not open profile " << profile;
return false;
@@ -173,7 +174,7 @@
}
}
- if (flock(fd, LOCK_EX | LOCK_NB) != 0) {
+ if (flock(ufd.get(), LOCK_EX | LOCK_NB) != 0) {
if (errno != EWOULDBLOCK) {
PLOG(WARNING) << "Error locking profile " << profile;
}
@@ -195,11 +196,11 @@
return false;
}
- bool truncated = ftruncate(fd, 0) == 0;
+ bool truncated = ftruncate(ufd.get(), 0) == 0;
if (!truncated) {
PLOG(WARNING) << "Could not truncate " << profile;
}
- if (flock(fd, LOCK_UN) != 0) {
+ if (flock(ufd.get(), LOCK_UN) != 0) {
PLOG(WARNING) << "Error unlocking profile " << profile;
}
return truncated;
@@ -233,7 +234,8 @@
return success ? 0 : -1;
}
-int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
+int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode) {
std::string suffix = "";
bool only_cache = false;
if (flags & FLAG_CLEAR_CACHE_ONLY) {
@@ -246,7 +248,7 @@
int res = 0;
if (flags & FLAG_STORAGE_CE) {
- auto path = create_data_user_package_path(uuid, userid, pkgname) + suffix;
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode) + suffix;
if (access(path.c_str(), F_OK) == 0) {
res |= delete_dir_contents(path);
}
@@ -288,11 +290,12 @@
return result;
}
-int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
+int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode) {
int res = 0;
if (flags & FLAG_STORAGE_CE) {
res |= delete_dir_contents_and_dir(
- create_data_user_package_path(uuid, userid, pkgname));
+ create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode));
}
if (flags & FLAG_STORAGE_DE) {
res |= delete_dir_contents_and_dir(
@@ -345,9 +348,9 @@
// Copy private data for all known users
// TODO: handle user_de paths
for (auto user : users) {
- std::string from(create_data_user_package_path(from_uuid, user, package_name));
- std::string to(create_data_user_package_path(to_uuid, user, package_name));
- std::string to_parent(create_data_user_path(to_uuid, user));
+ std::string from(create_data_user_ce_package_path(from_uuid, user, package_name));
+ std::string to(create_data_user_ce_package_path(to_uuid, user, package_name));
+ std::string to_parent(create_data_user_ce_path(to_uuid, user));
// Data source may not exist for all users; that's okay
if (access(from.c_str(), F_OK) != 0) {
@@ -355,7 +358,7 @@
continue;
}
- std::string user_path(create_data_user_path(to_uuid, user));
+ std::string user_path(create_data_user_ce_path(to_uuid, user));
if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) {
LOG(ERROR) << "Failed to prepare user target " << user_path;
goto fail;
@@ -408,7 +411,7 @@
}
}
for (auto user : users) {
- std::string to(create_data_user_package_path(to_uuid, user, package_name));
+ std::string to(create_data_user_ce_package_path(to_uuid, user, package_name));
if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
LOG(WARNING) << "Failed to rollback " << to;
}
@@ -416,38 +419,29 @@
return -1;
}
-int make_user_config(userid_t userid)
-{
- if (ensure_config_user_dirs(userid) == -1) {
- return -1;
+int create_user_data(const char *uuid, userid_t userid, int user_serial ATTRIBUTE_UNUSED,
+ int flags) {
+ if (flags & FLAG_STORAGE_DE) {
+ if (uuid == nullptr) {
+ return ensure_config_user_dirs(userid);
+ }
}
-
return 0;
}
-int delete_user(const char *uuid, userid_t userid) {
+int destroy_user_data(const char *uuid, userid_t userid, int flags) {
int res = 0;
-
- std::string data_path(create_data_user_path(uuid, userid));
- std::string data_de_path(create_data_user_de_path(uuid, userid));
- std::string media_path(create_data_media_path(uuid, userid));
- std::string profiles_path(create_data_user_profiles_path(userid));
-
- res |= delete_dir_contents_and_dir(data_path);
- // TODO: include result once 25796509 is fixed
- delete_dir_contents_and_dir(data_de_path);
- res |= delete_dir_contents_and_dir(media_path);
- res |= delete_dir_contents_and_dir(profiles_path);
-
- // Config paths only exist on internal storage
- if (uuid == nullptr) {
- char config_path[PATH_MAX];
- if ((create_user_config_path(config_path, userid) != 0)
- || (delete_dir_contents(config_path, 1, NULL) != 0)) {
- res = -1;
+ if (flags & FLAG_STORAGE_DE) {
+ res |= delete_dir_contents_and_dir(create_data_user_de_path(uuid, userid), true);
+ if (uuid == nullptr) {
+ res |= delete_dir_contents_and_dir(create_data_misc_legacy_path(userid), true);
+ res |= delete_dir_contents_and_dir(create_data_user_profiles_path(userid), true);
}
}
-
+ if (flags & FLAG_STORAGE_CE) {
+ res |= delete_dir_contents_and_dir(create_data_user_ce_path(uuid, userid), true);
+ res |= delete_dir_contents_and_dir(create_data_media_path(uuid, userid), true);
+ }
return res;
}
@@ -479,7 +473,7 @@
// Special case for owner on internal storage
if (uuid == nullptr) {
- std::string _tmpdir(create_data_user_path(nullptr, 0));
+ std::string _tmpdir(create_data_user_ce_path(nullptr, 0));
add_cache_files(cache, _tmpdir.c_str(), "cache");
}
@@ -566,142 +560,96 @@
}
}
-int get_app_size(const char *uuid, const char *pkgname, int userid, int flags,
- const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath,
- const char *asecpath, const char *instruction_set, int64_t *_codesize, int64_t *_datasize,
- int64_t *_cachesize, int64_t* _asecsize) {
+static void add_app_data_size(std::string& path, int64_t *codesize, int64_t *datasize,
+ int64_t *cachesize) {
DIR *d;
int dfd;
struct dirent *de;
struct stat s;
- char path[PKG_PATH_MAX];
- int64_t codesize = 0;
- int64_t datasize = 0;
- int64_t cachesize = 0;
- int64_t asecsize = 0;
+ d = opendir(path.c_str());
+ if (d == nullptr) {
+ PLOG(WARNING) << "Failed to open " << path;
+ return;
+ }
+ dfd = dirfd(d);
+ while ((de = readdir(d))) {
+ const char *name = de->d_name;
- /* count the source apk as code -- but only if it's not
- * on the /system partition and its not on the sdcard. */
- if (validate_system_app_path(apkpath) &&
- strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
- if (stat(apkpath, &s) == 0) {
- codesize += stat_size(&s);
- if (S_ISDIR(s.st_mode)) {
- d = opendir(apkpath);
- if (d != NULL) {
- dfd = dirfd(d);
- codesize += calculate_dir_size(dfd);
- closedir(d);
- }
+ int64_t statsize = 0;
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ statsize = stat_size(&s);
+ }
+
+ if (de->d_type == DT_DIR) {
+ int subfd;
+ int64_t dirsize = 0;
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
}
- }
- }
-
- /* count the forward locked apk as code if it is given */
- if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
- if (stat(fwdlock_apkpath, &s) == 0) {
- codesize += stat_size(&s);
- }
- }
-
- /* count the cached dexfile as code */
- if (create_cache_path(path, apkpath, instruction_set)) {
- if (stat(path, &s) == 0) {
- codesize += stat_size(&s);
- }
- }
-
- /* add in size of any libraries */
- if (libdirpath != NULL && libdirpath[0] != '!') {
- d = opendir(libdirpath);
- if (d != NULL) {
- dfd = dirfd(d);
- codesize += calculate_dir_size(dfd);
- closedir(d);
- }
- }
-
- /* compute asec size if it is given */
- if (asecpath != NULL && asecpath[0] != '!') {
- if (stat(asecpath, &s) == 0) {
- asecsize += stat_size(&s);
- }
- }
-
- std::vector<userid_t> users;
- if (userid == -1) {
- users = get_known_users(uuid);
- } else {
- users.push_back(userid);
- }
-
- for (auto user : users) {
- // TODO: handle user_de directories
- if (!(flags & FLAG_STORAGE_CE)) continue;
-
- std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname));
- const char* pkgdir = _pkgdir.c_str();
-
- d = opendir(pkgdir);
- if (d == NULL) {
- PLOG(WARNING) << "Failed to open " << pkgdir;
- continue;
- }
- dfd = dirfd(d);
-
- /* most stuff in the pkgdir is data, except for the "cache"
- * directory and below, which is cache, and the "lib" directory
- * and below, which is code...
- */
- while ((de = readdir(d))) {
- const char *name = de->d_name;
-
- if (de->d_type == DT_DIR) {
- int subfd;
- int64_t statsize = 0;
- int64_t dirsize = 0;
- /* always skip "." and ".." */
- if (name[0] == '.') {
- if (name[1] == 0) continue;
- if ((name[1] == '.') && (name[2] == 0)) continue;
- }
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- statsize = stat_size(&s);
- }
- subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
- if (subfd >= 0) {
- dirsize = calculate_dir_size(subfd);
- }
- if(!strcmp(name,"lib")) {
- codesize += dirsize + statsize;
- } else if(!strcmp(name,"cache")) {
- cachesize += dirsize + statsize;
- } else {
- datasize += dirsize + statsize;
- }
- } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
- // This is the symbolic link to the application's library
- // code. We'll count this as code instead of data, since
- // it is not something that the app creates.
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- codesize += stat_size(&s);
- }
+ subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (subfd >= 0) {
+ dirsize = calculate_dir_size(subfd);
+ close(subfd);
+ }
+ // TODO: check xattrs!
+ if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) {
+ *datasize += statsize;
+ *cachesize += dirsize;
} else {
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- datasize += stat_size(&s);
- }
+ *datasize += dirsize + statsize;
}
+ } else if (de->d_type == DT_LNK && !strcmp(name, "lib")) {
+ *codesize += statsize;
+ } else {
+ *datasize += statsize;
}
+ }
+ closedir(d);
+}
+
+int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+ const char *code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
+ int64_t* asecsize) {
+ DIR *d;
+ int dfd;
+
+ d = opendir(code_path);
+ if (d != nullptr) {
+ dfd = dirfd(d);
+ *codesize += calculate_dir_size(dfd);
closedir(d);
}
- *_codesize = codesize;
- *_datasize = datasize;
- *_cachesize = cachesize;
- *_asecsize = asecsize;
+
+ if (flags & FLAG_STORAGE_CE) {
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode);
+ add_app_data_size(path, codesize, datasize, cachesize);
+ }
+ if (flags & FLAG_STORAGE_DE) {
+ auto path = create_data_user_de_package_path(uuid, userid, pkgname);
+ add_app_data_size(path, codesize, datasize, cachesize);
+ }
+
+ *asecsize = 0;
+
return 0;
}
+int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode) {
+ struct stat buf;
+ memset(&buf, 0, sizeof(buf));
+ if (flags & FLAG_STORAGE_CE) {
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
+ if (stat(path.c_str(), &buf) == 0) {
+ *inode = buf.st_ino;
+ return 0;
+ }
+ }
+ return -1;
+}
+
static int split_count(const char *str)
{
char *ctx;
@@ -1303,13 +1251,17 @@
return true;
}
-static int open_output_file(char* file_name, bool recreate) {
+static int open_output_file(char* file_name, bool recreate, int permissions) {
int flags = O_RDWR | O_CREAT;
if (recreate) {
- unlink(file_name);
+ if (unlink(file_name) < 0) {
+ if (errno != ENOENT) {
+ PLOG(ERROR) << "open_output_file: Couldn't unlink " << file_name;
+ }
+ }
flags |= O_EXCL;
}
- return open(file_name, flags, 0600);
+ return open(file_name, flags, permissions);
}
static bool set_permissions_and_ownership(int fd, bool is_public, int uid, const char* path) {
@@ -1426,8 +1378,7 @@
return -1;
}
- unlink(out_path);
- out_fd = open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644);
+ out_fd = open_output_file(out_path, /*recreate*/true, /*permissions*/0644);
if (out_fd < 0) {
ALOGE("installd cannot open '%s' for output during dexopt\n", out_path);
goto fail;
@@ -1441,7 +1392,7 @@
// Make sure there really is enough space.
strcpy(swap_file_name, out_path);
if (add_extension_to_file_name(swap_file_name, ".swap")) {
- swap_fd = open_output_file(swap_file_name, /*recreate*/true);
+ swap_fd = open_output_file(swap_file_name, /*recreate*/true, /*permissions*/0600);
}
if (swap_fd < 0) {
// Could not create swap file. Optimistically go on and hope that we can compile
@@ -1449,7 +1400,9 @@
ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name);
} else {
// Immediately unlink. We don't really want to hit flash.
- unlink(swap_file_name);
+ if (unlink(swap_file_name) < 0) {
+ PLOG(ERROR) << "Couldn't unlink swap file " << swap_file_name;
+ }
}
}
@@ -1465,7 +1418,7 @@
if (profile_guided && have_app_image_format) {
// Recreate is true since we do not want to modify a mapped image. If the app is already
// running and we modify the image file, it can cause crashes (b/27493510).
- image_fd = open_output_file(image_path, /*recreate*/true);
+ image_fd = open_output_file(image_path, /*recreate*/true, /*permissions*/0600);
if (image_fd < 0) {
// Could not create application image file. Go on since we can compile without it.
ALOGE("installd could not create '%s' for image file during dexopt\n", image_path);
@@ -1475,7 +1428,11 @@
}
// If we have a valid image file path but no image fd, erase the image file.
if (image_fd < 0) {
- unlink(image_path);
+ if (unlink(image_path) < 0) {
+ if (errno != ENOENT) {
+ PLOG(ERROR) << "Couldn't unlink image file " << image_path;
+ }
+ }
}
}
@@ -1607,7 +1564,7 @@
struct stat s, libStat;
int rc = 0;
- std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname));
+ std::string _pkgdir(create_data_user_ce_package_path(uuid, userId, pkgname));
std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX);
const char* pkgdir = _pkgdir.c_str();
@@ -1794,7 +1751,7 @@
uid_t uid = multiuser_get_uid(userid, appid);
if (flags & FLAG_STORAGE_CE) {
- auto path = create_data_user_package_path(uuid, userid, pkgName);
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgName);
if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
PLOG(ERROR) << "restorecon failed for " << path;
res = -1;
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index 13143c5..81c13b4 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -33,19 +33,22 @@
int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags,
appid_t appid, const char* seinfo);
int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
-int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
-int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
+int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode);
+int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode);
int move_complete_app(const char* from_uuid, const char *to_uuid, const char *package_name,
const char *data_app_name, appid_t appid, const char* seinfo, int target_sdk_version);
-int get_app_size(const char *uuid, const char *pkgname, int userid, int flags,
- const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath,
- const char *asecpath, const char *instruction_set, int64_t *codesize, int64_t *datasize,
- int64_t *cachesize, int64_t *asecsize);
+int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+ const char* code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
+ int64_t *asecsize);
+int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode);
-int make_user_config(userid_t userid);
-int delete_user(const char *uuid, userid_t userid);
+int create_user_data(const char *uuid, userid_t userid, int user_serial, int flags);
+int destroy_user_data(const char *uuid, userid_t userid, int flags);
+
int rm_dex(const char *path, const char *instruction_set);
int free_cache(const char *uuid, int64_t free_size);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index de3f54a..eb51e70 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -207,13 +207,13 @@
}
static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
- /* const char *uuid, const char *pkgname, userid_t userid, int flags */
- return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
+ /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
+ return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
}
static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
- /* const char *uuid, const char *pkgname, userid_t userid, int flags */
- return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
+ /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
+ return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
}
// We use otapreopt_chroot to get into the chroot.
@@ -303,11 +303,10 @@
int64_t asecsize = 0;
int res = 0;
- /* const char *uuid, const char *pkgname, userid_t userid, int flags,
- const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath,
- const char *asecpath, const char *instruction_set */
- res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4], arg[5],
- arg[6], arg[7], arg[8], &codesize, &datasize, &cachesize, &asecsize);
+ /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+ const char* code_path */
+ res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]),
+ arg[5], &codesize, &datasize, &cachesize, &asecsize);
/*
* Each int64_t can take up 22 characters printed out. Make sure it
@@ -318,6 +317,17 @@
return res;
}
+static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) {
+ ino_t inode = 0;
+ int res = 0;
+
+ /* const char *uuid, const char *pkgname, int userid, int flags */
+ res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode);
+
+ snprintf(reply, REPLY_MAX, "%" PRId64, (int64_t) inode);
+ return res;
+}
+
static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
/* const char* from_uuid, const char *to_uuid, const char *package_name,
const char *data_app_name, appid_t appid, const char* seinfo,
@@ -326,14 +336,16 @@
atoi(arg[4]), arg[5], atoi(arg[6]));
}
-static int do_mk_user_config(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+static int do_create_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
- return make_user_config(atoi(arg[0])); /* userid */
+ /* const char *uuid, userid_t userid, int user_serial, int flags */
+ return create_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]), atoi(arg[3]));
}
-static int do_rm_user(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+static int do_destroy_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
- return delete_user(parse_null(arg[0]), atoi(arg[1])); /* uuid, userid */
+ /* const char *uuid, userid_t userid, int flags */
+ return destroy_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]));
}
static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
@@ -393,18 +405,20 @@
{ "create_app_data", 7, do_create_app_data },
{ "restorecon_app_data", 6, do_restorecon_app_data },
{ "migrate_app_data", 4, do_migrate_app_data },
- { "clear_app_data", 4, do_clear_app_data },
- { "destroy_app_data", 4, do_destroy_app_data },
+ { "clear_app_data", 5, do_clear_app_data },
+ { "destroy_app_data", 5, do_destroy_app_data },
{ "move_complete_app", 7, do_move_complete_app },
- { "get_app_size", 9, do_get_app_size },
+ { "get_app_size", 6, do_get_app_size },
+ { "get_app_data_inode", 4, do_get_app_data_inode },
+
+ { "create_user_data", 4, do_create_user_data },
+ { "destroy_user_data", 3, do_destroy_user_data },
{ "dexopt", 9, do_dexopt },
{ "markbootcomplete", 1, do_mark_boot_complete },
{ "rmdex", 2, do_rm_dex },
{ "freecache", 2, do_free_cache },
{ "linklib", 4, do_linklib },
- { "mkuserconfig", 1, do_mk_user_config },
- { "rmuser", 2, do_rm_user },
{ "idmap", 3, do_idmap },
{ "createoatdir", 2, do_create_oat_dir },
{ "rmpackagedir", 1, do_rm_package_dir },
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index ff69f4b..9b2de88 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -472,13 +472,13 @@
}
TEST_F(UtilsTest, CreateDataUserPath) {
- EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0));
- EXPECT_EQ("/data/user/10", create_data_user_path(nullptr, 10));
+ EXPECT_EQ("/data/data", create_data_user_ce_path(nullptr, 0));
+ EXPECT_EQ("/data/user/10", create_data_user_ce_path(nullptr, 10));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0",
- create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
+ create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10",
- create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
+ create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
}
TEST_F(UtilsTest, CreateDataMediaPath) {
@@ -499,13 +499,13 @@
}
TEST_F(UtilsTest, CreateDataUserPackagePath) {
- EXPECT_EQ("/data/data/com.example", create_data_user_package_path(nullptr, 0, "com.example"));
- EXPECT_EQ("/data/user/10/com.example", create_data_user_package_path(nullptr, 10, "com.example"));
+ EXPECT_EQ("/data/data/com.example", create_data_user_ce_package_path(nullptr, 0, "com.example"));
+ EXPECT_EQ("/data/user/10/com.example", create_data_user_ce_package_path(nullptr, 10, "com.example"));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0/com.example",
- create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
+ create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10/com.example",
- create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
+ create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
}
} // namespace installd
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index d84d9f6..90d2a9e 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -81,11 +81,44 @@
* volume UUID, package name, and user ID. An empty UUID is assumed to be
* internal storage.
*/
-std::string create_data_user_package_path(const char* volume_uuid,
+std::string create_data_user_ce_package_path(const char* volume_uuid,
userid_t user, const char* package_name) {
check_package_name(package_name);
return StringPrintf("%s/%s",
- create_data_user_path(volume_uuid, user).c_str(), package_name);
+ create_data_user_ce_path(volume_uuid, user).c_str(), package_name);
+}
+
+std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user,
+ const char* package_name, ino_t ce_data_inode) {
+ // For testing purposes, rely on the inode when defined; this could be
+ // optimized to use access() in the future.
+ auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name);
+ if (ce_data_inode != 0) {
+ auto user_path = create_data_user_ce_path(volume_uuid, user);
+ DIR* dir = opendir(user_path.c_str());
+ if (dir == nullptr) {
+ PLOG(ERROR) << "Failed to opendir " << user_path;
+ return fallback;
+ }
+
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (ent->d_ino == ce_data_inode) {
+ auto resolved = StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
+ if (resolved != fallback) {
+ LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode
+ << " instead of " << fallback;
+ }
+ closedir(dir);
+ return resolved;
+ }
+ }
+ LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback;
+ closedir(dir);
+ return fallback;
+ } else {
+ return fallback;
+ }
}
std::string create_data_user_de_package_path(const char* volume_uuid,
@@ -102,7 +135,7 @@
return -1;
}
- std::string _tmp(create_data_user_package_path(nullptr, userid, pkgname) + postfix);
+ std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix);
const char* tmp = _tmp.c_str();
if (strlen(tmp) >= PKG_PATH_MAX) {
path[0] = '\0';
@@ -132,7 +165,7 @@
/**
* Create the path name for user data for a certain userid.
*/
-std::string create_data_user_path(const char* volume_uuid, userid_t userid) {
+std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
std::string data(create_data_path(volume_uuid));
if (volume_uuid == nullptr) {
if (userid == 0) {
@@ -160,6 +193,10 @@
return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
}
+std::string create_data_misc_legacy_path(userid_t userid) {
+ return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
+}
+
std::string create_data_user_profiles_path(userid_t userid) {
return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid);
}
@@ -206,17 +243,6 @@
return users;
}
-/**
- * Create the path name for config for a certain userid.
- * Returns 0 on success, and -1 on failure.
- */
-int create_user_config_path(char path[PATH_MAX], userid_t userid) {
- if (snprintf(path, PATH_MAX, "%s%d", "/data/misc/user/", userid) > PATH_MAX) {
- return -1;
- }
- return 0;
-}
-
int create_move_path(char path[PKG_PATH_MAX],
const char* pkgname,
const char* leaf,
@@ -1186,19 +1212,13 @@
}
int ensure_config_user_dirs(userid_t userid) {
- char config_user_path[PATH_MAX];
-
// writable by system, readable by any app within the same user
const int uid = multiuser_get_uid(userid, AID_SYSTEM);
const int gid = multiuser_get_uid(userid, AID_EVERYBODY);
// Ensure /data/misc/user/<userid> exists
- create_user_config_path(config_user_path, userid);
- if (fs_prepare_dir(config_user_path, 0750, uid, gid) == -1) {
- return -1;
- }
-
- return 0;
+ auto path = create_data_misc_legacy_path(userid);
+ return fs_prepare_dir(path.c_str(), 0750, uid, gid);
}
int wait_child(pid_t pid)
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 416a726..477baea 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -73,17 +73,20 @@
std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
-// TODO: finish refactoring to "_ce"
-std::string create_data_user_path(const char* volume_uuid, userid_t userid);
+std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid);
std::string create_data_user_de_path(const char* volume_uuid, userid_t userid);
-std::string create_data_user_package_path(const char* volume_uuid,
+std::string create_data_user_ce_package_path(const char* volume_uuid,
userid_t user, const char* package_name);
+std::string create_data_user_ce_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name, ino_t ce_data_inode);
std::string create_data_user_de_package_path(const char* volume_uuid,
userid_t user, const char* package_name);
std::string create_data_media_path(const char* volume_uuid, userid_t userid);
+std::string create_data_misc_legacy_path(userid_t userid);
+
std::string create_data_user_profiles_path(userid_t userid);
std::string create_data_user_profile_package_path(userid_t user, const char* package_name);
std::string create_data_ref_profile_package_path(const char* package_name);
@@ -139,8 +142,6 @@
char *build_string2(const char *s1, const char *s2);
char *build_string3(const char *s1, const char *s2, const char *s3);
-int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
-int ensure_media_user_dirs(const char* uuid, userid_t userid);
int ensure_config_user_dirs(userid_t userid);
int wait_child(pid_t pid);
diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc
index 1ba339d..aee7bd8 100644
--- a/cmds/servicemanager/servicemanager.rc
+++ b/cmds/servicemanager/servicemanager.rc
@@ -11,4 +11,5 @@
onrestart restart inputflinger
onrestart restart drm
onrestart restart cameraserver
+ writepid /dev/cpuset/system-background/tasks
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index 8ed8460..ab89ef5 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -24,15 +24,11 @@
-->
<permissions>
<feature name="android.hardware.audio.output" />
- <feature name="android.hardware.camera" />
<feature name="android.hardware.location" />
<feature name="android.hardware.location.network" />
- <feature name="android.hardware.sensor.compass" />
- <feature name="android.hardware.sensor.accelerometer" />
<feature name="android.hardware.bluetooth" />
<feature name="android.hardware.touchscreen" />
<feature name="android.hardware.microphone" />
- <feature name="android.hardware.screen.landscape" />
<!-- Feature to specify if the device is a car -->
<feature name="android.hardware.type.automotive" />
diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml
index 346abad..4b7a706 100644
--- a/data/etc/wearable_core_hardware.xml
+++ b/data/etc/wearable_core_hardware.xml
@@ -22,7 +22,8 @@
-->
<permissions>
<feature name="android.hardware.location" />
- <feature name="android.hardware.sensor.compass" />
+ <!-- devices supporting compass/magnitometer sensor must include
+ android.hardware.sensor.compass.xml -->
<feature name="android.hardware.sensor.accelerometer" />
<feature name="android.hardware.bluetooth" />
<feature name="android.hardware.touchscreen" />
@@ -31,8 +32,10 @@
<!-- basic system services -->
<feature name="android.software.home_screen" />
- <!-- devices that support a device administrator policy must include
- android.software.device_admin.xml -->
+ <!-- device administration -->
+ <feature name="android.software.device_admin" />
+ <feature name="android.software.managed_users" />
+
<!-- devices with GPS must include device/google/clockwork/gps.xml -->
<!-- devices with an autofocus camera and/or flash must include either
android.hardware.camera.autofocus.xml or
diff --git a/include/batteryservice/BatteryService.h b/include/batteryservice/BatteryService.h
index 912dcf6..b399905 100644
--- a/include/batteryservice/BatteryService.h
+++ b/include/batteryservice/BatteryService.h
@@ -68,6 +68,7 @@
int batteryCurrent;
int batteryCycleCount;
int batteryFullCharge;
+ int batteryChargeCounter;
String8 batteryTechnology;
status_t writeToParcel(Parcel* parcel) const;
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
index f9edc2a..64cf72e 100644
--- a/include/binder/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -91,6 +91,8 @@
size_t mExecutingThreadsCount;
// Maximum number for binder threads allowed for this process.
size_t mMaxThreads;
+ // Time when thread pool was emptied
+ int64_t mStarvationStartTimeMs;
mutable Mutex mLock; // protects everything below.
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index d232dbb..4337da9 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -319,6 +319,9 @@
android_dataspace dataspace;
} mSharedBufferCache;
+ // The slot of the last queued buffer
+ int mLastQueuedSlot;
+
}; // class BufferQueueCore
} // namespace android
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 691487d..7256f73 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -182,6 +182,10 @@
// See IGraphicBufferProducer::setDequeueTimeout
virtual status_t setDequeueTimeout(nsecs_t timeout) override;
+ // See IGraphicBufferProducer::getLastQueuedBuffer
+ virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+ sp<Fence>* outFence) override;
+
private:
// This is required by the IBinder::DeathRecipient interface
virtual void binderDied(const wp<IBinder>& who);
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 32bf988..049406c 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -557,6 +557,15 @@
// happen because of trying to allocate/deallocate the async
// buffer.
virtual status_t setDequeueTimeout(nsecs_t timeout) = 0;
+
+ // Returns the last queued buffer along with a fence which must signal
+ // before the contents of the buffer are read. If there are no buffers in
+ // the queue, outBuffer will be populated with nullptr and outFence will be
+ // populated with Fence::NO_FENCE
+ //
+ // Returns NO_ERROR or the status of the Binder transaction
+ virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+ sp<Fence>* outFence) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 8c3d49e..af26721 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -39,6 +39,7 @@
class DisplayState;
struct DisplayInfo;
struct DisplayStatInfo;
+class HdrCapabilities;
class IDisplayEventConnection;
class IMemoryHeap;
class Rect;
@@ -157,6 +158,13 @@
* Requires the ACCESS_SURFACE_FLINGER permission.
*/
virtual status_t getAnimationFrameStats(FrameStats* outStats) const = 0;
+
+ /* Gets the supported HDR capabilities of the given display.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ virtual status_t getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) const = 0;
};
// ----------------------------------------------------------------------------
@@ -184,6 +192,7 @@
GET_ANIMATION_FRAME_STATS,
SET_POWER_MODE,
GET_DISPLAY_STATS,
+ GET_HDR_CAPABILITIES,
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index 3792540..353003c 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -56,7 +56,7 @@
uint8_t b[16];
} uuid_t;
- Sensor();
+ Sensor(const char * name = "");
Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
~Sensor();
@@ -80,6 +80,7 @@
int32_t getMaxDelay() const;
uint32_t getFlags() const;
bool isWakeUpSensor() const;
+ bool isDynamicSensor() const;
int32_t getReportingMode() const;
const uuid_t& getUuid() const;
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 5d1d7bf..bbf427d 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -122,6 +122,17 @@
// See IGraphicBufferProducer::setDequeueTimeout
status_t setDequeueTimeout(nsecs_t timeout);
+ /*
+ * Wait for frame number to increase past lastFrame for at most
+ * timeoutNs. Useful for one thread to wait for another unknown
+ * thread to queue a buffer.
+ */
+ bool waitForNextFrame(uint64_t lastFrame, nsecs_t timeout);
+
+ // See IGraphicBufferProducer::getLastQueuedBuffer
+ status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+ sp<Fence>* outFence);
+
protected:
virtual ~Surface();
@@ -348,6 +359,8 @@
// This is true if the shared buffer has already been queued/canceled. It's
// used to prevent a mismatch between the number of queue/dequeue calls.
bool mSharedBufferHasBeenQueued;
+
+ Condition mQueueBufferCondition;
};
namespace view {
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 794fe4c..73f923c 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -40,6 +40,7 @@
class DisplayInfo;
class Composer;
+class HdrCapabilities;
class ISurfaceComposerClient;
class IGraphicBufferProducer;
class Region;
@@ -137,6 +138,8 @@
status_t setLayerStack(const sp<IBinder>& id, uint32_t layerStack);
status_t deferTransactionUntil(const sp<IBinder>& id,
const sp<IBinder>& handle, uint64_t frameNumber);
+ status_t setOverrideScalingMode(const sp<IBinder>& id,
+ int32_t overrideScalingMode);
status_t destroySurface(const sp<IBinder>& id);
status_t clearLayerFrameStats(const sp<IBinder>& token) const;
@@ -145,6 +148,9 @@
static status_t clearAnimationFrameStats();
static status_t getAnimationFrameStats(FrameStats* outStats);
+ static status_t getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities);
+
static void setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
static void setDisplayLayerStack(const sp<IBinder>& token,
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index 35644db..bedebb6 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -77,6 +77,11 @@
// identified by handle reaches the given frameNumber
status_t deferTransactionUntil(sp<IBinder> handle, uint64_t frameNumber);
+ // Set an override scaling mode as documented in <system/window.h>
+ // the override scaling mode will take precedence over any client
+ // specified scaling mode. -1 will clear the override scaling mode.
+ status_t setOverrideScalingMode(int32_t overrideScalingMode);
+
static status_t writeSurfaceToParcel(
const sp<SurfaceControl>& control, Parcel* parcel);
diff --git a/include/input/Input.h b/include/input/Input.h
index 3b1c86b..55787e7 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -45,6 +45,19 @@
};
enum {
+
+ /**
+ * This flag indicates that the window that received this motion event is partly
+ * or wholly obscured by another visible window above it. This flag is set to true
+ * even if the event did not directly pass through the obscured area.
+ * A security sensitive application can check this flag to identify situations in which
+ * a malicious application may have covered up part of its content for the purpose
+ * of misleading the user or hijacking touches. An appropriate response might be
+ * to drop the suspect touches or to take additional precautions to confirm the user's
+ * actual intent.
+ */
+ AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 0x2,
+
/* Motion event is inconsistent with previously sent motion events. */
AMOTION_EVENT_FLAG_TAINTED = 0x80000000,
};
diff --git a/include/media/openmax/OMX_VideoExt.h b/include/media/openmax/OMX_VideoExt.h
index 1a2f0b5..4bb5f9a 100644
--- a/include/media/openmax/OMX_VideoExt.h
+++ b/include/media/openmax/OMX_VideoExt.h
@@ -77,10 +77,13 @@
/** VP9 profiles */
typedef enum OMX_VIDEO_VP9PROFILETYPE {
- OMX_VIDEO_VP9Profile0 = 0x0,
- OMX_VIDEO_VP9Profile1 = 0x1,
- OMX_VIDEO_VP9Profile2 = 0x2,
- OMX_VIDEO_VP9Profile3 = 0x3,
+ OMX_VIDEO_VP9Profile0 = 0x1,
+ OMX_VIDEO_VP9Profile1 = 0x2,
+ OMX_VIDEO_VP9Profile2 = 0x4,
+ OMX_VIDEO_VP9Profile3 = 0x8,
+ // HDR profiles also support passing HDR metadata
+ OMX_VIDEO_VP9Profile2HDR = 0x1000,
+ OMX_VIDEO_VP9Profile3HDR = 0x2000,
OMX_VIDEO_VP9ProfileUnknown = 0x6EFFFFFF,
OMX_VIDEO_VP9ProfileMax = 0x7FFFFFFF
} OMX_VIDEO_VP9PROFILETYPE;
@@ -252,12 +255,13 @@
/** Dolby Vision Profile enum type */
typedef enum OMX_VIDEO_DOLBYVISIONPROFILETYPE {
OMX_VIDEO_DolbyVisionProfileUnknown = 0x0,
- OMX_VIDEO_DolbyVisionProfileDvavDer = 0x1,
- OMX_VIDEO_DolbyVisionProfileDvavDen = 0x2,
- OMX_VIDEO_DolbyVisionProfileDvheDer = 0x3,
- OMX_VIDEO_DolbyVisionProfileDvheDen = 0x4,
- OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x5,
- OMX_VIDEO_DolbyVisionProfileDvheStn = 0x6,
+ OMX_VIDEO_DolbyVisionProfileDvavPer = 0x1,
+ OMX_VIDEO_DolbyVisionProfileDvavPen = 0x2,
+ OMX_VIDEO_DolbyVisionProfileDvheDer = 0x4,
+ OMX_VIDEO_DolbyVisionProfileDvheDen = 0x8,
+ OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x10,
+ OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
+ OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
OMX_VIDEO_DolbyVisionProfileMax = 0x7FFFFFFF
} OMX_VIDEO_DOLBYVISIONPROFILETYPE;
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 078720a..92d31d1 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -53,7 +53,8 @@
eLayerStackChanged = 0x00000080,
eCropChanged = 0x00000100,
eDeferTransaction = 0x00000200,
- eFinalCropChanged = 0x00000400
+ eFinalCropChanged = 0x00000400,
+ eOverrideScalingModeChanged = 0x00000800
};
layer_state_t()
@@ -61,7 +62,8 @@
x(0), y(0), z(0), w(0), h(0), layerStack(0),
alpha(0), flags(0), mask(0),
reserved(0), crop(Rect::INVALID_RECT),
- finalCrop(Rect::INVALID_RECT), frameNumber(0)
+ finalCrop(Rect::INVALID_RECT), frameNumber(0),
+ overrideScalingMode(-1)
{
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
@@ -93,6 +95,7 @@
Rect finalCrop;
sp<IBinder> handle;
uint64_t frameNumber;
+ int32_t overrideScalingMode;
// non POD must be last. see write/read
Region transparentRegion;
};
diff --git a/include/ui/HdrCapabilities.h b/include/ui/HdrCapabilities.h
new file mode 100644
index 0000000..a7cd5fb
--- /dev/null
+++ b/include/ui/HdrCapabilities.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_HDR_CAPABILTIES_H
+#define ANDROID_UI_HDR_CAPABILTIES_H
+
+#include <binder/Parcelable.h>
+
+namespace android {
+
+class HdrCapabilities : public Parcelable
+{
+public:
+ HdrCapabilities(const std::vector<int32_t /*android_hdr_t*/>& types,
+ float maxLuminance, float maxAverageLuminance, float minLuminance)
+ : mSupportedHdrTypes(types),
+ mMaxLuminance(maxLuminance),
+ mMaxAverageLuminance(maxAverageLuminance),
+ mMinLuminance(minLuminance) {}
+
+ // Make this move-constructable and move-assignable
+ HdrCapabilities(HdrCapabilities&& other) = default;
+ HdrCapabilities& operator=(HdrCapabilities&& other) = default;
+
+ HdrCapabilities()
+ : mSupportedHdrTypes(),
+ mMaxLuminance(-1.0f),
+ mMaxAverageLuminance(-1.0f),
+ mMinLuminance(-1.0f) {}
+
+ virtual ~HdrCapabilities() = default;
+
+ const std::vector<int32_t /*android_hdr_t*/>& getSupportedHdrTypes() const {
+ return mSupportedHdrTypes;
+ }
+ float getDesiredMaxLuminance() const { return mMaxLuminance; }
+ float getDesiredMaxAverageLuminance() const { return mMaxAverageLuminance; }
+ float getDesiredMinLuminance() const { return mMinLuminance; }
+
+ // Parcelable interface
+ virtual status_t writeToParcel(Parcel* parcel) const override;
+ virtual status_t readFromParcel(const Parcel* parcel) override;
+
+private:
+ std::vector<int32_t /*android_hdr_t*/> mSupportedHdrTypes;
+ float mMaxLuminance;
+ float mMaxAverageLuminance;
+ float mMinLuminance;
+};
+
+} // namespace android
+
+#endif
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 1cbcfe4..d90798f 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -24,12 +24,14 @@
#include <cutils/sched_policy.h>
#include <utils/Log.h>
+#include <utils/SystemClock.h>
#include <utils/threads.h>
#include <private/binder/binder_module.h>
#include <private/binder/Static.h>
#include <errno.h>
+#include <inttypes.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
@@ -434,12 +436,25 @@
pthread_mutex_lock(&mProcess->mThreadCountLock);
mProcess->mExecutingThreadsCount++;
+ if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads &&
+ mProcess->mStarvationStartTimeMs == 0) {
+ mProcess->mStarvationStartTimeMs = uptimeMillis();
+ }
pthread_mutex_unlock(&mProcess->mThreadCountLock);
result = executeCommand(cmd);
pthread_mutex_lock(&mProcess->mThreadCountLock);
mProcess->mExecutingThreadsCount--;
+ if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&
+ mProcess->mStarvationStartTimeMs != 0) {
+ int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs;
+ if (starvationTimeMs > 100) {
+ ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms",
+ mProcess->mMaxThreads, starvationTimeMs);
+ }
+ mProcess->mStarvationStartTimeMs = 0;
+ }
pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
pthread_mutex_unlock(&mProcess->mThreadCountLock);
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 33fe26c..f13f49f 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -40,12 +40,12 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#include <sys/types.h>
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
#define DEFAULT_MAX_BINDER_THREADS 15
-
-// ---------------------------------------------------------------------------
+// -------------------------------------------------------------------------
namespace android {
@@ -278,8 +278,9 @@
String8 ProcessState::makeBinderThreadName() {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
+ pid_t pid = getpid();
String8 name;
- name.appendFormat("Binder_%X", s);
+ name.appendFormat("Binder:%d_%X", pid, s);
return name;
}
@@ -342,6 +343,7 @@
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
+ , mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
diff --git a/libs/diskusage/dirsize.c b/libs/diskusage/dirsize.c
index 7576994..5b5ab70 100644
--- a/libs/diskusage/dirsize.c
+++ b/libs/diskusage/dirsize.c
@@ -24,16 +24,7 @@
int64_t stat_size(struct stat *s)
{
- int64_t blksize = s->st_blksize;
- // count actual blocks used instead of nominal file size
- int64_t size = s->st_blocks * 512;
-
- if (blksize) {
- /* round up to filesystem block size */
- size = (size + blksize - 1) & (~(blksize - 1));
- }
-
- return size;
+ return s->st_blocks * 512;
}
int64_t calculate_dir_size(int dfd)
@@ -51,9 +42,6 @@
while ((de = readdir(d))) {
const char *name = de->d_name;
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- size += stat_size(&s);
- }
if (de->d_type == DT_DIR) {
int subfd;
@@ -65,10 +53,17 @@
continue;
}
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ size += stat_size(&s);
+ }
subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
if (subfd >= 0) {
size += calculate_dir_size(subfd);
}
+ } else {
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ size += stat_size(&s);
+ }
}
}
closedir(d);
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index b591c4e..cbc8893 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -622,6 +622,10 @@
return NO_INIT;
}
+ if (maxAcquiredBuffers == mCore->mMaxAcquiredBufferCount) {
+ return NO_ERROR;
+ }
+
// The new maxAcquiredBuffers count should not be violated by the number
// of currently acquired buffers
int acquiredCount = 0;
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index cdece73..052de3d 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -200,6 +200,10 @@
}
mSlots[slot].mFence = Fence::NO_FENCE;
mSlots[slot].mEglDisplay = EGL_NO_DISPLAY;
+
+ if (mLastQueuedSlot == slot) {
+ mLastQueuedSlot = INVALID_BUFFER_SLOT;
+ }
}
void BufferQueueCore::freeAllBuffersLocked() {
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index bb8d39b..0b7ce17 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -101,6 +101,10 @@
return NO_INIT;
}
+ if (maxDequeuedBuffers == mCore->mMaxDequeuedBufferCount) {
+ return NO_ERROR;
+ }
+
// The new maxDequeuedBuffer count should not be violated by the number
// of currently dequeued buffers
int dequeuedCount = 0;
@@ -175,6 +179,10 @@
return NO_INIT;
}
+ if (async == mCore->mAsyncMode) {
+ return NO_ERROR;
+ }
+
if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
(async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
mCore->mMaxBufferCount) {
@@ -199,7 +207,9 @@
mCore->mAsyncMode = async;
VALIDATE_CONSISTENCY();
mCore->mDequeueCondition.broadcast();
- listener = mCore->mConsumerListener;
+ if (delta < 0) {
+ listener = mCore->mConsumerListener;
+ }
} // Autolock scope
// Call back without lock held
@@ -834,30 +844,31 @@
mCore->mQueue.push_back(item);
frameAvailableListener = mCore->mConsumerListener;
} else {
- // When the queue is not empty, we need to look at the front buffer
- // state to see if we need to replace it
- BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
- if (front->mIsDroppable) {
+ // When the queue is not empty, we need to look at the last buffer
+ // in the queue to see if we need to replace it
+ const BufferItem& last = mCore->mQueue.itemAt(
+ mCore->mQueue.size() - 1);
+ if (last.mIsDroppable) {
- if (!front->mIsStale) {
- mSlots[front->mSlot].mBufferState.freeQueued();
+ if (!last.mIsStale) {
+ mSlots[last.mSlot].mBufferState.freeQueued();
// After leaving shared buffer mode, the shared buffer will
// still be around. Mark it as no longer shared if this
// operation causes it to be free.
if (!mCore->mSharedBufferMode &&
- mSlots[front->mSlot].mBufferState.isFree()) {
- mSlots[front->mSlot].mBufferState.mShared = false;
+ mSlots[last.mSlot].mBufferState.isFree()) {
+ mSlots[last.mSlot].mBufferState.mShared = false;
}
// Don't put the shared buffer on the free list.
- if (!mSlots[front->mSlot].mBufferState.isShared()) {
- mCore->mActiveBuffers.erase(front->mSlot);
- mCore->mFreeBuffers.push_back(front->mSlot);
+ if (!mSlots[last.mSlot].mBufferState.isShared()) {
+ mCore->mActiveBuffers.erase(last.mSlot);
+ mCore->mFreeBuffers.push_back(last.mSlot);
}
}
// Overwrite the droppable buffer with the incoming one
- *front = item;
+ mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
frameReplacedListener = mCore->mConsumerListener;
} else {
mCore->mQueue.push_back(item);
@@ -867,6 +878,7 @@
mCore->mBufferHasBeenQueued = true;
mCore->mDequeueCondition.broadcast();
+ mCore->mLastQueuedSlot = slot;
output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
mCore->mTransformHint,
@@ -909,8 +921,8 @@
// third. In the event that frames take varying time, this makes a
// small trade-off in favor of latency rather than throughput.
mLastQueueBufferFence->waitForever("Throttling EGL Production");
- mLastQueueBufferFence = fence;
}
+ mLastQueueBufferFence = fence;
return NO_ERROR;
}
@@ -1356,6 +1368,24 @@
return NO_ERROR;
}
+status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+ sp<Fence>* outFence) {
+ ATRACE_CALL();
+ BQ_LOGV("getLastQueuedBuffer");
+
+ Mutex::Autolock lock(mCore->mMutex);
+ if (mCore->mLastQueuedSlot == BufferItem::INVALID_BUFFER_SLOT) {
+ *outBuffer = nullptr;
+ *outFence = Fence::NO_FENCE;
+ return NO_ERROR;
+ }
+
+ *outBuffer = mSlots[mCore->mLastQueuedSlot].mGraphicBuffer;
+ *outFence = mLastQueueBufferFence;
+
+ return NO_ERROR;
+}
+
void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
// If we're here, it means that a producer we were connected to died.
// We're guaranteed that we are still connected to it because we remove
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 7cdb8f4..c36fcad 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -54,6 +54,7 @@
SET_SHARED_BUFFER_MODE,
SET_AUTO_REFRESH,
SET_DEQUEUE_TIMEOUT,
+ GET_LAST_QUEUED_BUFFER,
};
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -379,6 +380,37 @@
}
return reply.readInt32();
}
+
+ virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+ sp<Fence>* outFence) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+ status_t result = remote()->transact(GET_LAST_QUEUED_BUFFER, data,
+ &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getLastQueuedBuffer failed to transact: %d", result);
+ return result;
+ }
+ result = reply.readInt32();
+ if (result != NO_ERROR) {
+ return result;
+ }
+ sp<GraphicBuffer> buffer(new GraphicBuffer);
+ result = reply.read(*buffer);
+ if (result != NO_ERROR) {
+ ALOGE("getLastQueuedBuffer failed to read buffer: %d", result);
+ return result;
+ }
+ sp<Fence> fence(new Fence);
+ result = reply.read(*fence);
+ if (result != NO_ERROR) {
+ ALOGE("getLastQueuedBuffer failed to read fence: %d", result);
+ return result;
+ }
+ *outBuffer = buffer;
+ *outFence = fence;
+ return result;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -590,6 +622,27 @@
reply->writeInt32(result);
return NO_ERROR;
}
+ case GET_LAST_QUEUED_BUFFER: {
+ CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+ sp<GraphicBuffer> buffer(nullptr);
+ sp<Fence> fence(Fence::NO_FENCE);
+ status_t result = getLastQueuedBuffer(&buffer, &fence);
+ reply->writeInt32(result);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply->write(*buffer);
+ if (result != NO_ERROR) {
+ ALOGE("getLastQueuedBuffer failed to write buffer: %d", result);
+ return result;
+ }
+ result = reply->write(*fence);
+ if (result != NO_ERROR) {
+ ALOGE("getLastQueuedBuffer failed to write fence: %d", result);
+ return result;
+ }
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index b4cbf84..a8b4fa8 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -34,6 +34,7 @@
#include <ui/DisplayInfo.h>
#include <ui/DisplayStatInfo.h>
+#include <ui/HdrCapabilities.h>
#include <utils/Log.h>
@@ -282,6 +283,28 @@
reply.read(*outStats);
return reply.readInt32();
}
+
+ virtual status_t getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) const {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ status_t result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("getHdrCapabilities failed to writeStrongBinder: %d", result);
+ return result;
+ }
+ result = remote()->transact(BnSurfaceComposer::GET_HDR_CAPABILITIES,
+ data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getHdrCapabilities failed to transact: %d", result);
+ return result;
+ }
+ result = reply.readInt32();
+ if (result == NO_ERROR) {
+ result = reply.readParcelable(outCapabilities);
+ }
+ return result;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -467,6 +490,23 @@
setPowerMode(display, mode);
return NO_ERROR;
}
+ case GET_HDR_CAPABILITIES: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("getHdrCapabilities failed to readStrongBinder: %d",
+ result);
+ return result;
+ }
+ HdrCapabilities capabilities;
+ result = getHdrCapabilities(display, &capabilities);
+ reply->writeInt32(result);
+ if (result == NO_ERROR) {
+ reply->writeParcelable(capabilities);
+ }
+ return NO_ERROR;
+ }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index e43342e..d1c576e 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -41,6 +41,7 @@
output.write(finalCrop);
output.writeStrongBinder(handle);
output.writeUint64(frameNumber);
+ output.writeInt32(overrideScalingMode);
output.write(transparentRegion);
return NO_ERROR;
}
@@ -68,6 +69,7 @@
input.read(finalCrop);
handle = input.readStrongBinder();
frameNumber = input.readUint64();
+ overrideScalingMode = input.readInt32();
input.read(transparentRegion);
return NO_ERROR;
}
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 0b2b942..0340d6b 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -35,8 +35,8 @@
namespace android {
// ----------------------------------------------------------------------------
-Sensor::Sensor()
- : mHandle(0), mType(0),
+Sensor::Sensor(const char * name)
+ : mName(name), mHandle(0), mType(0),
mMinValue(0), mMaxValue(0), mResolution(0),
mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
mFifoMaxEventCount(0), mRequiredAppOp(0),
@@ -272,6 +272,11 @@
break;
}
+ // Set DYNAMIC_SENSOR_MASK and ADDITIONAL_INFO_MASK flag here. Compatible with HAL 1_3.
+ if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
+ mFlags |= (hwSensor->flags & (DYNAMIC_SENSOR_MASK | ADDITIONAL_INFO_MASK));
+ }
+
// Set DATA_INJECTION flag here. Defined in HAL 1_4.
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_4) {
mFlags |= (hwSensor->flags & DATA_INJECTION_MASK);
@@ -390,6 +395,10 @@
return mFlags & SENSOR_FLAG_WAKE_UP;
}
+bool Sensor::isDynamicSensor() const {
+ return mFlags & SENSOR_FLAG_DYNAMIC_SENSOR;
+}
+
int32_t Sensor::getReportingMode() const {
return ((mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT);
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 76b62f1..b304633 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -127,6 +127,11 @@
return mGraphicBufferProducer->setDequeueTimeout(timeout);
}
+status_t Surface::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+ sp<Fence>* outFence) {
+ return mGraphicBufferProducer->getLastQueuedBuffer(outBuffer, outFence);
+}
+
int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
Surface* c = getSelf(window);
return c->setSwapInterval(interval);
@@ -480,6 +485,8 @@
mSharedBufferHasBeenQueued = true;
}
+ mQueueBufferCondition.broadcast();
+
return err;
}
@@ -1259,6 +1266,15 @@
return err;
}
+bool Surface::waitForNextFrame(uint64_t lastFrame, nsecs_t timeout) {
+ Mutex::Autolock lock(mMutex);
+ uint64_t currentFrame = mGraphicBufferProducer->getNextFrameNumber();
+ if (currentFrame > lastFrame) {
+ return true;
+ }
+ return mQueueBufferCondition.waitRelative(mMutex, timeout) == OK;
+}
+
namespace view {
status_t Surface::writeToParcel(Parcel* parcel) const {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 04b5446..e33cc37 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -163,6 +163,8 @@
status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
const sp<IBinder>& id, const sp<IBinder>& handle,
uint64_t frameNumber);
+ status_t setOverrideScalingMode(const sp<SurfaceComposerClient>& client,
+ const sp<IBinder>& id, int32_t overrideScalingMode);
void setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
@@ -414,6 +416,33 @@
return NO_ERROR;
}
+status_t Composer::setOverrideScalingMode(
+ const sp<SurfaceComposerClient>& client,
+ const sp<IBinder>& id, int32_t overrideScalingMode) {
+ Mutex::Autolock lock(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s) {
+ return BAD_INDEX;
+ }
+
+ switch (overrideScalingMode) {
+ case NATIVE_WINDOW_SCALING_MODE_FREEZE:
+ case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
+ case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
+ case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
+ case -1:
+ break;
+ default:
+ ALOGE("unknown scaling mode: %d",
+ overrideScalingMode);
+ return BAD_VALUE;
+ }
+
+ s->what |= layer_state_t::eOverrideScalingModeChanged;
+ s->overrideScalingMode = overrideScalingMode;
+ return NO_ERROR;
+}
+
// ---------------------------------------------------------------------------
DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) {
@@ -650,6 +679,12 @@
return getComposer().deferTransactionUntil(this, id, handle, frameNumber);
}
+status_t SurfaceComposerClient::setOverrideScalingMode(
+ const sp<IBinder>& id, int32_t overrideScalingMode) {
+ return getComposer().setOverrideScalingMode(
+ this, id, overrideScalingMode);
+}
+
// ----------------------------------------------------------------------------
void SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token,
@@ -722,6 +757,12 @@
return ComposerService::getComposerService()->getAnimationFrameStats(outStats);
}
+status_t SurfaceComposerClient::getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) {
+ return ComposerService::getComposerService()->getHdrCapabilities(display,
+ outCapabilities);
+}
+
// ----------------------------------------------------------------------------
status_t ScreenshotClient::capture(
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 184de71..314d83a 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -165,6 +165,12 @@
return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
}
+status_t SurfaceControl::setOverrideScalingMode(int32_t overrideScalingMode) {
+ status_t err = validate();
+ if (err < 0) return err;
+ return mClient->setOverrideScalingMode(mHandle, overrideScalingMode);
+}
+
status_t SurfaceControl::clearLayerFrameStats() const {
status_t err = validate();
if (err < 0) return err;
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 82df9a9..9876d94 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -796,4 +796,56 @@
ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
}
+TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
+ createBufferQueue();
+ sp<DummyConsumer> dc(new DummyConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+ IGraphicBufferProducer::QueueBufferOutput output;
+ ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+ NATIVE_WINDOW_API_CPU, false, &output));
+
+ // Dequeue and queue the first buffer, storing the handle
+ int slot = BufferQueue::INVALID_BUFFER_SLOT;
+ sp<Fence> fence;
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ sp<GraphicBuffer> firstBuffer;
+ ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
+
+ IGraphicBufferProducer::QueueBufferInput input(0ull, true,
+ HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+ ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+ // Dequeue a second buffer
+ slot = BufferQueue::INVALID_BUFFER_SLOT;
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ sp<GraphicBuffer> secondBuffer;
+ ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
+
+ // Ensure it's a new buffer
+ ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
+ secondBuffer->getNativeBuffer()->handle);
+
+ // Queue the second buffer
+ ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+ // Acquire and release both buffers
+ for (size_t i = 0; i < 2; ++i) {
+ BufferItem item;
+ ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
+ EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ }
+
+ // Make sure we got the second buffer back
+ sp<GraphicBuffer> returnedBuffer;
+ sp<Fence> returnedFence;
+ ASSERT_EQ(OK,
+ mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence));
+ ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
+ returnedBuffer->getNativeBuffer()->handle);
+}
+
} // namespace android
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index e4cdcab..ee6c093 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -40,12 +40,14 @@
GraphicBuffer.cpp \
GraphicBufferAllocator.cpp \
GraphicBufferMapper.cpp \
+ HdrCapabilities.cpp \
PixelFormat.cpp \
Rect.cpp \
Region.cpp \
UiConfig.cpp
LOCAL_SHARED_LIBRARIES := \
+ libbinder \
libcutils \
libhardware \
libsync \
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
new file mode 100644
index 0000000..511f68a
--- /dev/null
+++ b/libs/ui/HdrCapabilities.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ui/HdrCapabilities.h>
+
+#include <binder/Parcel.h>
+
+namespace android {
+
+status_t HdrCapabilities::writeToParcel(Parcel* parcel) const
+{
+ status_t result = parcel->writeInt32Vector(mSupportedHdrTypes);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->writeFloat(mMaxLuminance);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->writeFloat(mMaxAverageLuminance);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->writeFloat(mMinLuminance);
+ return result;
+}
+
+status_t HdrCapabilities::readFromParcel(const Parcel* parcel)
+{
+ status_t result = parcel->readInt32Vector(&mSupportedHdrTypes);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->readFloat(&mMaxLuminance);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->readFloat(&mMaxAverageLuminance);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->readFloat(&mMinLuminance);
+ return result;
+}
+
+} // namespace android
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 5d838e6..bef5f02 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -602,8 +602,8 @@
#define EGL_ANDROID_create_native_client_buffer 1
#define EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143
#define EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001
-#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID 0x00000002
-#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID 0x00000004
+#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002
+#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLClientBuffer eglCreateNativeClientBufferANDROID (const EGLint *attrib_list);
#else
@@ -616,6 +616,10 @@
#define EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C
#endif
+#ifndef EGL_KHR_mutable_render_buffer
+#define EGL_KHR_mutable_render_buffer 1
+#define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000
+#endif
#ifdef __cplusplus
}
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index e7703d8..217c821 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -115,6 +115,8 @@
"EGL_KHR_partial_update " // strongly recommended
"EGL_EXT_buffer_age " // strongly recommended with partial_update
"EGL_KHR_create_context_no_error "
+ "EGL_KHR_mutable_render_buffer "
+ "EGL_EXT_yuv_surface "
;
// extensions not exposed to applications but used by the ANDROID system
@@ -1814,21 +1816,17 @@
case EGL_NATIVE_BUFFER_USAGE_ANDROID:
if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
usage |= GRALLOC_USAGE_PROTECTED;
- // If we are using QCOM then add in extra bits. This
- // should be removed before launch. These correspond to:
- // USAGE_PRIVATE_MM_HEAP | USAGE_PRIVATE_UNCACHED
- usage |= 0x82000000;
}
- if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID) {
+ if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
usage |= GRALLOC_USAGE_HW_RENDER;
}
- if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID) {
+ if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
usage |= GRALLOC_USAGE_HW_TEXTURE;
}
// The buffer must be used for either a texture or a
// renderbuffer.
- if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID) &&
- (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID)) {
+ if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) &&
+ (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) {
return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
}
break;
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 6a9d7b6..e335a6c 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -44,9 +44,10 @@
static bool findExtension(const char* exts, const char* name, size_t nameLen) {
if (exts) {
- const char* match = strstr(exts, name);
- if (match && (match[nameLen] == '\0' || match[nameLen] == ' ')) {
- return true;
+ for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) {
+ if (match[nameLen] == '\0' || match[nameLen] == ' ') {
+ return true;
+ }
}
}
return false;
diff --git a/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt b/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt
new file mode 100644
index 0000000..a6fae80
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt
@@ -0,0 +1,197 @@
+Name
+
+ ANDROID_create_native_client_buffer
+
+Name Strings
+
+ EGL_ANDROID_create_native_client_buffer
+
+Contributors
+
+ Craig Donner
+
+Contact
+
+ Craig Donner, Google Inc. (cdonner 'at' google.com)
+
+Status
+
+ Draft
+
+Version
+
+ Version 1, January 19, 2016
+
+Number
+
+ EGL Extension #XXX
+
+Dependencies
+
+ Requires EGL 1.2.
+
+ EGL_ANDROID_image_native_buffer and EGL_KHR_image_base are required.
+
+ This extension is written against the wording of the EGL 1.2
+ Specification as modified by EGL_KHR_image_base and
+ EGL_ANDROID_image_native_buffer.
+
+Overview
+
+ This extension allows creating an EGLClientBuffer backed by an Android
+ window buffer (struct ANativeWindowBuffer) which can be later used to
+ create an EGLImage.
+
+New Types
+
+ None.
+
+New Procedures and Functions
+
+EGLClientBuffer eglCreateNativeClientBufferANDROID(
+ const EGLint *attrib_list)
+
+New Tokens
+
+ EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143
+ EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001
+ EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002
+ EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004
+
+Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors)
+
+ Add the following to section 2.5.1 "EGLImage Specification" (as modified by
+ the EGL_KHR_image_base and EGL_ANDROID_image_native_buffer specifications),
+ below the description of eglCreateImageKHR:
+
+ "The command
+
+ EGLClientBuffer eglCreateNativeClientBufferANDROID(
+ const EGLint *attrib_list)
+
+ may be used to create an EGLClientBuffer backed by an ANativeWindowBuffer
+ struct. EGL implementations must guarantee that the lifetime of the
+ returned EGLClientBuffer is at least as long as the EGLImage(s) it is bound
+ to, following the lifetime semantics described below in section 2.5.2; the
+ EGLClientBuffer must be destroyed no earlier than when all of its associated
+ EGLImages are destroyed by eglDestroyImageKHR. <attrib_list> is a list of
+ attribute-value pairs which is used to specify the dimensions, format, and
+ usage of the underlying buffer structure. If <attrib_list> is non-NULL, the
+ last attribute specified in the list must be EGL_NONE.
+
+ Attribute names accepted in <attrib_list> are shown in Table aaa,
+ together with the <target> for which each attribute name is valid, and
+ the default value used for each attribute if it is not included in
+ <attrib_list>.
+
+ +---------------------------------+----------------------+---------------+
+ | Attribute | Description | Default Value |
+ | | | |
+ +---------------------------------+----------------------+---------------+
+ | EGL_NONE | Marks the end of the | N/A |
+ | | attribute-value list | |
+ | EGL_WIDTH | The width of the | 0 |
+ | | buffer data | |
+ | EGL_HEIGHT | The height of the | 0 |
+ | | buffer data | |
+ | EGL_RED_SIZE | The bits of Red in | 0 |
+ | | the color buffer | |
+ | EGL_GREEN_SIZE | The bits of Green in | 0 |
+ | | the color buffer | |
+ | EGL_BLUE_SIZE | The bits of Blue in | 0 |
+ | | the color buffer | |
+ | EGL_ALPHA_SIZE | The bits of Alpha in | 0 |
+ | | the color buffer | |
+ | | buffer data | |
+ | EGL_NATIVE_BUFFER_USAGE_ANDROID | The usage bits of | 0 |
+ | | the buffer data | |
+ +---------------------------------+----------------------+---------------+
+ Table aaa. Legal attributes for eglCreateNativeClientBufferANDROID
+ <attrib_list> parameter.
+
+ The maximum width and height may depend on the amount of available memory,
+ which may also depend on the format and usage flags. The values of
+ EGL_RED_SIZE, EGL_GREEN_SIZE, and EGL_BLUE_SIZE must be non-zero and
+ correspond to a valid pixel format for the implementation. If EGL_ALPHA_SIZE
+ is non-zero then the combination of all four sizes must correspond to a
+ valid pixel format for the implementation. The
+ EGL_NATIVE_BUFFER_USAGE_ANDROID flag may include any of the following bits:
+
+ EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID: Indicates that the
+ created buffer must have a hardware-protected path to external display
+ sink. If a hardware-protected path is not available, then either don't
+ composite only this buffer (preferred) to the external sink, or (less
+ desirable) do not route the entire composition to the external sink.
+
+ EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID: The buffer will be
+ used to create a renderbuffer. This flag must not be set if
+ EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID is set.
+
+ EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID: The buffer will be used to
+ create a texture. This flag must not be set if
+ EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID is set.
+
+ Errors
+
+ If eglCreateNativeClientBufferANDROID fails, NULL will be returned, no
+ memory will be allocated, and one of the following errors will be
+ generated:
+
+ * If the value of EGL_WIDTH or EGL_HEIGHT is not positive, the error
+ EGL_BAD_PARAMETER is generated.
+
+ * If the combination of the values of EGL_RED_SIZE, EGL_GREEN_SIZE,
+ EGL_BLUE_SIZE, and EGL_ALPHA_SIZE is not a valid pixel format for the
+ EGL implementation, the error EGL_BAD_PARAMETER is generated.
+
+ * If the value of EGL_NATIVE_BUFFER_ANDROID is not a valid combination
+ of gralloc usage flags for the EGL implementation, or is incompatible
+ with the value of EGL_FORMAT, the error EGL_BAD_PARAMETER is
+ Generated.
+
+ * If both the EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID and
+ EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID are set in the value of
+ EGL_NATIVE_BUFFER_USAGE_ANDROID, the error EGL_BAD_PARAMETER is
+ Generated."
+
+Issues
+
+ 1. Should this extension define what combinations of formats and usage flags
+ EGL implementations are required to support?
+
+ RESOLVED: Partially.
+
+ The set of valid color combinations is implementation-specific and may
+ depend on additional EGL extensions, but generally RGB565 and RGBA888 should
+ be supported. The particular valid combinations for a given Android version
+ and implementation should be documented by that version.
+
+ 2. Should there be an eglDestroyNativeClientBufferANDROID to destroy the
+ client buffers created by this extension?
+
+ RESOLVED: No.
+
+ A destroy function would add several complications:
+
+ a) ANativeWindowBuffer is a reference counted object, may be used
+ outside of EGL.
+ b) The same buffer may back multiple EGLImages, though this usage may
+ result in undefined behavior.
+ c) The interactions between the lifetimes of EGLImages and their
+ EGLClientBuffers would become needlessly complex.
+
+ Because ANativeWindowBuffer is a reference counted object, implementations
+ of this extension should ensure the buffer has a lifetime at least as long
+ as a generated EGLImage (via EGL_ANDROID_image_native_buffer). The simplest
+ method is to increment the reference count of the buffer in
+ eglCreateImagKHR, and then decrement it in eglDestroyImageKHR. This should
+ ensure proper lifetime semantics.
+
+Revision History
+
+#2 (Craig Donner, April 15, 2016)
+ - Set color formats and usage bits explicitly using additional attributes,
+ and add value for new token EGL_NATIVE_BUFFER_USAGE_ANDROID.
+
+#1 (Craig Donner, January 19, 2016)
+ - Initial draft.
diff --git a/services/batteryservice/BatteryProperties.cpp b/services/batteryservice/BatteryProperties.cpp
index 07cc797..d89d4c9 100644
--- a/services/batteryservice/BatteryProperties.cpp
+++ b/services/batteryservice/BatteryProperties.cpp
@@ -41,6 +41,7 @@
batteryLevel = p->readInt32();
batteryVoltage = p->readInt32();
batteryTemperature = p->readInt32();
+ batteryChargeCounter = p->readInt32();
batteryTechnology = String8((p->readString16()).string());
return OK;
}
@@ -57,6 +58,7 @@
p->writeInt32(batteryLevel);
p->writeInt32(batteryVoltage);
p->writeInt32(batteryTemperature);
+ p->writeInt32(batteryChargeCounter);
p->writeString16(String16(batteryTechnology));
return OK;
}
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index eed14ab..3f69d49 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -1227,6 +1227,8 @@
int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE;
if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+ } else if (isWindowObscuredLocked(windowHandle)) {
+ outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
}
mTempTouchState.addOrUpdateWindow(
@@ -1264,6 +1266,8 @@
}
if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+ } else if (isWindowObscuredLocked(newTouchedWindowHandle)) {
+ targetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
}
// Update hover state.
@@ -1439,6 +1443,7 @@
== InputWindowInfo::TYPE_WALLPAPER) {
mTempTouchState.addOrUpdateWindow(windowHandle,
InputTarget::FLAG_WINDOW_IS_OBSCURED
+ | InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED
| InputTarget::FLAG_DISPATCH_AS_IS,
BitSet32(0));
}
@@ -1633,6 +1638,27 @@
return false;
}
+
+bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const {
+ int32_t displayId = windowHandle->getInfo()->displayId;
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
+ size_t numWindows = mWindowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
+ if (otherHandle == windowHandle) {
+ break;
+ }
+
+ const InputWindowInfo* otherInfo = otherHandle->getInfo();
+ if (otherInfo->displayId == displayId
+ && otherInfo->visible && !otherInfo->isTrustedOverlay()
+ && otherInfo->overlaps(windowInfo)) {
+ return true;
+ }
+ }
+ return false;
+}
+
String8 InputDispatcher::checkWindowReadyForMoreInputLocked(nsecs_t currentTime,
const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry,
const char* targetType) {
@@ -1907,6 +1933,9 @@
if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
}
+ if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED) {
+ dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+ }
if (!connection->inputState.trackMotion(motionEntry,
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 98355c6..1c054f5 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -89,7 +89,7 @@
/* This flag indicates that the event is being delivered to a foreground application. */
FLAG_FOREGROUND = 1 << 0,
- /* This flag indicates that the target of a MotionEvent is partly or wholly
+ /* This flag indicates that the MotionEvent falls within the area of the target
* obscured by another visible window above it. The motion event should be
* delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
FLAG_WINDOW_IS_OBSCURED = 1 << 1,
@@ -139,6 +139,12 @@
| FLAG_DISPATCH_AS_HOVER_EXIT
| FLAG_DISPATCH_AS_SLIPPERY_EXIT
| FLAG_DISPATCH_AS_SLIPPERY_ENTER,
+
+ /* This flag indicates that the target of a MotionEvent is partly or wholly
+ * obscured by another visible window above it. The motion event should be
+ * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
+ FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
+
};
// The input channel to be targeted.
@@ -1048,6 +1054,7 @@
const InjectionState* injectionState);
bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
int32_t x, int32_t y) const;
+ bool isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const;
String8 getApplicationWindowLabelLocked(const sp<InputApplicationHandle>& applicationHandle,
const sp<InputWindowHandle>& windowHandle);
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 8556c23..374a5de 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -697,6 +697,21 @@
return result;
}
+void InputReader::toggleCapsLockState(int32_t deviceId) {
+ ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+ if (deviceIndex < 0) {
+ ALOGW("Ignoring toggleCapsLock for unknown deviceId %" PRId32 ".", deviceId);
+ return;
+ }
+
+ InputDevice* device = mDevices.valueAt(deviceIndex);
+ if (device->isIgnored()) {
+ return;
+ }
+
+ device->updateMetaState(AKEYCODE_CAPS_LOCK);
+}
+
bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
AutoMutex _l(mLock);
@@ -1172,6 +1187,13 @@
return result;
}
+void InputDevice::updateMetaState(int32_t keyCode) {
+ size_t numMappers = mMappers.size();
+ for (size_t i = 0; i < numMappers; i++) {
+ mMappers[i]->updateMetaState(keyCode);
+ }
+}
+
void InputDevice::fadePointer() {
size_t numMappers = mMappers.size();
for (size_t i = 0; i < numMappers; i++) {
@@ -1880,6 +1902,9 @@
return 0;
}
+void InputMapper::updateMetaState(int32_t keyCode) {
+}
+
void InputMapper::updateExternalStylusState(const StylusState& state) {
}
@@ -2265,18 +2290,12 @@
}
}
- int32_t oldMetaState = mMetaState;
- int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
- bool metaStateChanged = oldMetaState != newMetaState;
- if (metaStateChanged) {
- mMetaState = newMetaState;
- updateLedState(false);
-
+ if (updateMetaStateIfNeeded(keyCode, down)) {
// If global meta state changed send it along with the key.
// If it has not changed then we'll use what keymap gave us,
// since key replacement logic might temporarily reset a few
// meta bits for given key.
- keyMetaState = newMetaState;
+ keyMetaState = mMetaState;
}
nsecs_t downTime = mDownTime;
@@ -2294,10 +2313,6 @@
policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
}
- if (metaStateChanged) {
- getContext()->updateGlobalMetaState();
- }
-
if (down && !isMetaKey(keyCode)) {
getContext()->fadePointer();
}
@@ -2335,6 +2350,24 @@
return mMetaState;
}
+void KeyboardInputMapper::updateMetaState(int32_t keyCode) {
+ updateMetaStateIfNeeded(keyCode, false);
+}
+
+bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
+ int32_t oldMetaState = mMetaState;
+ int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
+ bool metaStateChanged = oldMetaState != newMetaState;
+ if (metaStateChanged) {
+ mMetaState = newMetaState;
+ updateLedState(false);
+
+ getContext()->updateGlobalMetaState();
+ }
+
+ return metaStateChanged;
+}
+
void KeyboardInputMapper::resetLedState() {
initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index e554e57..076f3d6 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -359,6 +359,9 @@
virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
int32_t sw) = 0;
+ /* Toggle Caps Lock */
+ virtual void toggleCapsLockState(int32_t deviceId) = 0;
+
/* Determine whether physical keys exist for the given framework-domain key codes. */
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
@@ -461,6 +464,8 @@
virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
int32_t sw);
+ virtual void toggleCapsLockState(int32_t deviceId);
+
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
@@ -616,6 +621,7 @@
void cancelTouch(nsecs_t when);
int32_t getMetaState();
+ void updateMetaState(int32_t keyCode);
void fadePointer();
@@ -1031,6 +1037,7 @@
virtual void cancelTouch(nsecs_t when);
virtual int32_t getMetaState();
+ virtual void updateMetaState(int32_t keyCode);
virtual void updateExternalStylusState(const StylusState& state);
@@ -1116,6 +1123,7 @@
const int32_t* keyCodes, uint8_t* outFlags);
virtual int32_t getMetaState();
+ virtual void updateMetaState(int32_t keyCode);
private:
struct KeyDown {
@@ -1156,6 +1164,8 @@
void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode);
+ bool updateMetaStateIfNeeded(int32_t keyCode, bool down);
+
ssize_t findKeyDown(int32_t scanCode);
void resetLedState();
diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp
index fda3ffa..1b913c5 100644
--- a/services/inputflinger/InputWindow.cpp
+++ b/services/inputflinger/InputWindow.cpp
@@ -36,14 +36,16 @@
}
bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
- return x >= frameLeft && x <= frameRight
- && y >= frameTop && y <= frameBottom;
+ return x >= frameLeft && x < frameRight
+ && y >= frameTop && y < frameBottom;
}
bool InputWindowInfo::isTrustedOverlay() const {
return layoutParamsType == TYPE_INPUT_METHOD
|| layoutParamsType == TYPE_INPUT_METHOD_DIALOG
|| layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
+ || layoutParamsType == TYPE_STATUS_BAR
+ || layoutParamsType == TYPE_NAVIGATION_BAR
|| layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
}
@@ -51,6 +53,11 @@
return layoutParamsFlags & FLAG_SPLIT_TOUCH;
}
+bool InputWindowInfo::overlaps(const InputWindowInfo* other) const {
+ return frameLeft < other->frameRight && frameRight > other->frameLeft
+ && frameTop < other->frameBottom && frameBottom > other->frameTop;
+}
+
// --- InputWindowHandle ---
diff --git a/services/inputflinger/InputWindow.h b/services/inputflinger/InputWindow.h
index 42457ce..0ac7fce 100644
--- a/services/inputflinger/InputWindow.h
+++ b/services/inputflinger/InputWindow.h
@@ -146,6 +146,8 @@
bool isTrustedOverlay() const;
bool supportsSplitTouch() const;
+
+ bool overlaps(const InputWindowInfo* other) const;
};
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index 57c56a6..85e96d6 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -16,6 +16,7 @@
SensorEventConnection.cpp \
MostRecentEventLogger.cpp \
SensorRecord.cpp \
+ SensorList.cpp \
LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
index 7b1f346..005af18 100644
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ b/services/sensorservice/CorrectedGyroSensor.cpp
@@ -30,15 +30,26 @@
// ---------------------------------------------------------------------------
CorrectedGyroSensor::CorrectedGyroSensor(sensor_t const* list, size_t count)
- : mSensorDevice(SensorDevice::getInstance()),
- mSensorFusion(SensorFusion::getInstance())
-{
+ : VirtualSensor() {
for (size_t i=0 ; i<count ; i++) {
if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
mGyro = Sensor(list + i);
break;
}
}
+
+ const sensor_t sensor = {
+ .name = "Corrected Gyroscope Sensor",
+ .vendor = "AOSP",
+ .version = 1,
+ .handle = '_cgy',
+ .type = SENSOR_TYPE_GYROSCOPE,
+ .maxRange = mGyro.getMaxValue(),
+ .resolution = mGyro.getResolution(),
+ .power = mSensorFusion.getPowerUsage(),
+ .minDelay = mGyro.getMinDelay(),
+ };
+ mSensor = Sensor(&sensor);
}
bool CorrectedGyroSensor::process(sensors_event_t* outEvent,
@@ -66,21 +77,6 @@
return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
-Sensor CorrectedGyroSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Corrected Gyroscope Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 1;
- hwSensor.handle = '_cgy';
- hwSensor.type = SENSOR_TYPE_GYROSCOPE;
- hwSensor.maxRange = mGyro.getMaxValue();
- hwSensor.resolution = mGyro.getResolution();
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mGyro.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
-}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/CorrectedGyroSensor.h b/services/sensorservice/CorrectedGyroSensor.h
index 3c49c08..68acd43 100644
--- a/services/sensorservice/CorrectedGyroSensor.h
+++ b/services/sensorservice/CorrectedGyroSensor.h
@@ -31,19 +31,14 @@
class SensorDevice;
class SensorFusion;
-class CorrectedGyroSensor : public SensorInterface {
- SensorDevice& mSensorDevice;
- SensorFusion& mSensorFusion;
+class CorrectedGyroSensor : public VirtualSensor {
Sensor mGyro;
public:
CorrectedGyroSensor(sensor_t const* list, size_t count);
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
index a165a5b..9d8add1 100644
--- a/services/sensorservice/GravitySensor.cpp
+++ b/services/sensorservice/GravitySensor.cpp
@@ -29,16 +29,26 @@
namespace android {
// ---------------------------------------------------------------------------
-GravitySensor::GravitySensor(sensor_t const* list, size_t count)
- : mSensorDevice(SensorDevice::getInstance()),
- mSensorFusion(SensorFusion::getInstance())
-{
+GravitySensor::GravitySensor(sensor_t const* list, size_t count) {
for (size_t i=0 ; i<count ; i++) {
if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
mAccelerometer = Sensor(list + i);
break;
}
}
+
+ const sensor_t sensor = {
+ .name = "Gravity Sensor",
+ .vendor = "AOSP",
+ .version = 3,
+ .handle = '_grv',
+ .type = SENSOR_TYPE_GRAVITY,
+ .maxRange = GRAVITY_EARTH * 2,
+ .resolution = mAccelerometer.getResolution(),
+ .power = mSensorFusion.getPowerUsage(),
+ .minDelay = mSensorFusion.getMinDelay(),
+ };
+ mSensor = Sensor(&sensor);
}
bool GravitySensor::process(sensors_event_t* outEvent,
@@ -73,21 +83,6 @@
return mSensorFusion.setDelay(FUSION_NOMAG, ident, ns);
}
-Sensor GravitySensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Gravity Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 3;
- hwSensor.handle = '_grv';
- hwSensor.type = SENSOR_TYPE_GRAVITY;
- hwSensor.maxRange = GRAVITY_EARTH * 2;
- hwSensor.resolution = mAccelerometer.getResolution();
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
-}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/GravitySensor.h b/services/sensorservice/GravitySensor.h
index ac177c4..8e33a73 100644
--- a/services/sensorservice/GravitySensor.h
+++ b/services/sensorservice/GravitySensor.h
@@ -31,19 +31,14 @@
class SensorDevice;
class SensorFusion;
-class GravitySensor : public SensorInterface {
- SensorDevice& mSensorDevice;
- SensorFusion& mSensorFusion;
+class GravitySensor : public VirtualSensor {
Sensor mAccelerometer;
public:
GravitySensor(sensor_t const* list, size_t count);
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp
index d5f20d2..d1cd732 100644
--- a/services/sensorservice/LinearAccelerationSensor.cpp
+++ b/services/sensorservice/LinearAccelerationSensor.cpp
@@ -29,10 +29,21 @@
namespace android {
// ---------------------------------------------------------------------------
-LinearAccelerationSensor::LinearAccelerationSensor(sensor_t const* list, size_t count)
- : mSensorDevice(SensorDevice::getInstance()),
- mGravitySensor(list, count)
-{
+LinearAccelerationSensor::LinearAccelerationSensor(sensor_t const* list, size_t count) :
+ mGravitySensor(list, count) {
+ const Sensor &gsensor = mGravitySensor.getSensor();
+ const sensor_t sensor = {
+ .name = "Linear Acceleration Sensor",
+ .vendor = "AOSP",
+ .version = gsensor.getVersion(),
+ .handle = '_lin',
+ .type = SENSOR_TYPE_LINEAR_ACCELERATION,
+ .maxRange = gsensor.getMaxValue(),
+ .resolution = gsensor.getResolution(),
+ .power = gsensor.getPowerUsage(),
+ .minDelay = gsensor.getMinDelay(),
+ };
+ mSensor = Sensor(&sensor);
}
bool LinearAccelerationSensor::process(sensors_event_t* outEvent,
@@ -58,22 +69,6 @@
return mGravitySensor.setDelay(ident, handle, ns);
}
-Sensor LinearAccelerationSensor::getSensor() const {
- Sensor gsensor(mGravitySensor.getSensor());
- sensor_t hwSensor;
- hwSensor.name = "Linear Acceleration Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = gsensor.getVersion();
- hwSensor.handle = '_lin';
- hwSensor.type = SENSOR_TYPE_LINEAR_ACCELERATION;
- hwSensor.maxRange = gsensor.getMaxValue();
- hwSensor.resolution = gsensor.getResolution();
- hwSensor.power = gsensor.getPowerUsage();
- hwSensor.minDelay = gsensor.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
-}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/LinearAccelerationSensor.h b/services/sensorservice/LinearAccelerationSensor.h
index 5deb24f..428baa6 100644
--- a/services/sensorservice/LinearAccelerationSensor.h
+++ b/services/sensorservice/LinearAccelerationSensor.h
@@ -32,18 +32,15 @@
class SensorDevice;
class SensorFusion;
-class LinearAccelerationSensor : public SensorInterface {
- SensorDevice& mSensorDevice;
+class LinearAccelerationSensor : public VirtualSensor {
GravitySensor mGravitySensor;
virtual bool process(sensors_event_t* outEvent,
const sensors_event_t& event);
public:
LinearAccelerationSensor(sensor_t const* list, size_t count);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
index d55f336..ea5dbc9 100644
--- a/services/sensorservice/OrientationSensor.cpp
+++ b/services/sensorservice/OrientationSensor.cpp
@@ -29,13 +29,19 @@
namespace android {
// ---------------------------------------------------------------------------
-OrientationSensor::OrientationSensor()
- : mSensorDevice(SensorDevice::getInstance()),
- mSensorFusion(SensorFusion::getInstance())
-{
- // FIXME: instead of using the SensorFusion code, we should use
- // the SENSOR_TYPE_ROTATION_VECTOR instead. This way we could use the
- // HAL's implementation.
+OrientationSensor::OrientationSensor() {
+ const sensor_t sensor = {
+ .name = "Orientation Sensor",
+ .vendor = "AOSP",
+ .version = 1,
+ .handle = '_ypr',
+ .type = SENSOR_TYPE_ORIENTATION,
+ .maxRange = 360.0f,
+ .resolution = 1.0f/256.0f, // FIXME: real value here
+ .power = mSensorFusion.getPowerUsage(),
+ .minDelay = mSensorFusion.getMinDelay(),
+ };
+ mSensor = Sensor(&sensor);
}
bool OrientationSensor::process(sensors_event_t* outEvent,
@@ -73,21 +79,6 @@
return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
-Sensor OrientationSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Orientation Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 1;
- hwSensor.handle = '_ypr';
- hwSensor.type = SENSOR_TYPE_ORIENTATION;
- hwSensor.maxRange = 360.0f;
- hwSensor.resolution = 1.0f/256.0f; // FIXME: real value here
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
-}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/OrientationSensor.h b/services/sensorservice/OrientationSensor.h
index 855949d..30ff226 100644
--- a/services/sensorservice/OrientationSensor.h
+++ b/services/sensorservice/OrientationSensor.h
@@ -31,18 +31,12 @@
class SensorDevice;
class SensorFusion;
-class OrientationSensor : public SensorInterface {
- SensorDevice& mSensorDevice;
- SensorFusion& mSensorFusion;
-
+class OrientationSensor : public VirtualSensor {
public:
OrientationSensor();
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index 238845b..7b00f4d 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -27,11 +27,20 @@
namespace android {
// ---------------------------------------------------------------------------
-RotationVectorSensor::RotationVectorSensor(int mode)
- : mSensorDevice(SensorDevice::getInstance()),
- mSensorFusion(SensorFusion::getInstance()),
- mMode(mode)
-{
+RotationVectorSensor::RotationVectorSensor(int mode) :
+ mMode(mode) {
+ const sensor_t sensor = {
+ .name = getSensorName(),
+ .vendor = "AOSP",
+ .version = 3,
+ .handle = getSensorToken(),
+ .type = getSensorType(),
+ .maxRange = 1,
+ .resolution = 1.0f / (1<<24),
+ .power = mSensorFusion.getPowerUsage(),
+ .minDelay = mSensorFusion.getMinDelay(),
+ };
+ mSensor = Sensor(&sensor);
}
bool RotationVectorSensor::process(sensors_event_t* outEvent,
@@ -61,21 +70,6 @@
return mSensorFusion.setDelay(mMode, ident, ns);
}
-Sensor RotationVectorSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = getSensorName();
- hwSensor.vendor = "AOSP";
- hwSensor.version = 3;
- hwSensor.handle = getSensorToken();
- hwSensor.type = getSensorType();
- hwSensor.maxRange = 1;
- hwSensor.resolution = 1.0f / (1<<24);
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
-}
-
int RotationVectorSensor::getSensorType() const {
switch(mMode) {
case FUSION_9AXIS:
@@ -120,10 +114,19 @@
// ---------------------------------------------------------------------------
-GyroDriftSensor::GyroDriftSensor()
- : mSensorDevice(SensorDevice::getInstance()),
- mSensorFusion(SensorFusion::getInstance())
-{
+GyroDriftSensor::GyroDriftSensor() {
+ const sensor_t sensor = {
+ .name = "Gyroscope Bias (debug)",
+ .vendor = "AOSP",
+ .version = 1,
+ .handle = '_gbs',
+ .type = SENSOR_TYPE_ACCELEROMETER,
+ .maxRange = 1,
+ .resolution = 1.0f / (1<<24),
+ .power = mSensorFusion.getPowerUsage(),
+ .minDelay = mSensorFusion.getMinDelay(),
+ };
+ mSensor = Sensor(&sensor);
}
bool GyroDriftSensor::process(sensors_event_t* outEvent,
@@ -152,21 +155,6 @@
return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
-Sensor GyroDriftSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Gyroscope Bias (debug)";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 1;
- hwSensor.handle = '_gbs';
- hwSensor.type = SENSOR_TYPE_ACCELEROMETER;
- hwSensor.maxRange = 1;
- hwSensor.resolution = 1.0f / (1<<24);
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
-}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
index 1fc316b..3cc2248 100644
--- a/services/sensorservice/RotationVectorSensor.h
+++ b/services/sensorservice/RotationVectorSensor.h
@@ -32,23 +32,18 @@
namespace android {
// ---------------------------------------------------------------------------
-class RotationVectorSensor : public SensorInterface {
- SensorDevice& mSensorDevice;
- SensorFusion& mSensorFusion;
- int mMode;
+class RotationVectorSensor : public VirtualSensor {
+public:
+ RotationVectorSensor(int mode = FUSION_9AXIS);
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+protected:
+ const int mMode;
int getSensorType() const;
const char* getSensorName() const ;
int getSensorToken() const ;
-
-public:
- RotationVectorSensor(int mode = FUSION_9AXIS);
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
};
class GameRotationVectorSensor : public RotationVectorSensor {
@@ -61,18 +56,12 @@
GeoMagRotationVectorSensor() : RotationVectorSensor(FUSION_NOGYRO) {}
};
-class GyroDriftSensor : public SensorInterface {
- SensorDevice& mSensorDevice;
- SensorFusion& mSensorFusion;
-
+class GyroDriftSensor : public VirtualSensor {
public:
GyroDriftSensor();
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index ca26535..c1e1bad 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -21,6 +21,7 @@
#include "vec.h"
#include "SensorEventConnection.h"
+#include "SensorDevice.h"
namespace android {
@@ -88,15 +89,14 @@
bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
Mutex::Autolock _l(mConnectionLock);
- if (!canAccessSensor(mService->getSensorFromHandle(handle),
- "Tried adding", mOpPackageName)) {
+ sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+ if (si == nullptr ||
+ !canAccessSensor(si->getSensor(), "Tried adding", mOpPackageName) ||
+ mSensorInfo.indexOfKey(handle) >= 0) {
return false;
}
- if (mSensorInfo.indexOfKey(handle) < 0) {
- mSensorInfo.add(handle, FlushInfo());
- return true;
- }
- return false;
+ mSensorInfo.add(handle, FlushInfo());
+ return true;
}
bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
@@ -121,7 +121,8 @@
Mutex::Autolock _l(mConnectionLock);
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const int handle = mSensorInfo.keyAt(i);
- if (mService->getSensorFromHandle(handle).getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
+ sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+ if (si != nullptr && si->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
return true;
}
}
@@ -164,9 +165,9 @@
if (mDataInjectionMode) looper_flags |= ALOOPER_EVENT_INPUT;
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const int handle = mSensorInfo.keyAt(i);
- if (mService->getSensorFromHandle(handle).isWakeUpSensor()) {
+ sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+ if (si != nullptr && si->getSensor().isWakeUpSensor()) {
looper_flags |= ALOOPER_EVENT_INPUT;
- break;
}
}
@@ -385,11 +386,16 @@
// Loop through all the sensors for this connection and check if there are any pending
// flush complete events to be sent.
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+ const int handle = mSensorInfo.keyAt(i);
+ sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+ if (si == nullptr) {
+ continue;
+ }
+
FlushInfo& flushInfo = mSensorInfo.editValueAt(i);
while (flushInfo.mPendingFlushEventsToSend > 0) {
- const int sensor_handle = mSensorInfo.keyAt(i);
- flushCompleteEvent.meta_data.sensor = sensor_handle;
- bool wakeUpSensor = mService->getSensorFromHandle(sensor_handle).isWakeUpSensor();
+ flushCompleteEvent.meta_data.sensor = handle;
+ bool wakeUpSensor = si->getSensor().isWakeUpSensor();
if (wakeUpSensor) {
++mWakeLockRefCount;
flushCompleteEvent.flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
@@ -544,37 +550,41 @@
unsigned char buf[sizeof(sensors_event_t)];
ssize_t numBytesRead = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
{
- Mutex::Autolock _l(mConnectionLock);
- if (numBytesRead == sizeof(sensors_event_t)) {
- if (!mDataInjectionMode) {
- ALOGE("Data injected in normal mode, dropping event"
- "package=%s uid=%d", mPackageName.string(), mUid);
- // Unregister call backs.
- return 0;
- }
- SensorDevice& dev(SensorDevice::getInstance());
- sensors_event_t sensor_event;
- memset(&sensor_event, 0, sizeof(sensor_event));
- memcpy(&sensor_event, buf, sizeof(sensors_event_t));
- Sensor sensor = mService->getSensorFromHandle(sensor_event.sensor);
- sensor_event.type = sensor.getType();
- dev.injectSensorData(&sensor_event);
+ Mutex::Autolock _l(mConnectionLock);
+ if (numBytesRead == sizeof(sensors_event_t)) {
+ if (!mDataInjectionMode) {
+ ALOGE("Data injected in normal mode, dropping event"
+ "package=%s uid=%d", mPackageName.string(), mUid);
+ // Unregister call backs.
+ return 0;
+ }
+ sensors_event_t sensor_event;
+ memcpy(&sensor_event, buf, sizeof(sensors_event_t));
+ sp<SensorInterface> si =
+ mService->getSensorInterfaceFromHandle(sensor_event.sensor);
+ if (si == nullptr) {
+ return 1;
+ }
+
+ SensorDevice& dev(SensorDevice::getInstance());
+ sensor_event.type = si->getSensor().getType();
+ dev.injectSensorData(&sensor_event);
#if DEBUG_CONNECTIONS
- ++mEventsReceived;
+ ++mEventsReceived;
#endif
- } else if (numBytesRead == sizeof(uint32_t)) {
- uint32_t numAcks = 0;
- memcpy(&numAcks, buf, numBytesRead);
- // Sanity check to ensure there are no read errors in recv, numAcks is always
- // within the range and not zero. If any of the above don't hold reset
- // mWakeLockRefCount to zero.
- if (numAcks > 0 && numAcks < mWakeLockRefCount) {
- mWakeLockRefCount -= numAcks;
- } else {
- mWakeLockRefCount = 0;
- }
+ } else if (numBytesRead == sizeof(uint32_t)) {
+ uint32_t numAcks = 0;
+ memcpy(&numAcks, buf, numBytesRead);
+ // Sanity check to ensure there are no read errors in recv, numAcks is always
+ // within the range and not zero. If any of the above don't hold reset
+ // mWakeLockRefCount to zero.
+ if (numAcks > 0 && numAcks < mWakeLockRefCount) {
+ mWakeLockRefCount -= numAcks;
+ } else {
+ mWakeLockRefCount = 0;
+ }
#if DEBUG_CONNECTIONS
- mTotalAcksReceived += numAcks;
+ mTotalAcksReceived += numAcks;
#endif
} else {
// Read error, reset wakelock refcount.
@@ -601,7 +611,11 @@
size_t fifoWakeUpSensors = 0;
size_t fifoNonWakeUpSensors = 0;
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
- const Sensor& sensor = mService->getSensorFromHandle(mSensorInfo.keyAt(i));
+ sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(mSensorInfo.keyAt(i));
+ if (si == nullptr) {
+ continue;
+ }
+ const Sensor& sensor = si->getSensor();
if (sensor.getFifoReservedEventCount() == sensor.getFifoMaxEventCount()) {
// Each sensor has a reserved fifo. Sum up the fifo sizes for all wake up sensors and
// non wake_up sensors.
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
index 970220b..cb24229 100644
--- a/services/sensorservice/SensorInterface.cpp
+++ b/services/sensorservice/SensorInterface.cpp
@@ -14,24 +14,30 @@
* limitations under the License.
*/
+#include "SensorInterface.h"
+#include "SensorDevice.h"
+#include "SensorFusion.h"
+
#include <stdint.h>
#include <sys/types.h>
-#include "SensorInterface.h"
-
namespace android {
// ---------------------------------------------------------------------------
-SensorInterface::~SensorInterface()
-{
+namespace {
+const sensor_t DUMMY_SENSOR = {
+ .name = "", .vendor = "", .stringType = "", .requiredPermission = ""};
+} //unnamed namespace
+
+BaseSensor::BaseSensor(const sensor_t& sensor) :
+ mSensorDevice(SensorDevice::getInstance()),
+ mSensor(&sensor, mSensorDevice.getHalDeviceVersion()) {
}
// ---------------------------------------------------------------------------
-HardwareSensor::HardwareSensor(const sensor_t& sensor)
- : mSensorDevice(SensorDevice::getInstance()),
- mSensor(&sensor, mSensorDevice.getHalDeviceVersion())
-{
+HardwareSensor::HardwareSensor(const sensor_t& sensor):
+ BaseSensor(sensor) {
}
HardwareSensor::~HardwareSensor() {
@@ -65,10 +71,9 @@
mSensorDevice.autoDisable(ident, handle);
}
-Sensor HardwareSensor::getSensor() const {
- return mSensor;
+VirtualSensor::VirtualSensor() :
+ BaseSensor(DUMMY_SENSOR), mSensorFusion(SensorFusion::getInstance()) {
}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
index 3e76377..d1cee41 100644
--- a/services/sensorservice/SensorInterface.h
+++ b/services/sensorservice/SensorInterface.h
@@ -17,53 +17,61 @@
#ifndef ANDROID_SENSOR_INTERFACE_H
#define ANDROID_SENSOR_INTERFACE_H
-#include <stdint.h>
-#include <sys/types.h>
-
#include <gui/Sensor.h>
-
-#include "SensorDevice.h"
+#include <utils/RefBase.h>
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
+class SensorDevice;
+class SensorFusion;
-class SensorInterface {
+class SensorInterface : public VirtualLightRefBase {
public:
- virtual ~SensorInterface();
+ virtual ~SensorInterface() {}
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event) = 0;
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) = 0;
virtual status_t activate(void* ident, bool enabled) = 0;
virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0;
+ virtual status_t batch(void* ident, int handle, int /*flags*/, int64_t samplingPeriodNs,
+ int64_t maxBatchReportLatencyNs) = 0;
+
+ virtual status_t flush(void* /*ident*/, int /*handle*/) = 0;
+
+ virtual const Sensor& getSensor() const = 0;
+ virtual bool isVirtual() const = 0;
+ virtual void autoDisable(void* /*ident*/, int /*handle*/) = 0;
+};
+
+class BaseSensor : public SensorInterface {
+public:
+ BaseSensor(const sensor_t& sensor);
// Not all sensors need to support batching.
- virtual status_t batch(void* ident, int handle, int /*flags*/, int64_t samplingPeriodNs,
- int64_t maxBatchReportLatencyNs) {
+ virtual status_t batch(void* ident, int handle, int, int64_t samplingPeriodNs,
+ int64_t maxBatchReportLatencyNs) override {
if (maxBatchReportLatencyNs == 0) {
return setDelay(ident, handle, samplingPeriodNs);
}
return -EINVAL;
}
- virtual status_t flush(void* /*ident*/, int /*handle*/) {
+ virtual status_t flush(void* /*ident*/, int /*handle*/) override {
return -EINVAL;
}
- virtual Sensor getSensor() const = 0;
- virtual bool isVirtual() const = 0;
- virtual void autoDisable(void* /*ident*/, int /*handle*/) { }
+ virtual const Sensor& getSensor() const override { return mSensor; }
+ virtual void autoDisable(void* /*ident*/, int /*handle*/) override { }
+protected:
+ SensorDevice& mSensorDevice;
+ Sensor mSensor;
};
// ---------------------------------------------------------------------------
-class HardwareSensor : public SensorInterface
-{
- SensorDevice& mSensorDevice;
- Sensor mSensor;
-
+class HardwareSensor : public BaseSensor {
public:
HardwareSensor(const sensor_t& sensor);
@@ -72,14 +80,22 @@
virtual bool process(sensors_event_t* outEvent,
const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
+ virtual status_t activate(void* ident, bool enabled) override;
virtual status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
- int64_t maxBatchReportLatencyNs);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual status_t flush(void* ident, int handle);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return false; }
- virtual void autoDisable(void *ident, int handle);
+ int64_t maxBatchReportLatencyNs) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual status_t flush(void* ident, int handle) override;
+ virtual bool isVirtual() const override { return false; }
+ virtual void autoDisable(void *ident, int handle) override;
+};
+
+class VirtualSensor : public BaseSensor
+{
+public:
+ VirtualSensor();
+ virtual bool isVirtual() const override { return true; }
+protected:
+ SensorFusion& mSensorFusion;
};
diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp
new file mode 100644
index 0000000..c23e21f
--- /dev/null
+++ b/services/sensorservice/SensorList.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SensorList.h"
+
+#include <hardware/sensors.h>
+#include <utils/String8.h>
+
+namespace android {
+namespace SensorServiceUtil {
+
+const Sensor SensorList::mNonSensor = Sensor("unknown");
+
+bool SensorList::add(
+ int handle, SensorInterface* si, bool isForDebug, bool isVirtual) {
+ std::lock_guard<std::mutex> lk(mLock);
+ if (handle == si->getSensor().getHandle() &&
+ mUsedHandle.insert(handle).second) {
+ // will succeed as the mUsedHandle does not have this handle
+ mHandleMap.emplace(handle, Entry(si, isForDebug, isVirtual));
+ return true;
+ }
+ // handle exist already or handle mismatch
+ return false;
+}
+
+bool SensorList::remove(int handle) {
+ std::lock_guard<std::mutex> lk(mLock);
+ auto entry = mHandleMap.find(handle);
+ if (entry != mHandleMap.end()) {
+ mHandleMap.erase(entry);
+ return true;
+ }
+ return false;
+}
+
+String8 SensorList::getName(int handle) const {
+ return getOne<String8>(
+ handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getName();},
+ mNonSensor.getName());
+}
+
+sp<SensorInterface> SensorList::getInterface(int handle) const {
+ return getOne<sp<SensorInterface>>(
+ handle, [] (const Entry& e) -> sp<SensorInterface> {return e.si;}, nullptr);
+}
+
+
+bool SensorList::isNewHandle(int handle) const {
+ std::lock_guard<std::mutex> lk(mLock);
+ return mUsedHandle.find(handle) == mUsedHandle.end();
+}
+
+const Vector<Sensor> SensorList::getUserSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (!e.isForDebug && !e.si->getSensor().isDynamicSensor()) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+const Vector<Sensor> SensorList::getUserDebugSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (!e.si->getSensor().isDynamicSensor()) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+const Vector<Sensor> SensorList::getDynamicSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (!e.isForDebug && e.si->getSensor().isDynamicSensor()) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+const Vector<Sensor> SensorList::getVirtualSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (e.isVirtual) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+std::string SensorList::dump() const {
+ String8 result;
+
+ result.append("Sensor List:\n");
+ forEachSensor([&result] (const Sensor& s) -> bool {
+ result.appendFormat(
+ "%-15s| %-10s| version=%d |%-20s| 0x%08x | \"%s\" | type=%d |",
+ s.getName().string(),
+ s.getVendor().string(),
+ s.getVersion(),
+ s.getStringType().string(),
+ s.getHandle(),
+ s.getRequiredPermission().string(),
+ s.getType());
+
+ const int reportingMode = s.getReportingMode();
+ if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
+ result.append(" continuous | ");
+ } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
+ result.append(" on-change | ");
+ } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
+ result.append(" one-shot | ");
+ } else if (reportingMode == AREPORTING_MODE_SPECIAL_TRIGGER) {
+ result.append(" special-trigger | ");
+ } else {
+ result.append(" unknown-mode | ");
+ }
+
+ if (s.getMaxDelay() > 0) {
+ result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
+ } else {
+ result.appendFormat("maxDelay=%dus | ", s.getMaxDelay());
+ }
+
+ if (s.getMinDelay() > 0) {
+ result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
+ } else {
+ result.appendFormat("minDelay=%dus | ", s.getMinDelay());
+ }
+
+ if (s.getFifoMaxEventCount() > 0) {
+ result.appendFormat("FifoMax=%d events | ",
+ s.getFifoMaxEventCount());
+ } else {
+ result.append("no batching | ");
+ }
+
+ if (s.isWakeUpSensor()) {
+ result.appendFormat("wakeUp | ");
+ } else {
+ result.appendFormat("non-wakeUp | ");
+ }
+
+ result.append("\n");
+ return true;
+ });
+ return std::string(result.string());
+}
+
+SensorList::~SensorList() {
+}
+
+} // namespace SensorServiceUtil
+} // namespace android
+
diff --git a/services/sensorservice/SensorList.h b/services/sensorservice/SensorList.h
new file mode 100644
index 0000000..ffde619
--- /dev/null
+++ b/services/sensorservice/SensorList.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSOR_LIST_H
+#define ANDROID_SENSOR_LIST_H
+
+#include "SensorInterface.h"
+
+#include <gui/Sensor.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <mutex>
+#include <map>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+namespace android {
+class SensorInterface;
+
+namespace SensorServiceUtil {
+
+class Dumpable {
+public:
+ virtual std::string dump() const;
+ virtual void setFormat(std::string ) {}
+ virtual ~Dumpable() {}
+};
+
+class SensorList : public Dumpable {
+public:
+ // After SensorInterface * is added into SensorList, it can be assumed that SensorList own the
+ // object it pointed to and the object should not be released elsewhere.
+ bool add(int handle, SensorInterface* si, bool isForDebug = false, bool isVirtual = false);
+
+ // After a handle is removed, the object that SensorInterface * pointing to may get deleted if
+ // no more sp<> of the same object exist.
+ bool remove(int handle);
+
+ inline bool hasAnySensor() const { return mHandleMap.size() > 0;}
+
+ //helper functions
+ const Vector<Sensor> getUserSensors() const;
+ const Vector<Sensor> getUserDebugSensors() const;
+ const Vector<Sensor> getDynamicSensors() const;
+ const Vector<Sensor> getVirtualSensors() const;
+
+ String8 getName(int handle) const;
+ sp<SensorInterface> getInterface(int handle) const;
+ bool isNewHandle(int handle) const;
+
+ // Iterate through Sensor in sensor list and perform operation f on each Sensor object.
+ //
+ // TF is a function with the signature:
+ // bool f(const Sensor &);
+ // A return value of 'false' stops the iteration immediately.
+ //
+ // Note: in the function f, it is illegal to make calls to member functions of the same
+ // SensorList object on which forEachSensor is invoked.
+ template <typename TF>
+ void forEachSensor(const TF& f) const;
+
+ const Sensor& getNonSensor() const { return mNonSensor;}
+
+ // Dumpable interface
+ virtual std::string dump() const override;
+
+ virtual ~SensorList();
+private:
+ struct Entry {
+ sp<SensorInterface> si;
+ const bool isForDebug;
+ const bool isVirtual;
+ Entry(SensorInterface* si_, bool debug_, bool virtual_) :
+ si(si_), isForDebug(debug_), isVirtual(virtual_) {
+ }
+ };
+
+ const static Sensor mNonSensor; //.getName() == "unknown",
+
+ // Iterate through Entry in sensor list and perform operation f on each Entry.
+ //
+ // TF is a function with the signature:
+ // bool f(const Entry &);
+ // A return value of 'false' stops the iteration over entries immediately.
+ //
+ // Note: in the function being passed in, it is illegal to make calls to member functions of the
+ // same SensorList object on which forEachSensor is invoked.
+ template <typename TF>
+ void forEachEntry(const TF& f) const;
+
+ template <typename T, typename TF>
+ T getOne(int handle, const TF& accessor, T def = T()) const;
+
+ mutable std::mutex mLock;
+ std::map<int, Entry> mHandleMap;
+ std::unordered_set<int> mUsedHandle;
+};
+
+template <typename TF>
+void SensorList::forEachSensor(const TF& f) const {
+ // lock happens in forEachEntry
+ forEachEntry([&f] (const Entry& e) -> bool { return f(e.si->getSensor());});
+}
+
+template <typename TF>
+void SensorList::forEachEntry(const TF& f) const {
+ std::lock_guard<std::mutex> lk(mLock);
+
+ for (auto&& i : mHandleMap) {
+ if (!f(i.second)){
+ break;
+ }
+ }
+}
+
+template <typename T, typename TF>
+T SensorList::getOne(int handle, const TF& accessor, T def) const {
+ std::lock_guard<std::mutex> lk(mLock);
+ auto i = mHandleMap.find(handle);
+ if (i != mHandleMap.end()) {
+ return accessor(i->second);
+ } else {
+ return def;
+ }
+}
+
+} // namespace SensorServiceUtil
+} // namespace android
+
+#endif // ANDROID_SENSOR_LIST_H
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 66ef4eb..b7a8740 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -33,6 +33,7 @@
#include "OrientationSensor.h"
#include "RotationVectorSensor.h"
#include "SensorFusion.h"
+#include "SensorInterface.h"
#include "SensorService.h"
#include "SensorEventConnection.h"
@@ -65,12 +66,10 @@
SensorService::SensorService()
: mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
- mWakeLockAcquired(false)
-{
+ mWakeLockAcquired(false) {
}
-void SensorService::onFirstRef()
-{
+void SensorService::onFirstRef() {
ALOGD("nuSensorService starting...");
SensorDevice& dev(SensorDevice::getInstance());
@@ -127,78 +126,51 @@
// registered)
SensorFusion::getInstance();
- // build the sensor list returned to users
- mUserSensorList = mSensorList;
-
if (hasGyro && hasAccel && hasMag) {
// Add Android virtual sensors if they're not already
// available in the HAL
- Sensor aSensor;
+ bool needRotationVector =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) != 0;
- aSensor = registerVirtualSensor( new RotationVectorSensor() );
- if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
- mUserSensorList.add(aSensor);
- }
+ registerSensor(new RotationVectorSensor(), !needRotationVector, true);
+ registerSensor(new OrientationSensor(), !needRotationVector, true);
- aSensor = registerVirtualSensor( new OrientationSensor() );
- if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
- // if we are doing our own rotation-vector, also add
- // the orientation sensor and remove the HAL provided one.
- mUserSensorList.replaceAt(aSensor, orientationIndex);
- }
+ bool needLinearAcceleration =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) != 0;
- aSensor = registerVirtualSensor(
- new LinearAccelerationSensor(list, count) );
- if (virtualSensorsNeeds &
- (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
- mUserSensorList.add(aSensor);
- }
+ registerSensor(new LinearAccelerationSensor(list, count),
+ !needLinearAcceleration, true);
- // virtual debugging sensors are not added to mUserSensorList
- registerVirtualSensor( new CorrectedGyroSensor(list, count) );
- registerVirtualSensor( new GyroDriftSensor() );
+ // virtual debugging sensors are not for user
+ registerSensor( new CorrectedGyroSensor(list, count), true, true);
+ registerSensor( new GyroDriftSensor(), true, true);
}
if (hasAccel && hasGyro) {
- Sensor aSensor;
+ bool needGravitySensor = (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) != 0;
+ registerSensor(new GravitySensor(list, count), !needGravitySensor, true);
- aSensor = registerVirtualSensor(
- new GravitySensor(list, count) );
- if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
- mUserSensorList.add(aSensor);
- }
-
- aSensor = registerVirtualSensor(
- new GameRotationVectorSensor() );
- if (virtualSensorsNeeds &
- (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) {
- mUserSensorList.add(aSensor);
- }
+ bool needGameRotationVector =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) != 0;
+ registerSensor(new GameRotationVectorSensor(), !needGameRotationVector, true);
}
if (hasAccel && hasMag) {
- Sensor aSensor;
-
- aSensor = registerVirtualSensor(
- new GeoMagRotationVectorSensor() );
- if (virtualSensorsNeeds &
- (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR)) {
- mUserSensorList.add(aSensor);
- }
+ bool needGeoMagRotationVector =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR)) != 0;
+ registerSensor(new GeoMagRotationVectorSensor(), !needGeoMagRotationVector, true);
}
- // debugging sensor list
- mUserSensorListDebug = mSensorList;
-
// Check if the device really supports batching by looking at the FIFO event
// counts for each sensor.
bool batchingSupported = false;
- for (size_t i = 0; i < mSensorList.size(); ++i) {
- if (mSensorList[i].getFifoMaxEventCount() > 0) {
- batchingSupported = true;
- break;
- }
- }
+ mSensors.forEachSensor(
+ [&batchingSupported] (const Sensor& s) -> bool {
+ if (s.getFifoMaxEventCount() > 0) {
+ batchingSupported = true;
+ }
+ return !batchingSupported;
+ });
if (batchingSupported) {
// Increase socket buffer size to a max of 100 KB for batching capabilities.
@@ -244,65 +216,38 @@
}
}
-Sensor SensorService::registerSensor(SensorInterface* s)
-{
- const Sensor sensor(s->getSensor());
- // add to the sensor list (returned to clients)
- mSensorList.add(sensor);
- // add to our handle->SensorInterface mapping
- mSensorMap.add(sensor.getHandle(), s);
- // create an entry in the mLastEventSeen array
- mLastEventSeen.add(sensor.getHandle(), NULL);
-
- return sensor;
+const Sensor& SensorService::registerSensor(SensorInterface* s, bool isDebug, bool isVirtual) {
+ int handle = s->getSensor().getHandle();
+ if (mSensors.add(handle, s, isDebug, isVirtual)){
+ mLastEventSeen.add(handle, nullptr);
+ return s->getSensor();
+ } else {
+ return mSensors.getNonSensor();
+ }
}
-Sensor SensorService::registerDynamicSensor(SensorInterface* s)
-{
- Sensor sensor = registerSensor(s);
- mDynamicSensorList.add(sensor);
- return sensor;
+const Sensor& SensorService::registerDynamicSensor(SensorInterface* s, bool isDebug) {
+ return registerSensor(s, isDebug);
}
bool SensorService::unregisterDynamicSensor(int handle) {
- bool found = false;
-
- for (size_t i=0 ; i<mSensorList.size() ; i++) {
- if (mSensorList[i].getHandle() == handle) {
- mSensorList.removeAt(i);
- found = true;
- break;
- }
+ bool ret = mSensors.remove(handle);
+ MostRecentEventLogger *buf = mLastEventSeen.valueFor(handle);
+ if (buf) {
+ delete buf;
}
-
- if (found) {
- for (size_t i=0 ; i<mDynamicSensorList.size() ; i++) {
- if (mDynamicSensorList[i].getHandle() == handle) {
- mDynamicSensorList.removeAt(i);
- }
- }
-
- mSensorMap.removeItem(handle);
- mLastEventSeen.removeItem(handle);
- }
- return found;
+ mLastEventSeen.removeItem(handle);
+ return ret;
}
-Sensor SensorService::registerVirtualSensor(SensorInterface* s)
-{
- Sensor sensor = registerSensor(s);
- mVirtualSensorList.add( s );
- return sensor;
+const Sensor& SensorService::registerVirtualSensor(SensorInterface* s, bool isDebug) {
+ return registerSensor(s, isDebug, true);
}
-SensorService::~SensorService()
-{
- for (size_t i=0 ; i<mSensorMap.size() ; i++)
- delete mSensorMap.valueAt(i);
+SensorService::~SensorService() {
}
-status_t SensorService::dump(int fd, const Vector<String16>& args)
-{
+status_t SensorService::dump(int fd, const Vector<String16>& args) {
String8 result;
if (!PermissionCache::checkCallingPermission(sDump)) {
result.appendFormat("Permission Denial: can't dump SensorService from pid=%d, uid=%d\n",
@@ -363,73 +308,31 @@
// Transition to data injection mode supported only from NORMAL mode.
return INVALID_OPERATION;
}
- } else if (mSensorList.size() == 0) {
+ } else if (!mSensors.hasAnySensor()) {
result.append("No Sensors on the device\n");
} else {
// Default dump the sensor list and debugging information.
- result.append("Sensor List:\n");
- for (size_t i=0 ; i<mSensorList.size() ; i++) {
- const Sensor& s(mSensorList[i]);
- result.appendFormat(
- "%-15s| %-10s| version=%d |%-20s| 0x%08x | \"%s\" | type=%d |",
- s.getName().string(),
- s.getVendor().string(),
- s.getVersion(),
- s.getStringType().string(),
- s.getHandle(),
- s.getRequiredPermission().string(),
- s.getType());
+ //
+ result.append(mSensors.dump().c_str());
- const int reportingMode = s.getReportingMode();
- if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
- result.append(" continuous | ");
- } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
- result.append(" on-change | ");
- } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
- result.append(" one-shot | ");
- } else {
- result.append(" special-trigger | ");
- }
-
- if (s.getMaxDelay() > 0) {
- result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
- } else {
- result.appendFormat("maxDelay=%dus |", s.getMaxDelay());
- }
-
- if (s.getMinDelay() > 0) {
- result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
- } else {
- result.appendFormat("minDelay=%dus |", s.getMinDelay());
- }
-
- if (s.getFifoMaxEventCount() > 0) {
- result.appendFormat("FifoMax=%d events | ",
- s.getFifoMaxEventCount());
- } else {
- result.append("no batching | ");
- }
-
- if (s.isWakeUpSensor()) {
- result.appendFormat("wakeUp | ");
- } else {
- result.appendFormat("non-wakeUp | ");
- }
-
- int bufIndex = mLastEventSeen.indexOfKey(s.getHandle());
- if (bufIndex >= 0) {
- const MostRecentEventLogger* buf = mLastEventSeen.valueAt(bufIndex);
- if (buf != NULL && s.getRequiredPermission().isEmpty()) {
- buf->printBuffer(result);
- } else {
- result.append("last=<> \n");
- }
- }
- result.append("\n");
- }
SensorFusion::getInstance().dump(result);
SensorDevice::getInstance().dump(result);
+ result.append("Recent Sensor events:\n");
+ auto& lastEvents = mLastEventSeen;
+ mSensors.forEachSensor([&result, &lastEvents] (const Sensor& s) -> bool {
+ int bufIndex = lastEvents.indexOfKey(s.getHandle());
+ if (bufIndex >= 0) {
+ const MostRecentEventLogger* buf = lastEvents.valueAt(bufIndex);
+ if (buf != nullptr && s.getRequiredPermission().isEmpty()) {
+ result.appendFormat("%s (handle:0x%08x): ",
+ s.getName().string(), s.getHandle());
+ buf->printBuffer(result);
+ }
+ }
+ return true;
+ });
+
result.append("Active sensors:\n");
for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
int handle = mActiveSensors.keyAt(i);
@@ -497,6 +400,7 @@
return NO_ERROR;
}
+//TODO: move to SensorEventConnection later
void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
sensors_event_t const* buffer, const int count) {
for (int i=0 ; i<count ; i++) {
@@ -505,12 +409,12 @@
handle = buffer[i].meta_data.sensor;
}
if (connection->hasSensor(handle)) {
- SensorInterface* sensor = mSensorMap.valueFor(handle);
+ sp<SensorInterface> si = getSensorInterfaceFromHandle(handle);
// If this buffer has an event from a one_shot sensor and this connection is registered
// for this particular one_shot sensor, try cleaning up the connection.
- if (sensor != NULL &&
- sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
- sensor->autoDisable(connection.get(), handle);
+ if (si != nullptr &&
+ si->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
+ si->autoDisable(connection.get(), handle);
cleanupWithoutDisableLocked(connection, handle);
}
@@ -518,18 +422,17 @@
}
}
-bool SensorService::threadLoop()
-{
+bool SensorService::threadLoop() {
ALOGD("nuSensorService thread starting...");
// each virtual sensor could generate an event per "real" event, that's why we need to size
// numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT. in practice, this is too
// aggressive, but guaranteed to be enough.
+ const size_t vcount = mSensors.getVirtualSensors().size();
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
- const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());
+ const size_t numEventMax = minBufferSize / (1 + vcount);
SensorDevice& device(SensorDevice::getInstance());
- const size_t vcount = mVirtualSensorList.size();
const int halVersion = device.getHalDeviceVersion();
do {
@@ -575,8 +478,7 @@
// handle virtual sensors
if (count && vcount) {
sensors_event_t const * const event = mSensorEventBuffer;
- const size_t activeVirtualSensorCount = mActiveVirtualSensors.size();
- if (activeVirtualSensorCount) {
+ if (!mActiveVirtualSensors.empty()) {
size_t k = 0;
SensorFusion& fusion(SensorFusion::getInstance());
if (fusion.isEnabled()) {
@@ -585,7 +487,7 @@
}
}
for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) {
- for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
+ for (int handle : mActiveVirtualSensors) {
if (count + k >= minBufferSize) {
ALOGE("buffer too small to hold all events: "
"count=%zd, k=%zu, size=%zu",
@@ -593,7 +495,12 @@
break;
}
sensors_event_t out;
- SensorInterface* si = mActiveVirtualSensors.valueAt(j);
+ sp<SensorInterface> si = mSensors.getInterface(handle);
+ if (si == nullptr) {
+ ALOGE("handle %d is not an valid virtual sensor", handle);
+ continue;
+ }
+
if (si->process(&out, event[i])) {
mSensorEventBuffer[count + k] = out;
k++;
@@ -622,10 +529,10 @@
}
for (int i = 0; i < count; ++i) {
- // Map flush_complete_events in the buffer to SensorEventConnections which called flush on
- // the hardware sensor. mapFlushEventsToConnections[i] will be the SensorEventConnection
- // mapped to the corresponding flush_complete_event in mSensorEventBuffer[i] if such a
- // mapping exists (NULL otherwise).
+ // Map flush_complete_events in the buffer to SensorEventConnections which called flush
+ // on the hardware sensor. mapFlushEventsToConnections[i] will be the
+ // SensorEventConnection mapped to the corresponding flush_complete_event in
+ // mSensorEventBuffer[i] if such a mapping exists (NULL otherwise).
mMapFlushEventsToConnections[i] = NULL;
if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) {
const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor;
@@ -646,9 +553,21 @@
ALOGI("Dynamic sensor handle 0x%x connected, type %d, name %s",
handle, dynamicSensor.type, dynamicSensor.name);
- device.handleDynamicSensorConnection(handle, true /*connected*/);
- registerDynamicSensor(new HardwareSensor(dynamicSensor));
+ if (mSensors.isNewHandle(handle)) {
+ sensor_t s = dynamicSensor;
+ // make sure the dynamic sensor flag is set
+ s.flags |= DYNAMIC_SENSOR_MASK;
+ // force the handle to be consistent
+ s.handle = handle;
+ SensorInterface *si = new HardwareSensor(s);
+ // This will release hold on dynamic sensor meta, so it should be called
+ // after Sensor object is created.
+ device.handleDynamicSensorConnection(handle, true /*connected*/);
+ registerDynamicSensor(si);
+ } else {
+ ALOGE("Handle %d has been used, cannot use again before reboot.", handle);
+ }
} else {
int handle = mSensorEventBuffer[i].dynamic_sensor_meta.handle;
ALOGI("Dynamic sensor handle 0x%x disconnected", handle);
@@ -768,8 +687,7 @@
}
}
-void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count)
-{
+void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count) {
struct compar {
static int cmp(void const* lhs, void const* rhs) {
sensors_event_t const* l = static_cast<sensors_event_t const*>(lhs);
@@ -781,20 +699,12 @@
}
String8 SensorService::getSensorName(int handle) const {
- size_t count = mUserSensorList.size();
- for (size_t i=0 ; i<count ; i++) {
- const Sensor& sensor(mUserSensorList[i]);
- if (sensor.getHandle() == handle) {
- return sensor.getName();
- }
- }
- String8 result("unknown");
- return result;
+ return mSensors.getName(handle);
}
bool SensorService::isVirtualSensor(int handle) const {
- SensorInterface* sensor = mSensorMap.valueFor(handle);
- return sensor != NULL && sensor->isVirtual();
+ sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+ return sensor != nullptr && sensor->isVirtual();
}
bool SensorService::isWakeUpSensorEvent(const sensors_event_t& event) const {
@@ -802,20 +712,15 @@
if (event.type == SENSOR_TYPE_META_DATA) {
handle = event.meta_data.sensor;
}
- SensorInterface* sensor = mSensorMap.valueFor(handle);
- return sensor != NULL && sensor->getSensor().isWakeUpSensor();
+ sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+ return sensor != nullptr && sensor->getSensor().isWakeUpSensor();
}
-SensorService::SensorRecord * SensorService::getSensorRecord(int handle) {
- return mActiveSensors.valueFor(handle);
-}
-
-Vector<Sensor> SensorService::getSensorList(const String16& opPackageName)
-{
+Vector<Sensor> SensorService::getSensorList(const String16& opPackageName) {
char value[PROPERTY_VALUE_MAX];
property_get("debug.sensors", value, "0");
const Vector<Sensor>& initialSensorList = (atoi(value)) ?
- mUserSensorListDebug : mUserSensorList;
+ mSensors.getUserDebugSensors() : mSensors.getUserSensors();
Vector<Sensor> accessibleSensorList;
for (size_t i = 0; i < initialSensorList.size(); i++) {
Sensor sensor = initialSensorList[i];
@@ -831,20 +736,22 @@
return accessibleSensorList;
}
-Vector<Sensor> SensorService::getDynamicSensorList(const String16& opPackageName)
-{
+Vector<Sensor> SensorService::getDynamicSensorList(const String16& opPackageName) {
Vector<Sensor> accessibleSensorList;
- for (size_t i = 0; i < mDynamicSensorList.size(); i++) {
- Sensor sensor = mDynamicSensorList[i];
- if (canAccessSensor(sensor, "getDynamicSensorList", opPackageName)) {
- accessibleSensorList.add(sensor);
- } else {
- ALOGI("Skipped sensor %s because it requires permission %s and app op %d",
- sensor.getName().string(),
- sensor.getRequiredPermission().string(),
- sensor.getRequiredAppOp());
- }
- }
+ mSensors.forEachSensor(
+ [&opPackageName, &accessibleSensorList] (const Sensor& sensor) -> bool {
+ if (sensor.isDynamicSensor()) {
+ if (canAccessSensor(sensor, "getDynamicSensorList", opPackageName)) {
+ accessibleSensorList.add(sensor);
+ } else {
+ ALOGI("Skipped sensor %s because it requires permission %s and app op %" PRId32,
+ sensor.getName().string(),
+ sensor.getRequiredPermission().string(),
+ sensor.getRequiredAppOp());
+ }
+ }
+ return true;
+ });
return accessibleSensorList;
}
@@ -895,8 +802,7 @@
return err;
}
-void SensorService::cleanupConnection(SensorEventConnection* c)
-{
+void SensorService::cleanupConnection(SensorEventConnection* c) {
Mutex::Autolock _l(mLock);
const wp<SensorEventConnection> connection(c);
size_t size = mActiveSensors.size();
@@ -905,10 +811,11 @@
int handle = mActiveSensors.keyAt(i);
if (c->hasSensor(handle)) {
ALOGD_IF(DEBUG_CONNECTIONS, "%zu: disabling handle=0x%08x", i, handle);
- SensorInterface* sensor = mSensorMap.valueFor( handle );
- ALOGE_IF(!sensor, "mSensorMap[handle=0x%08x] is null!", handle);
- if (sensor) {
+ sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+ if (sensor != nullptr) {
sensor->activate(c, false);
+ } else {
+ ALOGE("sensor interface of handle=0x%08x is null!", handle);
}
c->removeSensor(handle);
}
@@ -921,7 +828,7 @@
if (rec && rec->removeConnection(connection)) {
ALOGD_IF(DEBUG_CONNECTIONS, "... and it was the last connection");
mActiveSensors.removeItemsAt(i, 1);
- mActiveVirtualSensors.removeItem(handle);
+ mActiveVirtualSensors.erase(handle);
delete rec;
size--;
} else {
@@ -936,23 +843,20 @@
}
}
-Sensor SensorService::getSensorFromHandle(int handle) const {
- return mSensorMap.valueFor(handle)->getSensor();
+sp<SensorInterface> SensorService::getSensorInterfaceFromHandle(int handle) const {
+ return mSensors.getInterface(handle);
}
+
status_t SensorService::enable(const sp<SensorEventConnection>& connection,
int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags,
- const String16& opPackageName)
-{
+ const String16& opPackageName) {
if (mInitCheck != NO_ERROR)
return mInitCheck;
- SensorInterface* sensor = mSensorMap.valueFor(handle);
- if (sensor == NULL) {
- return BAD_VALUE;
- }
-
- if (!canAccessSensor(sensor->getSensor(), "Tried enabling", opPackageName)) {
+ sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+ if (sensor == nullptr ||
+ !canAccessSensor(sensor->getSensor(), "Tried enabling", opPackageName)) {
return BAD_VALUE;
}
@@ -967,7 +871,7 @@
rec = new SensorRecord(connection);
mActiveSensors.add(handle, rec);
if (sensor->isVirtual()) {
- mActiveVirtualSensors.add(handle, sensor);
+ mActiveVirtualSensors.emplace(handle);
}
} else {
if (rec->addConnection(connection)) {
@@ -1073,17 +977,15 @@
return err;
}
-status_t SensorService::disable(const sp<SensorEventConnection>& connection,
- int handle)
-{
+status_t SensorService::disable(const sp<SensorEventConnection>& connection, int handle) {
if (mInitCheck != NO_ERROR)
return mInitCheck;
Mutex::Autolock _l(mLock);
status_t err = cleanupWithoutDisableLocked(connection, handle);
if (err == NO_ERROR) {
- SensorInterface* sensor = mSensorMap.valueFor(handle);
- err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
+ sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+ err = sensor != nullptr ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
}
if (err == NO_ERROR) {
@@ -1123,7 +1025,7 @@
// see if this sensor becomes inactive
if (rec->removeConnection(connection)) {
mActiveSensors.removeItem(handle);
- mActiveVirtualSensors.removeItem(handle);
+ mActiveVirtualSensors.erase(handle);
delete rec;
}
return NO_ERROR;
@@ -1132,16 +1034,13 @@
}
status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection,
- int handle, nsecs_t ns, const String16& opPackageName)
-{
+ int handle, nsecs_t ns, const String16& opPackageName) {
if (mInitCheck != NO_ERROR)
return mInitCheck;
- SensorInterface* sensor = mSensorMap.valueFor(handle);
- if (!sensor)
- return BAD_VALUE;
-
- if (!canAccessSensor(sensor->getSensor(), "Tried configuring", opPackageName)) {
+ sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+ if (sensor == nullptr ||
+ !canAccessSensor(sensor->getSensor(), "Tried configuring", opPackageName)) {
return BAD_VALUE;
}
@@ -1166,7 +1065,10 @@
// Loop through all sensors for this connection and call flush on each of them.
for (size_t i = 0; i < connection->mSensorInfo.size(); ++i) {
const int handle = connection->mSensorInfo.keyAt(i);
- SensorInterface* sensor = mSensorMap.valueFor(handle);
+ sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+ if (sensor == nullptr) {
+ continue;
+ }
if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
ALOGE("flush called on a one-shot sensor");
err = INVALID_OPERATION;
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index ef4516b..6473edb 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -17,26 +17,25 @@
#ifndef ANDROID_SENSOR_SERVICE_H
#define ANDROID_SENSOR_SERVICE_H
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Vector.h>
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/AndroidThreads.h>
-#include <utils/RefBase.h>
-#include <utils/Looper.h>
-#include <utils/String8.h>
+#include "SensorList.h"
#include <binder/BinderService.h>
-
-#include <gui/Sensor.h>
-#include <gui/BitTube.h>
+#include <cutils/compiler.h>
#include <gui/ISensorServer.h>
#include <gui/ISensorEventConnection.h>
+#include <gui/Sensor.h>
-#include "SensorInterface.h"
+#include <utils/AndroidThreads.h>
+#include <utils/KeyedVector.h>
+#include <utils/Looper.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unordered_set>
#if __clang__
// Clang warns about SensorEventConnection::dump hiding BBinder::dump. The cause isn't fixable
@@ -56,6 +55,7 @@
namespace android {
// ---------------------------------------------------------------------------
+class SensorInterface;
class SensorService :
public BinderService<SensorService>,
@@ -137,7 +137,6 @@
};
static const char* WAKE_LOCK_NAME;
-
static char const* getServiceName() ANDROID_API { return "sensorservice"; }
SensorService() ANDROID_API;
virtual ~SensorService();
@@ -156,17 +155,17 @@
virtual int isDataInjectionEnabled();
virtual status_t dump(int fd, const Vector<String16>& args);
-
static int getNumEventsForSensorType(int sensor_event_type);
String8 getSensorName(int handle) const;
bool isVirtualSensor(int handle) const;
- Sensor getSensorFromHandle(int handle) const;
+ sp<SensorInterface> getSensorInterfaceFromHandle(int handle) const;
bool isWakeUpSensor(int type) const;
void recordLastValueLocked(sensors_event_t const* buffer, size_t count);
static void sortEventBuffer(sensors_event_t* buffer, size_t count);
- Sensor registerSensor(SensorInterface* sensor);
- Sensor registerVirtualSensor(SensorInterface* sensor);
- Sensor registerDynamicSensor(SensorInterface* sensor);
+ const Sensor& registerSensor(SensorInterface* sensor,
+ bool isDebug = false, bool isVirtual = false);
+ const Sensor& registerVirtualSensor(SensorInterface* sensor, bool isDebug = false);
+ const Sensor& registerDynamicSensor(SensorInterface* sensor, bool isDebug = false);
bool unregisterDynamicSensor(int handle);
status_t cleanupWithoutDisable(const sp<SensorEventConnection>& connection, int handle);
status_t cleanupWithoutDisableLocked(const sp<SensorEventConnection>& connection, int handle);
@@ -182,8 +181,6 @@
bool isWakeLockAcquired();
bool isWakeUpSensorEvent(const sensors_event_t& event) const;
- SensorRecord * getSensorRecord(int handle);
-
sp<Looper> getLooper() const;
// Reset mWakeLockRefCounts for all SensorEventConnections to zero. This may happen if
@@ -211,27 +208,24 @@
status_t resetToNormalMode();
status_t resetToNormalModeLocked();
- // constants
- Vector<Sensor> mSensorList;
- Vector<Sensor> mUserSensorListDebug;
- Vector<Sensor> mUserSensorList;
- Vector<Sensor> mDynamicSensorList;
- DefaultKeyedVector<int, SensorInterface*> mSensorMap;
- Vector<SensorInterface *> mVirtualSensorList;
+ SensorServiceUtil::SensorList mSensors;
status_t mInitCheck;
// Socket buffersize used to initialize BitTube. This size depends on whether batching is
// supported or not.
- uint32_t mSocketBufferSize; sp<Looper> mLooper; sp<SensorEventAckReceiver> mAckReceiver;
+ uint32_t mSocketBufferSize;
+ sp<Looper> mLooper;
+ sp<SensorEventAckReceiver> mAckReceiver;
// protected by mLock
mutable Mutex mLock;
DefaultKeyedVector<int, SensorRecord*> mActiveSensors;
- DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors;
+ std::unordered_set<int> mActiveVirtualSensors;
SortedVector< wp<SensorEventConnection> > mActiveConnections;
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
SensorEventConnection const **mMapFlushEventsToConnections;
+ KeyedVector<int32_t, MostRecentEventLogger*> mLastEventSeen;
Mode mCurrentOperatingMode;
// This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
@@ -240,9 +234,6 @@
// sensors.
String8 mWhiteListedPackage;
- // The size of this vector is constant, only the items are mutable
- KeyedVector<int32_t, MostRecentEventLogger *> mLastEventSeen;
-
int mNextSensorRegIndex;
Vector<SensorRegistrationInfo> mLastNSensorRegistrations;
};
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index d0a0401..fb6307e 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -12,6 +12,7 @@
EventThread.cpp \
FenceTracker.cpp \
FrameTracker.cpp \
+ GpuService.cpp \
Layer.cpp \
LayerDim.cpp \
MessageQueue.cpp \
@@ -37,10 +38,13 @@
RenderEngine/GLES11RenderEngine.cpp \
RenderEngine/GLES20RenderEngine.cpp
+LOCAL_C_INCLUDES := \
+ frameworks/native/vulkan/include \
+ external/vulkan-validation-layers/libs/vkjson
LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-
+#LOCAL_CFLAGS += -DENABLE_FENCE_TRACKING
USE_HWC2 := false
ifeq ($(USE_HWC2),true)
@@ -106,6 +110,7 @@
LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
LOCAL_CFLAGS += -std=c++14
+LOCAL_STATIC_LIBRARIES := libvkjson
LOCAL_SHARED_LIBRARIES := \
libcutils \
liblog \
@@ -118,7 +123,8 @@
libbinder \
libui \
libgui \
- libpowermanager
+ libpowermanager \
+ libvulkan
LOCAL_MODULE := libsurfaceflinger
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 5ba387d..37b6420 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -15,6 +15,7 @@
*/
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
// This is needed for stdint.h to define INT64_MAX in C++
#define __STDC_LIMIT_MACROS
@@ -33,12 +34,21 @@
#include "DispSync.h"
#include "EventLog/EventLog.h"
+#include <algorithm>
+
+using std::max;
+using std::min;
+
namespace android {
// Setting this to true enables verbose tracing that can be used to debug
// vsync event model or phase issues.
static const bool kTraceDetailedInfo = false;
+// Setting this to true adds a zero-phase tracer for correlating with hardware
+// vsync events
+static const bool kEnableZeroPhaseTracer = false;
+
// This is the threshold used to determine when hardware vsync events are
// needed to re-synchronize the software vsync model with the hardware. The
// error metric used is the mean of the squared difference between each
@@ -49,28 +59,36 @@
// vsync event.
static const int64_t kPresentTimeOffset = PRESENT_TIME_OFFSET_FROM_VSYNC_NS;
+#undef LOG_TAG
+#define LOG_TAG "DispSyncThread"
class DispSyncThread: public Thread {
public:
- DispSyncThread():
+ DispSyncThread(const char* name):
+ mName(name),
mStop(false),
mPeriod(0),
mPhase(0),
mReferenceTime(0),
- mWakeupLatency(0) {
- }
+ mWakeupLatency(0),
+ mFrameNumber(0) {}
virtual ~DispSyncThread() {}
void updateModel(nsecs_t period, nsecs_t phase, nsecs_t referenceTime) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
mPeriod = period;
mPhase = phase;
mReferenceTime = referenceTime;
+ ALOGV("[%s] updateModel: mPeriod = %" PRId64 ", mPhase = %" PRId64
+ " mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
+ ns2us(mPhase), ns2us(mReferenceTime));
mCond.signal();
}
void stop() {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
mStop = true;
mCond.signal();
@@ -79,7 +97,6 @@
virtual bool threadLoop() {
status_t err;
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- nsecs_t nextEventTime = 0;
while (true) {
Vector<CallbackInvocation> callbackInvocations;
@@ -89,6 +106,12 @@
{ // Scope for lock
Mutex::Autolock lock(mMutex);
+ if (kTraceDetailedInfo) {
+ ATRACE_INT64("DispSync:Frame", mFrameNumber);
+ }
+ ALOGV("[%s] Frame %" PRId64, mName, mFrameNumber);
+ ++mFrameNumber;
+
if (mStop) {
return false;
}
@@ -103,13 +126,21 @@
continue;
}
- nextEventTime = computeNextEventTimeLocked(now);
- targetTime = nextEventTime;
+ targetTime = computeNextEventTimeLocked(now);
bool isWakeup = false;
if (now < targetTime) {
- err = mCond.waitRelative(mMutex, targetTime - now);
+ if (kTraceDetailedInfo) ATRACE_NAME("DispSync waiting");
+
+ if (targetTime == INT64_MAX) {
+ ALOGV("[%s] Waiting forever", mName);
+ err = mCond.wait(mMutex);
+ } else {
+ ALOGV("[%s] Waiting until %" PRId64, mName,
+ ns2us(targetTime));
+ err = mCond.waitRelative(mMutex, targetTime - now);
+ }
if (err == TIMED_OUT) {
isWakeup = true;
@@ -122,15 +153,15 @@
now = systemTime(SYSTEM_TIME_MONOTONIC);
+ // Don't correct by more than 1.5 ms
+ static const nsecs_t kMaxWakeupLatency = us2ns(1500);
+
if (isWakeup) {
mWakeupLatency = ((mWakeupLatency * 63) +
(now - targetTime)) / 64;
- if (mWakeupLatency > 500000) {
- // Don't correct by more than 500 us
- mWakeupLatency = 500000;
- }
+ mWakeupLatency = min(mWakeupLatency, kMaxWakeupLatency);
if (kTraceDetailedInfo) {
- ATRACE_INT64("DispSync:WakeupLat", now - nextEventTime);
+ ATRACE_INT64("DispSync:WakeupLat", now - targetTime);
ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);
}
}
@@ -146,7 +177,9 @@
return false;
}
- status_t addEventListener(nsecs_t phase, const sp<DispSync::Callback>& callback) {
+ status_t addEventListener(const char* name, nsecs_t phase,
+ const sp<DispSync::Callback>& callback) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
for (size_t i = 0; i < mEventListeners.size(); i++) {
@@ -156,15 +189,14 @@
}
EventListener listener;
+ listener.mName = name;
listener.mPhase = phase;
listener.mCallback = callback;
// We want to allow the firstmost future event to fire without
- // allowing any past events to fire. Because
- // computeListenerNextEventTimeLocked filters out events within a half
- // a period of the last event time, we need to initialize the last
- // event time to a half a period in the past.
- listener.mLastEventTime = systemTime(SYSTEM_TIME_MONOTONIC) - mPeriod / 2;
+ // allowing any past events to fire
+ listener.mLastEventTime = systemTime() - mPeriod / 2 + mPhase -
+ mWakeupLatency;
mEventListeners.push(listener);
@@ -174,6 +206,7 @@
}
status_t removeEventListener(const sp<DispSync::Callback>& callback) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
for (size_t i = 0; i < mEventListeners.size(); i++) {
@@ -189,6 +222,7 @@
// This method is only here to handle the kIgnorePresentFences case.
bool hasAnyEventListeners() {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
return !mEventListeners.empty();
}
@@ -196,6 +230,7 @@
private:
struct EventListener {
+ const char* mName;
nsecs_t mPhase;
nsecs_t mLastEventTime;
sp<DispSync::Callback> mCallback;
@@ -207,6 +242,8 @@
};
nsecs_t computeNextEventTimeLocked(nsecs_t now) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
+ ALOGV("[%s] computeNextEventTimeLocked", mName);
nsecs_t nextEventTime = INT64_MAX;
for (size_t i = 0; i < mEventListeners.size(); i++) {
nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
@@ -217,21 +254,28 @@
}
}
+ ALOGV("[%s] nextEventTime = %" PRId64, mName, ns2us(nextEventTime));
return nextEventTime;
}
Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
+ ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName,
+ ns2us(now));
+
Vector<CallbackInvocation> callbackInvocations;
- nsecs_t ref = now - mPeriod;
+ nsecs_t onePeriodAgo = now - mPeriod;
for (size_t i = 0; i < mEventListeners.size(); i++) {
nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
- ref);
+ onePeriodAgo);
if (t < now) {
CallbackInvocation ci;
ci.mCallback = mEventListeners[i].mCallback;
ci.mEventTime = t;
+ ALOGV("[%s] [%s] Preparing to fire", mName,
+ mEventListeners[i].mName);
callbackInvocations.push(ci);
mEventListeners.editItemAt(i).mLastEventTime = t;
}
@@ -241,29 +285,67 @@
}
nsecs_t computeListenerNextEventTimeLocked(const EventListener& listener,
- nsecs_t ref) {
+ nsecs_t baseTime) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
+ ALOGV("[%s] [%s] computeListenerNextEventTimeLocked(%" PRId64 ")",
+ mName, listener.mName, ns2us(baseTime));
- nsecs_t lastEventTime = listener.mLastEventTime;
- if (ref < lastEventTime) {
- ref = lastEventTime;
+ nsecs_t lastEventTime = listener.mLastEventTime + mWakeupLatency;
+ ALOGV("[%s] lastEventTime: %" PRId64, mName, ns2us(lastEventTime));
+ if (baseTime < lastEventTime) {
+ baseTime = lastEventTime;
+ ALOGV("[%s] Clamping baseTime to lastEventTime -> %" PRId64, mName,
+ ns2us(baseTime));
}
- nsecs_t phase = mReferenceTime + mPhase + listener.mPhase;
- nsecs_t t = (((ref - phase) / mPeriod) + 1) * mPeriod + phase;
+ baseTime -= mReferenceTime;
+ ALOGV("[%s] Relative baseTime = %" PRId64, mName, ns2us(baseTime));
+ nsecs_t phase = mPhase + listener.mPhase;
+ ALOGV("[%s] Phase = %" PRId64, mName, ns2us(phase));
+ baseTime -= phase;
+ ALOGV("[%s] baseTime - phase = %" PRId64, mName, ns2us(baseTime));
- if (t - listener.mLastEventTime < mPeriod / 2) {
+ // If our previous time is before the reference (because the reference
+ // has since been updated), the division by mPeriod will truncate
+ // towards zero instead of computing the floor. Since in all cases
+ // before the reference we want the next time to be effectively now, we
+ // set baseTime to -mPeriod so that numPeriods will be -1.
+ // When we add 1 and the phase, we will be at the correct event time for
+ // this period.
+ if (baseTime < 0) {
+ ALOGV("[%s] Correcting negative baseTime", mName);
+ baseTime = -mPeriod;
+ }
+
+ nsecs_t numPeriods = baseTime / mPeriod;
+ ALOGV("[%s] numPeriods = %" PRId64, mName, numPeriods);
+ nsecs_t t = (numPeriods + 1) * mPeriod + phase;
+ ALOGV("[%s] t = %" PRId64, mName, ns2us(t));
+ t += mReferenceTime;
+ ALOGV("[%s] Absolute t = %" PRId64, mName, ns2us(t));
+
+ // Check that it's been slightly more than half a period since the last
+ // event so that we don't accidentally fall into double-rate vsyncs
+ if (t - listener.mLastEventTime < (3 * mPeriod / 5)) {
t += mPeriod;
+ ALOGV("[%s] Modifying t -> %" PRId64, mName, ns2us(t));
}
+ t -= mWakeupLatency;
+ ALOGV("[%s] Corrected for wakeup latency -> %" PRId64, mName, ns2us(t));
+
return t;
}
void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
for (size_t i = 0; i < callbacks.size(); i++) {
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
}
}
+ const char* const mName;
+
bool mStop;
nsecs_t mPeriod;
@@ -271,12 +353,17 @@
nsecs_t mReferenceTime;
nsecs_t mWakeupLatency;
+ int64_t mFrameNumber;
+
Vector<EventListener> mEventListeners;
Mutex mMutex;
Condition mCond;
};
+#undef LOG_TAG
+#define LOG_TAG "DispSync"
+
class ZeroPhaseTracer : public DispSync::Callback {
public:
ZeroPhaseTracer() : mParity(false) {}
@@ -290,9 +377,10 @@
bool mParity;
};
-DispSync::DispSync() :
+DispSync::DispSync(const char* name) :
+ mName(name),
mRefreshSkipCount(0),
- mThread(new DispSyncThread()) {
+ mThread(new DispSyncThread(name)) {
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
@@ -305,8 +393,8 @@
// Even if we're just ignoring the fences, the zero-phase tracing is
// not needed because any time there is an event registered we will
// turn on the HW vsync events.
- if (!kIgnorePresentFences) {
- addEventListener(0, new ZeroPhaseTracer());
+ if (!kIgnorePresentFences && kEnableZeroPhaseTracer) {
+ addEventListener("ZeroPhaseTracer", 0, new ZeroPhaseTracer());
}
}
}
@@ -351,7 +439,7 @@
void DispSync::beginResync() {
Mutex::Autolock lock(mMutex);
-
+ ALOGV("[%s] beginResync", mName);
mModelUpdated = false;
mNumResyncSamples = 0;
}
@@ -359,11 +447,17 @@
bool DispSync::addResyncSample(nsecs_t timestamp) {
Mutex::Autolock lock(mMutex);
+ ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));
+
size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
mResyncSamples[idx] = timestamp;
if (mNumResyncSamples == 0) {
mPhase = 0;
mReferenceTime = timestamp;
+ ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "
+ "mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
+ ns2us(mReferenceTime));
+ mThread->updateModel(mPeriod, mPhase, mReferenceTime);
}
if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
@@ -387,17 +481,21 @@
return mThread->hasAnyEventListeners();
}
- return !mModelUpdated || mError > kErrorThreshold;
+ // Check against kErrorThreshold / 2 to add some hysteresis before having to
+ // resync again
+ bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2);
+ ALOGV("[%s] addResyncSample returning %s", mName,
+ modelLocked ? "locked" : "unlocked");
+ return !modelLocked;
}
void DispSync::endResync() {
}
-status_t DispSync::addEventListener(nsecs_t phase,
+status_t DispSync::addEventListener(const char* name, nsecs_t phase,
const sp<Callback>& callback) {
-
Mutex::Autolock lock(mMutex);
- return mThread->addEventListener(phase, callback);
+ return mThread->addEventListener(name, phase, callback);
}
void DispSync::setRefreshSkipCount(int count) {
@@ -427,20 +525,32 @@
}
void DispSync::updateModelLocked() {
+ ALOGV("[%s] updateModelLocked %zu", mName, mNumResyncSamples);
if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {
+ ALOGV("[%s] Computing...", mName);
nsecs_t durationSum = 0;
+ nsecs_t minDuration = INT64_MAX;
+ nsecs_t maxDuration = 0;
for (size_t i = 1; i < mNumResyncSamples; i++) {
size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES;
- durationSum += mResyncSamples[idx] - mResyncSamples[prev];
+ nsecs_t duration = mResyncSamples[idx] - mResyncSamples[prev];
+ durationSum += duration;
+ minDuration = min(minDuration, duration);
+ maxDuration = max(maxDuration, duration);
}
- mPeriod = durationSum / (mNumResyncSamples - 1);
+ // Exclude the min and max from the average
+ durationSum -= minDuration + maxDuration;
+ mPeriod = durationSum / (mNumResyncSamples - 3);
+
+ ALOGV("[%s] mPeriod = %" PRId64, mName, ns2us(mPeriod));
double sampleAvgX = 0;
double sampleAvgY = 0;
double scale = 2.0 * M_PI / double(mPeriod);
- for (size_t i = 0; i < mNumResyncSamples; i++) {
+ // Intentionally skip the first sample
+ for (size_t i = 1; i < mNumResyncSamples; i++) {
size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
nsecs_t sample = mResyncSamples[idx] - mReferenceTime;
double samplePhase = double(sample % mPeriod) * scale;
@@ -448,18 +558,21 @@
sampleAvgY += sin(samplePhase);
}
- sampleAvgX /= double(mNumResyncSamples);
- sampleAvgY /= double(mNumResyncSamples);
+ sampleAvgX /= double(mNumResyncSamples - 1);
+ sampleAvgY /= double(mNumResyncSamples - 1);
mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale);
- if (mPhase < 0) {
+ ALOGV("[%s] mPhase = %" PRId64, mName, ns2us(mPhase));
+
+ if (mPhase < -(mPeriod / 2)) {
mPhase += mPeriod;
+ ALOGV("[%s] Adjusting mPhase -> %" PRId64, mName, ns2us(mPhase));
}
if (kTraceDetailedInfo) {
ATRACE_INT64("DispSync:Period", mPeriod);
- ATRACE_INT64("DispSync:Phase", mPhase);
+ ATRACE_INT64("DispSync:Phase", mPhase + mPeriod / 2);
}
// Artificially inflate the period if requested.
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index a8524b9..537c81b 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -26,11 +26,8 @@
namespace android {
// Ignore present (retire) fences if the device doesn't have support for the
-// sync framework, or if all phase offsets are zero. The latter is useful
-// because it allows us to avoid resync bursts on devices that don't need
-// phase-offset VSYNC events.
-#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) || \
- (VSYNC_EVENT_PHASE_OFFSET_NS == 0 && SF_VSYNC_EVENT_PHASE_OFFSET_NS == 0)
+// sync framework
+#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK)
static const bool kIgnorePresentFences = true;
#else
static const bool kIgnorePresentFences = false;
@@ -64,7 +61,7 @@
virtual void onDispSyncEvent(nsecs_t when) = 0;
};
- DispSync();
+ DispSync(const char* name);
~DispSync();
// reset clears the resync samples and error value.
@@ -114,7 +111,8 @@
// given phase offset from the hardware vsync events. The callback is
// called from a separate thread and it should return reasonably quickly
// (i.e. within a few hundred microseconds).
- status_t addEventListener(nsecs_t phase, const sp<Callback>& callback);
+ status_t addEventListener(const char* name, nsecs_t phase,
+ const sp<Callback>& callback);
// removeEventListener removes an already-registered event callback. Once
// this method returns that callback will no longer be called by the
@@ -137,10 +135,12 @@
void resetErrorLocked();
enum { MAX_RESYNC_SAMPLES = 32 };
- enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 3 };
+ enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 6 };
enum { NUM_PRESENT_SAMPLES = 8 };
enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
+ const char* const mName;
+
// mPeriod is the computed period of the modeled vsync events in
// nanoseconds.
nsecs_t mPeriod;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index f7c8473..a67b3ff 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -68,6 +68,8 @@
*
*/
+uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0;
+
DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
@@ -550,10 +552,32 @@
}
mOrientation = orientation;
+ if (mType == DisplayType::DISPLAY_PRIMARY) {
+ uint32_t transform = 0;
+ switch (mOrientation) {
+ case DisplayState::eOrientationDefault:
+ transform = Transform::ROT_0;
+ break;
+ case DisplayState::eOrientation90:
+ transform = Transform::ROT_90;
+ break;
+ case DisplayState::eOrientation180:
+ transform = Transform::ROT_180;
+ break;
+ case DisplayState::eOrientation270:
+ transform = Transform::ROT_270;
+ break;
+ }
+ sPrimaryDisplayOrientation = transform;
+ }
mViewport = viewport;
mFrame = frame;
}
+uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() {
+ return sPrimaryDisplayOrientation;
+}
+
void DisplayDevice::dump(String8& result) const {
const Transform& tr(mGlobalTransform);
result.appendFormat(
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 9ac8a97..dd9b104 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -129,6 +129,7 @@
int getOrientation() const { return mOrientation; }
uint32_t getOrientationTransform() const;
+ static uint32_t getPrimaryDisplayOrientationTransform();
const Transform& getTransform() const { return mGlobalTransform; }
const Rect getViewport() const { return mViewport; }
const Rect getFrame() const { return mFrame; }
@@ -238,6 +239,7 @@
uint32_t mLayerStack;
int mOrientation;
+ static uint32_t sPrimaryDisplayOrientation;
// user-provided visible area of the layer stack
Rect mViewport;
// user-provided rectangle where mViewport gets mapped to
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 0e97a53..f7678e4 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -30,6 +30,7 @@
#include <android/configuration.h>
+#include <algorithm>
#include <inttypes.h>
extern "C" {
@@ -74,6 +75,7 @@
using android::Fence;
using android::FloatRect;
using android::GraphicBuffer;
+using android::HdrCapabilities;
using android::Rect;
using android::Region;
using android::sp;
@@ -100,6 +102,7 @@
mGetDisplayRequests(nullptr),
mGetDisplayType(nullptr),
mGetDozeSupport(nullptr),
+ mGetHdrCapabilities(nullptr),
mGetReleaseFences(nullptr),
mPresentDisplay(nullptr),
mSetActiveConfig(nullptr),
@@ -301,88 +304,98 @@
mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, asInt);
}
+bool Device::hasCapability(HWC2::Capability capability) const
+{
+ return std::find(mCapabilities.cbegin(), mCapabilities.cend(),
+ capability) != mCapabilities.cend();
+}
+
void Device::loadFunctionPointers()
{
// For all of these early returns, we log an error message inside
// loadFunctionPointer specifying which function failed to load
// Display function pointers
- if(!loadFunctionPointer(FunctionDescriptor::CreateVirtualDisplay,
+ if (!loadFunctionPointer(FunctionDescriptor::CreateVirtualDisplay,
mCreateVirtualDisplay)) return;
- if(!loadFunctionPointer(FunctionDescriptor::DestroyVirtualDisplay,
+ if (!loadFunctionPointer(FunctionDescriptor::DestroyVirtualDisplay,
mDestroyVirtualDisplay)) return;
- if(!loadFunctionPointer(FunctionDescriptor::Dump, mDump)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetMaxVirtualDisplayCount,
+ if (!loadFunctionPointer(FunctionDescriptor::Dump, mDump)) return;
+ if (!loadFunctionPointer(FunctionDescriptor::GetMaxVirtualDisplayCount,
mGetMaxVirtualDisplayCount)) return;
- if(!loadFunctionPointer(FunctionDescriptor::RegisterCallback,
+ if (!loadFunctionPointer(FunctionDescriptor::RegisterCallback,
mRegisterCallback)) return;
// Device function pointers
- if(!loadFunctionPointer(FunctionDescriptor::AcceptDisplayChanges,
+ if (!loadFunctionPointer(FunctionDescriptor::AcceptDisplayChanges,
mAcceptDisplayChanges)) return;
- if(!loadFunctionPointer(FunctionDescriptor::CreateLayer,
+ if (!loadFunctionPointer(FunctionDescriptor::CreateLayer,
mCreateLayer)) return;
- if(!loadFunctionPointer(FunctionDescriptor::DestroyLayer,
+ if (!loadFunctionPointer(FunctionDescriptor::DestroyLayer,
mDestroyLayer)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetActiveConfig,
+ if (!loadFunctionPointer(FunctionDescriptor::GetActiveConfig,
mGetActiveConfig)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
+ if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
mGetChangedCompositionTypes)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
mGetDisplayAttribute)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
mGetDisplayConfigs)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDisplayName,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDisplayName,
mGetDisplayName)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDisplayRequests,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDisplayRequests,
mGetDisplayRequests)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDisplayType,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDisplayType,
mGetDisplayType)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDozeSupport,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDozeSupport,
mGetDozeSupport)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetReleaseFences,
+ if (!loadFunctionPointer(FunctionDescriptor::GetHdrCapabilities,
+ mGetHdrCapabilities)) return;
+ if (!loadFunctionPointer(FunctionDescriptor::GetReleaseFences,
mGetReleaseFences)) return;
- if(!loadFunctionPointer(FunctionDescriptor::PresentDisplay,
+ if (!loadFunctionPointer(FunctionDescriptor::PresentDisplay,
mPresentDisplay)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetActiveConfig,
+ if (!loadFunctionPointer(FunctionDescriptor::SetActiveConfig,
mSetActiveConfig)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
+ if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
mSetClientTarget)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
+ if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
mSetOutputBuffer)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
+ if (!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
mSetPowerMode)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetVsyncEnabled,
+ if (!loadFunctionPointer(FunctionDescriptor::SetVsyncEnabled,
mSetVsyncEnabled)) return;
- if(!loadFunctionPointer(FunctionDescriptor::ValidateDisplay,
+ if (!loadFunctionPointer(FunctionDescriptor::ValidateDisplay,
mValidateDisplay)) return;
// Layer function pointers
- if(!loadFunctionPointer(FunctionDescriptor::SetCursorPosition,
+ if (!loadFunctionPointer(FunctionDescriptor::SetCursorPosition,
mSetCursorPosition)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerBuffer,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerBuffer,
mSetLayerBuffer)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerSurfaceDamage,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerSurfaceDamage,
mSetLayerSurfaceDamage)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerBlendMode,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerBlendMode,
mSetLayerBlendMode)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerColor,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerColor,
mSetLayerColor)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
mSetLayerCompositionType)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
mSetLayerDisplayFrame)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
mSetLayerPlaneAlpha)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerSidebandStream,
- mSetLayerSidebandStream)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerSourceCrop,
+ if (hasCapability(Capability::SidebandStream)) {
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerSidebandStream,
+ mSetLayerSidebandStream)) return;
+ }
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerSourceCrop,
mSetLayerSourceCrop)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerTransform,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerTransform,
mSetLayerTransform)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerVisibleRegion,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerVisibleRegion,
mSetLayerVisibleRegion)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
mSetLayerZOrder)) return;
}
@@ -637,6 +650,34 @@
return Error::None;
}
+Error Display::getHdrCapabilities(
+ std::unique_ptr<HdrCapabilities>* outCapabilities) const
+{
+ uint32_t numTypes = 0;
+ float maxLuminance = -1.0f;
+ float maxAverageLuminance = -1.0f;
+ float minLuminance = -1.0f;
+ int32_t intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId,
+ &numTypes, nullptr, &maxLuminance, &maxAverageLuminance,
+ &minLuminance);
+ auto error = static_cast<HWC2::Error>(intError);
+ if (error != Error::None) {
+ return error;
+ }
+
+ std::vector<int32_t> types(numTypes);
+ intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId, &numTypes,
+ types.data(), &maxLuminance, &maxAverageLuminance, &minLuminance);
+ error = static_cast<HWC2::Error>(intError);
+ if (error != Error::None) {
+ return error;
+ }
+
+ *outCapabilities = std::make_unique<HdrCapabilities>(std::move(types),
+ maxLuminance, maxAverageLuminance, minLuminance);
+ return Error::None;
+}
+
Error Display::getReleaseFences(
std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
{
@@ -941,6 +982,11 @@
Error Layer::setSidebandStream(const native_handle_t* stream)
{
+ if (!mDevice.hasCapability(Capability::SidebandStream)) {
+ ALOGE("Attempted to call setSidebandStream without checking that the "
+ "device supports sideband streams");
+ return Error::Unsupported;
+ }
int32_t intError = mDevice.mSetLayerSidebandStream(mDevice.mHwcDevice,
mDisplayId, mId, stream);
return static_cast<Error>(intError);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index a7bd28c..967add0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -23,6 +23,8 @@
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
+#include <ui/HdrCapabilities.h>
+
#include <utils/Log.h>
#include <utils/StrongPointer.h>
#include <utils/Timers.h>
@@ -87,6 +89,8 @@
// as connected
std::shared_ptr<Display> getDisplayById(hwc2_display_t id);
+ bool hasCapability(HWC2::Capability capability) const;
+
private:
// Initialization methods
@@ -145,6 +149,7 @@
HWC2_PFN_GET_DISPLAY_REQUESTS mGetDisplayRequests;
HWC2_PFN_GET_DISPLAY_TYPE mGetDisplayType;
HWC2_PFN_GET_DOZE_SUPPORT mGetDozeSupport;
+ HWC2_PFN_GET_HDR_CAPABILITIES mGetHdrCapabilities;
HWC2_PFN_GET_RELEASE_FENCES mGetReleaseFences;
HWC2_PFN_PRESENT_DISPLAY mPresentDisplay;
HWC2_PFN_SET_ACTIVE_CONFIG mSetActiveConfig;
@@ -279,6 +284,8 @@
outLayerRequests);
[[clang::warn_unused_result]] Error getType(DisplayType* outType) const;
[[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const;
+ [[clang::warn_unused_result]] Error getHdrCapabilities(
+ std::unique_ptr<android::HdrCapabilities>* outCapabilities) const;
[[clang::warn_unused_result]] Error getReleaseFences(
std::unordered_map<std::shared_ptr<Layer>,
android::sp<android::Fence>>* outFences) const;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index dabc77f..6ebcdfe 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -238,6 +238,11 @@
return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(
displayHook<decltype(&Display::getDozeSupport),
&Display::getDozeSupport, int32_t*>);
+ case FunctionDescriptor::GetHdrCapabilities:
+ return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(
+ displayHook<decltype(&Display::getHdrCapabilities),
+ &Display::getHdrCapabilities, uint32_t*, int32_t*, float*,
+ float*, float*>);
case FunctionDescriptor::GetReleaseFences:
return asFP<HWC2_PFN_GET_RELEASE_FENCES>(
displayHook<decltype(&Display::getReleaseFences),
@@ -709,6 +714,15 @@
return Error::None;
}
+Error HWC2On1Adapter::Display::getHdrCapabilities(uint32_t* outNumTypes,
+ int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+ float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/)
+{
+ // This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0
+ *outNumTypes = 0;
+ return Error::None;
+}
+
Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName)
{
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
index bffeefe..6fdb184 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
@@ -194,6 +194,9 @@
HWC2::Error getConfigs(uint32_t* outNumConfigs,
hwc2_config_t* outConfigIds);
HWC2::Error getDozeSupport(int32_t* outSupport);
+ HWC2::Error getHdrCapabilities(uint32_t* outNumTypes,
+ int32_t* outTypes, float* outMaxLuminance,
+ float* outMaxAverageLuminance, float* outMinLuminance);
HWC2::Error getName(uint32_t* outSize, char* outName);
HWC2::Error getReleaseFences(uint32_t* outNumElements,
hwc2_layer_t* outLayers, int32_t* outFences);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 26f9519..0bec0b8 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -116,22 +116,20 @@
abort();
}
- if (module->module_api_version >= 0x0200) {
- hwc2_device_t* hwc2device = nullptr;
- int error = hwc2_open(module, &hwc2device);
- if (error != 0) {
- ALOGE("Failed to open HWC2 device (%s), aborting", strerror(-error));
- abort();
- }
- mHwcDevice = std::make_unique<HWC2::Device>(hwc2device);
+ hw_device_t* device = nullptr;
+ int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
+ if (error != 0) {
+ ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));
+ abort();
+ }
+
+ uint32_t majorVersion = (device->version >> 24) & 0xF;
+ if (majorVersion == 2) {
+ mHwcDevice = std::make_unique<HWC2::Device>(
+ reinterpret_cast<hwc2_device_t*>(device));
} else {
- hwc_composer_device_1_t* hwc1device = nullptr;
- int error = hwc_open_1(module, &hwc1device);
- if (error) {
- ALOGE("Failed to open HWC1 device (%s), aborting", strerror(-error));
- abort();
- }
- mAdapter = std::make_unique<HWC2On1Adapter>(hwc1device);
+ mAdapter = std::make_unique<HWC2On1Adapter>(
+ reinterpret_cast<hwc_composer_device_1_t*>(device));
uint8_t minorVersion = mAdapter->getHwc1MinorVersion();
if (minorVersion < 1) {
ALOGE("Cannot adapt to HWC version %d.%d",
@@ -736,6 +734,26 @@
mDisplayData[displayId].releaseFences.clear();
}
+std::unique_ptr<HdrCapabilities> HWComposer::getHdrCapabilities(
+ int32_t displayId) {
+ if (!isValidDisplay(displayId)) {
+ ALOGE("getHdrCapabilities: Display %d is not valid", displayId);
+ return nullptr;
+ }
+
+ auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+ std::unique_ptr<HdrCapabilities> capabilities;
+ auto error = hwcDisplay->getHdrCapabilities(&capabilities);
+ if (error != HWC2::Error::None) {
+ ALOGE("getOutputCapabilities: Failed to get capabilities on display %d:"
+ " %s (%d)", displayId, to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ return nullptr;
+ }
+
+ return capabilities;
+}
+
// Converts a PixelFormat to a human-readable string. Max 11 chars.
// (Could use a table of prefab String8 objects.)
/*
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 30c8f67..d407877 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -130,6 +130,9 @@
// it can call this to clear the shared pointers in the release fence map
void clearReleaseFences(int32_t displayId);
+ // Returns the HDR capabilities of the given display
+ std::unique_ptr<HdrCapabilities> getHdrCapabilities(int32_t displayId);
+
// Events handling ---------------------------------------------------------
void setVsyncEnabled(int32_t disp, HWC2::Vsync enabled);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index d37fcb2..4afd8a2 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -926,16 +926,19 @@
protected:
HWCTYPE* const mLayerList;
HWCTYPE* mCurrentLayer;
- Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer) { }
+ Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer),
+ mIndex(0) { }
inline HWCTYPE const * getLayer() const { return mCurrentLayer; }
inline HWCTYPE* getLayer() { return mCurrentLayer; }
virtual ~Iterable() { }
+ size_t mIndex;
private:
// returns a copy of ourselves
virtual HWComposer::HWCLayer* dup() {
return new CONCRETE( static_cast<const CONCRETE&>(*this) );
}
virtual status_t setLayer(size_t index) {
+ mIndex = index;
mCurrentLayer = &mLayerList[index];
return NO_ERROR;
}
@@ -948,8 +951,12 @@
class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
struct hwc_composer_device_1* mHwc;
public:
- HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer)
- : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc) { }
+ HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer,
+ Vector<Region>* visibleRegions,
+ Vector<Region>* surfaceDamageRegions)
+ : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc),
+ mVisibleRegions(visibleRegions),
+ mSurfaceDamageRegions(surfaceDamageRegions) {}
virtual int32_t getCompositionType() const {
return getLayer()->compositionType;
@@ -1037,9 +1044,10 @@
}
virtual void setVisibleRegionScreen(const Region& reg) {
hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
- mVisibleRegion = reg;
+ mVisibleRegions->editItemAt(mIndex) = reg;
visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(
- mVisibleRegion.getArray(&visibleRegion.numRects));
+ mVisibleRegions->itemAt(mIndex).getArray(
+ &visibleRegion.numRects));
}
virtual void setSurfaceDamage(const Region& reg) {
if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
@@ -1053,9 +1061,10 @@
surfaceDamage.rects = NULL;
return;
}
- mSurfaceDamage = reg;
+ mSurfaceDamageRegions->editItemAt(mIndex) = reg;
surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(
- mSurfaceDamage.getArray(&surfaceDamage.numRects));
+ mSurfaceDamageRegions->itemAt(mIndex).getArray(
+ &surfaceDamage.numRects));
}
virtual void setSidebandStream(const sp<NativeHandle>& stream) {
ALOG_ASSERT(stream->handle() != NULL);
@@ -1081,11 +1090,10 @@
}
protected:
- // We need to hold "copies" of these for memory management purposes. The
- // actual hwc_layer_1_t holds pointers to the memory within. Vector<>
- // internally doesn't copy the memory unless one of the copies is modified.
- Region mVisibleRegion;
- Region mSurfaceDamage;
+ // Pointers to the vectors of Region backing-memory held in DisplayData.
+ // Only the Region at mIndex corresponds to this Layer.
+ Vector<Region>* mVisibleRegions;
+ Vector<Region>* mSurfaceDamageRegions;
};
/*
@@ -1095,11 +1103,18 @@
if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
return LayerListIterator();
}
- const DisplayData& disp(mDisplayData[id]);
+ DisplayData& disp(mDisplayData[id]);
if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
return LayerListIterator();
}
- return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index);
+ if (disp.visibleRegions.size() < disp.list->numHwLayers) {
+ disp.visibleRegions.resize(disp.list->numHwLayers);
+ }
+ if (disp.surfaceDamageRegions.size() < disp.list->numHwLayers) {
+ disp.surfaceDamageRegions.resize(disp.list->numHwLayers);
+ }
+ return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers,
+ &disp.visibleRegions, &disp.surfaceDamageRegions), index);
}
/*
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
index f5f7d77..c861817 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -346,6 +346,13 @@
// protected by mEventControlLock
int32_t events;
+
+ // We need to hold "copies" of these for memory management purposes. The
+ // actual hwc_layer_1_t holds pointers to the memory within. Vector<>
+ // internally doesn't copy the memory unless one of the copies is
+ // modified.
+ Vector<Region> visibleRegions;
+ Vector<Region> surfaceDamageRegions;
};
sp<SurfaceFlinger> mFlinger;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 37b7aba..7e4e797 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -605,6 +605,12 @@
return INVALID_OPERATION;
}
+status_t VirtualDisplaySurface::getLastQueuedBuffer(
+ sp<GraphicBuffer>* /*outBuffer*/, sp<Fence>* /*outFence*/) {
+ ALOGE("getLastQueuedBuffer not supported on VirtualDisplaySurface");
+ return INVALID_OPERATION;
+}
+
void VirtualDisplaySurface::updateQueueBufferOutput(
const QueueBufferOutput& qbo) {
uint32_t w, h, transformHint, numPendingBuffers;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 818d3eb..bd1cfb1 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -126,6 +126,8 @@
virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
virtual status_t setAutoRefresh(bool autoRefresh) override;
virtual status_t setDequeueTimeout(nsecs_t timeout) override;
+ virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+ sp<Fence>* outFence) override;
//
// Utility methods
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index f760200..dd88adb 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -44,8 +44,9 @@
return;
}
-EventThread::EventThread(const sp<VSyncSource>& src)
+EventThread::EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger)
: mVSyncSource(src),
+ mFlinger(flinger),
mUseSoftwareVSync(false),
mVsyncEnabled(false),
mDebugVsyncEnabled(false),
@@ -126,6 +127,9 @@
void EventThread::requestNextVsync(
const sp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock);
+
+ mFlinger.resyncWithRateLimit();
+
if (connection->count < 0) {
connection->count = 0;
mCondition.broadcast();
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 9ba179a..34654fa 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -77,7 +77,7 @@
public:
- EventThread(const sp<VSyncSource>& src);
+ EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger);
sp<Connection> createEventConnection() const;
status_t registerDisplayEventConnection(const sp<Connection>& connection);
@@ -116,6 +116,7 @@
// constants
sp<VSyncSource> mVSyncSource;
PowerHAL mPowerHAL;
+ SurfaceFlinger& mFlinger;
mutable Mutex mLock;
mutable Condition mCondition;
diff --git a/services/surfaceflinger/FenceTracker.cpp b/services/surfaceflinger/FenceTracker.cpp
index 7da1d93..885d712 100644
--- a/services/surfaceflinger/FenceTracker.cpp
+++ b/services/surfaceflinger/FenceTracker.cpp
@@ -14,9 +14,12 @@
* limitations under the License.
*/
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
#include <inttypes.h>
#include "FenceTracker.h"
#include "Layer.h"
+#include <utils/Trace.h>
namespace android {
@@ -78,6 +81,7 @@
}
void FenceTracker::checkFencesForCompletion() {
+ ATRACE_CALL();
for (auto& frame : mFrames) {
if (frame.retireFence != Fence::NO_FENCE) {
nsecs_t time = frame.retireFence->getSignalTime();
@@ -115,6 +119,7 @@
void FenceTracker::addFrame(nsecs_t refreshStartTime, sp<Fence> retireFence,
const Vector<sp<Layer>>& layers, sp<Fence> glDoneFence) {
+ ATRACE_CALL();
Mutex::Autolock lock(mMutex);
FrameRecord& frame = mFrames[mOffset];
FrameRecord& prevFrame = mFrames[(mOffset + MAX_FRAME_HISTORY - 1) %
diff --git a/services/surfaceflinger/GpuService.cpp b/services/surfaceflinger/GpuService.cpp
new file mode 100644
index 0000000..0c29971
--- /dev/null
+++ b/services/surfaceflinger/GpuService.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GpuService.h"
+
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+#include <vkjson.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class BpGpuService : public BpInterface<IGpuService>
+{
+public:
+ BpGpuService(const sp<IBinder>& impl) : BpInterface<IGpuService>(impl) {}
+};
+
+IMPLEMENT_META_INTERFACE(GpuService, "android.ui.IGpuService");
+
+status_t BnGpuService::onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case SHELL_COMMAND_TRANSACTION: {
+ int in = data.readFileDescriptor();
+ int out = data.readFileDescriptor();
+ int err = data.readFileDescriptor();
+ int argc = data.readInt32();
+ Vector<String16> args;
+ for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+ args.add(data.readString16());
+ }
+ return shellCommand(in, out, err, args);
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+namespace {
+ status_t cmd_help(int out);
+ status_t cmd_vkjson(int out, int err);
+}
+
+const char* const GpuService::SERVICE_NAME = "gpu";
+
+GpuService::GpuService() {}
+
+status_t GpuService::shellCommand(int /*in*/, int out, int err,
+ Vector<String16>& args)
+{
+ ALOGV("GpuService::shellCommand");
+ for (size_t i = 0, n = args.size(); i < n; i++)
+ ALOGV(" arg[%zu]: '%s'", i, String8(args[i]).string());
+
+ if (args[0] == String16("vkjson"))
+ return cmd_vkjson(out, err);
+ else if (args[0] == String16("help"))
+ return cmd_help(out);
+
+ return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+namespace {
+
+status_t cmd_help(int out) {
+ FILE* outs = fdopen(out, "w");
+ if (!outs) {
+ ALOGE("vkjson: failed to create out stream: %s (%d)", strerror(errno),
+ errno);
+ return BAD_VALUE;
+ }
+ fprintf(outs,
+ "GPU Service commands:\n"
+ " vkjson dump Vulkan device capabilities as JSON\n");
+ fclose(outs);
+ return NO_ERROR;
+}
+
+VkResult vkjsonPrint(FILE* out, FILE* err) {
+ VkResult result;
+
+ const VkApplicationInfo app_info = {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr,
+ "vkjson", 1, /* app name, version */
+ "", 0, /* engine name, version */
+ VK_API_VERSION
+ };
+ const VkInstanceCreateInfo instance_info = {
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr,
+ 0, /* flags */
+ &app_info,
+ 0, nullptr, /* layers */
+ 0, nullptr, /* extensions */
+ };
+ VkInstance instance;
+ result = vkCreateInstance(&instance_info, nullptr, &instance);
+ if (result != VK_SUCCESS) {
+ fprintf(err, "vkCreateInstance failed: %d\n", result);
+ return result;
+ }
+
+ uint32_t ngpu = 0;
+ result = vkEnumeratePhysicalDevices(instance, &ngpu, nullptr);
+ if (result != VK_SUCCESS) {
+ fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
+ return result;
+ }
+ std::vector<VkPhysicalDevice> gpus(ngpu, VK_NULL_HANDLE);
+ result = vkEnumeratePhysicalDevices(instance, &ngpu, gpus.data());
+ if (result != VK_SUCCESS) {
+ fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
+ return result;
+ }
+
+ for (size_t i = 0, n = gpus.size(); i < n; i++) {
+ auto props = VkJsonGetAllProperties(gpus[i]);
+ std::string json = VkJsonAllPropertiesToJson(props);
+ fwrite(json.data(), 1, json.size(), out);
+ if (i < n - 1)
+ fputc(',', out);
+ fputc('\n', out);
+ }
+
+ vkDestroyInstance(instance, nullptr);
+
+ return VK_SUCCESS;
+}
+
+status_t cmd_vkjson(int out, int err) {
+ int errnum;
+ FILE* outs = fdopen(out, "w");
+ if (!outs) {
+ errnum = errno;
+ ALOGE("vkjson: failed to create output stream: %s", strerror(errnum));
+ return -errnum;
+ }
+ FILE* errs = fdopen(err, "w");
+ if (!errs) {
+ errnum = errno;
+ ALOGE("vkjson: failed to create error stream: %s", strerror(errnum));
+ fclose(outs);
+ return -errnum;
+ }
+ fprintf(outs, "[\n");
+ VkResult result = vkjsonPrint(outs, errs);
+ fprintf(outs, "]\n");
+ fclose(errs);
+ fclose(outs);
+ return result >= 0 ? NO_ERROR : UNKNOWN_ERROR;
+}
+
+} // anonymous namespace
+
+} // namespace android
diff --git a/services/surfaceflinger/GpuService.h b/services/surfaceflinger/GpuService.h
new file mode 100644
index 0000000..b8c28d2
--- /dev/null
+++ b/services/surfaceflinger/GpuService.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GPUSERVICE_H
+#define ANDROID_GPUSERVICE_H
+
+#include <binder/IInterface.h>
+#include <cutils/compiler.h>
+
+namespace android {
+
+/*
+ * This class defines the Binder IPC interface for GPU-related queries and
+ * control.
+ */
+class IGpuService : public IInterface {
+public:
+ DECLARE_META_INTERFACE(GpuService);
+};
+
+class BnGpuService: public BnInterface<IGpuService> {
+protected:
+ virtual status_t shellCommand(int in, int out, int err,
+ Vector<String16>& args) = 0;
+
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags = 0) override;
+};
+
+class GpuService : public BnGpuService
+{
+public:
+ static const char* const SERVICE_NAME ANDROID_API;
+
+ GpuService() ANDROID_API;
+
+protected:
+ virtual status_t shellCommand(int in, int out, int err,
+ Vector<String16>& args) override;
+};
+
+} // namespace android
+
+#endif // ANDROID_GPUSERVICE_H
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a2c0462..c640f58 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -75,6 +75,7 @@
mSidebandStreamChanged(false),
mCurrentTransform(0),
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
+ mOverrideScalingMode(-1),
mCurrentOpacity(true),
mCurrentFrameNumber(0),
mRefreshPending(false),
@@ -250,7 +251,7 @@
ALOGE("Can't replace a frame on an empty queue");
return;
}
- mQueueItems.editItemAt(0) = item;
+ mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
// Wake up any pending callbacks
mLastFrameNumberReceived = item.mFrameNumber;
@@ -435,9 +436,11 @@
uint32_t invTransform = mCurrentTransform;
if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
/*
- * the code below applies the display's inverse transform to the buffer
+ * the code below applies the primary display's inverse transform to the
+ * buffer
*/
- uint32_t invTransformOrient = hw->getOrientationTransform();
+ uint32_t invTransformOrient =
+ DisplayDevice::getPrimaryDisplayOrientationTransform();
// calculate the inverse transform
if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) {
invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
@@ -634,13 +637,12 @@
if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
/*
- * the code below applies the display's inverse transform to the buffer
+ * the code below applies the primary display's inverse transform to the
+ * buffer
*/
-#ifdef USE_HWC2
- uint32_t invTransform = displayDevice->getOrientationTransform();
-#else
- uint32_t invTransform = hw->getOrientationTransform();
-#endif
+ uint32_t invTransform =
+ DisplayDevice::getPrimaryDisplayOrientationTransform();
+
uint32_t t_orientation = transform.getOrientation();
// calculate the inverse transform
if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
@@ -941,7 +943,8 @@
if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
/*
- * the code below applies the display's inverse transform to the texture transform
+ * the code below applies the primary display's inverse transform to
+ * the texture transform
*/
// create a 4x4 transform matrix from the display transform flags
@@ -950,7 +953,8 @@
const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1);
mat4 tr;
- uint32_t transform = hw->getOrientationTransform();
+ uint32_t transform =
+ DisplayDevice::getPrimaryDisplayOrientationTransform();
if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90)
tr = tr * rot90;
if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H)
@@ -1244,7 +1248,7 @@
}
bool Layer::isFixedSize() const {
- return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+ return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE;
}
bool Layer::isCropped() const {
@@ -1309,16 +1313,16 @@
mPendingStates.push_back(mCurrentState);
}
-void Layer::popPendingState() {
- auto oldFlags = mCurrentState.flags;
- mCurrentState = mPendingStates[0];
- mCurrentState.flags = (oldFlags & ~mCurrentState.mask) |
- (mCurrentState.flags & mCurrentState.mask);
+void Layer::popPendingState(State* stateToCommit) {
+ auto oldFlags = stateToCommit->flags;
+ *stateToCommit = mPendingStates[0];
+ stateToCommit->flags = (oldFlags & ~stateToCommit->mask) |
+ (stateToCommit->flags & stateToCommit->mask);
mPendingStates.removeAt(0);
}
-bool Layer::applyPendingStates() {
+bool Layer::applyPendingStates(State* stateToCommit) {
bool stateUpdateAvailable = false;
while (!mPendingStates.empty()) {
if (mPendingStates[0].handle != nullptr) {
@@ -1327,7 +1331,7 @@
// will be visually wrong, but it should keep us from getting
// into too much trouble.
ALOGE("[%s] No local sync point found", mName.string());
- popPendingState();
+ popPendingState(stateToCommit);
stateUpdateAvailable = true;
continue;
}
@@ -1345,7 +1349,7 @@
if (mRemoteSyncPoints.front()->frameIsAvailable()) {
// Apply the state update
- popPendingState();
+ popPendingState(stateToCommit);
stateUpdateAvailable = true;
// Signal our end of the sync point and then dispose of it
@@ -1355,7 +1359,7 @@
break;
}
} else {
- popPendingState();
+ popPendingState(stateToCommit);
stateUpdateAvailable = true;
}
}
@@ -1385,12 +1389,12 @@
ATRACE_CALL();
pushPendingState();
- if (!applyPendingStates()) {
+ Layer::State c = getCurrentState();
+ if (!applyPendingStates(&c)) {
return 0;
}
const Layer::State& s(getDrawingState());
- const Layer::State& c(getCurrentState());
const bool sizeChanged = (c.requested.w != s.requested.w) ||
(c.requested.h != s.requested.h);
@@ -1403,7 +1407,8 @@
" requested={ wh={%4u,%4u} }}\n"
" drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
" requested={ wh={%4u,%4u} }}\n",
- this, getName().string(), mCurrentTransform, mCurrentScalingMode,
+ this, getName().string(), mCurrentTransform,
+ getEffectiveScalingMode(),
c.active.w, c.active.h,
c.crop.left,
c.crop.top,
@@ -1454,8 +1459,7 @@
// this is used by Layer, which special cases resizes.
if (flags & eDontUpdateGeometryState) {
} else {
- Layer::State& editCurrentState(getCurrentState());
- editCurrentState.active = c.requested;
+ c.active = c.requested;
}
if (s.active != c.active) {
@@ -1475,12 +1479,12 @@
}
// Commit the transaction
- commitTransaction();
+ commitTransaction(c);
return flags;
}
-void Layer::commitTransaction() {
- mDrawingState = mCurrentState;
+void Layer::commitTransaction(const State& stateToCommit) {
+ mDrawingState = stateToCommit;
}
uint32_t Layer::getTransactionFlags(uint32_t flags) {
@@ -1581,6 +1585,20 @@
return true;
}
+bool Layer::setOverrideScalingMode(int32_t scalingMode) {
+ if (scalingMode == mOverrideScalingMode)
+ return false;
+ mOverrideScalingMode = scalingMode;
+ return true;
+}
+
+uint32_t Layer::getEffectiveScalingMode() const {
+ if (mOverrideScalingMode >= 0) {
+ return mOverrideScalingMode;
+ }
+ return mCurrentScalingMode;
+}
+
bool Layer::setLayerStack(uint32_t layerStack) {
if (mCurrentState.layerStack == layerStack)
return false;
@@ -1739,14 +1757,17 @@
bool& recomputeVisibleRegions;
bool stickyTransformSet;
const char* name;
+ int32_t overrideScalingMode;
Reject(Layer::State& front, Layer::State& current,
bool& recomputeVisibleRegions, bool stickySet,
- const char* name)
+ const char* name,
+ int32_t overrideScalingMode)
: front(front), current(current),
recomputeVisibleRegions(recomputeVisibleRegions),
stickyTransformSet(stickySet),
- name(name) {
+ name(name),
+ overrideScalingMode(overrideScalingMode) {
}
virtual bool reject(const sp<GraphicBuffer>& buf,
@@ -1764,7 +1785,9 @@
swap(bufWidth, bufHeight);
}
- bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+ int actualScalingMode = overrideScalingMode >= 0 ?
+ overrideScalingMode : item.mScalingMode;
+ bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
if (front.active != front.requested) {
if (isFixedSize ||
@@ -1840,7 +1863,8 @@
};
Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
- getProducerStickyTransform() != 0, mName.string());
+ getProducerStickyTransform() != 0, mName.string(),
+ mOverrideScalingMode);
// Check all of our local sync points to ensure that all transactions
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 1d73b43..7d085a4 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -160,6 +160,7 @@
bool setFinalCrop(const Rect& crop);
bool setLayerStack(uint32_t layerStack);
void deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber);
+ bool setOverrideScalingMode(int32_t overrideScalingMode);
// If we have received a new buffer this frame, we will pass its surface
// damage down to hardware composer. Otherwise, we must send a region with
@@ -431,7 +432,7 @@
virtual void onFrameReplaced(const BufferItem& item) override;
virtual void onSidebandStreamChanged() override;
- void commitTransaction();
+ void commitTransaction(const State& stateToCommit);
// needsLinearFiltering - true if this surface's state requires filtering
bool needsFiltering(const sp<const DisplayDevice>& hw) const;
@@ -500,8 +501,13 @@
bool addSyncPoint(const std::shared_ptr<SyncPoint>& point);
void pushPendingState();
- void popPendingState();
- bool applyPendingStates();
+ void popPendingState(State* stateToCommit);
+ bool applyPendingStates(State* stateToCommit);
+
+ // Returns mCurrentScaling mode (originating from the
+ // Client) or mOverrideScalingMode mode (originating from
+ // the Surface Controller) if set.
+ uint32_t getEffectiveScalingMode() const;
public:
void notifyAvailableFrames();
private:
@@ -536,6 +542,8 @@
Rect mCurrentCrop;
uint32_t mCurrentTransform;
uint32_t mCurrentScalingMode;
+ // We encode unset as -1.
+ int32_t mOverrideScalingMode;
bool mCurrentOpacity;
std::atomic<uint64_t> mCurrentFrameNumber;
bool mRefreshPending;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 75559da..e689127 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -143,6 +143,11 @@
return mProducer->setDequeueTimeout(timeout);
}
+status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+ sp<Fence>* outFence) {
+ return mProducer->getLastQueuedBuffer(outBuffer, outFence);
+}
+
IBinder* MonitoredProducer::onAsBinder() {
return IInterface::asBinder(mProducer).get();
}
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 441cf50..d2b4b43 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -59,6 +59,8 @@
virtual String8 getConsumerName() const override;
virtual uint64_t getNextFrameNumber() const override;
virtual status_t setDequeueTimeout(nsecs_t timeout) override;
+ virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+ sp<Fence>* outFence) override;
virtual IBinder* onAsBinder();
virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
virtual status_t setAutoRefresh(bool autoRefresh) override;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9b43849..a69b11b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -149,6 +149,7 @@
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
+ mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
mDaltonize(false),
@@ -331,11 +332,12 @@
class DispSyncSource : public VSyncSource, private DispSync::Callback {
public:
DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
- const char* label) :
+ const char* name) :
+ mName(name),
mValue(0),
mTraceVsync(traceVsync),
- mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
- mVsyncEventLabel(String8::format("VSYNC-%s", label)),
+ mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
+ mVsyncEventLabel(String8::format("VSYNC-%s", name)),
mDispSync(dispSync),
mCallbackMutex(),
mCallback(),
@@ -348,7 +350,7 @@
virtual void setVSyncEnabled(bool enable) {
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
- status_t err = mDispSync->addEventListener(mPhaseOffset,
+ status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -399,7 +401,7 @@
}
// Add a listener with the new offset
- err = mDispSync->addEventListener(mPhaseOffset,
+ err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -425,6 +427,8 @@
}
}
+ const char* const mName;
+
int mValue;
const bool mTraceVsync;
@@ -455,10 +459,10 @@
// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc);
+ mEventThread = new EventThread(vsyncSrc, *this);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc);
+ mSFEventThread = new EventThread(sfVsyncSrc, *this);
mEventQueue.setEventThread(mSFEventThread);
// Get a RenderEngine for the given display / config (can't fail)
@@ -715,6 +719,27 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) const {
+ Mutex::Autolock _l(mStateLock);
+
+ sp<const DisplayDevice> displayDevice(getDisplayDevice(display));
+ if (displayDevice == nullptr) {
+ ALOGE("getHdrCapabilities: Invalid display %p", displayDevice.get());
+ return BAD_VALUE;
+ }
+
+ std::unique_ptr<HdrCapabilities> capabilities =
+ mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId());
+ if (capabilities) {
+ std::swap(*outCapabilities, *capabilities);
+ } else {
+ return BAD_VALUE;
+ }
+
+ return NO_ERROR;
+}
+
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
@@ -775,7 +800,8 @@
if (makeAvailable) {
mHWVsyncAvailable = true;
} else if (!mHWVsyncAvailable) {
- ALOGE("resyncToHardwareVsync called when HW vsync unavailable");
+ // Hardware vsync is not currently available, so abort the resync
+ // attempt for now
return;
}
@@ -806,6 +832,13 @@
}
}
+void SurfaceFlinger::resyncWithRateLimit() {
+ static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
+ if (systemTime() - mLastSwapTime > kIgnoreDelay) {
+ resyncToHardwareVsync(false);
+ }
+}
+
void SurfaceFlinger::onVSyncReceived(int32_t type, nsecs_t timestamp) {
bool needsHwVsync = false;
@@ -910,7 +943,11 @@
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
+#ifdef ENABLE_FENCE_TRACKING
nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
+#else
+ nsecs_t refreshStartTime = 0;
+#endif
static nsecs_t previousExpectedPresent = 0;
nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0);
static bool previousFrameMissed = false;
@@ -1000,7 +1037,11 @@
}
}
+#ifdef ENABLE_FENCE_TRACKING
void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
+#else
+void SurfaceFlinger::postComposition(nsecs_t /*refreshStartTime*/)
+#endif
{
ATRACE_CALL();
ALOGV("postComposition");
@@ -1028,8 +1069,10 @@
}
}
+#ifdef ENABLE_FENCE_TRACKING
mFenceTracker.addFrame(refreshStartTime, presentFence,
hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence());
+#endif
if (mAnimCompositionPending) {
mAnimCompositionPending = false;
@@ -1238,6 +1281,7 @@
if (hwcId >= 0) {
mHwc->commit(hwcId);
}
+ displayDevice->onSwapBuffersCompleted();
if (displayId == 0) {
// Make the default display current because the VirtualDisplayDevice
// code cannot deal with dequeueBuffer() being called outside of the
@@ -1245,7 +1289,6 @@
// is allowed to (and does in some case) call dequeueBuffer().
displayDevice->makeCurrent(mEGLDisplay, mEGLContext);
}
- displayDevice->onSwapBuffersCompleted();
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
sp<Fence> releaseFence = Fence::NO_FENCE;
if (layer->getCompositionType(hwcId) == HWC2::Composition::Client) {
@@ -2260,6 +2303,11 @@
// We don't trigger a traversal here because if no other state is
// changed, we don't want this to cause any more work
}
+ if (what & layer_state_t::eOverrideScalingModeChanged) {
+ layer->setOverrideScalingMode(s.overrideScalingMode);
+ // We don't trigger a traversal here because if no other state is
+ // changed, we don't want this to cause any more work
+ }
}
return flags;
}
@@ -2548,12 +2596,14 @@
dumpAll = false;
}
+#ifdef ENABLE_FENCE_TRACKING
if ((index < numArgs) &&
(args[index] == String16("--fences"))) {
index++;
mFenceTracker.dump(&result);
dumpAll = false;
}
+#endif
}
if (dumpAll) {
@@ -2869,6 +2919,7 @@
case CLEAR_ANIMATION_FRAME_STATS:
case GET_ANIMATION_FRAME_STATS:
case SET_POWER_MODE:
+ case GET_HDR_CAPABILITIES:
{
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 37110b9..633e956 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -222,6 +222,8 @@
virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
virtual status_t clearAnimationFrameStats();
virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
+ virtual status_t getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) const;
/* ------------------------------------------------------------------------
* DeathRecipient interface
@@ -407,8 +409,11 @@
* VSync
*/
void enableHardwareVsync();
- void disableHardwareVsync(bool makeUnavailable);
void resyncToHardwareVsync(bool makeAvailable);
+ void disableHardwareVsync(bool makeUnavailable);
+public:
+ void resyncWithRateLimit();
+private:
/* ------------------------------------------------------------------------
* Debugging & dumpsys
@@ -520,7 +525,7 @@
static const size_t NUM_BUCKETS = 8; // < 1-7, 7+
nsecs_t mFrameBuckets[NUM_BUCKETS];
nsecs_t mTotalTime;
- nsecs_t mLastSwapTime;
+ std::atomic<nsecs_t> mLastSwapTime;
};
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 11f19d0..00700ab 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -45,6 +45,7 @@
#include <gui/GraphicBufferAlloc.h>
#include <ui/GraphicBufferAllocator.h>
+#include <ui/HdrCapabilities.h>
#include <ui/PixelFormat.h>
#include <ui/UiConfig.h>
@@ -147,6 +148,7 @@
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
+ mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
mDaltonize(false),
@@ -328,11 +330,12 @@
class DispSyncSource : public VSyncSource, private DispSync::Callback {
public:
DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
- const char* label) :
+ const char* name) :
+ mName(name),
mValue(0),
mTraceVsync(traceVsync),
- mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
- mVsyncEventLabel(String8::format("VSYNC-%s", label)),
+ mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
+ mVsyncEventLabel(String8::format("VSYNC-%s", name)),
mDispSync(dispSync),
mCallbackMutex(),
mCallback(),
@@ -345,7 +348,7 @@
virtual void setVSyncEnabled(bool enable) {
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
- status_t err = mDispSync->addEventListener(mPhaseOffset,
+ status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -396,7 +399,7 @@
}
// Add a listener with the new offset
- err = mDispSync->addEventListener(mPhaseOffset,
+ err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -422,6 +425,8 @@
}
}
+ const char* const mName;
+
int mValue;
const bool mTraceVsync;
@@ -451,10 +456,10 @@
// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc);
+ mEventThread = new EventThread(vsyncSrc, *this);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc);
+ mSFEventThread = new EventThread(sfVsyncSrc, *this);
mEventQueue.setEventThread(mSFEventThread);
// Initialize the H/W composer object. There may or may not be an
@@ -748,6 +753,13 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& /*display*/,
+ HdrCapabilities* outCapabilities) const {
+ // HWC1 does not provide HDR capabilities
+ *outCapabilities = HdrCapabilities();
+ return NO_ERROR;
+}
+
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
@@ -808,7 +820,8 @@
if (makeAvailable) {
mHWVsyncAvailable = true;
} else if (!mHWVsyncAvailable) {
- ALOGE("resyncToHardwareVsync called when HW vsync unavailable");
+ // Hardware vsync is not currently available, so abort the resync
+ // attempt for now
return;
}
@@ -839,6 +852,13 @@
}
}
+void SurfaceFlinger::resyncWithRateLimit() {
+ static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
+ if (systemTime() - mLastSwapTime > kIgnoreDelay) {
+ resyncToHardwareVsync(false);
+ }
+}
+
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
bool needsHwVsync = false;
@@ -927,7 +947,11 @@
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
+#ifdef ENABLE_FENCE_TRACKING
nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
+#else
+ nsecs_t refreshStartTime = 0;
+#endif
static nsecs_t previousExpectedPresent = 0;
nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0);
static bool previousFrameMissed = false;
@@ -1009,7 +1033,11 @@
}
}
+#ifdef ENABLE_FENCE_TRACKING
void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
+#else
+void SurfaceFlinger::postComposition(nsecs_t /*refreshStartTime*/)
+#endif
{
const LayerVector& layers(mDrawingState.layersSortedByZ);
const size_t count = layers.size();
@@ -1035,8 +1063,10 @@
}
}
+#ifdef ENABLE_FENCE_TRACKING
mFenceTracker.addFrame(refreshStartTime, presentFence,
hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence());
+#endif
if (mAnimCompositionPending) {
mAnimCompositionPending = false;
@@ -2298,6 +2328,11 @@
// We don't trigger a traversal here because if no other state is
// changed, we don't want this to cause any more work
}
+ if (what & layer_state_t::eOverrideScalingModeChanged) {
+ layer->setOverrideScalingMode(s.overrideScalingMode);
+ // We don't trigger a traversal here because if no other state is
+ // changed, we don't want this to cause any more work
+ }
}
return flags;
}
@@ -2586,12 +2621,14 @@
dumpAll = false;
}
+#ifdef ENABLE_FENCE_TRACKING
if ((index < numArgs) &&
(args[index] == String16("--fences"))) {
index++;
mFenceTracker.dump(&result);
dumpAll = false;
}
+#endif
}
if (dumpAll) {
@@ -2905,6 +2942,7 @@
case CLEAR_ANIMATION_FRAME_STATS:
case GET_ANIMATION_FRAME_STATS:
case SET_POWER_MODE:
+ case GET_HDR_CAPABILITIES:
{
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 4cd7aeb..97a1e8b 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -21,6 +21,7 @@
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+#include "GpuService.h"
#include "SurfaceFlinger.h"
using namespace android;
@@ -56,7 +57,11 @@
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
- // run in this thread
+ // publish GpuService
+ sp<GpuService> gpuservice = new GpuService();
+ sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
+
+ // run surface flinger in this thread
flinger->run();
return 0;
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index d7cb899..320fddb 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -459,4 +459,61 @@
}
}
+TEST_F(LayerUpdateTest, DeferredTransactionTest) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before anything");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 32, 32, 63, 63, 195);
+ sc->checkPixel( 96, 96, 195, 63, 63);
+ sc->checkPixel(160, 160, 63, 63, 195);
+ }
+
+ // set up two deferred transactions on different frames
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75));
+ mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
+ mSyncSurfaceControl->getSurface()->getNextFrameNumber());
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128,128));
+ mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
+ mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ {
+ SCOPED_TRACE("before any trigger");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 32, 32, 63, 63, 195);
+ sc->checkPixel( 96, 96, 195, 63, 63);
+ sc->checkPixel(160, 160, 63, 63, 195);
+ }
+
+ // should trigger the first deferred transaction, but not the second one
+ fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+ {
+ SCOPED_TRACE("after first trigger");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 32, 32, 63, 63, 195);
+ sc->checkPixel( 96, 96, 162, 63, 96);
+ sc->checkPixel(160, 160, 63, 63, 195);
+ }
+
+ // should show up immediately since it's not deferred
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(1.0));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ // trigger the second deferred transaction
+ fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+ {
+ SCOPED_TRACE("after second trigger");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 32, 32, 63, 63, 195);
+ sc->checkPixel( 96, 96, 63, 63, 195);
+ sc->checkPixel(160, 160, 195, 63, 63);
+ }
+}
+
}
diff --git a/vulkan/README.md b/vulkan/README.md
index 44747fd..9fba728 100644
--- a/vulkan/README.md
+++ b/vulkan/README.md
@@ -22,7 +22,7 @@
- You should now have `$GOPATH/bin/apic`. You might want to add `$GOPATH/bin` to your `$PATH`.
### Generating code
-To generate `libvulkan/dispatch_gen.*`,
+To generate `libvulkan/*_gen.*`,
- `$ cd libvulkan`
-- `$ apic template ../api/vulkan.api dispatch.tmpl`
-Similar for `nulldrv/null_driver_gen.*`.
\ No newline at end of file
+- `$ apic template ../api/vulkan.api code-generator.tmpl`
+Similar for `nulldrv/null_driver_gen.*`.
diff --git a/vulkan/api/platform.api b/vulkan/api/platform.api
index 980722d..7aa19e7 100644
--- a/vulkan/api/platform.api
+++ b/vulkan/api/platform.api
@@ -43,6 +43,7 @@
// VK_USE_PLATFORM_ANDROID_KHR
@internal class ANativeWindow {}
+@internal type void* buffer_handle_t
// VK_USE_PLATFORM_WIN32_KHR
@internal type void* HINSTANCE
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 10565ab..ae690a3 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -75,6 +75,9 @@
@extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_SPEC_VERSION 5
@extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_NAME "VK_KHR_win32_surface"
+@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 5
+@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME "VK_ANDROID_native_buffer"
+
@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION 1
@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME "VK_EXT_debug_report"
@@ -646,6 +649,9 @@
//@extension("VK_KHR_win32_surface")
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
+ //@extension("VK_ANDROID_native_buffer")
+ VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID = 1000010000,
+
//@extension("VK_EXT_debug_report")
VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = 1000011000,
}
@@ -2591,6 +2597,16 @@
platform.HWND hwnd
}
+@extension("VK_ANDROID_native_buffer")
+class VkNativeBufferANDROID {
+ VkStructureType sType
+ const void* pNext
+ platform.buffer_handle_t handle
+ int stride
+ int format
+ int usage
+}
+
@extension("VK_EXT_debug_report")
class VkDebugReportCallbackCreateInfoEXT {
VkStructureType sType
@@ -5134,6 +5150,35 @@
return ?
}
+@extension("VK_ANDROID_native_buffer")
+cmd VkResult vkGetSwapchainGrallocUsageANDROID(
+ VkDevice device,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
+ int* grallocUsage) {
+ return ?
+}
+
+@extension("VK_ANDROID_native_buffer")
+cmd VkResult vkAcquireImageANDROID(
+ VkDevice device,
+ VkImage image,
+ int nativeFenceFd,
+ VkSemaphore semaphore,
+ VkFence fence) {
+ return ?
+}
+
+@extension("VK_ANDROID_native_buffer")
+cmd VkResult vkQueueSignalReleaseImageANDROID(
+ VkQueue queue,
+ u32 waitSemaphoreCount,
+ const VkSemaphore* pWaitSemaphores,
+ VkImage image,
+ int* pNativeFenceFd) {
+ return ?
+}
+
@extension("VK_EXT_debug_report")
@external type void* PFN_vkDebugReportCallbackEXT
@extension("VK_EXT_debug_report")
diff --git a/vulkan/include/vulkan/vk_layer_interface.h b/vulkan/include/vulkan/vk_layer_interface.h
index 5aae51e..f2a5232 100644
--- a/vulkan/include/vulkan/vk_layer_interface.h
+++ b/vulkan/include/vulkan/vk_layer_interface.h
@@ -14,10 +14,6 @@
* The above copyright notice(s) and this permission notice shall be included in
* all copies or substantial portions of the Materials.
*
- * The Materials are Confidential Information as defined by the Khronos
- * Membership Agreement until designated non-confidential by Khronos, at which
- * point this condition clause shall be removed.
- *
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -37,38 +33,18 @@
typedef enum VkLayerFunction_ {
VK_LAYER_FUNCTION_LINK = 0,
- VK_LAYER_FUNCTION_DEVICE = 1,
- VK_LAYER_FUNCTION_INSTANCE = 2
+ VK_LAYER_FUNCTION_DATA_CALLBACK = 1
} VkLayerFunction;
-/*
- * When creating the device chain the loader needs to pass
- * down information about it's device structure needed at
- * the end of the chain. Passing the data via the
- * VkLayerInstanceInfo avoids issues with finding the
- * exact instance being used.
- */
-typedef struct VkLayerInstanceInfo_ {
- void* instance_info;
- PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
-} VkLayerInstanceInfo;
-
typedef struct VkLayerInstanceLink_ {
struct VkLayerInstanceLink_* pNext;
PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
} VkLayerInstanceLink;
-/*
- * When creating the device chain the loader needs to pass
- * down information about it's device structure needed at
- * the end of the chain. Passing the data via the
- * VkLayerDeviceInfo avoids issues with finding the
- * exact instance being used.
- */
-typedef struct VkLayerDeviceInfo_ {
- void* device_info;
- PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
-} VkLayerDeviceInfo;
+typedef VkResult(VKAPI_PTR* PFN_vkSetInstanceLoaderData)(VkInstance instance,
+ void* object);
+typedef VkResult(VKAPI_PTR* PFN_vkSetDeviceLoaderData)(VkDevice device,
+ void* object);
typedef struct {
VkStructureType sType; // VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
@@ -76,7 +52,7 @@
VkLayerFunction function;
union {
VkLayerInstanceLink* pLayerInfo;
- VkLayerInstanceInfo instanceInfo;
+ PFN_vkSetInstanceLoaderData pfnSetInstanceLoaderData;
} u;
} VkLayerInstanceCreateInfo;
@@ -92,6 +68,6 @@
VkLayerFunction function;
union {
VkLayerDeviceLink* pLayerInfo;
- VkLayerDeviceInfo deviceInfo;
+ PFN_vkSetDeviceLoaderData pfnSetDeviceLoaderData;
} u;
} VkLayerDeviceCreateInfo;
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
index 85b8ab2..71788a9 100644
--- a/vulkan/libvulkan/Android.mk
+++ b/vulkan/libvulkan/Android.mk
@@ -19,6 +19,7 @@
LOCAL_SANITIZE := integer
LOCAL_CFLAGS := -DLOG_TAG=\"vulkan\" \
+ -DVK_USE_PLATFORM_ANDROID_KHR \
-std=c99 -fvisibility=hidden -fstrict-aliasing \
-Weverything -Werror \
-Wno-padded \
@@ -26,7 +27,6 @@
-Wno-undef
#LOCAL_CFLAGS += -DLOG_NDEBUG=0
LOCAL_CPPFLAGS := -std=c++14 \
- -fexceptions \
-Wno-c99-extensions \
-Wno-c++98-compat-pedantic \
-Wno-exit-time-destructors \
@@ -38,10 +38,13 @@
system/core/libsync/include
LOCAL_SRC_FILES := \
+ api.cpp \
+ api_gen.cpp \
debug_report.cpp \
- dispatch_gen.cpp \
+ driver.cpp \
+ driver_gen.cpp \
layers_extensions.cpp \
- loader.cpp \
+ stubhal.cpp \
swapchain.cpp \
vulkan_loader_data.cpp
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
new file mode 100644
index 0000000..e7f10b3
--- /dev/null
+++ b/vulkan/libvulkan/api.cpp
@@ -0,0 +1,1174 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// The API layer of the loader defines Vulkan API and manages layers. The
+// entrypoints are generated and defined in api_dispatch.cpp. Most of them
+// simply find the dispatch table and jump.
+//
+// There are a few of them requiring manual code for things such as layer
+// discovery or chaining. They call into functions defined in this file.
+
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <mutex>
+#include <new>
+#include <utility>
+#include <cutils/properties.h>
+#include <log/log.h>
+
+#include <vulkan/vk_layer_interface.h>
+#include "api.h"
+#include "driver.h"
+#include "layers_extensions.h"
+
+namespace vulkan {
+namespace api {
+
+namespace {
+
+// Provide overridden layer names when there are implicit layers. No effect
+// otherwise.
+class OverrideLayerNames {
+ public:
+ OverrideLayerNames(bool is_instance, const VkAllocationCallbacks& allocator)
+ : is_instance_(is_instance),
+ allocator_(allocator),
+ scope_(VK_SYSTEM_ALLOCATION_SCOPE_COMMAND),
+ names_(nullptr),
+ name_count_(0),
+ implicit_layers_() {
+ implicit_layers_.result = VK_SUCCESS;
+ }
+
+ ~OverrideLayerNames() {
+ allocator_.pfnFree(allocator_.pUserData, names_);
+ allocator_.pfnFree(allocator_.pUserData, implicit_layers_.elements);
+ allocator_.pfnFree(allocator_.pUserData, implicit_layers_.name_pool);
+ }
+
+ VkResult Parse(const char* const* names, uint32_t count) {
+ AddImplicitLayers();
+
+ const auto& arr = implicit_layers_;
+ if (arr.result != VK_SUCCESS)
+ return arr.result;
+
+ // no need to override when there is no implicit layer
+ if (!arr.count)
+ return VK_SUCCESS;
+
+ names_ = AllocateNameArray(arr.count + count);
+ if (!names_)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ // add implicit layer names
+ for (uint32_t i = 0; i < arr.count; i++)
+ names_[i] = GetImplicitLayerName(i);
+
+ name_count_ = arr.count;
+
+ // add explicit layer names
+ for (uint32_t i = 0; i < count; i++) {
+ // ignore explicit layers that are also implicit
+ if (IsImplicitLayer(names[i]))
+ continue;
+
+ names_[name_count_++] = names[i];
+ }
+
+ return VK_SUCCESS;
+ }
+
+ const char* const* Names() const { return names_; }
+
+ uint32_t Count() const { return name_count_; }
+
+ private:
+ struct ImplicitLayer {
+ int priority;
+ size_t name_offset;
+ };
+
+ struct ImplicitLayerArray {
+ ImplicitLayer* elements;
+ uint32_t max_count;
+ uint32_t count;
+
+ char* name_pool;
+ size_t max_pool_size;
+ size_t pool_size;
+
+ VkResult result;
+ };
+
+ void AddImplicitLayers() {
+ if (!driver::Debuggable())
+ return;
+
+ ParseDebugVulkanLayers();
+ property_list(ParseDebugVulkanLayer, this);
+
+ // sort by priorities
+ auto& arr = implicit_layers_;
+ std::sort(arr.elements, arr.elements + arr.count,
+ [](const ImplicitLayer& a, const ImplicitLayer& b) {
+ return (a.priority < b.priority);
+ });
+ }
+
+ void ParseDebugVulkanLayers() {
+ // debug.vulkan.layers specifies colon-separated layer names
+ char prop[PROPERTY_VALUE_MAX];
+ if (!property_get("debug.vulkan.layers", prop, ""))
+ return;
+
+ // assign negative/high priorities to them
+ int prio = -PROPERTY_VALUE_MAX;
+
+ const char* p = prop;
+ const char* delim;
+ while ((delim = strchr(p, ':'))) {
+ if (delim > p)
+ AddImplicitLayer(prio, p, static_cast<size_t>(delim - p));
+
+ prio++;
+ p = delim + 1;
+ }
+
+ if (p[0] != '\0')
+ AddImplicitLayer(prio, p, strlen(p));
+ }
+
+ static void ParseDebugVulkanLayer(const char* key,
+ const char* val,
+ void* user_data) {
+ static const char prefix[] = "debug.vulkan.layer.";
+ const size_t prefix_len = sizeof(prefix) - 1;
+
+ if (strncmp(key, prefix, prefix_len) || val[0] == '\0')
+ return;
+ key += prefix_len;
+
+ // debug.vulkan.layer.<priority>
+ int priority = -1;
+ if (key[0] >= '0' && key[0] <= '9')
+ priority = atoi(key);
+
+ if (priority < 0) {
+ ALOGW("Ignored implicit layer %s with invalid priority %s", val,
+ key);
+ return;
+ }
+
+ OverrideLayerNames& override_layers =
+ *reinterpret_cast<OverrideLayerNames*>(user_data);
+ override_layers.AddImplicitLayer(priority, val, strlen(val));
+ }
+
+ void AddImplicitLayer(int priority, const char* name, size_t len) {
+ if (!GrowImplicitLayerArray(1, 0))
+ return;
+
+ auto& arr = implicit_layers_;
+ auto& layer = arr.elements[arr.count++];
+
+ layer.priority = priority;
+ layer.name_offset = AddImplicitLayerName(name, len);
+
+ ALOGV("Added implicit layer %s", GetImplicitLayerName(arr.count - 1));
+ }
+
+ size_t AddImplicitLayerName(const char* name, size_t len) {
+ if (!GrowImplicitLayerArray(0, len + 1))
+ return 0;
+
+ // add the name to the pool
+ auto& arr = implicit_layers_;
+ size_t offset = arr.pool_size;
+ char* dst = arr.name_pool + offset;
+
+ std::copy(name, name + len, dst);
+ dst[len] = '\0';
+
+ arr.pool_size += len + 1;
+
+ return offset;
+ }
+
+ bool GrowImplicitLayerArray(uint32_t layer_count, size_t name_size) {
+ const uint32_t initial_max_count = 16;
+ const size_t initial_max_pool_size = 512;
+
+ auto& arr = implicit_layers_;
+
+ // grow the element array if needed
+ while (arr.count + layer_count > arr.max_count) {
+ uint32_t new_max_count =
+ (arr.max_count) ? (arr.max_count << 1) : initial_max_count;
+ void* new_mem = nullptr;
+
+ if (new_max_count > arr.max_count) {
+ new_mem = allocator_.pfnReallocation(
+ allocator_.pUserData, arr.elements,
+ sizeof(ImplicitLayer) * new_max_count,
+ alignof(ImplicitLayer), scope_);
+ }
+
+ if (!new_mem) {
+ arr.result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ arr.count = 0;
+ return false;
+ }
+
+ arr.elements = reinterpret_cast<ImplicitLayer*>(new_mem);
+ arr.max_count = new_max_count;
+ }
+
+ // grow the name pool if needed
+ while (arr.pool_size + name_size > arr.max_pool_size) {
+ size_t new_max_pool_size = (arr.max_pool_size)
+ ? (arr.max_pool_size << 1)
+ : initial_max_pool_size;
+ void* new_mem = nullptr;
+
+ if (new_max_pool_size > arr.max_pool_size) {
+ new_mem = allocator_.pfnReallocation(
+ allocator_.pUserData, arr.name_pool, new_max_pool_size,
+ alignof(char), scope_);
+ }
+
+ if (!new_mem) {
+ arr.result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ arr.pool_size = 0;
+ return false;
+ }
+
+ arr.name_pool = reinterpret_cast<char*>(new_mem);
+ arr.max_pool_size = new_max_pool_size;
+ }
+
+ return true;
+ }
+
+ const char* GetImplicitLayerName(uint32_t index) const {
+ const auto& arr = implicit_layers_;
+
+ // this may return nullptr when arr.result is not VK_SUCCESS
+ return implicit_layers_.name_pool + arr.elements[index].name_offset;
+ }
+
+ bool IsImplicitLayer(const char* name) const {
+ const auto& arr = implicit_layers_;
+
+ for (uint32_t i = 0; i < arr.count; i++) {
+ if (strcmp(name, GetImplicitLayerName(i)) == 0)
+ return true;
+ }
+
+ return false;
+ }
+
+ const char** AllocateNameArray(uint32_t count) const {
+ return reinterpret_cast<const char**>(allocator_.pfnAllocation(
+ allocator_.pUserData, sizeof(const char*) * count,
+ alignof(const char*), scope_));
+ }
+
+ const bool is_instance_;
+ const VkAllocationCallbacks& allocator_;
+ const VkSystemAllocationScope scope_;
+
+ const char** names_;
+ uint32_t name_count_;
+
+ ImplicitLayerArray implicit_layers_;
+};
+
+// Provide overridden extension names when there are implicit extensions.
+// No effect otherwise.
+//
+// This is used only to enable VK_EXT_debug_report.
+class OverrideExtensionNames {
+ public:
+ OverrideExtensionNames(bool is_instance,
+ const VkAllocationCallbacks& allocator)
+ : is_instance_(is_instance),
+ allocator_(allocator),
+ scope_(VK_SYSTEM_ALLOCATION_SCOPE_COMMAND),
+ names_(nullptr),
+ name_count_(0),
+ install_debug_callback_(false) {}
+
+ ~OverrideExtensionNames() {
+ allocator_.pfnFree(allocator_.pUserData, names_);
+ }
+
+ VkResult Parse(const char* const* names, uint32_t count) {
+ // this is only for debug.vulkan.enable_callback
+ if (!EnableDebugCallback())
+ return VK_SUCCESS;
+
+ names_ = AllocateNameArray(count + 1);
+ if (!names_)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ std::copy(names, names + count, names_);
+
+ name_count_ = count;
+ names_[name_count_++] = "VK_EXT_debug_report";
+
+ install_debug_callback_ = true;
+
+ return VK_SUCCESS;
+ }
+
+ const char* const* Names() const { return names_; }
+
+ uint32_t Count() const { return name_count_; }
+
+ bool InstallDebugCallback() const { return install_debug_callback_; }
+
+ private:
+ bool EnableDebugCallback() const {
+ return (is_instance_ && driver::Debuggable() &&
+ property_get_bool("debug.vulkan.enable_callback", false));
+ }
+
+ const char** AllocateNameArray(uint32_t count) const {
+ return reinterpret_cast<const char**>(allocator_.pfnAllocation(
+ allocator_.pUserData, sizeof(const char*) * count,
+ alignof(const char*), scope_));
+ }
+
+ const bool is_instance_;
+ const VkAllocationCallbacks& allocator_;
+ const VkSystemAllocationScope scope_;
+
+ const char** names_;
+ uint32_t name_count_;
+ bool install_debug_callback_;
+};
+
+// vkCreateInstance and vkCreateDevice helpers with support for layer
+// chaining.
+class LayerChain {
+ public:
+ static VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkInstance* instance_out);
+
+ static VkResult CreateDevice(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkDevice* dev_out);
+
+ static void DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* allocator);
+
+ static void DestroyDevice(VkDevice dev,
+ const VkAllocationCallbacks* allocator);
+
+ private:
+ struct ActiveLayer {
+ LayerRef ref;
+ union {
+ VkLayerInstanceLink instance_link;
+ VkLayerDeviceLink device_link;
+ };
+ };
+
+ LayerChain(bool is_instance, const VkAllocationCallbacks& allocator);
+ ~LayerChain();
+
+ VkResult ActivateLayers(const char* const* layer_names,
+ uint32_t layer_count,
+ const char* const* extension_names,
+ uint32_t extension_count);
+ ActiveLayer* AllocateLayerArray(uint32_t count) const;
+ VkResult LoadLayer(ActiveLayer& layer, const char* name);
+ void SetupLayerLinks();
+
+ bool Empty() const;
+ void ModifyCreateInfo(VkInstanceCreateInfo& info);
+ void ModifyCreateInfo(VkDeviceCreateInfo& info);
+
+ VkResult Create(const VkInstanceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkInstance* instance_out);
+
+ VkResult Create(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkDevice* dev_out);
+
+ VkResult ValidateExtensions(const char* const* extension_names,
+ uint32_t extension_count);
+ VkResult ValidateExtensions(VkPhysicalDevice physical_dev,
+ const char* const* extension_names,
+ uint32_t extension_count);
+ VkExtensionProperties* AllocateDriverExtensionArray(uint32_t count) const;
+ bool IsLayerExtension(const char* name) const;
+ bool IsDriverExtension(const char* name) const;
+
+ template <typename DataType>
+ void StealLayers(DataType& data);
+
+ static void DestroyLayers(ActiveLayer* layers,
+ uint32_t count,
+ const VkAllocationCallbacks& allocator);
+
+ static VKAPI_ATTR VkResult SetInstanceLoaderData(VkInstance instance,
+ void* object);
+ static VKAPI_ATTR VkResult SetDeviceLoaderData(VkDevice device,
+ void* object);
+
+ static VKAPI_ATTR VkBool32
+ DebugReportCallback(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT obj_type,
+ uint64_t obj,
+ size_t location,
+ int32_t msg_code,
+ const char* layer_prefix,
+ const char* msg,
+ void* user_data);
+
+ const bool is_instance_;
+ const VkAllocationCallbacks& allocator_;
+
+ OverrideLayerNames override_layers_;
+ OverrideExtensionNames override_extensions_;
+
+ ActiveLayer* layers_;
+ uint32_t layer_count_;
+
+ PFN_vkGetInstanceProcAddr get_instance_proc_addr_;
+ PFN_vkGetDeviceProcAddr get_device_proc_addr_;
+
+ union {
+ VkLayerInstanceCreateInfo instance_chain_info_[2];
+ VkLayerDeviceCreateInfo device_chain_info_[2];
+ };
+
+ VkExtensionProperties* driver_extensions_;
+ uint32_t driver_extension_count_;
+ std::bitset<driver::ProcHook::EXTENSION_COUNT> enabled_extensions_;
+};
+
+LayerChain::LayerChain(bool is_instance, const VkAllocationCallbacks& allocator)
+ : is_instance_(is_instance),
+ allocator_(allocator),
+ override_layers_(is_instance, allocator),
+ override_extensions_(is_instance, allocator),
+ layers_(nullptr),
+ layer_count_(0),
+ get_instance_proc_addr_(nullptr),
+ get_device_proc_addr_(nullptr),
+ driver_extensions_(nullptr),
+ driver_extension_count_(0) {
+ enabled_extensions_.set(driver::ProcHook::EXTENSION_CORE);
+}
+
+LayerChain::~LayerChain() {
+ allocator_.pfnFree(allocator_.pUserData, driver_extensions_);
+ DestroyLayers(layers_, layer_count_, allocator_);
+}
+
+VkResult LayerChain::ActivateLayers(const char* const* layer_names,
+ uint32_t layer_count,
+ const char* const* extension_names,
+ uint32_t extension_count) {
+ VkResult result = override_layers_.Parse(layer_names, layer_count);
+ if (result != VK_SUCCESS)
+ return result;
+
+ result = override_extensions_.Parse(extension_names, extension_count);
+ if (result != VK_SUCCESS)
+ return result;
+
+ if (override_layers_.Count()) {
+ layer_names = override_layers_.Names();
+ layer_count = override_layers_.Count();
+ }
+
+ if (!layer_count) {
+ // point head of chain to the driver
+ get_instance_proc_addr_ = driver::GetInstanceProcAddr;
+ if (!is_instance_)
+ get_device_proc_addr_ = driver::GetDeviceProcAddr;
+
+ return VK_SUCCESS;
+ }
+
+ layers_ = AllocateLayerArray(layer_count);
+ if (!layers_)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ // load layers
+ for (uint32_t i = 0; i < layer_count; i++) {
+ result = LoadLayer(layers_[i], layer_names[i]);
+ if (result != VK_SUCCESS)
+ return result;
+
+ // count loaded layers for proper destructions on errors
+ layer_count_++;
+ }
+
+ SetupLayerLinks();
+
+ return VK_SUCCESS;
+}
+
+LayerChain::ActiveLayer* LayerChain::AllocateLayerArray(uint32_t count) const {
+ VkSystemAllocationScope scope = (is_instance_)
+ ? VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
+ : VK_SYSTEM_ALLOCATION_SCOPE_DEVICE;
+
+ return reinterpret_cast<ActiveLayer*>(allocator_.pfnAllocation(
+ allocator_.pUserData, sizeof(ActiveLayer) * count, alignof(ActiveLayer),
+ scope));
+}
+
+VkResult LayerChain::LoadLayer(ActiveLayer& layer, const char* name) {
+ if (is_instance_)
+ new (&layer) ActiveLayer{GetInstanceLayerRef(name), {}};
+ else
+ new (&layer) ActiveLayer{GetDeviceLayerRef(name), {}};
+
+ if (!layer.ref) {
+ ALOGE("Failed to load layer %s", name);
+ layer.ref.~LayerRef();
+ return VK_ERROR_LAYER_NOT_PRESENT;
+ }
+
+ ALOGI("Loaded %s layer %s", (is_instance_) ? "instance" : "device", name);
+
+ return VK_SUCCESS;
+}
+
+void LayerChain::SetupLayerLinks() {
+ if (is_instance_) {
+ for (uint32_t i = 0; i < layer_count_; i++) {
+ ActiveLayer& layer = layers_[i];
+
+ // point head of chain to the first layer
+ if (i == 0)
+ get_instance_proc_addr_ = layer.ref.GetGetInstanceProcAddr();
+
+ // point tail of chain to the driver
+ if (i == layer_count_ - 1) {
+ layer.instance_link.pNext = nullptr;
+ layer.instance_link.pfnNextGetInstanceProcAddr =
+ driver::GetInstanceProcAddr;
+ break;
+ }
+
+ const ActiveLayer& next = layers_[i + 1];
+
+ // const_cast as some naughty layers want to modify our links!
+ layer.instance_link.pNext =
+ const_cast<VkLayerInstanceLink*>(&next.instance_link);
+ layer.instance_link.pfnNextGetInstanceProcAddr =
+ next.ref.GetGetInstanceProcAddr();
+ }
+ } else {
+ for (uint32_t i = 0; i < layer_count_; i++) {
+ ActiveLayer& layer = layers_[i];
+
+ // point head of chain to the first layer
+ if (i == 0) {
+ get_instance_proc_addr_ = layer.ref.GetGetInstanceProcAddr();
+ get_device_proc_addr_ = layer.ref.GetGetDeviceProcAddr();
+ }
+
+ // point tail of chain to the driver
+ if (i == layer_count_ - 1) {
+ layer.device_link.pNext = nullptr;
+ layer.device_link.pfnNextGetInstanceProcAddr =
+ driver::GetInstanceProcAddr;
+ layer.device_link.pfnNextGetDeviceProcAddr =
+ driver::GetDeviceProcAddr;
+ break;
+ }
+
+ const ActiveLayer& next = layers_[i + 1];
+
+ // const_cast as some naughty layers want to modify our links!
+ layer.device_link.pNext =
+ const_cast<VkLayerDeviceLink*>(&next.device_link);
+ layer.device_link.pfnNextGetInstanceProcAddr =
+ next.ref.GetGetInstanceProcAddr();
+ layer.device_link.pfnNextGetDeviceProcAddr =
+ next.ref.GetGetDeviceProcAddr();
+ }
+ }
+}
+
+bool LayerChain::Empty() const {
+ return (!layer_count_ && !override_layers_.Count() &&
+ !override_extensions_.Count());
+}
+
+void LayerChain::ModifyCreateInfo(VkInstanceCreateInfo& info) {
+ if (layer_count_) {
+ auto& link_info = instance_chain_info_[1];
+ link_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+ link_info.pNext = info.pNext;
+ link_info.function = VK_LAYER_FUNCTION_LINK;
+ link_info.u.pLayerInfo = &layers_[0].instance_link;
+
+ auto& cb_info = instance_chain_info_[0];
+ cb_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+ cb_info.pNext = &link_info;
+ cb_info.function = VK_LAYER_FUNCTION_DATA_CALLBACK;
+ cb_info.u.pfnSetInstanceLoaderData = SetInstanceLoaderData;
+
+ info.pNext = &cb_info;
+ }
+
+ if (override_layers_.Count()) {
+ info.enabledLayerCount = override_layers_.Count();
+ info.ppEnabledLayerNames = override_layers_.Names();
+ }
+
+ if (override_extensions_.Count()) {
+ info.enabledExtensionCount = override_extensions_.Count();
+ info.ppEnabledExtensionNames = override_extensions_.Names();
+ }
+}
+
+void LayerChain::ModifyCreateInfo(VkDeviceCreateInfo& info) {
+ if (layer_count_) {
+ auto& link_info = device_chain_info_[1];
+ link_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
+ link_info.pNext = info.pNext;
+ link_info.function = VK_LAYER_FUNCTION_LINK;
+ link_info.u.pLayerInfo = &layers_[0].device_link;
+
+ auto& cb_info = device_chain_info_[0];
+ cb_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
+ cb_info.pNext = &link_info;
+ cb_info.function = VK_LAYER_FUNCTION_DATA_CALLBACK;
+ cb_info.u.pfnSetDeviceLoaderData = SetDeviceLoaderData;
+
+ info.pNext = &cb_info;
+ }
+
+ if (override_layers_.Count()) {
+ info.enabledLayerCount = override_layers_.Count();
+ info.ppEnabledLayerNames = override_layers_.Names();
+ }
+
+ if (override_extensions_.Count()) {
+ info.enabledExtensionCount = override_extensions_.Count();
+ info.ppEnabledExtensionNames = override_extensions_.Names();
+ }
+}
+
+VkResult LayerChain::Create(const VkInstanceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkInstance* instance_out) {
+ VkResult result = ValidateExtensions(create_info->ppEnabledExtensionNames,
+ create_info->enabledExtensionCount);
+ if (result != VK_SUCCESS)
+ return result;
+
+ // call down the chain
+ PFN_vkCreateInstance create_instance =
+ reinterpret_cast<PFN_vkCreateInstance>(
+ get_instance_proc_addr_(VK_NULL_HANDLE, "vkCreateInstance"));
+ VkInstance instance;
+ result = create_instance(create_info, allocator, &instance);
+ if (result != VK_SUCCESS)
+ return result;
+
+ // initialize InstanceData
+ InstanceData& data = GetData(instance);
+
+ data.instance = instance;
+
+ if (!InitDispatchTable(instance, get_instance_proc_addr_,
+ enabled_extensions_)) {
+ if (data.dispatch.DestroyInstance)
+ data.dispatch.DestroyInstance(instance, allocator);
+
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ // install debug report callback
+ if (override_extensions_.InstallDebugCallback()) {
+ PFN_vkCreateDebugReportCallbackEXT create_debug_report_callback =
+ reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+ get_instance_proc_addr_(instance,
+ "vkCreateDebugReportCallbackEXT"));
+ data.destroy_debug_callback =
+ reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+ get_instance_proc_addr_(instance,
+ "vkDestroyDebugReportCallbackEXT"));
+ if (!create_debug_report_callback || !data.destroy_debug_callback) {
+ ALOGE("Broken VK_EXT_debug_report support");
+ data.dispatch.DestroyInstance(instance, allocator);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ VkDebugReportCallbackCreateInfoEXT debug_callback_info = {};
+ debug_callback_info.sType =
+ VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
+ debug_callback_info.flags =
+ VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
+ debug_callback_info.pfnCallback = DebugReportCallback;
+
+ VkDebugReportCallbackEXT debug_callback;
+ result = create_debug_report_callback(instance, &debug_callback_info,
+ nullptr, &debug_callback);
+ if (result != VK_SUCCESS) {
+ ALOGE("Failed to install debug report callback");
+ data.dispatch.DestroyInstance(instance, allocator);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ data.debug_callback = debug_callback;
+
+ ALOGI("Installed debug report callback");
+ }
+
+ StealLayers(data);
+
+ *instance_out = instance;
+
+ return VK_SUCCESS;
+}
+
+VkResult LayerChain::Create(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkDevice* dev_out) {
+ VkResult result =
+ ValidateExtensions(physical_dev, create_info->ppEnabledExtensionNames,
+ create_info->enabledExtensionCount);
+ if (result != VK_SUCCESS)
+ return result;
+
+ // call down the chain
+ //
+ // TODO Instance call chain available at
+ // GetData(physical_dev).dispatch.CreateDevice is ignored. Is that
+ // right?
+ VkInstance instance = GetData(physical_dev).instance;
+ PFN_vkCreateDevice create_device = reinterpret_cast<PFN_vkCreateDevice>(
+ get_instance_proc_addr_(instance, "vkCreateDevice"));
+ VkDevice dev;
+ result = create_device(physical_dev, create_info, allocator, &dev);
+ if (result != VK_SUCCESS)
+ return result;
+
+ // initialize DeviceData
+ DeviceData& data = GetData(dev);
+
+ if (!InitDispatchTable(dev, get_device_proc_addr_, enabled_extensions_)) {
+ if (data.dispatch.DestroyDevice)
+ data.dispatch.DestroyDevice(dev, allocator);
+
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ StealLayers(data);
+
+ *dev_out = dev;
+
+ return VK_SUCCESS;
+}
+
+VkResult LayerChain::ValidateExtensions(const char* const* extension_names,
+ uint32_t extension_count) {
+ if (!extension_count)
+ return VK_SUCCESS;
+
+ // query driver instance extensions
+ uint32_t count;
+ VkResult result =
+ EnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
+ if (result == VK_SUCCESS && count) {
+ driver_extensions_ = AllocateDriverExtensionArray(count);
+ result = (driver_extensions_) ? EnumerateInstanceExtensionProperties(
+ nullptr, &count, driver_extensions_)
+ : VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ if (result != VK_SUCCESS)
+ return result;
+
+ driver_extension_count_ = count;
+
+ for (uint32_t i = 0; i < extension_count; i++) {
+ const char* name = extension_names[i];
+ if (!IsLayerExtension(name) && !IsDriverExtension(name)) {
+ ALOGE("Failed to enable missing instance extension %s", name);
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ auto ext_bit = driver::GetProcHookExtension(name);
+ if (ext_bit != driver::ProcHook::EXTENSION_UNKNOWN)
+ enabled_extensions_.set(ext_bit);
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult LayerChain::ValidateExtensions(VkPhysicalDevice physical_dev,
+ const char* const* extension_names,
+ uint32_t extension_count) {
+ if (!extension_count)
+ return VK_SUCCESS;
+
+ // query driver device extensions
+ uint32_t count;
+ VkResult result = EnumerateDeviceExtensionProperties(physical_dev, nullptr,
+ &count, nullptr);
+ if (result == VK_SUCCESS && count) {
+ driver_extensions_ = AllocateDriverExtensionArray(count);
+ result = (driver_extensions_)
+ ? EnumerateDeviceExtensionProperties(
+ physical_dev, nullptr, &count, driver_extensions_)
+ : VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ if (result != VK_SUCCESS)
+ return result;
+
+ driver_extension_count_ = count;
+
+ for (uint32_t i = 0; i < extension_count; i++) {
+ const char* name = extension_names[i];
+ if (!IsLayerExtension(name) && !IsDriverExtension(name)) {
+ ALOGE("Failed to enable missing device extension %s", name);
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ auto ext_bit = driver::GetProcHookExtension(name);
+ if (ext_bit != driver::ProcHook::EXTENSION_UNKNOWN)
+ enabled_extensions_.set(ext_bit);
+ }
+
+ return VK_SUCCESS;
+}
+
+VkExtensionProperties* LayerChain::AllocateDriverExtensionArray(
+ uint32_t count) const {
+ return reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
+ allocator_.pUserData, sizeof(VkExtensionProperties) * count,
+ alignof(VkExtensionProperties), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
+}
+
+bool LayerChain::IsLayerExtension(const char* name) const {
+ for (uint32_t i = 0; i < layer_count_; i++) {
+ const ActiveLayer& layer = layers_[i];
+ if (layer.ref.SupportsExtension(name))
+ return true;
+ }
+
+ return false;
+}
+
+bool LayerChain::IsDriverExtension(const char* name) const {
+ for (uint32_t i = 0; i < driver_extension_count_; i++) {
+ if (strcmp(driver_extensions_[i].extensionName, name) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+template <typename DataType>
+void LayerChain::StealLayers(DataType& data) {
+ data.layers = layers_;
+ data.layer_count = layer_count_;
+
+ layers_ = nullptr;
+ layer_count_ = 0;
+}
+
+void LayerChain::DestroyLayers(ActiveLayer* layers,
+ uint32_t count,
+ const VkAllocationCallbacks& allocator) {
+ for (uint32_t i = 0; i < count; i++)
+ layers[i].ref.~LayerRef();
+
+ allocator.pfnFree(allocator.pUserData, layers);
+}
+
+VkResult LayerChain::SetInstanceLoaderData(VkInstance instance, void* object) {
+ driver::InstanceDispatchable dispatchable =
+ reinterpret_cast<driver::InstanceDispatchable>(object);
+
+ return (driver::SetDataInternal(dispatchable, &driver::GetData(instance)))
+ ? VK_SUCCESS
+ : VK_ERROR_INITIALIZATION_FAILED;
+}
+
+VkResult LayerChain::SetDeviceLoaderData(VkDevice device, void* object) {
+ driver::DeviceDispatchable dispatchable =
+ reinterpret_cast<driver::DeviceDispatchable>(object);
+
+ return (driver::SetDataInternal(dispatchable, &driver::GetData(device)))
+ ? VK_SUCCESS
+ : VK_ERROR_INITIALIZATION_FAILED;
+}
+
+VkBool32 LayerChain::DebugReportCallback(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT obj_type,
+ uint64_t obj,
+ size_t location,
+ int32_t msg_code,
+ const char* layer_prefix,
+ const char* msg,
+ void* user_data) {
+ int prio;
+
+ if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
+ prio = ANDROID_LOG_ERROR;
+ else if (flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT |
+ VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT))
+ prio = ANDROID_LOG_WARN;
+ else if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)
+ prio = ANDROID_LOG_INFO;
+ else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT)
+ prio = ANDROID_LOG_DEBUG;
+ else
+ prio = ANDROID_LOG_UNKNOWN;
+
+ LOG_PRI(prio, LOG_TAG, "[%s] Code %d : %s", layer_prefix, msg_code, msg);
+
+ (void)obj_type;
+ (void)obj;
+ (void)location;
+ (void)user_data;
+
+ return false;
+}
+
+VkResult LayerChain::CreateInstance(const VkInstanceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkInstance* instance_out) {
+ LayerChain chain(true,
+ (allocator) ? *allocator : driver::GetDefaultAllocator());
+
+ VkResult result = chain.ActivateLayers(create_info->ppEnabledLayerNames,
+ create_info->enabledLayerCount,
+ create_info->ppEnabledExtensionNames,
+ create_info->enabledExtensionCount);
+ if (result != VK_SUCCESS)
+ return result;
+
+ // use a local create info when the chain is not empty
+ VkInstanceCreateInfo local_create_info;
+ if (!chain.Empty()) {
+ local_create_info = *create_info;
+ chain.ModifyCreateInfo(local_create_info);
+ create_info = &local_create_info;
+ }
+
+ return chain.Create(create_info, allocator, instance_out);
+}
+
+VkResult LayerChain::CreateDevice(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkDevice* dev_out) {
+ LayerChain chain(false, (allocator)
+ ? *allocator
+ : driver::GetData(physical_dev).allocator);
+
+ VkResult result = chain.ActivateLayers(create_info->ppEnabledLayerNames,
+ create_info->enabledLayerCount,
+ create_info->ppEnabledExtensionNames,
+ create_info->enabledExtensionCount);
+ if (result != VK_SUCCESS)
+ return result;
+
+ // use a local create info when the chain is not empty
+ VkDeviceCreateInfo local_create_info;
+ if (!chain.Empty()) {
+ local_create_info = *create_info;
+ chain.ModifyCreateInfo(local_create_info);
+ create_info = &local_create_info;
+ }
+
+ return chain.Create(physical_dev, create_info, allocator, dev_out);
+}
+
+void LayerChain::DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* allocator) {
+ InstanceData& data = GetData(instance);
+
+ if (data.debug_callback != VK_NULL_HANDLE)
+ data.destroy_debug_callback(instance, data.debug_callback, allocator);
+
+ ActiveLayer* layers = reinterpret_cast<ActiveLayer*>(data.layers);
+ uint32_t layer_count = data.layer_count;
+
+ VkAllocationCallbacks local_allocator;
+ if (!allocator)
+ local_allocator = driver::GetData(instance).allocator;
+
+ // this also destroys InstanceData
+ data.dispatch.DestroyInstance(instance, allocator);
+
+ DestroyLayers(layers, layer_count,
+ (allocator) ? *allocator : local_allocator);
+}
+
+void LayerChain::DestroyDevice(VkDevice device,
+ const VkAllocationCallbacks* allocator) {
+ DeviceData& data = GetData(device);
+
+ ActiveLayer* layers = reinterpret_cast<ActiveLayer*>(data.layers);
+ uint32_t layer_count = data.layer_count;
+
+ VkAllocationCallbacks local_allocator;
+ if (!allocator)
+ local_allocator = driver::GetData(device).allocator;
+
+ // this also destroys DeviceData
+ data.dispatch.DestroyDevice(device, allocator);
+
+ DestroyLayers(layers, layer_count,
+ (allocator) ? *allocator : local_allocator);
+}
+
+// ----------------------------------------------------------------------------
+
+bool EnsureInitialized() {
+ static std::once_flag once_flag;
+ static bool initialized;
+
+ std::call_once(once_flag, []() {
+ if (driver::OpenHAL()) {
+ DiscoverLayers();
+ initialized = true;
+ }
+ });
+
+ return initialized;
+}
+
+} // anonymous namespace
+
+VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkInstance* pInstance) {
+ if (!EnsureInitialized())
+ return VK_ERROR_INITIALIZATION_FAILED;
+
+ return LayerChain::CreateInstance(pCreateInfo, pAllocator, pInstance);
+}
+
+void DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* pAllocator) {
+ if (instance != VK_NULL_HANDLE)
+ LayerChain::DestroyInstance(instance, pAllocator);
+}
+
+VkResult CreateDevice(VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDevice* pDevice) {
+ return LayerChain::CreateDevice(physicalDevice, pCreateInfo, pAllocator,
+ pDevice);
+}
+
+void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
+ if (device != VK_NULL_HANDLE)
+ LayerChain::DestroyDevice(device, pAllocator);
+}
+
+VkResult EnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
+ VkLayerProperties* pProperties) {
+ if (!EnsureInitialized())
+ return VK_ERROR_INITIALIZATION_FAILED;
+
+ uint32_t count =
+ EnumerateInstanceLayers(pProperties ? *pPropertyCount : 0, pProperties);
+
+ if (!pProperties || *pPropertyCount > count)
+ *pPropertyCount = count;
+
+ return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
+}
+
+VkResult EnumerateInstanceExtensionProperties(
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties) {
+ if (!EnsureInitialized())
+ return VK_ERROR_INITIALIZATION_FAILED;
+
+ if (pLayerName) {
+ const VkExtensionProperties* props;
+ uint32_t count;
+ GetInstanceLayerExtensions(pLayerName, &props, &count);
+
+ if (!pProperties || *pPropertyCount > count)
+ *pPropertyCount = count;
+ if (pProperties)
+ std::copy(props, props + *pPropertyCount, pProperties);
+
+ return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
+ }
+
+ // TODO how about extensions from implicitly enabled layers?
+ return vulkan::driver::EnumerateInstanceExtensionProperties(
+ nullptr, pPropertyCount, pProperties);
+}
+
+VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkLayerProperties* pProperties) {
+ (void)physicalDevice;
+
+ uint32_t count =
+ EnumerateDeviceLayers(pProperties ? *pPropertyCount : 0, pProperties);
+
+ if (!pProperties || *pPropertyCount > count)
+ *pPropertyCount = count;
+
+ return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
+}
+
+VkResult EnumerateDeviceExtensionProperties(
+ VkPhysicalDevice physicalDevice,
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties) {
+ if (pLayerName) {
+ const VkExtensionProperties* props;
+ uint32_t count;
+ GetDeviceLayerExtensions(pLayerName, &props, &count);
+
+ if (!pProperties || *pPropertyCount > count)
+ *pPropertyCount = count;
+ if (pProperties)
+ std::copy(props, props + *pPropertyCount, pProperties);
+
+ return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
+ }
+
+ // TODO how about extensions from implicitly enabled layers?
+ const InstanceData& data = GetData(physicalDevice);
+ return data.dispatch.EnumerateDeviceExtensionProperties(
+ physicalDevice, nullptr, pPropertyCount, pProperties);
+}
+
+} // namespace api
+} // namespace vulkan
diff --git a/vulkan/libvulkan/api.h b/vulkan/libvulkan/api.h
new file mode 100644
index 0000000..ded7d17
--- /dev/null
+++ b/vulkan/libvulkan/api.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LIBVULKAN_API_H
+#define LIBVULKAN_API_H 1
+
+#include <vulkan/vulkan.h>
+#include "api_gen.h"
+#include "driver.h"
+
+namespace vulkan {
+namespace api {
+
+// clang-format off
+VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
+VKAPI_ATTR void DestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
+VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult EnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties);
+VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties);
+VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+// clang-format on
+
+inline InstanceData& GetData(VkInstance instance) {
+ return driver::GetData(instance).opaque_api_data;
+}
+
+inline InstanceData& GetData(VkPhysicalDevice physical_dev) {
+ return driver::GetData(physical_dev).opaque_api_data;
+}
+
+inline DeviceData& GetData(VkDevice dev) {
+ return driver::GetData(dev).opaque_api_data;
+}
+
+inline DeviceData& GetData(VkQueue queue) {
+ return driver::GetData(queue).opaque_api_data;
+}
+
+inline DeviceData& GetData(VkCommandBuffer cmd) {
+ return driver::GetData(cmd).opaque_api_data;
+}
+
+} // namespace api
+} // namespace vulkan
+
+#endif // LIBVULKAN_API_H
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
new file mode 100644
index 0000000..fe4136f
--- /dev/null
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -0,0 +1,1243 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+#include <string.h>
+#include <algorithm>
+#include <log/log.h>
+
+#include "api.h"
+
+namespace vulkan {
+namespace api {
+
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
+
+#define INIT_PROC(obj, proc) \
+ do { \
+ data.dispatch.proc = \
+ reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \
+ if (UNLIKELY(!data.dispatch.proc)) { \
+ ALOGE("missing " #obj " proc: vk" #proc); \
+ success = false; \
+ } \
+ } while (0)
+
+// Exported extension functions may be invoked even when their extensions
+// are disabled. Dispatch to stubs when that happens.
+#define INIT_PROC_EXT(ext, obj, proc) \
+ do { \
+ if (extensions[driver::ProcHook::ext]) \
+ INIT_PROC(obj, proc); \
+ else \
+ data.dispatch.proc = disabled##proc; \
+ } while (0)
+
+namespace {
+
+// clang-format off
+
+VKAPI_ATTR void disabledDestroySurfaceKHR(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks*) {
+ ALOGE("VK_KHR_surface not enabled. vkDestroySurfaceKHR not executed.");
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32*) {
+ ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceSupportKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR*) {
+ ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceCapabilitiesKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkSurfaceFormatKHR*) {
+ ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceFormatsKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkPresentModeKHR*) {
+ ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfacePresentModesKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledCreateSwapchainKHR(VkDevice, const VkSwapchainCreateInfoKHR*, const VkAllocationCallbacks*, VkSwapchainKHR*) {
+ ALOGE("VK_KHR_swapchain not enabled. vkCreateSwapchainKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR void disabledDestroySwapchainKHR(VkDevice, VkSwapchainKHR, const VkAllocationCallbacks*) {
+ ALOGE("VK_KHR_swapchain not enabled. vkDestroySwapchainKHR not executed.");
+}
+
+VKAPI_ATTR VkResult disabledGetSwapchainImagesKHR(VkDevice, VkSwapchainKHR, uint32_t*, VkImage*) {
+ ALOGE("VK_KHR_swapchain not enabled. vkGetSwapchainImagesKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledAcquireNextImageKHR(VkDevice, VkSwapchainKHR, uint64_t, VkSemaphore, VkFence, uint32_t*) {
+ ALOGE("VK_KHR_swapchain not enabled. vkAcquireNextImageKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledQueuePresentKHR(VkQueue, const VkPresentInfoKHR*) {
+ ALOGE("VK_KHR_swapchain not enabled. vkQueuePresentKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledCreateAndroidSurfaceKHR(VkInstance, const VkAndroidSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*) {
+ ALOGE("VK_KHR_android_surface not enabled. vkCreateAndroidSurfaceKHR not executed.");
+ return VK_SUCCESS;
+}
+
+// clang-format on
+
+} // anonymous
+
+bool InitDispatchTable(
+ VkInstance instance,
+ PFN_vkGetInstanceProcAddr get_proc,
+ const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
+ auto& data = GetData(instance);
+ bool success = true;
+
+ // clang-format off
+ INIT_PROC(instance, DestroyInstance);
+ INIT_PROC(instance, EnumeratePhysicalDevices);
+ INIT_PROC(instance, GetInstanceProcAddr);
+ INIT_PROC(instance, GetPhysicalDeviceProperties);
+ INIT_PROC(instance, GetPhysicalDeviceQueueFamilyProperties);
+ INIT_PROC(instance, GetPhysicalDeviceMemoryProperties);
+ INIT_PROC(instance, GetPhysicalDeviceFeatures);
+ INIT_PROC(instance, GetPhysicalDeviceFormatProperties);
+ INIT_PROC(instance, GetPhysicalDeviceImageFormatProperties);
+ INIT_PROC(instance, CreateDevice);
+ INIT_PROC(instance, EnumerateDeviceLayerProperties);
+ INIT_PROC(instance, EnumerateDeviceExtensionProperties);
+ INIT_PROC(instance, GetPhysicalDeviceSparseImageFormatProperties);
+ INIT_PROC_EXT(KHR_surface, instance, DestroySurfaceKHR);
+ INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfaceSupportKHR);
+ INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
+ INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfaceFormatsKHR);
+ INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfacePresentModesKHR);
+ INIT_PROC_EXT(KHR_android_surface, instance, CreateAndroidSurfaceKHR);
+ // clang-format on
+
+ return success;
+}
+
+bool InitDispatchTable(
+ VkDevice dev,
+ PFN_vkGetDeviceProcAddr get_proc,
+ const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
+ auto& data = GetData(dev);
+ bool success = true;
+
+ // clang-format off
+ INIT_PROC(dev, GetDeviceProcAddr);
+ INIT_PROC(dev, DestroyDevice);
+ INIT_PROC(dev, GetDeviceQueue);
+ INIT_PROC(dev, QueueSubmit);
+ INIT_PROC(dev, QueueWaitIdle);
+ INIT_PROC(dev, DeviceWaitIdle);
+ INIT_PROC(dev, AllocateMemory);
+ INIT_PROC(dev, FreeMemory);
+ INIT_PROC(dev, MapMemory);
+ INIT_PROC(dev, UnmapMemory);
+ INIT_PROC(dev, FlushMappedMemoryRanges);
+ INIT_PROC(dev, InvalidateMappedMemoryRanges);
+ INIT_PROC(dev, GetDeviceMemoryCommitment);
+ INIT_PROC(dev, GetBufferMemoryRequirements);
+ INIT_PROC(dev, BindBufferMemory);
+ INIT_PROC(dev, GetImageMemoryRequirements);
+ INIT_PROC(dev, BindImageMemory);
+ INIT_PROC(dev, GetImageSparseMemoryRequirements);
+ INIT_PROC(dev, QueueBindSparse);
+ INIT_PROC(dev, CreateFence);
+ INIT_PROC(dev, DestroyFence);
+ INIT_PROC(dev, ResetFences);
+ INIT_PROC(dev, GetFenceStatus);
+ INIT_PROC(dev, WaitForFences);
+ INIT_PROC(dev, CreateSemaphore);
+ INIT_PROC(dev, DestroySemaphore);
+ INIT_PROC(dev, CreateEvent);
+ INIT_PROC(dev, DestroyEvent);
+ INIT_PROC(dev, GetEventStatus);
+ INIT_PROC(dev, SetEvent);
+ INIT_PROC(dev, ResetEvent);
+ INIT_PROC(dev, CreateQueryPool);
+ INIT_PROC(dev, DestroyQueryPool);
+ INIT_PROC(dev, GetQueryPoolResults);
+ INIT_PROC(dev, CreateBuffer);
+ INIT_PROC(dev, DestroyBuffer);
+ INIT_PROC(dev, CreateBufferView);
+ INIT_PROC(dev, DestroyBufferView);
+ INIT_PROC(dev, CreateImage);
+ INIT_PROC(dev, DestroyImage);
+ INIT_PROC(dev, GetImageSubresourceLayout);
+ INIT_PROC(dev, CreateImageView);
+ INIT_PROC(dev, DestroyImageView);
+ INIT_PROC(dev, CreateShaderModule);
+ INIT_PROC(dev, DestroyShaderModule);
+ INIT_PROC(dev, CreatePipelineCache);
+ INIT_PROC(dev, DestroyPipelineCache);
+ INIT_PROC(dev, GetPipelineCacheData);
+ INIT_PROC(dev, MergePipelineCaches);
+ INIT_PROC(dev, CreateGraphicsPipelines);
+ INIT_PROC(dev, CreateComputePipelines);
+ INIT_PROC(dev, DestroyPipeline);
+ INIT_PROC(dev, CreatePipelineLayout);
+ INIT_PROC(dev, DestroyPipelineLayout);
+ INIT_PROC(dev, CreateSampler);
+ INIT_PROC(dev, DestroySampler);
+ INIT_PROC(dev, CreateDescriptorSetLayout);
+ INIT_PROC(dev, DestroyDescriptorSetLayout);
+ INIT_PROC(dev, CreateDescriptorPool);
+ INIT_PROC(dev, DestroyDescriptorPool);
+ INIT_PROC(dev, ResetDescriptorPool);
+ INIT_PROC(dev, AllocateDescriptorSets);
+ INIT_PROC(dev, FreeDescriptorSets);
+ INIT_PROC(dev, UpdateDescriptorSets);
+ INIT_PROC(dev, CreateFramebuffer);
+ INIT_PROC(dev, DestroyFramebuffer);
+ INIT_PROC(dev, CreateRenderPass);
+ INIT_PROC(dev, DestroyRenderPass);
+ INIT_PROC(dev, GetRenderAreaGranularity);
+ INIT_PROC(dev, CreateCommandPool);
+ INIT_PROC(dev, DestroyCommandPool);
+ INIT_PROC(dev, ResetCommandPool);
+ INIT_PROC(dev, AllocateCommandBuffers);
+ INIT_PROC(dev, FreeCommandBuffers);
+ INIT_PROC(dev, BeginCommandBuffer);
+ INIT_PROC(dev, EndCommandBuffer);
+ INIT_PROC(dev, ResetCommandBuffer);
+ INIT_PROC(dev, CmdBindPipeline);
+ INIT_PROC(dev, CmdSetViewport);
+ INIT_PROC(dev, CmdSetScissor);
+ INIT_PROC(dev, CmdSetLineWidth);
+ INIT_PROC(dev, CmdSetDepthBias);
+ INIT_PROC(dev, CmdSetBlendConstants);
+ INIT_PROC(dev, CmdSetDepthBounds);
+ INIT_PROC(dev, CmdSetStencilCompareMask);
+ INIT_PROC(dev, CmdSetStencilWriteMask);
+ INIT_PROC(dev, CmdSetStencilReference);
+ INIT_PROC(dev, CmdBindDescriptorSets);
+ INIT_PROC(dev, CmdBindIndexBuffer);
+ INIT_PROC(dev, CmdBindVertexBuffers);
+ INIT_PROC(dev, CmdDraw);
+ INIT_PROC(dev, CmdDrawIndexed);
+ INIT_PROC(dev, CmdDrawIndirect);
+ INIT_PROC(dev, CmdDrawIndexedIndirect);
+ INIT_PROC(dev, CmdDispatch);
+ INIT_PROC(dev, CmdDispatchIndirect);
+ INIT_PROC(dev, CmdCopyBuffer);
+ INIT_PROC(dev, CmdCopyImage);
+ INIT_PROC(dev, CmdBlitImage);
+ INIT_PROC(dev, CmdCopyBufferToImage);
+ INIT_PROC(dev, CmdCopyImageToBuffer);
+ INIT_PROC(dev, CmdUpdateBuffer);
+ INIT_PROC(dev, CmdFillBuffer);
+ INIT_PROC(dev, CmdClearColorImage);
+ INIT_PROC(dev, CmdClearDepthStencilImage);
+ INIT_PROC(dev, CmdClearAttachments);
+ INIT_PROC(dev, CmdResolveImage);
+ INIT_PROC(dev, CmdSetEvent);
+ INIT_PROC(dev, CmdResetEvent);
+ INIT_PROC(dev, CmdWaitEvents);
+ INIT_PROC(dev, CmdPipelineBarrier);
+ INIT_PROC(dev, CmdBeginQuery);
+ INIT_PROC(dev, CmdEndQuery);
+ INIT_PROC(dev, CmdResetQueryPool);
+ INIT_PROC(dev, CmdWriteTimestamp);
+ INIT_PROC(dev, CmdCopyQueryPoolResults);
+ INIT_PROC(dev, CmdPushConstants);
+ INIT_PROC(dev, CmdBeginRenderPass);
+ INIT_PROC(dev, CmdNextSubpass);
+ INIT_PROC(dev, CmdEndRenderPass);
+ INIT_PROC(dev, CmdExecuteCommands);
+ INIT_PROC_EXT(KHR_swapchain, dev, CreateSwapchainKHR);
+ INIT_PROC_EXT(KHR_swapchain, dev, DestroySwapchainKHR);
+ INIT_PROC_EXT(KHR_swapchain, dev, GetSwapchainImagesKHR);
+ INIT_PROC_EXT(KHR_swapchain, dev, AcquireNextImageKHR);
+ INIT_PROC_EXT(KHR_swapchain, dev, QueuePresentKHR);
+ // clang-format on
+
+ return success;
+}
+
+} // namespace api
+} // namespace vulkan
+
+// clang-format off
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
+ // call into api.cpp
+ return vulkan::api::CreateInstance(pCreateInfo, pAllocator, pInstance);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator) {
+ // call into api.cpp
+ vulkan::api::DestroyInstance(instance, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) {
+ return vulkan::api::GetData(instance).dispatch.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR PFN_vkVoidFunction vkGetDeviceProcAddr(VkDevice device, const char* pName) {
+ if (device == VK_NULL_HANDLE) {
+ ALOGE("vkGetDeviceProcAddr called with invalid device");
+ return nullptr;
+ }
+
+ static const char* const known_non_device_names[] = {
+ "vkCreateAndroidSurfaceKHR",
+ "vkCreateDebugReportCallbackEXT",
+ "vkCreateDevice",
+ "vkCreateInstance",
+ "vkDebugReportMessageEXT",
+ "vkDestroyDebugReportCallbackEXT",
+ "vkDestroyInstance",
+ "vkDestroySurfaceKHR",
+ "vkEnumerateDeviceExtensionProperties",
+ "vkEnumerateDeviceLayerProperties",
+ "vkEnumerateInstanceExtensionProperties",
+ "vkEnumerateInstanceLayerProperties",
+ "vkEnumeratePhysicalDevices",
+ "vkGetInstanceProcAddr",
+ "vkGetPhysicalDeviceFeatures",
+ "vkGetPhysicalDeviceFormatProperties",
+ "vkGetPhysicalDeviceImageFormatProperties",
+ "vkGetPhysicalDeviceMemoryProperties",
+ "vkGetPhysicalDeviceProperties",
+ "vkGetPhysicalDeviceQueueFamilyProperties",
+ "vkGetPhysicalDeviceSparseImageFormatProperties",
+ "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
+ "vkGetPhysicalDeviceSurfaceFormatsKHR",
+ "vkGetPhysicalDeviceSurfacePresentModesKHR",
+ "vkGetPhysicalDeviceSurfaceSupportKHR",
+ };
+ // clang-format on
+ constexpr size_t count =
+ sizeof(known_non_device_names) / sizeof(known_non_device_names[0]);
+ if (!pName ||
+ std::binary_search(
+ known_non_device_names, known_non_device_names + count, pName,
+ [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
+ ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)");
+ return nullptr;
+ }
+ // clang-format off
+
+ if (strcmp(pName, "vkGetDeviceProcAddr") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceProcAddr);
+ if (strcmp(pName, "vkDestroyDevice") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::DestroyDevice);
+
+ return vulkan::api::GetData(device).dispatch.GetDeviceProcAddr(device, pName);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
+ // global functions
+ if (!instance) {
+ if (strcmp(pName, "vkCreateInstance") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::CreateInstance);
+ if (strcmp(pName, "vkEnumerateInstanceLayerProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::EnumerateInstanceLayerProperties);
+ if (strcmp(pName, "vkEnumerateInstanceExtensionProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::EnumerateInstanceExtensionProperties);
+
+ ALOGE("vkGetInstanceProcAddr called with %s without instance", pName);
+ return nullptr;
+ }
+
+ static const struct Hook {
+ const char* name;
+ PFN_vkVoidFunction proc;
+ } hooks[] = {
+ { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR) },
+ { "vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(vkAllocateCommandBuffers) },
+ { "vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkAllocateDescriptorSets) },
+ { "vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(vkAllocateMemory) },
+ { "vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkBeginCommandBuffer) },
+ { "vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(vkBindBufferMemory) },
+ { "vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(vkBindImageMemory) },
+ { "vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBeginQuery) },
+ { "vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBeginRenderPass) },
+ { "vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindDescriptorSets) },
+ { "vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindIndexBuffer) },
+ { "vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindPipeline) },
+ { "vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindVertexBuffers) },
+ { "vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBlitImage) },
+ { "vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearAttachments) },
+ { "vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearColorImage) },
+ { "vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearDepthStencilImage) },
+ { "vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyBuffer) },
+ { "vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyBufferToImage) },
+ { "vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyImage) },
+ { "vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyImageToBuffer) },
+ { "vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyQueryPoolResults) },
+ { "vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDispatch) },
+ { "vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDispatchIndirect) },
+ { "vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDraw) },
+ { "vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndexed) },
+ { "vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndexedIndirect) },
+ { "vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndirect) },
+ { "vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(vkCmdEndQuery) },
+ { "vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdEndRenderPass) },
+ { "vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(vkCmdExecuteCommands) },
+ { "vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdFillBuffer) },
+ { "vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdNextSubpass) },
+ { "vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(vkCmdPipelineBarrier) },
+ { "vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(vkCmdPushConstants) },
+ { "vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResetEvent) },
+ { "vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResetQueryPool) },
+ { "vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResolveImage) },
+ { "vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetBlendConstants) },
+ { "vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetDepthBias) },
+ { "vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetDepthBounds) },
+ { "vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetEvent) },
+ { "vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetLineWidth) },
+ { "vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetScissor) },
+ { "vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetStencilCompareMask) },
+ { "vkCmdSetStencilReference", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetStencilReference) },
+ { "vkCmdSetStencilWriteMask", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetStencilWriteMask) },
+ { "vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetViewport) },
+ { "vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdUpdateBuffer) },
+ { "vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(vkCmdWaitEvents) },
+ { "vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(vkCmdWriteTimestamp) },
+ { "vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCreateBuffer) },
+ { "vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(vkCreateBufferView) },
+ { "vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateCommandPool) },
+ { "vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(vkCreateComputePipelines) },
+ { "vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDescriptorPool) },
+ { "vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDescriptorSetLayout) },
+ { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::CreateDevice) },
+ { "vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCreateEvent) },
+ { "vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(vkCreateFence) },
+ { "vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCreateFramebuffer) },
+ { "vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(vkCreateGraphicsPipelines) },
+ { "vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(vkCreateImage) },
+ { "vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(vkCreateImageView) },
+ { "vkCreateInstance", nullptr },
+ { "vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(vkCreatePipelineCache) },
+ { "vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(vkCreatePipelineLayout) },
+ { "vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateQueryPool) },
+ { "vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCreateRenderPass) },
+ { "vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(vkCreateSampler) },
+ { "vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(vkCreateSemaphore) },
+ { "vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(vkCreateShaderModule) },
+ { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR) },
+ { "vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyBuffer) },
+ { "vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyBufferView) },
+ { "vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyCommandPool) },
+ { "vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDescriptorPool) },
+ { "vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDescriptorSetLayout) },
+ { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::DestroyDevice) },
+ { "vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyEvent) },
+ { "vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyFence) },
+ { "vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyFramebuffer) },
+ { "vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyImage) },
+ { "vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyImageView) },
+ { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::DestroyInstance) },
+ { "vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipeline) },
+ { "vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipelineCache) },
+ { "vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipelineLayout) },
+ { "vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyQueryPool) },
+ { "vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyRenderPass) },
+ { "vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySampler) },
+ { "vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySemaphore) },
+ { "vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyShaderModule) },
+ { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR) },
+ { "vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(vkDeviceWaitIdle) },
+ { "vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkEndCommandBuffer) },
+ { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::EnumerateDeviceExtensionProperties) },
+ { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::EnumerateDeviceLayerProperties) },
+ { "vkEnumerateInstanceExtensionProperties", nullptr },
+ { "vkEnumerateInstanceLayerProperties", nullptr },
+ { "vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(vkFlushMappedMemoryRanges) },
+ { "vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(vkFreeCommandBuffers) },
+ { "vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkFreeDescriptorSets) },
+ { "vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(vkFreeMemory) },
+ { "vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetBufferMemoryRequirements) },
+ { "vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceMemoryCommitment) },
+ { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceProcAddr) },
+ { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceQueue) },
+ { "vkGetEventStatus", reinterpret_cast<PFN_vkVoidFunction>(vkGetEventStatus) },
+ { "vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(vkGetFenceStatus) },
+ { "vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageMemoryRequirements) },
+ { "vkGetImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageSparseMemoryRequirements) },
+ { "vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageSubresourceLayout) },
+ { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr) },
+ { "vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(vkGetPipelineCacheData) },
+ { "vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(vkGetQueryPoolResults) },
+ { "vkGetRenderAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(vkGetRenderAreaGranularity) },
+ { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR) },
+ { "vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(vkInvalidateMappedMemoryRanges) },
+ { "vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(vkMapMemory) },
+ { "vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(vkMergePipelineCaches) },
+ { "vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(vkQueueBindSparse) },
+ { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR) },
+ { "vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(vkQueueSubmit) },
+ { "vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(vkQueueWaitIdle) },
+ { "vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkResetCommandBuffer) },
+ { "vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkResetCommandPool) },
+ { "vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkResetDescriptorPool) },
+ { "vkResetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkResetEvent) },
+ { "vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(vkResetFences) },
+ { "vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkSetEvent) },
+ { "vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(vkUnmapMemory) },
+ { "vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkUpdateDescriptorSets) },
+ { "vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(vkWaitForFences) },
+ };
+ // clang-format on
+ constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
+ auto hook = std::lower_bound(
+ hooks, hooks + count, pName,
+ [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
+ if (hook < hooks + count && strcmp(hook->name, pName) == 0) {
+ if (!hook->proc)
+ ALOGE("vkGetInstanceProcAddr called with %s with instance", pName);
+ return hook->proc;
+ }
+ // clang-format off
+
+ return vulkan::api::GetData(instance).dispatch.GetInstanceProcAddr(instance, pName);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties) {
+ vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceProperties(physicalDevice, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties) {
+ vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
+ vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) {
+ vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) {
+ vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties) {
+ return vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) {
+ // call into api.cpp
+ return vulkan::api::CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
+ // call into api.cpp
+ vulkan::api::DestroyDevice(device, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
+ // call into api.cpp
+ return vulkan::api::EnumerateInstanceLayerProperties(pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) {
+ // call into api.cpp
+ return vulkan::api::EnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
+ // call into api.cpp
+ return vulkan::api::EnumerateDeviceLayerProperties(physicalDevice, pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) {
+ // call into api.cpp
+ return vulkan::api::EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue) {
+ vulkan::api::GetData(device).dispatch.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence) {
+ return vulkan::api::GetData(queue).dispatch.QueueSubmit(queue, submitCount, pSubmits, fence);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkQueueWaitIdle(VkQueue queue) {
+ return vulkan::api::GetData(queue).dispatch.QueueWaitIdle(queue);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkDeviceWaitIdle(VkDevice device) {
+ return vulkan::api::GetData(device).dispatch.DeviceWaitIdle(device);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) {
+ return vulkan::api::GetData(device).dispatch.AllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.FreeMemory(device, memory, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) {
+ return vulkan::api::GetData(device).dispatch.MapMemory(device, memory, offset, size, flags, ppData);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkUnmapMemory(VkDevice device, VkDeviceMemory memory) {
+ vulkan::api::GetData(device).dispatch.UnmapMemory(device, memory);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) {
+ return vulkan::api::GetData(device).dispatch.FlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) {
+ return vulkan::api::GetData(device).dispatch.InvalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes) {
+ vulkan::api::GetData(device).dispatch.GetDeviceMemoryCommitment(device, memory, pCommittedMemoryInBytes);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements) {
+ vulkan::api::GetData(device).dispatch.GetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) {
+ return vulkan::api::GetData(device).dispatch.BindBufferMemory(device, buffer, memory, memoryOffset);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements) {
+ vulkan::api::GetData(device).dispatch.GetImageMemoryRequirements(device, image, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) {
+ return vulkan::api::GetData(device).dispatch.BindImageMemory(device, image, memory, memoryOffset);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements) {
+ vulkan::api::GetData(device).dispatch.GetImageSparseMemoryRequirements(device, image, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties) {
+ vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence) {
+ return vulkan::api::GetData(queue).dispatch.QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateFence(VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence) {
+ return vulkan::api::GetData(device).dispatch.CreateFence(device, pCreateInfo, pAllocator, pFence);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyFence(device, fence, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences) {
+ return vulkan::api::GetData(device).dispatch.ResetFences(device, fenceCount, pFences);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetFenceStatus(VkDevice device, VkFence fence) {
+ return vulkan::api::GetData(device).dispatch.GetFenceStatus(device, fence);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout) {
+ return vulkan::api::GetData(device).dispatch.WaitForFences(device, fenceCount, pFences, waitAll, timeout);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore) {
+ return vulkan::api::GetData(device).dispatch.CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroySemaphore(device, semaphore, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateEvent(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent) {
+ return vulkan::api::GetData(device).dispatch.CreateEvent(device, pCreateInfo, pAllocator, pEvent);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyEvent(device, event, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetEventStatus(VkDevice device, VkEvent event) {
+ return vulkan::api::GetData(device).dispatch.GetEventStatus(device, event);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkSetEvent(VkDevice device, VkEvent event) {
+ return vulkan::api::GetData(device).dispatch.SetEvent(device, event);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkResetEvent(VkDevice device, VkEvent event) {
+ return vulkan::api::GetData(device).dispatch.ResetEvent(device, event);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool) {
+ return vulkan::api::GetData(device).dispatch.CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyQueryPool(device, queryPool, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags) {
+ return vulkan::api::GetData(device).dispatch.GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer) {
+ return vulkan::api::GetData(device).dispatch.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyBuffer(device, buffer, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateBufferView(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView) {
+ return vulkan::api::GetData(device).dispatch.CreateBufferView(device, pCreateInfo, pAllocator, pView);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyBufferView(device, bufferView, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage) {
+ return vulkan::api::GetData(device).dispatch.CreateImage(device, pCreateInfo, pAllocator, pImage);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyImage(device, image, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) {
+ vulkan::api::GetData(device).dispatch.GetImageSubresourceLayout(device, image, pSubresource, pLayout);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView) {
+ return vulkan::api::GetData(device).dispatch.CreateImageView(device, pCreateInfo, pAllocator, pView);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyImageView(device, imageView, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule) {
+ return vulkan::api::GetData(device).dispatch.CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyShaderModule(device, shaderModule, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache) {
+ return vulkan::api::GetData(device).dispatch.CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyPipelineCache(device, pipelineCache, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData) {
+ return vulkan::api::GetData(device).dispatch.GetPipelineCacheData(device, pipelineCache, pDataSize, pData);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkMergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches) {
+ return vulkan::api::GetData(device).dispatch.MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) {
+ return vulkan::api::GetData(device).dispatch.CreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) {
+ return vulkan::api::GetData(device).dispatch.CreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyPipeline(device, pipeline, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout) {
+ return vulkan::api::GetData(device).dispatch.CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyPipelineLayout(device, pipelineLayout, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateSampler(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler) {
+ return vulkan::api::GetData(device).dispatch.CreateSampler(device, pCreateInfo, pAllocator, pSampler);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroySampler(device, sampler, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout) {
+ return vulkan::api::GetData(device).dispatch.CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool) {
+ return vulkan::api::GetData(device).dispatch.CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyDescriptorPool(device, descriptorPool, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) {
+ return vulkan::api::GetData(device).dispatch.ResetDescriptorPool(device, descriptorPool, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets) {
+ return vulkan::api::GetData(device).dispatch.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets) {
+ return vulkan::api::GetData(device).dispatch.FreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies) {
+ vulkan::api::GetData(device).dispatch.UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer) {
+ return vulkan::api::GetData(device).dispatch.CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyFramebuffer(device, framebuffer, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass) {
+ return vulkan::api::GetData(device).dispatch.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyRenderPass(device, renderPass, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity) {
+ vulkan::api::GetData(device).dispatch.GetRenderAreaGranularity(device, renderPass, pGranularity);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool) {
+ return vulkan::api::GetData(device).dispatch.CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroyCommandPool(device, commandPool, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) {
+ return vulkan::api::GetData(device).dispatch.ResetCommandPool(device, commandPool, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers) {
+ return vulkan::api::GetData(device).dispatch.AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers) {
+ vulkan::api::GetData(device).dispatch.FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo) {
+ return vulkan::api::GetData(commandBuffer).dispatch.BeginCommandBuffer(commandBuffer, pBeginInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEndCommandBuffer(VkCommandBuffer commandBuffer) {
+ return vulkan::api::GetData(commandBuffer).dispatch.EndCommandBuffer(commandBuffer);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
+ return vulkan::api::GetData(commandBuffer).dispatch.ResetCommandBuffer(commandBuffer, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdSetLineWidth(commandBuffer, lineWidth);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdSetBlendConstants(commandBuffer, blendConstants);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdSetStencilReference(commandBuffer, faceMask, reference);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdDrawIndirect(commandBuffer, buffer, offset, drawCount, stride);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdDispatch(commandBuffer, x, y, z);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdDispatchIndirect(commandBuffer, buffer, offset);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t* pData) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdSetEvent(commandBuffer, event, stageMask);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdResetEvent(commandBuffer, event, stageMask);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdWaitEvents(commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdBeginQuery(commandBuffer, queryPool, query, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdEndQuery(commandBuffer, queryPool, query);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, query);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdNextSubpass(commandBuffer, contents);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdEndRenderPass(VkCommandBuffer commandBuffer) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdEndRenderPass(commandBuffer);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers) {
+ vulkan::api::GetData(commandBuffer).dispatch.CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(instance).dispatch.DestroySurfaceKHR(instance, surface, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported) {
+ return vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities) {
+ return vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats) {
+ return vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes) {
+ return vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, pPresentModes);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) {
+ return vulkan::api::GetData(device).dispatch.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::GetData(device).dispatch.DestroySwapchainKHR(device, swapchain, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) {
+ return vulkan::api::GetData(device).dispatch.GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex) {
+ return vulkan::api::GetData(device).dispatch.AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) {
+ return vulkan::api::GetData(queue).dispatch.QueuePresentKHR(queue, pPresentInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
+ return vulkan::api::GetData(instance).dispatch.CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
+}
+
+// clang-format on
diff --git a/vulkan/libvulkan/dispatch_gen.h b/vulkan/libvulkan/api_gen.h
similarity index 82%
rename from vulkan/libvulkan/dispatch_gen.h
rename to vulkan/libvulkan/api_gen.h
index cef4ccf..779b654 100644
--- a/vulkan/libvulkan/dispatch_gen.h
+++ b/vulkan/libvulkan/api_gen.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 The Android Open Source Project
+ * Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,16 +16,21 @@
// WARNING: This file is generated. See ../README.md for instructions.
-#define VK_USE_PLATFORM_ANDROID_KHR
-#include <vulkan/vk_android_native_buffer.h>
+#ifndef LIBVULKAN_API_GEN_H
+#define LIBVULKAN_API_GEN_H
+
+#include <bitset>
#include <vulkan/vulkan.h>
+#include "driver_gen.h"
namespace vulkan {
+namespace api {
struct InstanceDispatchTable {
// clang-format off
PFN_vkDestroyInstance DestroyInstance;
PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
+ PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
PFN_vkGetPhysicalDeviceQueueFamilyProperties GetPhysicalDeviceQueueFamilyProperties;
PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties;
@@ -33,6 +38,7 @@
PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
PFN_vkCreateDevice CreateDevice;
+ PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
@@ -41,14 +47,12 @@
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
- PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
- PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
- PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
// clang-format on
};
struct DeviceDispatchTable {
// clang-format off
+ PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
PFN_vkDestroyDevice DestroyDevice;
PFN_vkGetDeviceQueue GetDeviceQueue;
PFN_vkQueueSubmit QueueSubmit;
@@ -177,29 +181,16 @@
// clang-format on
};
-struct DriverDispatchTable {
- // clang-format off
- PFN_vkDestroyInstance DestroyInstance;
- PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
- PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
- PFN_vkGetPhysicalDeviceQueueFamilyProperties GetPhysicalDeviceQueueFamilyProperties;
- PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties;
- PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
- PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
- PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
- PFN_vkCreateDevice CreateDevice;
- PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
- PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
- PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
- PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
- PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
- PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
- PFN_vkCreateImage CreateImage;
- PFN_vkDestroyImage DestroyImage;
- PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
- PFN_vkAcquireImageANDROID AcquireImageANDROID;
- PFN_vkQueueSignalReleaseImageANDROID QueueSignalReleaseImageANDROID;
- // clang-format on
-};
+bool InitDispatchTable(
+ VkInstance instance,
+ PFN_vkGetInstanceProcAddr get_proc,
+ const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions);
+bool InitDispatchTable(
+ VkDevice dev,
+ PFN_vkGetDeviceProcAddr get_proc,
+ const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions);
+} // namespace api
} // namespace vulkan
+
+#endif // LIBVULKAN_API_GEN_H
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
new file mode 100644
index 0000000..3968371
--- /dev/null
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -0,0 +1,1108 @@
+{{define "Copyright"}}
+/*
+•* Copyright 2016 The Android Open Source Project
+•*
+•* Licensed under the Apache License, Version 2.0 (the "License");
+•* you may not use this file except in compliance with the License.
+•* You may obtain a copy of the License at
+•*
+•* http://www.apache.org/licenses/LICENSE-2.0
+•*
+•* Unless required by applicable law or agreed to in writing, software
+•* distributed under the License is distributed on an "AS IS" BASIS,
+•* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+•* See the License for the specific language governing permissions and
+•* limitations under the License.
+•*/
+¶{{end}}
+
+{{Include "../api/templates/vulkan_common.tmpl"}}
+{{Global "clang-format" (Strings "clang-format" "-style=file")}}
+{{Macro "DefineGlobals" $}}
+{{$ | Macro "api_gen.h" | Format (Global "clang-format") | Write "api_gen.h" }}
+{{$ | Macro "api_gen.cpp" | Format (Global "clang-format") | Write "api_gen.cpp"}}
+{{$ | Macro "driver_gen.h" | Format (Global "clang-format") | Write "driver_gen.h"}}
+{{$ | Macro "driver_gen.cpp" | Format (Global "clang-format") | Write "driver_gen.cpp"}}
+
+{{/*
+-------------------------------------------------------------------------------
+ api_gen.h
+-------------------------------------------------------------------------------
+*/}}
+{{define "api_gen.h"}}
+{{Macro "Copyright"}}
+¶
+// WARNING: This file is generated. See ../README.md for instructions.
+¶
+#ifndef LIBVULKAN_API_GEN_H
+#define LIBVULKAN_API_GEN_H
+¶
+#include <bitset>
+#include <vulkan/vulkan.h>
+#include "driver_gen.h"
+¶
+namespace vulkan {«
+namespace api {«
+¶
+struct InstanceDispatchTable {
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
+ {{Macro "C++.DeclareTableEntry" $f}};
+ {{end}}
+ {{end}}
+ // clang-format on
+};
+¶
+struct DeviceDispatchTable {
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
+ {{Macro "C++.DeclareTableEntry" $f}};
+ {{end}}
+ {{end}}
+ // clang-format on
+};
+¶
+bool InitDispatchTable(
+ VkInstance instance,
+ PFN_vkGetInstanceProcAddr get_proc,
+ const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);
+bool InitDispatchTable(
+ VkDevice dev,
+ PFN_vkGetDeviceProcAddr get_proc,
+ const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);
+¶
+»} // namespace api
+»} // namespace vulkan
+¶
+#endif // LIBVULKAN_API_GEN_H
+¶{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ api_gen.cpp
+-------------------------------------------------------------------------------
+*/}}
+{{define "api_gen.cpp"}}
+{{Macro "Copyright"}}
+¶
+// WARNING: This file is generated. See ../README.md for instructions.
+¶
+#include <string.h>
+#include <algorithm>
+#include <log/log.h>
+¶
+#include "api.h"
+¶
+namespace vulkan {«
+namespace api {«
+¶
+{{Macro "C++.DefineInitProcMacro" "dispatch"}}
+¶
+{{Macro "api.C++.DefineInitProcExtMacro"}}
+¶
+namespace {«
+¶
+// clang-format off
+¶
+{{range $f := AllCommands $}}
+ {{Macro "api.C++.DefineExtensionStub" $f}}
+{{end}}
+// clang-format on
+¶
+»} // anonymous
+¶
+bool InitDispatchTable(
+ VkInstance instance,
+ PFN_vkGetInstanceProcAddr get_proc,
+ const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
+ auto& data = GetData(instance);
+ bool success = true;
+ ¶
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
+ {{Macro "C++.InitProc" $f}}
+ {{end}}
+ {{end}}
+ // clang-format on
+ ¶
+ return success;
+}
+¶
+bool InitDispatchTable(
+ VkDevice dev,
+ PFN_vkGetDeviceProcAddr get_proc,
+ const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
+ auto& data = GetData(dev);
+ bool success = true;
+ ¶
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
+ {{Macro "C++.InitProc" $f}}
+ {{end}}
+ {{end}}
+ // clang-format on
+ ¶
+ return success;
+}
+¶
+»} // namespace api
+»} // namespace vulkan
+¶
+// clang-format off
+¶
+{{range $f := AllCommands $}}
+ {{if (Macro "IsFunctionExported" $f)}}
+ __attribute__((visibility("default")))
+ VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
+ {{ if eq $f.Name "vkGetInstanceProcAddr"}}
+ {{Macro "api.C++.InterceptInstanceProcAddr" $}}
+ {{else if eq $f.Name "vkGetDeviceProcAddr"}}
+ {{Macro "api.C++.InterceptDeviceProcAddr" $}}
+ {{end}}
+
+ {{Macro "api.C++.Dispatch" $f}}
+ }
+ ¶
+ {{end}}
+{{end}}
+¶
+// clang-format on
+¶{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ driver_gen.h
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver_gen.h"}}
+{{Macro "Copyright"}}
+¶
+// WARNING: This file is generated. See ../README.md for instructions.
+¶
+#ifndef LIBVULKAN_DRIVER_GEN_H
+#define LIBVULKAN_DRIVER_GEN_H
+¶
+#include <bitset>
+#include <vulkan/vulkan.h>
+#include <vulkan/vk_android_native_buffer.h>
+¶
+namespace vulkan {«
+namespace driver {«
+¶
+{{Macro "driver.C++.DefineProcHookType"}}
+¶
+struct InstanceDriverTable {
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
+ {{Macro "C++.DeclareTableEntry" $f}};
+ {{end}}
+ {{end}}
+ // clang-format on
+};
+¶
+struct DeviceDriverTable {
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
+ {{Macro "C++.DeclareTableEntry" $f}};
+ {{end}}
+ {{end}}
+ // clang-format on
+};
+¶
+const ProcHook* GetProcHook(const char* name);
+ProcHook::Extension GetProcHookExtension(const char* name);
+¶
+bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
+ const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
+bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
+ const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
+¶
+»} // namespace driver
+»} // namespace vulkan
+¶
+#endif // LIBVULKAN_DRIVER_TABLE_H
+¶{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ driver_gen.cpp
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver_gen.cpp"}}
+{{Macro "Copyright"}}
+¶
+// WARNING: This file is generated. See ../README.md for instructions.
+¶
+#include <string.h>
+#include <algorithm>
+#include <log/log.h>
+¶
+#include "driver.h"
+¶
+namespace vulkan {«
+namespace driver {«
+¶
+namespace {«
+¶
+// clang-format off
+¶
+{{range $f := AllCommands $}}
+ {{Macro "driver.C++.DefineProcHookStub" $f}}
+{{end}}
+// clang-format on
+¶
+const ProcHook g_proc_hooks[] = {
+ // clang-format off
+ {{range $f := SortBy (AllCommands $) "FunctionName"}}
+ {{if (Macro "driver.IsIntercepted" $f)}}
+ {{ if (Macro "IsGloballyDispatched" $f)}}
+ {{Macro "driver.C++.DefineGlobalProcHook" $f}}
+ {{else if (Macro "IsInstanceDispatched" $f)}}
+ {{Macro "driver.C++.DefineInstanceProcHook" $f}}
+ {{else if (Macro "IsDeviceDispatched" $f)}}
+ {{Macro "driver.C++.DefineDeviceProcHook" $f}}
+ {{end}}
+ {{end}}
+ {{end}}
+ // clang-format on
+};
+¶
+»} // anonymous
+¶
+const ProcHook* GetProcHook(const char* name) {
+ const auto& begin = g_proc_hooks;
+ const auto& end = g_proc_hooks +
+ sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
+ const auto hook = std::lower_bound(begin, end, name,
+ [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
+ return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
+}
+¶
+ProcHook::Extension GetProcHookExtension(const char* name) {
+ {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
+ // clang-format off
+ {{range $e := $exts}}
+ if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
+ {{end}}
+ // clang-format on
+ return ProcHook::EXTENSION_UNKNOWN;
+}
+¶
+{{Macro "C++.DefineInitProcMacro" "driver"}}
+¶
+{{Macro "driver.C++.DefineInitProcExtMacro"}}
+¶
+bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
+ const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
+{
+ auto& data = GetData(instance);
+ bool success = true;
+ ¶
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
+ {{Macro "C++.InitProc" $f}}
+ {{end}}
+ {{end}}
+ // clang-format on
+ ¶
+ return success;
+}
+¶
+bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
+ const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
+{
+ auto& data = GetData(dev);
+ bool success = true;
+ ¶
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
+ {{Macro "C++.InitProc" $f}}
+ {{end}}
+ {{end}}
+ // clang-format on
+ ¶
+ return success;
+}
+¶
+»} // namespace driver
+»} // namespace vulkan
+¶
+// clang-format on
+¶{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits a declaration of a dispatch/driver table entry.
+------------------------------------------------------------------------------
+*/}}
+{{define "C++.DeclareTableEntry"}}
+ {{AssertType $ "Function"}}
+
+ {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits INIT_PROC macro.
+-------------------------------------------------------------------------------
+*/}}
+{{define "C++.DefineInitProcMacro"}}
+ #define UNLIKELY(expr) __builtin_expect((expr), 0)
+ ¶
+ #define INIT_PROC(obj, proc) do { \
+ data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>( \
+ get_proc(obj, "vk" # proc)); \
+ if (UNLIKELY(!data.{{$}}.proc)) { \
+ ALOGE("missing " # obj " proc: vk" # proc); \
+ success = false; \
+ } \
+ } while(0)
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits code to invoke INIT_PROC or INIT_PROC_EXT.
+-------------------------------------------------------------------------------
+*/}}
+{{define "C++.InitProc"}}
+ {{AssertType $ "Function"}}
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
+ {{else}}
+ INIT_PROC(§
+ {{end}}
+
+ {{if (Macro "IsInstanceDispatched" $)}}
+ instance, §
+ {{else}}
+ dev, §
+ {{end}}
+
+ {{Macro "BaseName" $}});
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if a function is exported and instance-dispatched.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.IsInstanceDispatchTableEntry"}}
+ {{AssertType $ "Function"}}
+
+ {{if and (Macro "IsFunctionExported" $) (Macro "IsInstanceDispatched" $)}}
+ true
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if a function is exported and device-dispatched.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.IsDeviceDispatchTableEntry"}}
+ {{AssertType $ "Function"}}
+
+ {{if and (Macro "IsFunctionExported" $) (Macro "IsDeviceDispatched" $)}}
+ true
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if a function is intercepted by vulkan::api.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.IsIntercepted"}}
+ {{AssertType $ "Function"}}
+
+ {{if (Macro "IsFunctionSupported" $)}}
+ {{/* Global functions cannot be dispatched at all */}}
+ {{ if (Macro "IsGloballyDispatched" $)}}true
+
+ {{/* VkPhysicalDevice functions that manage device layers */}}
+ {{else if eq $.Name "vkCreateDevice"}}true
+ {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
+ {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
+
+ {{/* Destroy functions of dispatchable objects */}}
+ {{else if eq $.Name "vkDestroyInstance"}}true
+ {{else if eq $.Name "vkDestroyDevice"}}true
+
+ {{end}}
+ {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits INIT_PROC_EXT macro for vulkan::api.
+-------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.DefineInitProcExtMacro"}}
+ // Exported extension functions may be invoked even when their extensions
+ // are disabled. Dispatch to stubs when that happens.
+ #define INIT_PROC_EXT(ext, obj, proc) do { \
+ if (extensions[driver::ProcHook::ext]) \
+ INIT_PROC(obj, proc); \
+ else \
+ data.dispatch.proc = disabled ## proc; \
+ } while(0)
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits a stub for an exported extension function.
+-------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.DefineExtensionStub"}}
+ {{AssertType $ "Function"}}
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if and $ext (Macro "IsFunctionExported" $)}}
+ {{$ext_name := index $ext.Arguments 0}}
+
+ {{$base := (Macro "BaseName" $)}}
+ {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}}
+
+ VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$unnamed_params}}) {
+ ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed.");
+ {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
+ }
+ ¶
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits code for vkGetInstanceProcAddr for function interception.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.InterceptInstanceProcAddr"}}
+ {{AssertType $ "API"}}
+
+ // global functions
+ if (!instance) {
+ {{range $f := AllCommands $}}
+ {{if (Macro "IsGloballyDispatched" $f)}}
+ if (strcmp(pName, "{{$f.Name}}") == 0) return §
+ reinterpret_cast<PFN_vkVoidFunction>(§
+ vulkan::api::{{Macro "BaseName" $f}});
+ {{end}}
+ {{end}}
+ ¶
+ ALOGE("vkGetInstanceProcAddr called with %s without instance", pName);
+ return nullptr;
+ }
+ ¶
+ static const struct Hook {
+ const char* name;
+ PFN_vkVoidFunction proc;
+ } hooks[] = {
+ {{range $f := SortBy (AllCommands $) "FunctionName"}}
+ {{if (Macro "IsFunctionExported" $f)}}
+ {{/* hide global functions */}}
+ {{if (Macro "IsGloballyDispatched" $f)}}
+ { "{{$f.Name}}", nullptr },
+
+ {{/* redirect intercepted functions */}}
+ {{else if (Macro "api.IsIntercepted" $f)}}
+ { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
+ vulkan::api::{{Macro "BaseName" $f}}) },
+
+ {{/* redirect vkGetInstanceProcAddr to itself */}}
+ {{else if eq $f.Name "vkGetInstanceProcAddr"}}
+ { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
+
+ {{/* redirect device functions to themselves as a workaround for
+ layers that do not intercept in their vkGetInstanceProcAddr */}}
+ {{else if (Macro "IsDeviceDispatched" $f)}}
+ { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
+
+ {{end}}
+ {{end}}
+ {{end}}
+ };
+ // clang-format on
+ constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
+ auto hook = std::lower_bound(
+ hooks, hooks + count, pName,
+ [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
+ if (hook < hooks + count && strcmp(hook->name, pName) == 0) {
+ if (!hook->proc)
+ ALOGE("vkGetInstanceProcAddr called with %s with instance", pName);
+ return hook->proc;
+ }
+ // clang-format off
+ ¶
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits code for vkGetDeviceProcAddr for function interception.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.InterceptDeviceProcAddr"}}
+ {{AssertType $ "API"}}
+
+ if (device == VK_NULL_HANDLE) {
+ ALOGE("vkGetDeviceProcAddr called with invalid device");
+ return nullptr;
+ }
+ ¶
+ static const char* const known_non_device_names[] = {
+ {{range $f := SortBy (AllCommands $) "FunctionName"}}
+ {{if (Macro "IsFunctionSupported" $f)}}
+ {{if not (Macro "IsDeviceDispatched" $f)}}
+ "{{$f.Name}}",
+ {{end}}
+ {{end}}
+ {{end}}
+ };
+ // clang-format on
+ constexpr size_t count = sizeof(known_non_device_names) /
+ sizeof(known_non_device_names[0]);
+ if (!pName ||
+ std::binary_search(
+ known_non_device_names, known_non_device_names + count, pName,
+ [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
+ ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)");
+ return nullptr;
+ }
+ // clang-format off
+ ¶
+ {{range $f := AllCommands $}}
+ {{if (Macro "IsDeviceDispatched" $f)}}
+ {{ if (Macro "api.IsIntercepted" $f)}}
+ if (strcmp(pName, "{{$f.Name}}") == 0) return §
+ reinterpret_cast<PFN_vkVoidFunction>(§
+ vulkan::api::{{Macro "BaseName" $f}});
+ {{else if eq $f.Name "vkGetDeviceProcAddr"}}
+ if (strcmp(pName, "{{$f.Name}}") == 0) return §
+ reinterpret_cast<PFN_vkVoidFunction>(§
+ {{$f.Name}});
+ {{end}}
+ {{end}}
+ {{end}}
+ ¶
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits code to dispatch a function.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.Dispatch"}}
+ {{AssertType $ "Function"}}
+
+ {{if (Macro "api.IsIntercepted" $)}}// call into api.cpp{{end}}
+ {{if not (IsVoid $.Return.Type)}}return §{{end}}
+
+ {{if (Macro "api.IsIntercepted" $)}}
+ vulkan::api::§
+ {{else}}
+ {{$p0 := index $.CallParameters 0}}
+ vulkan::api::GetData({{$p0.Name}}).dispatch.§
+ {{end}}
+
+ {{Macro "BaseName" $}}({{Macro "Arguments" $}});
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits a list of extensions intercepted by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.InterceptedExtensions"}}
+VK_ANDROID_native_buffer
+VK_EXT_debug_report
+VK_KHR_android_surface
+VK_KHR_surface
+VK_KHR_swapchain
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if an extension is intercepted by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsExtensionIntercepted"}}
+ {{$ext_name := index $.Arguments 0}}
+ {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
+
+ {{range $f := $filters}}
+ {{if eq $ext_name $f}}true{{end}}
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if a function is intercepted by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsIntercepted"}}
+ {{AssertType $ "Function"}}
+
+ {{if (Macro "IsFunctionSupported" $)}}
+ {{/* Create functions of dispatchable objects */}}
+ {{ if eq $.Name "vkCreateInstance"}}true
+ {{else if eq $.Name "vkCreateDevice"}}true
+ {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
+ {{else if eq $.Name "vkGetDeviceQueue"}}true
+ {{else if eq $.Name "vkAllocateCommandBuffers"}}true
+
+ {{/* Destroy functions of dispatchable objects */}}
+ {{else if eq $.Name "vkDestroyInstance"}}true
+ {{else if eq $.Name "vkDestroyDevice"}}true
+
+ {{/* Enumeration of extensions */}}
+ {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
+ {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
+
+ {{else if eq $.Name "vkGetInstanceProcAddr"}}true
+ {{else if eq $.Name "vkGetDeviceProcAddr"}}true
+
+ {{end}}
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ {{Macro "driver.IsExtensionIntercepted" $ext}}
+ {{end}}
+
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if a function needs a ProcHook stub.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.NeedProcHookStub"}}
+ {{AssertType $ "Function"}}
+
+ {{if and (Macro "driver.IsIntercepted" $) (Macro "IsDeviceDispatched" $)}}
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
+ {{end}}
+ {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits definition of struct ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineProcHookType"}}
+ struct ProcHook {
+ enum Type {
+ GLOBAL,
+ INSTANCE,
+ DEVICE,
+ };
+
+ enum Extension {
+ {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
+ {{range $e := $exts}}
+ {{TrimPrefix "VK_" $e}},
+ {{end}}
+ ¶
+ EXTENSION_CORE, // valid bit
+ EXTENSION_COUNT,
+ EXTENSION_UNKNOWN,
+ };
+ ¶
+ const char* name;
+ Type type;
+ Extension extension;
+ ¶
+ PFN_vkVoidFunction proc;
+ PFN_vkVoidFunction checked_proc; // always nullptr for non-device hooks
+ };
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits INIT_PROC_EXT macro for vulkan::driver.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineInitProcExtMacro"}}
+ #define INIT_PROC_EXT(ext, obj, proc) do { \
+ if (extensions[ProcHook::ext]) \
+ INIT_PROC(obj, proc); \
+ } while(0)
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits a stub for ProcHook::checked_proc.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineProcHookStub"}}
+ {{AssertType $ "Function"}}
+
+ {{if (Macro "driver.NeedProcHookStub" $)}}
+ {{$ext := GetAnnotation $ "extension"}}
+ {{$ext_name := index $ext.Arguments 0}}
+
+ {{$base := (Macro "BaseName" $)}}
+ {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}}
+
+ VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
+ {{$p0 := index $.CallParameters 0}}
+ {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
+
+ if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) {
+ {{if not (IsVoid $.Return.Type)}}return §{{end}}
+ {{$base}}({{Macro "Arguments" $}});
+ } else {
+ ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed.");
+ {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
+ }
+ }
+ ¶
+ {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits definition of a global ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineGlobalProcHook"}}
+ {{AssertType $ "Function"}}
+
+ {{$base := (Macro "BaseName" $)}}
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ {{Error "invalid global extension"}}
+ {{end}}
+
+ {
+ "{{$.Name}}",
+ ProcHook::GLOBAL,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+ nullptr,
+ },
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits definition of an instance ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineInstanceProcHook"}}
+ {{AssertType $ "Function"}}
+
+ {{$base := (Macro "BaseName" $)}}
+
+ {
+ "{{$.Name}}",
+ ProcHook::INSTANCE,
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ ProcHook::{{Macro "BaseName" $ext}},
+
+ {{if (Macro "IsExtensionInternal" $ext)}}
+ nullptr,
+ nullptr,
+ {{else}}
+ reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+ nullptr,
+ {{end}}
+ {{else}}
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+ nullptr,
+ {{end}}
+ },
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits definition of a device ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineDeviceProcHook"}}
+ {{AssertType $ "Function"}}
+
+ {{$base := (Macro "BaseName" $)}}
+
+ {
+ "{{$.Name}}",
+ ProcHook::DEVICE,
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ ProcHook::{{Macro "BaseName" $ext}},
+
+ {{if (Macro "IsExtensionInternal" $ext)}}
+ nullptr,
+ nullptr,
+ {{else}}
+ reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+ reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
+ {{end}}
+ {{else}}
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+ nullptr,
+ {{end}}
+ },
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits true if a function is needed by vulkan::driver.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsDriverTableEntry"}}
+ {{AssertType $ "Function"}}
+
+ {{if (Macro "IsFunctionSupported" $)}}
+ {{/* Create functions of dispatchable objects */}}
+ {{ if eq $.Name "vkCreateDevice"}}true
+ {{else if eq $.Name "vkGetDeviceQueue"}}true
+ {{else if eq $.Name "vkAllocateCommandBuffers"}}true
+
+ {{/* Destroy functions of dispatchable objects */}}
+ {{else if eq $.Name "vkDestroyInstance"}}true
+ {{else if eq $.Name "vkDestroyDevice"}}true
+
+ {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
+
+ {{/* Enumeration of extensions */}}
+ {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
+
+ {{/* We cache physical devices in loader.cpp */}}
+ {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
+
+ {{else if eq $.Name "vkGetInstanceProcAddr"}}true
+ {{else if eq $.Name "vkGetDeviceProcAddr"}}true
+
+ {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
+ {{else if eq $.Name "vkCreateImage"}}true
+ {{else if eq $.Name "vkDestroyImage"}}true
+
+ {{end}}
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ {{$ext_name := index $ext.Arguments 0}}
+ {{ if eq $ext_name "VK_ANDROID_native_buffer"}}true
+ {{else if eq $ext_name "VK_EXT_debug_report"}}true
+ {{end}}
+ {{end}}
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if an instance-dispatched function is needed by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsInstanceDriverTableEntry"}}
+ {{AssertType $ "Function"}}
+
+ {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
+ true
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if a device-dispatched function is needed by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsDeviceDriverTableEntry"}}
+ {{AssertType $ "Function"}}
+
+ {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
+ true
+ {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits a function/extension name without the "vk"/"VK_" prefix.
+-------------------------------------------------------------------------------
+*/}}
+{{define "BaseName"}}
+ {{ if IsFunction $}}{{TrimPrefix "vk" $.Name}}
+ {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
+ {{else}}{{Error "invalid use of BaseName"}}
+ {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits a comma-separated list of C parameter names for the given command.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Arguments"}}
+ {{AssertType $ "Function"}}
+
+ {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+*/}}
+{{define "IsGloballyDispatched"}}
+ {{AssertType $ "Function"}}
+ {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
+ true
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emit "true" for supported functions that undergo table dispatch. Only global
+ functions and functions handled in the loader top without calling into
+ lower layers are not dispatched.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsInstanceDispatched"}}
+ {{AssertType $ "Function"}}
+ {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
+ true
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emit "true" for supported functions that can have device-specific dispatch.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsDeviceDispatched"}}
+ {{AssertType $ "Function"}}
+ {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
+ true
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emit "true" if a function is core or from a supportable extension.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsFunctionSupported"}}
+ {{AssertType $ "Function"}}
+ {{if not (GetAnnotation $ "pfn")}}
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if not $ext}}true
+ {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
+ {{end}}
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Decides whether a function should be exported from the Android Vulkan
+ library. Functions in the core API and in loader extensions are exported.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsFunctionExported"}}
+ {{AssertType $ "Function"}}
+
+ {{if (Macro "IsFunctionSupported" $)}}
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ {{Macro "IsExtensionExported" $ext}}
+ {{else}}
+ true
+ {{end}}
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emit "true" if an extension is unsupportable on Android.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsExtensionBlacklisted"}}
+ {{$ext := index $.Arguments 0}}
+ {{ if eq $ext "VK_KHR_display"}}true
+ {{else if eq $ext "VK_KHR_display_swapchain"}}true
+ {{else if eq $ext "VK_KHR_xlib_surface"}}true
+ {{else if eq $ext "VK_KHR_xcb_surface"}}true
+ {{else if eq $ext "VK_KHR_wayland_surface"}}true
+ {{else if eq $ext "VK_KHR_mir_surface"}}true
+ {{else if eq $ext "VK_KHR_win32_surface"}}true
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Reports whether an extension is implemented entirely by the loader,
+ so drivers should not enumerate it.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsExtensionExported"}}
+ {{$ext := index $.Arguments 0}}
+ {{ if eq $ext "VK_KHR_surface"}}true
+ {{else if eq $ext "VK_KHR_swapchain"}}true
+ {{else if eq $ext "VK_KHR_android_surface"}}true
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Reports whether an extension is internal to the loader and drivers,
+ so the loader should not enumerate it.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsExtensionInternal"}}
+ {{$ext := index $.Arguments 0}}
+ {{ if eq $ext "VK_ANDROID_native_buffer"}}true
+ {{end}}
+{{end}}
diff --git a/vulkan/libvulkan/debug_report.cpp b/vulkan/libvulkan/debug_report.cpp
index 41b6040..c4a1174 100644
--- a/vulkan/libvulkan/debug_report.cpp
+++ b/vulkan/libvulkan/debug_report.cpp
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-#include "loader.h"
+#include "driver.h"
namespace vulkan {
+namespace driver {
VkResult DebugReportCallbackList::CreateCallback(
VkInstance instance,
@@ -25,24 +26,22 @@
VkDebugReportCallbackEXT* callback) {
VkDebugReportCallbackEXT driver_callback = VK_NULL_HANDLE;
- if (GetDriverDispatch(instance).CreateDebugReportCallbackEXT) {
- VkResult result =
- GetDriverDispatch(instance).CreateDebugReportCallbackEXT(
- GetDriverInstance(instance), create_info, allocator,
- &driver_callback);
+ if (GetData(instance).driver.CreateDebugReportCallbackEXT) {
+ VkResult result = GetData(instance).driver.CreateDebugReportCallbackEXT(
+ instance, create_info, allocator, &driver_callback);
if (result != VK_SUCCESS)
return result;
}
const VkAllocationCallbacks* alloc =
- allocator ? allocator : GetAllocator(instance);
+ allocator ? allocator : &GetData(instance).allocator;
void* mem =
alloc->pfnAllocation(alloc->pUserData, sizeof(Node), alignof(Node),
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!mem) {
- if (GetDriverDispatch(instance).DestroyDebugReportCallbackEXT) {
- GetDriverDispatch(instance).DestroyDebugReportCallbackEXT(
- GetDriverInstance(instance), driver_callback, allocator);
+ if (GetData(instance).driver.DestroyDebugReportCallbackEXT) {
+ GetData(instance).driver.DestroyDebugReportCallbackEXT(
+ instance, driver_callback, allocator);
}
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
@@ -68,13 +67,13 @@
prev->next = node->next;
lock.unlock();
- if (GetDriverDispatch(instance).DestroyDebugReportCallbackEXT) {
- GetDriverDispatch(instance).DestroyDebugReportCallbackEXT(
- GetDriverInstance(instance), node->driver_callback, allocator);
+ if (GetData(instance).driver.DestroyDebugReportCallbackEXT) {
+ GetData(instance).driver.DestroyDebugReportCallbackEXT(
+ instance, node->driver_callback, allocator);
}
const VkAllocationCallbacks* alloc =
- allocator ? allocator : GetAllocator(instance);
+ allocator ? allocator : &GetData(instance).allocator;
alloc->pfnFree(alloc->pUserData, node);
}
@@ -95,40 +94,40 @@
}
}
-VkResult CreateDebugReportCallbackEXT_Bottom(
+VkResult CreateDebugReportCallbackEXT(
VkInstance instance,
const VkDebugReportCallbackCreateInfoEXT* create_info,
const VkAllocationCallbacks* allocator,
VkDebugReportCallbackEXT* callback) {
- return GetDebugReportCallbacks(instance).CreateCallback(
+ return GetData(instance).debug_report_callbacks.CreateCallback(
instance, create_info, allocator, callback);
}
-void DestroyDebugReportCallbackEXT_Bottom(
- VkInstance instance,
- VkDebugReportCallbackEXT callback,
- const VkAllocationCallbacks* allocator) {
+void DestroyDebugReportCallbackEXT(VkInstance instance,
+ VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks* allocator) {
if (callback)
- GetDebugReportCallbacks(instance).DestroyCallback(instance, callback,
- allocator);
+ GetData(instance).debug_report_callbacks.DestroyCallback(
+ instance, callback, allocator);
}
-void DebugReportMessageEXT_Bottom(VkInstance instance,
- VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT object_type,
- uint64_t object,
- size_t location,
- int32_t message_code,
- const char* layer_prefix,
- const char* message) {
- if (GetDriverDispatch(instance).DebugReportMessageEXT) {
- GetDriverDispatch(instance).DebugReportMessageEXT(
- GetDriverInstance(instance), flags, object_type, object, location,
- message_code, layer_prefix, message);
+void DebugReportMessageEXT(VkInstance instance,
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT object_type,
+ uint64_t object,
+ size_t location,
+ int32_t message_code,
+ const char* layer_prefix,
+ const char* message) {
+ if (GetData(instance).driver.DebugReportMessageEXT) {
+ GetData(instance).driver.DebugReportMessageEXT(
+ instance, flags, object_type, object, location, message_code,
+ layer_prefix, message);
}
- GetDebugReportCallbacks(instance).Message(flags, object_type, object,
- location, message_code,
- layer_prefix, message);
+ GetData(instance).debug_report_callbacks.Message(flags, object_type, object,
+ location, message_code,
+ layer_prefix, message);
}
+} // namespace driver
} // namespace vulkan
diff --git a/vulkan/libvulkan/debug_report.h b/vulkan/libvulkan/debug_report.h
index c6f7570..72b1887 100644
--- a/vulkan/libvulkan/debug_report.h
+++ b/vulkan/libvulkan/debug_report.h
@@ -17,14 +17,16 @@
#ifndef LIBVULKAN_DEBUG_REPORT_H
#define LIBVULKAN_DEBUG_REPORT_H 1
+#include <vulkan/vulkan.h>
#include <shared_mutex>
namespace vulkan {
+namespace driver {
// clang-format off
-VKAPI_ATTR VkResult CreateDebugReportCallbackEXT_Bottom(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
-VKAPI_ATTR void DestroyDebugReportCallbackEXT_Bottom(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
-VKAPI_ATTR void DebugReportMessageEXT_Bottom(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
+VKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
+VKAPI_ATTR void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
// clang-format on
class DebugReportCallbackList {
@@ -65,6 +67,7 @@
Node head_;
};
+} // namespace driver
} // namespace vulkan
#endif // LIBVULKAN_DEBUG_REPORT_H
diff --git a/vulkan/libvulkan/dispatch.tmpl b/vulkan/libvulkan/dispatch.tmpl
deleted file mode 100644
index 0a0338e..0000000
--- a/vulkan/libvulkan/dispatch.tmpl
+++ /dev/null
@@ -1,624 +0,0 @@
-{{/*
- * Copyright 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */}}
-
-{{Include "../api/templates/vulkan_common.tmpl"}}
-{{Global "clang-format" (Strings "clang-format" "-style=file")}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "dispatch_gen.h" | Format (Global "clang-format") | Write "dispatch_gen.h" }}
-{{$ | Macro "dispatch_gen.cpp" | Format (Global "clang-format") | Write "dispatch_gen.cpp"}}
-
-{{/*
--------------------------------------------------------------------------------
- dispatch_gen.h
--------------------------------------------------------------------------------
-*/}}
-{{define "dispatch_gen.h"}}
-/*
-•* Copyright 2015 The Android Open Source Project
-•*
-•* Licensed under the Apache License, Version 2.0 (the "License");
-•* you may not use this file except in compliance with the License.
-•* You may obtain a copy of the License at
-•*
-•* http://www.apache.org/licenses/LICENSE-2.0
-•*
-•* Unless required by applicable law or agreed to in writing, software
-•* distributed under the License is distributed on an "AS IS" BASIS,
-•* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-•* See the License for the specific language governing permissions and
-•* limitations under the License.
-•*/
-¶
-// WARNING: This file is generated. See ../README.md for instructions.
-¶
-#define VK_USE_PLATFORM_ANDROID_KHR
-#include <vulkan/vk_android_native_buffer.h>
-#include <vulkan/vulkan.h>
-¶
-namespace vulkan {
-¶
-struct InstanceDispatchTable {«
- // clang-format off
- {{range $f := AllCommands $}}
- {{if (Macro "IsInstanceDispatched" $f)}}
- {{Macro "FunctionPtrName" $f}} {{Macro "BaseName" $f}};
- {{end}}
- {{end}}
- // clang-format on
-»};
-¶
-struct DeviceDispatchTable {«
- // clang-format off
- {{range $f := AllCommands $}}
- {{if (Macro "IsDeviceDispatched" $f)}}
- {{Macro "FunctionPtrName" $f}} {{Macro "BaseName" $f}};
- {{end}}
- {{end}}
- // clang-format on
-»};
-¶
-struct DriverDispatchTable {«
- // clang-format off
- {{range $f := AllCommands $}}
- {{if (Macro "IsInstanceDispatched" $f)}}
- {{if not (Macro "IsLoaderFunction" $f)}}
- {{Macro "FunctionPtrName" $f}} {{Macro "BaseName" $f}};
- {{end}}
- {{end}}
- {{end}}
-
- PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
-
- {{/* TODO(jessehall): Needed by swapchain code. Figure out a better way of
- handling this that avoids the special case. Probably should rework
- things so the driver dispatch table has all driver functions. Probably
- need separate instance- and device-level copies, fill in all device-
- dispatched functions in the device-level copies only, and change
- GetDeviceProcAddr_Bottom to look in the already-loaded driver
- dispatch table rather than forwarding to the driver's
- vkGetDeviceProcAddr. */}}
- PFN_vkCreateImage CreateImage;
- PFN_vkDestroyImage DestroyImage;
-
- PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
- PFN_vkAcquireImageANDROID AcquireImageANDROID;
- PFN_vkQueueSignalReleaseImageANDROID QueueSignalReleaseImageANDROID;
- // clang-format on
-»};
-¶
-} // namespace vulkan
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
- dispatch_gen.cpp
--------------------------------------------------------------------------------
-*/}}
-{{define "dispatch_gen.cpp"}}
-/*
-•* Copyright 2015 The Android Open Source Project
-•*
-•* Licensed under the Apache License, Version 2.0 (the "License");
-•* you may not use this file except in compliance with the License.
-•* You may obtain a copy of the License at
-•*
-•* http://www.apache.org/licenses/LICENSE-2.0
-•*
-•* Unless required by applicable law or agreed to in writing, software
-•* distributed under the License is distributed on an "AS IS" BASIS,
-•* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-•* See the License for the specific language governing permissions and
-•* limitations under the License.
-•*/
-¶
-// WARNING: This file is generated. See ../README.md for instructions.
-¶
-#include <log/log.h>
-#include <algorithm>
-#include "loader.h"
-¶
-#define UNLIKELY(expr) __builtin_expect((expr), 0)
-¶
-using namespace vulkan;
-¶
-namespace {
-¶
-struct NameProc {
- const char* name;
- PFN_vkVoidFunction proc;
-};
-¶
-PFN_vkVoidFunction Lookup(const char* name, const NameProc* begin, const NameProc* end) {
- const auto& entry = std::lower_bound(
- begin, end, name,
- [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
- if (entry == end || strcmp(entry->name, name) != 0)
- return nullptr;
- return entry->proc;
-}
-¶
-template <size_t N>
-PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
- return Lookup(name, procs, procs + N);
-}
-¶
-const NameProc kLoaderExportProcs[] = {«
- // clang-format off
- {{range $f := SortBy (AllCommands $) "FunctionName"}}
- {{if (Macro "IsExported" $f)}}
- {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}})},
- {{end}}
- {{end}}
- // clang-format on
-»};
-¶
-const NameProc kLoaderGlobalProcs[] = {«
- // clang-format off
- {{range $f := SortBy (AllCommands $) "FunctionName"}}
- {{if and (Macro "HasLoaderTopImpl" $f) (eq (Macro "Vtbl" $f) "Global")}}
- {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
- static_cast<{{Macro "FunctionPtrName" $f}}>(§
- {{Macro "BaseName" $f}}_Top))},
- {{end}}
- {{end}}
- // clang-format on
-»};
-¶
-const NameProc kLoaderTopProcs[] = {«
- // clang-format off
- {{range $f := SortBy (AllCommands $) "FunctionName"}}
- {{if (Macro "HasLoaderTopImpl" $f)}}
- {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
- static_cast<{{Macro "FunctionPtrName" $f}}>(§
- {{Macro "BaseName" $f}}_Top))},
- {{end}}
- {{end}}
- // clang-format on
-»};
-¶
-const NameProc kLoaderBottomProcs[] = {«
- // clang-format off
- {{range $f := SortBy (AllCommands $) "FunctionName"}}
- {{if (Macro "HasLoaderBottomImpl" $f)}}
- {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
- static_cast<{{Macro "FunctionPtrName" $f}}>(§
- {{Macro "BaseName" $f}}_Bottom))},
- {{end}}
- {{end}}
- // clang-format on
-»};
-¶
-struct NameOffset {
- const char* name;
- size_t offset;
-};
-¶
-ssize_t Lookup(const char* name,
- const NameOffset* begin,
- const NameOffset* end) {
- const auto& entry = std::lower_bound(
- begin, end, name, [](const NameOffset& e, const char* n) {
- return strcmp(e.name, n) < 0;
- });
- if (entry == end || strcmp(entry->name, name) != 0)
- return -1;
- return static_cast<ssize_t>(entry->offset);
-}
-¶
-template <size_t N, class Table>
-PFN_vkVoidFunction Lookup(const char* name,
- const NameOffset (&offsets)[N],
- const Table& table) {
- ssize_t offset = Lookup(name, offsets, offsets + N);
- if (offset < 0)
- return nullptr;
- uintptr_t base = reinterpret_cast<uintptr_t>(&table);
- return *reinterpret_cast<PFN_vkVoidFunction*>(base +
- static_cast<size_t>(offset));
-}
-¶
-const NameOffset kInstanceDispatchOffsets[] = {«
- // clang-format off
- {{range $f := SortBy (AllCommands $) "FunctionName"}}
- {{if (Macro "IsInstanceDispatched" $f)}}
- {"{{$f.Name}}", offsetof(InstanceDispatchTable, {{Macro "BaseName" $f}})},
- {{end}}
- {{end}}
- // clang-format on
-»};
-¶
-const NameOffset kDeviceDispatchOffsets[] = {«
- // clang-format off
- {{range $f := SortBy (AllCommands $) "FunctionName"}}
- {{if (Macro "IsDeviceDispatched" $f)}}
- {"{{$f.Name}}", offsetof(DeviceDispatchTable, {{Macro "BaseName" $f}})},
- {{end}}
- {{end}}
- // clang-format on
-»};
-¶
-} // anonymous namespace
-¶
-namespace vulkan {
-¶
-PFN_vkVoidFunction GetLoaderExportProcAddr(const char* name) {
- return Lookup(name, kLoaderExportProcs);
-}
-¶
-PFN_vkVoidFunction GetLoaderGlobalProcAddr(const char* name) {
- return Lookup(name, kLoaderGlobalProcs);
-}
-¶
-PFN_vkVoidFunction GetLoaderTopProcAddr(const char* name) {
- return Lookup(name, kLoaderTopProcs);
-}
-¶
-PFN_vkVoidFunction GetLoaderBottomProcAddr(const char* name) {
- return Lookup(name, kLoaderBottomProcs);
-}
-¶
-PFN_vkVoidFunction GetDispatchProcAddr(const InstanceDispatchTable& dispatch,
- const char* name) {
- return Lookup(name, kInstanceDispatchOffsets, dispatch);
-}
-¶
-PFN_vkVoidFunction GetDispatchProcAddr(const DeviceDispatchTable& dispatch,
- const char* name) {
- return Lookup(name, kDeviceDispatchOffsets, dispatch);
-}
-¶
-bool LoadInstanceDispatchTable(VkInstance instance,
- PFN_vkGetInstanceProcAddr get_proc_addr,
- InstanceDispatchTable& dispatch) {«
- bool success = true;
- // clang-format off
- {{range $f := AllCommands $}}
- {{if (Macro "IsInstanceDispatched" $f)}}
- dispatch.{{Macro "BaseName" $f}} = §
- reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
- get_proc_addr(instance, "{{$f.Name}}"));
- if (UNLIKELY(!dispatch.{{Macro "BaseName" $f}})) {
- ALOGE("missing instance proc: %s", "{{$f.Name}}");
- success = false;
- }
- {{end}}
- {{end}}
- // clang-format on
- return success;
-»}
-¶
-bool LoadDeviceDispatchTable(VkDevice device,
- PFN_vkGetDeviceProcAddr get_proc_addr,
- DeviceDispatchTable& dispatch) {«
- bool success = true;
- // clang-format off
- {{range $f := AllCommands $}}
- {{if (Macro "IsDeviceDispatched" $f)}}
- dispatch.{{Macro "BaseName" $f}} = §
- reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
- get_proc_addr(device, "{{$f.Name}}"));
- if (UNLIKELY(!dispatch.{{Macro "BaseName" $f}})) {
- ALOGE("missing device proc: %s", "{{$f.Name}}");
- success = false;
- }
- {{end}}
- {{end}}
- // clang-format on
- return success;
-»}
-¶
-bool LoadDriverDispatchTable(VkInstance instance,
- PFN_vkGetInstanceProcAddr get_proc_addr,
- const InstanceExtensionSet& extensions,
- DriverDispatchTable& dispatch) {«
- bool success = true;
- // clang-format off
- {{range $f := AllCommands $}}
- {{if (Macro "IsInstanceDispatched" $f)}}
- {{if not (Macro "IsLoaderFunction" $f)}}
- {{$ext := GetAnnotation $f "extension"}}
- {{if $ext}}
- if (extensions[{{Macro "ExtensionConstant" $ext}}]) {
- {{end}}
- dispatch.{{Macro "BaseName" $f}} = §
- reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
- get_proc_addr(instance, "{{$f.Name}}"));
- if (UNLIKELY(!dispatch.{{Macro "BaseName" $f}})) {
- ALOGE("missing driver proc: %s", "{{$f.Name}}");
- success = false;
- }
- {{if $ext}}
- }
- {{end}}
- {{end}}
- {{end}}
- {{end}}
- dispatch.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(get_proc_addr(instance, "vkGetDeviceProcAddr"));
- if (UNLIKELY(!dispatch.GetDeviceProcAddr)) {
- ALOGE("missing driver proc: %s", "vkGetDeviceProcAddr");
- success = false;
- }
- dispatch.CreateImage = reinterpret_cast<PFN_vkCreateImage>(get_proc_addr(instance, "vkCreateImage"));
- if (UNLIKELY(!dispatch.CreateImage)) {
- ALOGE("missing driver proc: %s", "vkCreateImage");
- success = false;
- }
- dispatch.DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(get_proc_addr(instance, "vkDestroyImage"));
- if (UNLIKELY(!dispatch.DestroyImage)) {
- ALOGE("missing driver proc: %s", "vkDestroyImage");
- success = false;
- }
- dispatch.GetSwapchainGrallocUsageANDROID = reinterpret_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(get_proc_addr(instance, "vkGetSwapchainGrallocUsageANDROID"));
- if (UNLIKELY(!dispatch.GetSwapchainGrallocUsageANDROID)) {
- ALOGE("missing driver proc: %s", "vkGetSwapchainGrallocUsageANDROID");
- success = false;
- }
- dispatch.AcquireImageANDROID = reinterpret_cast<PFN_vkAcquireImageANDROID>(get_proc_addr(instance, "vkAcquireImageANDROID"));
- if (UNLIKELY(!dispatch.AcquireImageANDROID)) {
- ALOGE("missing driver proc: %s", "vkAcquireImageANDROID");
- success = false;
- }
- dispatch.QueueSignalReleaseImageANDROID = reinterpret_cast<PFN_vkQueueSignalReleaseImageANDROID>(get_proc_addr(instance, "vkQueueSignalReleaseImageANDROID"));
- if (UNLIKELY(!dispatch.QueueSignalReleaseImageANDROID)) {
- ALOGE("missing driver proc: %s", "vkQueueSignalReleaseImageANDROID");
- success = false;
- }
- // clang-format on
- return success;
-»}
-¶
-} // namespace vulkan
-¶
-// clang-format off
-¶
-{{range $f := AllCommands $}}
- {{if and (not (GetAnnotation $f "pfn")) (Macro "IsExported" $f)}}
- __attribute__((visibility("default")))
- VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
- {{if not (IsVoid $f.Return.Type)}}return §{{end}}
- {{Macro "Dispatch" $f}}({{Macro "Arguments" $f}});
- }
- ¶
- {{end}}
-{{end}}
-¶
-// clang-format on
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
- Emit the dispatch lookup for a function based on its first parameter.
--------------------------------------------------------------------------------
-*/}}
-{{define "Dispatch"}}
- {{AssertType $ "Function"}}
-
- {{if (Macro "HasLoaderTopImpl" $)}}
- {{Macro "BaseName" $}}_Top§
- {{else}}
- {{$p0 := index $.CallParameters 0}}
- GetDispatchTable({{$p0.Name}}).{{Macro "BaseName" $}}§
- {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
- Map an extension name to InstanceExtension or DeviceExtension enum value
--------------------------------------------------------------------------------
-*/}}
-{{define "ExtensionConstant"}}
- {{$name := index $.Arguments 0}}
- {{ if (eq $name "VK_KHR_surface")}}kKHR_surface
- {{else if (eq $name "VK_KHR_android_surface")}}kKHR_android_surface
- {{else if (eq $name "VK_EXT_debug_report")}}kEXT_debug_report
- {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
- Emits a function name without the "vk" prefix.
--------------------------------------------------------------------------------
-*/}}
-{{define "BaseName"}}
- {{AssertType $ "Function"}}
- {{TrimPrefix "vk" $.Name}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
- Emits a comma-separated list of C parameter names for the given command.
--------------------------------------------------------------------------------
-*/}}
-{{define "Arguments"}}
- {{AssertType $ "Function"}}
-
- {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Emit "true" for supported functions that undergo table dispatch. Only global
- functions and functions handled in the loader top without calling into
- lower layers are not dispatched.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsInstanceDispatched"}}
- {{AssertType $ "Function"}}
- {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
- {{if and (ne $.Name "vkEnumerateDeviceLayerProperties") (ne $.Name "vkGetInstanceProcAddr")}}true{{end}}
- {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Emit "true" for supported functions that can have device-specific dispatch.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsDeviceDispatched"}}
- {{AssertType $ "Function"}}
- {{if (Macro "IsFunctionSupported" $)}}
- {{if eq (Macro "Vtbl" $) "Device"}}
- {{if ne $.Name "vkGetDeviceProcAddr"}}
- true
- {{end}}
- {{end}}
- {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Emit "true" if a function is core or from a supportable extension.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsFunctionSupported"}}
- {{AssertType $ "Function"}}
- {{if not (GetAnnotation $ "pfn")}}
- {{$ext := GetAnnotation $ "extension"}}
- {{if not $ext}}true
- {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
- {{end}}
- {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Decides whether a function should be exported from the Android Vulkan
- library. Functions in the core API and in loader extensions are exported.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsExported"}}
- {{AssertType $ "Function"}}
-
- {{if (Macro "IsFunctionSupported" $)}}
- {{$ext := GetAnnotation $ "extension"}}
- {{if $ext}}
- {{Macro "IsLoaderExtension" $ext}}
- {{else}}
- true
- {{end}}
- {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Reports whether an extension function is implemented entirely by the loader,
- and not implemented by drivers.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsLoaderFunction"}}
- {{AssertType $ "Function"}}
-
- {{$ext := GetAnnotation $ "extension"}}
- {{if $ext}}
- {{Macro "IsLoaderExtension" $ext}}
- {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
- Emit "true" if the loader has a top-level implementation for the function
- that should be called directly rather than dispatching to the first layer.
--------------------------------------------------------------------------------
-*/}}
-{{define "HasLoaderTopImpl"}}
- {{AssertType $ "Function"}}
-
- {{/* Global functions can't be dispatched */}}
- {{ if and (not (GetAnnotation $ "pfn")) (eq (Macro "Vtbl" $) "Global")}}true
-
- {{/* G*PA are implemented by reading the dispatch table, not by dispatching
- through it. */}}
- {{else if eq $.Name "vkGetInstanceProcAddr"}}true
- {{else if eq $.Name "vkGetDeviceProcAddr"}}true
-
- {{/* Loader top needs to initialize dispatch for device-level dispatchable
- objects */}}
- {{else if eq $.Name "vkGetDeviceQueue"}}true
- {{else if eq $.Name "vkAllocateCommandBuffers"}}true
- {{else if eq $.Name "vkCreateDevice"}}true
- {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
- {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
-
- {{/* vkDestroy for dispatchable objects needs to handle VK_NULL_HANDLE;
- trying to dispatch through that would crash. */}}
- {{else if eq $.Name "vkDestroyInstance"}}true
- {{else if eq $.Name "vkDestroyDevice"}}true
-
- {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
- Emit "true" if the loader has a bottom-level implementation for the function
- which terminates the dispatch chain.
--------------------------------------------------------------------------------
-*/}}
-{{define "HasLoaderBottomImpl"}}
- {{AssertType $ "Function"}}
-
- {{if (Macro "IsFunctionSupported" $)}}
- {{ if (eq (Macro "Vtbl" $) "Instance")}}true
- {{else if (Macro "IsLoaderFunction" $)}}true
- {{else if (eq $.Name "vkCreateInstance")}}true
- {{else if (eq $.Name "vkGetDeviceProcAddr")}}true
- {{end}}
- {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Emit "true" if an extension is unsupportable on Android.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsExtensionBlacklisted"}}
- {{$ext := index $.Arguments 0}}
- {{ if eq $ext "VK_KHR_display"}}true
- {{else if eq $ext "VK_KHR_display_swapchain"}}true
- {{else if eq $ext "VK_KHR_xlib_surface"}}true
- {{else if eq $ext "VK_KHR_xcb_surface"}}true
- {{else if eq $ext "VK_KHR_wayland_surface"}}true
- {{else if eq $ext "VK_KHR_mir_surface"}}true
- {{else if eq $ext "VK_KHR_win32_surface"}}true
- {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Reports whether an extension is implemented entirely by the loader,
- so drivers should not enumerate it.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsLoaderExtension"}}
- {{$ext := index $.Arguments 0}}
- {{ if eq $ext "VK_KHR_surface"}}true
- {{else if eq $ext "VK_KHR_swapchain"}}true
- {{else if eq $ext "VK_KHR_android_surface"}}true
- {{end}}
-{{end}}
diff --git a/vulkan/libvulkan/dispatch_gen.cpp b/vulkan/libvulkan/dispatch_gen.cpp
deleted file mode 100644
index b41efb8..0000000
--- a/vulkan/libvulkan/dispatch_gen.cpp
+++ /dev/null
@@ -1,2079 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// WARNING: This file is generated. See ../README.md for instructions.
-
-#include <log/log.h>
-#include <algorithm>
-#include "loader.h"
-
-#define UNLIKELY(expr) __builtin_expect((expr), 0)
-
-using namespace vulkan;
-
-namespace {
-
-struct NameProc {
- const char* name;
- PFN_vkVoidFunction proc;
-};
-
-PFN_vkVoidFunction Lookup(const char* name,
- const NameProc* begin,
- const NameProc* end) {
- const auto& entry = std::lower_bound(
- begin, end, name,
- [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
- if (entry == end || strcmp(entry->name, name) != 0)
- return nullptr;
- return entry->proc;
-}
-
-template <size_t N>
-PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
- return Lookup(name, procs, procs + N);
-}
-
-const NameProc kLoaderExportProcs[] = {
- // clang-format off
- {"vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR)},
- {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(vkAllocateCommandBuffers)},
- {"vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkAllocateDescriptorSets)},
- {"vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(vkAllocateMemory)},
- {"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkBeginCommandBuffer)},
- {"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(vkBindBufferMemory)},
- {"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(vkBindImageMemory)},
- {"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBeginQuery)},
- {"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBeginRenderPass)},
- {"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindDescriptorSets)},
- {"vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindIndexBuffer)},
- {"vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindPipeline)},
- {"vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindVertexBuffers)},
- {"vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBlitImage)},
- {"vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearAttachments)},
- {"vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearColorImage)},
- {"vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearDepthStencilImage)},
- {"vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyBuffer)},
- {"vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyBufferToImage)},
- {"vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyImage)},
- {"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyImageToBuffer)},
- {"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyQueryPoolResults)},
- {"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDispatch)},
- {"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDispatchIndirect)},
- {"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDraw)},
- {"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndexed)},
- {"vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndexedIndirect)},
- {"vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndirect)},
- {"vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(vkCmdEndQuery)},
- {"vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdEndRenderPass)},
- {"vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(vkCmdExecuteCommands)},
- {"vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdFillBuffer)},
- {"vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdNextSubpass)},
- {"vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(vkCmdPipelineBarrier)},
- {"vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(vkCmdPushConstants)},
- {"vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResetEvent)},
- {"vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResetQueryPool)},
- {"vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResolveImage)},
- {"vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetBlendConstants)},
- {"vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetDepthBias)},
- {"vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetDepthBounds)},
- {"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetEvent)},
- {"vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetLineWidth)},
- {"vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetScissor)},
- {"vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetStencilCompareMask)},
- {"vkCmdSetStencilReference", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetStencilReference)},
- {"vkCmdSetStencilWriteMask", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetStencilWriteMask)},
- {"vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetViewport)},
- {"vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdUpdateBuffer)},
- {"vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(vkCmdWaitEvents)},
- {"vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(vkCmdWriteTimestamp)},
- {"vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(vkCreateAndroidSurfaceKHR)},
- {"vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCreateBuffer)},
- {"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(vkCreateBufferView)},
- {"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateCommandPool)},
- {"vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(vkCreateComputePipelines)},
- {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDescriptorPool)},
- {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDescriptorSetLayout)},
- {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDevice)},
- {"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCreateEvent)},
- {"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(vkCreateFence)},
- {"vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCreateFramebuffer)},
- {"vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(vkCreateGraphicsPipelines)},
- {"vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(vkCreateImage)},
- {"vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(vkCreateImageView)},
- {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(vkCreateInstance)},
- {"vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(vkCreatePipelineCache)},
- {"vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(vkCreatePipelineLayout)},
- {"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateQueryPool)},
- {"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCreateRenderPass)},
- {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(vkCreateSampler)},
- {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(vkCreateSemaphore)},
- {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(vkCreateShaderModule)},
- {"vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR)},
- {"vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyBuffer)},
- {"vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyBufferView)},
- {"vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyCommandPool)},
- {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDescriptorPool)},
- {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDescriptorSetLayout)},
- {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDevice)},
- {"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyEvent)},
- {"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyFence)},
- {"vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyFramebuffer)},
- {"vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyImage)},
- {"vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyImageView)},
- {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyInstance)},
- {"vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipeline)},
- {"vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipelineCache)},
- {"vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipelineLayout)},
- {"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyQueryPool)},
- {"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyRenderPass)},
- {"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySampler)},
- {"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySemaphore)},
- {"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyShaderModule)},
- {"vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySurfaceKHR)},
- {"vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR)},
- {"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(vkDeviceWaitIdle)},
- {"vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkEndCommandBuffer)},
- {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateDeviceExtensionProperties)},
- {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateDeviceLayerProperties)},
- {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceExtensionProperties)},
- {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceLayerProperties)},
- {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(vkEnumeratePhysicalDevices)},
- {"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(vkFlushMappedMemoryRanges)},
- {"vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(vkFreeCommandBuffers)},
- {"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkFreeDescriptorSets)},
- {"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(vkFreeMemory)},
- {"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetBufferMemoryRequirements)},
- {"vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceMemoryCommitment)},
- {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceProcAddr)},
- {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceQueue)},
- {"vkGetEventStatus", reinterpret_cast<PFN_vkVoidFunction>(vkGetEventStatus)},
- {"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(vkGetFenceStatus)},
- {"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageMemoryRequirements)},
- {"vkGetImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageSparseMemoryRequirements)},
- {"vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageSubresourceLayout)},
- {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr)},
- {"vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceFeatures)},
- {"vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceFormatProperties)},
- {"vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceImageFormatProperties)},
- {"vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceMemoryProperties)},
- {"vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceProperties)},
- {"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceQueueFamilyProperties)},
- {"vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSparseImageFormatProperties)},
- {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceCapabilitiesKHR)},
- {"vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceFormatsKHR)},
- {"vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfacePresentModesKHR)},
- {"vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR)},
- {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(vkGetPipelineCacheData)},
- {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(vkGetQueryPoolResults)},
- {"vkGetRenderAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(vkGetRenderAreaGranularity)},
- {"vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR)},
- {"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(vkInvalidateMappedMemoryRanges)},
- {"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(vkMapMemory)},
- {"vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(vkMergePipelineCaches)},
- {"vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(vkQueueBindSparse)},
- {"vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR)},
- {"vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(vkQueueSubmit)},
- {"vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(vkQueueWaitIdle)},
- {"vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkResetCommandBuffer)},
- {"vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkResetCommandPool)},
- {"vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkResetDescriptorPool)},
- {"vkResetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkResetEvent)},
- {"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(vkResetFences)},
- {"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkSetEvent)},
- {"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(vkUnmapMemory)},
- {"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkUpdateDescriptorSets)},
- {"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(vkWaitForFences)},
- // clang-format on
-};
-
-const NameProc kLoaderGlobalProcs[] = {
- // clang-format off
- {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateInstance>(CreateInstance_Top))},
- {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceExtensionProperties>(EnumerateInstanceExtensionProperties_Top))},
- {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceLayerProperties>(EnumerateInstanceLayerProperties_Top))},
- // clang-format on
-};
-
-const NameProc kLoaderTopProcs[] = {
- // clang-format off
- {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAllocateCommandBuffers>(AllocateCommandBuffers_Top))},
- {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDevice>(CreateDevice_Top))},
- {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateInstance>(CreateInstance_Top))},
- {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDevice>(DestroyDevice_Top))},
- {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyInstance>(DestroyInstance_Top))},
- {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceExtensionProperties>(EnumerateDeviceExtensionProperties_Top))},
- {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceLayerProperties>(EnumerateDeviceLayerProperties_Top))},
- {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceExtensionProperties>(EnumerateInstanceExtensionProperties_Top))},
- {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceLayerProperties>(EnumerateInstanceLayerProperties_Top))},
- {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr_Top))},
- {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceQueue>(GetDeviceQueue_Top))},
- {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr_Top))},
- // clang-format on
-};
-
-const NameProc kLoaderBottomProcs[] = {
- // clang-format off
- {"vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAcquireNextImageKHR>(AcquireNextImageKHR_Bottom))},
- {"vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateAndroidSurfaceKHR>(CreateAndroidSurfaceKHR_Bottom))},
- {"vkCreateDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDebugReportCallbackEXT>(CreateDebugReportCallbackEXT_Bottom))},
- {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDevice>(CreateDevice_Bottom))},
- {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateInstance>(CreateInstance_Bottom))},
- {"vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSwapchainKHR>(CreateSwapchainKHR_Bottom))},
- {"vkDebugReportMessageEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDebugReportMessageEXT>(DebugReportMessageEXT_Bottom))},
- {"vkDestroyDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDebugReportCallbackEXT>(DestroyDebugReportCallbackEXT_Bottom))},
- {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyInstance>(DestroyInstance_Bottom))},
- {"vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySurfaceKHR>(DestroySurfaceKHR_Bottom))},
- {"vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySwapchainKHR>(DestroySwapchainKHR_Bottom))},
- {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceExtensionProperties>(EnumerateDeviceExtensionProperties_Bottom))},
- {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceLayerProperties>(EnumerateDeviceLayerProperties_Bottom))},
- {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumeratePhysicalDevices>(EnumeratePhysicalDevices_Bottom))},
- {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr_Bottom))},
- {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr_Bottom))},
- {"vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFeatures>(GetPhysicalDeviceFeatures_Bottom))},
- {"vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFormatProperties>(GetPhysicalDeviceFormatProperties_Bottom))},
- {"vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(GetPhysicalDeviceImageFormatProperties_Bottom))},
- {"vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(GetPhysicalDeviceMemoryProperties_Bottom))},
- {"vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceProperties>(GetPhysicalDeviceProperties_Bottom))},
- {"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(GetPhysicalDeviceQueueFamilyProperties_Bottom))},
- {"vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(GetPhysicalDeviceSparseImageFormatProperties_Bottom))},
- {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(GetPhysicalDeviceSurfaceCapabilitiesKHR_Bottom))},
- {"vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(GetPhysicalDeviceSurfaceFormatsKHR_Bottom))},
- {"vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(GetPhysicalDeviceSurfacePresentModesKHR_Bottom))},
- {"vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(GetPhysicalDeviceSurfaceSupportKHR_Bottom))},
- {"vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetSwapchainImagesKHR>(GetSwapchainImagesKHR_Bottom))},
- {"vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkQueuePresentKHR>(QueuePresentKHR_Bottom))},
- // clang-format on
-};
-
-struct NameOffset {
- const char* name;
- size_t offset;
-};
-
-ssize_t Lookup(const char* name,
- const NameOffset* begin,
- const NameOffset* end) {
- const auto& entry = std::lower_bound(
- begin, end, name, [](const NameOffset& e, const char* n) {
- return strcmp(e.name, n) < 0;
- });
- if (entry == end || strcmp(entry->name, name) != 0)
- return -1;
- return static_cast<ssize_t>(entry->offset);
-}
-
-template <size_t N, class Table>
-PFN_vkVoidFunction Lookup(const char* name,
- const NameOffset (&offsets)[N],
- const Table& table) {
- ssize_t offset = Lookup(name, offsets, offsets + N);
- if (offset < 0)
- return nullptr;
- uintptr_t base = reinterpret_cast<uintptr_t>(&table);
- return *reinterpret_cast<PFN_vkVoidFunction*>(base +
- static_cast<size_t>(offset));
-}
-
-const NameOffset kInstanceDispatchOffsets[] = {
- // clang-format off
- {"vkCreateAndroidSurfaceKHR", offsetof(InstanceDispatchTable, CreateAndroidSurfaceKHR)},
- {"vkCreateDebugReportCallbackEXT", offsetof(InstanceDispatchTable, CreateDebugReportCallbackEXT)},
- {"vkCreateDevice", offsetof(InstanceDispatchTable, CreateDevice)},
- {"vkDebugReportMessageEXT", offsetof(InstanceDispatchTable, DebugReportMessageEXT)},
- {"vkDestroyDebugReportCallbackEXT", offsetof(InstanceDispatchTable, DestroyDebugReportCallbackEXT)},
- {"vkDestroyInstance", offsetof(InstanceDispatchTable, DestroyInstance)},
- {"vkDestroySurfaceKHR", offsetof(InstanceDispatchTable, DestroySurfaceKHR)},
- {"vkEnumerateDeviceExtensionProperties", offsetof(InstanceDispatchTable, EnumerateDeviceExtensionProperties)},
- {"vkEnumeratePhysicalDevices", offsetof(InstanceDispatchTable, EnumeratePhysicalDevices)},
- {"vkGetPhysicalDeviceFeatures", offsetof(InstanceDispatchTable, GetPhysicalDeviceFeatures)},
- {"vkGetPhysicalDeviceFormatProperties", offsetof(InstanceDispatchTable, GetPhysicalDeviceFormatProperties)},
- {"vkGetPhysicalDeviceImageFormatProperties", offsetof(InstanceDispatchTable, GetPhysicalDeviceImageFormatProperties)},
- {"vkGetPhysicalDeviceMemoryProperties", offsetof(InstanceDispatchTable, GetPhysicalDeviceMemoryProperties)},
- {"vkGetPhysicalDeviceProperties", offsetof(InstanceDispatchTable, GetPhysicalDeviceProperties)},
- {"vkGetPhysicalDeviceQueueFamilyProperties", offsetof(InstanceDispatchTable, GetPhysicalDeviceQueueFamilyProperties)},
- {"vkGetPhysicalDeviceSparseImageFormatProperties", offsetof(InstanceDispatchTable, GetPhysicalDeviceSparseImageFormatProperties)},
- {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", offsetof(InstanceDispatchTable, GetPhysicalDeviceSurfaceCapabilitiesKHR)},
- {"vkGetPhysicalDeviceSurfaceFormatsKHR", offsetof(InstanceDispatchTable, GetPhysicalDeviceSurfaceFormatsKHR)},
- {"vkGetPhysicalDeviceSurfacePresentModesKHR", offsetof(InstanceDispatchTable, GetPhysicalDeviceSurfacePresentModesKHR)},
- {"vkGetPhysicalDeviceSurfaceSupportKHR", offsetof(InstanceDispatchTable, GetPhysicalDeviceSurfaceSupportKHR)},
- // clang-format on
-};
-
-const NameOffset kDeviceDispatchOffsets[] = {
- // clang-format off
- {"vkAcquireNextImageKHR", offsetof(DeviceDispatchTable, AcquireNextImageKHR)},
- {"vkAllocateCommandBuffers", offsetof(DeviceDispatchTable, AllocateCommandBuffers)},
- {"vkAllocateDescriptorSets", offsetof(DeviceDispatchTable, AllocateDescriptorSets)},
- {"vkAllocateMemory", offsetof(DeviceDispatchTable, AllocateMemory)},
- {"vkBeginCommandBuffer", offsetof(DeviceDispatchTable, BeginCommandBuffer)},
- {"vkBindBufferMemory", offsetof(DeviceDispatchTable, BindBufferMemory)},
- {"vkBindImageMemory", offsetof(DeviceDispatchTable, BindImageMemory)},
- {"vkCmdBeginQuery", offsetof(DeviceDispatchTable, CmdBeginQuery)},
- {"vkCmdBeginRenderPass", offsetof(DeviceDispatchTable, CmdBeginRenderPass)},
- {"vkCmdBindDescriptorSets", offsetof(DeviceDispatchTable, CmdBindDescriptorSets)},
- {"vkCmdBindIndexBuffer", offsetof(DeviceDispatchTable, CmdBindIndexBuffer)},
- {"vkCmdBindPipeline", offsetof(DeviceDispatchTable, CmdBindPipeline)},
- {"vkCmdBindVertexBuffers", offsetof(DeviceDispatchTable, CmdBindVertexBuffers)},
- {"vkCmdBlitImage", offsetof(DeviceDispatchTable, CmdBlitImage)},
- {"vkCmdClearAttachments", offsetof(DeviceDispatchTable, CmdClearAttachments)},
- {"vkCmdClearColorImage", offsetof(DeviceDispatchTable, CmdClearColorImage)},
- {"vkCmdClearDepthStencilImage", offsetof(DeviceDispatchTable, CmdClearDepthStencilImage)},
- {"vkCmdCopyBuffer", offsetof(DeviceDispatchTable, CmdCopyBuffer)},
- {"vkCmdCopyBufferToImage", offsetof(DeviceDispatchTable, CmdCopyBufferToImage)},
- {"vkCmdCopyImage", offsetof(DeviceDispatchTable, CmdCopyImage)},
- {"vkCmdCopyImageToBuffer", offsetof(DeviceDispatchTable, CmdCopyImageToBuffer)},
- {"vkCmdCopyQueryPoolResults", offsetof(DeviceDispatchTable, CmdCopyQueryPoolResults)},
- {"vkCmdDispatch", offsetof(DeviceDispatchTable, CmdDispatch)},
- {"vkCmdDispatchIndirect", offsetof(DeviceDispatchTable, CmdDispatchIndirect)},
- {"vkCmdDraw", offsetof(DeviceDispatchTable, CmdDraw)},
- {"vkCmdDrawIndexed", offsetof(DeviceDispatchTable, CmdDrawIndexed)},
- {"vkCmdDrawIndexedIndirect", offsetof(DeviceDispatchTable, CmdDrawIndexedIndirect)},
- {"vkCmdDrawIndirect", offsetof(DeviceDispatchTable, CmdDrawIndirect)},
- {"vkCmdEndQuery", offsetof(DeviceDispatchTable, CmdEndQuery)},
- {"vkCmdEndRenderPass", offsetof(DeviceDispatchTable, CmdEndRenderPass)},
- {"vkCmdExecuteCommands", offsetof(DeviceDispatchTable, CmdExecuteCommands)},
- {"vkCmdFillBuffer", offsetof(DeviceDispatchTable, CmdFillBuffer)},
- {"vkCmdNextSubpass", offsetof(DeviceDispatchTable, CmdNextSubpass)},
- {"vkCmdPipelineBarrier", offsetof(DeviceDispatchTable, CmdPipelineBarrier)},
- {"vkCmdPushConstants", offsetof(DeviceDispatchTable, CmdPushConstants)},
- {"vkCmdResetEvent", offsetof(DeviceDispatchTable, CmdResetEvent)},
- {"vkCmdResetQueryPool", offsetof(DeviceDispatchTable, CmdResetQueryPool)},
- {"vkCmdResolveImage", offsetof(DeviceDispatchTable, CmdResolveImage)},
- {"vkCmdSetBlendConstants", offsetof(DeviceDispatchTable, CmdSetBlendConstants)},
- {"vkCmdSetDepthBias", offsetof(DeviceDispatchTable, CmdSetDepthBias)},
- {"vkCmdSetDepthBounds", offsetof(DeviceDispatchTable, CmdSetDepthBounds)},
- {"vkCmdSetEvent", offsetof(DeviceDispatchTable, CmdSetEvent)},
- {"vkCmdSetLineWidth", offsetof(DeviceDispatchTable, CmdSetLineWidth)},
- {"vkCmdSetScissor", offsetof(DeviceDispatchTable, CmdSetScissor)},
- {"vkCmdSetStencilCompareMask", offsetof(DeviceDispatchTable, CmdSetStencilCompareMask)},
- {"vkCmdSetStencilReference", offsetof(DeviceDispatchTable, CmdSetStencilReference)},
- {"vkCmdSetStencilWriteMask", offsetof(DeviceDispatchTable, CmdSetStencilWriteMask)},
- {"vkCmdSetViewport", offsetof(DeviceDispatchTable, CmdSetViewport)},
- {"vkCmdUpdateBuffer", offsetof(DeviceDispatchTable, CmdUpdateBuffer)},
- {"vkCmdWaitEvents", offsetof(DeviceDispatchTable, CmdWaitEvents)},
- {"vkCmdWriteTimestamp", offsetof(DeviceDispatchTable, CmdWriteTimestamp)},
- {"vkCreateBuffer", offsetof(DeviceDispatchTable, CreateBuffer)},
- {"vkCreateBufferView", offsetof(DeviceDispatchTable, CreateBufferView)},
- {"vkCreateCommandPool", offsetof(DeviceDispatchTable, CreateCommandPool)},
- {"vkCreateComputePipelines", offsetof(DeviceDispatchTable, CreateComputePipelines)},
- {"vkCreateDescriptorPool", offsetof(DeviceDispatchTable, CreateDescriptorPool)},
- {"vkCreateDescriptorSetLayout", offsetof(DeviceDispatchTable, CreateDescriptorSetLayout)},
- {"vkCreateEvent", offsetof(DeviceDispatchTable, CreateEvent)},
- {"vkCreateFence", offsetof(DeviceDispatchTable, CreateFence)},
- {"vkCreateFramebuffer", offsetof(DeviceDispatchTable, CreateFramebuffer)},
- {"vkCreateGraphicsPipelines", offsetof(DeviceDispatchTable, CreateGraphicsPipelines)},
- {"vkCreateImage", offsetof(DeviceDispatchTable, CreateImage)},
- {"vkCreateImageView", offsetof(DeviceDispatchTable, CreateImageView)},
- {"vkCreatePipelineCache", offsetof(DeviceDispatchTable, CreatePipelineCache)},
- {"vkCreatePipelineLayout", offsetof(DeviceDispatchTable, CreatePipelineLayout)},
- {"vkCreateQueryPool", offsetof(DeviceDispatchTable, CreateQueryPool)},
- {"vkCreateRenderPass", offsetof(DeviceDispatchTable, CreateRenderPass)},
- {"vkCreateSampler", offsetof(DeviceDispatchTable, CreateSampler)},
- {"vkCreateSemaphore", offsetof(DeviceDispatchTable, CreateSemaphore)},
- {"vkCreateShaderModule", offsetof(DeviceDispatchTable, CreateShaderModule)},
- {"vkCreateSwapchainKHR", offsetof(DeviceDispatchTable, CreateSwapchainKHR)},
- {"vkDestroyBuffer", offsetof(DeviceDispatchTable, DestroyBuffer)},
- {"vkDestroyBufferView", offsetof(DeviceDispatchTable, DestroyBufferView)},
- {"vkDestroyCommandPool", offsetof(DeviceDispatchTable, DestroyCommandPool)},
- {"vkDestroyDescriptorPool", offsetof(DeviceDispatchTable, DestroyDescriptorPool)},
- {"vkDestroyDescriptorSetLayout", offsetof(DeviceDispatchTable, DestroyDescriptorSetLayout)},
- {"vkDestroyDevice", offsetof(DeviceDispatchTable, DestroyDevice)},
- {"vkDestroyEvent", offsetof(DeviceDispatchTable, DestroyEvent)},
- {"vkDestroyFence", offsetof(DeviceDispatchTable, DestroyFence)},
- {"vkDestroyFramebuffer", offsetof(DeviceDispatchTable, DestroyFramebuffer)},
- {"vkDestroyImage", offsetof(DeviceDispatchTable, DestroyImage)},
- {"vkDestroyImageView", offsetof(DeviceDispatchTable, DestroyImageView)},
- {"vkDestroyPipeline", offsetof(DeviceDispatchTable, DestroyPipeline)},
- {"vkDestroyPipelineCache", offsetof(DeviceDispatchTable, DestroyPipelineCache)},
- {"vkDestroyPipelineLayout", offsetof(DeviceDispatchTable, DestroyPipelineLayout)},
- {"vkDestroyQueryPool", offsetof(DeviceDispatchTable, DestroyQueryPool)},
- {"vkDestroyRenderPass", offsetof(DeviceDispatchTable, DestroyRenderPass)},
- {"vkDestroySampler", offsetof(DeviceDispatchTable, DestroySampler)},
- {"vkDestroySemaphore", offsetof(DeviceDispatchTable, DestroySemaphore)},
- {"vkDestroyShaderModule", offsetof(DeviceDispatchTable, DestroyShaderModule)},
- {"vkDestroySwapchainKHR", offsetof(DeviceDispatchTable, DestroySwapchainKHR)},
- {"vkDeviceWaitIdle", offsetof(DeviceDispatchTable, DeviceWaitIdle)},
- {"vkEndCommandBuffer", offsetof(DeviceDispatchTable, EndCommandBuffer)},
- {"vkFlushMappedMemoryRanges", offsetof(DeviceDispatchTable, FlushMappedMemoryRanges)},
- {"vkFreeCommandBuffers", offsetof(DeviceDispatchTable, FreeCommandBuffers)},
- {"vkFreeDescriptorSets", offsetof(DeviceDispatchTable, FreeDescriptorSets)},
- {"vkFreeMemory", offsetof(DeviceDispatchTable, FreeMemory)},
- {"vkGetBufferMemoryRequirements", offsetof(DeviceDispatchTable, GetBufferMemoryRequirements)},
- {"vkGetDeviceMemoryCommitment", offsetof(DeviceDispatchTable, GetDeviceMemoryCommitment)},
- {"vkGetDeviceQueue", offsetof(DeviceDispatchTable, GetDeviceQueue)},
- {"vkGetEventStatus", offsetof(DeviceDispatchTable, GetEventStatus)},
- {"vkGetFenceStatus", offsetof(DeviceDispatchTable, GetFenceStatus)},
- {"vkGetImageMemoryRequirements", offsetof(DeviceDispatchTable, GetImageMemoryRequirements)},
- {"vkGetImageSparseMemoryRequirements", offsetof(DeviceDispatchTable, GetImageSparseMemoryRequirements)},
- {"vkGetImageSubresourceLayout", offsetof(DeviceDispatchTable, GetImageSubresourceLayout)},
- {"vkGetPipelineCacheData", offsetof(DeviceDispatchTable, GetPipelineCacheData)},
- {"vkGetQueryPoolResults", offsetof(DeviceDispatchTable, GetQueryPoolResults)},
- {"vkGetRenderAreaGranularity", offsetof(DeviceDispatchTable, GetRenderAreaGranularity)},
- {"vkGetSwapchainImagesKHR", offsetof(DeviceDispatchTable, GetSwapchainImagesKHR)},
- {"vkInvalidateMappedMemoryRanges", offsetof(DeviceDispatchTable, InvalidateMappedMemoryRanges)},
- {"vkMapMemory", offsetof(DeviceDispatchTable, MapMemory)},
- {"vkMergePipelineCaches", offsetof(DeviceDispatchTable, MergePipelineCaches)},
- {"vkQueueBindSparse", offsetof(DeviceDispatchTable, QueueBindSparse)},
- {"vkQueuePresentKHR", offsetof(DeviceDispatchTable, QueuePresentKHR)},
- {"vkQueueSubmit", offsetof(DeviceDispatchTable, QueueSubmit)},
- {"vkQueueWaitIdle", offsetof(DeviceDispatchTable, QueueWaitIdle)},
- {"vkResetCommandBuffer", offsetof(DeviceDispatchTable, ResetCommandBuffer)},
- {"vkResetCommandPool", offsetof(DeviceDispatchTable, ResetCommandPool)},
- {"vkResetDescriptorPool", offsetof(DeviceDispatchTable, ResetDescriptorPool)},
- {"vkResetEvent", offsetof(DeviceDispatchTable, ResetEvent)},
- {"vkResetFences", offsetof(DeviceDispatchTable, ResetFences)},
- {"vkSetEvent", offsetof(DeviceDispatchTable, SetEvent)},
- {"vkUnmapMemory", offsetof(DeviceDispatchTable, UnmapMemory)},
- {"vkUpdateDescriptorSets", offsetof(DeviceDispatchTable, UpdateDescriptorSets)},
- {"vkWaitForFences", offsetof(DeviceDispatchTable, WaitForFences)},
- // clang-format on
-};
-
-} // anonymous namespace
-
-namespace vulkan {
-
-PFN_vkVoidFunction GetLoaderExportProcAddr(const char* name) {
- return Lookup(name, kLoaderExportProcs);
-}
-
-PFN_vkVoidFunction GetLoaderGlobalProcAddr(const char* name) {
- return Lookup(name, kLoaderGlobalProcs);
-}
-
-PFN_vkVoidFunction GetLoaderTopProcAddr(const char* name) {
- return Lookup(name, kLoaderTopProcs);
-}
-
-PFN_vkVoidFunction GetLoaderBottomProcAddr(const char* name) {
- return Lookup(name, kLoaderBottomProcs);
-}
-
-PFN_vkVoidFunction GetDispatchProcAddr(const InstanceDispatchTable& dispatch,
- const char* name) {
- return Lookup(name, kInstanceDispatchOffsets, dispatch);
-}
-
-PFN_vkVoidFunction GetDispatchProcAddr(const DeviceDispatchTable& dispatch,
- const char* name) {
- return Lookup(name, kDeviceDispatchOffsets, dispatch);
-}
-
-bool LoadInstanceDispatchTable(VkInstance instance,
- PFN_vkGetInstanceProcAddr get_proc_addr,
- InstanceDispatchTable& dispatch) {
- bool success = true;
- // clang-format off
- dispatch.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(get_proc_addr(instance, "vkDestroyInstance"));
- if (UNLIKELY(!dispatch.DestroyInstance)) {
- ALOGE("missing instance proc: %s", "vkDestroyInstance");
- success = false;
- }
- dispatch.EnumeratePhysicalDevices = reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(get_proc_addr(instance, "vkEnumeratePhysicalDevices"));
- if (UNLIKELY(!dispatch.EnumeratePhysicalDevices)) {
- ALOGE("missing instance proc: %s", "vkEnumeratePhysicalDevices");
- success = false;
- }
- dispatch.GetPhysicalDeviceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceProperties)) {
- ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceQueueFamilyProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceQueueFamilyProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceQueueFamilyProperties)) {
- ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceQueueFamilyProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceMemoryProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceMemoryProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceMemoryProperties)) {
- ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceMemoryProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceFeatures = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures>(get_proc_addr(instance, "vkGetPhysicalDeviceFeatures"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceFeatures)) {
- ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceFeatures");
- success = false;
- }
- dispatch.GetPhysicalDeviceFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceFormatProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceFormatProperties)) {
- ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceFormatProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceImageFormatProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceImageFormatProperties)) {
- ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceImageFormatProperties");
- success = false;
- }
- dispatch.CreateDevice = reinterpret_cast<PFN_vkCreateDevice>(get_proc_addr(instance, "vkCreateDevice"));
- if (UNLIKELY(!dispatch.CreateDevice)) {
- ALOGE("missing instance proc: %s", "vkCreateDevice");
- success = false;
- }
- dispatch.EnumerateDeviceExtensionProperties = reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(get_proc_addr(instance, "vkEnumerateDeviceExtensionProperties"));
- if (UNLIKELY(!dispatch.EnumerateDeviceExtensionProperties)) {
- ALOGE("missing instance proc: %s", "vkEnumerateDeviceExtensionProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceSparseImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceSparseImageFormatProperties)) {
- ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceSparseImageFormatProperties");
- success = false;
- }
- dispatch.DestroySurfaceKHR = reinterpret_cast<PFN_vkDestroySurfaceKHR>(get_proc_addr(instance, "vkDestroySurfaceKHR"));
- if (UNLIKELY(!dispatch.DestroySurfaceKHR)) {
- ALOGE("missing instance proc: %s", "vkDestroySurfaceKHR");
- success = false;
- }
- dispatch.GetPhysicalDeviceSurfaceSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(get_proc_addr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceSurfaceSupportKHR)) {
- ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceSurfaceSupportKHR");
- success = false;
- }
- dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(get_proc_addr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR)) {
- ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
- success = false;
- }
- dispatch.GetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(get_proc_addr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceSurfaceFormatsKHR)) {
- ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceSurfaceFormatsKHR");
- success = false;
- }
- dispatch.GetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(get_proc_addr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceSurfacePresentModesKHR)) {
- ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceSurfacePresentModesKHR");
- success = false;
- }
- dispatch.CreateAndroidSurfaceKHR = reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>(get_proc_addr(instance, "vkCreateAndroidSurfaceKHR"));
- if (UNLIKELY(!dispatch.CreateAndroidSurfaceKHR)) {
- ALOGE("missing instance proc: %s", "vkCreateAndroidSurfaceKHR");
- success = false;
- }
- dispatch.CreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(get_proc_addr(instance, "vkCreateDebugReportCallbackEXT"));
- if (UNLIKELY(!dispatch.CreateDebugReportCallbackEXT)) {
- ALOGE("missing instance proc: %s", "vkCreateDebugReportCallbackEXT");
- success = false;
- }
- dispatch.DestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(get_proc_addr(instance, "vkDestroyDebugReportCallbackEXT"));
- if (UNLIKELY(!dispatch.DestroyDebugReportCallbackEXT)) {
- ALOGE("missing instance proc: %s", "vkDestroyDebugReportCallbackEXT");
- success = false;
- }
- dispatch.DebugReportMessageEXT = reinterpret_cast<PFN_vkDebugReportMessageEXT>(get_proc_addr(instance, "vkDebugReportMessageEXT"));
- if (UNLIKELY(!dispatch.DebugReportMessageEXT)) {
- ALOGE("missing instance proc: %s", "vkDebugReportMessageEXT");
- success = false;
- }
- // clang-format on
- return success;
-}
-
-bool LoadDeviceDispatchTable(VkDevice device,
- PFN_vkGetDeviceProcAddr get_proc_addr,
- DeviceDispatchTable& dispatch) {
- bool success = true;
- // clang-format off
- dispatch.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(get_proc_addr(device, "vkDestroyDevice"));
- if (UNLIKELY(!dispatch.DestroyDevice)) {
- ALOGE("missing device proc: %s", "vkDestroyDevice");
- success = false;
- }
- dispatch.GetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>(get_proc_addr(device, "vkGetDeviceQueue"));
- if (UNLIKELY(!dispatch.GetDeviceQueue)) {
- ALOGE("missing device proc: %s", "vkGetDeviceQueue");
- success = false;
- }
- dispatch.QueueSubmit = reinterpret_cast<PFN_vkQueueSubmit>(get_proc_addr(device, "vkQueueSubmit"));
- if (UNLIKELY(!dispatch.QueueSubmit)) {
- ALOGE("missing device proc: %s", "vkQueueSubmit");
- success = false;
- }
- dispatch.QueueWaitIdle = reinterpret_cast<PFN_vkQueueWaitIdle>(get_proc_addr(device, "vkQueueWaitIdle"));
- if (UNLIKELY(!dispatch.QueueWaitIdle)) {
- ALOGE("missing device proc: %s", "vkQueueWaitIdle");
- success = false;
- }
- dispatch.DeviceWaitIdle = reinterpret_cast<PFN_vkDeviceWaitIdle>(get_proc_addr(device, "vkDeviceWaitIdle"));
- if (UNLIKELY(!dispatch.DeviceWaitIdle)) {
- ALOGE("missing device proc: %s", "vkDeviceWaitIdle");
- success = false;
- }
- dispatch.AllocateMemory = reinterpret_cast<PFN_vkAllocateMemory>(get_proc_addr(device, "vkAllocateMemory"));
- if (UNLIKELY(!dispatch.AllocateMemory)) {
- ALOGE("missing device proc: %s", "vkAllocateMemory");
- success = false;
- }
- dispatch.FreeMemory = reinterpret_cast<PFN_vkFreeMemory>(get_proc_addr(device, "vkFreeMemory"));
- if (UNLIKELY(!dispatch.FreeMemory)) {
- ALOGE("missing device proc: %s", "vkFreeMemory");
- success = false;
- }
- dispatch.MapMemory = reinterpret_cast<PFN_vkMapMemory>(get_proc_addr(device, "vkMapMemory"));
- if (UNLIKELY(!dispatch.MapMemory)) {
- ALOGE("missing device proc: %s", "vkMapMemory");
- success = false;
- }
- dispatch.UnmapMemory = reinterpret_cast<PFN_vkUnmapMemory>(get_proc_addr(device, "vkUnmapMemory"));
- if (UNLIKELY(!dispatch.UnmapMemory)) {
- ALOGE("missing device proc: %s", "vkUnmapMemory");
- success = false;
- }
- dispatch.FlushMappedMemoryRanges = reinterpret_cast<PFN_vkFlushMappedMemoryRanges>(get_proc_addr(device, "vkFlushMappedMemoryRanges"));
- if (UNLIKELY(!dispatch.FlushMappedMemoryRanges)) {
- ALOGE("missing device proc: %s", "vkFlushMappedMemoryRanges");
- success = false;
- }
- dispatch.InvalidateMappedMemoryRanges = reinterpret_cast<PFN_vkInvalidateMappedMemoryRanges>(get_proc_addr(device, "vkInvalidateMappedMemoryRanges"));
- if (UNLIKELY(!dispatch.InvalidateMappedMemoryRanges)) {
- ALOGE("missing device proc: %s", "vkInvalidateMappedMemoryRanges");
- success = false;
- }
- dispatch.GetDeviceMemoryCommitment = reinterpret_cast<PFN_vkGetDeviceMemoryCommitment>(get_proc_addr(device, "vkGetDeviceMemoryCommitment"));
- if (UNLIKELY(!dispatch.GetDeviceMemoryCommitment)) {
- ALOGE("missing device proc: %s", "vkGetDeviceMemoryCommitment");
- success = false;
- }
- dispatch.GetBufferMemoryRequirements = reinterpret_cast<PFN_vkGetBufferMemoryRequirements>(get_proc_addr(device, "vkGetBufferMemoryRequirements"));
- if (UNLIKELY(!dispatch.GetBufferMemoryRequirements)) {
- ALOGE("missing device proc: %s", "vkGetBufferMemoryRequirements");
- success = false;
- }
- dispatch.BindBufferMemory = reinterpret_cast<PFN_vkBindBufferMemory>(get_proc_addr(device, "vkBindBufferMemory"));
- if (UNLIKELY(!dispatch.BindBufferMemory)) {
- ALOGE("missing device proc: %s", "vkBindBufferMemory");
- success = false;
- }
- dispatch.GetImageMemoryRequirements = reinterpret_cast<PFN_vkGetImageMemoryRequirements>(get_proc_addr(device, "vkGetImageMemoryRequirements"));
- if (UNLIKELY(!dispatch.GetImageMemoryRequirements)) {
- ALOGE("missing device proc: %s", "vkGetImageMemoryRequirements");
- success = false;
- }
- dispatch.BindImageMemory = reinterpret_cast<PFN_vkBindImageMemory>(get_proc_addr(device, "vkBindImageMemory"));
- if (UNLIKELY(!dispatch.BindImageMemory)) {
- ALOGE("missing device proc: %s", "vkBindImageMemory");
- success = false;
- }
- dispatch.GetImageSparseMemoryRequirements = reinterpret_cast<PFN_vkGetImageSparseMemoryRequirements>(get_proc_addr(device, "vkGetImageSparseMemoryRequirements"));
- if (UNLIKELY(!dispatch.GetImageSparseMemoryRequirements)) {
- ALOGE("missing device proc: %s", "vkGetImageSparseMemoryRequirements");
- success = false;
- }
- dispatch.QueueBindSparse = reinterpret_cast<PFN_vkQueueBindSparse>(get_proc_addr(device, "vkQueueBindSparse"));
- if (UNLIKELY(!dispatch.QueueBindSparse)) {
- ALOGE("missing device proc: %s", "vkQueueBindSparse");
- success = false;
- }
- dispatch.CreateFence = reinterpret_cast<PFN_vkCreateFence>(get_proc_addr(device, "vkCreateFence"));
- if (UNLIKELY(!dispatch.CreateFence)) {
- ALOGE("missing device proc: %s", "vkCreateFence");
- success = false;
- }
- dispatch.DestroyFence = reinterpret_cast<PFN_vkDestroyFence>(get_proc_addr(device, "vkDestroyFence"));
- if (UNLIKELY(!dispatch.DestroyFence)) {
- ALOGE("missing device proc: %s", "vkDestroyFence");
- success = false;
- }
- dispatch.ResetFences = reinterpret_cast<PFN_vkResetFences>(get_proc_addr(device, "vkResetFences"));
- if (UNLIKELY(!dispatch.ResetFences)) {
- ALOGE("missing device proc: %s", "vkResetFences");
- success = false;
- }
- dispatch.GetFenceStatus = reinterpret_cast<PFN_vkGetFenceStatus>(get_proc_addr(device, "vkGetFenceStatus"));
- if (UNLIKELY(!dispatch.GetFenceStatus)) {
- ALOGE("missing device proc: %s", "vkGetFenceStatus");
- success = false;
- }
- dispatch.WaitForFences = reinterpret_cast<PFN_vkWaitForFences>(get_proc_addr(device, "vkWaitForFences"));
- if (UNLIKELY(!dispatch.WaitForFences)) {
- ALOGE("missing device proc: %s", "vkWaitForFences");
- success = false;
- }
- dispatch.CreateSemaphore = reinterpret_cast<PFN_vkCreateSemaphore>(get_proc_addr(device, "vkCreateSemaphore"));
- if (UNLIKELY(!dispatch.CreateSemaphore)) {
- ALOGE("missing device proc: %s", "vkCreateSemaphore");
- success = false;
- }
- dispatch.DestroySemaphore = reinterpret_cast<PFN_vkDestroySemaphore>(get_proc_addr(device, "vkDestroySemaphore"));
- if (UNLIKELY(!dispatch.DestroySemaphore)) {
- ALOGE("missing device proc: %s", "vkDestroySemaphore");
- success = false;
- }
- dispatch.CreateEvent = reinterpret_cast<PFN_vkCreateEvent>(get_proc_addr(device, "vkCreateEvent"));
- if (UNLIKELY(!dispatch.CreateEvent)) {
- ALOGE("missing device proc: %s", "vkCreateEvent");
- success = false;
- }
- dispatch.DestroyEvent = reinterpret_cast<PFN_vkDestroyEvent>(get_proc_addr(device, "vkDestroyEvent"));
- if (UNLIKELY(!dispatch.DestroyEvent)) {
- ALOGE("missing device proc: %s", "vkDestroyEvent");
- success = false;
- }
- dispatch.GetEventStatus = reinterpret_cast<PFN_vkGetEventStatus>(get_proc_addr(device, "vkGetEventStatus"));
- if (UNLIKELY(!dispatch.GetEventStatus)) {
- ALOGE("missing device proc: %s", "vkGetEventStatus");
- success = false;
- }
- dispatch.SetEvent = reinterpret_cast<PFN_vkSetEvent>(get_proc_addr(device, "vkSetEvent"));
- if (UNLIKELY(!dispatch.SetEvent)) {
- ALOGE("missing device proc: %s", "vkSetEvent");
- success = false;
- }
- dispatch.ResetEvent = reinterpret_cast<PFN_vkResetEvent>(get_proc_addr(device, "vkResetEvent"));
- if (UNLIKELY(!dispatch.ResetEvent)) {
- ALOGE("missing device proc: %s", "vkResetEvent");
- success = false;
- }
- dispatch.CreateQueryPool = reinterpret_cast<PFN_vkCreateQueryPool>(get_proc_addr(device, "vkCreateQueryPool"));
- if (UNLIKELY(!dispatch.CreateQueryPool)) {
- ALOGE("missing device proc: %s", "vkCreateQueryPool");
- success = false;
- }
- dispatch.DestroyQueryPool = reinterpret_cast<PFN_vkDestroyQueryPool>(get_proc_addr(device, "vkDestroyQueryPool"));
- if (UNLIKELY(!dispatch.DestroyQueryPool)) {
- ALOGE("missing device proc: %s", "vkDestroyQueryPool");
- success = false;
- }
- dispatch.GetQueryPoolResults = reinterpret_cast<PFN_vkGetQueryPoolResults>(get_proc_addr(device, "vkGetQueryPoolResults"));
- if (UNLIKELY(!dispatch.GetQueryPoolResults)) {
- ALOGE("missing device proc: %s", "vkGetQueryPoolResults");
- success = false;
- }
- dispatch.CreateBuffer = reinterpret_cast<PFN_vkCreateBuffer>(get_proc_addr(device, "vkCreateBuffer"));
- if (UNLIKELY(!dispatch.CreateBuffer)) {
- ALOGE("missing device proc: %s", "vkCreateBuffer");
- success = false;
- }
- dispatch.DestroyBuffer = reinterpret_cast<PFN_vkDestroyBuffer>(get_proc_addr(device, "vkDestroyBuffer"));
- if (UNLIKELY(!dispatch.DestroyBuffer)) {
- ALOGE("missing device proc: %s", "vkDestroyBuffer");
- success = false;
- }
- dispatch.CreateBufferView = reinterpret_cast<PFN_vkCreateBufferView>(get_proc_addr(device, "vkCreateBufferView"));
- if (UNLIKELY(!dispatch.CreateBufferView)) {
- ALOGE("missing device proc: %s", "vkCreateBufferView");
- success = false;
- }
- dispatch.DestroyBufferView = reinterpret_cast<PFN_vkDestroyBufferView>(get_proc_addr(device, "vkDestroyBufferView"));
- if (UNLIKELY(!dispatch.DestroyBufferView)) {
- ALOGE("missing device proc: %s", "vkDestroyBufferView");
- success = false;
- }
- dispatch.CreateImage = reinterpret_cast<PFN_vkCreateImage>(get_proc_addr(device, "vkCreateImage"));
- if (UNLIKELY(!dispatch.CreateImage)) {
- ALOGE("missing device proc: %s", "vkCreateImage");
- success = false;
- }
- dispatch.DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(get_proc_addr(device, "vkDestroyImage"));
- if (UNLIKELY(!dispatch.DestroyImage)) {
- ALOGE("missing device proc: %s", "vkDestroyImage");
- success = false;
- }
- dispatch.GetImageSubresourceLayout = reinterpret_cast<PFN_vkGetImageSubresourceLayout>(get_proc_addr(device, "vkGetImageSubresourceLayout"));
- if (UNLIKELY(!dispatch.GetImageSubresourceLayout)) {
- ALOGE("missing device proc: %s", "vkGetImageSubresourceLayout");
- success = false;
- }
- dispatch.CreateImageView = reinterpret_cast<PFN_vkCreateImageView>(get_proc_addr(device, "vkCreateImageView"));
- if (UNLIKELY(!dispatch.CreateImageView)) {
- ALOGE("missing device proc: %s", "vkCreateImageView");
- success = false;
- }
- dispatch.DestroyImageView = reinterpret_cast<PFN_vkDestroyImageView>(get_proc_addr(device, "vkDestroyImageView"));
- if (UNLIKELY(!dispatch.DestroyImageView)) {
- ALOGE("missing device proc: %s", "vkDestroyImageView");
- success = false;
- }
- dispatch.CreateShaderModule = reinterpret_cast<PFN_vkCreateShaderModule>(get_proc_addr(device, "vkCreateShaderModule"));
- if (UNLIKELY(!dispatch.CreateShaderModule)) {
- ALOGE("missing device proc: %s", "vkCreateShaderModule");
- success = false;
- }
- dispatch.DestroyShaderModule = reinterpret_cast<PFN_vkDestroyShaderModule>(get_proc_addr(device, "vkDestroyShaderModule"));
- if (UNLIKELY(!dispatch.DestroyShaderModule)) {
- ALOGE("missing device proc: %s", "vkDestroyShaderModule");
- success = false;
- }
- dispatch.CreatePipelineCache = reinterpret_cast<PFN_vkCreatePipelineCache>(get_proc_addr(device, "vkCreatePipelineCache"));
- if (UNLIKELY(!dispatch.CreatePipelineCache)) {
- ALOGE("missing device proc: %s", "vkCreatePipelineCache");
- success = false;
- }
- dispatch.DestroyPipelineCache = reinterpret_cast<PFN_vkDestroyPipelineCache>(get_proc_addr(device, "vkDestroyPipelineCache"));
- if (UNLIKELY(!dispatch.DestroyPipelineCache)) {
- ALOGE("missing device proc: %s", "vkDestroyPipelineCache");
- success = false;
- }
- dispatch.GetPipelineCacheData = reinterpret_cast<PFN_vkGetPipelineCacheData>(get_proc_addr(device, "vkGetPipelineCacheData"));
- if (UNLIKELY(!dispatch.GetPipelineCacheData)) {
- ALOGE("missing device proc: %s", "vkGetPipelineCacheData");
- success = false;
- }
- dispatch.MergePipelineCaches = reinterpret_cast<PFN_vkMergePipelineCaches>(get_proc_addr(device, "vkMergePipelineCaches"));
- if (UNLIKELY(!dispatch.MergePipelineCaches)) {
- ALOGE("missing device proc: %s", "vkMergePipelineCaches");
- success = false;
- }
- dispatch.CreateGraphicsPipelines = reinterpret_cast<PFN_vkCreateGraphicsPipelines>(get_proc_addr(device, "vkCreateGraphicsPipelines"));
- if (UNLIKELY(!dispatch.CreateGraphicsPipelines)) {
- ALOGE("missing device proc: %s", "vkCreateGraphicsPipelines");
- success = false;
- }
- dispatch.CreateComputePipelines = reinterpret_cast<PFN_vkCreateComputePipelines>(get_proc_addr(device, "vkCreateComputePipelines"));
- if (UNLIKELY(!dispatch.CreateComputePipelines)) {
- ALOGE("missing device proc: %s", "vkCreateComputePipelines");
- success = false;
- }
- dispatch.DestroyPipeline = reinterpret_cast<PFN_vkDestroyPipeline>(get_proc_addr(device, "vkDestroyPipeline"));
- if (UNLIKELY(!dispatch.DestroyPipeline)) {
- ALOGE("missing device proc: %s", "vkDestroyPipeline");
- success = false;
- }
- dispatch.CreatePipelineLayout = reinterpret_cast<PFN_vkCreatePipelineLayout>(get_proc_addr(device, "vkCreatePipelineLayout"));
- if (UNLIKELY(!dispatch.CreatePipelineLayout)) {
- ALOGE("missing device proc: %s", "vkCreatePipelineLayout");
- success = false;
- }
- dispatch.DestroyPipelineLayout = reinterpret_cast<PFN_vkDestroyPipelineLayout>(get_proc_addr(device, "vkDestroyPipelineLayout"));
- if (UNLIKELY(!dispatch.DestroyPipelineLayout)) {
- ALOGE("missing device proc: %s", "vkDestroyPipelineLayout");
- success = false;
- }
- dispatch.CreateSampler = reinterpret_cast<PFN_vkCreateSampler>(get_proc_addr(device, "vkCreateSampler"));
- if (UNLIKELY(!dispatch.CreateSampler)) {
- ALOGE("missing device proc: %s", "vkCreateSampler");
- success = false;
- }
- dispatch.DestroySampler = reinterpret_cast<PFN_vkDestroySampler>(get_proc_addr(device, "vkDestroySampler"));
- if (UNLIKELY(!dispatch.DestroySampler)) {
- ALOGE("missing device proc: %s", "vkDestroySampler");
- success = false;
- }
- dispatch.CreateDescriptorSetLayout = reinterpret_cast<PFN_vkCreateDescriptorSetLayout>(get_proc_addr(device, "vkCreateDescriptorSetLayout"));
- if (UNLIKELY(!dispatch.CreateDescriptorSetLayout)) {
- ALOGE("missing device proc: %s", "vkCreateDescriptorSetLayout");
- success = false;
- }
- dispatch.DestroyDescriptorSetLayout = reinterpret_cast<PFN_vkDestroyDescriptorSetLayout>(get_proc_addr(device, "vkDestroyDescriptorSetLayout"));
- if (UNLIKELY(!dispatch.DestroyDescriptorSetLayout)) {
- ALOGE("missing device proc: %s", "vkDestroyDescriptorSetLayout");
- success = false;
- }
- dispatch.CreateDescriptorPool = reinterpret_cast<PFN_vkCreateDescriptorPool>(get_proc_addr(device, "vkCreateDescriptorPool"));
- if (UNLIKELY(!dispatch.CreateDescriptorPool)) {
- ALOGE("missing device proc: %s", "vkCreateDescriptorPool");
- success = false;
- }
- dispatch.DestroyDescriptorPool = reinterpret_cast<PFN_vkDestroyDescriptorPool>(get_proc_addr(device, "vkDestroyDescriptorPool"));
- if (UNLIKELY(!dispatch.DestroyDescriptorPool)) {
- ALOGE("missing device proc: %s", "vkDestroyDescriptorPool");
- success = false;
- }
- dispatch.ResetDescriptorPool = reinterpret_cast<PFN_vkResetDescriptorPool>(get_proc_addr(device, "vkResetDescriptorPool"));
- if (UNLIKELY(!dispatch.ResetDescriptorPool)) {
- ALOGE("missing device proc: %s", "vkResetDescriptorPool");
- success = false;
- }
- dispatch.AllocateDescriptorSets = reinterpret_cast<PFN_vkAllocateDescriptorSets>(get_proc_addr(device, "vkAllocateDescriptorSets"));
- if (UNLIKELY(!dispatch.AllocateDescriptorSets)) {
- ALOGE("missing device proc: %s", "vkAllocateDescriptorSets");
- success = false;
- }
- dispatch.FreeDescriptorSets = reinterpret_cast<PFN_vkFreeDescriptorSets>(get_proc_addr(device, "vkFreeDescriptorSets"));
- if (UNLIKELY(!dispatch.FreeDescriptorSets)) {
- ALOGE("missing device proc: %s", "vkFreeDescriptorSets");
- success = false;
- }
- dispatch.UpdateDescriptorSets = reinterpret_cast<PFN_vkUpdateDescriptorSets>(get_proc_addr(device, "vkUpdateDescriptorSets"));
- if (UNLIKELY(!dispatch.UpdateDescriptorSets)) {
- ALOGE("missing device proc: %s", "vkUpdateDescriptorSets");
- success = false;
- }
- dispatch.CreateFramebuffer = reinterpret_cast<PFN_vkCreateFramebuffer>(get_proc_addr(device, "vkCreateFramebuffer"));
- if (UNLIKELY(!dispatch.CreateFramebuffer)) {
- ALOGE("missing device proc: %s", "vkCreateFramebuffer");
- success = false;
- }
- dispatch.DestroyFramebuffer = reinterpret_cast<PFN_vkDestroyFramebuffer>(get_proc_addr(device, "vkDestroyFramebuffer"));
- if (UNLIKELY(!dispatch.DestroyFramebuffer)) {
- ALOGE("missing device proc: %s", "vkDestroyFramebuffer");
- success = false;
- }
- dispatch.CreateRenderPass = reinterpret_cast<PFN_vkCreateRenderPass>(get_proc_addr(device, "vkCreateRenderPass"));
- if (UNLIKELY(!dispatch.CreateRenderPass)) {
- ALOGE("missing device proc: %s", "vkCreateRenderPass");
- success = false;
- }
- dispatch.DestroyRenderPass = reinterpret_cast<PFN_vkDestroyRenderPass>(get_proc_addr(device, "vkDestroyRenderPass"));
- if (UNLIKELY(!dispatch.DestroyRenderPass)) {
- ALOGE("missing device proc: %s", "vkDestroyRenderPass");
- success = false;
- }
- dispatch.GetRenderAreaGranularity = reinterpret_cast<PFN_vkGetRenderAreaGranularity>(get_proc_addr(device, "vkGetRenderAreaGranularity"));
- if (UNLIKELY(!dispatch.GetRenderAreaGranularity)) {
- ALOGE("missing device proc: %s", "vkGetRenderAreaGranularity");
- success = false;
- }
- dispatch.CreateCommandPool = reinterpret_cast<PFN_vkCreateCommandPool>(get_proc_addr(device, "vkCreateCommandPool"));
- if (UNLIKELY(!dispatch.CreateCommandPool)) {
- ALOGE("missing device proc: %s", "vkCreateCommandPool");
- success = false;
- }
- dispatch.DestroyCommandPool = reinterpret_cast<PFN_vkDestroyCommandPool>(get_proc_addr(device, "vkDestroyCommandPool"));
- if (UNLIKELY(!dispatch.DestroyCommandPool)) {
- ALOGE("missing device proc: %s", "vkDestroyCommandPool");
- success = false;
- }
- dispatch.ResetCommandPool = reinterpret_cast<PFN_vkResetCommandPool>(get_proc_addr(device, "vkResetCommandPool"));
- if (UNLIKELY(!dispatch.ResetCommandPool)) {
- ALOGE("missing device proc: %s", "vkResetCommandPool");
- success = false;
- }
- dispatch.AllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>(get_proc_addr(device, "vkAllocateCommandBuffers"));
- if (UNLIKELY(!dispatch.AllocateCommandBuffers)) {
- ALOGE("missing device proc: %s", "vkAllocateCommandBuffers");
- success = false;
- }
- dispatch.FreeCommandBuffers = reinterpret_cast<PFN_vkFreeCommandBuffers>(get_proc_addr(device, "vkFreeCommandBuffers"));
- if (UNLIKELY(!dispatch.FreeCommandBuffers)) {
- ALOGE("missing device proc: %s", "vkFreeCommandBuffers");
- success = false;
- }
- dispatch.BeginCommandBuffer = reinterpret_cast<PFN_vkBeginCommandBuffer>(get_proc_addr(device, "vkBeginCommandBuffer"));
- if (UNLIKELY(!dispatch.BeginCommandBuffer)) {
- ALOGE("missing device proc: %s", "vkBeginCommandBuffer");
- success = false;
- }
- dispatch.EndCommandBuffer = reinterpret_cast<PFN_vkEndCommandBuffer>(get_proc_addr(device, "vkEndCommandBuffer"));
- if (UNLIKELY(!dispatch.EndCommandBuffer)) {
- ALOGE("missing device proc: %s", "vkEndCommandBuffer");
- success = false;
- }
- dispatch.ResetCommandBuffer = reinterpret_cast<PFN_vkResetCommandBuffer>(get_proc_addr(device, "vkResetCommandBuffer"));
- if (UNLIKELY(!dispatch.ResetCommandBuffer)) {
- ALOGE("missing device proc: %s", "vkResetCommandBuffer");
- success = false;
- }
- dispatch.CmdBindPipeline = reinterpret_cast<PFN_vkCmdBindPipeline>(get_proc_addr(device, "vkCmdBindPipeline"));
- if (UNLIKELY(!dispatch.CmdBindPipeline)) {
- ALOGE("missing device proc: %s", "vkCmdBindPipeline");
- success = false;
- }
- dispatch.CmdSetViewport = reinterpret_cast<PFN_vkCmdSetViewport>(get_proc_addr(device, "vkCmdSetViewport"));
- if (UNLIKELY(!dispatch.CmdSetViewport)) {
- ALOGE("missing device proc: %s", "vkCmdSetViewport");
- success = false;
- }
- dispatch.CmdSetScissor = reinterpret_cast<PFN_vkCmdSetScissor>(get_proc_addr(device, "vkCmdSetScissor"));
- if (UNLIKELY(!dispatch.CmdSetScissor)) {
- ALOGE("missing device proc: %s", "vkCmdSetScissor");
- success = false;
- }
- dispatch.CmdSetLineWidth = reinterpret_cast<PFN_vkCmdSetLineWidth>(get_proc_addr(device, "vkCmdSetLineWidth"));
- if (UNLIKELY(!dispatch.CmdSetLineWidth)) {
- ALOGE("missing device proc: %s", "vkCmdSetLineWidth");
- success = false;
- }
- dispatch.CmdSetDepthBias = reinterpret_cast<PFN_vkCmdSetDepthBias>(get_proc_addr(device, "vkCmdSetDepthBias"));
- if (UNLIKELY(!dispatch.CmdSetDepthBias)) {
- ALOGE("missing device proc: %s", "vkCmdSetDepthBias");
- success = false;
- }
- dispatch.CmdSetBlendConstants = reinterpret_cast<PFN_vkCmdSetBlendConstants>(get_proc_addr(device, "vkCmdSetBlendConstants"));
- if (UNLIKELY(!dispatch.CmdSetBlendConstants)) {
- ALOGE("missing device proc: %s", "vkCmdSetBlendConstants");
- success = false;
- }
- dispatch.CmdSetDepthBounds = reinterpret_cast<PFN_vkCmdSetDepthBounds>(get_proc_addr(device, "vkCmdSetDepthBounds"));
- if (UNLIKELY(!dispatch.CmdSetDepthBounds)) {
- ALOGE("missing device proc: %s", "vkCmdSetDepthBounds");
- success = false;
- }
- dispatch.CmdSetStencilCompareMask = reinterpret_cast<PFN_vkCmdSetStencilCompareMask>(get_proc_addr(device, "vkCmdSetStencilCompareMask"));
- if (UNLIKELY(!dispatch.CmdSetStencilCompareMask)) {
- ALOGE("missing device proc: %s", "vkCmdSetStencilCompareMask");
- success = false;
- }
- dispatch.CmdSetStencilWriteMask = reinterpret_cast<PFN_vkCmdSetStencilWriteMask>(get_proc_addr(device, "vkCmdSetStencilWriteMask"));
- if (UNLIKELY(!dispatch.CmdSetStencilWriteMask)) {
- ALOGE("missing device proc: %s", "vkCmdSetStencilWriteMask");
- success = false;
- }
- dispatch.CmdSetStencilReference = reinterpret_cast<PFN_vkCmdSetStencilReference>(get_proc_addr(device, "vkCmdSetStencilReference"));
- if (UNLIKELY(!dispatch.CmdSetStencilReference)) {
- ALOGE("missing device proc: %s", "vkCmdSetStencilReference");
- success = false;
- }
- dispatch.CmdBindDescriptorSets = reinterpret_cast<PFN_vkCmdBindDescriptorSets>(get_proc_addr(device, "vkCmdBindDescriptorSets"));
- if (UNLIKELY(!dispatch.CmdBindDescriptorSets)) {
- ALOGE("missing device proc: %s", "vkCmdBindDescriptorSets");
- success = false;
- }
- dispatch.CmdBindIndexBuffer = reinterpret_cast<PFN_vkCmdBindIndexBuffer>(get_proc_addr(device, "vkCmdBindIndexBuffer"));
- if (UNLIKELY(!dispatch.CmdBindIndexBuffer)) {
- ALOGE("missing device proc: %s", "vkCmdBindIndexBuffer");
- success = false;
- }
- dispatch.CmdBindVertexBuffers = reinterpret_cast<PFN_vkCmdBindVertexBuffers>(get_proc_addr(device, "vkCmdBindVertexBuffers"));
- if (UNLIKELY(!dispatch.CmdBindVertexBuffers)) {
- ALOGE("missing device proc: %s", "vkCmdBindVertexBuffers");
- success = false;
- }
- dispatch.CmdDraw = reinterpret_cast<PFN_vkCmdDraw>(get_proc_addr(device, "vkCmdDraw"));
- if (UNLIKELY(!dispatch.CmdDraw)) {
- ALOGE("missing device proc: %s", "vkCmdDraw");
- success = false;
- }
- dispatch.CmdDrawIndexed = reinterpret_cast<PFN_vkCmdDrawIndexed>(get_proc_addr(device, "vkCmdDrawIndexed"));
- if (UNLIKELY(!dispatch.CmdDrawIndexed)) {
- ALOGE("missing device proc: %s", "vkCmdDrawIndexed");
- success = false;
- }
- dispatch.CmdDrawIndirect = reinterpret_cast<PFN_vkCmdDrawIndirect>(get_proc_addr(device, "vkCmdDrawIndirect"));
- if (UNLIKELY(!dispatch.CmdDrawIndirect)) {
- ALOGE("missing device proc: %s", "vkCmdDrawIndirect");
- success = false;
- }
- dispatch.CmdDrawIndexedIndirect = reinterpret_cast<PFN_vkCmdDrawIndexedIndirect>(get_proc_addr(device, "vkCmdDrawIndexedIndirect"));
- if (UNLIKELY(!dispatch.CmdDrawIndexedIndirect)) {
- ALOGE("missing device proc: %s", "vkCmdDrawIndexedIndirect");
- success = false;
- }
- dispatch.CmdDispatch = reinterpret_cast<PFN_vkCmdDispatch>(get_proc_addr(device, "vkCmdDispatch"));
- if (UNLIKELY(!dispatch.CmdDispatch)) {
- ALOGE("missing device proc: %s", "vkCmdDispatch");
- success = false;
- }
- dispatch.CmdDispatchIndirect = reinterpret_cast<PFN_vkCmdDispatchIndirect>(get_proc_addr(device, "vkCmdDispatchIndirect"));
- if (UNLIKELY(!dispatch.CmdDispatchIndirect)) {
- ALOGE("missing device proc: %s", "vkCmdDispatchIndirect");
- success = false;
- }
- dispatch.CmdCopyBuffer = reinterpret_cast<PFN_vkCmdCopyBuffer>(get_proc_addr(device, "vkCmdCopyBuffer"));
- if (UNLIKELY(!dispatch.CmdCopyBuffer)) {
- ALOGE("missing device proc: %s", "vkCmdCopyBuffer");
- success = false;
- }
- dispatch.CmdCopyImage = reinterpret_cast<PFN_vkCmdCopyImage>(get_proc_addr(device, "vkCmdCopyImage"));
- if (UNLIKELY(!dispatch.CmdCopyImage)) {
- ALOGE("missing device proc: %s", "vkCmdCopyImage");
- success = false;
- }
- dispatch.CmdBlitImage = reinterpret_cast<PFN_vkCmdBlitImage>(get_proc_addr(device, "vkCmdBlitImage"));
- if (UNLIKELY(!dispatch.CmdBlitImage)) {
- ALOGE("missing device proc: %s", "vkCmdBlitImage");
- success = false;
- }
- dispatch.CmdCopyBufferToImage = reinterpret_cast<PFN_vkCmdCopyBufferToImage>(get_proc_addr(device, "vkCmdCopyBufferToImage"));
- if (UNLIKELY(!dispatch.CmdCopyBufferToImage)) {
- ALOGE("missing device proc: %s", "vkCmdCopyBufferToImage");
- success = false;
- }
- dispatch.CmdCopyImageToBuffer = reinterpret_cast<PFN_vkCmdCopyImageToBuffer>(get_proc_addr(device, "vkCmdCopyImageToBuffer"));
- if (UNLIKELY(!dispatch.CmdCopyImageToBuffer)) {
- ALOGE("missing device proc: %s", "vkCmdCopyImageToBuffer");
- success = false;
- }
- dispatch.CmdUpdateBuffer = reinterpret_cast<PFN_vkCmdUpdateBuffer>(get_proc_addr(device, "vkCmdUpdateBuffer"));
- if (UNLIKELY(!dispatch.CmdUpdateBuffer)) {
- ALOGE("missing device proc: %s", "vkCmdUpdateBuffer");
- success = false;
- }
- dispatch.CmdFillBuffer = reinterpret_cast<PFN_vkCmdFillBuffer>(get_proc_addr(device, "vkCmdFillBuffer"));
- if (UNLIKELY(!dispatch.CmdFillBuffer)) {
- ALOGE("missing device proc: %s", "vkCmdFillBuffer");
- success = false;
- }
- dispatch.CmdClearColorImage = reinterpret_cast<PFN_vkCmdClearColorImage>(get_proc_addr(device, "vkCmdClearColorImage"));
- if (UNLIKELY(!dispatch.CmdClearColorImage)) {
- ALOGE("missing device proc: %s", "vkCmdClearColorImage");
- success = false;
- }
- dispatch.CmdClearDepthStencilImage = reinterpret_cast<PFN_vkCmdClearDepthStencilImage>(get_proc_addr(device, "vkCmdClearDepthStencilImage"));
- if (UNLIKELY(!dispatch.CmdClearDepthStencilImage)) {
- ALOGE("missing device proc: %s", "vkCmdClearDepthStencilImage");
- success = false;
- }
- dispatch.CmdClearAttachments = reinterpret_cast<PFN_vkCmdClearAttachments>(get_proc_addr(device, "vkCmdClearAttachments"));
- if (UNLIKELY(!dispatch.CmdClearAttachments)) {
- ALOGE("missing device proc: %s", "vkCmdClearAttachments");
- success = false;
- }
- dispatch.CmdResolveImage = reinterpret_cast<PFN_vkCmdResolveImage>(get_proc_addr(device, "vkCmdResolveImage"));
- if (UNLIKELY(!dispatch.CmdResolveImage)) {
- ALOGE("missing device proc: %s", "vkCmdResolveImage");
- success = false;
- }
- dispatch.CmdSetEvent = reinterpret_cast<PFN_vkCmdSetEvent>(get_proc_addr(device, "vkCmdSetEvent"));
- if (UNLIKELY(!dispatch.CmdSetEvent)) {
- ALOGE("missing device proc: %s", "vkCmdSetEvent");
- success = false;
- }
- dispatch.CmdResetEvent = reinterpret_cast<PFN_vkCmdResetEvent>(get_proc_addr(device, "vkCmdResetEvent"));
- if (UNLIKELY(!dispatch.CmdResetEvent)) {
- ALOGE("missing device proc: %s", "vkCmdResetEvent");
- success = false;
- }
- dispatch.CmdWaitEvents = reinterpret_cast<PFN_vkCmdWaitEvents>(get_proc_addr(device, "vkCmdWaitEvents"));
- if (UNLIKELY(!dispatch.CmdWaitEvents)) {
- ALOGE("missing device proc: %s", "vkCmdWaitEvents");
- success = false;
- }
- dispatch.CmdPipelineBarrier = reinterpret_cast<PFN_vkCmdPipelineBarrier>(get_proc_addr(device, "vkCmdPipelineBarrier"));
- if (UNLIKELY(!dispatch.CmdPipelineBarrier)) {
- ALOGE("missing device proc: %s", "vkCmdPipelineBarrier");
- success = false;
- }
- dispatch.CmdBeginQuery = reinterpret_cast<PFN_vkCmdBeginQuery>(get_proc_addr(device, "vkCmdBeginQuery"));
- if (UNLIKELY(!dispatch.CmdBeginQuery)) {
- ALOGE("missing device proc: %s", "vkCmdBeginQuery");
- success = false;
- }
- dispatch.CmdEndQuery = reinterpret_cast<PFN_vkCmdEndQuery>(get_proc_addr(device, "vkCmdEndQuery"));
- if (UNLIKELY(!dispatch.CmdEndQuery)) {
- ALOGE("missing device proc: %s", "vkCmdEndQuery");
- success = false;
- }
- dispatch.CmdResetQueryPool = reinterpret_cast<PFN_vkCmdResetQueryPool>(get_proc_addr(device, "vkCmdResetQueryPool"));
- if (UNLIKELY(!dispatch.CmdResetQueryPool)) {
- ALOGE("missing device proc: %s", "vkCmdResetQueryPool");
- success = false;
- }
- dispatch.CmdWriteTimestamp = reinterpret_cast<PFN_vkCmdWriteTimestamp>(get_proc_addr(device, "vkCmdWriteTimestamp"));
- if (UNLIKELY(!dispatch.CmdWriteTimestamp)) {
- ALOGE("missing device proc: %s", "vkCmdWriteTimestamp");
- success = false;
- }
- dispatch.CmdCopyQueryPoolResults = reinterpret_cast<PFN_vkCmdCopyQueryPoolResults>(get_proc_addr(device, "vkCmdCopyQueryPoolResults"));
- if (UNLIKELY(!dispatch.CmdCopyQueryPoolResults)) {
- ALOGE("missing device proc: %s", "vkCmdCopyQueryPoolResults");
- success = false;
- }
- dispatch.CmdPushConstants = reinterpret_cast<PFN_vkCmdPushConstants>(get_proc_addr(device, "vkCmdPushConstants"));
- if (UNLIKELY(!dispatch.CmdPushConstants)) {
- ALOGE("missing device proc: %s", "vkCmdPushConstants");
- success = false;
- }
- dispatch.CmdBeginRenderPass = reinterpret_cast<PFN_vkCmdBeginRenderPass>(get_proc_addr(device, "vkCmdBeginRenderPass"));
- if (UNLIKELY(!dispatch.CmdBeginRenderPass)) {
- ALOGE("missing device proc: %s", "vkCmdBeginRenderPass");
- success = false;
- }
- dispatch.CmdNextSubpass = reinterpret_cast<PFN_vkCmdNextSubpass>(get_proc_addr(device, "vkCmdNextSubpass"));
- if (UNLIKELY(!dispatch.CmdNextSubpass)) {
- ALOGE("missing device proc: %s", "vkCmdNextSubpass");
- success = false;
- }
- dispatch.CmdEndRenderPass = reinterpret_cast<PFN_vkCmdEndRenderPass>(get_proc_addr(device, "vkCmdEndRenderPass"));
- if (UNLIKELY(!dispatch.CmdEndRenderPass)) {
- ALOGE("missing device proc: %s", "vkCmdEndRenderPass");
- success = false;
- }
- dispatch.CmdExecuteCommands = reinterpret_cast<PFN_vkCmdExecuteCommands>(get_proc_addr(device, "vkCmdExecuteCommands"));
- if (UNLIKELY(!dispatch.CmdExecuteCommands)) {
- ALOGE("missing device proc: %s", "vkCmdExecuteCommands");
- success = false;
- }
- dispatch.CreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(get_proc_addr(device, "vkCreateSwapchainKHR"));
- if (UNLIKELY(!dispatch.CreateSwapchainKHR)) {
- ALOGE("missing device proc: %s", "vkCreateSwapchainKHR");
- success = false;
- }
- dispatch.DestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(get_proc_addr(device, "vkDestroySwapchainKHR"));
- if (UNLIKELY(!dispatch.DestroySwapchainKHR)) {
- ALOGE("missing device proc: %s", "vkDestroySwapchainKHR");
- success = false;
- }
- dispatch.GetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(get_proc_addr(device, "vkGetSwapchainImagesKHR"));
- if (UNLIKELY(!dispatch.GetSwapchainImagesKHR)) {
- ALOGE("missing device proc: %s", "vkGetSwapchainImagesKHR");
- success = false;
- }
- dispatch.AcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(get_proc_addr(device, "vkAcquireNextImageKHR"));
- if (UNLIKELY(!dispatch.AcquireNextImageKHR)) {
- ALOGE("missing device proc: %s", "vkAcquireNextImageKHR");
- success = false;
- }
- dispatch.QueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(get_proc_addr(device, "vkQueuePresentKHR"));
- if (UNLIKELY(!dispatch.QueuePresentKHR)) {
- ALOGE("missing device proc: %s", "vkQueuePresentKHR");
- success = false;
- }
- // clang-format on
- return success;
-}
-
-bool LoadDriverDispatchTable(VkInstance instance,
- PFN_vkGetInstanceProcAddr get_proc_addr,
- const InstanceExtensionSet& extensions,
- DriverDispatchTable& dispatch) {
- bool success = true;
- // clang-format off
- dispatch.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(get_proc_addr(instance, "vkDestroyInstance"));
- if (UNLIKELY(!dispatch.DestroyInstance)) {
- ALOGE("missing driver proc: %s", "vkDestroyInstance");
- success = false;
- }
- dispatch.EnumeratePhysicalDevices = reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(get_proc_addr(instance, "vkEnumeratePhysicalDevices"));
- if (UNLIKELY(!dispatch.EnumeratePhysicalDevices)) {
- ALOGE("missing driver proc: %s", "vkEnumeratePhysicalDevices");
- success = false;
- }
- dispatch.GetPhysicalDeviceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceQueueFamilyProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceQueueFamilyProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceQueueFamilyProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceQueueFamilyProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceMemoryProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceMemoryProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceMemoryProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceMemoryProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceFeatures = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures>(get_proc_addr(instance, "vkGetPhysicalDeviceFeatures"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceFeatures)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceFeatures");
- success = false;
- }
- dispatch.GetPhysicalDeviceFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceFormatProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceFormatProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceFormatProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceImageFormatProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceImageFormatProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceImageFormatProperties");
- success = false;
- }
- dispatch.CreateDevice = reinterpret_cast<PFN_vkCreateDevice>(get_proc_addr(instance, "vkCreateDevice"));
- if (UNLIKELY(!dispatch.CreateDevice)) {
- ALOGE("missing driver proc: %s", "vkCreateDevice");
- success = false;
- }
- dispatch.EnumerateDeviceExtensionProperties = reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(get_proc_addr(instance, "vkEnumerateDeviceExtensionProperties"));
- if (UNLIKELY(!dispatch.EnumerateDeviceExtensionProperties)) {
- ALOGE("missing driver proc: %s", "vkEnumerateDeviceExtensionProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceSparseImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceSparseImageFormatProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceSparseImageFormatProperties");
- success = false;
- }
- if (extensions[kEXT_debug_report]) {
- dispatch.CreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(get_proc_addr(instance, "vkCreateDebugReportCallbackEXT"));
- if (UNLIKELY(!dispatch.CreateDebugReportCallbackEXT)) {
- ALOGE("missing driver proc: %s", "vkCreateDebugReportCallbackEXT");
- success = false;
- }
- }
- if (extensions[kEXT_debug_report]) {
- dispatch.DestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(get_proc_addr(instance, "vkDestroyDebugReportCallbackEXT"));
- if (UNLIKELY(!dispatch.DestroyDebugReportCallbackEXT)) {
- ALOGE("missing driver proc: %s", "vkDestroyDebugReportCallbackEXT");
- success = false;
- }
- }
- if (extensions[kEXT_debug_report]) {
- dispatch.DebugReportMessageEXT = reinterpret_cast<PFN_vkDebugReportMessageEXT>(get_proc_addr(instance, "vkDebugReportMessageEXT"));
- if (UNLIKELY(!dispatch.DebugReportMessageEXT)) {
- ALOGE("missing driver proc: %s", "vkDebugReportMessageEXT");
- success = false;
- }
- }
- dispatch.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(get_proc_addr(instance, "vkGetDeviceProcAddr"));
- if (UNLIKELY(!dispatch.GetDeviceProcAddr)) {
- ALOGE("missing driver proc: %s", "vkGetDeviceProcAddr");
- success = false;
- }
- dispatch.CreateImage = reinterpret_cast<PFN_vkCreateImage>(get_proc_addr(instance, "vkCreateImage"));
- if (UNLIKELY(!dispatch.CreateImage)) {
- ALOGE("missing driver proc: %s", "vkCreateImage");
- success = false;
- }
- dispatch.DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(get_proc_addr(instance, "vkDestroyImage"));
- if (UNLIKELY(!dispatch.DestroyImage)) {
- ALOGE("missing driver proc: %s", "vkDestroyImage");
- success = false;
- }
- dispatch.GetSwapchainGrallocUsageANDROID = reinterpret_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(get_proc_addr(instance, "vkGetSwapchainGrallocUsageANDROID"));
- if (UNLIKELY(!dispatch.GetSwapchainGrallocUsageANDROID)) {
- ALOGE("missing driver proc: %s", "vkGetSwapchainGrallocUsageANDROID");
- success = false;
- }
- dispatch.AcquireImageANDROID = reinterpret_cast<PFN_vkAcquireImageANDROID>(get_proc_addr(instance, "vkAcquireImageANDROID"));
- if (UNLIKELY(!dispatch.AcquireImageANDROID)) {
- ALOGE("missing driver proc: %s", "vkAcquireImageANDROID");
- success = false;
- }
- dispatch.QueueSignalReleaseImageANDROID = reinterpret_cast<PFN_vkQueueSignalReleaseImageANDROID>(get_proc_addr(instance, "vkQueueSignalReleaseImageANDROID"));
- if (UNLIKELY(!dispatch.QueueSignalReleaseImageANDROID)) {
- ALOGE("missing driver proc: %s", "vkQueueSignalReleaseImageANDROID");
- success = false;
- }
- // clang-format on
- return success;
-}
-
-} // namespace vulkan
-
-// clang-format off
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
- return CreateInstance_Top(pCreateInfo, pAllocator, pInstance);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator) {
- DestroyInstance_Top(instance, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) {
- return GetDispatchTable(instance).EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR PFN_vkVoidFunction vkGetDeviceProcAddr(VkDevice device, const char* pName) {
- return GetDeviceProcAddr_Top(device, pName);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
- return GetInstanceProcAddr_Top(instance, pName);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties) {
- GetDispatchTable(physicalDevice).GetPhysicalDeviceProperties(physicalDevice, pProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties) {
- GetDispatchTable(physicalDevice).GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
- GetDispatchTable(physicalDevice).GetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) {
- GetDispatchTable(physicalDevice).GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) {
- GetDispatchTable(physicalDevice).GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties) {
- return GetDispatchTable(physicalDevice).GetPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) {
- return CreateDevice_Top(physicalDevice, pCreateInfo, pAllocator, pDevice);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
- DestroyDevice_Top(device, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
- return EnumerateInstanceLayerProperties_Top(pPropertyCount, pProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkEnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) {
- return EnumerateInstanceExtensionProperties_Top(pLayerName, pPropertyCount, pProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
- return EnumerateDeviceLayerProperties_Top(physicalDevice, pPropertyCount, pProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) {
- return EnumerateDeviceExtensionProperties_Top(physicalDevice, pLayerName, pPropertyCount, pProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue) {
- GetDeviceQueue_Top(device, queueFamilyIndex, queueIndex, pQueue);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence) {
- return GetDispatchTable(queue).QueueSubmit(queue, submitCount, pSubmits, fence);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkQueueWaitIdle(VkQueue queue) {
- return GetDispatchTable(queue).QueueWaitIdle(queue);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkDeviceWaitIdle(VkDevice device) {
- return GetDispatchTable(device).DeviceWaitIdle(device);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) {
- return GetDispatchTable(device).AllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).FreeMemory(device, memory, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) {
- return GetDispatchTable(device).MapMemory(device, memory, offset, size, flags, ppData);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkUnmapMemory(VkDevice device, VkDeviceMemory memory) {
- GetDispatchTable(device).UnmapMemory(device, memory);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) {
- return GetDispatchTable(device).FlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) {
- return GetDispatchTable(device).InvalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes) {
- GetDispatchTable(device).GetDeviceMemoryCommitment(device, memory, pCommittedMemoryInBytes);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements) {
- GetDispatchTable(device).GetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) {
- return GetDispatchTable(device).BindBufferMemory(device, buffer, memory, memoryOffset);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements) {
- GetDispatchTable(device).GetImageMemoryRequirements(device, image, pMemoryRequirements);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) {
- return GetDispatchTable(device).BindImageMemory(device, image, memory, memoryOffset);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements) {
- GetDispatchTable(device).GetImageSparseMemoryRequirements(device, image, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties) {
- GetDispatchTable(physicalDevice).GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pPropertyCount, pProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence) {
- return GetDispatchTable(queue).QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateFence(VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence) {
- return GetDispatchTable(device).CreateFence(device, pCreateInfo, pAllocator, pFence);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyFence(device, fence, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences) {
- return GetDispatchTable(device).ResetFences(device, fenceCount, pFences);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetFenceStatus(VkDevice device, VkFence fence) {
- return GetDispatchTable(device).GetFenceStatus(device, fence);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout) {
- return GetDispatchTable(device).WaitForFences(device, fenceCount, pFences, waitAll, timeout);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore) {
- return GetDispatchTable(device).CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroySemaphore(device, semaphore, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateEvent(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent) {
- return GetDispatchTable(device).CreateEvent(device, pCreateInfo, pAllocator, pEvent);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyEvent(device, event, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetEventStatus(VkDevice device, VkEvent event) {
- return GetDispatchTable(device).GetEventStatus(device, event);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkSetEvent(VkDevice device, VkEvent event) {
- return GetDispatchTable(device).SetEvent(device, event);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkResetEvent(VkDevice device, VkEvent event) {
- return GetDispatchTable(device).ResetEvent(device, event);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool) {
- return GetDispatchTable(device).CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyQueryPool(device, queryPool, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags) {
- return GetDispatchTable(device).GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer) {
- return GetDispatchTable(device).CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyBuffer(device, buffer, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateBufferView(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView) {
- return GetDispatchTable(device).CreateBufferView(device, pCreateInfo, pAllocator, pView);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyBufferView(device, bufferView, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage) {
- return GetDispatchTable(device).CreateImage(device, pCreateInfo, pAllocator, pImage);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyImage(device, image, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) {
- GetDispatchTable(device).GetImageSubresourceLayout(device, image, pSubresource, pLayout);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView) {
- return GetDispatchTable(device).CreateImageView(device, pCreateInfo, pAllocator, pView);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyImageView(device, imageView, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule) {
- return GetDispatchTable(device).CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyShaderModule(device, shaderModule, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache) {
- return GetDispatchTable(device).CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyPipelineCache(device, pipelineCache, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData) {
- return GetDispatchTable(device).GetPipelineCacheData(device, pipelineCache, pDataSize, pData);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkMergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches) {
- return GetDispatchTable(device).MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) {
- return GetDispatchTable(device).CreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) {
- return GetDispatchTable(device).CreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyPipeline(device, pipeline, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout) {
- return GetDispatchTable(device).CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyPipelineLayout(device, pipelineLayout, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateSampler(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler) {
- return GetDispatchTable(device).CreateSampler(device, pCreateInfo, pAllocator, pSampler);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroySampler(device, sampler, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout) {
- return GetDispatchTable(device).CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool) {
- return GetDispatchTable(device).CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyDescriptorPool(device, descriptorPool, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) {
- return GetDispatchTable(device).ResetDescriptorPool(device, descriptorPool, flags);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets) {
- return GetDispatchTable(device).AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets) {
- return GetDispatchTable(device).FreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies) {
- GetDispatchTable(device).UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer) {
- return GetDispatchTable(device).CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyFramebuffer(device, framebuffer, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass) {
- return GetDispatchTable(device).CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyRenderPass(device, renderPass, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity) {
- GetDispatchTable(device).GetRenderAreaGranularity(device, renderPass, pGranularity);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool) {
- return GetDispatchTable(device).CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroyCommandPool(device, commandPool, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) {
- return GetDispatchTable(device).ResetCommandPool(device, commandPool, flags);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers) {
- return AllocateCommandBuffers_Top(device, pAllocateInfo, pCommandBuffers);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers) {
- GetDispatchTable(device).FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo) {
- return GetDispatchTable(commandBuffer).BeginCommandBuffer(commandBuffer, pBeginInfo);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkEndCommandBuffer(VkCommandBuffer commandBuffer) {
- return GetDispatchTable(commandBuffer).EndCommandBuffer(commandBuffer);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
- return GetDispatchTable(commandBuffer).ResetCommandBuffer(commandBuffer, flags);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
- GetDispatchTable(commandBuffer).CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports) {
- GetDispatchTable(commandBuffer).CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors) {
- GetDispatchTable(commandBuffer).CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
- GetDispatchTable(commandBuffer).CmdSetLineWidth(commandBuffer, lineWidth);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) {
- GetDispatchTable(commandBuffer).CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) {
- GetDispatchTable(commandBuffer).CmdSetBlendConstants(commandBuffer, blendConstants);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) {
- GetDispatchTable(commandBuffer).CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask) {
- GetDispatchTable(commandBuffer).CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) {
- GetDispatchTable(commandBuffer).CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) {
- GetDispatchTable(commandBuffer).CmdSetStencilReference(commandBuffer, faceMask, reference);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets) {
- GetDispatchTable(commandBuffer).CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
- GetDispatchTable(commandBuffer).CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets) {
- GetDispatchTable(commandBuffer).CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
- GetDispatchTable(commandBuffer).CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
- GetDispatchTable(commandBuffer).CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
- GetDispatchTable(commandBuffer).CmdDrawIndirect(commandBuffer, buffer, offset, drawCount, stride);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
- GetDispatchTable(commandBuffer).CmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
- GetDispatchTable(commandBuffer).CmdDispatch(commandBuffer, x, y, z);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
- GetDispatchTable(commandBuffer).CmdDispatchIndirect(commandBuffer, buffer, offset);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions) {
- GetDispatchTable(commandBuffer).CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions) {
- GetDispatchTable(commandBuffer).CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter) {
- GetDispatchTable(commandBuffer).CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
- GetDispatchTable(commandBuffer).CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
- GetDispatchTable(commandBuffer).CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t* pData) {
- GetDispatchTable(commandBuffer).CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
- GetDispatchTable(commandBuffer).CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
- GetDispatchTable(commandBuffer).CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
- GetDispatchTable(commandBuffer).CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects) {
- GetDispatchTable(commandBuffer).CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions) {
- GetDispatchTable(commandBuffer).CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
- GetDispatchTable(commandBuffer).CmdSetEvent(commandBuffer, event, stageMask);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
- GetDispatchTable(commandBuffer).CmdResetEvent(commandBuffer, event, stageMask);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) {
- GetDispatchTable(commandBuffer).CmdWaitEvents(commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) {
- GetDispatchTable(commandBuffer).CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags) {
- GetDispatchTable(commandBuffer).CmdBeginQuery(commandBuffer, queryPool, query, flags);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query) {
- GetDispatchTable(commandBuffer).CmdEndQuery(commandBuffer, queryPool, query);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
- GetDispatchTable(commandBuffer).CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query) {
- GetDispatchTable(commandBuffer).CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, query);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) {
- GetDispatchTable(commandBuffer).CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues) {
- GetDispatchTable(commandBuffer).CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents) {
- GetDispatchTable(commandBuffer).CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
- GetDispatchTable(commandBuffer).CmdNextSubpass(commandBuffer, contents);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdEndRenderPass(VkCommandBuffer commandBuffer) {
- GetDispatchTable(commandBuffer).CmdEndRenderPass(commandBuffer);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers) {
- GetDispatchTable(commandBuffer).CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(instance).DestroySurfaceKHR(instance, surface, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported) {
- return GetDispatchTable(physicalDevice).GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities) {
- return GetDispatchTable(physicalDevice).GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats) {
- return GetDispatchTable(physicalDevice).GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes) {
- return GetDispatchTable(physicalDevice).GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, pPresentModes);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) {
- return GetDispatchTable(device).CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator) {
- GetDispatchTable(device).DestroySwapchainKHR(device, swapchain, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) {
- return GetDispatchTable(device).GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex) {
- return GetDispatchTable(device).AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) {
- return GetDispatchTable(queue).QueuePresentKHR(queue, pPresentInfo);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
- return GetDispatchTable(instance).CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
-}
-
-// clang-format on
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
new file mode 100644
index 0000000..b02f5b4
--- /dev/null
+++ b/vulkan/libvulkan/driver.cpp
@@ -0,0 +1,777 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <array>
+#include <new>
+#include <malloc.h>
+#include <sys/prctl.h>
+
+#include "driver.h"
+#include "stubhal.h"
+
+// #define ENABLE_ALLOC_CALLSTACKS 1
+#if ENABLE_ALLOC_CALLSTACKS
+#include <utils/CallStack.h>
+#define ALOGD_CALLSTACK(...) \
+ do { \
+ ALOGD(__VA_ARGS__); \
+ android::CallStack callstack; \
+ callstack.update(); \
+ callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
+ } while (false)
+#else
+#define ALOGD_CALLSTACK(...) \
+ do { \
+ } while (false)
+#endif
+
+namespace vulkan {
+namespace driver {
+
+namespace {
+
+class CreateInfoWrapper {
+ public:
+ CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
+ const VkInstanceCreateInfo& create_info,
+ const VkAllocationCallbacks& allocator);
+ CreateInfoWrapper(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo& create_info,
+ const VkAllocationCallbacks& allocator);
+ ~CreateInfoWrapper();
+
+ VkResult Validate();
+
+ const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
+ const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
+
+ explicit operator const VkInstanceCreateInfo*() const;
+ explicit operator const VkDeviceCreateInfo*() const;
+
+ private:
+ struct ExtensionFilter {
+ VkExtensionProperties* exts;
+ uint32_t ext_count;
+
+ const char** names;
+ uint32_t name_count;
+ };
+
+ VkResult SanitizePNext();
+
+ VkResult SanitizeLayers();
+ VkResult SanitizeExtensions();
+
+ VkResult QueryExtensionCount(uint32_t& count) const;
+ VkResult EnumerateExtensions(uint32_t& count,
+ VkExtensionProperties* props) const;
+ VkResult InitExtensionFilter();
+ void FilterExtension(const char* name);
+
+ const bool is_instance_;
+ const VkAllocationCallbacks& allocator_;
+
+ union {
+ const hwvulkan_device_t* hw_dev_;
+ VkPhysicalDevice physical_dev_;
+ };
+
+ union {
+ VkInstanceCreateInfo instance_info_;
+ VkDeviceCreateInfo dev_info_;
+ };
+
+ ExtensionFilter extension_filter_;
+
+ std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
+ std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
+};
+
+CreateInfoWrapper::CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
+ const VkInstanceCreateInfo& create_info,
+ const VkAllocationCallbacks& allocator)
+ : is_instance_(true),
+ allocator_(allocator),
+ hw_dev_(hw_dev),
+ instance_info_(create_info),
+ extension_filter_() {
+ hook_extensions_.set(ProcHook::EXTENSION_CORE);
+ hal_extensions_.set(ProcHook::EXTENSION_CORE);
+}
+
+CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo& create_info,
+ const VkAllocationCallbacks& allocator)
+ : is_instance_(false),
+ allocator_(allocator),
+ physical_dev_(physical_dev),
+ dev_info_(create_info),
+ extension_filter_() {
+ hook_extensions_.set(ProcHook::EXTENSION_CORE);
+ hal_extensions_.set(ProcHook::EXTENSION_CORE);
+}
+
+CreateInfoWrapper::~CreateInfoWrapper() {
+ allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
+ allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
+}
+
+VkResult CreateInfoWrapper::Validate() {
+ VkResult result = SanitizePNext();
+ if (result == VK_SUCCESS)
+ result = SanitizeLayers();
+ if (result == VK_SUCCESS)
+ result = SanitizeExtensions();
+
+ return result;
+}
+
+const std::bitset<ProcHook::EXTENSION_COUNT>&
+CreateInfoWrapper::GetHookExtensions() const {
+ return hook_extensions_;
+}
+
+const std::bitset<ProcHook::EXTENSION_COUNT>&
+CreateInfoWrapper::GetHalExtensions() const {
+ return hal_extensions_;
+}
+
+CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
+ return &instance_info_;
+}
+
+CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
+ return &dev_info_;
+}
+
+VkResult CreateInfoWrapper::SanitizePNext() {
+ const struct StructHeader {
+ VkStructureType type;
+ const void* next;
+ } * header;
+
+ if (is_instance_) {
+ header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
+
+ // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
+ while (header &&
+ header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
+ header = reinterpret_cast<const StructHeader*>(header->next);
+
+ instance_info_.pNext = header;
+ } else {
+ header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
+
+ // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
+ while (header &&
+ header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
+ header = reinterpret_cast<const StructHeader*>(header->next);
+
+ dev_info_.pNext = header;
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult CreateInfoWrapper::SanitizeLayers() {
+ auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
+ : dev_info_.ppEnabledLayerNames;
+ auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
+ : dev_info_.enabledLayerCount;
+
+ // remove all layers
+ layer_names = nullptr;
+ layer_count = 0;
+
+ return VK_SUCCESS;
+}
+
+VkResult CreateInfoWrapper::SanitizeExtensions() {
+ auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
+ : dev_info_.ppEnabledExtensionNames;
+ auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
+ : dev_info_.enabledExtensionCount;
+ if (!ext_count)
+ return VK_SUCCESS;
+
+ VkResult result = InitExtensionFilter();
+ if (result != VK_SUCCESS)
+ return result;
+
+ for (uint32_t i = 0; i < ext_count; i++)
+ FilterExtension(ext_names[i]);
+
+ ext_names = extension_filter_.names;
+ ext_count = extension_filter_.name_count;
+
+ return VK_SUCCESS;
+}
+
+VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
+ if (is_instance_) {
+ return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
+ nullptr);
+ } else {
+ const auto& driver = GetData(physical_dev_).driver;
+ return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
+ &count, nullptr);
+ }
+}
+
+VkResult CreateInfoWrapper::EnumerateExtensions(
+ uint32_t& count,
+ VkExtensionProperties* props) const {
+ if (is_instance_) {
+ return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
+ props);
+ } else {
+ const auto& driver = GetData(physical_dev_).driver;
+ return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
+ &count, props);
+ }
+}
+
+VkResult CreateInfoWrapper::InitExtensionFilter() {
+ // query extension count
+ uint32_t count;
+ VkResult result = QueryExtensionCount(count);
+ if (result != VK_SUCCESS || count == 0)
+ return result;
+
+ auto& filter = extension_filter_;
+ filter.exts =
+ reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
+ allocator_.pUserData, sizeof(VkExtensionProperties) * count,
+ alignof(VkExtensionProperties),
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
+ if (!filter.exts)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ // enumerate extensions
+ result = EnumerateExtensions(count, filter.exts);
+ if (result != VK_SUCCESS && result != VK_INCOMPLETE)
+ return result;
+
+ if (!count)
+ return VK_SUCCESS;
+
+ filter.ext_count = count;
+
+ // allocate name array
+ uint32_t enabled_ext_count = (is_instance_)
+ ? instance_info_.enabledExtensionCount
+ : dev_info_.enabledExtensionCount;
+ count = std::min(filter.ext_count, enabled_ext_count);
+ filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
+ allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
+ if (!filter.names)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ return VK_SUCCESS;
+}
+
+void CreateInfoWrapper::FilterExtension(const char* name) {
+ auto& filter = extension_filter_;
+
+ ProcHook::Extension ext_bit = GetProcHookExtension(name);
+ if (is_instance_) {
+ switch (ext_bit) {
+ case ProcHook::KHR_android_surface:
+ case ProcHook::KHR_surface:
+ hook_extensions_.set(ext_bit);
+ // return now as these extensions do not require HAL support
+ return;
+ case ProcHook::EXT_debug_report:
+ // both we and HAL can take part in
+ hook_extensions_.set(ext_bit);
+ break;
+ case ProcHook::EXTENSION_UNKNOWN:
+ // HAL's extensions
+ break;
+ default:
+ ALOGW("Ignored invalid instance extension %s", name);
+ return;
+ }
+ } else {
+ switch (ext_bit) {
+ case ProcHook::KHR_swapchain:
+ // map VK_KHR_swapchain to VK_ANDROID_native_buffer
+ name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
+ ext_bit = ProcHook::ANDROID_native_buffer;
+ break;
+ case ProcHook::EXTENSION_UNKNOWN:
+ // HAL's extensions
+ break;
+ default:
+ ALOGW("Ignored invalid device extension %s", name);
+ return;
+ }
+ }
+
+ for (uint32_t i = 0; i < filter.ext_count; i++) {
+ const VkExtensionProperties& props = filter.exts[i];
+ // ignore unknown extensions
+ if (strcmp(name, props.extensionName) != 0)
+ continue;
+
+ filter.names[filter.name_count++] = name;
+ if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
+ if (ext_bit == ProcHook::ANDROID_native_buffer)
+ hook_extensions_.set(ProcHook::KHR_swapchain);
+
+ hal_extensions_.set(ext_bit);
+ }
+
+ break;
+ }
+}
+
+const hwvulkan_device_t* g_hwdevice = nullptr;
+
+VKAPI_ATTR void* DefaultAllocate(void*,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope) {
+ void* ptr = nullptr;
+ // Vulkan requires 'alignment' to be a power of two, but posix_memalign
+ // additionally requires that it be at least sizeof(void*).
+ int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
+ ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
+ ret, ptr);
+ return ret == 0 ? ptr : nullptr;
+}
+
+VKAPI_ATTR void* DefaultReallocate(void*,
+ void* ptr,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope) {
+ if (size == 0) {
+ free(ptr);
+ return nullptr;
+ }
+
+ // TODO(jessehall): Right now we never shrink allocations; if the new
+ // request is smaller than the existing chunk, we just continue using it.
+ // Right now the loader never reallocs, so this doesn't matter. If that
+ // changes, or if this code is copied into some other project, this should
+ // probably have a heuristic to allocate-copy-free when doing so will save
+ // "enough" space.
+ size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
+ if (size <= old_size)
+ return ptr;
+
+ void* new_ptr = nullptr;
+ if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
+ return nullptr;
+ if (ptr) {
+ memcpy(new_ptr, ptr, std::min(old_size, size));
+ free(ptr);
+ }
+ return new_ptr;
+}
+
+VKAPI_ATTR void DefaultFree(void*, void* ptr) {
+ ALOGD_CALLSTACK("Free: %p", ptr);
+ free(ptr);
+}
+
+InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
+ void* data_mem = allocator.pfnAllocation(
+ allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (!data_mem)
+ return nullptr;
+
+ return new (data_mem) InstanceData(allocator);
+}
+
+void FreeInstanceData(InstanceData* data,
+ const VkAllocationCallbacks& allocator) {
+ data->~InstanceData();
+ allocator.pfnFree(allocator.pUserData, data);
+}
+
+DeviceData* AllocateDeviceData(const VkAllocationCallbacks& allocator) {
+ void* data_mem = allocator.pfnAllocation(
+ allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
+ VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+ if (!data_mem)
+ return nullptr;
+
+ return new (data_mem) DeviceData(allocator);
+}
+
+void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
+ data->~DeviceData();
+ allocator.pfnFree(allocator.pUserData, data);
+}
+
+} // anonymous namespace
+
+bool Debuggable() {
+ return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
+}
+
+bool OpenHAL() {
+ ALOG_ASSERT(!g_hwdevice, "OpenHAL called more than once");
+
+ // Use a stub device unless we successfully open a real HAL device.
+ g_hwdevice = &stubhal::kDevice;
+
+ const hwvulkan_module_t* module;
+ int result =
+ hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
+ if (result != 0) {
+ ALOGV("no Vulkan HAL present, using stub HAL");
+ return true;
+ }
+
+ hwvulkan_device_t* device;
+ result =
+ module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
+ reinterpret_cast<hw_device_t**>(&device));
+ if (result != 0) {
+ // Any device with a Vulkan HAL should be able to open the device.
+ ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
+ result);
+ return false;
+ }
+
+ g_hwdevice = device;
+
+ return true;
+}
+
+const VkAllocationCallbacks& GetDefaultAllocator() {
+ static const VkAllocationCallbacks kDefaultAllocCallbacks = {
+ .pUserData = nullptr,
+ .pfnAllocation = DefaultAllocate,
+ .pfnReallocation = DefaultReallocate,
+ .pfnFree = DefaultFree,
+ };
+
+ return kDefaultAllocCallbacks;
+}
+
+PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
+ const ProcHook* hook = GetProcHook(pName);
+ if (!hook)
+ return g_hwdevice->GetInstanceProcAddr(instance, pName);
+
+ if (!instance) {
+ if (hook->type == ProcHook::GLOBAL)
+ return hook->proc;
+
+ // v0 layers expect
+ //
+ // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
+ //
+ // to work.
+ if (strcmp(pName, "vkCreateDevice") == 0)
+ return hook->proc;
+
+ ALOGE(
+ "Invalid use of vkGetInstanceProcAddr to query %s without an "
+ "instance",
+ pName);
+
+ return nullptr;
+ }
+
+ PFN_vkVoidFunction proc;
+
+ switch (hook->type) {
+ case ProcHook::INSTANCE:
+ proc = (GetData(instance).hook_extensions[hook->extension])
+ ? hook->proc
+ : nullptr;
+ break;
+ case ProcHook::DEVICE:
+ proc = (hook->extension == ProcHook::EXTENSION_CORE)
+ ? hook->proc
+ : hook->checked_proc;
+ break;
+ default:
+ ALOGE(
+ "Invalid use of vkGetInstanceProcAddr to query %s with an "
+ "instance",
+ pName);
+ proc = nullptr;
+ break;
+ }
+
+ return proc;
+}
+
+PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
+ const ProcHook* hook = GetProcHook(pName);
+ if (!hook)
+ return GetData(device).driver.GetDeviceProcAddr(device, pName);
+
+ if (hook->type != ProcHook::DEVICE) {
+ ALOGE("Invalid use of vkGetDeviceProcAddr to query %s", pName);
+ return nullptr;
+ }
+
+ return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
+ : nullptr;
+}
+
+VkResult EnumerateInstanceExtensionProperties(
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties) {
+ static const std::array<VkExtensionProperties, 2> loader_extensions = {{
+ // WSI extensions
+ {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
+ {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
+ VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
+ }};
+
+ // enumerate our extensions first
+ if (!pLayerName && pProperties) {
+ uint32_t count = std::min(
+ *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
+
+ std::copy_n(loader_extensions.begin(), count, pProperties);
+
+ if (count < loader_extensions.size()) {
+ *pPropertyCount = count;
+ return VK_INCOMPLETE;
+ }
+
+ pProperties += count;
+ *pPropertyCount -= count;
+ }
+
+ VkResult result = g_hwdevice->EnumerateInstanceExtensionProperties(
+ pLayerName, pPropertyCount, pProperties);
+
+ if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE))
+ *pPropertyCount += loader_extensions.size();
+
+ return result;
+}
+
+VkResult EnumerateDeviceExtensionProperties(
+ VkPhysicalDevice physicalDevice,
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties) {
+ const InstanceData& data = GetData(physicalDevice);
+
+ VkResult result = data.driver.EnumerateDeviceExtensionProperties(
+ physicalDevice, pLayerName, pPropertyCount, pProperties);
+ if (result != VK_SUCCESS && result != VK_INCOMPLETE)
+ return result;
+
+ if (!pProperties)
+ return result;
+
+ // map VK_ANDROID_native_buffer to VK_KHR_swapchain
+ for (uint32_t i = 0; i < *pPropertyCount; i++) {
+ auto& prop = pProperties[i];
+
+ if (strcmp(prop.extensionName,
+ VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
+ continue;
+
+ memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+ sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
+ prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
+ }
+
+ return result;
+}
+
+VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkInstance* pInstance) {
+ const VkAllocationCallbacks& data_allocator =
+ (pAllocator) ? *pAllocator : GetDefaultAllocator();
+
+ CreateInfoWrapper wrapper(g_hwdevice, *pCreateInfo, data_allocator);
+ VkResult result = wrapper.Validate();
+ if (result != VK_SUCCESS)
+ return result;
+
+ InstanceData* data = AllocateInstanceData(data_allocator);
+ if (!data)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ data->hook_extensions |= wrapper.GetHookExtensions();
+
+ // call into the driver
+ VkInstance instance;
+ result = g_hwdevice->CreateInstance(
+ static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
+ &instance);
+ if (result != VK_SUCCESS) {
+ FreeInstanceData(data, data_allocator);
+ return result;
+ }
+
+ // initialize InstanceDriverTable
+ if (!SetData(instance, *data) ||
+ !InitDriverTable(instance, g_hwdevice->GetInstanceProcAddr,
+ wrapper.GetHalExtensions())) {
+ data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
+ g_hwdevice->GetInstanceProcAddr(instance, "vkDestroyInstance"));
+ if (data->driver.DestroyInstance)
+ data->driver.DestroyInstance(instance, pAllocator);
+
+ FreeInstanceData(data, data_allocator);
+
+ return VK_ERROR_INCOMPATIBLE_DRIVER;
+ }
+
+ data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
+ g_hwdevice->GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
+ if (!data->get_device_proc_addr) {
+ data->driver.DestroyInstance(instance, pAllocator);
+ FreeInstanceData(data, data_allocator);
+
+ return VK_ERROR_INCOMPATIBLE_DRIVER;
+ }
+
+ *pInstance = instance;
+
+ return VK_SUCCESS;
+}
+
+void DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* pAllocator) {
+ InstanceData& data = GetData(instance);
+ data.driver.DestroyInstance(instance, pAllocator);
+
+ VkAllocationCallbacks local_allocator;
+ if (!pAllocator) {
+ local_allocator = data.allocator;
+ pAllocator = &local_allocator;
+ }
+
+ FreeInstanceData(&data, *pAllocator);
+}
+
+VkResult CreateDevice(VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDevice* pDevice) {
+ const InstanceData& instance_data = GetData(physicalDevice);
+ const VkAllocationCallbacks& data_allocator =
+ (pAllocator) ? *pAllocator : instance_data.allocator;
+
+ CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
+ VkResult result = wrapper.Validate();
+ if (result != VK_SUCCESS)
+ return result;
+
+ DeviceData* data = AllocateDeviceData(data_allocator);
+ if (!data)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ data->hook_extensions |= wrapper.GetHookExtensions();
+
+ // call into the driver
+ VkDevice dev;
+ result = instance_data.driver.CreateDevice(
+ physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
+ pAllocator, &dev);
+ if (result != VK_SUCCESS) {
+ FreeDeviceData(data, data_allocator);
+ return result;
+ }
+
+ // initialize DeviceDriverTable
+ if (!SetData(dev, *data) ||
+ !InitDriverTable(dev, instance_data.get_device_proc_addr,
+ wrapper.GetHalExtensions())) {
+ data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
+ instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
+ if (data->driver.DestroyDevice)
+ data->driver.DestroyDevice(dev, pAllocator);
+
+ FreeDeviceData(data, data_allocator);
+
+ return VK_ERROR_INCOMPATIBLE_DRIVER;
+ }
+
+ *pDevice = dev;
+
+ return VK_SUCCESS;
+}
+
+void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
+ DeviceData& data = GetData(device);
+ data.driver.DestroyDevice(device, pAllocator);
+
+ VkAllocationCallbacks local_allocator;
+ if (!pAllocator) {
+ local_allocator = data.allocator;
+ pAllocator = &local_allocator;
+ }
+
+ FreeDeviceData(&data, *pAllocator);
+}
+
+VkResult EnumeratePhysicalDevices(VkInstance instance,
+ uint32_t* pPhysicalDeviceCount,
+ VkPhysicalDevice* pPhysicalDevices) {
+ const auto& data = GetData(instance);
+
+ VkResult result = data.driver.EnumeratePhysicalDevices(
+ instance, pPhysicalDeviceCount, pPhysicalDevices);
+ if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
+ for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
+ SetData(pPhysicalDevices[i], data);
+ }
+
+ return result;
+}
+
+void GetDeviceQueue(VkDevice device,
+ uint32_t queueFamilyIndex,
+ uint32_t queueIndex,
+ VkQueue* pQueue) {
+ const auto& data = GetData(device);
+
+ data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
+ SetData(*pQueue, data);
+}
+
+VKAPI_ATTR VkResult
+AllocateCommandBuffers(VkDevice device,
+ const VkCommandBufferAllocateInfo* pAllocateInfo,
+ VkCommandBuffer* pCommandBuffers) {
+ const auto& data = GetData(device);
+
+ VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
+ pCommandBuffers);
+ if (result == VK_SUCCESS) {
+ for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
+ SetData(pCommandBuffers[i], data);
+ }
+
+ return result;
+}
+
+} // namespace driver
+} // namespace vulkan
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
new file mode 100644
index 0000000..85b36b6
--- /dev/null
+++ b/vulkan/libvulkan/driver.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LIBVULKAN_DRIVER_H
+#define LIBVULKAN_DRIVER_H 1
+
+#include <inttypes.h>
+#include <bitset>
+#include <type_traits>
+#include <log/log.h>
+
+#include <vulkan/vulkan.h>
+#include <hardware/hwvulkan.h>
+
+#include "api_gen.h"
+#include "driver_gen.h"
+#include "debug_report.h"
+#include "swapchain.h"
+
+namespace vulkan {
+
+// This is here so that we can embed api::{Instance,Device}Data in
+// driver::{Instance,Device}Data to avoid pointer chasing. They are
+// considered opaque to the driver layer.
+namespace api {
+
+struct InstanceData {
+ InstanceDispatchTable dispatch;
+
+ // for VkPhysicalDevice->VkInstance mapping
+ VkInstance instance;
+
+ // LayerChain::ActiveLayer array
+ void* layers;
+ uint32_t layer_count;
+
+ // debug.vulkan.enable_callback
+ PFN_vkDestroyDebugReportCallbackEXT destroy_debug_callback;
+ VkDebugReportCallbackEXT debug_callback;
+};
+
+struct DeviceData {
+ DeviceDispatchTable dispatch;
+
+ // LayerChain::ActiveLayer array
+ void* layers;
+ uint32_t layer_count;
+};
+
+} // namespace api
+
+namespace driver {
+
+VK_DEFINE_HANDLE(InstanceDispatchable)
+VK_DEFINE_HANDLE(DeviceDispatchable)
+
+struct InstanceData {
+ InstanceData(const VkAllocationCallbacks& alloc)
+ : opaque_api_data(),
+ allocator(alloc),
+ driver(),
+ get_device_proc_addr(nullptr) {
+ hook_extensions.set(ProcHook::EXTENSION_CORE);
+ }
+
+ api::InstanceData opaque_api_data;
+
+ const VkAllocationCallbacks allocator;
+
+ std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions;
+
+ InstanceDriverTable driver;
+ PFN_vkGetDeviceProcAddr get_device_proc_addr;
+
+ DebugReportCallbackList debug_report_callbacks;
+};
+
+struct DeviceData {
+ DeviceData(const VkAllocationCallbacks& alloc)
+ : opaque_api_data(), allocator(alloc), driver() {
+ hook_extensions.set(ProcHook::EXTENSION_CORE);
+ }
+
+ api::DeviceData opaque_api_data;
+
+ const VkAllocationCallbacks allocator;
+
+ std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions;
+
+ DeviceDriverTable driver;
+};
+
+bool Debuggable();
+bool OpenHAL();
+const VkAllocationCallbacks& GetDefaultAllocator();
+
+// clang-format off
+VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName);
+VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName);
+VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+
+VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+
+VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
+VKAPI_ATTR void DestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
+VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
+VKAPI_ATTR void GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
+VKAPI_ATTR VkResult AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
+// clang-format on
+
+template <typename DispatchableType>
+void StaticAssertDispatchable(DispatchableType) {
+ static_assert(
+ std::is_same<DispatchableType, VkInstance>::value ||
+ std::is_same<DispatchableType, VkPhysicalDevice>::value ||
+ std::is_same<DispatchableType, VkDevice>::value ||
+ std::is_same<DispatchableType, InstanceDispatchable>::value ||
+ std::is_same<DispatchableType, VkQueue>::value ||
+ std::is_same<DispatchableType, VkCommandBuffer>::value ||
+ std::is_same<DispatchableType, DeviceDispatchable>::value,
+ "unrecognized dispatchable type");
+}
+
+template <typename DispatchableType>
+bool SetDataInternal(DispatchableType dispatchable, const void* data) {
+ StaticAssertDispatchable(dispatchable);
+
+ hwvulkan_dispatch_t* dispatch =
+ reinterpret_cast<hwvulkan_dispatch_t*>(dispatchable);
+ // must be magic or already set
+ if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != data) {
+ ALOGE("invalid dispatchable object magic 0x%" PRIxPTR, dispatch->magic);
+ return false;
+ }
+
+ dispatch->vtbl = data;
+
+ return true;
+}
+
+template <typename DispatchableType>
+void* GetDataInternal(DispatchableType dispatchable) {
+ StaticAssertDispatchable(dispatchable);
+
+ const hwvulkan_dispatch_t* dispatch =
+ reinterpret_cast<const hwvulkan_dispatch_t*>(dispatchable);
+
+ return const_cast<void*>(dispatch->vtbl);
+}
+
+inline bool SetData(VkInstance instance, const InstanceData& data) {
+ return SetDataInternal(instance, &data);
+}
+
+inline bool SetData(VkPhysicalDevice physical_dev, const InstanceData& data) {
+ return SetDataInternal(physical_dev, &data);
+}
+
+inline bool SetData(InstanceDispatchable dispatchable,
+ const InstanceData& data) {
+ return SetDataInternal(dispatchable, &data);
+}
+
+inline bool SetData(VkDevice dev, const DeviceData& data) {
+ return SetDataInternal(dev, &data);
+}
+
+inline bool SetData(VkQueue queue, const DeviceData& data) {
+ return SetDataInternal(queue, &data);
+}
+
+inline bool SetData(VkCommandBuffer cmd, const DeviceData& data) {
+ return SetDataInternal(cmd, &data);
+}
+
+inline bool SetData(DeviceDispatchable dispatchable, const DeviceData& data) {
+ return SetDataInternal(dispatchable, &data);
+}
+
+inline InstanceData& GetData(VkInstance instance) {
+ return *reinterpret_cast<InstanceData*>(GetDataInternal(instance));
+}
+
+inline InstanceData& GetData(VkPhysicalDevice physical_dev) {
+ return *reinterpret_cast<InstanceData*>(GetDataInternal(physical_dev));
+}
+
+inline InstanceData& GetData(InstanceDispatchable dispatchable) {
+ return *reinterpret_cast<InstanceData*>(GetDataInternal(dispatchable));
+}
+
+inline DeviceData& GetData(VkDevice dev) {
+ return *reinterpret_cast<DeviceData*>(GetDataInternal(dev));
+}
+
+inline DeviceData& GetData(VkQueue queue) {
+ return *reinterpret_cast<DeviceData*>(GetDataInternal(queue));
+}
+
+inline DeviceData& GetData(VkCommandBuffer cmd) {
+ return *reinterpret_cast<DeviceData*>(GetDataInternal(cmd));
+}
+
+inline DeviceData& GetData(DeviceDispatchable dispatchable) {
+ return *reinterpret_cast<DeviceData*>(GetDataInternal(dispatchable));
+}
+
+} // namespace driver
+} // namespace vulkan
+
+#endif // LIBVULKAN_DRIVER_H
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
new file mode 100644
index 0000000..5bd2159
--- /dev/null
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+#include <string.h>
+#include <algorithm>
+#include <log/log.h>
+
+#include "driver.h"
+
+namespace vulkan {
+namespace driver {
+
+namespace {
+
+// clang-format off
+
+VKAPI_ATTR VkResult checkedCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) {
+ if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+ return CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
+ } else {
+ ALOGE("VK_KHR_swapchain not enabled. vkCreateSwapchainKHR not executed.");
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR void checkedDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator) {
+ if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+ DestroySwapchainKHR(device, swapchain, pAllocator);
+ } else {
+ ALOGE("VK_KHR_swapchain not enabled. vkDestroySwapchainKHR not executed.");
+ }
+}
+
+VKAPI_ATTR VkResult checkedGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) {
+ if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+ return GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
+ } else {
+ ALOGE("VK_KHR_swapchain not enabled. vkGetSwapchainImagesKHR not executed.");
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR VkResult checkedAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex) {
+ if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+ return AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
+ } else {
+ ALOGE("VK_KHR_swapchain not enabled. vkAcquireNextImageKHR not executed.");
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR VkResult checkedQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) {
+ if (GetData(queue).hook_extensions[ProcHook::KHR_swapchain]) {
+ return QueuePresentKHR(queue, pPresentInfo);
+ } else {
+ ALOGE("VK_KHR_swapchain not enabled. vkQueuePresentKHR not executed.");
+ return VK_SUCCESS;
+ }
+}
+
+// clang-format on
+
+const ProcHook g_proc_hooks[] = {
+ // clang-format off
+ {
+ "vkAcquireImageANDROID",
+ ProcHook::DEVICE,
+ ProcHook::ANDROID_native_buffer,
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkAcquireNextImageKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedAcquireNextImageKHR),
+ },
+ {
+ "vkAllocateCommandBuffers",
+ ProcHook::DEVICE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers),
+ nullptr,
+ },
+ {
+ "vkCreateAndroidSurfaceKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_android_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR),
+ nullptr,
+ },
+ {
+ "vkCreateDebugReportCallbackEXT",
+ ProcHook::INSTANCE,
+ ProcHook::EXT_debug_report,
+ reinterpret_cast<PFN_vkVoidFunction>(CreateDebugReportCallbackEXT),
+ nullptr,
+ },
+ {
+ "vkCreateDevice",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(CreateDevice),
+ nullptr,
+ },
+ {
+ "vkCreateInstance",
+ ProcHook::GLOBAL,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(CreateInstance),
+ nullptr,
+ },
+ {
+ "vkCreateSwapchainKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedCreateSwapchainKHR),
+ },
+ {
+ "vkDebugReportMessageEXT",
+ ProcHook::INSTANCE,
+ ProcHook::EXT_debug_report,
+ reinterpret_cast<PFN_vkVoidFunction>(DebugReportMessageEXT),
+ nullptr,
+ },
+ {
+ "vkDestroyDebugReportCallbackEXT",
+ ProcHook::INSTANCE,
+ ProcHook::EXT_debug_report,
+ reinterpret_cast<PFN_vkVoidFunction>(DestroyDebugReportCallbackEXT),
+ nullptr,
+ },
+ {
+ "vkDestroyDevice",
+ ProcHook::DEVICE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice),
+ nullptr,
+ },
+ {
+ "vkDestroyInstance",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance),
+ nullptr,
+ },
+ {
+ "vkDestroySurfaceKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR),
+ nullptr,
+ },
+ {
+ "vkDestroySwapchainKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedDestroySwapchainKHR),
+ },
+ {
+ "vkEnumerateDeviceExtensionProperties",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties),
+ nullptr,
+ },
+ {
+ "vkEnumerateInstanceExtensionProperties",
+ ProcHook::GLOBAL,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties),
+ nullptr,
+ },
+ {
+ "vkEnumeratePhysicalDevices",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices),
+ nullptr,
+ },
+ {
+ "vkGetDeviceProcAddr",
+ ProcHook::DEVICE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr),
+ nullptr,
+ },
+ {
+ "vkGetDeviceQueue",
+ ProcHook::DEVICE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue),
+ nullptr,
+ },
+ {
+ "vkGetInstanceProcAddr",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceSurfaceFormatsKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceSurfacePresentModesKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceSurfaceSupportKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR),
+ nullptr,
+ },
+ {
+ "vkGetSwapchainGrallocUsageANDROID",
+ ProcHook::DEVICE,
+ ProcHook::ANDROID_native_buffer,
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkGetSwapchainImagesKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedGetSwapchainImagesKHR),
+ },
+ {
+ "vkQueuePresentKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedQueuePresentKHR),
+ },
+ {
+ "vkQueueSignalReleaseImageANDROID",
+ ProcHook::DEVICE,
+ ProcHook::ANDROID_native_buffer,
+ nullptr,
+ nullptr,
+ },
+ // clang-format on
+};
+
+} // anonymous
+
+const ProcHook* GetProcHook(const char* name) {
+ const auto& begin = g_proc_hooks;
+ const auto& end =
+ g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
+ const auto hook = std::lower_bound(
+ begin, end, name,
+ [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
+ return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
+}
+
+ProcHook::Extension GetProcHookExtension(const char* name) {
+ // clang-format off
+ if (strcmp(name, "VK_ANDROID_native_buffer") == 0) return ProcHook::ANDROID_native_buffer;
+ if (strcmp(name, "VK_EXT_debug_report") == 0) return ProcHook::EXT_debug_report;
+ if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
+ if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
+ if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
+ // clang-format on
+ return ProcHook::EXTENSION_UNKNOWN;
+}
+
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
+
+#define INIT_PROC(obj, proc) \
+ do { \
+ data.driver.proc = \
+ reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \
+ if (UNLIKELY(!data.driver.proc)) { \
+ ALOGE("missing " #obj " proc: vk" #proc); \
+ success = false; \
+ } \
+ } while (0)
+
+#define INIT_PROC_EXT(ext, obj, proc) \
+ do { \
+ if (extensions[ProcHook::ext]) \
+ INIT_PROC(obj, proc); \
+ } while (0)
+
+bool InitDriverTable(VkInstance instance,
+ PFN_vkGetInstanceProcAddr get_proc,
+ const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
+ auto& data = GetData(instance);
+ bool success = true;
+
+ // clang-format off
+ INIT_PROC(instance, DestroyInstance);
+ INIT_PROC(instance, EnumeratePhysicalDevices);
+ INIT_PROC(instance, GetInstanceProcAddr);
+ INIT_PROC(instance, CreateDevice);
+ INIT_PROC(instance, EnumerateDeviceLayerProperties);
+ INIT_PROC(instance, EnumerateDeviceExtensionProperties);
+ INIT_PROC_EXT(EXT_debug_report, instance, CreateDebugReportCallbackEXT);
+ INIT_PROC_EXT(EXT_debug_report, instance, DestroyDebugReportCallbackEXT);
+ INIT_PROC_EXT(EXT_debug_report, instance, DebugReportMessageEXT);
+ // clang-format on
+
+ return success;
+}
+
+bool InitDriverTable(VkDevice dev,
+ PFN_vkGetDeviceProcAddr get_proc,
+ const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
+ auto& data = GetData(dev);
+ bool success = true;
+
+ // clang-format off
+ INIT_PROC(dev, GetDeviceProcAddr);
+ INIT_PROC(dev, DestroyDevice);
+ INIT_PROC(dev, GetDeviceQueue);
+ INIT_PROC(dev, CreateImage);
+ INIT_PROC(dev, DestroyImage);
+ INIT_PROC(dev, AllocateCommandBuffers);
+ INIT_PROC_EXT(ANDROID_native_buffer, dev, GetSwapchainGrallocUsageANDROID);
+ INIT_PROC_EXT(ANDROID_native_buffer, dev, AcquireImageANDROID);
+ INIT_PROC_EXT(ANDROID_native_buffer, dev, QueueSignalReleaseImageANDROID);
+ // clang-format on
+
+ return success;
+}
+
+} // namespace driver
+} // namespace vulkan
+
+// clang-format on
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
new file mode 100644
index 0000000..ca17d57
--- /dev/null
+++ b/vulkan/libvulkan/driver_gen.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+#ifndef LIBVULKAN_DRIVER_GEN_H
+#define LIBVULKAN_DRIVER_GEN_H
+
+#include <bitset>
+#include <vulkan/vulkan.h>
+#include <vulkan/vk_android_native_buffer.h>
+
+namespace vulkan {
+namespace driver {
+
+struct ProcHook {
+ enum Type {
+ GLOBAL,
+ INSTANCE,
+ DEVICE,
+ };
+ enum Extension {
+ ANDROID_native_buffer,
+ EXT_debug_report,
+ KHR_android_surface,
+ KHR_surface,
+ KHR_swapchain,
+
+ EXTENSION_CORE, // valid bit
+ EXTENSION_COUNT,
+ EXTENSION_UNKNOWN,
+ };
+
+ const char* name;
+ Type type;
+ Extension extension;
+
+ PFN_vkVoidFunction proc;
+ PFN_vkVoidFunction checked_proc; // always nullptr for non-device hooks
+};
+
+struct InstanceDriverTable {
+ // clang-format off
+ PFN_vkDestroyInstance DestroyInstance;
+ PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
+ PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+ PFN_vkCreateDevice CreateDevice;
+ PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
+ PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+ PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
+ PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
+ PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
+ // clang-format on
+};
+
+struct DeviceDriverTable {
+ // clang-format off
+ PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+ PFN_vkDestroyDevice DestroyDevice;
+ PFN_vkGetDeviceQueue GetDeviceQueue;
+ PFN_vkCreateImage CreateImage;
+ PFN_vkDestroyImage DestroyImage;
+ PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+ PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
+ PFN_vkAcquireImageANDROID AcquireImageANDROID;
+ PFN_vkQueueSignalReleaseImageANDROID QueueSignalReleaseImageANDROID;
+ // clang-format on
+};
+
+const ProcHook* GetProcHook(const char* name);
+ProcHook::Extension GetProcHookExtension(const char* name);
+
+bool InitDriverTable(VkInstance instance,
+ PFN_vkGetInstanceProcAddr get_proc,
+ const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
+bool InitDriverTable(VkDevice dev,
+ PFN_vkGetDeviceProcAddr get_proc,
+ const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
+
+} // namespace driver
+} // namespace vulkan
+
+#endif // LIBVULKAN_DRIVER_TABLE_H
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index aec0fd0..6b53a9a 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -16,7 +16,7 @@
// #define LOG_NDEBUG 0
-#include "loader.h"
+#include "layers_extensions.h"
#include <alloca.h>
#include <dirent.h>
#include <dlfcn.h>
@@ -28,8 +28,6 @@
#include <log/log.h>
#include <vulkan/vulkan_loader_data.h>
-using namespace vulkan;
-
// TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
// not a good long-term solution. Having a hard-coded enum of extensions is
// bad, of course. Representing sets of extensions (requested, supported, etc.)
@@ -50,12 +48,13 @@
// with a mask saying what kind(s) it is.
namespace vulkan {
+namespace api {
+
struct Layer {
VkLayerProperties properties;
size_t library_idx;
std::vector<VkExtensionProperties> extensions;
};
-} // namespace vulkan
namespace {
@@ -341,8 +340,6 @@
} // anonymous namespace
-namespace vulkan {
-
void DiscoverLayers() {
if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
DiscoverLayersInDirectory("/data/local/debug/vulkan");
@@ -425,22 +422,5 @@
}) != layer_->extensions.cend();
}
-InstanceExtension InstanceExtensionFromName(const char* name) {
- if (strcmp(name, VK_KHR_SURFACE_EXTENSION_NAME) == 0)
- return kKHR_surface;
- if (strcmp(name, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0)
- return kKHR_android_surface;
- if (strcmp(name, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0)
- return kEXT_debug_report;
- return kInstanceExtensionCount;
-}
-
-DeviceExtension DeviceExtensionFromName(const char* name) {
- if (strcmp(name, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0)
- return kKHR_swapchain;
- if (strcmp(name, VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) == 0)
- return kANDROID_native_buffer;
- return kDeviceExtensionCount;
-}
-
+} // namespace api
} // namespace vulkan
diff --git a/vulkan/libvulkan/layers_extensions.h b/vulkan/libvulkan/layers_extensions.h
new file mode 100644
index 0000000..7e7bfd3
--- /dev/null
+++ b/vulkan/libvulkan/layers_extensions.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LIBVULKAN_LAYERS_EXTENSIONS_H
+#define LIBVULKAN_LAYERS_EXTENSIONS_H 1
+
+#include <vulkan/vulkan.h>
+
+namespace vulkan {
+namespace api {
+
+struct Layer;
+class LayerRef {
+ public:
+ LayerRef(Layer* layer);
+ LayerRef(LayerRef&& other);
+ ~LayerRef();
+ LayerRef(const LayerRef&) = delete;
+ LayerRef& operator=(const LayerRef&) = delete;
+
+ const char* GetName() const;
+ uint32_t GetSpecVersion();
+
+ // provides bool-like behavior
+ operator const Layer*() const { return layer_; }
+
+ PFN_vkGetInstanceProcAddr GetGetInstanceProcAddr() const;
+ PFN_vkGetDeviceProcAddr GetGetDeviceProcAddr() const;
+
+ bool SupportsExtension(const char* name) const;
+
+ private:
+ Layer* layer_;
+};
+
+void DiscoverLayers();
+uint32_t EnumerateInstanceLayers(uint32_t count, VkLayerProperties* properties);
+uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties);
+void GetInstanceLayerExtensions(const char* name,
+ const VkExtensionProperties** properties,
+ uint32_t* count);
+void GetDeviceLayerExtensions(const char* name,
+ const VkExtensionProperties** properties,
+ uint32_t* count);
+LayerRef GetInstanceLayerRef(const char* name);
+LayerRef GetDeviceLayerRef(const char* name);
+
+} // namespace api
+} // namespace vulkan
+
+#endif // LIBVULKAN_LAYERS_EXTENSIONS_H
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
deleted file mode 100644
index 6531968..0000000
--- a/vulkan/libvulkan/loader.cpp
+++ /dev/null
@@ -1,1721 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// module header
-#include "loader.h"
-// standard C headers
-#include <dirent.h>
-#include <dlfcn.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/prctl.h>
-// standard C++ headers
-#include <algorithm>
-#include <mutex>
-#include <sstream>
-#include <string>
-#include <unordered_map>
-#include <vector>
-// platform/library headers
-#include <cutils/properties.h>
-#include <hardware/hwvulkan.h>
-#include <log/log.h>
-#include <vulkan/vulkan_loader_data.h>
-#include <vulkan/vk_layer_interface.h>
-
-// #define ENABLE_ALLOC_CALLSTACKS 1
-#if ENABLE_ALLOC_CALLSTACKS
-#include <utils/CallStack.h>
-#define ALOGD_CALLSTACK(...) \
- do { \
- ALOGD(__VA_ARGS__); \
- android::CallStack callstack; \
- callstack.update(); \
- callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
- } while (false)
-#else
-#define ALOGD_CALLSTACK(...) \
- do { \
- } while (false)
-#endif
-
-using namespace vulkan;
-
-static const uint32_t kMaxPhysicalDevices = 4;
-
-namespace {
-
-// ----------------------------------------------------------------------------
-
-// Standard-library allocator that delegates to VkAllocationCallbacks.
-//
-// TODO(jessehall): This class currently always uses
-// VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE. The scope to use could be a template
-// parameter or a constructor parameter. The former would help catch bugs
-// where we use the wrong scope, e.g. adding a command-scope string to an
-// instance-scope vector. But that might also be pretty annoying to deal with.
-template <class T>
-class CallbackAllocator {
- public:
- typedef T value_type;
-
- CallbackAllocator(const VkAllocationCallbacks* alloc_input)
- : alloc(alloc_input) {}
-
- template <class T2>
- CallbackAllocator(const CallbackAllocator<T2>& other)
- : alloc(other.alloc) {}
-
- T* allocate(std::size_t n) {
- void* mem =
- alloc->pfnAllocation(alloc->pUserData, n * sizeof(T), alignof(T),
- VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
- if (!mem)
- throw std::bad_alloc();
- return static_cast<T*>(mem);
- }
-
- void deallocate(T* array, std::size_t /*n*/) noexcept {
- alloc->pfnFree(alloc->pUserData, array);
- }
-
- const VkAllocationCallbacks* alloc;
-};
-// These are needed in order to move Strings
-template <class T>
-bool operator==(const CallbackAllocator<T>& alloc1,
- const CallbackAllocator<T>& alloc2) {
- return alloc1.alloc == alloc2.alloc;
-}
-template <class T>
-bool operator!=(const CallbackAllocator<T>& alloc1,
- const CallbackAllocator<T>& alloc2) {
- return !(alloc1 == alloc2);
-}
-
-template <class T>
-using Vector = std::vector<T, CallbackAllocator<T>>;
-
-typedef std::basic_string<char, std::char_traits<char>, CallbackAllocator<char>>
- String;
-
-// ----------------------------------------------------------------------------
-
-VKAPI_ATTR void* DefaultAllocate(void*,
- size_t size,
- size_t alignment,
- VkSystemAllocationScope) {
- void* ptr = nullptr;
- // Vulkan requires 'alignment' to be a power of two, but posix_memalign
- // additionally requires that it be at least sizeof(void*).
- int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
- ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
- ret, ptr);
- return ret == 0 ? ptr : nullptr;
-}
-
-VKAPI_ATTR void* DefaultReallocate(void*,
- void* ptr,
- size_t size,
- size_t alignment,
- VkSystemAllocationScope) {
- if (size == 0) {
- free(ptr);
- return nullptr;
- }
-
- // TODO(jessehall): Right now we never shrink allocations; if the new
- // request is smaller than the existing chunk, we just continue using it.
- // Right now the loader never reallocs, so this doesn't matter. If that
- // changes, or if this code is copied into some other project, this should
- // probably have a heuristic to allocate-copy-free when doing so will save
- // "enough" space.
- size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
- if (size <= old_size)
- return ptr;
-
- void* new_ptr = nullptr;
- if (posix_memalign(&new_ptr, alignment, size) != 0)
- return nullptr;
- if (ptr) {
- memcpy(new_ptr, ptr, std::min(old_size, size));
- free(ptr);
- }
- return new_ptr;
-}
-
-VKAPI_ATTR void DefaultFree(void*, void* ptr) {
- ALOGD_CALLSTACK("Free: %p", ptr);
- free(ptr);
-}
-
-const VkAllocationCallbacks kDefaultAllocCallbacks = {
- .pUserData = nullptr,
- .pfnAllocation = DefaultAllocate,
- .pfnReallocation = DefaultReallocate,
- .pfnFree = DefaultFree,
-};
-
-// ----------------------------------------------------------------------------
-// Global Data and Initialization
-
-hwvulkan_device_t* g_hwdevice = nullptr;
-InstanceExtensionSet g_driver_instance_extensions;
-
-void LoadVulkanHAL() {
- static const hwvulkan_module_t* module;
- int result =
- hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
- if (result != 0) {
- ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result), result);
- return;
- }
- result = module->common.methods->open(
- &module->common, HWVULKAN_DEVICE_0,
- reinterpret_cast<hw_device_t**>(&g_hwdevice));
- if (result != 0) {
- ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
- result);
- module = nullptr;
- return;
- }
-
- VkResult vkresult;
- uint32_t count;
- if ((vkresult = g_hwdevice->EnumerateInstanceExtensionProperties(
- nullptr, &count, nullptr)) != VK_SUCCESS) {
- ALOGE("driver EnumerateInstanceExtensionProperties failed: %d",
- vkresult);
- g_hwdevice->common.close(&g_hwdevice->common);
- g_hwdevice = nullptr;
- module = nullptr;
- return;
- }
- VkExtensionProperties* extensions = static_cast<VkExtensionProperties*>(
- alloca(count * sizeof(VkExtensionProperties)));
- if ((vkresult = g_hwdevice->EnumerateInstanceExtensionProperties(
- nullptr, &count, extensions)) != VK_SUCCESS) {
- ALOGE("driver EnumerateInstanceExtensionProperties failed: %d",
- vkresult);
- g_hwdevice->common.close(&g_hwdevice->common);
- g_hwdevice = nullptr;
- module = nullptr;
- return;
- }
- ALOGV_IF(count > 0, "Driver-supported instance extensions:");
- for (uint32_t i = 0; i < count; i++) {
- ALOGV(" %s (v%u)", extensions[i].extensionName,
- extensions[i].specVersion);
- InstanceExtension id =
- InstanceExtensionFromName(extensions[i].extensionName);
- if (id != kInstanceExtensionCount)
- g_driver_instance_extensions.set(id);
- }
- // Ignore driver attempts to support loader extensions
- g_driver_instance_extensions.reset(kKHR_surface);
- g_driver_instance_extensions.reset(kKHR_android_surface);
-}
-
-bool EnsureInitialized() {
- static std::once_flag once_flag;
- std::call_once(once_flag, []() {
- LoadVulkanHAL();
- DiscoverLayers();
- });
- return g_hwdevice != nullptr;
-}
-
-// -----------------------------------------------------------------------------
-
-struct Instance {
- Instance(const VkAllocationCallbacks* alloc_callbacks)
- : dispatch_ptr(&dispatch),
- handle(reinterpret_cast<VkInstance>(&dispatch_ptr)),
- alloc(alloc_callbacks),
- num_physical_devices(0),
- active_layers(CallbackAllocator<LayerRef>(alloc)),
- message(VK_NULL_HANDLE) {
- memset(&dispatch, 0, sizeof(dispatch));
- memset(physical_devices, 0, sizeof(physical_devices));
- enabled_extensions.reset();
- drv.instance = VK_NULL_HANDLE;
- memset(&drv.dispatch, 0, sizeof(drv.dispatch));
- drv.num_physical_devices = 0;
- }
-
- ~Instance() {}
-
- const InstanceDispatchTable* dispatch_ptr;
- const VkInstance handle;
- InstanceDispatchTable dispatch;
-
- const VkAllocationCallbacks* alloc;
- uint32_t num_physical_devices;
- VkPhysicalDevice physical_devices_top[kMaxPhysicalDevices];
- VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
- DeviceExtensionSet physical_device_driver_extensions[kMaxPhysicalDevices];
-
- Vector<LayerRef> active_layers;
- VkDebugReportCallbackEXT message;
- DebugReportCallbackList debug_report_callbacks;
- InstanceExtensionSet enabled_extensions;
-
- struct {
- VkInstance instance;
- DriverDispatchTable dispatch;
- uint32_t num_physical_devices;
- } drv; // may eventually be an array
-};
-
-struct Device {
- Device(Instance* instance_)
- : instance(instance_),
- active_layers(CallbackAllocator<LayerRef>(instance->alloc)) {
- memset(&dispatch, 0, sizeof(dispatch));
- enabled_extensions.reset();
- }
- DeviceDispatchTable dispatch;
- Instance* instance;
- PFN_vkGetDeviceProcAddr get_device_proc_addr;
- Vector<LayerRef> active_layers;
- DeviceExtensionSet enabled_extensions;
-};
-
-template <typename THandle>
-struct HandleTraits {};
-template <>
-struct HandleTraits<VkInstance> {
- typedef Instance LoaderObjectType;
-};
-template <>
-struct HandleTraits<VkPhysicalDevice> {
- typedef Instance LoaderObjectType;
-};
-template <>
-struct HandleTraits<VkDevice> {
- typedef Device LoaderObjectType;
-};
-template <>
-struct HandleTraits<VkQueue> {
- typedef Device LoaderObjectType;
-};
-template <>
-struct HandleTraits<VkCommandBuffer> {
- typedef Device LoaderObjectType;
-};
-
-template <typename THandle>
-typename HandleTraits<THandle>::LoaderObjectType& GetDispatchParent(
- THandle handle) {
- // TODO(jessehall): Make Instance and Device POD types (by removing the
- // non-default constructors), so that offsetof is actually legal to use.
- // The specific case we're using here is safe in gcc/clang (and probably
- // most other C++ compilers), but isn't guaranteed by C++.
- typedef typename HandleTraits<THandle>::LoaderObjectType ObjectType;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Winvalid-offsetof"
- const size_t kDispatchOffset = offsetof(ObjectType, dispatch);
-#pragma clang diagnostic pop
-
- const auto& dispatch = GetDispatchTable(handle);
- uintptr_t dispatch_addr = reinterpret_cast<uintptr_t>(&dispatch);
- uintptr_t object_addr = dispatch_addr - kDispatchOffset;
- return *reinterpret_cast<ObjectType*>(object_addr);
-}
-
-// -----------------------------------------------------------------------------
-
-void DestroyDevice(Device* device) {
- const VkAllocationCallbacks* alloc = device->instance->alloc;
- device->~Device();
- alloc->pfnFree(alloc->pUserData, device);
-}
-
-template <class TObject>
-LayerRef GetLayerRef(const char* name);
-template <>
-LayerRef GetLayerRef<Instance>(const char* name) {
- return GetInstanceLayerRef(name);
-}
-template <>
-LayerRef GetLayerRef<Device>(const char* name) {
- return GetDeviceLayerRef(name);
-}
-
-template <class TObject>
-bool ActivateLayer(TObject* object, const char* name) {
- LayerRef layer(GetLayerRef<TObject>(name));
- if (!layer)
- return false;
- if (std::find(object->active_layers.begin(), object->active_layers.end(),
- layer) == object->active_layers.end()) {
- try {
- object->active_layers.push_back(std::move(layer));
- } catch (std::bad_alloc&) {
- // TODO(jessehall): We should fail with VK_ERROR_OUT_OF_MEMORY
- // if we can't enable a requested layer. Callers currently ignore
- // ActivateLayer's return value.
- ALOGW("failed to activate layer '%s': out of memory", name);
- return false;
- }
- }
- ALOGV("activated layer '%s'", name);
- return true;
-}
-
-struct InstanceNamesPair {
- Instance* instance;
- Vector<String>* layer_names;
-};
-
-void SetLayerNamesFromProperty(const char* name,
- const char* value,
- void* data) {
- try {
- const char prefix[] = "debug.vulkan.layer.";
- const size_t prefixlen = sizeof(prefix) - 1;
- if (value[0] == '\0' || strncmp(name, prefix, prefixlen) != 0)
- return;
- const char* number_str = name + prefixlen;
- long layer_number = strtol(number_str, nullptr, 10);
- if (layer_number <= 0 || layer_number == LONG_MAX) {
- ALOGW("Cannot use a layer at number %ld from string %s",
- layer_number, number_str);
- return;
- }
- auto instance_names_pair = static_cast<InstanceNamesPair*>(data);
- Vector<String>* layer_names = instance_names_pair->layer_names;
- Instance* instance = instance_names_pair->instance;
- size_t layer_size = static_cast<size_t>(layer_number);
- if (layer_size > layer_names->size()) {
- layer_names->resize(
- layer_size, String(CallbackAllocator<char>(instance->alloc)));
- }
- (*layer_names)[layer_size - 1] = value;
- } catch (std::bad_alloc&) {
- ALOGW("failed to handle property '%s'='%s': out of memory", name,
- value);
- return;
- }
-}
-
-template <class TInfo, class TObject>
-VkResult ActivateAllLayers(TInfo create_info,
- Instance* instance,
- TObject* object) {
- ALOG_ASSERT(create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO ||
- create_info->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- "Cannot activate layers for unknown object %p", object);
- CallbackAllocator<char> string_allocator(instance->alloc);
- // Load system layers
- if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
- char layer_prop[PROPERTY_VALUE_MAX];
- property_get("debug.vulkan.layers", layer_prop, "");
- char* strtok_state;
- char* layer_name = nullptr;
- while ((layer_name = strtok_r(layer_name ? nullptr : layer_prop, ":",
- &strtok_state))) {
- ActivateLayer(object, layer_name);
- }
- Vector<String> layer_names(CallbackAllocator<String>(instance->alloc));
- InstanceNamesPair instance_names_pair = {.instance = instance,
- .layer_names = &layer_names};
- property_list(SetLayerNamesFromProperty,
- static_cast<void*>(&instance_names_pair));
- for (auto layer_name_element : layer_names) {
- ActivateLayer(object, layer_name_element.c_str());
- }
- }
- // Load app layers
- for (uint32_t i = 0; i < create_info->enabledLayerCount; ++i) {
- if (!ActivateLayer(object, create_info->ppEnabledLayerNames[i])) {
- ALOGE("requested %s layer '%s' not present",
- create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
- ? "instance"
- : "device",
- create_info->ppEnabledLayerNames[i]);
- return VK_ERROR_LAYER_NOT_PRESENT;
- }
- }
- return VK_SUCCESS;
-}
-
-template <class TCreateInfo, class TObject>
-bool AddLayersToCreateInfo(TCreateInfo& local_create_info,
- const TObject& object,
- const VkAllocationCallbacks* alloc,
- bool& allocatedMemory) {
- // This should never happen and means there is a likely a bug in layer
- // tracking
- if (object->active_layers.size() < local_create_info.enabledLayerCount) {
- ALOGE("Total number of layers is less than those enabled by the app!");
- return false;
- }
- // Check if the total number of layers enabled is greater than those
- // enabled by the application. If it is then we have system enabled
- // layers which need to be added to the list of layers passed in through
- // create.
- if (object->active_layers.size() > local_create_info.enabledLayerCount) {
- void* mem = alloc->pfnAllocation(
- alloc->pUserData, object->active_layers.size() * sizeof(char*),
- alignof(char*), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
- if (mem) {
- local_create_info.enabledLayerCount = 0;
- const char** names = static_cast<const char**>(mem);
- for (const auto& layer : object->active_layers) {
- const char* name = layer.GetName();
- names[local_create_info.enabledLayerCount++] = name;
- }
- local_create_info.ppEnabledLayerNames = names;
- } else {
- ALOGE("System layers cannot be enabled: memory allocation failed");
- return false;
- }
- allocatedMemory = true;
- } else {
- allocatedMemory = false;
- }
- return true;
-}
-
-template <class T>
-void FreeAllocatedLayerCreateInfo(T& local_create_info,
- const VkAllocationCallbacks* alloc) {
- alloc->pfnFree(alloc->pUserData,
- const_cast<char**>(local_create_info.ppEnabledLayerNames));
-}
-
-template <class TCreateInfo>
-bool AddExtensionToCreateInfo(TCreateInfo& local_create_info,
- const char* extension_name,
- const VkAllocationCallbacks* alloc) {
- uint32_t extension_count = local_create_info.enabledExtensionCount;
- local_create_info.enabledExtensionCount++;
- void* mem = alloc->pfnAllocation(
- alloc->pUserData,
- local_create_info.enabledExtensionCount * sizeof(char*), alignof(char*),
- VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
- if (mem) {
- const char** enabled_extensions = static_cast<const char**>(mem);
- for (uint32_t i = 0; i < extension_count; ++i) {
- enabled_extensions[i] =
- local_create_info.ppEnabledExtensionNames[i];
- }
- enabled_extensions[extension_count] = extension_name;
- local_create_info.ppEnabledExtensionNames = enabled_extensions;
- } else {
- ALOGE("%s extension cannot be enabled: memory allocation failed",
- extension_name);
- return false;
- }
- return true;
-}
-
-template <class T>
-void FreeAllocatedExtensionCreateInfo(T& local_create_info,
- const VkAllocationCallbacks* alloc) {
- alloc->pfnFree(
- alloc->pUserData,
- const_cast<char**>(local_create_info.ppEnabledExtensionNames));
-}
-
-VKAPI_ATTR
-VkBool32 LogDebugMessageCallback(VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT /*objectType*/,
- uint64_t /*object*/,
- size_t /*location*/,
- int32_t message_code,
- const char* layer_prefix,
- const char* message,
- void* /*user_data*/) {
- if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
- ALOGE("[%s] Code %d : %s", layer_prefix, message_code, message);
- } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
- ALOGW("[%s] Code %d : %s", layer_prefix, message_code, message);
- }
- return false;
-}
-
-VkResult Noop() {
- return VK_SUCCESS;
-}
-
-/*
- * This function will return the pNext pointer of any
- * CreateInfo extensions that are not loader extensions.
- * This is used to skip past the loader extensions prepended
- * to the list during CreateInstance and CreateDevice.
- */
-void* StripCreateExtensions(const void* pNext) {
- VkLayerInstanceCreateInfo* create_info =
- const_cast<VkLayerInstanceCreateInfo*>(
- static_cast<const VkLayerInstanceCreateInfo*>(pNext));
-
- while (
- create_info &&
- (create_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO ||
- create_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)) {
- create_info = const_cast<VkLayerInstanceCreateInfo*>(
- static_cast<const VkLayerInstanceCreateInfo*>(create_info->pNext));
- }
-
- return create_info;
-}
-
-// Clean up and deallocate an Instance; called from both the failure paths in
-// CreateInstance_Top as well as from DestroyInstance_Top. This function does
-// not call down the dispatch chain; that should be done before calling this
-// function, iff the lower vkCreateInstance call has been made and returned
-// successfully.
-void DestroyInstance(Instance* instance,
- const VkAllocationCallbacks* allocator) {
- if (instance->message) {
- PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report_callback;
- destroy_debug_report_callback =
- reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
- GetInstanceProcAddr_Top(instance->handle,
- "vkDestroyDebugReportCallbackEXT"));
- destroy_debug_report_callback(instance->handle, instance->message,
- allocator);
- }
- instance->~Instance();
- allocator->pfnFree(allocator->pUserData, instance);
-}
-
-} // anonymous namespace
-
-namespace vulkan {
-
-// -----------------------------------------------------------------------------
-// "Bottom" functions. These are called at the end of the instance dispatch
-// chain.
-
-VkResult CreateInstance_Bottom(const VkInstanceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkInstance* vkinstance) {
- VkResult result;
-
- VkLayerInstanceCreateInfo* chain_info =
- const_cast<VkLayerInstanceCreateInfo*>(
- static_cast<const VkLayerInstanceCreateInfo*>(create_info->pNext));
- while (
- chain_info &&
- !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO &&
- chain_info->function == VK_LAYER_FUNCTION_INSTANCE)) {
- chain_info = const_cast<VkLayerInstanceCreateInfo*>(
- static_cast<const VkLayerInstanceCreateInfo*>(chain_info->pNext));
- }
- ALOG_ASSERT(chain_info != nullptr, "Missing initialization chain info!");
-
- Instance& instance = GetDispatchParent(
- static_cast<VkInstance>(chain_info->u.instanceInfo.instance_info));
-
- // Check that all enabled extensions are supported
- uint32_t num_driver_extensions = 0;
- for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
- const char* name = create_info->ppEnabledExtensionNames[i];
- InstanceExtension id = InstanceExtensionFromName(name);
- if (id != kInstanceExtensionCount) {
- if (g_driver_instance_extensions[id]) {
- num_driver_extensions++;
- instance.enabled_extensions.set(id);
- continue;
- }
- if (id == kKHR_surface || id == kKHR_android_surface) {
- instance.enabled_extensions.set(id);
- continue;
- }
- // The loader natively supports debug report.
- if (id == kEXT_debug_report) {
- continue;
- }
- }
- bool supported = false;
- for (const auto& layer : instance.active_layers) {
- if (layer.SupportsExtension(name))
- supported = true;
- }
- if (!supported) {
- ALOGE(
- "requested instance extension '%s' not supported by "
- "loader, driver, or any active layers",
- name);
- DestroyInstance_Bottom(instance.handle, allocator);
- return VK_ERROR_EXTENSION_NOT_PRESENT;
- }
- }
-
- VkInstanceCreateInfo driver_create_info = *create_info;
- driver_create_info.pNext = StripCreateExtensions(create_info->pNext);
- driver_create_info.enabledLayerCount = 0;
- driver_create_info.ppEnabledLayerNames = nullptr;
- driver_create_info.enabledExtensionCount = 0;
- driver_create_info.ppEnabledExtensionNames = nullptr;
- if (num_driver_extensions > 0) {
- const char** names = static_cast<const char**>(
- alloca(num_driver_extensions * sizeof(char*)));
- for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
- const char* name = create_info->ppEnabledExtensionNames[i];
- InstanceExtension id = InstanceExtensionFromName(name);
- if (id != kInstanceExtensionCount) {
- if (g_driver_instance_extensions[id]) {
- names[driver_create_info.enabledExtensionCount++] = name;
- continue;
- }
- }
- }
- driver_create_info.ppEnabledExtensionNames = names;
- ALOG_ASSERT(
- driver_create_info.enabledExtensionCount == num_driver_extensions,
- "counted enabled driver instance extensions twice and got "
- "different answers!");
- }
-
- result = g_hwdevice->CreateInstance(&driver_create_info, instance.alloc,
- &instance.drv.instance);
- if (result != VK_SUCCESS) {
- DestroyInstance_Bottom(instance.handle, allocator);
- return result;
- }
-
- hwvulkan_dispatch_t* drv_dispatch =
- reinterpret_cast<hwvulkan_dispatch_t*>(instance.drv.instance);
- if (drv_dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
- ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
- drv_dispatch->magic);
- DestroyInstance_Bottom(instance.handle, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- // Skip setting drv_dispatch->vtbl, since we never call through it;
- // we go through instance.drv.dispatch instead.
-
- if (!LoadDriverDispatchTable(
- instance.drv.instance, g_hwdevice->GetInstanceProcAddr,
- instance.enabled_extensions, instance.drv.dispatch)) {
- DestroyInstance_Bottom(instance.handle, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- uint32_t num_physical_devices = 0;
- result = instance.drv.dispatch.EnumeratePhysicalDevices(
- instance.drv.instance, &num_physical_devices, nullptr);
- if (result != VK_SUCCESS) {
- DestroyInstance_Bottom(instance.handle, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
- result = instance.drv.dispatch.EnumeratePhysicalDevices(
- instance.drv.instance, &num_physical_devices,
- instance.physical_devices);
- if (result != VK_SUCCESS) {
- DestroyInstance_Bottom(instance.handle, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- Vector<VkExtensionProperties> extensions(
- Vector<VkExtensionProperties>::allocator_type(instance.alloc));
- for (uint32_t i = 0; i < num_physical_devices; i++) {
- hwvulkan_dispatch_t* pdev_dispatch =
- reinterpret_cast<hwvulkan_dispatch_t*>(
- instance.physical_devices[i]);
- if (pdev_dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
- ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
- pdev_dispatch->magic);
- DestroyInstance_Bottom(instance.handle, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- pdev_dispatch->vtbl = instance.dispatch_ptr;
-
- uint32_t count;
- if ((result = instance.drv.dispatch.EnumerateDeviceExtensionProperties(
- instance.physical_devices[i], nullptr, &count, nullptr)) !=
- VK_SUCCESS) {
- ALOGW("driver EnumerateDeviceExtensionProperties(%u) failed: %d", i,
- result);
- continue;
- }
- try {
- extensions.resize(count);
- } catch (std::bad_alloc&) {
- ALOGE("instance creation failed: out of memory");
- DestroyInstance_Bottom(instance.handle, allocator);
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
- if ((result = instance.drv.dispatch.EnumerateDeviceExtensionProperties(
- instance.physical_devices[i], nullptr, &count,
- extensions.data())) != VK_SUCCESS) {
- ALOGW("driver EnumerateDeviceExtensionProperties(%u) failed: %d", i,
- result);
- continue;
- }
- ALOGV_IF(count > 0, "driver gpu[%u] supports extensions:", i);
- for (const auto& extension : extensions) {
- ALOGV(" %s (v%u)", extension.extensionName, extension.specVersion);
- DeviceExtension id =
- DeviceExtensionFromName(extension.extensionName);
- if (id == kDeviceExtensionCount) {
- ALOGW("driver gpu[%u] extension '%s' unknown to loader", i,
- extension.extensionName);
- } else {
- instance.physical_device_driver_extensions[i].set(id);
- }
- }
- // Ignore driver attempts to support loader extensions
- instance.physical_device_driver_extensions[i].reset(kKHR_swapchain);
- }
- instance.drv.num_physical_devices = num_physical_devices;
- instance.num_physical_devices = instance.drv.num_physical_devices;
-
- *vkinstance = instance.handle;
-
- return VK_SUCCESS;
-}
-
-VkResult CreateAndroidSurfaceKHR_Disabled(VkInstance,
- const VkAndroidSurfaceCreateInfoKHR*,
- const VkAllocationCallbacks*,
- VkSurfaceKHR*) {
- ALOGE(
- "VK_KHR_android_surface not enabled. vkCreateAndroidSurfaceKHR not "
- "executed.");
-
- return VK_SUCCESS;
-}
-
-void DestroySurfaceKHR_Disabled(VkInstance,
- VkSurfaceKHR,
- const VkAllocationCallbacks*) {
- ALOGE("VK_KHR_surface not enabled. vkDestroySurfaceKHR not executed.");
-}
-
-VkResult GetPhysicalDeviceSurfaceSupportKHR_Disabled(VkPhysicalDevice,
- uint32_t,
- VkSurfaceKHR,
- VkBool32*) {
- ALOGE(
- "VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceSupportKHR not "
- "executed.");
-
- return VK_SUCCESS;
-}
-
-VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR_Disabled(
- VkPhysicalDevice,
- VkSurfaceKHR,
- VkSurfaceCapabilitiesKHR*) {
- ALOGE(
- "VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceapabilitiesKHR "
- "not executed.");
-
- return VK_SUCCESS;
-}
-
-VkResult GetPhysicalDeviceSurfaceFormatsKHR_Disabled(VkPhysicalDevice,
- VkSurfaceKHR,
- uint32_t*,
- VkSurfaceFormatKHR*) {
- ALOGE(
- "VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceFormatsKHR not "
- "executed.");
-
- return VK_SUCCESS;
-}
-
-VkResult GetPhysicalDeviceSurfacePresentModesKHR_Disabled(VkPhysicalDevice,
- VkSurfaceKHR,
- uint32_t*,
- VkPresentModeKHR*) {
- ALOGE(
- "VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfacePresentModesKHR "
- "not executed.");
-
- return VK_SUCCESS;
-}
-
-PFN_vkVoidFunction GetInstanceProcAddr_Bottom(VkInstance vkinstance,
- const char* name) {
- PFN_vkVoidFunction pfn;
-
- if (vkinstance) {
- Instance& instance = GetDispatchParent(vkinstance);
- if (!instance.enabled_extensions[kKHR_android_surface]) {
- // KHR_android_surface is not enabled, use error stubs instead
- if (strcmp(name, "vkCreateAndroidSurfaceKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- CreateAndroidSurfaceKHR_Disabled);
- }
- }
- if (!instance.enabled_extensions[kKHR_surface]) {
- // KHR_surface is not enabled, use error stubs instead
- if (strcmp(name, "vkDestroySurfaceKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- DestroySurfaceKHR_Disabled);
- }
- if (strcmp(name, "vkGetPhysicalDeviceSurfaceSupportKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- GetPhysicalDeviceSurfaceSupportKHR_Disabled);
- }
- if (strcmp(name, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR") ==
- 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- GetPhysicalDeviceSurfaceCapabilitiesKHR_Disabled);
- }
- if (strcmp(name, "vkGetPhysicalDeviceSurfaceFormatsKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- GetPhysicalDeviceSurfaceFormatsKHR_Disabled);
- }
- if (strcmp(name, "vkGetPhysicalDeviceSurfacePresentModesKHR") ==
- 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- GetPhysicalDeviceSurfacePresentModesKHR_Disabled);
- }
- }
- }
- if ((pfn = GetLoaderBottomProcAddr(name)))
- return pfn;
- return nullptr;
-}
-
-VkResult EnumeratePhysicalDevices_Bottom(VkInstance vkinstance,
- uint32_t* pdev_count,
- VkPhysicalDevice* pdevs) {
- Instance& instance = GetDispatchParent(vkinstance);
- uint32_t count = instance.num_physical_devices;
- if (pdevs) {
- count = std::min(count, *pdev_count);
- std::copy(instance.physical_devices, instance.physical_devices + count,
- pdevs);
- }
- *pdev_count = count;
- return VK_SUCCESS;
-}
-
-void GetPhysicalDeviceProperties_Bottom(
- VkPhysicalDevice pdev,
- VkPhysicalDeviceProperties* properties) {
- GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceProperties(
- pdev, properties);
-}
-
-void GetPhysicalDeviceFeatures_Bottom(VkPhysicalDevice pdev,
- VkPhysicalDeviceFeatures* features) {
- GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceFeatures(pdev,
- features);
-}
-
-void GetPhysicalDeviceMemoryProperties_Bottom(
- VkPhysicalDevice pdev,
- VkPhysicalDeviceMemoryProperties* properties) {
- GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceMemoryProperties(
- pdev, properties);
-}
-
-void GetPhysicalDeviceQueueFamilyProperties_Bottom(
- VkPhysicalDevice pdev,
- uint32_t* pCount,
- VkQueueFamilyProperties* properties) {
- GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceQueueFamilyProperties(
- pdev, pCount, properties);
-}
-
-void GetPhysicalDeviceFormatProperties_Bottom(VkPhysicalDevice pdev,
- VkFormat format,
- VkFormatProperties* properties) {
- GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceFormatProperties(
- pdev, format, properties);
-}
-
-VkResult GetPhysicalDeviceImageFormatProperties_Bottom(
- VkPhysicalDevice pdev,
- VkFormat format,
- VkImageType type,
- VkImageTiling tiling,
- VkImageUsageFlags usage,
- VkImageCreateFlags flags,
- VkImageFormatProperties* properties) {
- return GetDispatchParent(pdev)
- .drv.dispatch.GetPhysicalDeviceImageFormatProperties(
- pdev, format, type, tiling, usage, flags, properties);
-}
-
-void GetPhysicalDeviceSparseImageFormatProperties_Bottom(
- VkPhysicalDevice pdev,
- VkFormat format,
- VkImageType type,
- VkSampleCountFlagBits samples,
- VkImageUsageFlags usage,
- VkImageTiling tiling,
- uint32_t* properties_count,
- VkSparseImageFormatProperties* properties) {
- GetDispatchParent(pdev)
- .drv.dispatch.GetPhysicalDeviceSparseImageFormatProperties(
- pdev, format, type, samples, usage, tiling, properties_count,
- properties);
-}
-
-// This is a no-op, the Top function returns the aggregate layer property
-// data. This is to keep the dispatch generator happy.
-VKAPI_ATTR
-VkResult EnumerateDeviceExtensionProperties_Bottom(
- VkPhysicalDevice /*pdev*/,
- const char* /*layer_name*/,
- uint32_t* /*properties_count*/,
- VkExtensionProperties* /*properties*/) {
- return VK_SUCCESS;
-}
-
-// This is a no-op, the Top function returns the aggregate layer property
-// data. This is to keep the dispatch generator happy.
-VKAPI_ATTR
-VkResult EnumerateDeviceLayerProperties_Bottom(
- VkPhysicalDevice /*pdev*/,
- uint32_t* /*properties_count*/,
- VkLayerProperties* /*properties*/) {
- return VK_SUCCESS;
-}
-
-VKAPI_ATTR
-VkResult CreateDevice_Bottom(VkPhysicalDevice gpu,
- const VkDeviceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkDevice* device_out) {
- VkLayerDeviceCreateInfo* chain_info = const_cast<VkLayerDeviceCreateInfo*>(
- static_cast<const VkLayerDeviceCreateInfo*>(create_info->pNext));
- while (chain_info &&
- !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO &&
- chain_info->function == VK_LAYER_FUNCTION_DEVICE)) {
- chain_info = const_cast<VkLayerDeviceCreateInfo*>(
- static_cast<const VkLayerDeviceCreateInfo*>(chain_info->pNext));
- }
- ALOG_ASSERT(chain_info != nullptr, "Missing initialization chain info!");
-
- Instance& instance = GetDispatchParent(gpu);
- size_t gpu_idx = 0;
- while (instance.physical_devices[gpu_idx] != gpu)
- gpu_idx++;
- Device* device = static_cast<Device*>(chain_info->u.deviceInfo.device_info);
- PFN_vkGetInstanceProcAddr get_instance_proc_addr =
- chain_info->u.deviceInfo.pfnNextGetInstanceProcAddr;
-
- VkDeviceCreateInfo driver_create_info = *create_info;
- driver_create_info.pNext = StripCreateExtensions(create_info->pNext);
- driver_create_info.enabledLayerCount = 0;
- driver_create_info.ppEnabledLayerNames = nullptr;
-
- uint32_t num_driver_extensions = 0;
- const char** driver_extensions = static_cast<const char**>(
- alloca(create_info->enabledExtensionCount * sizeof(const char*)));
- for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
- const char* name = create_info->ppEnabledExtensionNames[i];
- DeviceExtension id = DeviceExtensionFromName(name);
- if (id != kDeviceExtensionCount) {
- if (instance.physical_device_driver_extensions[gpu_idx][id]) {
- driver_extensions[num_driver_extensions++] = name;
- device->enabled_extensions.set(id);
- continue;
- }
- // Add the VK_ANDROID_native_buffer extension to the list iff
- // the VK_KHR_swapchain extension was requested
- if (id == kKHR_swapchain &&
- instance.physical_device_driver_extensions
- [gpu_idx][kANDROID_native_buffer]) {
- driver_extensions[num_driver_extensions++] =
- VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
- device->enabled_extensions.set(id);
- continue;
- }
- }
- bool supported = false;
- for (const auto& layer : device->active_layers) {
- if (layer.SupportsExtension(name))
- supported = true;
- }
- if (!supported) {
- ALOGE(
- "requested device extension '%s' not supported by loader, "
- "driver, or any active layers",
- name);
- return VK_ERROR_EXTENSION_NOT_PRESENT;
- }
- }
-
- driver_create_info.enabledExtensionCount = num_driver_extensions;
- driver_create_info.ppEnabledExtensionNames = driver_extensions;
- VkDevice drv_device;
- VkResult result = instance.drv.dispatch.CreateDevice(
- gpu, &driver_create_info, allocator, &drv_device);
- if (result != VK_SUCCESS) {
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- hwvulkan_dispatch_t* drv_dispatch =
- reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
- if (drv_dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
- ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR,
- drv_dispatch->magic);
- PFN_vkDestroyDevice destroy_device =
- reinterpret_cast<PFN_vkDestroyDevice>(
- instance.drv.dispatch.GetDeviceProcAddr(drv_device,
- "vkDestroyDevice"));
- destroy_device(drv_device, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- // Set dispatch table for newly created Device
- // CreateDevice_Top will fill in the details
- drv_dispatch->vtbl = &device->dispatch;
- device->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
- instance.drv.dispatch.GetDeviceProcAddr(drv_device,
- "vkGetDeviceProcAddr"));
- *device_out = drv_device;
- return VK_SUCCESS;
-}
-
-void DestroyInstance_Bottom(VkInstance vkinstance,
- const VkAllocationCallbacks* allocator) {
- Instance& instance = GetDispatchParent(vkinstance);
-
- // These checks allow us to call DestroyInstance_Bottom from any error
- // path in CreateInstance_Bottom, before the driver instance is fully
- // initialized.
- if (instance.drv.instance != VK_NULL_HANDLE &&
- instance.drv.dispatch.DestroyInstance) {
- instance.drv.dispatch.DestroyInstance(instance.drv.instance, allocator);
- instance.drv.instance = VK_NULL_HANDLE;
- }
-}
-
-VkResult CreateSwapchainKHR_Disabled(VkDevice,
- const VkSwapchainCreateInfoKHR*,
- const VkAllocationCallbacks*,
- VkSwapchainKHR*) {
- ALOGE("VK_KHR_swapchain not enabled. vkCreateSwapchainKHR not executed.");
-
- return VK_SUCCESS;
-}
-
-void DestroySwapchainKHR_Disabled(VkDevice,
- VkSwapchainKHR,
- const VkAllocationCallbacks*) {
- ALOGE("VK_KHR_swapchain not enabled. vkDestroySwapchainKHR not executed.");
-}
-
-VkResult GetSwapchainImagesKHR_Disabled(VkDevice,
- VkSwapchainKHR,
- uint32_t*,
- VkImage*) {
- ALOGE(
- "VK_KHR_swapchain not enabled. vkGetSwapchainImagesKHR not executed.");
-
- return VK_SUCCESS;
-}
-
-VkResult AcquireNextImageKHR_Disabled(VkDevice,
- VkSwapchainKHR,
- uint64_t,
- VkSemaphore,
- VkFence,
- uint32_t*) {
- ALOGE("VK_KHR_swapchain not enabled. vkAcquireNextImageKHR not executed.");
-
- return VK_SUCCESS;
-}
-
-VkResult QueuePresentKHR_Disabled(VkQueue, const VkPresentInfoKHR*) {
- ALOGE("VK_KHR_swapchain not enabled. vkQueuePresentKHR not executed.");
-
- return VK_SUCCESS;
-}
-
-PFN_vkVoidFunction GetDeviceProcAddr_Bottom(VkDevice vkdevice,
- const char* name) {
- if (strcmp(name, "vkCreateDevice") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(CreateDevice_Bottom);
- }
-
- Device& device = GetDispatchParent(vkdevice);
- if (!device.enabled_extensions[kKHR_swapchain]) {
- if (strcmp(name, "vkCreateSwapchainKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- CreateSwapchainKHR_Disabled);
- }
- if (strcmp(name, "vkDestroySwapchainKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- DestroySwapchainKHR_Disabled);
- }
- if (strcmp(name, "vkGetSwapchainImagesKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- GetSwapchainImagesKHR_Disabled);
- }
- if (strcmp(name, "vkAcquireNextSwapchainImageKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- AcquireNextImageKHR_Disabled);
- }
- if (strcmp(name, "vkQueuePresentKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- QueuePresentKHR_Disabled);
- }
- }
-
- // VK_ANDROID_native_buffer should be hidden from applications and layers.
- // TODO(jessehall): Generate this as part of GetLoaderBottomProcAddr.
- PFN_vkVoidFunction pfn;
- if (strcmp(name, "vkGetSwapchainGrallocUsageANDROID") == 0 ||
- strcmp(name, "vkAcquireImageANDROID") == 0 ||
- strcmp(name, "vkQueueSignalReleaseImageANDROID") == 0) {
- return nullptr;
- }
- if ((pfn = GetLoaderBottomProcAddr(name)))
- return pfn;
- return GetDispatchParent(vkdevice).get_device_proc_addr(vkdevice, name);
-}
-
-// -----------------------------------------------------------------------------
-// Loader top functions. These are called directly from the loader entry
-// points or from the application (via vkGetInstanceProcAddr) without going
-// through a dispatch table.
-
-VkResult EnumerateInstanceExtensionProperties_Top(
- const char* layer_name,
- uint32_t* properties_count,
- VkExtensionProperties* properties) {
- if (!EnsureInitialized())
- return VK_ERROR_INITIALIZATION_FAILED;
-
- const VkExtensionProperties* extensions = nullptr;
- uint32_t num_extensions = 0;
- if (layer_name) {
- GetInstanceLayerExtensions(layer_name, &extensions, &num_extensions);
- } else {
- VkExtensionProperties* available = static_cast<VkExtensionProperties*>(
- alloca(kInstanceExtensionCount * sizeof(VkExtensionProperties)));
- available[num_extensions++] = VkExtensionProperties{
- VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION};
- available[num_extensions++] =
- VkExtensionProperties{VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
- VK_KHR_ANDROID_SURFACE_SPEC_VERSION};
- if (g_driver_instance_extensions[kEXT_debug_report]) {
- available[num_extensions++] =
- VkExtensionProperties{VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
- VK_EXT_DEBUG_REPORT_SPEC_VERSION};
- }
- // TODO(jessehall): We need to also enumerate extensions supported by
- // implicitly-enabled layers. Currently we don't have that list of
- // layers until instance creation.
- extensions = available;
- }
-
- if (!properties || *properties_count > num_extensions)
- *properties_count = num_extensions;
- if (properties)
- std::copy(extensions, extensions + *properties_count, properties);
- return *properties_count < num_extensions ? VK_INCOMPLETE : VK_SUCCESS;
-}
-
-VkResult EnumerateInstanceLayerProperties_Top(uint32_t* properties_count,
- VkLayerProperties* properties) {
- if (!EnsureInitialized())
- return VK_ERROR_INITIALIZATION_FAILED;
-
- uint32_t layer_count =
- EnumerateInstanceLayers(properties ? *properties_count : 0, properties);
- if (!properties || *properties_count > layer_count)
- *properties_count = layer_count;
- return *properties_count < layer_count ? VK_INCOMPLETE : VK_SUCCESS;
-}
-
-VKAPI_ATTR
-VkResult EnumerateDeviceExtensionProperties_Top(
- VkPhysicalDevice gpu,
- const char* layer_name,
- uint32_t* properties_count,
- VkExtensionProperties* properties) {
- const VkExtensionProperties* extensions = nullptr;
- uint32_t num_extensions = 0;
-
- ALOGV("EnumerateDeviceExtensionProperties_Top:");
- if (layer_name) {
- ALOGV(" layer %s", layer_name);
- GetDeviceLayerExtensions(layer_name, &extensions, &num_extensions);
- } else {
- ALOGV(" no layer");
- Instance& instance = GetDispatchParent(gpu);
- size_t gpu_idx = 0;
- while (instance.physical_devices_top[gpu_idx] != gpu)
- gpu_idx++;
- const DeviceExtensionSet driver_extensions =
- instance.physical_device_driver_extensions[gpu_idx];
-
- // We only support VK_KHR_swapchain if the GPU supports
- // VK_ANDROID_native_buffer
- VkExtensionProperties* available = static_cast<VkExtensionProperties*>(
- alloca(kDeviceExtensionCount * sizeof(VkExtensionProperties)));
- if (driver_extensions[kANDROID_native_buffer]) {
- available[num_extensions++] = VkExtensionProperties{
- VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_SPEC_VERSION};
- }
-
- // TODO(jessehall): We need to also enumerate extensions supported by
- // implicitly-enabled layers. Currently we don't have that list of
- // layers until instance creation.
- extensions = available;
- }
-
- ALOGV(" num: %d, extensions: %p", num_extensions, extensions);
- if (!properties || *properties_count > num_extensions)
- *properties_count = num_extensions;
- if (properties)
- std::copy(extensions, extensions + *properties_count, properties);
- return *properties_count < num_extensions ? VK_INCOMPLETE : VK_SUCCESS;
-}
-
-VkResult CreateInstance_Top(const VkInstanceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkInstance* instance_out) {
- VkResult result;
-
- if (!EnsureInitialized())
- return VK_ERROR_INITIALIZATION_FAILED;
-
- if (!allocator)
- allocator = &kDefaultAllocCallbacks;
-
- VkInstanceCreateInfo local_create_info = *create_info;
- create_info = &local_create_info;
-
- void* instance_mem = allocator->pfnAllocation(
- allocator->pUserData, sizeof(Instance), alignof(Instance),
- VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
- if (!instance_mem)
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- Instance* instance = new (instance_mem) Instance(allocator);
-
- result = ActivateAllLayers(create_info, instance, instance);
- if (result != VK_SUCCESS) {
- DestroyInstance(instance, allocator);
- return result;
- }
-
- uint32_t activated_layers = 0;
- VkLayerInstanceCreateInfo chain_info;
- VkLayerInstanceLink* layer_instance_link_info = nullptr;
- PFN_vkGetInstanceProcAddr next_gipa = GetInstanceProcAddr_Bottom;
- VkInstance local_instance = nullptr;
-
- if (instance->active_layers.size() > 0) {
- chain_info.u.pLayerInfo = nullptr;
- chain_info.pNext = create_info->pNext;
- chain_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
- chain_info.function = VK_LAYER_FUNCTION_LINK;
- local_create_info.pNext = &chain_info;
-
- layer_instance_link_info = static_cast<VkLayerInstanceLink*>(alloca(
- sizeof(VkLayerInstanceLink) * instance->active_layers.size()));
- if (!layer_instance_link_info) {
- ALOGE("Failed to alloc Instance objects for layers");
- DestroyInstance(instance, allocator);
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
-
- /* Create instance chain of enabled layers */
- for (auto rit = instance->active_layers.rbegin();
- rit != instance->active_layers.rend(); ++rit) {
- LayerRef& layer = *rit;
- layer_instance_link_info[activated_layers].pNext =
- chain_info.u.pLayerInfo;
- layer_instance_link_info[activated_layers]
- .pfnNextGetInstanceProcAddr = next_gipa;
- chain_info.u.pLayerInfo =
- &layer_instance_link_info[activated_layers];
- next_gipa = layer.GetGetInstanceProcAddr();
-
- ALOGV("Insert instance layer %s (v%u)", layer.GetName(),
- layer.GetSpecVersion());
-
- activated_layers++;
- }
- }
-
- PFN_vkCreateInstance create_instance =
- reinterpret_cast<PFN_vkCreateInstance>(
- next_gipa(VK_NULL_HANDLE, "vkCreateInstance"));
- if (!create_instance) {
- DestroyInstance(instance, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- VkLayerInstanceCreateInfo instance_create_info;
-
- instance_create_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
- instance_create_info.function = VK_LAYER_FUNCTION_INSTANCE;
-
- instance_create_info.u.instanceInfo.instance_info = instance;
- instance_create_info.u.instanceInfo.pfnNextGetInstanceProcAddr = next_gipa;
-
- instance_create_info.pNext = local_create_info.pNext;
- local_create_info.pNext = &instance_create_info;
-
- // Force enable callback extension if required
- bool enable_callback = false;
- if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
- enable_callback =
- property_get_bool("debug.vulkan.enable_callback", false);
- if (enable_callback) {
- if (!AddExtensionToCreateInfo(local_create_info,
- "VK_EXT_debug_report", allocator)) {
- DestroyInstance(instance, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- }
- }
- bool allocatedLayerMem;
- if (!AddLayersToCreateInfo(local_create_info, instance, allocator,
- allocatedLayerMem)) {
- if (enable_callback) {
- FreeAllocatedExtensionCreateInfo(local_create_info, allocator);
- }
- DestroyInstance(instance, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- result = create_instance(&local_create_info, allocator, &local_instance);
-
- if (allocatedLayerMem) {
- FreeAllocatedLayerCreateInfo(local_create_info, allocator);
- }
- if (enable_callback) {
- FreeAllocatedExtensionCreateInfo(local_create_info, allocator);
- }
-
- if (result != VK_SUCCESS) {
- DestroyInstance(instance, allocator);
- return result;
- }
-
- const InstanceDispatchTable& instance_dispatch =
- GetDispatchTable(local_instance);
- if (!LoadInstanceDispatchTable(
- local_instance, next_gipa,
- const_cast<InstanceDispatchTable&>(instance_dispatch))) {
- ALOGV("Failed to initialize instance dispatch table");
- PFN_vkDestroyInstance destroy_instance =
- reinterpret_cast<PFN_vkDestroyInstance>(
- next_gipa(local_instance, "vkDestroyInstance"));
- if (!destroy_instance) {
- ALOGD("Loader unable to find DestroyInstance");
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- destroy_instance(local_instance, allocator);
- DestroyInstance(instance, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- // Capture the physical devices from the top of the
- // chain in case it has been wrapped by a layer.
- uint32_t num_physical_devices = 0;
- result = instance_dispatch.EnumeratePhysicalDevices(
- local_instance, &num_physical_devices, nullptr);
- if (result != VK_SUCCESS) {
- DestroyInstance(instance, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
- result = instance_dispatch.EnumeratePhysicalDevices(
- local_instance, &num_physical_devices,
- instance->physical_devices_top);
- if (result != VK_SUCCESS) {
- DestroyInstance(instance, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- *instance_out = local_instance;
-
- if (enable_callback) {
- const VkDebugReportCallbackCreateInfoEXT callback_create_info = {
- .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
- .flags =
- VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT,
- .pfnCallback = LogDebugMessageCallback,
- };
- PFN_vkCreateDebugReportCallbackEXT create_debug_report_callback =
- reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
- GetInstanceProcAddr_Top(instance->handle,
- "vkCreateDebugReportCallbackEXT"));
- create_debug_report_callback(instance->handle, &callback_create_info,
- allocator, &instance->message);
- }
-
- return result;
-}
-
-PFN_vkVoidFunction GetInstanceProcAddr_Top(VkInstance vkinstance,
- const char* name) {
- // vkGetInstanceProcAddr(NULL_HANDLE, ..) only works for global commands
- if (!vkinstance)
- return GetLoaderGlobalProcAddr(name);
-
- const InstanceDispatchTable& dispatch = GetDispatchTable(vkinstance);
- PFN_vkVoidFunction pfn;
- // Always go through the loader-top function if there is one.
- if ((pfn = GetLoaderTopProcAddr(name)))
- return pfn;
- // Otherwise, look up the handler in the instance dispatch table
- if ((pfn = GetDispatchProcAddr(dispatch, name)))
- return pfn;
- // Anything not handled already must be a device-dispatched function
- // without a loader-top. We must return a function that will dispatch based
- // on the dispatchable object parameter -- which is exactly what the
- // exported functions do. So just return them here.
- return GetLoaderExportProcAddr(name);
-}
-
-void DestroyInstance_Top(VkInstance vkinstance,
- const VkAllocationCallbacks* allocator) {
- if (!vkinstance)
- return;
- if (!allocator)
- allocator = &kDefaultAllocCallbacks;
- GetDispatchTable(vkinstance).DestroyInstance(vkinstance, allocator);
- DestroyInstance(&(GetDispatchParent(vkinstance)), allocator);
-}
-
-VKAPI_ATTR
-VkResult EnumerateDeviceLayerProperties_Top(VkPhysicalDevice /*pdev*/,
- uint32_t* properties_count,
- VkLayerProperties* properties) {
- uint32_t layer_count =
- EnumerateDeviceLayers(properties ? *properties_count : 0, properties);
- if (!properties || *properties_count > layer_count)
- *properties_count = layer_count;
- return *properties_count < layer_count ? VK_INCOMPLETE : VK_SUCCESS;
-}
-
-VKAPI_ATTR
-VkResult CreateDevice_Top(VkPhysicalDevice gpu,
- const VkDeviceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkDevice* device_out) {
- Instance& instance = GetDispatchParent(gpu);
- VkResult result;
-
- // FIXME(jessehall): We don't have good conventions or infrastructure yet to
- // do better than just using the instance allocator and scope for
- // everything. See b/26732122.
- if (true /*!allocator*/)
- allocator = instance.alloc;
-
- void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Device),
- alignof(Device),
- VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
- if (!mem)
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- Device* device = new (mem) Device(&instance);
-
- result = ActivateAllLayers(create_info, &instance, device);
- if (result != VK_SUCCESS) {
- DestroyDevice(device);
- return result;
- }
-
- uint32_t activated_layers = 0;
- VkLayerDeviceCreateInfo chain_info;
- VkLayerDeviceLink* layer_device_link_info = nullptr;
- PFN_vkGetInstanceProcAddr next_gipa = GetInstanceProcAddr_Bottom;
- PFN_vkGetDeviceProcAddr next_gdpa = GetDeviceProcAddr_Bottom;
- VkDeviceCreateInfo local_create_info = *create_info;
- VkDevice local_device = nullptr;
-
- if (device->active_layers.size() > 0) {
- chain_info.u.pLayerInfo = nullptr;
- chain_info.pNext = local_create_info.pNext;
- chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
- chain_info.function = VK_LAYER_FUNCTION_LINK;
- local_create_info.pNext = &chain_info;
-
- layer_device_link_info = static_cast<VkLayerDeviceLink*>(
- alloca(sizeof(VkLayerDeviceLink) * device->active_layers.size()));
- if (!layer_device_link_info) {
- ALOGE("Failed to alloc Device objects for layers");
- DestroyDevice(device);
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
-
- /* Create device chain of enabled layers */
- for (auto rit = device->active_layers.rbegin();
- rit != device->active_layers.rend(); ++rit) {
- LayerRef& layer = *rit;
- layer_device_link_info[activated_layers].pNext =
- chain_info.u.pLayerInfo;
- layer_device_link_info[activated_layers].pfnNextGetDeviceProcAddr =
- next_gdpa;
- layer_device_link_info[activated_layers]
- .pfnNextGetInstanceProcAddr = next_gipa;
- chain_info.u.pLayerInfo = &layer_device_link_info[activated_layers];
-
- next_gipa = layer.GetGetInstanceProcAddr();
- next_gdpa = layer.GetGetDeviceProcAddr();
-
- ALOGV("Insert device layer %s (v%u)", layer.GetName(),
- layer.GetSpecVersion());
-
- activated_layers++;
- }
- }
-
- PFN_vkCreateDevice create_device = reinterpret_cast<PFN_vkCreateDevice>(
- next_gipa(instance.handle, "vkCreateDevice"));
- if (!create_device) {
- ALOGE("Unable to find vkCreateDevice for driver");
- DestroyDevice(device);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- VkLayerDeviceCreateInfo device_create_info;
-
- device_create_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
- device_create_info.function = VK_LAYER_FUNCTION_DEVICE;
-
- device_create_info.u.deviceInfo.device_info = device;
- device_create_info.u.deviceInfo.pfnNextGetInstanceProcAddr = next_gipa;
-
- device_create_info.pNext = local_create_info.pNext;
- local_create_info.pNext = &device_create_info;
-
- bool allocatedLayerMem;
- if (!AddLayersToCreateInfo(local_create_info, device, allocator,
- allocatedLayerMem)) {
- DestroyDevice(device);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- result = create_device(gpu, &local_create_info, allocator, &local_device);
-
- if (allocatedLayerMem) {
- FreeAllocatedLayerCreateInfo(local_create_info, allocator);
- }
-
- if (result != VK_SUCCESS) {
- DestroyDevice(device);
- return result;
- }
-
- // Set dispatch table for newly created Device
- hwvulkan_dispatch_t* vulkan_dispatch =
- reinterpret_cast<hwvulkan_dispatch_t*>(local_device);
- vulkan_dispatch->vtbl = &device->dispatch;
-
- const DeviceDispatchTable& device_dispatch = GetDispatchTable(local_device);
- if (!LoadDeviceDispatchTable(
- local_device, next_gdpa,
- const_cast<DeviceDispatchTable&>(device_dispatch))) {
- ALOGV("Failed to initialize device dispatch table");
- PFN_vkDestroyDevice destroy_device =
- reinterpret_cast<PFN_vkDestroyDevice>(
- next_gipa(instance.handle, "vkDestroyDevice"));
- ALOG_ASSERT(destroy_device != nullptr,
- "Loader unable to find DestroyDevice");
- destroy_device(local_device, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- *device_out = local_device;
-
- return VK_SUCCESS;
-}
-
-PFN_vkVoidFunction GetDeviceProcAddr_Top(VkDevice device, const char* name) {
- PFN_vkVoidFunction pfn;
- if (!device)
- return nullptr;
- if ((pfn = GetLoaderTopProcAddr(name)))
- return pfn;
- return GetDispatchProcAddr(GetDispatchTable(device), name);
-}
-
-void GetDeviceQueue_Top(VkDevice vkdevice,
- uint32_t family,
- uint32_t index,
- VkQueue* queue_out) {
- const auto& table = GetDispatchTable(vkdevice);
- table.GetDeviceQueue(vkdevice, family, index, queue_out);
- hwvulkan_dispatch_t* queue_dispatch =
- reinterpret_cast<hwvulkan_dispatch_t*>(*queue_out);
- if (queue_dispatch->magic != HWVULKAN_DISPATCH_MAGIC &&
- queue_dispatch->vtbl != &table)
- ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR,
- queue_dispatch->magic);
- queue_dispatch->vtbl = &table;
-}
-
-VkResult AllocateCommandBuffers_Top(
- VkDevice vkdevice,
- const VkCommandBufferAllocateInfo* alloc_info,
- VkCommandBuffer* cmdbufs) {
- const auto& table = GetDispatchTable(vkdevice);
- VkResult result =
- table.AllocateCommandBuffers(vkdevice, alloc_info, cmdbufs);
- if (result != VK_SUCCESS)
- return result;
- for (uint32_t i = 0; i < alloc_info->commandBufferCount; i++) {
- hwvulkan_dispatch_t* cmdbuf_dispatch =
- reinterpret_cast<hwvulkan_dispatch_t*>(cmdbufs[i]);
- ALOGE_IF(cmdbuf_dispatch->magic != HWVULKAN_DISPATCH_MAGIC,
- "invalid VkCommandBuffer dispatch magic: 0x%" PRIxPTR,
- cmdbuf_dispatch->magic);
- cmdbuf_dispatch->vtbl = &table;
- }
- return VK_SUCCESS;
-}
-
-void DestroyDevice_Top(VkDevice vkdevice,
- const VkAllocationCallbacks* /*allocator*/) {
- if (!vkdevice)
- return;
- Device& device = GetDispatchParent(vkdevice);
- device.dispatch.DestroyDevice(vkdevice, device.instance->alloc);
- DestroyDevice(&device);
-}
-
-// -----------------------------------------------------------------------------
-
-const VkAllocationCallbacks* GetAllocator(VkInstance vkinstance) {
- return GetDispatchParent(vkinstance).alloc;
-}
-
-const VkAllocationCallbacks* GetAllocator(VkDevice vkdevice) {
- return GetDispatchParent(vkdevice).instance->alloc;
-}
-
-VkInstance GetDriverInstance(VkInstance instance) {
- return GetDispatchParent(instance).drv.instance;
-}
-
-const DriverDispatchTable& GetDriverDispatch(VkInstance instance) {
- return GetDispatchParent(instance).drv.dispatch;
-}
-
-const DriverDispatchTable& GetDriverDispatch(VkDevice device) {
- return GetDispatchParent(device).instance->drv.dispatch;
-}
-
-const DriverDispatchTable& GetDriverDispatch(VkQueue queue) {
- return GetDispatchParent(queue).instance->drv.dispatch;
-}
-
-DebugReportCallbackList& GetDebugReportCallbacks(VkInstance instance) {
- return GetDispatchParent(instance).debug_report_callbacks;
-}
-
-} // namespace vulkan
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
deleted file mode 100644
index ada66f1..0000000
--- a/vulkan/libvulkan/loader.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LIBVULKAN_LOADER_H
-#define LIBVULKAN_LOADER_H 1
-
-#include <bitset>
-#include "dispatch_gen.h"
-#include "debug_report.h"
-
-namespace vulkan {
-
-enum InstanceExtension {
- kKHR_surface,
- kKHR_android_surface,
- kEXT_debug_report,
- kInstanceExtensionCount
-};
-typedef std::bitset<kInstanceExtensionCount> InstanceExtensionSet;
-
-enum DeviceExtension {
- kKHR_swapchain,
- kANDROID_native_buffer,
- kDeviceExtensionCount
-};
-typedef std::bitset<kDeviceExtensionCount> DeviceExtensionSet;
-
-inline const InstanceDispatchTable& GetDispatchTable(VkInstance instance) {
- return **reinterpret_cast<InstanceDispatchTable**>(instance);
-}
-
-inline const InstanceDispatchTable& GetDispatchTable(
- VkPhysicalDevice physical_device) {
- return **reinterpret_cast<InstanceDispatchTable**>(physical_device);
-}
-
-inline const DeviceDispatchTable& GetDispatchTable(VkDevice device) {
- return **reinterpret_cast<DeviceDispatchTable**>(device);
-}
-
-inline const DeviceDispatchTable& GetDispatchTable(VkQueue queue) {
- return **reinterpret_cast<DeviceDispatchTable**>(queue);
-}
-
-inline const DeviceDispatchTable& GetDispatchTable(
- VkCommandBuffer command_buffer) {
- return **reinterpret_cast<DeviceDispatchTable**>(command_buffer);
-}
-
-// -----------------------------------------------------------------------------
-// dispatch_gen.cpp
-
-PFN_vkVoidFunction GetLoaderExportProcAddr(const char* name);
-PFN_vkVoidFunction GetLoaderGlobalProcAddr(const char* name);
-PFN_vkVoidFunction GetLoaderTopProcAddr(const char* name);
-PFN_vkVoidFunction GetLoaderBottomProcAddr(const char* name);
-PFN_vkVoidFunction GetDispatchProcAddr(const InstanceDispatchTable& dispatch,
- const char* name);
-PFN_vkVoidFunction GetDispatchProcAddr(const DeviceDispatchTable& dispatch,
- const char* name);
-bool LoadInstanceDispatchTable(VkInstance instance,
- PFN_vkGetInstanceProcAddr get_proc_addr,
- InstanceDispatchTable& dispatch);
-bool LoadDeviceDispatchTable(VkDevice device,
- PFN_vkGetDeviceProcAddr get_proc_addr,
- DeviceDispatchTable& dispatch);
-bool LoadDriverDispatchTable(VkInstance instance,
- PFN_vkGetInstanceProcAddr get_proc_addr,
- const InstanceExtensionSet& extensions,
- DriverDispatchTable& dispatch);
-
-// -----------------------------------------------------------------------------
-// loader.cpp
-
-// clang-format off
-VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties_Top(const char* layer_name, uint32_t* count, VkExtensionProperties* properties);
-VKAPI_ATTR VkResult EnumerateInstanceLayerProperties_Top(uint32_t* count, VkLayerProperties* properties);
-VKAPI_ATTR VkResult CreateInstance_Top(const VkInstanceCreateInfo* create_info, const VkAllocationCallbacks* allocator, VkInstance* instance_out);
-VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr_Top(VkInstance instance, const char* name);
-VKAPI_ATTR void DestroyInstance_Top(VkInstance instance, const VkAllocationCallbacks* allocator);
-VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr_Top(VkDevice drv_device, const char* name);
-VKAPI_ATTR void GetDeviceQueue_Top(VkDevice drv_device, uint32_t family, uint32_t index, VkQueue* out_queue);
-VKAPI_ATTR VkResult AllocateCommandBuffers_Top(VkDevice device, const VkCommandBufferAllocateInfo* alloc_info, VkCommandBuffer* cmdbufs);
-VKAPI_ATTR VkResult EnumerateDeviceLayerProperties_Top(VkPhysicalDevice pdev, uint32_t* properties_count, VkLayerProperties* properties);
-VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties_Top(VkPhysicalDevice pdev, const char * layer_name, uint32_t* properties_count, VkExtensionProperties* properties);
-VKAPI_ATTR VkResult CreateDevice_Top(VkPhysicalDevice pdev, const VkDeviceCreateInfo* create_info, const VkAllocationCallbacks* allocator, VkDevice* device_out);
-VKAPI_ATTR void DestroyDevice_Top(VkDevice drv_device, const VkAllocationCallbacks* allocator);
-
-VKAPI_ATTR VkResult CreateInstance_Bottom(const VkInstanceCreateInfo* create_info, const VkAllocationCallbacks* allocator, VkInstance* vkinstance);
-VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr_Bottom(VkInstance, const char* name);
-VKAPI_ATTR VkResult EnumeratePhysicalDevices_Bottom(VkInstance vkinstance, uint32_t* pdev_count, VkPhysicalDevice* pdevs);
-VKAPI_ATTR void GetPhysicalDeviceProperties_Bottom(VkPhysicalDevice pdev, VkPhysicalDeviceProperties* properties);
-VKAPI_ATTR void GetPhysicalDeviceFeatures_Bottom(VkPhysicalDevice pdev, VkPhysicalDeviceFeatures* features);
-VKAPI_ATTR void GetPhysicalDeviceMemoryProperties_Bottom(VkPhysicalDevice pdev, VkPhysicalDeviceMemoryProperties* properties);
-VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties_Bottom(VkPhysicalDevice pdev, uint32_t* properties_count, VkQueueFamilyProperties* properties);
-VKAPI_ATTR void GetPhysicalDeviceFormatProperties_Bottom(VkPhysicalDevice pdev, VkFormat format, VkFormatProperties* properties);
-VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties_Bottom(VkPhysicalDevice pdev, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* properties);
-VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties_Bottom(VkPhysicalDevice pdev, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* properties_count, VkSparseImageFormatProperties* properties);
-VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties_Bottom(VkPhysicalDevice pdev, const char* layer_name, uint32_t* properties_count, VkExtensionProperties* properties);
-VKAPI_ATTR VkResult EnumerateDeviceLayerProperties_Bottom(VkPhysicalDevice pdev, uint32_t* properties_count, VkLayerProperties* properties);
-VKAPI_ATTR VkResult CreateDevice_Bottom(VkPhysicalDevice pdev, const VkDeviceCreateInfo* create_info, const VkAllocationCallbacks* allocator, VkDevice* device_out);
-VKAPI_ATTR void DestroyInstance_Bottom(VkInstance vkinstance, const VkAllocationCallbacks* allocator);
-VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr_Bottom(VkDevice vkdevice, const char* name);
-// clang-format on
-
-const VkAllocationCallbacks* GetAllocator(VkInstance instance);
-const VkAllocationCallbacks* GetAllocator(VkDevice device);
-VkInstance GetDriverInstance(VkInstance instance);
-const DriverDispatchTable& GetDriverDispatch(VkInstance instance);
-const DriverDispatchTable& GetDriverDispatch(VkDevice device);
-const DriverDispatchTable& GetDriverDispatch(VkQueue queue);
-DebugReportCallbackList& GetDebugReportCallbacks(VkInstance instance);
-
-// -----------------------------------------------------------------------------
-// swapchain.cpp
-
-// clang-format off
-VKAPI_ATTR VkResult CreateAndroidSurfaceKHR_Bottom(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
-VKAPI_ATTR void DestroySurfaceKHR_Bottom(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* allocator);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceSupportKHR_Bottom(VkPhysicalDevice pdev, uint32_t queue_family, VkSurfaceKHR surface, VkBool32* pSupported);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR_Bottom(VkPhysicalDevice pdev, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* capabilities);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormatsKHR_Bottom(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkSurfaceFormatKHR* formats);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfacePresentModesKHR_Bottom(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkPresentModeKHR* modes);
-VKAPI_ATTR VkResult CreateSwapchainKHR_Bottom(VkDevice device, const VkSwapchainCreateInfoKHR* create_info, const VkAllocationCallbacks* allocator, VkSwapchainKHR* swapchain_handle);
-VKAPI_ATTR void DestroySwapchainKHR_Bottom(VkDevice device, VkSwapchainKHR swapchain_handle, const VkAllocationCallbacks* allocator);
-VKAPI_ATTR VkResult GetSwapchainImagesKHR_Bottom(VkDevice device, VkSwapchainKHR swapchain_handle, uint32_t* count, VkImage* images);
-VKAPI_ATTR VkResult AcquireNextImageKHR_Bottom(VkDevice device, VkSwapchainKHR swapchain_handle, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* image_index);
-VKAPI_ATTR VkResult QueuePresentKHR_Bottom(VkQueue queue, const VkPresentInfoKHR* present_info);
-
-VKAPI_ATTR VkResult CreateAndroidSurfaceKHR_Disabled(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
-VKAPI_ATTR void DestroySurfaceKHR_Disabled(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks*);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceSupportKHR_Disabled(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32*);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR_Disabled(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR*);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormatsKHR_Disabled(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkSurfaceFormatKHR*);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfacePresentModesKHR_Disabled(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkPresentModeKHR*);
-VKAPI_ATTR VkResult CreateSwapchainKHR_Disabled(VkDevice device, const VkSwapchainCreateInfoKHR* create_info, const VkAllocationCallbacks* allocator, VkSwapchainKHR* swapchain_handle);
-VKAPI_ATTR void DestroySwapchainKHR_Disabled(VkDevice device, VkSwapchainKHR swapchain_handle, const VkAllocationCallbacks* allocator);
-VKAPI_ATTR VkResult GetSwapchainImagesKHR_Disabled(VkDevice device, VkSwapchainKHR swapchain_handle, uint32_t* count, VkImage* images);
-VKAPI_ATTR VkResult AcquireNextImageKHR_Disabled(VkDevice device, VkSwapchainKHR swapchain_handle, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* image_index);
-VKAPI_ATTR VkResult QueuePresentKHR_Disabled(VkQueue queue, const VkPresentInfoKHR* present_info);
-// clang-format on
-
-// -----------------------------------------------------------------------------
-// layers_extensions.cpp
-
-struct Layer;
-class LayerRef {
- public:
- LayerRef(Layer* layer);
- LayerRef(LayerRef&& other);
- ~LayerRef();
- LayerRef(const LayerRef&) = delete;
- LayerRef& operator=(const LayerRef&) = delete;
-
- const char* GetName() const;
- uint32_t GetSpecVersion();
-
- // provides bool-like behavior
- operator const Layer*() const { return layer_; }
-
- PFN_vkGetInstanceProcAddr GetGetInstanceProcAddr() const;
- PFN_vkGetDeviceProcAddr GetGetDeviceProcAddr() const;
-
- bool SupportsExtension(const char* name) const;
-
- private:
- Layer* layer_;
-};
-
-void DiscoverLayers();
-uint32_t EnumerateInstanceLayers(uint32_t count, VkLayerProperties* properties);
-uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties);
-void GetInstanceLayerExtensions(const char* name,
- const VkExtensionProperties** properties,
- uint32_t* count);
-void GetDeviceLayerExtensions(const char* name,
- const VkExtensionProperties** properties,
- uint32_t* count);
-LayerRef GetInstanceLayerRef(const char* name);
-LayerRef GetDeviceLayerRef(const char* name);
-
-InstanceExtension InstanceExtensionFromName(const char* name);
-DeviceExtension DeviceExtensionFromName(const char* name);
-
-} // namespace vulkan
-
-#endif // LIBVULKAN_LOADER_H
diff --git a/vulkan/libvulkan/stubhal.cpp b/vulkan/libvulkan/stubhal.cpp
new file mode 100644
index 0000000..a74d370
--- /dev/null
+++ b/vulkan/libvulkan/stubhal.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* NOTE:
+ * This stub HAL is only used internally by the loader when a real HAL
+ * implementation is not present, in order to avoid needing "null HAL" checks
+ * throughout the loader. It does not enumerate any physical devices, and is
+ * only as conformant to the Vulkan and Android HAL interfaces as the loader
+ * needs it to be. Do not use it as an example of a correct implementation; the
+ * code in ../null_driver is better for that.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "vkstub"
+
+#include <array>
+#include <bitset>
+#include <mutex>
+#include <hardware/hwvulkan.h>
+#include <log/log.h>
+#include "stubhal.h"
+
+namespace vulkan {
+namespace stubhal {
+
+namespace {
+
+const size_t kMaxInstances = 32;
+static std::mutex g_instance_mutex;
+static std::bitset<kMaxInstances> g_instance_used(false);
+static std::array<hwvulkan_dispatch_t, kMaxInstances> g_instances;
+
+[[noreturn]] void NoOp() {
+ LOG_ALWAYS_FATAL("invalid stub function called");
+}
+
+VKAPI_ATTR VkResult
+EnumerateInstanceExtensionProperties(const char* /*layer_name*/,
+ uint32_t* count,
+ VkExtensionProperties* /*properties*/) {
+ *count = 0;
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult
+EnumerateInstanceLayerProperties(uint32_t* count,
+ VkLayerProperties* /*properties*/) {
+ *count = 0;
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* /*create_info*/,
+ const VkAllocationCallbacks* /*allocator*/,
+ VkInstance* instance) {
+ std::lock_guard<std::mutex> lock(g_instance_mutex);
+ for (size_t i = 0; i < kMaxInstances; i++) {
+ if (!g_instance_used[i]) {
+ g_instance_used[i] = true;
+ g_instances[i].magic = HWVULKAN_DISPATCH_MAGIC;
+ *instance = reinterpret_cast<VkInstance>(&g_instances[i]);
+ return VK_SUCCESS;
+ }
+ }
+ ALOGE("no more instances available (max=%zu)", kMaxInstances);
+ return VK_ERROR_INITIALIZATION_FAILED;
+}
+
+VKAPI_ATTR void DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* /*allocator*/) {
+ std::lock_guard<std::mutex> lock(g_instance_mutex);
+ ssize_t idx =
+ reinterpret_cast<hwvulkan_dispatch_t*>(instance) - &g_instances[0];
+ ALOG_ASSERT(idx >= 0 && static_cast<size_t>(idx) < g_instance_used.size(),
+ "DestroyInstance: invalid instance handle");
+ g_instance_used[static_cast<size_t>(idx)] = false;
+}
+
+VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance /*instance*/,
+ uint32_t* count,
+ VkPhysicalDevice* /*gpus*/) {
+ *count = 0;
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance /*instance*/,
+ const char* name) {
+ if (strcmp(name, "vkCreateInstance") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
+ if (strcmp(name, "vkDestroyInstance") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
+ if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(
+ EnumerateInstanceExtensionProperties);
+ if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
+ if (strcmp(name, "vkGetInstanceProcAddr") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
+
+ // None of the other Vulkan functions should ever be called, as they all
+ // take a VkPhysicalDevice or other object obtained from a physical device.
+ return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
+}
+
+} // anonymous namespace
+
+const hwvulkan_device_t kDevice = {
+ .common =
+ {
+ .tag = HARDWARE_DEVICE_TAG,
+ .version = HWVULKAN_DEVICE_API_VERSION_0_1,
+ .module = nullptr,
+ .close = nullptr,
+ },
+ .EnumerateInstanceExtensionProperties =
+ EnumerateInstanceExtensionProperties,
+ .CreateInstance = CreateInstance,
+ .GetInstanceProcAddr = GetInstanceProcAddr,
+};
+
+} // namespace stubhal
+} // namespace vulkan
diff --git a/vulkan/libvulkan/stubhal.h b/vulkan/libvulkan/stubhal.h
new file mode 100644
index 0000000..9ba7d04
--- /dev/null
+++ b/vulkan/libvulkan/stubhal.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LIBVULKAN_STUBHAL_H
+#define LIBVULKAN_STUBHAL_H 1
+
+struct hwvulkan_device_t;
+
+namespace vulkan {
+namespace stubhal {
+
+extern const hwvulkan_device_t kDevice;
+
+} // namespace stubhal
+} // namespace vulkan
+
+#endif // LIBVULKAN_STUBHAL_H
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 7f944cf..69e8e84 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -15,98 +15,23 @@
*/
#include <algorithm>
-#include <memory>
#include <gui/BufferQueue.h>
#include <log/log.h>
#include <sync/sync.h>
+#include <utils/StrongPointer.h>
-#include "loader.h"
-
-using namespace vulkan;
+#include "driver.h"
// TODO(jessehall): Currently we don't have a good error code for when a native
// window operation fails. Just returning INITIALIZATION_FAILED for now. Later
// versions (post SDK 0.9) of the API/extension have a better error code.
// When updating to that version, audit all error returns.
+namespace vulkan {
+namespace driver {
namespace {
-// ----------------------------------------------------------------------------
-// These functions/classes form an adaptor that allows objects to be refcounted
-// by both android::sp<> and std::shared_ptr<> simultaneously, and delegates
-// allocation of the shared_ptr<> control structure to VkAllocationCallbacks.
-// The
-// platform holds a reference to the ANativeWindow using its embedded reference
-// count, and the ANativeWindow implementation holds references to the
-// ANativeWindowBuffers using their embedded reference counts, so the
-// shared_ptr *must* cooperate with these and hold at least one reference to
-// the object using the embedded reference count.
-
-template <typename T>
-struct NativeBaseDeleter {
- void operator()(T* obj) { obj->common.decRef(&obj->common); }
-};
-
-template <typename Host>
-struct AllocScope {};
-
-template <>
-struct AllocScope<VkInstance> {
- static const VkSystemAllocationScope kScope =
- VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE;
-};
-
-template <>
-struct AllocScope<VkDevice> {
- static const VkSystemAllocationScope kScope =
- VK_SYSTEM_ALLOCATION_SCOPE_DEVICE;
-};
-
-template <typename T>
-class VulkanAllocator {
- public:
- typedef T value_type;
-
- VulkanAllocator(const VkAllocationCallbacks& allocator,
- VkSystemAllocationScope scope)
- : allocator_(allocator), scope_(scope) {}
-
- template <typename U>
- explicit VulkanAllocator(const VulkanAllocator<U>& other)
- : allocator_(other.allocator_), scope_(other.scope_) {}
-
- T* allocate(size_t n) const {
- T* p = static_cast<T*>(allocator_.pfnAllocation(
- allocator_.pUserData, n * sizeof(T), alignof(T), scope_));
- if (!p)
- throw std::bad_alloc();
- return p;
- }
- void deallocate(T* p, size_t) const noexcept {
- return allocator_.pfnFree(allocator_.pUserData, p);
- }
-
- private:
- template <typename U>
- friend class VulkanAllocator;
- const VkAllocationCallbacks& allocator_;
- const VkSystemAllocationScope scope_;
-};
-
-template <typename T, typename Host>
-std::shared_ptr<T> InitSharedPtr(Host host, T* obj) {
- try {
- obj->common.incRef(&obj->common);
- return std::shared_ptr<T>(
- obj, NativeBaseDeleter<T>(),
- VulkanAllocator<T>(*GetAllocator(host), AllocScope<Host>::kScope));
- } catch (std::bad_alloc&) {
- obj->common.decRef(&obj->common);
- return nullptr;
- }
-}
-
const VkSurfaceTransformFlagsKHR kSupportedTransforms =
VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR |
VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
@@ -183,7 +108,7 @@
// ----------------------------------------------------------------------------
struct Surface {
- std::shared_ptr<ANativeWindow> window;
+ android::sp<ANativeWindow> window;
};
VkSurfaceKHR HandleFromSurface(Surface* surface) {
@@ -204,7 +129,7 @@
struct Image {
Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {}
VkImage image;
- std::shared_ptr<ANativeWindowBuffer> buffer;
+ android::sp<ANativeWindowBuffer> buffer;
// The fence is only valid when the buffer is dequeued, and should be
// -1 any other time. When valid, we own the fd, and must ensure it is
// closed: either by closing it explicitly when queueing the buffer,
@@ -224,16 +149,14 @@
} // anonymous namespace
-namespace vulkan {
-
VKAPI_ATTR
-VkResult CreateAndroidSurfaceKHR_Bottom(
+VkResult CreateAndroidSurfaceKHR(
VkInstance instance,
const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* out_surface) {
if (!allocator)
- allocator = GetAllocator(instance);
+ allocator = &GetData(instance).allocator;
void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Surface),
alignof(Surface),
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
@@ -241,13 +164,7 @@
return VK_ERROR_OUT_OF_HOST_MEMORY;
Surface* surface = new (mem) Surface;
- surface->window = InitSharedPtr(instance, pCreateInfo->window);
- if (!surface->window) {
- ALOGE("surface creation failed: out of memory");
- surface->~Surface();
- allocator->pfnFree(allocator->pUserData, surface);
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
+ surface->window = pCreateInfo->window;
// TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN.
int err =
@@ -267,30 +184,30 @@
}
VKAPI_ATTR
-void DestroySurfaceKHR_Bottom(VkInstance instance,
- VkSurfaceKHR surface_handle,
- const VkAllocationCallbacks* allocator) {
+void DestroySurfaceKHR(VkInstance instance,
+ VkSurfaceKHR surface_handle,
+ const VkAllocationCallbacks* allocator) {
Surface* surface = SurfaceFromHandle(surface_handle);
if (!surface)
return;
native_window_api_disconnect(surface->window.get(), NATIVE_WINDOW_API_EGL);
surface->~Surface();
if (!allocator)
- allocator = GetAllocator(instance);
+ allocator = &GetData(instance).allocator;
allocator->pfnFree(allocator->pUserData, surface);
}
VKAPI_ATTR
-VkResult GetPhysicalDeviceSurfaceSupportKHR_Bottom(VkPhysicalDevice /*pdev*/,
- uint32_t /*queue_family*/,
- VkSurfaceKHR /*surface*/,
- VkBool32* supported) {
+VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
+ uint32_t /*queue_family*/,
+ VkSurfaceKHR /*surface*/,
+ VkBool32* supported) {
*supported = VK_TRUE;
return VK_SUCCESS;
}
VKAPI_ATTR
-VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR_Bottom(
+VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(
VkPhysicalDevice /*pdev*/,
VkSurfaceKHR surface,
VkSurfaceCapabilitiesKHR* capabilities) {
@@ -357,11 +274,10 @@
}
VKAPI_ATTR
-VkResult GetPhysicalDeviceSurfaceFormatsKHR_Bottom(
- VkPhysicalDevice /*pdev*/,
- VkSurfaceKHR /*surface*/,
- uint32_t* count,
- VkSurfaceFormatKHR* formats) {
+VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice /*pdev*/,
+ VkSurfaceKHR /*surface*/,
+ uint32_t* count,
+ VkSurfaceFormatKHR* formats) {
// TODO(jessehall): Fill out the set of supported formats. Longer term, add
// a new gralloc method to query whether a (format, usage) pair is
// supported, and check that for each gralloc format that corresponds to a
@@ -386,11 +302,10 @@
}
VKAPI_ATTR
-VkResult GetPhysicalDeviceSurfacePresentModesKHR_Bottom(
- VkPhysicalDevice /*pdev*/,
- VkSurfaceKHR /*surface*/,
- uint32_t* count,
- VkPresentModeKHR* modes) {
+VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice /*pdev*/,
+ VkSurfaceKHR /*surface*/,
+ uint32_t* count,
+ VkPresentModeKHR* modes) {
const VkPresentModeKHR kModes[] = {
VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR,
};
@@ -407,15 +322,26 @@
}
VKAPI_ATTR
-VkResult CreateSwapchainKHR_Bottom(VkDevice device,
- const VkSwapchainCreateInfoKHR* create_info,
- const VkAllocationCallbacks* allocator,
- VkSwapchainKHR* swapchain_handle) {
+VkResult CreateSwapchainKHR(VkDevice device,
+ const VkSwapchainCreateInfoKHR* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkSwapchainKHR* swapchain_handle) {
int err;
VkResult result = VK_SUCCESS;
+ ALOGV("vkCreateSwapchainKHR: surface=0x%" PRIx64
+ " minImageCount=%u imageFormat=%u imageColorSpace=%u"
+ " imageExtent=%ux%u imageUsage=%#x preTransform=%u presentMode=%u"
+ " oldSwapchain=0x%" PRIx64,
+ reinterpret_cast<uint64_t>(create_info->surface),
+ create_info->minImageCount, create_info->imageFormat,
+ create_info->imageColorSpace, create_info->imageExtent.width,
+ create_info->imageExtent.height, create_info->imageUsage,
+ create_info->preTransform, create_info->presentMode,
+ reinterpret_cast<uint64_t>(create_info->oldSwapchain));
+
if (!allocator)
- allocator = GetAllocator(device);
+ allocator = &GetData(device).allocator;
ALOGV_IF(create_info->imageArrayLayers != 1,
"Swapchain imageArrayLayers (%u) != 1 not supported",
@@ -433,10 +359,33 @@
"swapchain present mode %d not supported",
create_info->presentMode);
+ Surface& surface = *SurfaceFromHandle(create_info->surface);
+
+ // -- Reset the native window --
+ // The native window might have been used previously, and had its properties
+ // changed from defaults. That will affect the answer we get for queries
+ // like MIN_UNDEQUED_BUFFERS. Reset to a known/default state before we
+ // attempt such queries.
+
+ err = native_window_set_buffer_count(surface.window.get(), 0);
+ if (err != 0) {
+ ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
+ strerror(-err), err);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ err = surface.window->setSwapInterval(surface.window.get(), 1);
+ if (err != 0) {
+ // TODO(jessehall): Improve error reporting. Can we enumerate possible
+ // errors and translate them to valid Vulkan result codes?
+ ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
+ strerror(-err), err);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
// -- Configure the native window --
- Surface& surface = *SurfaceFromHandle(create_info->surface);
- const DriverDispatchTable& dispatch = GetDriverDispatch(device);
+ const auto& dispatch = GetData(device).driver;
int native_format = HAL_PIXEL_FORMAT_RGBA_8888;
switch (create_info->imageFormat) {
@@ -536,8 +485,8 @@
if (err != 0) {
// TODO(jessehall): Improve error reporting. Can we enumerate possible
// errors and translate them to valid Vulkan result codes?
- ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
- err);
+ ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
+ strerror(-err), err);
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -562,14 +511,14 @@
return VK_ERROR_INITIALIZATION_FAILED;
}
- err = surface.window->setSwapInterval(
- surface.window.get(),
- create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1);
+ int swap_interval =
+ create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
+ err = surface.window->setSwapInterval(surface.window.get(), swap_interval);
if (err != 0) {
// TODO(jessehall): Improve error reporting. Can we enumerate possible
// errors and translate them to valid Vulkan result codes?
- ALOGE("native_window->setSwapInterval failed: %s (%d)", strerror(-err),
- err);
+ ALOGE("native_window->setSwapInterval(%d) failed: %s (%d)",
+ swap_interval, strerror(-err), err);
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -623,14 +572,7 @@
result = VK_ERROR_INITIALIZATION_FAILED;
break;
}
- img.buffer = InitSharedPtr(device, buffer);
- if (!img.buffer) {
- ALOGE("swapchain creation failed: out of memory");
- surface.window->cancelBuffer(surface.window.get(), buffer,
- img.dequeue_fence);
- result = VK_ERROR_OUT_OF_HOST_MEMORY;
- break;
- }
+ img.buffer = buffer;
img.dequeued = true;
image_create.extent =
@@ -681,12 +623,12 @@
}
VKAPI_ATTR
-void DestroySwapchainKHR_Bottom(VkDevice device,
- VkSwapchainKHR swapchain_handle,
- const VkAllocationCallbacks* allocator) {
- const DriverDispatchTable& dispatch = GetDriverDispatch(device);
+void DestroySwapchainKHR(VkDevice device,
+ VkSwapchainKHR swapchain_handle,
+ const VkAllocationCallbacks* allocator) {
+ const auto& dispatch = GetData(device).driver;
Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
- const std::shared_ptr<ANativeWindow>& window = swapchain->surface.window;
+ const android::sp<ANativeWindow>& window = swapchain->surface.window;
for (uint32_t i = 0; i < swapchain->num_images; i++) {
Swapchain::Image& img = swapchain->images[i];
@@ -702,16 +644,16 @@
}
if (!allocator)
- allocator = GetAllocator(device);
+ allocator = &GetData(device).allocator;
swapchain->~Swapchain();
allocator->pfnFree(allocator->pUserData, swapchain);
}
VKAPI_ATTR
-VkResult GetSwapchainImagesKHR_Bottom(VkDevice,
- VkSwapchainKHR swapchain_handle,
- uint32_t* count,
- VkImage* images) {
+VkResult GetSwapchainImagesKHR(VkDevice,
+ VkSwapchainKHR swapchain_handle,
+ uint32_t* count,
+ VkImage* images) {
Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
VkResult result = VK_SUCCESS;
if (images) {
@@ -728,12 +670,12 @@
}
VKAPI_ATTR
-VkResult AcquireNextImageKHR_Bottom(VkDevice device,
- VkSwapchainKHR swapchain_handle,
- uint64_t timeout,
- VkSemaphore semaphore,
- VkFence vk_fence,
- uint32_t* image_index) {
+VkResult AcquireNextImageKHR(VkDevice device,
+ VkSwapchainKHR swapchain_handle,
+ uint64_t timeout,
+ VkSemaphore semaphore,
+ VkFence vk_fence,
+ uint32_t* image_index) {
Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
ANativeWindow* window = swapchain.surface.window.get();
VkResult result;
@@ -777,7 +719,7 @@
}
}
- result = GetDriverDispatch(device).AcquireImageANDROID(
+ result = GetData(device).driver.AcquireImageANDROID(
device, swapchain.images[idx].image, fence_clone, semaphore, vk_fence);
if (result != VK_SUCCESS) {
// NOTE: we're relying on AcquireImageANDROID to close fence_clone,
@@ -798,14 +740,13 @@
}
VKAPI_ATTR
-VkResult QueuePresentKHR_Bottom(VkQueue queue,
- const VkPresentInfoKHR* present_info) {
+VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
"vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d",
present_info->sType);
ALOGV_IF(present_info->pNext, "VkPresentInfo::pNext != NULL");
- const DriverDispatchTable& dispatch = GetDriverDispatch(queue);
+ const auto& dispatch = GetData(queue).driver;
VkResult final_result = VK_SUCCESS;
for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
Swapchain& swapchain =
@@ -858,4 +799,5 @@
return final_result;
}
+} // namespace driver
} // namespace vulkan
diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h
new file mode 100644
index 0000000..2c60c49
--- /dev/null
+++ b/vulkan/libvulkan/swapchain.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LIBVULKAN_SWAPCHAIN_H
+#define LIBVULKAN_SWAPCHAIN_H 1
+
+#include <vulkan/vulkan.h>
+
+namespace vulkan {
+namespace driver {
+
+// clang-format off
+VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
+VKAPI_ATTR void DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* allocator);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice pdev, uint32_t queue_family, VkSurfaceKHR surface, VkBool32* pSupported);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* capabilities);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkSurfaceFormatKHR* formats);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkPresentModeKHR* modes);
+VKAPI_ATTR VkResult CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* create_info, const VkAllocationCallbacks* allocator, VkSwapchainKHR* swapchain_handle);
+VKAPI_ATTR void DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain_handle, const VkAllocationCallbacks* allocator);
+VKAPI_ATTR VkResult GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint32_t* count, VkImage* images);
+VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* image_index);
+VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info);
+// clang-format on
+
+} // namespace driver
+} // namespace vulkan
+
+#endif // LIBVULKAN_SWAPCHAIN_H
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 6f57238..f29cb68 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -19,6 +19,7 @@
#include <algorithm>
#include <array>
#include <inttypes.h>
+#include <stdlib.h>
#include <string.h>
#include <log/log.h>
@@ -186,6 +187,58 @@
AllocHandle(type, &device->next_handle[type]));
}
+VKAPI_ATTR void* DefaultAllocate(void*,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope) {
+ void* ptr = nullptr;
+ // Vulkan requires 'alignment' to be a power of two, but posix_memalign
+ // additionally requires that it be at least sizeof(void*).
+ int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
+ return ret == 0 ? ptr : nullptr;
+}
+
+VKAPI_ATTR void* DefaultReallocate(void*,
+ void* ptr,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope) {
+ if (size == 0) {
+ free(ptr);
+ return nullptr;
+ }
+
+ // TODO(jessehall): Right now we never shrink allocations; if the new
+ // request is smaller than the existing chunk, we just continue using it.
+ // The null driver never reallocs, so this doesn't matter. If that changes,
+ // or if this code is copied into some other project, this should probably
+ // have a heuristic to allocate-copy-free when doing so will save "enough"
+ // space.
+ size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
+ if (size <= old_size)
+ return ptr;
+
+ void* new_ptr = nullptr;
+ if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
+ return nullptr;
+ if (ptr) {
+ memcpy(new_ptr, ptr, std::min(old_size, size));
+ free(ptr);
+ }
+ return new_ptr;
+}
+
+VKAPI_ATTR void DefaultFree(void*, void* ptr) {
+ free(ptr);
+}
+
+const VkAllocationCallbacks kDefaultAllocCallbacks = {
+ .pUserData = nullptr,
+ .pfnAllocation = DefaultAllocate,
+ .pfnReallocation = DefaultReallocate,
+ .pfnFree = DefaultFree,
+};
+
} // namespace
namespace null_driver {
@@ -239,10 +292,8 @@
VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
const VkAllocationCallbacks* allocator,
VkInstance* out_instance) {
- // Assume the loader provided alloc callbacks even if the app didn't.
- ALOG_ASSERT(
- allocator,
- "Missing alloc callbacks, loader or app should have provided them");
+ if (!allocator)
+ allocator = &kDefaultAllocCallbacks;
VkInstance_T* instance =
static_cast<VkInstance_T*>(allocator->pfnAllocation(
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
index e97e5f5..62d8240 100644
--- a/vulkan/tools/vkinfo.cpp
+++ b/vulkan/tools/vkinfo.cpp
@@ -162,8 +162,11 @@
uint32_t num_extensions = 0;
for (const auto& desired_ext : kDesiredExtensions) {
bool available = HasExtension(info.extensions, desired_ext);
- for (size_t i = 0; !available && i < info.layer_extensions.size(); i++)
- available = HasExtension(info.layer_extensions[i], desired_ext);
+ if (options.validate) {
+ for (size_t i = 0; !available && i < info.layer_extensions.size();
+ i++)
+ available = HasExtension(info.layer_extensions[i], desired_ext);
+ }
if (available)
extensions[num_extensions++] = desired_ext;
}
@@ -179,12 +182,11 @@
// clang-format off
const char *kValidationLayers[] = {
"VK_LAYER_GOOGLE_threading",
+ "VK_LAYER_LUNARG_parameter_validation",
"VK_LAYER_LUNARG_device_limits",
- "VK_LAYER_LUNARG_draw_state",
- "VK_LAYER_LUNARG_image",
- "VK_LAYER_LUNARG_mem_tracker",
"VK_LAYER_LUNARG_object_tracker",
- "VK_LAYER_LUNARG_param_checker",
+ "VK_LAYER_LUNARG_image",
+ "VK_LAYER_LUNARG_core_validation",
"VK_LAYER_LUNARG_swapchain",
"VK_LAYER_GOOGLE_unique_objects"
};
@@ -236,8 +238,12 @@
uint32_t num_extensions = 0;
for (const auto& desired_ext : kDesiredExtensions) {
bool available = HasExtension(info->extensions, desired_ext);
- for (size_t i = 0; !available && i < info->layer_extensions.size(); i++)
- available = HasExtension(info->layer_extensions[i], desired_ext);
+ if (options.validate) {
+ for (size_t i = 0; !available && i < info->layer_extensions.size();
+ i++)
+ available =
+ HasExtension(info->layer_extensions[i], desired_ext);
+ }
if (available)
extensions[num_extensions++] = desired_ext;
}
@@ -245,12 +251,11 @@
// clang-format off
const char *kValidationLayers[] = {
"VK_LAYER_GOOGLE_threading",
+ "VK_LAYER_LUNARG_parameter_validation",
"VK_LAYER_LUNARG_device_limits",
- "VK_LAYER_LUNARG_draw_state",
- "VK_LAYER_LUNARG_image",
- "VK_LAYER_LUNARG_mem_tracker",
"VK_LAYER_LUNARG_object_tracker",
- "VK_LAYER_LUNARG_param_checker",
+ "VK_LAYER_LUNARG_image",
+ "VK_LAYER_LUNARG_core_validation",
"VK_LAYER_LUNARG_swapchain",
"VK_LAYER_GOOGLE_unique_objects"
};