Merge "Caps Lock toggle with Meta + Alt (1/2)" into nyc-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 87f637c..61b8f6b 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+ #define LOG_TAG "atrace"
+
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
@@ -173,6 +175,7 @@
static const char* g_categoriesFile = NULL;
static const char* g_kernelTraceFuncs = NULL;
static const char* g_debugAppCmdLine = "";
+static const char* g_outputFile = nullptr;
/* Global state */
static bool g_traceAborted = false;
@@ -767,8 +770,9 @@
}
// Read the current kernel trace and write it to stdout.
-static void dumpTrace()
+static void dumpTrace(int outFd)
{
+ ALOGI("Dumping trace");
int traceFD = open(k_tracePath, O_RDWR);
if (traceFD == -1) {
fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
@@ -817,7 +821,7 @@
if (zs.avail_out == 0) {
// Need to write the output.
- result = write(STDOUT_FILENO, out, bufSize);
+ result = write(outFd, out, bufSize);
if ((size_t)result < bufSize) {
fprintf(stderr, "error writing deflated trace: %s (%d)\n",
strerror(errno), errno);
@@ -837,7 +841,7 @@
if (zs.avail_out < bufSize) {
size_t bytes = bufSize - zs.avail_out;
- result = write(STDOUT_FILENO, out, bytes);
+ result = write(outFd, out, bytes);
if ((size_t)result < bytes) {
fprintf(stderr, "error writing deflated trace: %s (%d)\n",
strerror(errno), errno);
@@ -853,7 +857,7 @@
free(out);
} else {
ssize_t sent = 0;
- while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0);
+ while ((sent = sendfile(outFd, traceFD, NULL, 64*1024*1024)) > 0);
if (sent == -1) {
fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
errno);
@@ -918,6 +922,8 @@
" CPU performance, like pagecache usage.\n"
" --list_categories\n"
" list the available tracing categories\n"
+ " -o filename write the trace to the specified file instead\n"
+ " of stdout.\n"
);
}
@@ -946,7 +952,7 @@
{ 0, 0, 0, 0 }
};
- ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:z",
+ ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:zo:",
long_options, &option_index);
if (ret < 0) {
@@ -996,6 +1002,10 @@
g_compress = true;
break;
+ case 'o':
+ g_outputFile = optarg;
+ break;
+
case 0:
if (!strcmp(long_options[option_index].name, "async_start")) {
async = true;
@@ -1073,9 +1083,21 @@
if (ok && traceDump) {
if (!g_traceAborted) {
- printf(" done\nTRACE:\n");
+ printf(" done\n");
fflush(stdout);
- dumpTrace();
+ int outFd = STDOUT_FILENO;
+ if (g_outputFile) {
+ outFd = open(g_outputFile, O_WRONLY | O_CREAT);
+ }
+ if (outFd == -1) {
+ printf("Failed to open '%s', err=%d", g_outputFile, errno);
+ } else {
+ dprintf(outFd, "TRACE:\n");
+ dumpTrace(outFd);
+ if (g_outputFile) {
+ close(outFd);
+ }
+ }
} else {
printf("\ntrace aborted.\n");
fflush(stdout);
diff --git a/cmds/dumpstate/bugreport-format.md b/cmds/dumpstate/bugreport-format.md
index fc43250..d7837ae 100644
--- a/cmds/dumpstate/bugreport-format.md
+++ b/cmds/dumpstate/bugreport-format.md
@@ -26,21 +26,23 @@
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
would generate a `FS/dirA/dirB/fileC` entry in the zip file.
+When systrace is enabled, the zip file will contain a `systrace.txt` file as well.
+
The flat file also has some minor changes:
- Tombstone files were removed and added to the zip file.
@@ -60,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 b52a829..f486e08 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -27,7 +27,6 @@
#include <stdlib.h>
#include <string>
#include <string.h>
-#include <sys/capability.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/stat.h>
@@ -63,11 +62,14 @@
static std::set<std::string> mount_points;
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);
#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. */
@@ -90,7 +92,8 @@
* See bugreport-format.txt for more info.
*/
// TODO: change to "v1" before final N build
-static std::string VERSION_DEFAULT = "v1-dev2";
+static std::string VERSION_DEFAULT = "v1-dev3";
+static std::string VERSION_BUILD_ON_NAME = "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. */
@@ -168,6 +171,46 @@
closedir(d);
}
+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)) {
+ return; // error already logged
+ }
+ if (is_tracing <= 0) {
+ MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
+ return;
+ }
+
+ 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 {
+ if (remove(systrace_path.c_str())) {
+ MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
+ }
+ }
+}
+
static bool skip_not_stat(const char *path) {
static const char stat[] = "/stat";
size_t len = strlen(path);
@@ -605,9 +648,8 @@
run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
- run_command("ROUTE", 10, "route", NULL);
run_command("PRINTENV", 10, "printenv", NULL);
- run_command("NETSTAT", 10, "netstat", NULL);
+ run_command("NETSTAT", 10, "netstat", "-n", NULL);
run_command("LSMOD", 10, "lsmod", NULL);
do_dmesg();
@@ -846,10 +888,7 @@
printf("== Android Framework Services\n");
printf("========================================================\n");
- /* the full dumpsys is starting to take a long time, so we need
- to increase its timeout. we really need to do the timeouts in
- dumpsys itself... */
- run_command("DUMPSYS", 60, "dumpsys", "--skip", "meminfo,cpuinfo", NULL);
+ run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo,cpuinfo", NULL);
printf("========================================================\n");
printf("== Checkins\n");
@@ -902,8 +941,8 @@
" -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());
+ " -V: sets the bugreport format version (valid values: %s, %s)\n",
+ VERSION_DEFAULT.c_str(), VERSION_BUILD_ON_NAME.c_str());
}
static void sigpipe_handler(int n) {
@@ -968,49 +1007,6 @@
return std::string(hash_buffer);
}
-/* switch to non-root user and group */
-bool drop_root() {
- /* ensure we will keep capabilities when we drop root */
- if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
- MYLOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
- return false;
- }
-
- gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
- AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC };
- if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
- MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
- return false;
- }
- if (setgid(AID_SHELL) != 0) {
- MYLOGE("Unable to setgid, aborting: %s\n", strerror(errno));
- return false;
- }
- if (setuid(AID_SHELL) != 0) {
- MYLOGE("Unable to setuid, aborting: %s\n", strerror(errno));
- return false;
- }
-
- struct __user_cap_header_struct capheader;
- struct __user_cap_data_struct capdata[2];
- memset(&capheader, 0, sizeof(capheader));
- memset(&capdata, 0, sizeof(capdata));
- capheader.version = _LINUX_CAPABILITY_VERSION_3;
- capheader.pid = 0;
-
- capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
- capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
- capdata[0].inheritable = 0;
- capdata[1].inheritable = 0;
-
- if (capset(&capheader, &capdata[0]) < 0) {
- MYLOGE("capset failed: %s\n", strerror(errno));
- return false;
- }
-
- return true;
-}
-
int main(int argc, char *argv[]) {
struct sigaction sigact;
int do_add_date = 0;
@@ -1059,7 +1055,9 @@
}
/* parse arguments */
- log_args("Dumpstate command line", argc, const_cast<const char **>(argv));
+ std::string args;
+ 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) {
switch (c) {
@@ -1096,7 +1094,7 @@
exit(1);
}
- if (version != VERSION_DEFAULT) {
+ if (version != VERSION_DEFAULT && version != VERSION_BUILD_ON_NAME) {
usage();
exit(1);
}
@@ -1120,6 +1118,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;
@@ -1149,6 +1150,11 @@
} else {
suffix = "undated";
}
+ if (version == VERSION_BUILD_ON_NAME) {
+ 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:
@@ -1158,6 +1164,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"
@@ -1169,8 +1176,8 @@
log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
if (do_zip_file) {
- MYLOGD("Creating initial .zip file\n");
path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
+ MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
create_parent_dirs(path.c_str());
zip_file.reset(fopen(path.c_str(), "wb"));
if (!zip_file) {
@@ -1251,10 +1258,13 @@
// duration is logged into MYLOG instead.
print_header(version);
+ // Dumps systrace right away, otherwise it will be filled with unnecessary events.
+ 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.
- run_command("DUMPSYS MEMINFO", 30, SU_PATH, "shell", "dumpsys", "meminfo", "-a", NULL);
- run_command("DUMPSYS CPUINFO", 30, SU_PATH, "shell", "dumpsys", "cpuinfo", "-a", NULL);
+ run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
+ run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "cpuinfo", "-a", NULL);
/* collect stack traces from Dalvik and native processes (needs root) */
dump_traces_path = dump_traces();
@@ -1262,9 +1272,11 @@
/* Get the tombstone fds, recovery files, and mount info here while we are running as root. */
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()) {
+ if (!drop_root_user()) {
return -1;
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 9c975d2..baba0f9 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -65,11 +65,10 @@
*
* It does not need to match the exact sum of all sections, but ideally it should to be slight more
* than such sum: a value too high will cause the bugreport to finish before the user expected (for
- * example, jumping from 70% to 100%), while a value too low will cause the progress to fluctuate
- * down (for example, from 70% to 50%, since the actual max will be automatically increased every
- * time it is reached).
+ * example, jumping from 70% to 100%), while a value too low will cause the progress to get stuck
+ * at an almost-finished value (like 99%) for a while.
*/
-static const int WEIGHT_TOTAL = 4000;
+static const int WEIGHT_TOTAL = 6500;
/* Most simple commands have 10 as timeout, so 5 is a good estimate */
static const int WEIGHT_FILE = 5;
@@ -85,6 +84,9 @@
/* prints the contents of a file */
int dump_file(const char *title, const char *path);
+/* saves the the contents of a file as a long */
+int read_file_as_long(const char *path, long int *output);
+
/* prints the contents of the fd
* fd must have been opened with the flag O_NONBLOCK.
*/
@@ -100,13 +102,24 @@
bool (*skip)(const char *path),
int (*dump_from_fd)(const char *title, const char *path, int fd));
+// TODO: need to refactor all those run_command variations; there shold be just one, receiving an
+// optional CommandOptions objects with values such as run_always, drop_root, etc...
+
/* forks a command and waits for it to finish -- terminate args with NULL */
+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, 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();
/* sends a broadcast using Activity Manager */
void send_broadcast(const std::string& action, const std::vector<std::string>& args);
@@ -171,8 +184,8 @@
/* dump eMMC Extended CSD data */
void dump_emmc_ecsd(const char *ext_csd_path);
-/** logs command-line arguments */
-void log_args(const std::string& message, int argc, const char *argv[]);
+/** gets command-line arguments */
+void format_args(int argc, const char *argv[], std::string *args);
/*
* Helper class used to report how long it takes for a section to finish.
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 884f250..d9738bb 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <string>
#include <string.h>
+#include <sys/capability.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <sys/sysconf.h>
@@ -394,7 +395,7 @@
sprintf(title, "SHOW MAP %d (%s)", pid, name);
sprintf(arg, "%d", pid);
- run_command(title, 10, SU_PATH, "root", "showmap", arg, NULL);
+ run_command(title, 10, SU_PATH, "root", "showmap", "-q", arg, NULL);
}
static int _dump_file_from_fd(const char *title, const char *path, int fd) {
@@ -474,6 +475,27 @@
return _dump_file_from_fd(title, path, fd);
}
+int read_file_as_long(const char *path, long int *output) {
+ int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
+ if (fd < 0) {
+ int err = errno;
+ MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
+ return -1;
+ }
+ char buffer[50];
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+ if (bytes_read == -1) {
+ MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
+ return -2;
+ }
+ if (bytes_read == 0) {
+ MYLOGE("File %s is empty\n", path);
+ return -3;
+ }
+ *output = atoi(buffer);
+ return 0;
+}
+
/* calls skip to gate calling dump_from_fd recursively
* in the specified directory. dump_from_fd defaults to
* dump_file_from_fd above when set to NULL. skip defaults
@@ -607,6 +629,9 @@
return true;
}
+// TODO: refactor all those commands that convert args
+void format_args(const char* command, const char *args[], std::string *string);
+
int run_command(const char *title, int timeout_seconds, const char *command, ...) {
DurationReporter duration_reporter(title);
fflush(stdout);
@@ -616,23 +641,77 @@
va_list ap;
va_start(ap, command);
if (title) printf("------ %s (%s", title, command);
+ bool null_terminated = false;
for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) {
args[arg] = va_arg(ap, const char *);
- if (args[arg] == NULL) break;
+ if (args[arg] == nullptr) {
+ null_terminated = true;
+ break;
+ }
+ // TODO: null_terminated check is not really working; line below would crash dumpstate if
+ // nullptr is missing
if (title) printf(" %s", args[arg]);
}
if (title) printf(") ------\n");
fflush(stdout);
+ if (!null_terminated) {
+ // Fail now, otherwise execvp() call on run_command_always() might hang.
+ std::string cmd;
+ format_args(command, args, &cmd);
+ MYLOGE("skipping command %s because its args were not NULL-terminated", cmd.c_str());
+ return -1;
+ }
ON_DRY_RUN({ update_progress(timeout_seconds); va_end(ap); return 0; });
- int status = run_command_always(title, timeout_seconds, args);
+ int status = run_command_always(title, DONT_DROP_ROOT, NORMAL_STDOUT, timeout_seconds, args);
+ va_end(ap);
+ return status;
+}
+
+int run_command_as_shell(const char *title, int timeout_seconds, const char *command, ...) {
+ DurationReporter duration_reporter(title);
+ fflush(stdout);
+
+ const char *args[1024] = {command};
+ size_t arg;
+ va_list ap;
+ va_start(ap, command);
+ if (title) printf("------ %s (%s", title, command);
+ bool null_terminated = false;
+ for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) {
+ args[arg] = va_arg(ap, const char *);
+ if (args[arg] == nullptr) {
+ null_terminated = true;
+ break;
+ }
+ // TODO: null_terminated check is not really working; line below would crash dumpstate if
+ // nullptr is missing
+ if (title) printf(" %s", args[arg]);
+ }
+ if (title) printf(") ------\n");
+ fflush(stdout);
+ if (!null_terminated) {
+ // Fail now, otherwise execvp() call on run_command_always() might hang.
+ std::string cmd;
+ format_args(command, args, &cmd);
+ MYLOGE("skipping command %s because its args were not NULL-terminated", cmd.c_str());
+ return -1;
+ }
+
+ ON_DRY_RUN({ update_progress(timeout_seconds); va_end(ap); return 0; });
+
+ 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, 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.
* It's a good approximation for most cases, except when calling dumpsys, where its weight
* should be much higher proportionally to its timeout. */
@@ -644,12 +723,24 @@
/* 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 (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);
@@ -661,37 +752,56 @@
sigaction(SIGPIPE, &sigact, NULL);
execvp(command, (char**) args);
- printf("*** exec(%s): %s\n", command, strerror(errno));
+ // execvp's result will be handled after waitpid_with_timeout() below, but if it failed,
+ // it's safer to exit dumpstate.
+ MYLOGD("execvp on command '%s' failed (error: %s)", command, strerror(errno));
fflush(stdout);
- _exit(-1);
+ // Must call _exit (instead of exit), otherwise it will corrupt the zip file.
+ _exit(EXIT_FAILURE);
}
/* handle parent case */
int status;
bool ret = waitpid_with_timeout(pid, timeout_seconds, &status);
uint64_t elapsed = DurationReporter::nanotime() - start;
+ std::string cmd; // used to log command and its args
if (!ret) {
if (errno == ETIMEDOUT) {
- printf("*** %s: Timed out after %.3fs (killing pid %d)\n", command,
+ format_args(command, args, &cmd);
+ 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 {
- printf("*** %s: Error after %.4fs (killing pid %d)\n", command,
+ format_args(command, args, &cmd);
+ 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);
}
kill(pid, SIGTERM);
if (!waitpid_with_timeout(pid, 5, NULL)) {
kill(pid, SIGKILL);
if (!waitpid_with_timeout(pid, 5, NULL)) {
- printf("*** %s: Cannot kill %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);
+ 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) {
@@ -700,21 +810,69 @@
return status;
}
+bool drop_root_user() {
+ if (getgid() == AID_SHELL && getuid() == AID_SHELL) {
+ MYLOGD("drop_root_user(): already running as Shell");
+ return true;
+ }
+ /* ensure we will keep capabilities when we drop root */
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+ MYLOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
+ return false;
+ }
+
+ gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
+ AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC };
+ if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
+ MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
+ return false;
+ }
+ if (setgid(AID_SHELL) != 0) {
+ MYLOGE("Unable to setgid, aborting: %s\n", strerror(errno));
+ return false;
+ }
+ if (setuid(AID_SHELL) != 0) {
+ MYLOGE("Unable to setuid, aborting: %s\n", strerror(errno));
+ return false;
+ }
+
+ struct __user_cap_header_struct capheader;
+ struct __user_cap_data_struct capdata[2];
+ memset(&capheader, 0, sizeof(capheader));
+ memset(&capdata, 0, sizeof(capdata));
+ capheader.version = _LINUX_CAPABILITY_VERSION_3;
+ capheader.pid = 0;
+
+ capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
+ capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
+ capdata[0].inheritable = 0;
+ capdata[1].inheritable = 0;
+
+ if (capset(&capheader, &capdata[0]) < 0) {
+ MYLOGE("capset failed: %s\n", strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
void send_broadcast(const std::string& action, const std::vector<std::string>& args) {
if (args.size() > 1000) {
MYLOGE("send_broadcast: too many arguments (%d)\n", (int) args.size());
return;
}
- const char *am_args[1024] = { SU_PATH, "shell", "/system/bin/am", "broadcast",
- "--user", "0", "-a", action.c_str() };
- size_t am_index = 7; // Starts at the index of last initial value above.
+ const char *am_args[1024] = { "/system/bin/am", "broadcast", "--user", "0", "-a",
+ action.c_str() };
+ size_t am_index = 5; // Starts at the index of last initial value above.
for (const std::string& arg : args) {
am_args[++am_index] = arg.c_str();
}
// Always terminate with NULL.
am_args[am_index + 1] = NULL;
- log_args("send_broadcast arguments", am_index, am_args);
- run_command_always(NULL, 5, am_args);
+ 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, DROP_ROOT, REDIRECT_TO_STDERR, 20, am_args);
}
size_t num_props = 0;
@@ -1053,7 +1211,7 @@
void take_screenshot(const std::string& path) {
const char *args[] = { "/system/bin/screencap", "-p", path.c_str(), NULL };
- run_command_always(NULL, 10, args);
+ run_command_always(NULL, DONT_DROP_ROOT, REDIRECT_TO_STDERR, 10, args);
}
void vibrate(FILE* vibrator, int ms) {
@@ -1194,11 +1352,29 @@
printf("\n");
}
-void log_args(const std::string& message, int argc, const char *argv[]) {
- std::string args;
+// TODO: refactor all those commands that convert args
+void format_args(int argc, const char *argv[], std::string *args) {
+ LOG_ALWAYS_FATAL_IF(args == nullptr);
for (int i = 0; i < argc; i++) {
- args.append(argv[i]);
- args.append(" ");
+ args->append(argv[i]);
+ if (i < argc -1) {
+ args->append(" ");
+ }
}
- MYLOGD("%s: %s\n", message.c_str(), args.c_str());
+}
+void format_args(const char* command, const char *args[], std::string *string) {
+ LOG_ALWAYS_FATAL_IF(args == nullptr || command == nullptr);
+ string->append(command);
+ if (args[0] == nullptr) return;
+ string->append(" ");
+
+ for (int arg = 1; arg <= 1000; ++arg) {
+ if (args[arg] == nullptr) return;
+ string->append(args[arg]);
+ if (args[arg+1] != nullptr) {
+ string->append(" ");
+ }
+ }
+ // TODO: not really working: if NULL is missing, it will crash dumpstate.
+ MYLOGE("internal error: missing NULL entry on %s", string->c_str());
}
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 003fcc3..7e5bbc5 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -43,9 +43,10 @@
"usage: dumpsys\n"
" To dump all services.\n"
"or:\n"
- " dumpsys [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n"
+ " dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n"
" --help: shows this help\n"
" -l: only list services, do not dump them\n"
+ " -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n"
" --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
" SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
}
@@ -74,44 +75,79 @@
Vector<String16> args;
Vector<String16> skippedServices;
bool showListOnly = false;
- if (argc == 2) {
- // 1 argument: check for special cases (-l or --help)
- if (strcmp(argv[1], "--help") == 0) {
- usage();
- return 0;
+ bool skipServices = false;
+ int timeoutArg = 10;
+ static struct option longOptions[] = {
+ {"skip", no_argument, 0, 0 },
+ {"help", no_argument, 0, 0 },
+ { 0, 0, 0, 0 }
+ };
+
+ while (1) {
+ int c;
+ int optionIndex = 0;
+
+ c = getopt_long(argc, argv, "+t:l", longOptions, &optionIndex);
+
+ if (c == -1) {
+ break;
}
- if (strcmp(argv[1], "-l") == 0) {
+
+ switch (c) {
+ case 0:
+ if (!strcmp(longOptions[optionIndex].name, "skip")) {
+ skipServices = true;
+ } else if (!strcmp(longOptions[optionIndex].name, "help")) {
+ usage();
+ return 0;
+ }
+ break;
+
+ case 't':
+ {
+ char *endptr;
+ timeoutArg = strtol(optarg, &endptr, 10);
+ if (*endptr != '\0' || timeoutArg <= 0) {
+ fprintf(stderr, "Error: invalid timeout number: '%s'\n", optarg);
+ return -1;
+ }
+ }
+ break;
+
+ case 'l':
showListOnly = true;
+ break;
+
+ default:
+ fprintf(stderr, "\n");
+ usage();
+ return -1;
}
}
- if (argc == 3) {
- // 2 arguments: check for special cases (--skip SERVICES)
- if (strcmp(argv[1], "--skip") == 0) {
- char* token = strtok(argv[2], ",");
- while (token != NULL) {
- skippedServices.add(String16(token));
- token = strtok(NULL, ",");
+
+ for (int i = optind; i < argc; i++) {
+ if (skipServices) {
+ skippedServices.add(String16(argv[i]));
+ } else {
+ if (i == optind) {
+ services.add(String16(argv[i]));
+ } else {
+ args.add(String16(argv[i]));
}
}
}
- bool dumpAll = argc == 1;
- if (dumpAll || !skippedServices.empty() || showListOnly) {
+
+ if ((skipServices && skippedServices.empty()) ||
+ (showListOnly && (!services.empty() || !skippedServices.empty()))) {
+ usage();
+ return -1;
+ }
+
+ if (services.empty() || showListOnly) {
// gets all services
services = sm->listServices();
services.sort(sort_func);
args.add(String16("-a"));
- } else {
- // gets a specific service:
- // first check if its name is not a special argument...
- if (strcmp(argv[1], "--skip") == 0 || strcmp(argv[1], "-l") == 0) {
- usage();
- return -1;
- }
- // ...then gets its arguments
- services.add(String16(argv[1]));
- for (int i=2; i<argc; i++) {
- args.add(String16(argv[i]));
- }
}
const size_t N = services.size();
@@ -173,8 +209,7 @@
}
});
- // TODO: Make this configurable at runtime.
- constexpr auto timeout = std::chrono::seconds(10);
+ auto timeout = std::chrono::seconds(timeoutArg);
auto end = std::chrono::steady_clock::now() + timeout;
struct pollfd pfd = {
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index 65bcf39..d35099a 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -80,6 +80,36 @@
LOCAL_CLANG := true
include $(BUILD_EXECUTABLE)
+# OTA chroot tool
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := otapreopt_chroot
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := $(common_cflags)
+
+LOCAL_SRC_FILES := otapreopt_chroot.cpp
+LOCAL_SHARED_LIBRARIES := \
+ libbase \
+ liblog \
+
+LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
+LOCAL_CLANG := true
+include $(BUILD_EXECUTABLE)
+
+# OTA postinstall script
+
+include $(CLEAR_VARS)
+LOCAL_MODULE:= otapreopt_script
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_SRC_FILES := otapreopt_script.sh
+
+# Let this depend on otapreopt and the chroot tool, so we just have to mention one in a
+# configuration.
+LOCAL_REQUIRED_MODULES := otapreopt otapreopt_chroot
+
+include $(BUILD_PREBUILT)
+
# Tests.
include $(LOCAL_PATH)/tests/Android.mk
\ No newline at end of file
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index ac2ee30..2bfea63 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>
@@ -161,47 +162,87 @@
return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME);
}
-static bool unlink_reference_profile(const char* pkgname) {
- std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
- std::string reference_profile = create_primary_profile(reference_profile_dir);
- if (unlink(reference_profile.c_str()) != 0) {
+static bool clear_profile(const std::string& profile) {
+ 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 unlink " << reference_profile;
+ PLOG(WARNING) << "Could not open profile " << profile;
return false;
+ } else {
+ // Nothing to clear. That's ok.
+ return true;
}
}
- return true;
+
+ if (flock(ufd.get(), LOCK_EX | LOCK_NB) != 0) {
+ if (errno != EWOULDBLOCK) {
+ PLOG(WARNING) << "Error locking profile " << profile;
+ }
+ // This implies that the app owning this profile is running
+ // (and has acquired the lock).
+ //
+ // If we can't acquire the lock bail out since clearing is useless anyway
+ // (the app will write again to the profile).
+ //
+ // Note:
+ // This does not impact the this is not an issue for the profiling correctness.
+ // In case this is needed because of an app upgrade, profiles will still be
+ // eventually cleared by the app itself due to checksum mismatch.
+ // If this is needed because profman advised, then keeping the data around
+ // until the next run is again not an issue.
+ //
+ // If the app attempts to acquire a lock while we've held one here,
+ // it will simply skip the current write cycle.
+ return false;
+ }
+
+ bool truncated = ftruncate(ufd.get(), 0) == 0;
+ if (!truncated) {
+ PLOG(WARNING) << "Could not truncate " << profile;
+ }
+ if (flock(ufd.get(), LOCK_UN) != 0) {
+ PLOG(WARNING) << "Error unlocking profile " << profile;
+ }
+ return truncated;
}
-static bool unlink_current_profiles(const char* pkgname) {
+static bool clear_reference_profile(const char* pkgname) {
+ std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
+ std::string reference_profile = create_primary_profile(reference_profile_dir);
+ return clear_profile(reference_profile);
+}
+
+static bool clear_current_profile(const char* pkgname, userid_t user) {
+ std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
+ std::string profile = create_primary_profile(profile_dir);
+ return clear_profile(profile);
+}
+
+static bool clear_current_profiles(const char* pkgname) {
bool success = true;
std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
for (auto user : users) {
- std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
- std::string profile = create_primary_profile(profile_dir);
- if (unlink(profile.c_str()) != 0) {
- if (errno != ENOENT) {
- PLOG(WARNING) << "Could not unlink " << profile;
- success = false;
- }
- }
+ success &= clear_current_profile(pkgname, user);
}
return success;
}
-static bool unlink_all_profiles(const char* pkgname) {
+int clear_app_profiles(const char* pkgname) {
bool success = true;
- success &= unlink_reference_profile(pkgname);
- success &= unlink_current_profiles(pkgname);
- return success;
+ success &= clear_reference_profile(pkgname);
+ success &= clear_current_profiles(pkgname);
+ return success ? 0 : -1;
}
int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
std::string suffix = "";
+ bool only_cache = false;
if (flags & FLAG_CLEAR_CACHE_ONLY) {
suffix = CACHE_DIR_POSTFIX;
+ only_cache = true;
} else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
suffix = CODE_CACHE_DIR_POSTFIX;
+ only_cache = true;
}
int res = 0;
@@ -217,11 +258,37 @@
// TODO: include result once 25796509 is fixed
delete_dir_contents(path);
}
- unlink_all_profiles(pkgname);
+ if (!only_cache) {
+ if (!clear_current_profile(pkgname, userid)) {
+ res |= -1;
+ }
+ }
}
return res;
}
+static int destroy_app_reference_profile(const char *pkgname) {
+ return delete_dir_contents_and_dir(
+ create_data_ref_profile_package_path(pkgname),
+ /*ignore_if_missing*/ true);
+}
+
+static int destroy_app_current_profiles(const char *pkgname, userid_t userid) {
+ return delete_dir_contents_and_dir(
+ create_data_user_profile_package_path(userid, pkgname),
+ /*ignore_if_missing*/ true);
+}
+
+int destroy_app_profiles(const char *pkgname) {
+ int result = 0;
+ std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
+ for (auto user : users) {
+ result |= destroy_app_current_profiles(pkgname, user);
+ }
+ result |= destroy_app_reference_profile(pkgname);
+ return result;
+}
+
int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
int res = 0;
if (flags & FLAG_STORAGE_CE) {
@@ -229,10 +296,13 @@
create_data_user_package_path(uuid, userid, pkgname));
}
if (flags & FLAG_STORAGE_DE) {
- // TODO: include result once 25796509 is fixed
- delete_dir_contents_and_dir(
+ res |= delete_dir_contents_and_dir(
create_data_user_de_package_path(uuid, userid, pkgname));
- unlink_all_profiles(pkgname);
+ destroy_app_current_profiles(pkgname, userid);
+ // TODO(calin): If the package is still installed by other users it's probably
+ // beneficial to keep the reference profile around.
+ // Verify if it's ok to do that.
+ destroy_app_reference_profile(pkgname);
}
return res;
}
@@ -707,7 +777,7 @@
static void run_dex2oat(int zip_fd, int oat_fd, int image_fd, const char* input_file_name,
const char* output_file_name, int swap_fd, const char *instruction_set,
- bool vm_safe_mode, bool debuggable, bool post_bootcomplete, bool extract_only,
+ const char* compiler_filter, bool vm_safe_mode, bool debuggable, bool post_bootcomplete,
int profile_fd) {
static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
@@ -723,10 +793,6 @@
char dex2oat_Xmx_flag[kPropertyValueMax];
bool have_dex2oat_Xmx_flag = get_property("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
- char dex2oat_compiler_filter_flag[kPropertyValueMax];
- bool have_dex2oat_compiler_filter_flag = get_property("dalvik.vm.dex2oat-filter",
- dex2oat_compiler_filter_flag, NULL) > 0;
-
char dex2oat_threads_buf[kPropertyValueMax];
bool have_dex2oat_threads_flag = get_property(post_bootcomplete
? "dalvik.vm.dex2oat-threads"
@@ -818,6 +884,10 @@
if (have_dex2oat_Xmx_flag) {
sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
}
+
+ // Compute compiler filter.
+
+ bool have_dex2oat_compiler_filter_flag;
if (skip_compilation) {
strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
have_dex2oat_compiler_filter_flag = true;
@@ -825,11 +895,20 @@
} else if (vm_safe_mode) {
strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
have_dex2oat_compiler_filter_flag = true;
- } else if (extract_only) {
- strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-at-runtime");
+ } else if (compiler_filter != nullptr &&
+ strlen(compiler_filter) + strlen("--compiler-filter=") <
+ arraysize(dex2oat_compiler_filter_arg)) {
+ sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
have_dex2oat_compiler_filter_flag = true;
- } else if (have_dex2oat_compiler_filter_flag) {
- sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag);
+ } else {
+ char dex2oat_compiler_filter_flag[kPropertyValueMax];
+ have_dex2oat_compiler_filter_flag = get_property("dalvik.vm.dex2oat-filter",
+ dex2oat_compiler_filter_flag, NULL) > 0;
+ if (have_dex2oat_compiler_filter_flag) {
+ sprintf(dex2oat_compiler_filter_arg,
+ "--compiler-filter=%s",
+ dex2oat_compiler_filter_flag);
+ }
}
// Check whether all apps should be compiled debuggable.
@@ -1154,8 +1233,8 @@
/* parent */
int return_code = wait_child(pid);
bool need_to_compile = false;
- bool delete_current_profiles = false;
- bool delete_reference_profile = false;
+ bool should_clear_current_profiles = false;
+ bool should_clear_reference_profile = false;
if (!WIFEXITED(return_code)) {
LOG(WARNING) << "profman failed for package " << pkgname << ": " << return_code;
} else {
@@ -1163,35 +1242,35 @@
switch (return_code) {
case PROFMAN_BIN_RETURN_CODE_COMPILE:
need_to_compile = true;
- delete_current_profiles = true;
- delete_reference_profile = false;
+ should_clear_current_profiles = true;
+ should_clear_reference_profile = false;
break;
case PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION:
need_to_compile = false;
- delete_current_profiles = false;
- delete_reference_profile = false;
+ should_clear_current_profiles = false;
+ should_clear_reference_profile = false;
break;
case PROFMAN_BIN_RETURN_CODE_BAD_PROFILES:
LOG(WARNING) << "Bad profiles for package " << pkgname;
need_to_compile = false;
- delete_current_profiles = true;
- delete_reference_profile = true;
+ should_clear_current_profiles = true;
+ should_clear_reference_profile = true;
break;
case PROFMAN_BIN_RETURN_CODE_ERROR_IO: // fall-through
case PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING:
// Temporary IO problem (e.g. locking). Ignore but log a warning.
LOG(WARNING) << "IO error while reading profiles for package " << pkgname;
need_to_compile = false;
- delete_current_profiles = false;
- delete_reference_profile = false;
+ should_clear_current_profiles = false;
+ should_clear_reference_profile = false;
break;
default:
// Unknown return code or error. Unlink profiles.
LOG(WARNING) << "Unknown error code while processing profiles for package " << pkgname
<< ": " << return_code;
need_to_compile = false;
- delete_current_profiles = true;
- delete_reference_profile = true;
+ should_clear_current_profiles = true;
+ should_clear_reference_profile = true;
break;
}
}
@@ -1199,11 +1278,11 @@
if (close(reference_profile_fd) != 0) {
PLOG(WARNING) << "Failed to close fd for reference profile";
}
- if (delete_current_profiles) {
- unlink_current_profiles(pkgname);
+ if (should_clear_current_profiles) {
+ clear_current_profiles(pkgname);
}
- if (delete_reference_profile) {
- unlink_reference_profile(pkgname);
+ if (should_clear_reference_profile) {
+ clear_reference_profile(pkgname);
}
return need_to_compile;
}
@@ -1274,9 +1353,14 @@
return true;
}
+// TODO: Consider returning error codes.
+bool merge_profiles(uid_t uid, const char *pkgname) {
+ return analyse_profiles(uid, pkgname);
+}
+
int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* instruction_set,
- int dexopt_needed, const char* oat_dir, int dexopt_flags,
- const char* volume_uuid ATTRIBUTE_UNUSED, bool use_profiles)
+ int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
+ const char* volume_uuid ATTRIBUTE_UNUSED)
{
struct utimbuf ut;
struct stat input_stat;
@@ -1291,29 +1375,18 @@
bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0;
bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
- bool extract_only = (dexopt_flags & DEXOPT_EXTRACTONLY) != 0;
+ bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
+
+ CHECK(pkgname != nullptr);
+ CHECK(pkgname[0] != 0);
+
fd_t reference_profile_fd = -1;
-
- if (is_public && use_profiles) {
- // We should not give public access to apks compiled with profile information.
- // Log an error and return early if are asked to do so.
- ALOGE("use_profiles should not be used with is_public.");
- return -1;
- }
-
- if (use_profiles) {
- if (analyse_profiles(uid, pkgname)) {
- // Open again reference profile in read only mode as dex2oat does not get write
- // permissions.
- reference_profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ false);
- if (reference_profile_fd == -1) {
- PLOG(WARNING) << "Couldn't open reference profile in read only mode " << pkgname;
- exit(72);
- }
- } else {
- // No need to (re)compile. Return early.
- return 0;
- }
+ // Public apps should not be compiled with profile information ever. Same goes for the special
+ // package '*' used for the system server.
+ if (!is_public && pkgname[0] != '*') {
+ // Open reference profile in read only mode as dex2oat does not get write permissions.
+ reference_profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ false);
+ // Note: it's OK to not find a profile here.
}
if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
@@ -1388,10 +1461,12 @@
char app_image_format[kPropertyValueMax];
bool have_app_image_format =
get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
- if (!extract_only && have_app_image_format) {
- // Recreate is false since we want to avoid deleting the image in case dex2oat decides to
- // not compile anything.
- image_fd = open_output_file(image_path, /*recreate*/false);
+ // Use app images only if it is enabled (by a set image format) and we are compiling
+ // profile-guided (so the app image doesn't conservatively contain all classes).
+ 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);
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);
@@ -1431,7 +1506,7 @@
input_file_name++;
}
run_dex2oat(input_fd, out_fd, image_fd, input_file_name, out_path, swap_fd,
- instruction_set, vm_safe_mode, debuggable, boot_complete, extract_only,
+ instruction_set, compiler_filter, vm_safe_mode, debuggable, boot_complete,
reference_profile_fd);
} else {
ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
@@ -1477,7 +1552,7 @@
close(reference_profile_fd);
// We failed to compile. Unlink the reference profile. Current profiles are already unlinked
// when profmoan advises compilation.
- unlink_reference_profile(pkgname);
+ clear_reference_profile(pkgname);
}
if (swap_fd >= 0) {
close(swap_fd);
@@ -1768,11 +1843,6 @@
return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */);
}
-int rm_profiles(const char* pkgname)
-{
- return unlink_all_profiles(pkgname) ? 0 : -1;
-}
-
int link_file(const char* relative_path, const char* from_base, const char* to_base) {
char from_path[PKG_PATH_MAX];
char to_path[PKG_PATH_MAX];
@@ -1852,7 +1922,8 @@
{
struct stat s;
if (stat(b_path.c_str(), &s) != 0) {
- LOG(ERROR) << "Can't find A/B artifact at " << b_path;
+ // Silently ignore for now. The service calling this isn't smart enough to understand
+ // lack of artifacts at the moment.
return -1;
}
if (!S_ISREG(s.st_mode)) {
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index b473e3e..13143c5 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -48,15 +48,19 @@
int delete_user(const char *uuid, userid_t userid);
int rm_dex(const char *path, const char *instruction_set);
int free_cache(const char *uuid, int64_t free_size);
+
+bool merge_profiles(uid_t uid, const char *pkgname);
+
int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
- int dexopt_needed, const char* oat_dir, int dexopt_flags,
- const char* volume_uuid, bool use_profiles);
+ int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
+ const char* volume_uuid);
int mark_boot_complete(const char *instruction_set);
int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
int idmap(const char *target_path, const char *overlay_path, uid_t uid);
int create_oat_dir(const char* oat_dir, const char *instruction_set);
int rm_package_dir(const char* apk_path);
-int rm_profiles(const char* pkgname);
+int clear_app_profiles(const char* pkgname);
+int destroy_app_profiles(const char* pkgname);
int link_file(const char *relative_path, const char *from_base, const char *to_base);
// Move a B version over to the A location. Only works for oat_dir != nullptr.
diff --git a/cmds/installd/file_parsing.h b/cmds/installd/file_parsing.h
new file mode 100644
index 0000000..3e2f815
--- /dev/null
+++ b/cmds/installd/file_parsing.h
@@ -0,0 +1,60 @@
+/*
+ * 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 OTAPREOPT_FILE_PARSING_H_
+#define OTAPREOPT_FILE_PARSING_H_
+
+#include <fstream>
+#include <functional>
+#include <string>
+
+namespace android {
+namespace installd {
+
+bool ParseFile(const std::string& strFile, std::function<bool (const std::string&)> parse) {
+ std::ifstream input_stream(strFile);
+
+ if (!input_stream.is_open()) {
+ return false;
+ }
+
+ while (!input_stream.eof()) {
+ // Read the next line.
+ std::string line;
+ getline(input_stream, line);
+
+ // Is the line empty? Simplifies the next check.
+ if (line.empty()) {
+ continue;
+ }
+
+ // Is this a comment (starts with pound)?
+ if (line[0] == '#') {
+ continue;
+ }
+
+ if (!parse(line)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace installd
+} // namespace android
+
+#endif // OTAPREOPT_FILE_PARSING_H_
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 7ca7527..de3f54a 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -128,13 +128,13 @@
bool create_cache_path(char path[PKG_PATH_MAX],
const char *src,
const char *instruction_set) {
- size_t srclen = strlen(src);
-
- /* demand that we are an absolute path */
- if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
+ /* demand that we are an absolute path */
+ if ((src == nullptr) || (src[0] != '/') || strstr(src,"..")) {
return false;
}
+ size_t srclen = strlen(src);
+
if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX?
return false;
}
@@ -216,29 +216,40 @@
return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
}
-static int do_ota_dexopt(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
- // Time to fork and run otapreopt.
- pid_t pid = fork();
- if (pid == 0) {
- const char* argv[1 + 9 + 1];
- argv[0] = "/system/bin/otapreopt";
- for (size_t i = 1; i <= 9; ++i) {
- argv[i] = arg[i - 1];
- }
- argv[10] = nullptr;
+// We use otapreopt_chroot to get into the chroot.
+static constexpr const char* kOtaPreopt = "/system/bin/otapreopt_chroot";
- execv(argv[0], (char * const *)argv);
- ALOGE("execv(OTAPREOPT) failed: %s\n", strerror(errno));
- exit(99);
- } else {
- int res = wait_child(pid);
- if (res == 0) {
- ALOGV("DexInv: --- END OTAPREOPT (success) ---\n");
- } else {
- ALOGE("DexInv: --- END OTAPREOPT --- status=0x%04x, process failed\n", res);
+static int do_ota_dexopt(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
+ // Time to fork and run otapreopt.
+
+ // Check that the tool exists.
+ struct stat s;
+ if (stat(kOtaPreopt, &s) != 0) {
+ LOG(ERROR) << "Otapreopt chroot tool not found.";
+ return -1;
}
- return res;
- }
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ const char* argv[1 + 9 + 1];
+ argv[0] = kOtaPreopt;
+ for (size_t i = 1; i <= 9; ++i) {
+ argv[i] = arg[i - 1];
+ }
+ argv[10] = nullptr;
+
+ execv(argv[0], (char * const *)argv);
+ PLOG(ERROR) << "execv(OTAPREOPT_CHROOT) failed";
+ exit(99);
+ } else {
+ int res = wait_child(pid);
+ if (res == 0) {
+ ALOGV("DexInv: --- END OTAPREOPT (success) ---\n");
+ } else {
+ ALOGE("DexInv: --- END OTAPREOPT --- status=0x%04x, process failed\n", res);
+ }
+ return res;
+ }
}
static int do_dexopt(char **arg, char reply[REPLY_MAX])
@@ -247,10 +258,27 @@
if ((dexopt_flags & DEXOPT_OTA) != 0) {
return do_ota_dexopt(arg, reply);
}
- /* apk_path, uid, pkgname, instruction_set, dexopt_needed, oat_dir, dexopt_flags, volume_uuid,
- use_profiles */
- return dexopt(arg[0], atoi(arg[1]), arg[2], arg[3], atoi(arg[4]),
- arg[5], dexopt_flags, parse_null(arg[7]), (atoi(arg[8]) == 0 ? false : true));
+ return dexopt(arg[0], // apk_path
+ atoi(arg[1]), // uid
+ arg[2], // pkgname
+ arg[3], // instruction_set
+ atoi(arg[4]), // dexopt_needed
+ arg[5], // oat_dir
+ dexopt_flags,
+ arg[7], // compiler_filter
+ parse_null(arg[8])); // volume_uuid
+}
+
+static int do_merge_profiles(char **arg, char reply[REPLY_MAX])
+{
+ uid_t uid = static_cast<uid_t>(atoi(arg[0]));
+ const char* pkgname = arg[1];
+ if (merge_profiles(uid, pkgname)) {
+ strncpy(reply, "true", REPLY_MAX);
+ } else {
+ strncpy(reply, "false", REPLY_MAX);
+ }
+ return 0;
}
static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
@@ -330,10 +358,16 @@
return rm_package_dir(arg[0]);
}
-static int do_rm_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+static int do_clear_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
/* package_name */
- return rm_profiles(arg[0]);
+ return clear_app_profiles(arg[0]);
+}
+
+static int do_destroy_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+{
+ /* package_name */
+ return destroy_app_profiles(arg[0]);
}
static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
@@ -374,9 +408,11 @@
{ "idmap", 3, do_idmap },
{ "createoatdir", 2, do_create_oat_dir },
{ "rmpackagedir", 1, do_rm_package_dir },
- { "rmprofiles", 1, do_rm_profiles },
+ { "clear_app_profiles", 1, do_clear_app_profiles },
+ { "destroy_app_profiles", 1, do_destroy_app_profiles },
{ "linkfile", 3, do_link_file },
{ "move_ab", 3, do_move_ab },
+ { "merge_profiles", 2, do_merge_profiles },
};
static int readx(int s, void *_buf, int count)
diff --git a/cmds/installd/installd_constants.h b/cmds/installd/installd_constants.h
index 8f6e928..8513695 100644
--- a/cmds/installd/installd_constants.h
+++ b/cmds/installd/installd_constants.h
@@ -75,12 +75,12 @@
* IMPORTANT: These values are passed from Java code. Keep them in sync with
* frameworks/base/services/core/java/com/android/server/pm/Installer.java
***************************************************************************/
-constexpr int DEXOPT_PUBLIC = 1 << 1;
-constexpr int DEXOPT_SAFEMODE = 1 << 2;
-constexpr int DEXOPT_DEBUGGABLE = 1 << 3;
-constexpr int DEXOPT_BOOTCOMPLETE = 1 << 4;
-constexpr int DEXOPT_EXTRACTONLY = 1 << 5;
-constexpr int DEXOPT_OTA = 1 << 6;
+constexpr int DEXOPT_PUBLIC = 1 << 1;
+constexpr int DEXOPT_SAFEMODE = 1 << 2;
+constexpr int DEXOPT_DEBUGGABLE = 1 << 3;
+constexpr int DEXOPT_BOOTCOMPLETE = 1 << 4;
+constexpr int DEXOPT_PROFILE_GUIDED = 1 << 5;
+constexpr int DEXOPT_OTA = 1 << 6;
/* all known values for dexopt flags */
constexpr int DEXOPT_MASK =
@@ -88,7 +88,7 @@
| DEXOPT_SAFEMODE
| DEXOPT_DEBUGGABLE
| DEXOPT_BOOTCOMPLETE
- | DEXOPT_EXTRACTONLY
+ | DEXOPT_PROFILE_GUIDED
| DEXOPT_OTA;
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 3aac48b..245694a 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -17,6 +17,7 @@
#include <algorithm>
#include <inttypes.h>
#include <random>
+#include <regex>
#include <selinux/android.h>
#include <selinux/avc.h>
#include <stdlib.h>
@@ -35,6 +36,7 @@
#include <private/android_filesystem_config.h>
#include <commands.h>
+#include <file_parsing.h>
#include <globals.h>
#include <installd_deps.h> // Need to fill in requirements of commands.
#include <string_helpers.h>
@@ -54,8 +56,8 @@
namespace android {
namespace installd {
-static constexpr const char* kBootClassPathPropertyName = "env.BOOTCLASSPATH";
-static constexpr const char* kAndroidRootPathPropertyName = "env.ANDROID_ROOT";
+static constexpr const char* kBootClassPathPropertyName = "BOOTCLASSPATH";
+static constexpr const char* kAndroidRootPathPropertyName = "ANDROID_ROOT";
static constexpr const char* kOTARootDirectory = "/system-b";
static constexpr size_t kISAIndex = 3;
@@ -131,41 +133,55 @@
private:
bool ReadSystemProperties() {
- // TODO(agampe): What to do about the things in default.prop? It's only heap sizes, so it's easy
- // to emulate for now, but has issues (e.g., vendors modifying the boot classpath
- // may require larger values here - revisit). That's why this goes first, so that
- // if those dummy values are overridden in build.prop, that's what we'll get.
- //
- // Note: It seems we'll get access to the B root partition, so we should read the default.prop
- // file.
- // if (!system_properties_.Load(b_mount_path_ + "/default.prop") {
- // return false;
- // }
- system_properties_.SetProperty("dalvik.vm.image-dex2oat-Xms", "64m");
- system_properties_.SetProperty("dalvik.vm.image-dex2oat-Xmx", "64m");
- system_properties_.SetProperty("dalvik.vm.dex2oat-Xms", "64m");
- system_properties_.SetProperty("dalvik.vm.dex2oat-Xmx", "512m");
+ static constexpr const char* kPropertyFiles[] = {
+ "/default.prop", "/system/build.prop"
+ };
- // TODO(agampe): Do this properly/test.
- return system_properties_.Load(b_mount_path_ + "/system/build.prop");
+ for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) {
+ if (!system_properties_.Load(kPropertyFiles[i])) {
+ return false;
+ }
+ }
+
+ return true;
}
bool ReadEnvironment() {
- // Read important environment variables. For simplicity, store them as
- // system properties.
- // TODO(agampe): We'll have to parse init.environ.rc for BOOTCLASSPATH.
- // For now, just the A version.
- const char* boot_classpath = getenv("BOOTCLASSPATH");
- if (boot_classpath == nullptr) {
- return false;
- }
- system_properties_.SetProperty(kBootClassPathPropertyName, boot_classpath);
+ // Parse the environment variables from init.environ.rc, which have the form
+ // export NAME VALUE
+ // For simplicity, don't respect string quotation. The values we are interested in can be
+ // encoded without them.
+ std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)");
+ bool parse_result = ParseFile("/init.environ.rc", [&](const std::string& line) {
+ std::smatch export_match;
+ if (!std::regex_match(line, export_match, export_regex)) {
+ return true;
+ }
- const char* root_path = getenv("ANDROID_ROOT");
- if (root_path == nullptr) {
+ if (export_match.size() != 3) {
+ return true;
+ }
+
+ std::string name = export_match[1].str();
+ std::string value = export_match[2].str();
+
+ system_properties_.SetProperty(name, value);
+
+ return true;
+ });
+ if (!parse_result) {
return false;
}
- system_properties_.SetProperty(kAndroidRootPathPropertyName, b_mount_path_ + root_path);
+
+ // Check that we found important properties.
+ constexpr const char* kRequiredProperties[] = {
+ kBootClassPathPropertyName, kAndroidRootPathPropertyName
+ };
+ for (size_t i = 0; i < arraysize(kRequiredProperties); ++i) {
+ if (system_properties_.GetProperty(kRequiredProperties[i]) == nullptr) {
+ return false;
+ }
+ }
return true;
}
@@ -239,9 +255,7 @@
// TODO: Delete files, just for a blank slate.
const std::string& boot_cp = *system_properties_.GetProperty(kBootClassPathPropertyName);
- std::string preopted_boot_art_path = StringPrintf("%s/system/framework/%s/boot.art",
- b_mount_path_.c_str(),
- isa);
+ std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
return PatchoatBootImage(art_path, isa);
} else {
@@ -254,7 +268,7 @@
// This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
std::vector<std::string> cmd;
- cmd.push_back(b_mount_path_ + "/system/bin/patchoat");
+ cmd.push_back("/system/bin/patchoat");
cmd.push_back("--input-image-location=/system/framework/boot.art");
cmd.push_back(StringPrintf("--output-image-file=%s", art_path.c_str()));
@@ -279,7 +293,7 @@
const char* isa) {
// This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
std::vector<std::string> cmd;
- cmd.push_back(b_mount_path_ + "/system/bin/dex2oat");
+ cmd.push_back("/system/bin/dex2oat");
cmd.push_back(StringPrintf("--image=%s", art_path.c_str()));
for (const std::string& boot_part : Split(boot_cp, ':')) {
cmd.push_back(StringPrintf("--dex-file=%s", boot_part.c_str()));
@@ -305,8 +319,7 @@
"--compiler-filter=",
false,
cmd);
- cmd.push_back(StringPrintf("--image-classes=%s/system/etc/preloaded-classes",
- b_mount_path_.c_str()));
+ cmd.push_back("--image-classes=/system/etc/preloaded-classes");
// TODO: Compiled-classes.
const std::string* extra_opts =
system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags");
@@ -344,17 +357,15 @@
}
int RunPreopt() {
- /* apk_path, uid, pkgname, instruction_set, dexopt_needed, oat_dir, dexopt_flags,
- volume_uuid, use_profiles */
- int ret = dexopt(package_parameters_[0],
- atoi(package_parameters_[1]),
- package_parameters_[2],
- package_parameters_[3],
- atoi(package_parameters_[4]),
- package_parameters_[5],
- atoi(package_parameters_[6]),
- ParseNull(package_parameters_[7]),
- (atoi(package_parameters_[8]) == 0 ? false : true));
+ int ret = dexopt(package_parameters_[0], // apk_path
+ atoi(package_parameters_[1]), // uid
+ package_parameters_[2], // pkgname
+ package_parameters_[3], // instruction_set
+ atoi(package_parameters_[4]), // dexopt_needed
+ package_parameters_[5], // oat_dir
+ atoi(package_parameters_[6]), // dexopt_flags
+ package_parameters_[7], // compiler_filter
+ ParseNull(package_parameters_[8])); // volume_uuid
return ret;
}
@@ -468,10 +479,6 @@
}
}
- // The path where the B partitions are mounted.
- // TODO(agampe): If we're running this *inside* the change-root, we wouldn't need this.
- std::string b_mount_path_;
-
// Stores the system properties read out of the B partition. We need to use these properties
// to compile, instead of the A properties we could get from init/get_property.
SystemProperties system_properties_;
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
new file mode 100644
index 0000000..f7f69a9
--- /dev/null
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -0,0 +1,99 @@
+/*
+ ** 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 <linux/unistd.h>
+#include <sys/mount.h>
+#include <sys/wait.h>
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android-base/stringprintf.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "otapreopt"
+#endif
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace installd {
+
+static int otapreopt_chroot(const int argc, char **arg) {
+ // We need to run the otapreopt tool from the postinstall partition. As such, set up a
+ // mount namespace and change root.
+
+ // Create our own mount namespace.
+ if (unshare(CLONE_NEWNS) != 0) {
+ PLOG(ERROR) << "Failed to unshare() for otapreopt.";
+ exit(200);
+ }
+
+ // Make postinstall private, so that our changes don't propagate.
+ if (mount("", "/postinstall", nullptr, MS_PRIVATE, nullptr) != 0) {
+ PLOG(ERROR) << "Failed to mount private.";
+ exit(201);
+ }
+
+ // Bind mount necessary directories.
+ constexpr const char* kBindMounts[] = {
+ "/data", "/dev", "/proc", "/sys"
+ };
+ for (size_t i = 0; i < arraysize(kBindMounts); ++i) {
+ std::string trg = StringPrintf("/postinstall%s", kBindMounts[i]);
+ if (mount(kBindMounts[i], trg.c_str(), nullptr, MS_BIND, nullptr) != 0) {
+ PLOG(ERROR) << "Failed to bind-mount " << kBindMounts[i];
+ exit(202);
+ }
+ }
+
+ // Chdir into /postinstall.
+ if (chdir("/postinstall") != 0) {
+ PLOG(ERROR) << "Unable to chdir into /postinstall.";
+ exit(203);
+ }
+
+ // Make /postinstall the root in our mount namespace.
+ if (chroot(".") != 0) {
+ PLOG(ERROR) << "Failed to chroot";
+ exit(204);
+ }
+
+ if (chdir("/") != 0) {
+ PLOG(ERROR) << "Unable to chdir into /.";
+ exit(205);
+ }
+
+ // Now go on and run otapreopt.
+
+ const char* argv[1 + 9 + 1];
+ CHECK_EQ(argc, 10);
+ argv[0] = "/system/bin/otapreopt";
+ for (size_t i = 1; i <= 9; ++i) {
+ argv[i] = arg[i];
+ }
+ argv[10] = nullptr;
+
+ execv(argv[0], (char * const *)argv);
+ PLOG(ERROR) << "execv(OTAPREOPT) failed.";
+ exit(99);
+}
+
+} // namespace installd
+} // namespace android
+
+int main(const int argc, char *argv[]) {
+ return android::installd::otapreopt_chroot(argc, argv);
+}
diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh
new file mode 100644
index 0000000..a31734a
--- /dev/null
+++ b/cmds/installd/otapreopt_script.sh
@@ -0,0 +1,50 @@
+#!/system/bin/sh
+
+#
+# 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.
+#
+
+# This script will run as a postinstall step to drive otapreopt.
+
+# Maximum number of packages/steps.
+MAXIMUM_PACKAGES=1000
+
+PREPARE=$(cmd otadexopt prepare)
+if [ "$PREPARE" != "Success" ] ; then
+ echo "Failed to prepare."
+ exit 1
+fi
+
+i=0
+while ((i<MAXIMUM_PACKAGES)) ; do
+ cmd otadexopt step
+ DONE=$(cmd otadexopt done)
+ if [ "$DONE" = "OTA complete." ] ; then
+ break
+ fi
+ sleep 1
+ i=$((i+1))
+done
+
+DONE=$(cmd otadexopt done)
+if [ "$DONE" = "OTA incomplete." ] ; then
+ echo "Incomplete."
+else
+ echo "Complete or error."
+fi
+
+cmd otadexopt cleanup
+
+exit 0
diff --git a/cmds/installd/system_properties.h b/cmds/installd/system_properties.h
index 1b5fb3a..2d940a3 100644
--- a/cmds/installd/system_properties.h
+++ b/cmds/installd/system_properties.h
@@ -21,6 +21,8 @@
#include <string>
#include <unordered_map>
+#include <file_parsing.h>
+
namespace android {
namespace installd {
@@ -28,31 +30,11 @@
class SystemProperties {
public:
bool Load(const std::string& strFile) {
- std::ifstream input_stream(strFile);
-
- if (!input_stream.is_open()) {
- return false;
- }
-
- while (!input_stream.eof()) {
- // Read the next line.
- std::string line;
- getline(input_stream, line);
-
- // Is the line empty? Simplifies the next check.
- if (line.empty()) {
- continue;
- }
-
- // Is this a comment (starts with pound)?
- if (line[0] == '#') {
- continue;
- }
-
+ return ParseFile(strFile, [&](const std::string& line) {
size_t equals_pos = line.find('=');
if (equals_pos == std::string::npos || equals_pos == 0) {
// Did not find equals sign, or it's the first character - isn't a valid line.
- continue;
+ return true;
}
std::string key = line.substr(0, equals_pos);
@@ -60,9 +42,9 @@
line.length() - equals_pos + 1);
properties_.insert(std::make_pair(key, value));
- }
- return true;
+ return true;
+ });
}
// Look up the key in the map. Returns null if the key isn't mapped.
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 74f4264..d84d9f6 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -341,23 +341,27 @@
return result;
}
-int delete_dir_contents(const std::string& pathname) {
- return delete_dir_contents(pathname.c_str(), 0, NULL);
+int delete_dir_contents(const std::string& pathname, bool ignore_if_missing) {
+ return delete_dir_contents(pathname.c_str(), 0, NULL, ignore_if_missing);
}
-int delete_dir_contents_and_dir(const std::string& pathname) {
- return delete_dir_contents(pathname.c_str(), 1, NULL);
+int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing) {
+ return delete_dir_contents(pathname.c_str(), 1, NULL, ignore_if_missing);
}
int delete_dir_contents(const char *pathname,
int also_delete_dir,
- int (*exclusion_predicate)(const char*, const int))
+ int (*exclusion_predicate)(const char*, const int),
+ bool ignore_if_missing)
{
int res = 0;
DIR *d;
d = opendir(pathname);
if (d == NULL) {
+ if (ignore_if_missing && (errno == ENOENT)) {
+ return 0;
+ }
ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno));
return -errno;
}
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 9bbddca..416a726 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -99,12 +99,13 @@
int is_valid_package_name(const char* pkgname);
-int delete_dir_contents(const std::string& pathname);
-int delete_dir_contents_and_dir(const std::string& pathname);
+int delete_dir_contents(const std::string& pathname, bool ignore_if_missing = false);
+int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing = false);
int delete_dir_contents(const char *pathname,
int also_delete_dir,
- int (*exclusion_predicate)(const char *name, const int is_dir));
+ int (*exclusion_predicate)(const char *name, const int is_dir),
+ bool ignore_if_missing = false);
int delete_dir_contents_fd(int dfd, const char *name);
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
index 9e99085..01218c9 100644
--- a/cmds/servicemanager/binder.c
+++ b/cmds/servicemanager/binder.c
@@ -167,20 +167,27 @@
return res;
}
-void binder_send_reply(struct binder_state *bs,
- struct binder_io *reply,
- binder_uintptr_t buffer_to_free,
- int status)
+void binder_free_buffer(struct binder_state *bs,
+ binder_uintptr_t buffer_to_free)
{
struct {
uint32_t cmd_free;
binder_uintptr_t buffer;
+ } __attribute__((packed)) data;
+ data.cmd_free = BC_FREE_BUFFER;
+ data.buffer = buffer_to_free;
+ binder_write(bs, &data, sizeof(data));
+}
+
+void binder_send_reply(struct binder_state *bs,
+ struct binder_io *reply,
+ int status)
+{
+ struct {
uint32_t cmd_reply;
struct binder_transaction_data txn;
} __attribute__((packed)) data;
- data.cmd_free = BC_FREE_BUFFER;
- data.buffer = buffer_to_free;
data.cmd_reply = BC_REPLY;
data.txn.target.ptr = 0;
data.txn.cookie = 0;
@@ -243,7 +250,9 @@
bio_init(&reply, rdata, sizeof(rdata), 4);
bio_init_from_txn(&msg, txn);
res = func(bs, txn, &msg, &reply);
- binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
+ binder_free_buffer(bs, txn->data.ptr.buffer);
+ if ((txn->flags & TF_ONE_WAY) == 0)
+ binder_send_reply(bs, &reply, res);
}
ptr += sizeof(*txn);
break;
diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml
index 346abad..ae0b4d4 100644
--- a/data/etc/wearable_core_hardware.xml
+++ b/data/etc/wearable_core_hardware.xml
@@ -31,8 +31,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/android/sensor.h b/include/android/sensor.h
index f2647be..5a61213 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -393,6 +393,13 @@
/*****************************************************************************/
/**
+ * Enable the selected sensor with a specified sampling period and max batch report latency.
+ * Returns a negative error code on failure.
+ */
+int ASensorEventQueue_registerSensor(ASensorEventQueue* queue, ASensor const* sensor,
+ int32_t samplingPeriodUs, int maxBatchReportLatencyUs);
+
+/**
* Enable the selected sensor. Returns a negative error code on failure.
*/
int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor);
diff --git a/include/binder/IMediaResourceMonitor.h b/include/binder/IMediaResourceMonitor.h
index b7b9c50..c671f7a 100644
--- a/include/binder/IMediaResourceMonitor.h
+++ b/include/binder/IMediaResourceMonitor.h
@@ -27,8 +27,13 @@
public:
DECLARE_META_INTERFACE(MediaResourceMonitor);
- virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const String16& type,
- /*in*/ const String16& subType, /*in*/ int64_t value) = 0;
+ // Values should be in sync with Intent.EXTRA_MEDIA_RESOURCE_TYPE_XXX.
+ enum {
+ TYPE_VIDEO_CODEC = 0,
+ TYPE_AUDIO_CODEC = 1,
+ };
+
+ virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const int32_t type) = 0;
enum {
NOTIFY_RESOURCE_GRANTED = IBinder::FIRST_CALL_TRANSACTION,
diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h
index aa415d5..60a624c 100644
--- a/include/binder/MemoryDealer.h
+++ b/include/binder/MemoryDealer.h
@@ -41,6 +41,9 @@
virtual void deallocate(size_t offset);
virtual void dump(const char* what) const;
+ // allocations are aligned to some value. return that value so clients can account for it.
+ static size_t getAllocationAlignment();
+
sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
protected:
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 44fd59e..2685bcc 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -425,7 +425,7 @@
mutable bool mFdsKnown;
mutable bool mHasFds;
bool mAllowFds;
-
+
release_func mOwner;
void* mOwnerCookie;
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 6f45181..f45d852 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -121,10 +121,10 @@
// Indicates that the consumer should acquire the next frame as soon as it
// can and not wait for a frame to become available. This is only relevant
- // in single buffer mode.
+ // in shared buffer mode.
bool mAutoRefresh;
- // Indicates that this buffer was queued by the producer. When in single
+ // Indicates that this buffer was queued by the producer. When in shared
// buffer mode acquire() can return a BufferItem that wasn't in the queue.
bool mQueuedBuffer;
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index acc8c4b..d232dbb 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -291,24 +291,21 @@
// enqueue buffers without blocking.
bool mAsyncMode;
- // mSingleBufferMode indicates whether or not single buffer mode is enabled.
- // In single buffer mode, the last buffer that was dequeued is cached and
- // returned to all calls to dequeueBuffer and acquireBuffer. This allows the
- // consumer and producer to access the same buffer simultaneously.
- bool mSingleBufferMode;
+ // mSharedBufferMode indicates whether or not shared buffer mode is enabled.
+ bool mSharedBufferMode;
- // When single buffer mode is enabled, this indicates whether the consumer
+ // When shared buffer mode is enabled, this indicates whether the consumer
// should acquire buffers even if BufferQueue doesn't indicate that they are
// available.
bool mAutoRefresh;
- // When single buffer mode is enabled, this tracks which slot contains the
+ // When shared buffer mode is enabled, this tracks which slot contains the
// shared buffer.
- int mSingleBufferSlot;
+ int mSharedBufferSlot;
- // Cached data about the shared buffer in single buffer mode
- struct SingleBufferCache {
- SingleBufferCache(Rect _crop, uint32_t _transform, int _scalingMode,
+ // Cached data about the shared buffer in shared buffer mode
+ struct SharedBufferCache {
+ SharedBufferCache(Rect _crop, uint32_t _transform, int _scalingMode,
android_dataspace _dataspace)
: crop(_crop),
transform(_transform),
@@ -320,7 +317,7 @@
uint32_t transform;
uint32_t scalingMode;
android_dataspace dataspace;
- } mSingleBufferCache;
+ } mSharedBufferCache;
}; // class BufferQueueCore
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 312f323..691487d 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -173,8 +173,8 @@
// See IGraphicBufferProducer::getNextFrameNumber
virtual uint64_t getNextFrameNumber() const override;
- // See IGraphicBufferProducer::setSingleBufferMode
- virtual status_t setSingleBufferMode(bool singleBufferMode) override;
+ // See IGraphicBufferProducer::setSharedBufferMode
+ virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
// See IGraphicBufferProducer::setAutoRefresh
virtual status_t setAutoRefresh(bool autoRefresh) override;
diff --git a/include/gui/BufferSlot.h b/include/gui/BufferSlot.h
index 943fa82..57704b1 100644
--- a/include/gui/BufferSlot.h
+++ b/include/gui/BufferSlot.h
@@ -79,7 +79,7 @@
// transitions to FREE when releaseBuffer (or detachBuffer) is called. A
// detached buffer can also enter the ACQUIRED state via attachBuffer.
//
- // SHARED indicates that this buffer is being used in single-buffer
+ // SHARED indicates that this buffer is being used in shared buffer
// mode. It can be in any combination of the other states at the same time,
// except for FREE (since that excludes being in any other state). It can
// also be dequeued, queued, or acquired multiple times.
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index 1b63552..9307a26 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -26,8 +26,6 @@
#include <utils/threads.h>
#include <gui/IConsumerListener.h>
-#include <queue>
-
namespace android {
// ----------------------------------------------------------------------------
@@ -110,18 +108,18 @@
// from the derived class.
virtual void onLastStrongRef(const void* id);
- // Handlers for the IConsumerListener interface, these will be called from
- // the message queue thread. These calls are used to notify the ConsumerBase
- // of asynchronous events in the BufferQueue. The onFrameAvailableHandler,
- // onFrameReplacedHandler, and onBuffersReleasedHandler methods should not
- // need to be overridden by derived classes, but if they are overridden the
- // ConsumerBase implementation must be called from the derived class. The
- // ConsumerBase version of onSidebandStreamChangedHandler does nothing and
- // can be overriden by derived classes if they want the notification.
- virtual void onFrameAvailableHandler(const BufferItem& item);
- virtual void onFrameReplacedHandler(const BufferItem& item);
- virtual void onBuffersReleasedHandler();
- virtual void onSidebandStreamChangedHandler();
+ // Implementation of the IConsumerListener interface. These
+ // calls are used to notify the ConsumerBase of asynchronous events in the
+ // BufferQueue. The onFrameAvailable, onFrameReplaced, and
+ // onBuffersReleased methods should not need to be overridden by derived
+ // classes, but if they are overridden the ConsumerBase implementation must
+ // be called from the derived class. The ConsumerBase version of
+ // onSidebandStreamChanged does nothing and can be overriden by derived
+ // classes if they want the notification.
+ virtual void onFrameAvailable(const BufferItem& item) override;
+ virtual void onFrameReplaced(const BufferItem& item) override;
+ virtual void onBuffersReleased() override;
+ virtual void onSidebandStreamChanged() override;
// freeBufferLocked frees up the given buffer slot. If the slot has been
// initialized this will release the reference to the GraphicBuffer in that
@@ -246,35 +244,6 @@
//
// This mutex is intended to be locked by derived classes.
mutable Mutex mMutex;
-
- // Implements the ConsumerListener interface
- virtual void onFrameAvailable(const BufferItem& item) override;
- virtual void onFrameReplaced(const BufferItem& item) override;
- virtual void onBuffersReleased() override;
- virtual void onSidebandStreamChanged() override;
-
- enum MessageType {
- ON_FRAME_AVAILABLE,
- ON_FRAME_REPLACED,
- ON_BUFFERS_RELEASED,
- ON_SIDEBAND_STREAM_CHANGED,
- EXIT,
- };
-
- mutable Mutex mMessageQueueLock;
- Condition mMessageAvailable;
- std::queue<std::pair<MessageType, BufferItem>> mMessageQueue;
-
- class MessageThread : public Thread {
- public:
- MessageThread(ConsumerBase* consumerBase) :
- mConsumerBase(consumerBase) {};
- protected:
- virtual bool threadLoop() override;
- ConsumerBase* mConsumerBase;
- };
-
- sp<MessageThread> mMessageThread;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index f6b4230..32bf988 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -524,16 +524,17 @@
// Returns the number of the next frame which will be dequeued.
virtual uint64_t getNextFrameNumber() const = 0;
- // Used to enable/disable single buffer mode.
+ // Used to enable/disable shared buffer mode.
//
- // In single buffer mode the last buffer that was dequeued will be cached
- // and returned to all calls to dequeueBuffer and acquireBuffer. This allows
- // the producer and consumer to simultaneously access the same buffer.
- virtual status_t setSingleBufferMode(bool singleBufferMode) = 0;
+ // When shared buffer mode is enabled the first buffer that is queued or
+ // dequeued will be cached and returned to all subsequent calls to
+ // dequeueBuffer and acquireBuffer. This allows the producer and consumer to
+ // simultaneously access the same buffer.
+ virtual status_t setSharedBufferMode(bool sharedBufferMode) = 0;
// Used to enable/disable auto-refresh.
//
- // Auto refresh has no effect outside of single buffer mode. In single
+ // Auto refresh has no effect outside of shared buffer mode. In shared
// buffer mode, when enabled, it indicates to the consumer that it should
// attempt to acquire buffers even if it is not aware of any being
// available.
diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h
index e5b9fc5..4ee7c02 100644
--- a/include/gui/SensorEventQueue.h
+++ b/include/gui/SensorEventQueue.h
@@ -53,6 +53,18 @@
enum { MAX_RECEIVE_BUFFER_EVENT_COUNT = 256 };
+ /**
+ * Typical sensor delay (sample period) in microseconds.
+ */
+ // Fastest sampling, system will bound it to minDelay
+ static constexpr int32_t SENSOR_DELAY_FASTEST = 0;
+ // Typical sample period for game, 50Hz;
+ static constexpr int32_t SENSOR_DELAY_GAME = 20000;
+ // Typical sample period for UI, 15Hz
+ static constexpr int32_t SENSOR_DELAY_UI = 66667;
+ // Default sensor sample period
+ static constexpr int32_t SENSOR_DELAY_NORMAL = 200000;
+
SensorEventQueue(const sp<ISensorEventConnection>& connection);
virtual ~SensorEventQueue();
virtual void onFirstRef();
@@ -68,6 +80,7 @@
status_t wake() const;
status_t enableSensor(Sensor const* sensor) const;
+ status_t enableSensor(Sensor const* sensor, int32_t samplingPeriodUs) const;
status_t disableSensor(Sensor const* sensor) const;
status_t setEventRate(Sensor const* sensor, nsecs_t ns) const;
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 9f51cdd..5d1d7bf 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -169,7 +169,7 @@
int dispatchSetSidebandStream(va_list args);
int dispatchSetBuffersDataSpace(va_list args);
int dispatchSetSurfaceDamage(va_list args);
- int dispatchSetSingleBufferMode(va_list args);
+ int dispatchSetSharedBufferMode(va_list args);
int dispatchSetAutoRefresh(va_list args);
protected:
@@ -199,7 +199,7 @@
public:
virtual int setMaxDequeuedBufferCount(int maxDequeuedBuffers);
virtual int setAsyncMode(bool async);
- virtual int setSingleBufferMode(bool singleBufferMode);
+ virtual int setSharedBufferMode(bool sharedBufferMode);
virtual int setAutoRefresh(bool autoRefresh);
virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
virtual int unlockAndPost();
@@ -337,10 +337,10 @@
uint32_t mGenerationNumber;
// Caches the values that have been passed to the producer.
- bool mSingleBufferMode;
+ bool mSharedBufferMode;
bool mAutoRefresh;
- // If in single buffer mode and auto refresh is enabled, store the shared
+ // If in shared buffer mode and auto refresh is enabled, store the shared
// buffer slot and return it for all calls to queue/dequeue without going
// over Binder.
int mSharedBufferSlot;
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index aa48718..794fe4c 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -133,6 +133,7 @@
status_t setPosition(const sp<IBinder>& id, float x, float y);
status_t setSize(const sp<IBinder>& id, uint32_t w, uint32_t h);
status_t setCrop(const sp<IBinder>& id, const Rect& crop);
+ status_t setFinalCrop(const sp<IBinder>& id, const Rect& crop);
status_t setLayerStack(const sp<IBinder>& id, uint32_t layerStack);
status_t deferTransactionUntil(const sp<IBinder>& id,
const sp<IBinder>& handle, uint64_t frameNumber);
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index 76ce68d..35644db 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -71,6 +71,7 @@
status_t setAlpha(float alpha=1.0f);
status_t setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
status_t setCrop(const Rect& crop);
+ status_t setFinalCrop(const Rect& crop);
// Defers applying any changes made in this transaction until the Layer
// identified by handle reaches the given frameNumber
diff --git a/include/hardware_properties/HardwarePropertiesManager.h b/include/hardware_properties/HardwarePropertiesManager.h
deleted file mode 100644
index 13f2b99..0000000
--- a/include/hardware_properties/HardwarePropertiesManager.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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_HARDWAREPROPERTIESMANAGER_H
-#define ANDROID_HARDWAREPROPERTIESMANAGER_H
-
-namespace android {
-
-// must be kept in sync with definitions in HardwarePropertiesManager.java
-enum {
- DEVICE_TEMPERATURE_CPU = 0,
- DEVICE_TEMPERATURE_GPU = 1,
- DEVICE_TEMPERATURE_BATTERY = 2,
-};
-
-}; // namespace android
-
-#endif // ANDROID_HARDWAREPROPERTIESMANAGER_H
diff --git a/include/media/hardware/HardwareAPI.h b/include/media/hardware/HardwareAPI.h
index 77ce563..2c50ad6 100644
--- a/include/media/hardware/HardwareAPI.h
+++ b/include/media/hardware/HardwareAPI.h
@@ -315,53 +315,183 @@
OMX_PTR pSidebandWindow; // OUT
};
-// Color description parameters. This is passed via OMX_SetConfig or OMX_GetConfig
-// to video encoders and decoders when the
-// 'OMX.google.android.index.describeColorAspects' extension is given.
+// Color space description (aspects) parameters.
+// This is passed via OMX_SetConfig or OMX_GetConfig to video encoders and decoders when the
+// 'OMX.google.android.index.describeColorAspects' extension is given. Component SHALL behave
+// as described below if it supports this extension.
//
-// Video encoders: the framework uses OMX_SetConfig to specify color aspects
-// of the coded video before the component transitions to idle state, as well
-// as before an input frame with a different color aspect is sent:
-// 1. The component should maintain an internal color aspect state, initialized
-// to Unspecified values.
-// 2. Upon OMX_SetConfig, it SHOULD update its internal state for the aspects that are not
-// Unspecified in the config param.
-// 3. If an aspect value cannot be encoded into the bitstream (including the Other value), that
-// aspect should be reset to the Unspecified value (in the internal state).
-// 4. OMX_GetConfig SHOULD return the current internal state.
-// 5. If changing the color aspects after the first input frame is not supported, and the config
-// params would actually cause a change, OMX_SetConfig should fail with the internal state
-// unchanged.
-// 6. If changing a portion of the aspects after the first input frame is supported, OMX_SetConfig
-// should succeed with the portion of the internal state updated.
+// bDataSpaceChanged and bRequestingDataSpace is assumed to be OMX_FALSE unless noted otherwise.
//
-// Video decoders: the framework uses OMX_SetConfig to specify color aspects
-// of the coded video parsed from the container before the component transitions
-// to idle state.
-// 1. The component should maintiain an internal color aspect state, initialized to Unspecified
-// values.
-// 2. Upon OMX_SetConfig, it SHOULD update its internal state for the aspects that are not
-// Unspecified in the config param, regardless of whether such aspects could be supplied by the
-// component bitstream. (E.g. it should blindly support all enumeration values, even unknown
-// ones, and the Other value).
-// 3. OMX_GetConfig SHOULD return the current internal state.
-// 4. When the component processes color aspect information in the bitstream with a non-Unspecified
-// value, it should update its internal state with that information just before the frame
-// with the new information is outputted, and the component SHALL signal an
-// OMX_EventPortSettingsChanged event with data2 set to the extension index (or
-// OMX_IndexConfigCommonOutputCrop, as it is handled identically).
-// 4a. Component shall not signal a separate event purely for color aspect change, if it occurs
-// together with a port definition (e.g. size) or crop change.
-// 5. If the aspects a component encounters in the bitstream cannot be represented with the below
-// enumeration values, it should set those aspects to Other. Restricted values in the bitstream
-// should be treated as defined by the relevant bitstream specifications/standards, or as
-// Unspecified, if not defined.
+// VIDEO ENCODERS: the framework uses OMX_SetConfig to specify color aspects of the coded video.
+// This may happen:
+// a) before the component transitions to idle state
+// b) before the input frame is sent via OMX_EmptyThisBuffer in executing state
+// c) during execution, just before an input frame with a different color aspect information
+// is sent.
//
+// The framework also uses OMX_GetConfig to
+// d) verify the color aspects that will be written to the stream
+// e) (optional) verify the color aspects that should be reported to the container for a
+// given dataspace/pixelformat received
+//
+// 1. Encoders SHOULD maintain an internal color aspect state, initialized to Unspecified values.
+// This represents the values that will be written into the bitstream.
+// 2. Upon OMX_SetConfig, they SHOULD update their internal state to the aspects received
+// (including Unspecified values). For specific aspect values that are not supported by the
+// codec standard, encoders SHOULD substitute Unspecified values; or they MAY use a suitable
+// alternative (e.g. to suggest the use of BT.709 EOTF instead of SMPTE 240M.)
+// 3. OMX_GetConfig SHALL return the internal state (values that will be written).
+// 4. OMX_SetConfig SHALL always succeed before receiving the first frame. It MAY fail afterwards,
+// but only if the configured values would change AND the component does not support updating the
+// color information to those values mid-stream. If component supports updating a portion of
+// the color information, those values should be updated in the internal state, and OMX_SetConfig
+// SHALL succeed. Otherwise, the internal state SHALL remain intact and OMX_SetConfig SHALL fail
+// with OMX_ErrorUnsupportedSettings.
+// 5. When the framework receives an input frame with an unexpected dataspace, it will query
+// encoders for the color aspects that should be reported to the container using OMX_GetConfig
+// with bDataSpaceChanged set to OMX_TRUE, and nPixelFormat/nDataSpace containing the new
+// format/dataspace values. This allows vendors to use extended dataspace during capture and
+// composition (e.g. screenrecord) - while performing color-space conversion inside the encoder -
+// and encode and report a different color-space information in the bitstream/container.
+// sColorAspects contains the requested color aspects by the client for reference, which may
+// include aspects not supported by the encoding. This is used together with guidance for
+// dataspace selection; see 6. below.
+//
+// VIDEO DECODERS: the framework uses OMX_SetConfig to specify the default color aspects to use
+// for the video.
+// This may happen:
+// a) before the component transitions to idle state
+// b) during execution, when the resolution or the default color aspects change.
+//
+// The framework also uses OMX_GetConfig to
+// c) get the final color aspects reported by the coded bitstream after taking the default values
+// into account.
+//
+// 1. Decoders should maintain two color aspect states - the default state as reported by the
+// framework, and the coded state as reported by the bitstream - as each state can change
+// independently from the other.
+// 2. Upon OMX_SetConfig, it SHALL update its default state regardless of whether such aspects
+// could be supplied by the component bitstream. (E.g. it should blindly support all enumeration
+// values, even unknown ones, and the Other value). This SHALL always succeed.
+// 3. Upon OMX_GetConfig, the component SHALL return the final color aspects by replacing
+// Unspecified coded values with the default values. This SHALL always succeed.
+// 4. Whenever the component processes color aspect information in the bitstream even with an
+// Unspecified value, it SHOULD update its internal coded state with that information just before
+// the frame with the new information would be outputted, and the component SHALL signal an
+// OMX_EventPortSettingsChanged event with data2 set to the extension index.
+// NOTE: Component SHOULD NOT signal a separate event purely for color aspect change, if it occurs
+// together with a port definition (e.g. size) or crop change.
+// 5. If the aspects a component encounters in the bitstream cannot be represented with enumeration
+// values as defined below, the component SHALL set those aspects to Other. Restricted values in
+// the bitstream SHALL be treated as defined by the relevant bitstream specifications/standards,
+// or as Unspecified, if not defined.
+//
+// BOTH DECODERS AND ENCODERS: the framework uses OMX_GetConfig during idle and executing state to
+// f) (optional) get guidance for the dataspace to set for given color aspects, by setting
+// bRequestingDataSpace to OMX_TRUE. The component SHALL return OMX_ErrorUnsupportedSettings
+// IF it does not support this request.
+//
+// 6. This is an information request that can happen at any time, independent of the normal
+// configuration process. This allows vendors to use extended dataspace during capture, playback
+// and composition - while performing color-space conversion inside the component. Component
+// SHALL set the desired dataspace into nDataSpace. Otherwise, it SHALL return
+// OMX_ErrorUnsupportedSettings to let the framework choose a nearby standard dataspace.
+//
+// 6.a. For encoders, this query happens before the first frame is received using surface encoding.
+// This allows the encoder to use a specific dataspace for the color aspects (e.g. because the
+// device supports additional dataspaces, or because it wants to perform color-space extension
+// to facilitate a more optimal rendering/capture pipeline.).
+//
+// 6.b. For decoders, this query happens before the first frame, and every time the color aspects
+// change, while using surface buffers. This allows the decoder to use a specific dataspace for
+// the color aspects (e.g. because the device supports additional dataspaces, or because it wants
+// to perform color-space extension by inline color-space conversion to facilitate a more optimal
+// rendering pipeline.).
+//
+// Note: the size of sAspects may increase in the future by additional fields.
+// Implementations SHOULD NOT require a certain size.
struct DescribeColorAspectsParams {
- OMX_U32 nSize; // IN
- OMX_VERSIONTYPE nVersion; // IN
- OMX_U32 nPortIndex; // IN
- ColorAspects sAspects; // IN/OUT
+ OMX_U32 nSize; // IN
+ OMX_VERSIONTYPE nVersion; // IN
+ OMX_U32 nPortIndex; // IN
+ OMX_BOOL bRequestingDataSpace; // IN
+ OMX_BOOL bDataSpaceChanged; // IN
+ OMX_U32 nPixelFormat; // IN
+ OMX_U32 nDataSpace; // OUT
+ ColorAspects sAspects; // IN/OUT
+};
+
+// HDR color description parameters.
+// This is passed via OMX_SetConfig or OMX_GetConfig to video encoders and decoders when the
+// 'OMX.google.android.index.describeHDRColorInfo' extension is given and an HDR stream
+// is detected. Component SHALL behave as described below if it supports this extension.
+//
+// Currently, only Static Metadata Descriptor Type 1 support is required.
+//
+// VIDEO ENCODERS: the framework uses OMX_SetConfig to specify the HDR static information of the
+// coded video.
+// This may happen:
+// a) before the component transitions to idle state
+// b) before the input frame is sent via OMX_EmptyThisBuffer in executing state
+// c) during execution, just before an input frame with a different HDR static
+// information is sent.
+//
+// The framework also uses OMX_GetConfig to
+// d) verify the HDR static information that will be written to the stream.
+//
+// 1. Encoders SHOULD maintain an internal HDR static info data, initialized to Unspecified values.
+// This represents the values that will be written into the bitstream.
+// 2. Upon OMX_SetConfig, they SHOULD update their internal state to the info received
+// (including Unspecified values). For specific parameters that are not supported by the
+// codec standard, encoders SHOULD substitute Unspecified values. NOTE: no other substitution
+// is allowed.
+// 3. OMX_GetConfig SHALL return the internal state (values that will be written).
+// 4. OMX_SetConfig SHALL always succeed before receiving the first frame if the encoder is
+// configured into an HDR compatible profile. It MAY fail with OMX_ErrorUnsupportedSettings error
+// code if it is not configured into such a profile, OR if the configured values would change
+// AND the component does not support updating the HDR static information mid-stream. If the
+// component supports updating a portion of the information, those values should be updated in
+// the internal state, and OMX_SetConfig SHALL succeed. Otherwise, the internal state SHALL
+// remain intact.
+//
+// VIDEO DECODERS: the framework uses OMX_SetConfig to specify the default HDR static information
+// to use for the video.
+// a) This only happens if the client supplies this information, in which case it occurs before
+// the component transitions to idle state.
+// b) This may also happen subsequently if the default HDR static information changes.
+//
+// The framework also uses OMX_GetConfig to
+// c) get the final HDR static information reported by the coded bitstream after taking the
+// default values into account.
+//
+// 1. Decoders should maintain two HDR static information structures - the default values as
+// reported by the framework, and the coded values as reported by the bitstream - as each
+// structure can change independently from the other.
+// 2. Upon OMX_SetConfig, it SHALL update its default structure regardless of whether such static
+// parameters could be supplied by the component bitstream. (E.g. it should blindly support all
+// parameter values, even seemingly illegal ones). This SHALL always succeed.
+// Note: The descriptor ID used in sInfo may change in subsequent calls. (although for now only
+// Type 1 support is required.)
+// 3. Upon OMX_GetConfig, the component SHALL return the final HDR static information by replacing
+// Unspecified coded values with the default values. This SHALL always succeed. This may be
+// provided using any supported descriptor ID (currently only Type 1) with the goal of expressing
+// the most of the available static information.
+// 4. Whenever the component processes HDR static information in the bitstream even ones with
+// Unspecified parameters, it SHOULD update its internal coded structure with that information
+// just before the frame with the new information would be outputted, and the component SHALL
+// signal an OMX_EventPortSettingsChanged event with data2 set to the extension index.
+// NOTE: Component SHOULD NOT signal a separate event purely for HDR static info change, if it
+// occurs together with a port definition (e.g. size), color aspect or crop change.
+// 5. If certain parameters of the HDR static information encountered in the bitstream cannot be
+// represented using sInfo, the component SHALL use the closest representation.
+//
+// Note: the size of sInfo may increase in the future by supporting additional descriptor types.
+// Implementations SHOULD NOT require a certain size.
+struct DescribeHDRStaticInfoParams {
+ OMX_U32 nSize; // IN
+ OMX_VERSIONTYPE nVersion; // IN
+ OMX_U32 nPortIndex; // IN
+ HDRStaticInfo sInfo; // IN/OUT
};
} // namespace android
diff --git a/include/media/hardware/VideoAPI.h b/include/media/hardware/VideoAPI.h
index 481cc67..3667c4b 100644
--- a/include/media/hardware/VideoAPI.h
+++ b/include/media/hardware/VideoAPI.h
@@ -57,7 +57,7 @@
/**
* Structure describing a media image (frame)
*/
-struct MediaImage2 {
+struct __attribute__ ((__packed__)) MediaImage2 {
enum Type : uint32_t {
MEDIA_IMAGE_TYPE_UNKNOWN = 0,
MEDIA_IMAGE_TYPE_YUV,
@@ -85,7 +85,7 @@
uint32_t mBitDepth; // useable bit depth (always MSB)
uint32_t mBitDepthAllocated; // bits per component (must be 8 or 16)
- struct PlaneInfo {
+ struct __attribute__ ((__packed__)) PlaneInfo {
uint32_t mOffset; // offset of first pixel of the plane in bytes
// from buffer offset
int32_t mColInc; // column increment in bytes
@@ -98,6 +98,9 @@
void initFromV1(const MediaImage&); // for internal use only
};
+static_assert(sizeof(MediaImage2::PlaneInfo) == 20, "wrong struct size");
+static_assert(sizeof(MediaImage2) == 104, "wrong struct size");
+
/**
* Aspects of color.
*/
@@ -107,7 +110,7 @@
// though could verify that nSize is at least the size of the structure at the
// time of implementation. All new fields will be added at the end of the structure
// ensuring backward compatibility.
-struct ColorAspects {
+struct __attribute__ ((__packed__)) ColorAspects {
// this is in sync with the range values in graphics.h
enum Range : uint32_t {
RangeUnspecified,
@@ -179,6 +182,46 @@
MatrixCoeffs mMatrixCoeffs; // IN/OUT
};
+static_assert(sizeof(ColorAspects) == 16, "wrong struct size");
+
+/**
+ * HDR Metadata.
+ */
+
+// HDR Static Metadata Descriptor as defined by CTA-861-3.
+struct __attribute__ ((__packed__)) HDRStaticInfo {
+ // Static_Metadata_Descriptor_ID
+ enum ID : uint8_t {
+ kType1 = 0, // Static Metadata Type 1
+ } mID;
+
+ struct __attribute__ ((__packed__)) Primaries1 {
+ // values are in units of 0.00002
+ uint16_t x;
+ uint16_t y;
+ };
+
+ // Static Metadata Descriptor Type 1
+ struct __attribute__ ((__packed__)) Type1 {
+ Primaries1 mR; // display primary 0
+ Primaries1 mG; // display primary 1
+ Primaries1 mB; // display primary 2
+ Primaries1 mW; // white point
+ uint16_t mMaxDisplayLuminance; // in cd/m^2
+ uint16_t mMinDisplayLuminance; // in 0.0001 cd/m^2
+ uint16_t mMaxContentLightLevel; // in cd/m^2
+ uint16_t mMaxFrameAverageLightLevel; // in cd/m^2
+ };
+
+ union {
+ Type1 sType1;
+ };
+};
+
+static_assert(sizeof(HDRStaticInfo::Primaries1) == 4, "wrong struct size");
+static_assert(sizeof(HDRStaticInfo::Type1) == 24, "wrong struct size");
+static_assert(sizeof(HDRStaticInfo) == 25, "wrong struct size");
+
#ifdef STRINGIFY_ENUMS
inline static const char *asString(MediaImage::Type i, const char *def = "??") {
diff --git a/include/media/openmax/OMX_AsString.h b/include/media/openmax/OMX_AsString.h
index aacffad..5fb8ca8 100644
--- a/include/media/openmax/OMX_AsString.h
+++ b/include/media/openmax/OMX_AsString.h
@@ -292,6 +292,7 @@
// case OMX_EventDynamicResourcesAvailable: return "DynamicResourcesAvailable";
// case OMX_EventPortFormatDetected: return "PortFormatDetected";
case OMX_EventOutputRendered: return "OutputRendered";
+ case OMX_EventDataSpaceChanged: return "DataSpaceChanged";
default: return def;
}
}
diff --git a/include/media/openmax/OMX_Audio.h b/include/media/openmax/OMX_Audio.h
index a0cbd3b..d8bee76 100644
--- a/include/media/openmax/OMX_Audio.h
+++ b/include/media/openmax/OMX_Audio.h
@@ -178,7 +178,7 @@
OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
OMX_U32 nPortIndex; /**< port that this structure applies to */
OMX_U32 nChannels; /**< Number of channels (e.g. 2 for stereo) */
- OMX_NUMERICALDATATYPE eNumData; /**< indicates PCM data as signed or unsigned */
+ OMX_NUMERICALDATATYPE eNumData; /**< indicates PCM data as signed, unsigned or floating pt. */
OMX_ENDIANTYPE eEndian; /**< indicates PCM data as little or big endian */
OMX_BOOL bInterleaved; /**< True for normal interleaved data; false for
non-interleaved data (e.g. block data) */
diff --git a/include/media/openmax/OMX_Core.h b/include/media/openmax/OMX_Core.h
index f746a69..99a7622 100644
--- a/include/media/openmax/OMX_Core.h
+++ b/include/media/openmax/OMX_Core.h
@@ -524,6 +524,21 @@
* frame.
*/
OMX_EventOutputRendered = 0x7F000001,
+
+ /** For framework internal use only: event sent by OMXNodeInstance when it receives a graphic
+ * input buffer with a new dataspace for encoding. |arg1| will contain the dataspace. |arg2|
+ * will contain the ColorAspects requested by the component (or framework defaults) using
+ * the following bitfield layout:
+ *
+ * +----------+-------------+----------------+------------+
+ * | Range | Primaries | MatrixCoeffs | Transfer |
+ * +----------+-------------+----------------+------------+
+ * bits: 31....24 23.......16 15...........8 7........0
+ *
+ * TODO: We would really need to tie this to an output buffer, but OMX does not provide a
+ * fool-proof way to do that for video encoders.
+ */
+ OMX_EventDataSpaceChanged,
OMX_EventMax = 0x7FFFFFFF
} OMX_EVENTTYPE;
diff --git a/include/media/openmax/OMX_Types.h b/include/media/openmax/OMX_Types.h
index 5afaba0..515e002 100644
--- a/include/media/openmax/OMX_Types.h
+++ b/include/media/openmax/OMX_Types.h
@@ -280,12 +280,18 @@
/** The OMX_NUMERICALDATATYPE enumeration is used to indicate if data
- is signed or unsigned
+ is signed, unsigned or floating point (Android extension).
+
+ Android floating point support policy:
+ If component does not support floating point raw audio, it can reset
+ configuration to signed 16-bit integer (support for which is required.)
+ nBitsPerSample will be set to 32 for float data.
*/
typedef enum OMX_NUMERICALDATATYPE
{
OMX_NumericalDataSigned, /**< signed data */
OMX_NumericalDataUnsigned, /**< unsigned data */
+ OMX_NumericalDataFloat = 0x7F000001, /**< floating point data */
OMX_NumercialDataMax = 0x7FFFFFFF
} OMX_NUMERICALDATATYPE;
diff --git a/include/media/openmax/OMX_VideoExt.h b/include/media/openmax/OMX_VideoExt.h
index 1a2f0b5..e11f569 100644
--- a/include/media/openmax/OMX_VideoExt.h
+++ b/include/media/openmax/OMX_VideoExt.h
@@ -252,12 +252,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/powermanager/PowerManager.h b/include/powermanager/PowerManager.h
index cbddc11..3268b45 100644
--- a/include/powermanager/PowerManager.h
+++ b/include/powermanager/PowerManager.h
@@ -28,8 +28,9 @@
USER_ACTIVITY_EVENT_OTHER = 0,
USER_ACTIVITY_EVENT_BUTTON = 1,
USER_ACTIVITY_EVENT_TOUCH = 2,
+ USER_ACTIVITY_EVENT_ACCESSIBILITY = 3,
- USER_ACTIVITY_EVENT_LAST = USER_ACTIVITY_EVENT_TOUCH, // Last valid event code.
+ USER_ACTIVITY_EVENT_LAST = USER_ACTIVITY_EVENT_ACCESSIBILITY, // Last valid event code.
};
}; // namespace android
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 5cf316f..078720a 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -52,14 +52,16 @@
eFlagsChanged = 0x00000040,
eLayerStackChanged = 0x00000080,
eCropChanged = 0x00000100,
- eDeferTransaction = 0x00000200
+ eDeferTransaction = 0x00000200,
+ eFinalCropChanged = 0x00000400
};
layer_state_t()
: what(0),
x(0), y(0), z(0), w(0), h(0), layerStack(0),
alpha(0), flags(0), mask(0),
- reserved(0), crop(Rect::INVALID_RECT), frameNumber(0)
+ reserved(0), crop(Rect::INVALID_RECT),
+ finalCrop(Rect::INVALID_RECT), frameNumber(0)
{
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
@@ -88,6 +90,7 @@
uint8_t reserved;
matrix22_t matrix;
Rect crop;
+ Rect finalCrop;
sp<IBinder> handle;
uint64_t frameNumber;
// non POD must be last. see write/read
diff --git a/libs/binder/IMediaResourceMonitor.cpp b/libs/binder/IMediaResourceMonitor.cpp
index e8deb4a..4800f5b 100644
--- a/libs/binder/IMediaResourceMonitor.cpp
+++ b/libs/binder/IMediaResourceMonitor.cpp
@@ -28,15 +28,12 @@
BpMediaResourceMonitor(const sp<IBinder>& impl)
: BpInterface<IMediaResourceMonitor>(impl) {}
- virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const String16& type,
- /*in*/ const String16& subType, /*in*/ int64_t value)
+ virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const int32_t type)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaResourceMonitor::getInterfaceDescriptor());
data.writeInt32(pid);
- data.writeString16(type);
- data.writeString16(subType);
- data.writeInt64(value);
+ data.writeInt32(type);
remote()->transact(NOTIFY_RESOURCE_GRANTED, data, &reply, IBinder::FLAG_ONEWAY);
}
};
@@ -51,10 +48,8 @@
case NOTIFY_RESOURCE_GRANTED: {
CHECK_INTERFACE(IMediaResourceMonitor, data, reply);
int32_t pid = data.readInt32();
- const String16 type = data.readString16();
- const String16 subType = data.readString16();
- int64_t value = data.readInt64();
- notifyResourceGranted(/*in*/ pid, /*in*/ type, /*in*/ subType, /*in*/ value);
+ const int32_t type = data.readInt32();
+ notifyResourceGranted(/*in*/ pid, /*in*/ type);
return NO_ERROR;
} break;
default:
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 1f6bda2..1cbcfe4 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -1089,8 +1089,16 @@
<< reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
}
if (tr.target.ptr) {
- sp<BBinder> b((BBinder*)tr.cookie);
- error = b->transact(tr.code, buffer, &reply, tr.flags);
+ // We only have a weak reference on the target object, so we must first try to
+ // safely acquire a strong reference before doing anything else with it.
+ if (reinterpret_cast<RefBase::weakref_type*>(
+ tr.target.ptr)->attemptIncStrong(this)) {
+ error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
+ &reply, tr.flags);
+ reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
+ } else {
+ error = UNKNOWN_TRANSACTION;
+ }
} else {
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index 8739625..51eac11 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -135,6 +135,8 @@
void dump(const char* what) const;
void dump(String8& res, const char* what) const;
+ static size_t getAllocationAlignment() { return kMemoryAlign; }
+
private:
struct chunk_t {
@@ -264,6 +266,12 @@
return mAllocator;
}
+// static
+size_t MemoryDealer::getAllocationAlignment()
+{
+ return SimpleBestFitAllocator::getAllocationAlignment();
+}
+
// ----------------------------------------------------------------------------
// align all the memory blocks on a cache-line boundary
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 678d98b..a0161b3 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -27,6 +27,7 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/resource.h>
#include <unistd.h>
#include <binder/Binder.h>
@@ -88,6 +89,8 @@
static size_t gParcelGlobalAllocSize = 0;
static size_t gParcelGlobalAllocCount = 0;
+static size_t gMaxFds = 0;
+
// Maximum size of a blob to transfer in-place.
static const size_t BLOB_INPLACE_LIMIT = 16 * 1024;
@@ -1268,7 +1271,7 @@
const size_t len = val.getFlattenedSize();
const size_t fd_count = val.getFdCount();
- if ((len > INT32_MAX) || (fd_count > INT32_MAX)) {
+ if ((len > INT32_MAX) || (fd_count >= gMaxFds)) {
// don't accept size_t values which may have come from an
// inadvertent conversion from a negative int.
return BAD_VALUE;
@@ -1287,7 +1290,11 @@
int* fds = NULL;
if (fd_count) {
- fds = new int[fd_count];
+ fds = new (std::nothrow) int[fd_count];
+ if (fds == nullptr) {
+ ALOGE("write: failed to allocate requested %zu fds", fd_count);
+ return BAD_VALUE;
+ }
}
err = val.flatten(buf, len, fds, fd_count);
@@ -1479,7 +1486,7 @@
}
parcel->setDataPosition(start);
- val->reset(new std::vector<T>());
+ val->reset(new (std::nothrow) std::vector<T>());
status = readByteVectorInternal(parcel, val->get());
@@ -1551,7 +1558,7 @@
}
setDataPosition(start);
- val->reset(new std::vector<bool>());
+ val->reset(new (std::nothrow) std::vector<bool>());
status = readBoolVector(val->get());
@@ -1811,7 +1818,7 @@
}
setDataPosition(start);
- str->reset(new std::string());
+ str->reset(new (std::nothrow) std::string());
return readUtf8FromUtf16(str->get());
}
@@ -1864,7 +1871,7 @@
}
setDataPosition(start);
- pArg->reset(new String16());
+ pArg->reset(new (std::nothrow) String16());
status = readString16(pArg->get());
@@ -2040,7 +2047,7 @@
const size_t len = this->readInt32();
const size_t fd_count = this->readInt32();
- if (len > INT32_MAX) {
+ if ((len > INT32_MAX) || (fd_count >= gMaxFds)) {
// don't accept size_t values which may have come from an
// inadvertent conversion from a negative int.
return BAD_VALUE;
@@ -2053,7 +2060,11 @@
int* fds = NULL;
if (fd_count) {
- fds = new int[fd_count];
+ fds = new (std::nothrow) int[fd_count];
+ if (fds == nullptr) {
+ ALOGE("read: failed to allocate requested %zu fds", fd_count);
+ return BAD_VALUE;
+ }
}
status_t err = NO_ERROR;
@@ -2530,6 +2541,18 @@
mAllowFds = true;
mOwner = NULL;
mOpenAshmemSize = 0;
+
+ // racing multiple init leads only to multiple identical write
+ if (gMaxFds == 0) {
+ struct rlimit result;
+ if (!getrlimit(RLIMIT_NOFILE, &result)) {
+ gMaxFds = (size_t)result.rlim_cur;
+ //ALOGI("parcel fd limit set to %zu", gMaxFds);
+ } else {
+ ALOGW("Unable to getrlimit: %s", strerror(errno));
+ gMaxFds = 1024;
+ }
+ }
}
void Parcel::scanForFds() const
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 4029496..b591c4e 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -70,8 +70,8 @@
return INVALID_OPERATION;
}
- bool sharedBufferAvailable = mCore->mSingleBufferMode &&
- mCore->mAutoRefresh && mCore->mSingleBufferSlot !=
+ bool sharedBufferAvailable = mCore->mSharedBufferMode &&
+ mCore->mAutoRefresh && mCore->mSharedBufferSlot !=
BufferQueueCore::INVALID_BUFFER_SLOT;
// In asynchronous mode the list is guaranteed to be one buffer deep,
@@ -85,7 +85,7 @@
// If expectedPresent is specified, we may not want to return a buffer yet.
// If it's specified and there's more than one buffer queued, we may want
// to drop a buffer.
- // Skip this if we're in single buffer mode and the queue is empty,
+ // Skip this if we're in shared buffer mode and the queue is empty,
// since in that case we'll just return the shared buffer.
if (expectedPresent != 0 && !mCore->mQueue.empty()) {
const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
@@ -148,10 +148,10 @@
// Front buffer is still in mSlots, so mark the slot as free
mSlots[front->mSlot].mBufferState.freeQueued();
- // After leaving single buffer mode, the shared buffer will
+ // 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->mSingleBufferMode &&
+ if (!mCore->mSharedBufferMode &&
mSlots[front->mSlot].mBufferState.isFree()) {
mSlots[front->mSlot].mBufferState.mShared = false;
}
@@ -199,28 +199,28 @@
// make sure the buffer has finished allocating before acquiring it
mCore->waitWhileAllocatingLocked();
- slot = mCore->mSingleBufferSlot;
+ slot = mCore->mSharedBufferSlot;
// Recreate the BufferItem for the shared buffer from the data that
// was cached when it was last queued.
outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer;
outBuffer->mFence = Fence::NO_FENCE;
- outBuffer->mCrop = mCore->mSingleBufferCache.crop;
- outBuffer->mTransform = mCore->mSingleBufferCache.transform &
+ outBuffer->mCrop = mCore->mSharedBufferCache.crop;
+ outBuffer->mTransform = mCore->mSharedBufferCache.transform &
~static_cast<uint32_t>(
NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
- outBuffer->mScalingMode = mCore->mSingleBufferCache.scalingMode;
- outBuffer->mDataSpace = mCore->mSingleBufferCache.dataspace;
+ outBuffer->mScalingMode = mCore->mSharedBufferCache.scalingMode;
+ outBuffer->mDataSpace = mCore->mSharedBufferCache.dataspace;
outBuffer->mFrameNumber = mCore->mFrameCounter;
outBuffer->mSlot = slot;
outBuffer->mAcquireCalled = mSlots[slot].mAcquireCalled;
outBuffer->mTransformToDisplayInverse =
- (mCore->mSingleBufferCache.transform &
+ (mCore->mSharedBufferCache.transform &
NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
outBuffer->mSurfaceDamage = Region::INVALID_REGION;
outBuffer->mQueuedBuffer = false;
outBuffer->mIsStale = false;
- outBuffer->mAutoRefresh = mCore->mSingleBufferMode &&
+ outBuffer->mAutoRefresh = mCore->mSharedBufferMode &&
mCore->mAutoRefresh;
} else {
slot = front->mSlot;
@@ -235,7 +235,7 @@
if (!outBuffer->mIsStale) {
mSlots[slot].mAcquireCalled = true;
// Don't decrease the queue count if the BufferItem wasn't
- // previously in the queue. This happens in single buffer mode when
+ // previously in the queue. This happens in shared buffer mode when
// the queue is empty and the BufferItem is created above.
if (mCore->mQueue.empty()) {
mSlots[slot].mBufferState.acquireNotInQueue();
@@ -284,9 +284,8 @@
return NO_INIT;
}
- if (mCore->mSingleBufferMode || slot == mCore->mSingleBufferSlot) {
- BQ_LOGE("detachBuffer: detachBuffer not allowed in single buffer"
- "mode");
+ if (mCore->mSharedBufferMode || slot == mCore->mSharedBufferSlot) {
+ BQ_LOGE("detachBuffer: detachBuffer not allowed in shared buffer mode");
return BAD_VALUE;
}
@@ -324,9 +323,8 @@
Mutex::Autolock lock(mCore->mMutex);
- if (mCore->mSingleBufferMode) {
- BQ_LOGE("attachBuffer: cannot attach a buffer in single buffer"
- "mode");
+ if (mCore->mSharedBufferMode) {
+ BQ_LOGE("attachBuffer: cannot attach a buffer in shared buffer mode");
return BAD_VALUE;
}
@@ -439,10 +437,10 @@
mSlots[slot].mFence = releaseFence;
mSlots[slot].mBufferState.release();
- // After leaving single buffer mode, the shared buffer will
+ // 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->mSingleBufferMode && mSlots[slot].mBufferState.isFree()) {
+ if (!mCore->mSharedBufferMode && mSlots[slot].mBufferState.isFree()) {
mSlots[slot].mBufferState.mShared = false;
}
// Don't put the shared buffer on the free list.
@@ -507,7 +505,7 @@
mCore->mConsumerListener = NULL;
mCore->mQueue.clear();
mCore->freeAllBuffersLocked();
- mCore->mSingleBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
+ mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
mCore->mDequeueCondition.broadcast();
return NO_ERROR;
}
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index ba07362..cdece73 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -78,10 +78,10 @@
mBufferAge(0),
mGenerationNumber(0),
mAsyncMode(false),
- mSingleBufferMode(false),
+ mSharedBufferMode(false),
mAutoRefresh(false),
- mSingleBufferSlot(INVALID_BUFFER_SLOT),
- mSingleBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
+ mSharedBufferSlot(INVALID_BUFFER_SLOT),
+ mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
HAL_DATASPACE_UNKNOWN)
{
if (allocator == NULL) {
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index e9d0654..bb8d39b 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -272,11 +272,11 @@
BQ_LOGV("%s: queue size is %zu, waiting", callerString,
mCore->mQueue.size());
} else {
- // If in single buffer mode and a shared buffer exists, always
+ // If in shared buffer mode and a shared buffer exists, always
// return it.
- if (mCore->mSingleBufferMode && mCore->mSingleBufferSlot !=
+ if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot !=
BufferQueueCore::INVALID_BUFFER_SLOT) {
- *found = mCore->mSingleBufferSlot;
+ *found = mCore->mSharedBufferSlot;
} else {
if (caller == FreeSlotCaller::Dequeue) {
// If we're calling this from dequeue, prefer free buffers
@@ -400,7 +400,7 @@
// requested attributes, we free it and attempt to get another one.
if (!mCore->mAllowAllocation) {
if (buffer->needsReallocation(width, height, format, usage)) {
- if (mCore->mSingleBufferSlot == found) {
+ if (mCore->mSharedBufferSlot == found) {
BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
"buffer");
return BAD_VALUE;
@@ -414,7 +414,7 @@
}
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
- if (mCore->mSingleBufferSlot == found &&
+ if (mCore->mSharedBufferSlot == found &&
buffer->needsReallocation(width, height, format, usage)) {
BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
"buffer");
@@ -422,7 +422,7 @@
return BAD_VALUE;
}
- if (mCore->mSingleBufferSlot != found) {
+ if (mCore->mSharedBufferSlot != found) {
mCore->mActiveBuffers.insert(found);
}
*outSlot = found;
@@ -433,11 +433,11 @@
mSlots[found].mBufferState.dequeue();
- // If single buffer mode has just been enabled, cache the slot of the
+ // If shared buffer mode has just been enabled, cache the slot of the
// first buffer that is dequeued and mark it as the shared buffer.
- if (mCore->mSingleBufferMode && mCore->mSingleBufferSlot ==
+ if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
BufferQueueCore::INVALID_BUFFER_SLOT) {
- mCore->mSingleBufferSlot = found;
+ mCore->mSharedBufferSlot = found;
mSlots[found].mBufferState.mShared = true;
}
@@ -550,8 +550,8 @@
return NO_INIT;
}
- if (mCore->mSingleBufferMode || mCore->mSingleBufferSlot == slot) {
- BQ_LOGE("detachBuffer: cannot detach a buffer in single buffer mode");
+ if (mCore->mSharedBufferMode || mCore->mSharedBufferSlot == slot) {
+ BQ_LOGE("detachBuffer: cannot detach a buffer in shared buffer mode");
return BAD_VALUE;
}
@@ -603,9 +603,9 @@
return NO_INIT;
}
- if (mCore->mSingleBufferMode) {
- BQ_LOGE("detachNextBuffer: cannot detach a buffer in single buffer"
- "mode");
+ if (mCore->mSharedBufferMode) {
+ BQ_LOGE("detachNextBuffer: cannot detach a buffer in shared buffer "
+ "mode");
return BAD_VALUE;
}
@@ -653,8 +653,8 @@
return NO_INIT;
}
- if (mCore->mSingleBufferMode) {
- BQ_LOGE("attachBuffer: cannot attach a buffer in single buffer mode");
+ if (mCore->mSharedBufferMode) {
+ BQ_LOGE("attachBuffer: cannot attach a buffer in shared buffer mode");
return BAD_VALUE;
}
@@ -761,6 +761,14 @@
return BAD_VALUE;
}
+ // If shared buffer mode has just been enabled, cache the slot of the
+ // first buffer that is queued and mark it as the shared buffer.
+ if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
+ BufferQueueCore::INVALID_BUFFER_SLOT) {
+ mCore->mSharedBufferSlot = slot;
+ mSlots[slot].mBufferState.mShared = true;
+ }
+
BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
" crop=[%d,%d,%d,%d] transform=%#x scale=%s",
slot, mCore->mFrameCounter + 1, timestamp, dataSpace,
@@ -804,20 +812,20 @@
item.mFence = fence;
item.mIsDroppable = mCore->mAsyncMode ||
mCore->mDequeueBufferCannotBlock ||
- (mCore->mSingleBufferMode && mCore->mSingleBufferSlot == slot);
+ (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
item.mSurfaceDamage = surfaceDamage;
item.mQueuedBuffer = true;
- item.mAutoRefresh = mCore->mSingleBufferMode && mCore->mAutoRefresh;
+ item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
mStickyTransform = stickyTransform;
// Cache the shared buffer data so that the BufferItem can be recreated.
- if (mCore->mSingleBufferMode) {
- mCore->mSingleBufferCache.crop = crop;
- mCore->mSingleBufferCache.transform = transform;
- mCore->mSingleBufferCache.scalingMode = static_cast<uint32_t>(
+ if (mCore->mSharedBufferMode) {
+ mCore->mSharedBufferCache.crop = crop;
+ mCore->mSharedBufferCache.transform = transform;
+ mCore->mSharedBufferCache.scalingMode = static_cast<uint32_t>(
scalingMode);
- mCore->mSingleBufferCache.dataspace = dataSpace;
+ mCore->mSharedBufferCache.dataspace = dataSpace;
}
if (mCore->mQueue.empty()) {
@@ -834,10 +842,10 @@
if (!front->mIsStale) {
mSlots[front->mSlot].mBufferState.freeQueued();
- // After leaving single buffer mode, the shared buffer will
+ // 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->mSingleBufferMode &&
+ if (!mCore->mSharedBufferMode &&
mSlots[front->mSlot].mBufferState.isFree()) {
mSlots[front->mSlot].mBufferState.mShared = false;
}
@@ -922,8 +930,8 @@
return NO_INIT;
}
- if (mCore->mSingleBufferMode) {
- BQ_LOGE("cancelBuffer: cannot cancel a buffer in single buffer mode");
+ if (mCore->mSharedBufferMode) {
+ BQ_LOGE("cancelBuffer: cannot cancel a buffer in shared buffer mode");
return BAD_VALUE;
}
@@ -942,9 +950,9 @@
mSlots[slot].mBufferState.cancel();
- // After leaving single buffer mode, the shared buffer will still be around.
+ // 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->mSingleBufferMode && mSlots[slot].mBufferState.isFree()) {
+ if (!mCore->mSharedBufferMode && mSlots[slot].mBufferState.isFree()) {
mSlots[slot].mBufferState.mShared = false;
}
@@ -1141,7 +1149,7 @@
token->unlinkToDeath(
static_cast<IBinder::DeathRecipient*>(this));
}
- mCore->mSingleBufferSlot =
+ mCore->mSharedBufferSlot =
BufferQueueCore::INVALID_BUFFER_SLOT;
mCore->mConnectedProducerListener = NULL;
mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
@@ -1306,15 +1314,15 @@
return nextFrameNumber;
}
-status_t BufferQueueProducer::setSingleBufferMode(bool singleBufferMode) {
+status_t BufferQueueProducer::setSharedBufferMode(bool sharedBufferMode) {
ATRACE_CALL();
- BQ_LOGV("setSingleBufferMode: %d", singleBufferMode);
+ BQ_LOGV("setSharedBufferMode: %d", sharedBufferMode);
Mutex::Autolock lock(mCore->mMutex);
- if (!singleBufferMode) {
- mCore->mSingleBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
+ if (!sharedBufferMode) {
+ mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
}
- mCore->mSingleBufferMode = singleBufferMode;
+ mCore->mSharedBufferMode = sharedBufferMode;
return NO_ERROR;
}
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index a22b81b..2187e5e 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -74,26 +74,12 @@
} else {
mConsumer->setConsumerName(mName);
}
-
- mMessageThread = new MessageThread(this);
- mMessageThread->run();
}
ConsumerBase::~ConsumerBase() {
CB_LOGV("~ConsumerBase");
-
- mMessageThread->requestExit();
- {
- Mutex::Autolock lock(mMessageQueueLock);
- mMessageQueue.emplace(std::piecewise_construct,
- std::forward_as_tuple(EXIT),
- std::forward_as_tuple());
- mMessageAvailable.signal();
- }
-
- mMessageThread->join();
-
Mutex::Autolock lock(mMutex);
+
// Verify that abandon() has been called before we get here. This should
// be done by ConsumerBase::onLastStrongRef(), but it's possible for a
// derived class to override that method and not call
@@ -114,13 +100,6 @@
}
void ConsumerBase::onFrameAvailable(const BufferItem& item) {
- Mutex::Autolock lock(mMessageQueueLock);
- mMessageQueue.emplace(std::piecewise_construct,
- std::forward_as_tuple(ON_FRAME_AVAILABLE),
- std::forward_as_tuple(item));
- mMessageAvailable.signal();
-}
-void ConsumerBase::onFrameAvailableHandler(const BufferItem& item) {
CB_LOGV("onFrameAvailable");
sp<FrameAvailableListener> listener;
@@ -136,14 +115,6 @@
}
void ConsumerBase::onFrameReplaced(const BufferItem &item) {
- Mutex::Autolock lock(mMessageQueueLock);
- mMessageQueue.emplace(std::piecewise_construct,
- std::forward_as_tuple(ON_FRAME_REPLACED),
- std::forward_as_tuple(item));
- mMessageAvailable.signal();
-}
-
-void ConsumerBase::onFrameReplacedHandler(const BufferItem &item) {
CB_LOGV("onFrameReplaced");
sp<FrameAvailableListener> listener;
@@ -159,14 +130,6 @@
}
void ConsumerBase::onBuffersReleased() {
- Mutex::Autolock lock(mMessageQueueLock);
- mMessageQueue.emplace(std::piecewise_construct,
- std::forward_as_tuple(ON_BUFFERS_RELEASED),
- std::forward_as_tuple());
- mMessageAvailable.signal();
-}
-
-void ConsumerBase::onBuffersReleasedHandler() {
Mutex::Autolock lock(mMutex);
CB_LOGV("onBuffersReleased");
@@ -186,45 +149,6 @@
}
void ConsumerBase::onSidebandStreamChanged() {
- Mutex::Autolock lock(mMessageQueueLock);
- mMessageQueue.emplace(std::piecewise_construct,
- std::forward_as_tuple(ON_SIDEBAND_STREAM_CHANGED),
- std::forward_as_tuple());
- mMessageAvailable.signal();
-}
-
-void ConsumerBase::onSidebandStreamChangedHandler() {
-}
-
-bool ConsumerBase::MessageThread::threadLoop() {
- Mutex::Autolock lock(mConsumerBase->mMessageQueueLock);
-
- if (mConsumerBase->mMessageQueue.empty()) {
- mConsumerBase->mMessageAvailable.wait(mConsumerBase->mMessageQueueLock);
- }
-
- while (!mConsumerBase->mMessageQueue.empty()) {
- auto nextMessage = mConsumerBase->mMessageQueue.front();
-
- switch (nextMessage.first) {
- case ON_FRAME_AVAILABLE:
- mConsumerBase->onFrameAvailableHandler(nextMessage.second);
- break;
- case ON_FRAME_REPLACED:
- mConsumerBase->onFrameReplacedHandler(nextMessage.second);
- break;
- case ON_BUFFERS_RELEASED:
- mConsumerBase->onBuffersReleasedHandler();
- break;
- case ON_SIDEBAND_STREAM_CHANGED:
- mConsumerBase->onSidebandStreamChangedHandler();
- break;
- case EXIT:
- break;
- }
- mConsumerBase->mMessageQueue.pop();
- }
- return true;
}
void ConsumerBase::abandon() {
@@ -238,7 +162,7 @@
}
void ConsumerBase::abandonLocked() {
- CB_LOGV("abandonLocked");
+ CB_LOGV("abandonLocked");
for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
freeBufferLocked(i);
}
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 149f5bd..3acd3ab 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -393,6 +393,21 @@
return err;
}
+ // For investigating b/27674961
+ if (mEglSlots[slot].mEglImage == nullptr) {
+ ALOGE("If you see this message in a log please post the log to "
+ "b/27674961");
+ ALOGE("slot = %d, mCurrentTexture = %d, mCurrentTextureImage = %p",
+ slot, mCurrentTexture, mCurrentTextureImage.get());
+ for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+ ALOGE("mEglSlots[%d].mEglImage = %p", i,
+ mEglSlots[i].mEglImage.get());
+ }
+ String8 dump;
+ dumpLocked(dump, "");
+ ALOGE("%s", dump.string());
+ }
+
// Ensure we have a valid EglImageKHR for the slot, creating an EglImage
// if nessessary, for the gralloc buffer currently in the slot in
// ConsumerBase.
@@ -427,7 +442,7 @@
slot, mSlots[slot].mGraphicBuffer->handle);
// Hang onto the pointer so that it isn't freed in the call to
- // releaseBufferLocked() if we're in single buffer mode and both buffers are
+ // releaseBufferLocked() if we're in shared buffer mode and both buffers are
// the same.
sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index a75569f..cb1ad35 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -338,7 +338,7 @@
}
case GET_RELEASED_BUFFERS: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- uint64_t slotMask;
+ uint64_t slotMask = 0;
status_t result = getReleasedBuffers(&slotMask);
reply->writeInt64(static_cast<int64_t>(slotMask));
reply->writeInt32(result);
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index c66694d..7cdb8f4 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -51,7 +51,7 @@
SET_MAX_DEQUEUED_BUFFER_COUNT,
SET_ASYNC_MODE,
GET_NEXT_FRAME_NUMBER,
- SET_SINGLE_BUFFER_MODE,
+ SET_SHARED_BUFFER_MODE,
SET_AUTO_REFRESH,
SET_DEQUEUE_TIMEOUT,
};
@@ -343,12 +343,12 @@
return frameNumber;
}
- virtual status_t setSingleBufferMode(bool singleBufferMode) {
+ virtual status_t setSharedBufferMode(bool sharedBufferMode) {
Parcel data, reply;
data.writeInterfaceToken(
IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(singleBufferMode);
- status_t result = remote()->transact(SET_SINGLE_BUFFER_MODE, data,
+ data.writeInt32(sharedBufferMode);
+ status_t result = remote()->transact(SET_SHARED_BUFFER_MODE, data,
&reply);
if (result == NO_ERROR) {
result = reply.readInt32();
@@ -513,6 +513,7 @@
QueueBufferOutput* const output =
reinterpret_cast<QueueBufferOutput *>(
reply->writeInplace(sizeof(QueueBufferOutput)));
+ memset(output, 0, sizeof(QueueBufferOutput));
status_t res = connect(listener, api, producerControlledByApp, output);
reply->writeInt32(res);
return NO_ERROR;
@@ -568,10 +569,10 @@
reply->writeUint64(frameNumber);
return NO_ERROR;
}
- case SET_SINGLE_BUFFER_MODE: {
+ case SET_SHARED_BUFFER_MODE: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- bool singleBufferMode = data.readInt32();
- status_t result = setSingleBufferMode(singleBufferMode);
+ bool sharedBufferMode = data.readInt32();
+ status_t result = setSharedBufferMode(sharedBufferMode);
reply->writeInt32(result);
return NO_ERROR;
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 06f13e8..e43342e 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -38,6 +38,7 @@
*reinterpret_cast<layer_state_t::matrix22_t *>(
output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix;
output.write(crop);
+ output.write(finalCrop);
output.writeStrongBinder(handle);
output.writeUint64(frameNumber);
output.write(transparentRegion);
@@ -64,6 +65,7 @@
return BAD_VALUE;
}
input.read(crop);
+ input.read(finalCrop);
handle = input.readStrongBinder();
frameNumber = input.readUint64();
input.read(transparentRegion);
diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp
index 4b7986e..6d69839 100644
--- a/libs/gui/SensorEventQueue.cpp
+++ b/libs/gui/SensorEventQueue.cpp
@@ -125,11 +125,16 @@
}
status_t SensorEventQueue::enableSensor(Sensor const* sensor) const {
- return mSensorEventConnection->enableDisable(sensor->getHandle(), true, 0, 0, false);
+ return enableSensor(sensor, SENSOR_DELAY_NORMAL);
+}
+
+status_t SensorEventQueue::enableSensor(Sensor const* sensor, int32_t samplingPeriodUs) const {
+ return mSensorEventConnection->enableDisable(sensor->getHandle(), true,
+ us2ns(samplingPeriodUs), 0, 0);
}
status_t SensorEventQueue::disableSensor(Sensor const* sensor) const {
- return mSensorEventConnection->enableDisable(sensor->getHandle(), false, 0, 0, false);
+ return mSensorEventConnection->enableDisable(sensor->getHandle(), false, 0, 0, 0);
}
status_t SensorEventQueue::enableSensor(int32_t handle, int32_t samplingPeriodUs,
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 8025ca5..76b62f1 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -45,7 +45,7 @@
: mGraphicBufferProducer(bufferProducer),
mCrop(Rect::EMPTY_RECT),
mGenerationNumber(0),
- mSingleBufferMode(false),
+ mSharedBufferMode(false),
mAutoRefresh(false),
mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
mSharedBufferHasBeenQueued(false)
@@ -237,7 +237,7 @@
reqFormat = mReqFormat;
reqUsage = mReqUsage;
- if (mSingleBufferMode && mAutoRefresh && mSharedBufferSlot !=
+ if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot !=
BufferItem::INVALID_BUFFER_SLOT) {
sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer);
if (gbuf != NULL) {
@@ -294,7 +294,7 @@
*buffer = gbuf.get();
- if (mSingleBufferMode && mAutoRefresh) {
+ if (mSharedBufferMode && mAutoRefresh) {
mSharedBufferSlot = buf;
mSharedBufferHasBeenQueued = false;
} else if (mSharedBufferSlot == buf) {
@@ -326,7 +326,7 @@
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
mGraphicBufferProducer->cancelBuffer(i, fence);
- if (mSingleBufferMode && mAutoRefresh && mSharedBufferSlot == i) {
+ if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot == i) {
mSharedBufferHasBeenQueued = true;
}
@@ -476,7 +476,7 @@
mDirtyRegion = Region::INVALID_REGION;
}
- if (mSingleBufferMode && mAutoRefresh && mSharedBufferSlot == i) {
+ if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot == i) {
mSharedBufferHasBeenQueued = true;
}
@@ -600,8 +600,8 @@
case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
res = dispatchSetSurfaceDamage(args);
break;
- case NATIVE_WINDOW_SET_SINGLE_BUFFER_MODE:
- res = dispatchSetSingleBufferMode(args);
+ case NATIVE_WINDOW_SET_SHARED_BUFFER_MODE:
+ res = dispatchSetSharedBufferMode(args);
break;
case NATIVE_WINDOW_SET_AUTO_REFRESH:
res = dispatchSetAutoRefresh(args);
@@ -716,9 +716,9 @@
return NO_ERROR;
}
-int Surface::dispatchSetSingleBufferMode(va_list args) {
- bool singleBufferMode = va_arg(args, int);
- return setSingleBufferMode(singleBufferMode);
+int Surface::dispatchSetSharedBufferMode(va_list args) {
+ bool sharedBufferMode = va_arg(args, int);
+ return setSharedBufferMode(sharedBufferMode);
}
int Surface::dispatchSetAutoRefresh(va_list args) {
@@ -927,18 +927,18 @@
return err;
}
-int Surface::setSingleBufferMode(bool singleBufferMode) {
+int Surface::setSharedBufferMode(bool sharedBufferMode) {
ATRACE_CALL();
- ALOGV("Surface::setSingleBufferMode (%d)", singleBufferMode);
+ ALOGV("Surface::setSharedBufferMode (%d)", sharedBufferMode);
Mutex::Autolock lock(mMutex);
- status_t err = mGraphicBufferProducer->setSingleBufferMode(
- singleBufferMode);
+ status_t err = mGraphicBufferProducer->setSharedBufferMode(
+ sharedBufferMode);
if (err == NO_ERROR) {
- mSingleBufferMode = singleBufferMode;
+ mSharedBufferMode = sharedBufferMode;
}
- ALOGE_IF(err, "IGraphicBufferProducer::setSingleBufferMode(%d) returned"
- "%s", singleBufferMode, strerror(-err));
+ ALOGE_IF(err, "IGraphicBufferProducer::setSharedBufferMode(%d) returned"
+ "%s", sharedBufferMode, strerror(-err));
return err;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 3242f55..04b5446 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -156,6 +156,8 @@
status_t setOrientation(int orientation);
status_t setCrop(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
const Rect& crop);
+ status_t setFinalCrop(const sp<SurfaceComposerClient>& client,
+ const sp<IBinder>& id, const Rect& crop);
status_t setLayerStack(const sp<SurfaceComposerClient>& client,
const sp<IBinder>& id, uint32_t layerStack);
status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
@@ -386,6 +388,18 @@
return NO_ERROR;
}
+status_t Composer::setFinalCrop(const sp<SurfaceComposerClient>& client,
+ const sp<IBinder>& id, const Rect& crop) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s) {
+ return BAD_INDEX;
+ }
+ s->what |= layer_state_t::eFinalCropChanged;
+ s->finalCrop = crop;
+ return NO_ERROR;
+}
+
status_t Composer::deferTransactionUntil(
const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
const sp<IBinder>& handle, uint64_t frameNumber) {
@@ -579,6 +593,11 @@
return getComposer().setCrop(this, id, crop);
}
+status_t SurfaceComposerClient::setFinalCrop(const sp<IBinder>& id,
+ const Rect& crop) {
+ return getComposer().setFinalCrop(this, id, crop);
+}
+
status_t SurfaceComposerClient::setPosition(const sp<IBinder>& id, float x, float y) {
return getComposer().setPosition(this, id, x, y);
}
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index e1a951c..184de71 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -152,6 +152,11 @@
if (err < 0) return err;
return mClient->setCrop(mHandle, crop);
}
+status_t SurfaceControl::setFinalCrop(const Rect& crop) {
+ status_t err = validate();
+ if (err < 0) return err;
+ return mClient->setFinalCrop(mHandle, crop);
+}
status_t SurfaceControl::deferTransactionUntil(sp<IBinder> handle,
uint64_t frameNumber) {
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index b6af166..82df9a9 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -291,7 +291,7 @@
sp<DummyConsumer> dc(new DummyConsumer);
mConsumer->consumerConnect(dc, false);
- // Test single buffer mode
+ // Test shared buffer mode
EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
}
@@ -542,7 +542,7 @@
ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
}
-TEST_F(BufferQueueTest, TestSingleBufferModeWithoutAutoRefresh) {
+TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
createBufferQueue();
sp<DummyConsumer> dc(new DummyConsumer);
ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
@@ -550,21 +550,21 @@
ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
NATIVE_WINDOW_API_CPU, true, &output));
- ASSERT_EQ(OK, mProducer->setSingleBufferMode(true));
+ ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
// Get a buffer
- int singleSlot;
+ int sharedSlot;
sp<Fence> fence;
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&singleSlot, &fence, 0, 0, 0, 0));
- ASSERT_EQ(OK, mProducer->requestBuffer(singleSlot, &buffer));
+ mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
// Queue the buffer
IGraphicBufferProducer::QueueBufferInput input(0, false,
HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
- ASSERT_EQ(OK, mProducer->queueBuffer(singleSlot, input, &output));
+ ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
// Repeatedly queue and dequeue a buffer from the producer side, it should
// always return the same one. And we won't run out of buffers because it's
@@ -572,14 +572,14 @@
int slot;
for (int i = 0; i < 5; i++) {
ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
- ASSERT_EQ(singleSlot, slot);
- ASSERT_EQ(OK, mProducer->queueBuffer(singleSlot, input, &output));
+ ASSERT_EQ(sharedSlot, slot);
+ ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
}
// acquire the buffer
BufferItem item;
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
- ASSERT_EQ(singleSlot, item.mSlot);
+ ASSERT_EQ(sharedSlot, item.mSlot);
testBufferItem(input, item);
ASSERT_EQ(true, item.mQueuedBuffer);
ASSERT_EQ(false, item.mAutoRefresh);
@@ -592,7 +592,7 @@
mConsumer->acquireBuffer(&item, 0));
}
-TEST_F(BufferQueueTest, TestSingleBufferModeWithAutoRefresh) {
+TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
createBufferQueue();
sp<DummyConsumer> dc(new DummyConsumer);
ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
@@ -600,29 +600,29 @@
ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
NATIVE_WINDOW_API_CPU, true, &output));
- ASSERT_EQ(OK, mProducer->setSingleBufferMode(true));
+ ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
// Get a buffer
- int singleSlot;
+ int sharedSlot;
sp<Fence> fence;
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&singleSlot, &fence, 0, 0, 0, 0));
- ASSERT_EQ(OK, mProducer->requestBuffer(singleSlot, &buffer));
+ mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
// Queue the buffer
IGraphicBufferProducer::QueueBufferInput input(0, false,
HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
- ASSERT_EQ(OK, mProducer->queueBuffer(singleSlot, input, &output));
+ ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
// Repeatedly acquire and release a buffer from the consumer side, it should
// always return the same one.
BufferItem item;
for (int i = 0; i < 5; i++) {
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
- ASSERT_EQ(singleSlot, item.mSlot);
+ ASSERT_EQ(sharedSlot, item.mSlot);
testBufferItem(input, item);
ASSERT_EQ(i == 0, item.mQueuedBuffer);
ASSERT_EQ(true, item.mAutoRefresh);
@@ -636,16 +636,16 @@
int slot;
for (int i = 0; i < 5; i++) {
ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
- ASSERT_EQ(singleSlot, slot);
- ASSERT_EQ(OK, mProducer->queueBuffer(singleSlot, input, &output));
+ ASSERT_EQ(sharedSlot, slot);
+ ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
}
// Repeatedly acquire and release a buffer from the consumer side, it should
// always return the same one. First grabbing them from the queue and then
- // when the queue is empty, returning the single buffer.
+ // when the queue is empty, returning the shared buffer.
for (int i = 0; i < 10; i++) {
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
- ASSERT_EQ(singleSlot, item.mSlot);
+ ASSERT_EQ(sharedSlot, item.mSlot);
ASSERT_EQ(0, item.mTimestamp);
ASSERT_EQ(false, item.mIsAutoTimestamp);
ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
@@ -661,6 +661,57 @@
}
}
+TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
+ createBufferQueue();
+ sp<DummyConsumer> dc(new DummyConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ IGraphicBufferProducer::QueueBufferOutput output;
+ ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+ NATIVE_WINDOW_API_CPU, true, &output));
+
+ // Dequeue a buffer
+ int sharedSlot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buffer;
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
+
+ // Enable shared buffer mode
+ ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
+
+ // Queue the buffer
+ IGraphicBufferProducer::QueueBufferInput input(0, false,
+ HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+ ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
+
+ // Repeatedly queue and dequeue a buffer from the producer side, it should
+ // always return the same one. And we won't run out of buffers because it's
+ // always the same one and because async mode gets enabled.
+ int slot;
+ for (int i = 0; i < 5; i++) {
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(sharedSlot, slot);
+ ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
+ }
+
+ // acquire the buffer
+ BufferItem item;
+ ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+ ASSERT_EQ(sharedSlot, item.mSlot);
+ testBufferItem(input, item);
+ ASSERT_EQ(true, item.mQueuedBuffer);
+ ASSERT_EQ(false, item.mAutoRefresh);
+
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
+ EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+
+ // attempt to acquire a second time should return no buffer available
+ ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
+ mConsumer->acquireBuffer(&item, 0));
+}
+
TEST_F(BufferQueueTest, TestTimeouts) {
createBufferQueue();
sp<DummyConsumer> dc(new DummyConsumer);
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 2356f54..a1578f6 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -564,7 +564,7 @@
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
- thread->run();
+ thread->run("MyThread");
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
//ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL.h b/libs/gui/tests/SurfaceTextureGLThreadToGL.h
index 14e42ac..2ce20eb 100644
--- a/libs/gui/tests/SurfaceTextureGLThreadToGL.h
+++ b/libs/gui/tests/SurfaceTextureGLThreadToGL.h
@@ -171,7 +171,7 @@
mProducerThread = producerThread;
producerThread->setEglObjects(mEglDisplay, mProducerEglSurface,
mProducerEglContext);
- producerThread->run();
+ producerThread->run("ProducerThread");
}
sp<ProducerThread> mProducerThread;
diff --git a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
index b8a7a90..c28b4d1 100644
--- a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
@@ -192,10 +192,6 @@
ASSERT_EQ(EGL_SUCCESS, eglGetError());
mProducerEglSurface = EGL_NO_SURFACE;
- // sleep for 10ms to allow any asynchronous operations to complete before
- // checking the reference counts
- usleep(10000);
-
// This test should have the only reference to buffer 0.
EXPECT_EQ(1, buffers[0]->getStrongCount());
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index 1a904b5..dddcf92 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -295,7 +295,7 @@
};
sp<Thread> pt(new ProducerThread(mANW, testPixels));
- pt->run();
+ pt->run("ProducerThread");
glViewport(0, 0, texWidth, texHeight);
@@ -484,7 +484,7 @@
sp<Thread> pt(new ProducerThread(mANW));
- pt->run();
+ pt->run("ProducerThread");
// eat a frame so GLConsumer will own an at least one slot
dw->waitForFrame();
@@ -681,7 +681,7 @@
};
sp<Thread> pt(new ProducerThread(mANW));
- pt->run();
+ pt->run("ProducerThread");
mFW->waitForFrame();
mFW->waitForFrame();
diff --git a/opengl/include/GLES2/gl2.h b/opengl/include/GLES2/gl2.h
index e29a789..f64ec00 100644
--- a/opengl/include/GLES2/gl2.h
+++ b/opengl/include/GLES2/gl2.h
@@ -42,6 +42,10 @@
#define GL_APIENTRYP GL_APIENTRY*
#endif
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
/* Generated on date 20151015 */
/* Generated C header for:
@@ -520,7 +524,7 @@
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
-#ifdef GL_GLEXT_PROTOTYPES
+#if GL_GLES_PROTOTYPES
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
diff --git a/opengl/include/GLES3/gl3.h b/opengl/include/GLES3/gl3.h
index 383230f..d51d2e6 100644
--- a/opengl/include/GLES3/gl3.h
+++ b/opengl/include/GLES3/gl3.h
@@ -42,6 +42,10 @@
#define GL_APIENTRYP GL_APIENTRY*
#endif
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
/* Generated on date 20151015 */
/* Generated C header for:
@@ -520,7 +524,7 @@
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
-#ifdef GL_GLEXT_PROTOTYPES
+#if GL_GLES_PROTOTYPES
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
@@ -1094,7 +1098,7 @@
typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
-#ifdef GL_GLEXT_PROTOTYPES
+#if GL_GLES_PROTOTYPES
GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
diff --git a/opengl/include/GLES3/gl31.h b/opengl/include/GLES3/gl31.h
index 922a20a..9b89a0a 100644
--- a/opengl/include/GLES3/gl31.h
+++ b/opengl/include/GLES3/gl31.h
@@ -42,6 +42,10 @@
#define GL_APIENTRYP GL_APIENTRY*
#endif
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
/* Generated on date 20151015 */
/* Generated C header for:
@@ -520,7 +524,7 @@
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
-#ifdef GL_GLEXT_PROTOTYPES
+#if GL_GLES_PROTOTYPES
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
@@ -1094,7 +1098,7 @@
typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
-#ifdef GL_GLEXT_PROTOTYPES
+#if GL_GLES_PROTOTYPES
GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
@@ -1445,7 +1449,7 @@
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
typedef void (GL_APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
-#ifdef GL_GLEXT_PROTOTYPES
+#if GL_GLES_PROTOTYPES
GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect);
GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
diff --git a/opengl/include/GLES3/gl32.h b/opengl/include/GLES3/gl32.h
index 21bded5..a2c3611 100644
--- a/opengl/include/GLES3/gl32.h
+++ b/opengl/include/GLES3/gl32.h
@@ -42,6 +42,10 @@
#define GL_APIENTRYP GL_APIENTRY*
#endif
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
/* Generated on date 20151015 */
/* Generated C header for:
@@ -520,7 +524,7 @@
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
-#ifdef GL_GLEXT_PROTOTYPES
+#if GL_GLES_PROTOTYPES
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
@@ -1094,7 +1098,7 @@
typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
-#ifdef GL_GLEXT_PROTOTYPES
+#if GL_GLES_PROTOTYPES
GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
@@ -1445,7 +1449,7 @@
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
typedef void (GL_APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
-#ifdef GL_GLEXT_PROTOTYPES
+#if GL_GLES_PROTOTYPES
GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect);
GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
@@ -1770,7 +1774,7 @@
typedef void (GL_APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer);
typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
-#ifdef GL_GLEXT_PROTOTYPES
+#if GL_GLES_PROTOTYPES
GL_APICALL void GL_APIENTRY glBlendBarrier (void);
GL_APICALL void GL_APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
GL_APICALL void GL_APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
diff --git a/opengl/include/KHR/khrplatform.h b/opengl/include/KHR/khrplatform.h
index a570d6c..153bbbd 100644
--- a/opengl/include/KHR/khrplatform.h
+++ b/opengl/include/KHR/khrplatform.h
@@ -92,8 +92,6 @@
* int arg2) KHRONOS_APIATTRIBUTES;
*/
-#define GL_GLEXT_PROTOTYPES
-
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 794a7e5..e7703d8 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -1196,8 +1196,10 @@
egl_surface_t const * const s = get_surface(surface);
if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
- return (native_window_set_auto_refresh(s->win.get(),
- value ? true : false)) ? EGL_TRUE : EGL_FALSE;
+ int err = native_window_set_auto_refresh(s->win.get(),
+ value ? true : false);
+ return (err == NO_ERROR) ? EGL_TRUE :
+ setError(EGL_BAD_SURFACE, EGL_FALSE);
}
if (s->cnx->egl.eglSurfaceAttrib) {
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index f368d75..8c135c8 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -165,7 +165,7 @@
// running, so there's no need to keep a ref around.
sp<Thread> deferredSaveThread(new DeferredSaveThread());
mSavePending = true;
- deferredSaveThread->run();
+ deferredSaveThread->run("DeferredSaveThread");
}
}
}
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index ef17630..57c56a6 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -20,7 +20,7 @@
LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
-LOCAL_CFLAGS += -Wall -Werror
+LOCAL_CFLAGS += -Wall -Werror -Wextra
LOCAL_CFLAGS += -fvisibility=hidden
@@ -50,6 +50,8 @@
libbinder \
libutils
+LOCAL_CFLAGS := -Wall -Werror -Wextra
+
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= sensorservice
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 66ef4eb..31ca0e3 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -65,12 +65,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());
@@ -244,9 +242,11 @@
}
}
-Sensor SensorService::registerSensor(SensorInterface* s)
-{
+Sensor SensorService::registerSensor(SensorInterface* s) {
const Sensor sensor(s->getSensor());
+
+ // add handle to used handle list
+ mUsedHandleList.add(sensor.getHandle());
// add to the sensor list (returned to clients)
mSensorList.add(sensor);
// add to our handle->SensorInterface mapping
@@ -257,17 +257,21 @@
return sensor;
}
-Sensor SensorService::registerDynamicSensor(SensorInterface* s)
-{
+Sensor SensorService::registerDynamicSensor(SensorInterface* s) {
Sensor sensor = registerSensor(s);
mDynamicSensorList.add(sensor);
+
+ auto compareSensorHandle = [] (const Sensor* lhs, const Sensor* rhs) {
+ return lhs->getHandle() - rhs->getHandle();
+ };
+ mDynamicSensorList.sort(compareSensorHandle);
return sensor;
}
bool SensorService::unregisterDynamicSensor(int handle) {
bool found = false;
- for (size_t i=0 ; i<mSensorList.size() ; i++) {
+ for (size_t i = 0 ; i < mSensorList.size() ; i++) {
if (mSensorList[i].getHandle() == handle) {
mSensorList.removeAt(i);
found = true;
@@ -276,7 +280,7 @@
}
if (found) {
- for (size_t i=0 ; i<mDynamicSensorList.size() ; i++) {
+ for (size_t i = 0 ; i < mDynamicSensorList.size() ; i++) {
if (mDynamicSensorList[i].getHandle() == handle) {
mDynamicSensorList.removeAt(i);
}
@@ -288,21 +292,28 @@
return found;
}
-Sensor SensorService::registerVirtualSensor(SensorInterface* s)
-{
+Sensor SensorService::registerVirtualSensor(SensorInterface* s) {
Sensor sensor = registerSensor(s);
mVirtualSensorList.add( s );
return sensor;
}
-SensorService::~SensorService()
-{
- for (size_t i=0 ; i<mSensorMap.size() ; i++)
- delete mSensorMap.valueAt(i);
+bool SensorService::isNewHandle(int handle) {
+ for (int h : mUsedHandleList) {
+ if (h == handle) {
+ return false;
+ }
+ }
+ return true;
}
-status_t SensorService::dump(int fd, const Vector<String16>& args)
-{
+SensorService::~SensorService() {
+ for (size_t i=0 ; i<mSensorMap.size() ; i++) {
+ delete mSensorMap.valueAt(i);
+ }
+}
+
+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",
@@ -505,7 +516,7 @@
handle = buffer[i].meta_data.sensor;
}
if (connection->hasSensor(handle)) {
- SensorInterface* sensor = mSensorMap.valueFor(handle);
+ SensorInterface* sensor = 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 &&
@@ -518,8 +529,7 @@
}
}
-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
@@ -646,9 +656,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 (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 +790,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);
@@ -788,12 +809,11 @@
return sensor.getName();
}
}
- String8 result("unknown");
- return result;
+ return String8("unknown");
}
bool SensorService::isVirtualSensor(int handle) const {
- SensorInterface* sensor = mSensorMap.valueFor(handle);
+ SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
return sensor != NULL && sensor->isVirtual();
}
@@ -802,16 +822,11 @@
if (event.type == SENSOR_TYPE_META_DATA) {
handle = event.meta_data.sensor;
}
- SensorInterface* sensor = mSensorMap.valueFor(handle);
+ SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
return sensor != NULL && 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)) ?
@@ -831,8 +846,7 @@
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];
@@ -895,8 +909,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,7 +918,7 @@
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 );
+ SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
ALOGE_IF(!sensor, "mSensorMap[handle=0x%08x] is null!", handle);
if (sensor) {
sensor->activate(c, false);
@@ -936,18 +949,23 @@
}
}
+SensorInterface* SensorService::getSensorInterfaceFromHandle(int handle) const {
+ ssize_t index = mSensorMap.indexOfKey(handle);
+ return index < 0 ? nullptr : mSensorMap.valueAt(index);
+}
+
Sensor SensorService::getSensorFromHandle(int handle) const {
- return mSensorMap.valueFor(handle)->getSensor();
+ SensorInterface* si = getSensorInterfaceFromHandle(handle);
+ return si ? si->getSensor() : Sensor();
}
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);
+ SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
if (sensor == NULL) {
return BAD_VALUE;
}
@@ -1073,16 +1091,14 @@
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);
+ SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
}
@@ -1132,12 +1148,11 @@
}
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);
+ SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
if (!sensor)
return BAD_VALUE;
@@ -1166,7 +1181,7 @@
// 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);
+ SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
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..da97286 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -160,6 +160,7 @@
static int getNumEventsForSensorType(int sensor_event_type);
String8 getSensorName(int handle) const;
bool isVirtualSensor(int handle) const;
+ SensorInterface* getSensorInterfaceFromHandle(int handle) const;
Sensor getSensorFromHandle(int handle) const;
bool isWakeUpSensor(int type) const;
void recordLastValueLocked(sensors_event_t const* buffer, size_t count);
@@ -181,8 +182,7 @@
void checkWakeLockStateLocked();
bool isWakeLockAcquired();
bool isWakeUpSensorEvent(const sensors_event_t& event) const;
-
- SensorRecord * getSensorRecord(int handle);
+ bool isNewHandle(int handle);
sp<Looper> getLooper() const;
@@ -211,13 +211,14 @@
status_t resetToNormalMode();
status_t resetToNormalModeLocked();
- // constants
+ // lists and maps
Vector<Sensor> mSensorList;
Vector<Sensor> mUserSensorListDebug;
Vector<Sensor> mUserSensorList;
Vector<Sensor> mDynamicSensorList;
DefaultKeyedVector<int, SensorInterface*> mSensorMap;
Vector<SensorInterface *> mVirtualSensorList;
+ Vector<int> mUsedHandleList;
status_t mInitCheck;
// Socket buffersize used to initialize BitTube. This size depends on whether batching is
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 8cc9fc1..fb6307e 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -10,7 +10,9 @@
DispSync.cpp \
EventControlThread.cpp \
EventThread.cpp \
+ FenceTracker.cpp \
FrameTracker.cpp \
+ GpuService.cpp \
Layer.cpp \
LayerDim.cpp \
MessageQueue.cpp \
@@ -36,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)
@@ -103,8 +108,9 @@
endif
LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
-LOCAL_CFLAGS += -std=c++11
+LOCAL_CFLAGS += -std=c++14
+LOCAL_STATIC_LIBRARIES := libvkjson
LOCAL_SHARED_LIBRARIES := \
libcutils \
liblog \
@@ -117,7 +123,8 @@
libbinder \
libui \
libgui \
- libpowermanager
+ libpowermanager \
+ libvulkan
LOCAL_MODULE := libsurfaceflinger
@@ -133,7 +140,7 @@
LOCAL_LDFLAGS := -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic
LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
-LOCAL_CPPFLAGS := -std=c++11
+LOCAL_CPPFLAGS := -std=c++14
LOCAL_INIT_RC := surfaceflinger.rc
@@ -172,7 +179,7 @@
LOCAL_CLANG := true
LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
-LOCAL_CPPFLAGS := -std=c++11
+LOCAL_CPPFLAGS := -std=c++14
LOCAL_SRC_FILES := \
DdmConnection.cpp
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 8d8e40d..f7c8473 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -364,11 +364,9 @@
false, Transform::ROT_0);
}
-#ifdef USE_HWC2
const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const {
return mDisplaySurface->getClientTargetAcquireFence();
}
-#endif
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 38241d9..9ac8a97 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -49,9 +49,7 @@
struct DisplayInfo;
class DisplaySurface;
-#ifdef USE_HWC2
class Fence;
-#endif
class IGraphicBufferProducer;
class Layer;
class SurfaceFlinger;
@@ -174,9 +172,7 @@
EGLBoolean makeCurrent(EGLDisplay dpy, EGLContext ctx) const;
void setViewportAndProjection() const;
-#ifdef USE_HWC2
const sp<Fence>& getClientTargetAcquireFence() const;
-#endif
/* ------------------------------------------------------------------------
* Display power mode management.
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
index d819f83..d801bb3 100644
--- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -76,9 +76,7 @@
virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0;
-#ifdef USE_HWC2
virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
-#endif
protected:
DisplaySurface() {}
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 29e0766..7368d77 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -60,15 +60,14 @@
ConsumerBase(consumer),
mDisplayType(disp),
mCurrentBufferSlot(-1),
-#ifdef USE_HWC2
mCurrentBuffer(),
mCurrentFence(Fence::NO_FENCE),
+#ifdef USE_HWC2
mHwc(hwc),
mHasPendingRelease(false),
mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
mPreviousBuffer()
#else
- mCurrentBuffer(0),
mHwc(hwc)
#endif
{
@@ -168,9 +167,7 @@
}
mCurrentBufferSlot = item.mSlot;
mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
-#ifdef USE_HWC2
mCurrentFence = item.mFence;
-#endif
outFence = item.mFence;
outBuffer = mCurrentBuffer;
@@ -254,11 +251,9 @@
ConsumerBase::dumpLocked(result, prefix);
}
-#ifdef USE_HWC2
const sp<Fence>& FramebufferSurface::getClientTargetAcquireFence() const {
return mCurrentFence;
}
-#endif
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 0605602..439435a 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -52,9 +52,7 @@
// displays.
virtual void resizeBuffers(const uint32_t /*w*/, const uint32_t /*h*/) { };
-#ifdef USE_HWC2
virtual const sp<Fence>& getClientTargetAcquireFence() const override;
-#endif
private:
virtual ~FramebufferSurface() { }; // this class cannot be overloaded
@@ -88,10 +86,8 @@
// no current buffer.
sp<GraphicBuffer> mCurrentBuffer;
-#ifdef USE_HWC2
// mCurrentFence is the current buffer's acquire fence
sp<Fence> mCurrentFence;
-#endif
// Hardware composer, owned by SurfaceFlinger.
HWComposer& mHwc;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 1afed36..37b7aba 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -311,11 +311,9 @@
mSinkBufferHeight = h;
}
-#ifdef USE_HWC2
const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const {
return mFbFence;
}
-#endif
status_t VirtualDisplaySurface::requestBuffer(int pslot,
sp<GraphicBuffer>* outBuf) {
@@ -592,8 +590,8 @@
return 0;
}
-status_t VirtualDisplaySurface::setSingleBufferMode(bool /*singleBufferMode*/) {
- ALOGE("setSingleBufferMode not supported on VirtualDisplaySurface");
+status_t VirtualDisplaySurface::setSharedBufferMode(bool /*sharedBufferMode*/) {
+ ALOGE("setSharedBufferMode not supported on VirtualDisplaySurface");
return INVALID_OPERATION;
}
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index fe187c2..818d3eb 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -90,9 +90,7 @@
virtual void onFrameCommitted();
virtual void dumpAsString(String8& result) const;
virtual void resizeBuffers(const uint32_t w, const uint32_t h);
-#ifdef USE_HWC2
virtual const sp<Fence>& getClientTargetAcquireFence() const override;
-#endif
private:
enum Source {SOURCE_SINK = 0, SOURCE_SCRATCH = 1};
@@ -125,7 +123,7 @@
virtual status_t setGenerationNumber(uint32_t generationNumber);
virtual String8 getConsumerName() const override;
virtual uint64_t getNextFrameNumber() const override;
- virtual status_t setSingleBufferMode(bool singleBufferMode) override;
+ virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
virtual status_t setAutoRefresh(bool autoRefresh) override;
virtual status_t setDequeueTimeout(nsecs_t timeout) override;
diff --git a/services/surfaceflinger/FenceTracker.cpp b/services/surfaceflinger/FenceTracker.cpp
new file mode 100644
index 0000000..885d712
--- /dev/null
+++ b/services/surfaceflinger/FenceTracker.cpp
@@ -0,0 +1,191 @@
+/*
+ * 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <inttypes.h>
+#include "FenceTracker.h"
+#include "Layer.h"
+#include <utils/Trace.h>
+
+namespace android {
+
+FenceTracker::FenceTracker() :
+ mFrameCounter(0),
+ mOffset(0),
+ mFrames() {}
+
+void FenceTracker::dump(String8* outString) {
+ Mutex::Autolock lock(mMutex);
+ checkFencesForCompletion();
+
+ for (size_t i = 0; i < MAX_FRAME_HISTORY; i++) {
+ int index = (mOffset + i) % MAX_FRAME_HISTORY;
+ const FrameRecord& frame = mFrames[index];
+
+ outString->appendFormat("Frame %" PRIu64 "\n", frame.frameId);
+ outString->appendFormat("- Refresh start\t%" PRId64 "\n",
+ frame.refreshStartTime);
+
+ if (frame.glesCompositionDoneTime) {
+ outString->appendFormat("- GLES done\t%" PRId64 "\n",
+ frame.glesCompositionDoneTime);
+ } else if (frame.glesCompositionDoneFence != Fence::NO_FENCE) {
+ outString->append("- GLES done\tNot signaled\n");
+ }
+ if (frame.retireTime) {
+ outString->appendFormat("- Retire\t%" PRId64 "\n",
+ frame.retireTime);
+ } else {
+ outString->append("- Retire\tNot signaled\n");
+ }
+ for (const auto& kv : frame.layers) {
+ const LayerRecord& layer = kv.second;
+ outString->appendFormat("-- %s\n", layer.name.string());
+ outString->appendFormat("---- Frame # %" PRIu64 " (%s)\n",
+ layer.frameNumber,
+ layer.isGlesComposition ? "GLES" : "HWC");
+ outString->appendFormat("---- Posted\t%" PRId64 "\n",
+ layer.postedTime);
+ if (layer.acquireTime) {
+ outString->appendFormat("---- Acquire\t%" PRId64 "\n",
+ layer.acquireTime);
+ } else {
+ outString->append("---- Acquire\tNot signaled\n");
+ }
+ if (layer.releaseTime) {
+ outString->appendFormat("---- Release\t%" PRId64 "\n",
+ layer.releaseTime);
+ } else {
+ outString->append("---- Release\tNot signaled\n");
+ }
+ }
+ }
+}
+
+static inline bool isValidTimestamp(nsecs_t time) {
+ return time > 0 && time < INT64_MAX;
+}
+
+void FenceTracker::checkFencesForCompletion() {
+ ATRACE_CALL();
+ for (auto& frame : mFrames) {
+ if (frame.retireFence != Fence::NO_FENCE) {
+ nsecs_t time = frame.retireFence->getSignalTime();
+ if (isValidTimestamp(time)) {
+ frame.retireTime = time;
+ frame.retireFence = Fence::NO_FENCE;
+ }
+ }
+ if (frame.glesCompositionDoneFence != Fence::NO_FENCE) {
+ nsecs_t time = frame.glesCompositionDoneFence->getSignalTime();
+ if (isValidTimestamp(time)) {
+ frame.glesCompositionDoneTime = time;
+ frame.glesCompositionDoneFence = Fence::NO_FENCE;
+ }
+ }
+ for (auto& kv : frame.layers) {
+ LayerRecord& layer = kv.second;
+ if (layer.acquireFence != Fence::NO_FENCE) {
+ nsecs_t time = layer.acquireFence->getSignalTime();
+ if (isValidTimestamp(time)) {
+ layer.acquireTime = time;
+ layer.acquireFence = Fence::NO_FENCE;
+ }
+ }
+ if (layer.releaseFence != Fence::NO_FENCE) {
+ nsecs_t time = layer.releaseFence->getSignalTime();
+ if (isValidTimestamp(time)) {
+ layer.releaseTime = time;
+ layer.releaseFence = Fence::NO_FENCE;
+ }
+ }
+ }
+ }
+}
+
+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) %
+ MAX_FRAME_HISTORY];
+ frame.layers.clear();
+
+ bool wasGlesCompositionDone = false;
+ const size_t count = layers.size();
+ for (size_t i = 0; i < count; i++) {
+ String8 name;
+ uint64_t frameNumber;
+ bool glesComposition;
+ nsecs_t postedTime;
+ sp<Fence> acquireFence;
+ sp<Fence> prevReleaseFence;
+ int32_t key = layers[i]->getSequence();
+
+ layers[i]->getFenceData(&name, &frameNumber, &glesComposition,
+ &postedTime, &acquireFence, &prevReleaseFence);
+#ifdef USE_HWC2
+ if (glesComposition) {
+ frame.layers.emplace(std::piecewise_construct,
+ std::forward_as_tuple(key),
+ std::forward_as_tuple(name, frameNumber, glesComposition,
+ postedTime, 0, 0, acquireFence, prevReleaseFence));
+ wasGlesCompositionDone = true;
+ } else {
+ frame.layers.emplace(std::piecewise_construct,
+ std::forward_as_tuple(key),
+ std::forward_as_tuple(name, frameNumber, glesComposition,
+ postedTime, 0, 0, acquireFence, Fence::NO_FENCE));
+
+ auto prevLayer = prevFrame.layers.find(key);
+ if (prevLayer != prevFrame.layers.end()) {
+ prevLayer->second.releaseFence = prevReleaseFence;
+ }
+ }
+#else
+ frame.layers.emplace(std::piecewise_construct,
+ std::forward_as_tuple(key),
+ std::forward_as_tuple(name, frameNumber, glesComposition,
+ postedTime, 0, 0, acquireFence,
+ glesComposition ? Fence::NO_FENCE : prevReleaseFence));
+ if (glesComposition) {
+ wasGlesCompositionDone = true;
+ }
+#endif
+ frame.layers.emplace(std::piecewise_construct,
+ std::forward_as_tuple(key),
+ std::forward_as_tuple(name, frameNumber, glesComposition,
+ postedTime, 0, 0, acquireFence, prevReleaseFence));
+ }
+
+ frame.frameId = mFrameCounter;
+ frame.refreshStartTime = refreshStartTime;
+ frame.retireTime = 0;
+ frame.glesCompositionDoneTime = 0;
+ prevFrame.retireFence = retireFence;
+ frame.retireFence = Fence::NO_FENCE;
+ frame.glesCompositionDoneFence = wasGlesCompositionDone ? glDoneFence :
+ Fence::NO_FENCE;
+
+ mOffset = (mOffset + 1) % MAX_FRAME_HISTORY;
+ mFrameCounter++;
+
+ checkFencesForCompletion();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/FenceTracker.h b/services/surfaceflinger/FenceTracker.h
new file mode 100644
index 0000000..de99820
--- /dev/null
+++ b/services/surfaceflinger/FenceTracker.h
@@ -0,0 +1,103 @@
+/*
+ * 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_FENCETRACKER_H
+#define ANDROID_FENCETRACKER_H
+
+#include <ui/Fence.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+#include <utils/Vector.h>
+
+#include <unordered_map>
+
+namespace android {
+
+class Layer;
+
+/*
+ * Keeps a circular buffer of fence/timestamp data for the last N frames in
+ * SurfaceFlinger. Gets timestamps for fences after they have signaled.
+ */
+class FenceTracker {
+public:
+ FenceTracker();
+ void dump(String8* outString);
+ void addFrame(nsecs_t refreshStartTime, sp<Fence> retireFence,
+ const Vector<sp<Layer>>& layers, sp<Fence> glDoneFence);
+
+protected:
+ static constexpr size_t MAX_FRAME_HISTORY = 128;
+
+ struct LayerRecord {
+ String8 name; // layer name
+ uint64_t frameNumber; // frame number for this layer
+ bool isGlesComposition; // was GLES composition used for this layer?
+ nsecs_t postedTime; // time when buffer was queued
+ nsecs_t acquireTime; // timestamp from the acquire fence
+ nsecs_t releaseTime; // timestamp from the release fence
+ sp<Fence> acquireFence; // acquire fence
+ sp<Fence> releaseFence; // release fence
+
+ LayerRecord(const String8& name, uint64_t frameNumber,
+ bool isGlesComposition, nsecs_t postedTime,
+ nsecs_t acquireTime, nsecs_t releaseTime,
+ sp<Fence> acquireFence, sp<Fence> releaseFence) :
+ name(name), frameNumber(frameNumber),
+ isGlesComposition(isGlesComposition), postedTime(postedTime),
+ acquireTime(acquireTime), releaseTime(releaseTime),
+ acquireFence(acquireFence), releaseFence(releaseFence) {};
+ LayerRecord() : name("uninitialized"), frameNumber(0),
+ isGlesComposition(false), postedTime(0), acquireTime(0),
+ releaseTime(0), acquireFence(Fence::NO_FENCE),
+ releaseFence(Fence::NO_FENCE) {};
+ };
+
+ struct FrameRecord {
+ // global SurfaceFlinger frame counter
+ uint64_t frameId;
+ // layer data for this frame
+ std::unordered_map<int32_t, LayerRecord> layers;
+ // timestamp for when SurfaceFlinger::handleMessageRefresh() was called
+ nsecs_t refreshStartTime;
+ // timestamp from the retire fence
+ nsecs_t retireTime;
+ // timestamp from the GLES composition completion fence
+ nsecs_t glesCompositionDoneTime;
+ // primary display retire fence for this frame
+ sp<Fence> retireFence;
+ // if GLES composition was done, the fence for its completion
+ sp<Fence> glesCompositionDoneFence;
+
+ FrameRecord() : frameId(0), layers(), refreshStartTime(0),
+ retireTime(0), glesCompositionDoneTime(0),
+ retireFence(Fence::NO_FENCE),
+ glesCompositionDoneFence(Fence::NO_FENCE) {}
+ };
+
+ uint64_t mFrameCounter;
+ uint32_t mOffset;
+ FrameRecord mFrames[MAX_FRAME_HISTORY];
+ Mutex mMutex;
+
+ void checkFencesForCompletion();
+};
+
+}
+
+#endif // ANDROID_FRAMETRACKER_H
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 42d0810..a2c0462 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -82,6 +82,9 @@
mFiltering(false),
mNeedsFiltering(false),
mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2),
+#ifndef USE_HWC2
+ mIsGlesComposition(false),
+#endif
mProtectedByApp(false),
mHasSurface(false),
mClientRef(client),
@@ -117,7 +120,8 @@
mCurrentState.active.w = w;
mCurrentState.active.h = h;
mCurrentState.active.transform.set(0, 0);
- mCurrentState.active.crop.makeInvalid();
+ mCurrentState.crop.makeInvalid();
+ mCurrentState.finalCrop.makeInvalid();
mCurrentState.z = 0;
#ifdef USE_HWC2
mCurrentState.alpha = 1.0f;
@@ -372,8 +376,9 @@
Rect Layer::computeBounds(const Region& activeTransparentRegion) const {
const Layer::State& s(getDrawingState());
Rect win(s.active.w, s.active.h);
- if (!s.active.crop.isEmpty()) {
- win.intersect(s.active.crop, &win);
+
+ if (!s.crop.isEmpty()) {
+ win.intersect(s.crop, &win);
}
// subtract the transparent region and snap to the bounds
return reduce(win, activeTransparentRegion);
@@ -384,7 +389,7 @@
// layer's size.
FloatRect crop(getContentCrop());
- // the active.crop is the area of the window that gets cropped, but not
+ // the crop is the area of the window that gets cropped, but not
// scaled in any ways.
const State& s(getDrawingState());
@@ -396,12 +401,19 @@
// a viewport clipping and a window transform. we should use floating point to fix this.
Rect activeCrop(s.active.w, s.active.h);
- if (!s.active.crop.isEmpty()) {
- activeCrop = s.active.crop;
+ if (!s.crop.isEmpty()) {
+ activeCrop = s.crop;
}
activeCrop = s.active.transform.transform(activeCrop);
- activeCrop.intersect(hw->getViewport(), &activeCrop);
+ if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
+ activeCrop.clear();
+ }
+ if (!s.finalCrop.isEmpty()) {
+ if(!activeCrop.intersect(s.finalCrop, &activeCrop)) {
+ activeCrop.clear();
+ }
+ }
activeCrop = s.active.transform.inverse().transform(activeCrop);
// This needs to be here as transform.transform(Rect) computes the
@@ -410,72 +422,73 @@
// transform.inverse().transform(transform.transform(Rect)) != Rect
// in which case we need to make sure the final rect is clipped to the
// display bounds.
- activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
+ if (!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) {
+ activeCrop.clear();
+ }
// subtract the transparent region and snap to the bounds
activeCrop = reduce(activeCrop, s.activeTransparentRegion);
- if (!activeCrop.isEmpty()) {
- // Transform the window crop to match the buffer coordinate system,
- // which means using the inverse of the current transform set on the
- // SurfaceFlingerConsumer.
- uint32_t invTransform = mCurrentTransform;
- if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
- /*
- * the code below applies the display's inverse transform to the buffer
- */
- uint32_t invTransformOrient = hw->getOrientationTransform();
- // calculate the inverse transform
- if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
- NATIVE_WINDOW_TRANSFORM_FLIP_H;
- // If the transform has been rotated the axis of flip has been swapped
- // so we need to swap which flip operations we are performing
- bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
- bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
- if (is_h_flipped != is_v_flipped) {
- invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
- NATIVE_WINDOW_TRANSFORM_FLIP_H;
- }
- }
- // and apply to the current transform
- invTransform = (Transform(invTransform) * Transform(invTransformOrient)).getOrientation();
- }
-
- int winWidth = s.active.w;
- int winHeight = s.active.h;
- if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- // If the activeCrop has been rotate the ends are rotated but not
- // the space itself so when transforming ends back we can't rely on
- // a modification of the axes of rotation. To account for this we
- // need to reorient the inverse rotation in terms of the current
- // axes of rotation.
+ // Transform the window crop to match the buffer coordinate system,
+ // which means using the inverse of the current transform set on the
+ // SurfaceFlingerConsumer.
+ uint32_t invTransform = mCurrentTransform;
+ if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
+ /*
+ * the code below applies the display's inverse transform to the buffer
+ */
+ uint32_t invTransformOrient = hw->getOrientationTransform();
+ // calculate the inverse transform
+ if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+ NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ // If the transform has been rotated the axis of flip has been swapped
+ // so we need to swap which flip operations we are performing
bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
- if (is_h_flipped == is_v_flipped) {
+ if (is_h_flipped != is_v_flipped) {
invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
NATIVE_WINDOW_TRANSFORM_FLIP_H;
}
- winWidth = s.active.h;
- winHeight = s.active.w;
}
- const Rect winCrop = activeCrop.transform(
- invTransform, s.active.w, s.active.h);
-
- // below, crop is intersected with winCrop expressed in crop's coordinate space
- float xScale = crop.getWidth() / float(winWidth);
- float yScale = crop.getHeight() / float(winHeight);
-
- float insetL = winCrop.left * xScale;
- float insetT = winCrop.top * yScale;
- float insetR = (winWidth - winCrop.right ) * xScale;
- float insetB = (winHeight - winCrop.bottom) * yScale;
-
- crop.left += insetL;
- crop.top += insetT;
- crop.right -= insetR;
- crop.bottom -= insetB;
+ // and apply to the current transform
+ invTransform = (Transform(invTransform) * Transform(invTransformOrient)).getOrientation();
}
+
+ int winWidth = s.active.w;
+ int winHeight = s.active.h;
+ if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ // If the activeCrop has been rotate the ends are rotated but not
+ // the space itself so when transforming ends back we can't rely on
+ // a modification of the axes of rotation. To account for this we
+ // need to reorient the inverse rotation in terms of the current
+ // axes of rotation.
+ bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
+ bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
+ if (is_h_flipped == is_v_flipped) {
+ invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+ NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ }
+ winWidth = s.active.h;
+ winHeight = s.active.w;
+ }
+ const Rect winCrop = activeCrop.transform(
+ invTransform, s.active.w, s.active.h);
+
+ // below, crop is intersected with winCrop expressed in crop's coordinate space
+ float xScale = crop.getWidth() / float(winWidth);
+ float yScale = crop.getHeight() / float(winHeight);
+
+ float insetL = winCrop.left * xScale;
+ float insetT = winCrop.top * yScale;
+ float insetR = (winWidth - winCrop.right ) * xScale;
+ float insetB = (winHeight - winCrop.bottom) * yScale;
+
+ crop.left += insetL;
+ crop.top += insetT;
+ crop.right -= insetR;
+ crop.bottom -= insetB;
+
return crop;
}
@@ -533,14 +546,16 @@
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
Region activeTransparentRegion(s.activeTransparentRegion);
- if (!s.active.crop.isEmpty()) {
- Rect activeCrop(s.active.crop);
+ if (!s.crop.isEmpty()) {
+ Rect activeCrop(s.crop);
activeCrop = s.active.transform.transform(activeCrop);
#ifdef USE_HWC2
- activeCrop.intersect(displayDevice->getViewport(), &activeCrop);
+ if(!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
#else
- activeCrop.intersect(hw->getViewport(), &activeCrop);
+ if(!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
#endif
+ activeCrop.clear();
+ }
activeCrop = s.active.transform.inverse().transform(activeCrop);
// This needs to be here as transform.transform(Rect) computes the
// transformed rect and then takes the bounding box of the result before
@@ -548,7 +563,9 @@
// transform.inverse().transform(transform.transform(Rect)) != Rect
// in which case we need to make sure the final rect is clipped to the
// display bounds.
- activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
+ if(!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) {
+ activeCrop.clear();
+ }
// mark regions outside the crop as transparent
activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top));
activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom,
@@ -559,8 +576,15 @@
s.active.w, activeCrop.bottom));
}
Rect frame(s.active.transform.transform(computeBounds(activeTransparentRegion)));
+ if (!s.finalCrop.isEmpty()) {
+ if(!frame.intersect(s.finalCrop, &frame)) {
+ frame.clear();
+ }
+ }
#ifdef USE_HWC2
- frame.intersect(displayDevice->getViewport(), &frame);
+ if (!frame.intersect(displayDevice->getViewport(), &frame)) {
+ frame.clear();
+ }
const Transform& tr(displayDevice->getTransform());
Rect transformedFrame = tr.transform(frame);
auto error = hwcLayer->setDisplayFrame(transformedFrame);
@@ -588,7 +612,9 @@
mName.string(), s.z, to_string(error).c_str(),
static_cast<int32_t>(error));
#else
- frame.intersect(hw->getViewport(), &frame);
+ if (!frame.intersect(hw->getViewport(), &frame)) {
+ frame.clear();
+ }
const Transform& tr(hw->getTransform());
layer.setFrame(tr.transform(frame));
layer.setCrop(computeCrop(hw));
@@ -750,6 +776,7 @@
Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
layer.setVisibleRegionScreen(visible);
layer.setSurfaceDamage(surfaceDamageRegion);
+ mIsGlesComposition = (layer.getCompositionType() == HWC_FRAMEBUFFER);
if (mSidebandStream.get()) {
layer.setSidebandStream(mSidebandStream);
@@ -775,13 +802,16 @@
// Apply the layer's transform, followed by the display's global transform
// Here we're guaranteed that the layer's transform preserves rects
Rect win(s.active.w, s.active.h);
- if (!s.active.crop.isEmpty()) {
- win.intersect(s.active.crop, &win);
+ if (!s.crop.isEmpty()) {
+ win.intersect(s.crop, &win);
}
// Subtract the transparent region and snap to the bounds
Rect bounds = reduce(win, s.activeTransparentRegion);
Rect frame(s.active.transform.transform(bounds));
frame.intersect(displayDevice->getViewport(), &frame);
+ if (!s.finalCrop.isEmpty()) {
+ frame.intersect(s.finalCrop, &frame);
+ }
auto& displayTransform(displayDevice->getTransform());
auto position = displayTransform.transform(frame);
@@ -821,13 +851,16 @@
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
Rect win(s.active.w, s.active.h);
- if (!s.active.crop.isEmpty()) {
- win.intersect(s.active.crop, &win);
+ if (!s.crop.isEmpty()) {
+ win.intersect(s.crop, &win);
}
// subtract the transparent region and snap to the bounds
Rect bounds = reduce(win, s.activeTransparentRegion);
Rect frame(s.active.transform.transform(bounds));
frame.intersect(hw->getViewport(), &frame);
+ if (!s.finalCrop.isEmpty()) {
+ frame.intersect(s.finalCrop, &frame);
+ }
const Transform& tr(hw->getTransform());
return Rect(tr.transform(frame));
}
@@ -982,7 +1015,18 @@
* minimal value)? Or, we could make GL behave like HWC -- but this feel
* like more of a hack.
*/
- const Rect win(computeBounds());
+ Rect win(computeBounds());
+
+ if (!s.finalCrop.isEmpty()) {
+ win = s.active.transform.transform(win);
+ if (!win.intersect(s.finalCrop, &win)) {
+ win.clear();
+ }
+ win = s.active.transform.inverse().transform(win);
+ if (!win.intersect(computeBounds(), &win)) {
+ win.clear();
+ }
+ }
float left = float(win.left) / float(s.active.w);
float top = float(win.top) / float(s.active.h);
@@ -1116,25 +1160,58 @@
// local state
// ----------------------------------------------------------------------------
+static void boundPoint(vec2* point, const Rect& crop) {
+ if (point->x < crop.left) {
+ point->x = crop.left;
+ }
+ if (point->x > crop.right) {
+ point->x = crop.right;
+ }
+ if (point->y < crop.top) {
+ point->y = crop.top;
+ }
+ if (point->y > crop.bottom) {
+ point->y = crop.bottom;
+ }
+}
+
void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
bool useIdentityTransform) const
{
const Layer::State& s(getDrawingState());
- const Transform tr(useIdentityTransform ?
- hw->getTransform() : hw->getTransform() * s.active.transform);
+ const Transform tr(hw->getTransform());
const uint32_t hw_h = hw->getHeight();
Rect win(s.active.w, s.active.h);
- if (!s.active.crop.isEmpty()) {
- win.intersect(s.active.crop, &win);
+ if (!s.crop.isEmpty()) {
+ win.intersect(s.crop, &win);
}
// subtract the transparent region and snap to the bounds
win = reduce(win, s.activeTransparentRegion);
+ vec2 lt = vec2(win.left, win.top);
+ vec2 lb = vec2(win.left, win.bottom);
+ vec2 rb = vec2(win.right, win.bottom);
+ vec2 rt = vec2(win.right, win.top);
+
+ if (!useIdentityTransform) {
+ lt = s.active.transform.transform(lt);
+ lb = s.active.transform.transform(lb);
+ rb = s.active.transform.transform(rb);
+ rt = s.active.transform.transform(rt);
+ }
+
+ if (!s.finalCrop.isEmpty()) {
+ boundPoint(<, s.finalCrop);
+ boundPoint(&lb, s.finalCrop);
+ boundPoint(&rb, s.finalCrop);
+ boundPoint(&rt, s.finalCrop);
+ }
+
Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
- position[0] = tr.transform(win.left, win.top);
- position[1] = tr.transform(win.left, win.bottom);
- position[2] = tr.transform(win.right, win.bottom);
- position[3] = tr.transform(win.right, win.top);
+ position[0] = tr.transform(lt);
+ position[1] = tr.transform(lb);
+ position[2] = tr.transform(rb);
+ position[3] = tr.transform(rt);
for (size_t i=0 ; i<4 ; i++) {
position[i].y = hw_h - position[i].y;
}
@@ -1323,38 +1400,26 @@
ALOGD_IF(DEBUG_RESIZE,
"doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
" current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
- " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
+ " requested={ wh={%4u,%4u} }}\n"
" drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
- " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
+ " requested={ wh={%4u,%4u} }}\n",
this, getName().string(), mCurrentTransform, mCurrentScalingMode,
c.active.w, c.active.h,
- c.active.crop.left,
- c.active.crop.top,
- c.active.crop.right,
- c.active.crop.bottom,
- c.active.crop.getWidth(),
- c.active.crop.getHeight(),
+ c.crop.left,
+ c.crop.top,
+ c.crop.right,
+ c.crop.bottom,
+ c.crop.getWidth(),
+ c.crop.getHeight(),
c.requested.w, c.requested.h,
- c.requested.crop.left,
- c.requested.crop.top,
- c.requested.crop.right,
- c.requested.crop.bottom,
- c.requested.crop.getWidth(),
- c.requested.crop.getHeight(),
s.active.w, s.active.h,
- s.active.crop.left,
- s.active.crop.top,
- s.active.crop.right,
- s.active.crop.bottom,
- s.active.crop.getWidth(),
- s.active.crop.getHeight(),
- s.requested.w, s.requested.h,
- s.requested.crop.left,
- s.requested.crop.top,
- s.requested.crop.right,
- s.requested.crop.bottom,
- s.requested.crop.getWidth(),
- s.requested.crop.getHeight());
+ s.crop.left,
+ s.crop.top,
+ s.crop.right,
+ s.crop.bottom,
+ s.crop.getWidth(),
+ s.crop.getHeight(),
+ s.requested.w, s.requested.h);
// record the new size, form this point on, when the client request
// a buffer, it'll get the new size.
@@ -1430,7 +1495,13 @@
if (mCurrentState.requested.transform.tx() == x && mCurrentState.requested.transform.ty() == y)
return false;
mCurrentState.sequence++;
+
+ // We update the requested and active position simultaneously because
+ // we want to apply the position portion of the transform matrix immediately,
+ // but still delay scaling when resizing a SCALING_MODE_FREEZE layer.
mCurrentState.requested.transform.set(x, y);
+ mCurrentState.active.transform.set(x, y);
+
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
@@ -1492,10 +1563,19 @@
return true;
}
bool Layer::setCrop(const Rect& crop) {
- if (mCurrentState.requested.crop == crop)
+ if (mCurrentState.crop == crop)
return false;
mCurrentState.sequence++;
- mCurrentState.requested.crop = crop;
+ mCurrentState.crop = crop;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+bool Layer::setFinalCrop(const Rect& crop) {
+ if (mCurrentState.finalCrop == crop)
+ return false;
+ mCurrentState.sequence++;
+ mCurrentState.finalCrop = crop;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
@@ -1658,11 +1738,15 @@
Layer::State& current;
bool& recomputeVisibleRegions;
bool stickyTransformSet;
+ const char* name;
+
Reject(Layer::State& front, Layer::State& current,
- bool& recomputeVisibleRegions, bool stickySet)
+ bool& recomputeVisibleRegions, bool stickySet,
+ const char* name)
: front(front), current(current),
recomputeVisibleRegions(recomputeVisibleRegions),
- stickyTransformSet(stickySet) {
+ stickyTransformSet(stickySet),
+ name(name) {
}
virtual bool reject(const sp<GraphicBuffer>& buf,
@@ -1705,32 +1789,28 @@
}
ALOGD_IF(DEBUG_RESIZE,
- "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
+ "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
" drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
- " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
+ " requested={ wh={%4u,%4u} }}\n",
+ name,
bufWidth, bufHeight, item.mTransform, item.mScalingMode,
front.active.w, front.active.h,
- front.active.crop.left,
- front.active.crop.top,
- front.active.crop.right,
- front.active.crop.bottom,
- front.active.crop.getWidth(),
- front.active.crop.getHeight(),
- front.requested.w, front.requested.h,
- front.requested.crop.left,
- front.requested.crop.top,
- front.requested.crop.right,
- front.requested.crop.bottom,
- front.requested.crop.getWidth(),
- front.requested.crop.getHeight());
+ front.crop.left,
+ front.crop.top,
+ front.crop.right,
+ front.crop.bottom,
+ front.crop.getWidth(),
+ front.crop.getHeight(),
+ front.requested.w, front.requested.h);
}
if (!isFixedSize && !stickyTransformSet) {
if (front.active.w != bufWidth ||
front.active.h != bufHeight) {
// reject this buffer
- ALOGE("rejecting buffer: bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
- bufWidth, bufHeight, front.active.w, front.active.h);
+ ALOGE("[%s] rejecting buffer: "
+ "bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
+ name, bufWidth, bufHeight, front.active.w, front.active.h);
return true;
}
}
@@ -1760,7 +1840,7 @@
};
Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
- getProducerStickyTransform() != 0);
+ getProducerStickyTransform() != 0, mName.string());
// Check all of our local sync points to ensure that all transactions
@@ -1799,7 +1879,7 @@
// This boolean is used to make sure that SurfaceFlinger's shadow copy
// of the buffer queue isn't modified when the buffer queue is returning
- // BufferItem's that weren't actually queued. This can happen in single
+ // BufferItem's that weren't actually queued. This can happen in shared
// buffer mode.
bool queuedBuffer = false;
status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
@@ -1993,7 +2073,8 @@
sp<Client> client(mClientRef.promote());
result.appendFormat( " "
- "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
+ "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), "
+ "crop=(%4d,%4d,%4d,%4d), finalCrop=(%4d,%4d,%4d,%4d), "
"isOpaque=%1d, invalidate=%1d, "
#ifdef USE_HWC2
"alpha=%.3f, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
@@ -2002,8 +2083,10 @@
#endif
" client=%p\n",
s.layerStack, s.z, s.active.transform.tx(), s.active.transform.ty(), s.active.w, s.active.h,
- s.active.crop.left, s.active.crop.top,
- s.active.crop.right, s.active.crop.bottom,
+ s.crop.left, s.crop.top,
+ s.crop.right, s.crop.bottom,
+ s.finalCrop.left, s.finalCrop.top,
+ s.finalCrop.right, s.finalCrop.bottom,
isOpaque(s), contentDirty,
s.alpha, s.flags,
s.active.transform[0][0], s.active.transform[0][1],
@@ -2046,6 +2129,23 @@
mFrameTracker.getStats(outStats);
}
+void Layer::getFenceData(String8* outName, uint64_t* outFrameNumber,
+ bool* outIsGlesComposition, nsecs_t* outPostedTime,
+ sp<Fence>* outAcquireFence, sp<Fence>* outPrevReleaseFence) const {
+ *outName = mName;
+ *outFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+#ifdef USE_HWC2
+ *outIsGlesComposition = mHwcLayers.count(HWC_DISPLAY_PRIMARY) ?
+ mHwcLayers.at(HWC_DISPLAY_PRIMARY).compositionType ==
+ HWC2::Composition::Client : true;
+#else
+ *outIsGlesComposition = mIsGlesComposition;
+#endif
+ *outPostedTime = mSurfaceFlingerConsumer->getTimestamp();
+ *outAcquireFence = mSurfaceFlingerConsumer->getCurrentFence();
+ *outPrevReleaseFence = mSurfaceFlingerConsumer->getPrevReleaseFence();
+}
// ---------------------------------------------------------------------------
Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index b0088e6..1d73b43 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -93,11 +93,10 @@
struct Geometry {
uint32_t w;
uint32_t h;
- Rect crop;
Transform transform;
inline bool operator ==(const Geometry& rhs) const {
- return (w == rhs.w && h == rhs.h && crop == rhs.crop);
+ return (w == rhs.w && h == rhs.h);
}
inline bool operator !=(const Geometry& rhs) const {
return !operator ==(rhs);
@@ -120,6 +119,9 @@
int32_t sequence; // changes when visible regions can change
bool modified;
+ Rect crop;
+ Rect finalCrop;
+
// If set, defers this state update until the Layer identified by handle
// receives a frame with the given frameNumber
sp<IBinder> handle;
@@ -155,6 +157,7 @@
bool setTransparentRegionHint(const Region& transparent);
bool setFlags(uint8_t flags, uint8_t mask);
bool setCrop(const Rect& crop);
+ bool setFinalCrop(const Rect& crop);
bool setLayerStack(uint32_t layerStack);
void deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber);
@@ -177,6 +180,8 @@
sp<IGraphicBufferProducer> getProducer() const;
const String8& getName() const;
+ int32_t getSequence() const { return sequence; }
+
// -----------------------------------------------------------------------
// Virtuals
@@ -396,6 +401,10 @@
void logFrameStats();
void getFrameStats(FrameStats* outStats) const;
+ void getFenceData(String8* outName, uint64_t* outFrameNumber,
+ bool* outIsGlesComposition, nsecs_t* outPostedTime,
+ sp<Fence>* outAcquireFence, sp<Fence>* outPrevReleaseFence) const;
+
protected:
// constant
sp<SurfaceFlinger> mFlinger;
@@ -555,6 +564,8 @@
bool clearClientTarget;
};
std::unordered_map<int32_t, HWCInfo> mHwcLayers;
+#else
+ bool mIsGlesComposition;
#endif
// page-flip thread (currently main thread)
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index e161d9f..75559da 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -131,8 +131,8 @@
return mProducer->getNextFrameNumber();
}
-status_t MonitoredProducer::setSingleBufferMode(bool singleBufferMode) {
- return mProducer->setSingleBufferMode(singleBufferMode);
+status_t MonitoredProducer::setSharedBufferMode(bool sharedBufferMode) {
+ return mProducer->setSharedBufferMode(sharedBufferMode);
}
status_t MonitoredProducer::setAutoRefresh(bool autoRefresh) {
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 35ce558..441cf50 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -60,7 +60,7 @@
virtual uint64_t getNextFrameNumber() const override;
virtual status_t setDequeueTimeout(nsecs_t timeout) override;
virtual IBinder* onAsBinder();
- virtual status_t setSingleBufferMode(bool singleBufferMode) override;
+ virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
virtual status_t setAutoRefresh(bool autoRefresh) override;
private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3a0e21f..40e9ae7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -910,6 +910,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;
@@ -930,7 +935,7 @@
setUpHWComposer();
doDebugFlashRegions();
doComposition();
- postComposition();
+ postComposition(refreshStartTime);
}
// Release any buffers which were replaced this frame
@@ -999,7 +1004,11 @@
}
}
-void SurfaceFlinger::postComposition()
+#ifdef ENABLE_FENCE_TRACKING
+void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
+#else
+void SurfaceFlinger::postComposition(nsecs_t /*refreshStartTime*/)
+#endif
{
ATRACE_CALL();
ALOGV("postComposition");
@@ -1027,6 +1036,11 @@
}
}
+#ifdef ENABLE_FENCE_TRACKING
+ mFenceTracker.addFrame(refreshStartTime, presentFence,
+ hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence());
+#endif
+
if (mAnimCompositionPending) {
mAnimCompositionPending = false;
@@ -1234,6 +1248,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
@@ -1241,7 +1256,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) {
@@ -2236,6 +2250,10 @@
if (layer->setCrop(s.crop))
flags |= eTraversalNeeded;
}
+ if (what & layer_state_t::eFinalCropChanged) {
+ if (layer->setFinalCrop(s.finalCrop))
+ flags |= eTraversalNeeded;
+ }
if (what & layer_state_t::eLayerStackChanged) {
// NOTE: index needs to be calculated before we update the state
ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
@@ -2539,6 +2557,15 @@
dumpStaticScreenStats(result);
dumpAll = false;
}
+
+#ifdef ENABLE_FENCE_TRACKING
+ if ((index < numArgs) &&
+ (args[index] == String16("--fences"))) {
+ index++;
+ mFenceTracker.dump(&result);
+ dumpAll = false;
+ }
+#endif
}
if (dumpAll) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 7d6f139..37110b9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -50,6 +50,7 @@
#include "Barrier.h"
#include "DisplayDevice.h"
#include "DispSync.h"
+#include "FenceTracker.h"
#include "FrameTracker.h"
#include "MessageQueue.h"
@@ -384,7 +385,7 @@
Region& dirtyRegion, Region& opaqueRegion);
void preComposition();
- void postComposition();
+ void postComposition(nsecs_t refreshStartTime);
void rebuildLayerStacks();
void setUpHWComposer();
void doComposition();
@@ -488,6 +489,7 @@
nsecs_t mLastTransactionTime;
bool mBootFinished;
bool mForceFullDamage;
+ FenceTracker mFenceTracker;
// these are thread safe
mutable MessageQueue mEventQueue;
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 4c80fa0..c71b3bc 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -190,6 +190,7 @@
#ifdef USE_HWC2
void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence)
{
+ mPrevReleaseFence = fence;
if (!mPendingRelease.isPending) {
GLConsumer::setReleaseFence(fence);
return;
@@ -219,8 +220,17 @@
strerror(-result), result);
mPendingRelease = PendingRelease();
}
+#else
+void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence) {
+ mPrevReleaseFence = fence;
+ GLConsumer::setReleaseFence(fence);
+}
#endif
+sp<Fence> SurfaceFlingerConsumer::getPrevReleaseFence() const {
+ return mPrevReleaseFence;
+}
+
void SurfaceFlingerConsumer::setContentsChangedListener(
const wp<ContentsChangedListener>& listener) {
setFrameAvailableListener(listener);
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index f40d53e..51b002f 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -37,7 +37,8 @@
SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
uint32_t tex)
: GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false),
- mTransformToDisplayInverse(false), mSurfaceDamage()
+ mTransformToDisplayInverse(false), mSurfaceDamage(),
+ mPrevReleaseFence(Fence::NO_FENCE)
{}
class BufferRejecter {
@@ -75,8 +76,9 @@
nsecs_t computeExpectedPresent(const DispSync& dispSync);
-#ifdef USE_HWC2
virtual void setReleaseFence(const sp<Fence>& fence) override;
+ sp<Fence> getPrevReleaseFence() const;
+#ifdef USE_HWC2
void releasePendingBuffer();
#endif
@@ -98,6 +100,9 @@
// presentDisplay
PendingRelease mPendingRelease;
#endif
+
+ // The release fence of the already displayed buffer (previous frame).
+ sp<Fence> mPrevReleaseFence;
};
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index d864874..a63ec50 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -927,6 +927,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;
@@ -947,7 +952,7 @@
setUpHWComposer();
doDebugFlashRegions();
doComposition();
- postComposition();
+ postComposition(refreshStartTime);
}
previousExpectedPresent = mPrimaryDispSync.computeNextRefresh(0);
@@ -1008,7 +1013,11 @@
}
}
-void SurfaceFlinger::postComposition()
+#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();
@@ -1034,6 +1043,11 @@
}
}
+#ifdef ENABLE_FENCE_TRACKING
+ mFenceTracker.addFrame(refreshStartTime, presentFence,
+ hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence());
+#endif
+
if (mAnimCompositionPending) {
mAnimCompositionPending = false;
@@ -2274,6 +2288,10 @@
if (layer->setCrop(s.crop))
flags |= eTraversalNeeded;
}
+ if (what & layer_state_t::eFinalCropChanged) {
+ if (layer->setFinalCrop(s.finalCrop))
+ flags |= eTraversalNeeded;
+ }
if (what & layer_state_t::eLayerStackChanged) {
// NOTE: index needs to be calculated before we update the state
ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
@@ -2577,6 +2595,15 @@
dumpStaticScreenStats(result);
dumpAll = false;
}
+
+#ifdef ENABLE_FENCE_TRACKING
+ if ((index < numArgs) &&
+ (args[index] == String16("--fences"))) {
+ index++;
+ mFenceTracker.dump(&result);
+ dumpAll = false;
+ }
+#endif
}
if (dumpAll) {
diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h
index c2f0010..9efeb9e 100644
--- a/services/surfaceflinger/Transform.h
+++ b/services/surfaceflinger/Transform.h
@@ -81,6 +81,9 @@
Region transform(const Region& reg) const;
Rect transform(const Rect& bounds) const;
Transform operator * (const Transform& rhs) const;
+ // assumes the last row is < 0 , 0 , 1 >
+ vec2 transform(const vec2& v) const;
+ vec3 transform(const vec3& v) const;
Transform inverse() const;
@@ -96,9 +99,6 @@
enum { UNKNOWN_TYPE = 0x80000000 };
- // assumes the last row is < 0 , 0 , 1 >
- vec2 transform(const vec2& v) const;
- vec3 transform(const vec3& v) const;
uint32_t type() const;
static bool absIsOne(float f);
static bool isZero(float f);
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 ee4ad4e..d7cb899 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -280,6 +280,31 @@
}
}
+TEST_F(LayerUpdateTest, LayerFinalCropWorks) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before crop");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 195, 63, 63);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+ SurfaceComposerClient::openGlobalTransaction();
+ Rect cropRect(16, 16, 32, 32);
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFinalCrop(cropRect));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+ {
+ // This should crop the foreground surface.
+ SCOPED_TRACE("after crop");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 63, 63, 195);
+ sc->checkPixel( 95, 80, 63, 63, 195);
+ sc->checkPixel( 80, 95, 63, 63, 195);
+ sc->checkPixel( 96, 96, 63, 63, 195);
+ }
+}
+
TEST_F(LayerUpdateTest, LayerSetLayerWorks) {
sp<ScreenCapture> sc;
{
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/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
index 85b8ab2..e60d74c 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 \
@@ -38,6 +39,8 @@
system/core/libsync/include
LOCAL_SRC_FILES := \
+ api.cpp \
+ api_gen.cpp \
debug_report.cpp \
dispatch_gen.cpp \
layers_extensions.cpp \
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
new file mode 100644
index 0000000..9c5aa3b
--- /dev/null
+++ b/vulkan/libvulkan/api.cpp
@@ -0,0 +1,1024 @@
+/*
+ * 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 "loader.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) {
+ add_implicit_layers();
+
+ 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_ = allocate_name_array(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] = get_implicit_layer_name(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 (is_implicit_layer(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 add_implicit_layers() {
+ if (!driver::Debuggable())
+ return;
+
+ parse_debug_vulkan_layers();
+ property_list(parse_debug_vulkan_layer, 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 parse_debug_vulkan_layers() {
+ // 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)
+ add_implicit_layer(prio, p, static_cast<size_t>(delim - p));
+
+ prio++;
+ p = delim + 1;
+ }
+
+ if (p[0] != '\0')
+ add_implicit_layer(prio, p, strlen(p));
+ }
+
+ static void parse_debug_vulkan_layer(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.add_implicit_layer(priority, val, strlen(val));
+ }
+
+ void add_implicit_layer(int priority, const char* name, size_t len) {
+ if (!grow_implicit_layer_array(1, 0))
+ return;
+
+ auto& arr = implicit_layers_;
+ auto& layer = arr.elements[arr.count++];
+
+ layer.priority = priority;
+ layer.name_offset = add_implicit_layer_name(name, len);
+
+ ALOGV("Added implicit layer %s",
+ get_implicit_layer_name(arr.count - 1));
+ }
+
+ size_t add_implicit_layer_name(const char* name, size_t len) {
+ if (!grow_implicit_layer_array(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 grow_implicit_layer_array(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* get_implicit_layer_name(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 is_implicit_layer(const char* name) const {
+ const auto& arr = implicit_layers_;
+
+ for (uint32_t i = 0; i < arr.count; i++) {
+ if (strcmp(name, get_implicit_layer_name(i)) == 0)
+ return true;
+ }
+
+ return false;
+ }
+
+ const char** allocate_name_array(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 (!enable_debug_callback())
+ return VK_SUCCESS;
+
+ names_ = allocate_name_array(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 install_debug_callback() const { return install_debug_callback_; }
+
+ private:
+ bool enable_debug_callback() const {
+ return (is_instance_ && driver::Debuggable() &&
+ property_get_bool("debug.vulkan.enable_callback", false));
+ }
+
+ const char** allocate_name_array(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 create_instance(const VkInstanceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkInstance* instance_out);
+
+ static VkResult create_device(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkDevice* dev_out);
+
+ static void destroy_instance(VkInstance instance,
+ const VkAllocationCallbacks* allocator);
+
+ static void destroy_device(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 activate_layers(const char* const* layer_names,
+ uint32_t layer_count,
+ const char* const* extension_names,
+ uint32_t extension_count);
+ ActiveLayer* allocate_layer_array(uint32_t count) const;
+ VkResult load_layer(ActiveLayer& layer, const char* name);
+ void setup_layer_links();
+
+ bool empty() const;
+ void modify_create_info(VkInstanceCreateInfo& info);
+ void modify_create_info(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);
+
+ template <typename DataType>
+ void steal_layers(DataType& data);
+
+ static void destroy_layers(ActiveLayer* layers,
+ uint32_t count,
+ const VkAllocationCallbacks& allocator);
+
+ static VKAPI_ATTR VkBool32
+ debug_report_callback(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_;
+ VkLayerDeviceCreateInfo device_chain_info_;
+ };
+};
+
+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) {}
+
+LayerChain::~LayerChain() {
+ destroy_layers(layers_, layer_count_, allocator_);
+}
+
+VkResult LayerChain::activate_layers(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_ = allocate_layer_array(layer_count);
+ if (!layers_)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ // load layers
+ for (uint32_t i = 0; i < layer_count; i++) {
+ result = load_layer(layers_[i], layer_names[i]);
+ if (result != VK_SUCCESS)
+ return result;
+
+ // count loaded layers for proper destructions on errors
+ layer_count_++;
+ }
+
+ setup_layer_links();
+
+ return VK_SUCCESS;
+}
+
+LayerChain::ActiveLayer* LayerChain::allocate_layer_array(
+ 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::load_layer(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::setup_layer_links() {
+ 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::modify_create_info(VkInstanceCreateInfo& info) {
+ if (layer_count_) {
+ const ActiveLayer& layer = layers_[0];
+
+ instance_chain_info_.sType =
+ VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+ instance_chain_info_.function = VK_LAYER_FUNCTION_LINK;
+ // TODO fix vk_layer_interface.h and get rid of const_cast?
+ instance_chain_info_.u.pLayerInfo =
+ const_cast<VkLayerInstanceLink*>(&layer.instance_link);
+
+ // insert layer info
+ instance_chain_info_.pNext = info.pNext;
+ info.pNext = &instance_chain_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::modify_create_info(VkDeviceCreateInfo& info) {
+ if (layer_count_) {
+ const ActiveLayer& layer = layers_[0];
+
+ device_chain_info_.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
+ device_chain_info_.function = VK_LAYER_FUNCTION_LINK;
+ // TODO fix vk_layer_interface.h and get rid of const_cast?
+ device_chain_info_.u.pLayerInfo =
+ const_cast<VkLayerDeviceLink*>(&layer.device_link);
+
+ // insert layer info
+ device_chain_info_.pNext = info.pNext;
+ info.pNext = &device_chain_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) {
+ // call down the chain
+ PFN_vkCreateInstance create_instance =
+ reinterpret_cast<PFN_vkCreateInstance>(
+ get_instance_proc_addr_(VK_NULL_HANDLE, "vkCreateInstance"));
+ VkInstance instance;
+ VkResult result = create_instance(create_info, allocator, &instance);
+ if (result != VK_SUCCESS)
+ return result;
+
+ // initialize InstanceData
+ InstanceData& data = GetData(instance);
+ memset(&data, 0, sizeof(data));
+
+ data.instance = instance;
+
+ if (!InitDispatchTable(instance, get_instance_proc_addr_)) {
+ if (data.dispatch.DestroyInstance)
+ data.dispatch.DestroyInstance(instance, allocator);
+
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ // install debug report callback
+ if (override_extensions_.install_debug_callback()) {
+ 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 = debug_report_callback;
+
+ 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");
+ }
+
+ steal_layers(data);
+
+ *instance_out = instance;
+
+ return VK_SUCCESS;
+}
+
+VkResult LayerChain::create(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkDevice* dev_out) {
+ // 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;
+ VkResult result = create_device(physical_dev, create_info, allocator, &dev);
+ if (result != VK_SUCCESS)
+ return result;
+
+ // initialize DeviceData
+ DeviceData& data = GetData(dev);
+ memset(&data, 0, sizeof(data));
+
+ if (!InitDispatchTable(dev, get_device_proc_addr_)) {
+ if (data.dispatch.DestroyDevice)
+ data.dispatch.DestroyDevice(dev, allocator);
+
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ steal_layers(data);
+
+ *dev_out = dev;
+
+ return VK_SUCCESS;
+}
+
+template <typename DataType>
+void LayerChain::steal_layers(DataType& data) {
+ data.layers = layers_;
+ data.layer_count = layer_count_;
+
+ layers_ = nullptr;
+ layer_count_ = 0;
+}
+
+void LayerChain::destroy_layers(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);
+}
+
+VkBool32 LayerChain::debug_report_callback(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::create_instance(const VkInstanceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkInstance* instance_out) {
+ LayerChain chain(true,
+ (allocator) ? *allocator : driver::GetDefaultAllocator());
+
+ VkResult result = chain.activate_layers(
+ 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.modify_create_info(local_create_info);
+ create_info = &local_create_info;
+ }
+
+ return chain.create(create_info, allocator, instance_out);
+}
+
+VkResult LayerChain::create_device(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.activate_layers(
+ 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.modify_create_info(local_create_info);
+ create_info = &local_create_info;
+ }
+
+ return chain.create(physical_dev, create_info, allocator, dev_out);
+}
+
+void LayerChain::destroy_instance(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);
+
+ destroy_layers(layers, layer_count,
+ (allocator) ? *allocator : local_allocator);
+}
+
+void LayerChain::destroy_device(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);
+
+ destroy_layers(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::create_instance(pCreateInfo, pAllocator, pInstance);
+}
+
+void DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* pAllocator) {
+ if (instance != VK_NULL_HANDLE)
+ LayerChain::destroy_instance(instance, pAllocator);
+}
+
+VkResult CreateDevice(VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDevice* pDevice) {
+ return LayerChain::create_device(physicalDevice, pCreateInfo, pAllocator,
+ pDevice);
+}
+
+void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
+ if (device != VK_NULL_HANDLE)
+ LayerChain::destroy_device(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..0c4cd9a
--- /dev/null
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -0,0 +1,1170 @@
+/*
+ * 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)
+
+// TODO do we want to point to a stub or nullptr when ext is not enabled?
+#define INIT_PROC_EXT(ext, obj, proc) \
+ do { \
+ INIT_PROC(obj, proc); \
+ } while (0)
+
+bool InitDispatchTable(VkInstance instance,
+ PFN_vkGetInstanceProcAddr get_proc) {
+ 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) {
+ 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);
+ return nullptr;
+ }
+ // clang-format off
+
+ 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/api_gen.h b/vulkan/libvulkan/api_gen.h
new file mode 100644
index 0000000..54be83b
--- /dev/null
+++ b/vulkan/libvulkan/api_gen.h
@@ -0,0 +1,188 @@
+/*
+ * 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_API_GEN_H
+#define LIBVULKAN_API_GEN_H
+
+#include <vulkan/vulkan.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;
+ PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
+ PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
+ PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
+ PFN_vkCreateDevice CreateDevice;
+ PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
+ PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
+ PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
+ PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
+ PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
+ PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
+ PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
+ // clang-format on
+};
+
+struct DeviceDispatchTable {
+ // clang-format off
+ PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+ PFN_vkDestroyDevice DestroyDevice;
+ PFN_vkGetDeviceQueue GetDeviceQueue;
+ PFN_vkQueueSubmit QueueSubmit;
+ PFN_vkQueueWaitIdle QueueWaitIdle;
+ PFN_vkDeviceWaitIdle DeviceWaitIdle;
+ PFN_vkAllocateMemory AllocateMemory;
+ PFN_vkFreeMemory FreeMemory;
+ PFN_vkMapMemory MapMemory;
+ PFN_vkUnmapMemory UnmapMemory;
+ PFN_vkFlushMappedMemoryRanges FlushMappedMemoryRanges;
+ PFN_vkInvalidateMappedMemoryRanges InvalidateMappedMemoryRanges;
+ PFN_vkGetDeviceMemoryCommitment GetDeviceMemoryCommitment;
+ PFN_vkGetBufferMemoryRequirements GetBufferMemoryRequirements;
+ PFN_vkBindBufferMemory BindBufferMemory;
+ PFN_vkGetImageMemoryRequirements GetImageMemoryRequirements;
+ PFN_vkBindImageMemory BindImageMemory;
+ PFN_vkGetImageSparseMemoryRequirements GetImageSparseMemoryRequirements;
+ PFN_vkQueueBindSparse QueueBindSparse;
+ PFN_vkCreateFence CreateFence;
+ PFN_vkDestroyFence DestroyFence;
+ PFN_vkResetFences ResetFences;
+ PFN_vkGetFenceStatus GetFenceStatus;
+ PFN_vkWaitForFences WaitForFences;
+ PFN_vkCreateSemaphore CreateSemaphore;
+ PFN_vkDestroySemaphore DestroySemaphore;
+ PFN_vkCreateEvent CreateEvent;
+ PFN_vkDestroyEvent DestroyEvent;
+ PFN_vkGetEventStatus GetEventStatus;
+ PFN_vkSetEvent SetEvent;
+ PFN_vkResetEvent ResetEvent;
+ PFN_vkCreateQueryPool CreateQueryPool;
+ PFN_vkDestroyQueryPool DestroyQueryPool;
+ PFN_vkGetQueryPoolResults GetQueryPoolResults;
+ PFN_vkCreateBuffer CreateBuffer;
+ PFN_vkDestroyBuffer DestroyBuffer;
+ PFN_vkCreateBufferView CreateBufferView;
+ PFN_vkDestroyBufferView DestroyBufferView;
+ PFN_vkCreateImage CreateImage;
+ PFN_vkDestroyImage DestroyImage;
+ PFN_vkGetImageSubresourceLayout GetImageSubresourceLayout;
+ PFN_vkCreateImageView CreateImageView;
+ PFN_vkDestroyImageView DestroyImageView;
+ PFN_vkCreateShaderModule CreateShaderModule;
+ PFN_vkDestroyShaderModule DestroyShaderModule;
+ PFN_vkCreatePipelineCache CreatePipelineCache;
+ PFN_vkDestroyPipelineCache DestroyPipelineCache;
+ PFN_vkGetPipelineCacheData GetPipelineCacheData;
+ PFN_vkMergePipelineCaches MergePipelineCaches;
+ PFN_vkCreateGraphicsPipelines CreateGraphicsPipelines;
+ PFN_vkCreateComputePipelines CreateComputePipelines;
+ PFN_vkDestroyPipeline DestroyPipeline;
+ PFN_vkCreatePipelineLayout CreatePipelineLayout;
+ PFN_vkDestroyPipelineLayout DestroyPipelineLayout;
+ PFN_vkCreateSampler CreateSampler;
+ PFN_vkDestroySampler DestroySampler;
+ PFN_vkCreateDescriptorSetLayout CreateDescriptorSetLayout;
+ PFN_vkDestroyDescriptorSetLayout DestroyDescriptorSetLayout;
+ PFN_vkCreateDescriptorPool CreateDescriptorPool;
+ PFN_vkDestroyDescriptorPool DestroyDescriptorPool;
+ PFN_vkResetDescriptorPool ResetDescriptorPool;
+ PFN_vkAllocateDescriptorSets AllocateDescriptorSets;
+ PFN_vkFreeDescriptorSets FreeDescriptorSets;
+ PFN_vkUpdateDescriptorSets UpdateDescriptorSets;
+ PFN_vkCreateFramebuffer CreateFramebuffer;
+ PFN_vkDestroyFramebuffer DestroyFramebuffer;
+ PFN_vkCreateRenderPass CreateRenderPass;
+ PFN_vkDestroyRenderPass DestroyRenderPass;
+ PFN_vkGetRenderAreaGranularity GetRenderAreaGranularity;
+ PFN_vkCreateCommandPool CreateCommandPool;
+ PFN_vkDestroyCommandPool DestroyCommandPool;
+ PFN_vkResetCommandPool ResetCommandPool;
+ PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+ PFN_vkFreeCommandBuffers FreeCommandBuffers;
+ PFN_vkBeginCommandBuffer BeginCommandBuffer;
+ PFN_vkEndCommandBuffer EndCommandBuffer;
+ PFN_vkResetCommandBuffer ResetCommandBuffer;
+ PFN_vkCmdBindPipeline CmdBindPipeline;
+ PFN_vkCmdSetViewport CmdSetViewport;
+ PFN_vkCmdSetScissor CmdSetScissor;
+ PFN_vkCmdSetLineWidth CmdSetLineWidth;
+ PFN_vkCmdSetDepthBias CmdSetDepthBias;
+ PFN_vkCmdSetBlendConstants CmdSetBlendConstants;
+ PFN_vkCmdSetDepthBounds CmdSetDepthBounds;
+ PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask;
+ PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask;
+ PFN_vkCmdSetStencilReference CmdSetStencilReference;
+ PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
+ PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer;
+ PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers;
+ PFN_vkCmdDraw CmdDraw;
+ PFN_vkCmdDrawIndexed CmdDrawIndexed;
+ PFN_vkCmdDrawIndirect CmdDrawIndirect;
+ PFN_vkCmdDrawIndexedIndirect CmdDrawIndexedIndirect;
+ PFN_vkCmdDispatch CmdDispatch;
+ PFN_vkCmdDispatchIndirect CmdDispatchIndirect;
+ PFN_vkCmdCopyBuffer CmdCopyBuffer;
+ PFN_vkCmdCopyImage CmdCopyImage;
+ PFN_vkCmdBlitImage CmdBlitImage;
+ PFN_vkCmdCopyBufferToImage CmdCopyBufferToImage;
+ PFN_vkCmdCopyImageToBuffer CmdCopyImageToBuffer;
+ PFN_vkCmdUpdateBuffer CmdUpdateBuffer;
+ PFN_vkCmdFillBuffer CmdFillBuffer;
+ PFN_vkCmdClearColorImage CmdClearColorImage;
+ PFN_vkCmdClearDepthStencilImage CmdClearDepthStencilImage;
+ PFN_vkCmdClearAttachments CmdClearAttachments;
+ PFN_vkCmdResolveImage CmdResolveImage;
+ PFN_vkCmdSetEvent CmdSetEvent;
+ PFN_vkCmdResetEvent CmdResetEvent;
+ PFN_vkCmdWaitEvents CmdWaitEvents;
+ PFN_vkCmdPipelineBarrier CmdPipelineBarrier;
+ PFN_vkCmdBeginQuery CmdBeginQuery;
+ PFN_vkCmdEndQuery CmdEndQuery;
+ PFN_vkCmdResetQueryPool CmdResetQueryPool;
+ PFN_vkCmdWriteTimestamp CmdWriteTimestamp;
+ PFN_vkCmdCopyQueryPoolResults CmdCopyQueryPoolResults;
+ PFN_vkCmdPushConstants CmdPushConstants;
+ PFN_vkCmdBeginRenderPass CmdBeginRenderPass;
+ PFN_vkCmdNextSubpass CmdNextSubpass;
+ PFN_vkCmdEndRenderPass CmdEndRenderPass;
+ PFN_vkCmdExecuteCommands CmdExecuteCommands;
+ PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
+ PFN_vkDestroySwapchainKHR DestroySwapchainKHR;
+ PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
+ PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
+ PFN_vkQueuePresentKHR QueuePresentKHR;
+ // clang-format on
+};
+
+bool InitDispatchTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc);
+bool InitDispatchTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc);
+
+} // 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..7ebe983
--- /dev/null
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -0,0 +1,519 @@
+{{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"}}
+
+{{/*
+-------------------------------------------------------------------------------
+ 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 <vulkan/vulkan.h>
+¶
+namespace vulkan {«
+namespace api {«
+¶
+struct InstanceDispatchTable {
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
+ {{Macro "C++.DeclareDispatchTableEntry" $f}};
+ {{end}}
+ {{end}}
+ // clang-format on
+};
+¶
+struct DeviceDispatchTable {
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
+ {{Macro "C++.DeclareDispatchTableEntry" $f}};
+ {{end}}
+ {{end}}
+ // clang-format on
+};
+¶
+bool InitDispatchTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc);
+bool InitDispatchTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc);
+¶
+»} // 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++.DefineInitProcMacros" "dispatch"}}
+¶
+bool InitDispatchTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc) {
+ 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) {
+ 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}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits a declaration of a dispatch table entry.
+------------------------------------------------------------------------------
+*/}}
+{{define "C++.DeclareDispatchTableEntry"}}
+ {{AssertType $ "Function"}}
+
+ {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits macros to help initialize dispatch tables.
+-------------------------------------------------------------------------------
+*/}}
+{{define "C++.DefineInitProcMacros"}}
+ #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)
+ ¶
+ // TODO do we want to point to a stub or nullptr when ext is not enabled?
+ #define INIT_PROC_EXT(ext, obj, proc) do { \
+ INIT_PROC(obj, proc); \
+ } 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 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);
+ return nullptr;
+ }
+ // clang-format off
+ ¶
+{{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 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}}
diff --git a/vulkan/libvulkan/dispatch.tmpl b/vulkan/libvulkan/dispatch.tmpl
index 0a0338e..67ead4a 100644
--- a/vulkan/libvulkan/dispatch.tmpl
+++ b/vulkan/libvulkan/dispatch.tmpl
@@ -44,32 +44,11 @@
¶
// 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 $}}
@@ -82,6 +61,10 @@
PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+ PFN_vkDestroyDevice DestroyDevice;
+ PFN_vkGetDeviceQueue GetDeviceQueue;
+ PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+
{{/* 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
@@ -156,40 +139,6 @@
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"}}
@@ -202,125 +151,14 @@
// 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,
@@ -352,6 +190,21 @@
ALOGE("missing driver proc: %s", "vkGetDeviceProcAddr");
success = false;
}
+ dispatch.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(get_proc_addr(instance, "vkDestroyDevice"));
+ if (UNLIKELY(!dispatch.DestroyDevice)) {
+ ALOGE("missing driver proc: %s", "vkDestroyDevice");
+ success = false;
+ }
+ dispatch.GetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>(get_proc_addr(instance, "vkGetDeviceQueue"));
+ if (UNLIKELY(!dispatch.GetDeviceQueue)) {
+ ALOGE("missing driver proc: %s", "vkGetDeviceQueue");
+ success = false;
+ }
+ dispatch.AllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>(get_proc_addr(instance, "vkAllocateCommandBuffers"));
+ if (UNLIKELY(!dispatch.AllocateCommandBuffers)) {
+ ALOGE("missing driver proc: %s", "vkAllocateCommandBuffers");
+ success = false;
+ }
dispatch.CreateImage = reinterpret_cast<PFN_vkCreateImage>(get_proc_addr(instance, "vkCreateImage"));
if (UNLIKELY(!dispatch.CreateImage)) {
ALOGE("missing driver proc: %s", "vkCreateImage");
@@ -382,43 +235,11 @@
»}
¶
} // 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
-------------------------------------------------------------------------------
*/}}
@@ -443,18 +264,6 @@
{{/*
--------------------------------------------------------------------------------
- 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
@@ -471,23 +280,6 @@
{{/*
------------------------------------------------------------------------------
- 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.
------------------------------------------------------------------------------
*/}}
@@ -504,26 +296,6 @@
{{/*
------------------------------------------------------------------------------
- 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.
------------------------------------------------------------------------------
@@ -540,40 +312,6 @@
{{/*
-------------------------------------------------------------------------------
- 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.
-------------------------------------------------------------------------------
@@ -586,6 +324,9 @@
{{else if (Macro "IsLoaderFunction" $)}}true
{{else if (eq $.Name "vkCreateInstance")}}true
{{else if (eq $.Name "vkGetDeviceProcAddr")}}true
+ {{else if (eq $.Name "vkDestroyDevice")}}true
+ {{else if (eq $.Name "vkGetDeviceQueue")}}true
+ {{else if (eq $.Name "vkAllocateCommandBuffers")}}true
{{end}}
{{end}}
{{end}}
diff --git a/vulkan/libvulkan/dispatch_gen.cpp b/vulkan/libvulkan/dispatch_gen.cpp
index b41efb8..eacf1a1 100644
--- a/vulkan/libvulkan/dispatch_gen.cpp
+++ b/vulkan/libvulkan/dispatch_gen.cpp
@@ -47,187 +47,10 @@
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))},
+ {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAllocateCommandBuffers>(AllocateCommandBuffers_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))},
@@ -235,6 +58,7 @@
{"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))},
+ {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDevice>(DestroyDevice_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))},
@@ -242,6 +66,7 @@
{"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))},
+ {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceQueue>(GetDeviceQueue_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))},
@@ -259,963 +84,14 @@
// 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,
@@ -1303,6 +179,21 @@
ALOGE("missing driver proc: %s", "vkGetDeviceProcAddr");
success = false;
}
+ dispatch.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(get_proc_addr(instance, "vkDestroyDevice"));
+ if (UNLIKELY(!dispatch.DestroyDevice)) {
+ ALOGE("missing driver proc: %s", "vkDestroyDevice");
+ success = false;
+ }
+ dispatch.GetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>(get_proc_addr(instance, "vkGetDeviceQueue"));
+ if (UNLIKELY(!dispatch.GetDeviceQueue)) {
+ ALOGE("missing driver proc: %s", "vkGetDeviceQueue");
+ success = false;
+ }
+ dispatch.AllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>(get_proc_addr(instance, "vkAllocateCommandBuffers"));
+ if (UNLIKELY(!dispatch.AllocateCommandBuffers)) {
+ ALOGE("missing driver proc: %s", "vkAllocateCommandBuffers");
+ success = false;
+ }
dispatch.CreateImage = reinterpret_cast<PFN_vkCreateImage>(get_proc_addr(instance, "vkCreateImage"));
if (UNLIKELY(!dispatch.CreateImage)) {
ALOGE("missing driver proc: %s", "vkCreateImage");
@@ -1333,747 +224,3 @@
}
} // 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/dispatch_gen.h b/vulkan/libvulkan/dispatch_gen.h
index cef4ccf..ca31caf 100644
--- a/vulkan/libvulkan/dispatch_gen.h
+++ b/vulkan/libvulkan/dispatch_gen.h
@@ -16,167 +16,11 @@
// 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
- 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_vkDestroySurfaceKHR DestroySurfaceKHR;
- PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
- PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
- 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_vkDestroyDevice DestroyDevice;
- PFN_vkGetDeviceQueue GetDeviceQueue;
- PFN_vkQueueSubmit QueueSubmit;
- PFN_vkQueueWaitIdle QueueWaitIdle;
- PFN_vkDeviceWaitIdle DeviceWaitIdle;
- PFN_vkAllocateMemory AllocateMemory;
- PFN_vkFreeMemory FreeMemory;
- PFN_vkMapMemory MapMemory;
- PFN_vkUnmapMemory UnmapMemory;
- PFN_vkFlushMappedMemoryRanges FlushMappedMemoryRanges;
- PFN_vkInvalidateMappedMemoryRanges InvalidateMappedMemoryRanges;
- PFN_vkGetDeviceMemoryCommitment GetDeviceMemoryCommitment;
- PFN_vkGetBufferMemoryRequirements GetBufferMemoryRequirements;
- PFN_vkBindBufferMemory BindBufferMemory;
- PFN_vkGetImageMemoryRequirements GetImageMemoryRequirements;
- PFN_vkBindImageMemory BindImageMemory;
- PFN_vkGetImageSparseMemoryRequirements GetImageSparseMemoryRequirements;
- PFN_vkQueueBindSparse QueueBindSparse;
- PFN_vkCreateFence CreateFence;
- PFN_vkDestroyFence DestroyFence;
- PFN_vkResetFences ResetFences;
- PFN_vkGetFenceStatus GetFenceStatus;
- PFN_vkWaitForFences WaitForFences;
- PFN_vkCreateSemaphore CreateSemaphore;
- PFN_vkDestroySemaphore DestroySemaphore;
- PFN_vkCreateEvent CreateEvent;
- PFN_vkDestroyEvent DestroyEvent;
- PFN_vkGetEventStatus GetEventStatus;
- PFN_vkSetEvent SetEvent;
- PFN_vkResetEvent ResetEvent;
- PFN_vkCreateQueryPool CreateQueryPool;
- PFN_vkDestroyQueryPool DestroyQueryPool;
- PFN_vkGetQueryPoolResults GetQueryPoolResults;
- PFN_vkCreateBuffer CreateBuffer;
- PFN_vkDestroyBuffer DestroyBuffer;
- PFN_vkCreateBufferView CreateBufferView;
- PFN_vkDestroyBufferView DestroyBufferView;
- PFN_vkCreateImage CreateImage;
- PFN_vkDestroyImage DestroyImage;
- PFN_vkGetImageSubresourceLayout GetImageSubresourceLayout;
- PFN_vkCreateImageView CreateImageView;
- PFN_vkDestroyImageView DestroyImageView;
- PFN_vkCreateShaderModule CreateShaderModule;
- PFN_vkDestroyShaderModule DestroyShaderModule;
- PFN_vkCreatePipelineCache CreatePipelineCache;
- PFN_vkDestroyPipelineCache DestroyPipelineCache;
- PFN_vkGetPipelineCacheData GetPipelineCacheData;
- PFN_vkMergePipelineCaches MergePipelineCaches;
- PFN_vkCreateGraphicsPipelines CreateGraphicsPipelines;
- PFN_vkCreateComputePipelines CreateComputePipelines;
- PFN_vkDestroyPipeline DestroyPipeline;
- PFN_vkCreatePipelineLayout CreatePipelineLayout;
- PFN_vkDestroyPipelineLayout DestroyPipelineLayout;
- PFN_vkCreateSampler CreateSampler;
- PFN_vkDestroySampler DestroySampler;
- PFN_vkCreateDescriptorSetLayout CreateDescriptorSetLayout;
- PFN_vkDestroyDescriptorSetLayout DestroyDescriptorSetLayout;
- PFN_vkCreateDescriptorPool CreateDescriptorPool;
- PFN_vkDestroyDescriptorPool DestroyDescriptorPool;
- PFN_vkResetDescriptorPool ResetDescriptorPool;
- PFN_vkAllocateDescriptorSets AllocateDescriptorSets;
- PFN_vkFreeDescriptorSets FreeDescriptorSets;
- PFN_vkUpdateDescriptorSets UpdateDescriptorSets;
- PFN_vkCreateFramebuffer CreateFramebuffer;
- PFN_vkDestroyFramebuffer DestroyFramebuffer;
- PFN_vkCreateRenderPass CreateRenderPass;
- PFN_vkDestroyRenderPass DestroyRenderPass;
- PFN_vkGetRenderAreaGranularity GetRenderAreaGranularity;
- PFN_vkCreateCommandPool CreateCommandPool;
- PFN_vkDestroyCommandPool DestroyCommandPool;
- PFN_vkResetCommandPool ResetCommandPool;
- PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
- PFN_vkFreeCommandBuffers FreeCommandBuffers;
- PFN_vkBeginCommandBuffer BeginCommandBuffer;
- PFN_vkEndCommandBuffer EndCommandBuffer;
- PFN_vkResetCommandBuffer ResetCommandBuffer;
- PFN_vkCmdBindPipeline CmdBindPipeline;
- PFN_vkCmdSetViewport CmdSetViewport;
- PFN_vkCmdSetScissor CmdSetScissor;
- PFN_vkCmdSetLineWidth CmdSetLineWidth;
- PFN_vkCmdSetDepthBias CmdSetDepthBias;
- PFN_vkCmdSetBlendConstants CmdSetBlendConstants;
- PFN_vkCmdSetDepthBounds CmdSetDepthBounds;
- PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask;
- PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask;
- PFN_vkCmdSetStencilReference CmdSetStencilReference;
- PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
- PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer;
- PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers;
- PFN_vkCmdDraw CmdDraw;
- PFN_vkCmdDrawIndexed CmdDrawIndexed;
- PFN_vkCmdDrawIndirect CmdDrawIndirect;
- PFN_vkCmdDrawIndexedIndirect CmdDrawIndexedIndirect;
- PFN_vkCmdDispatch CmdDispatch;
- PFN_vkCmdDispatchIndirect CmdDispatchIndirect;
- PFN_vkCmdCopyBuffer CmdCopyBuffer;
- PFN_vkCmdCopyImage CmdCopyImage;
- PFN_vkCmdBlitImage CmdBlitImage;
- PFN_vkCmdCopyBufferToImage CmdCopyBufferToImage;
- PFN_vkCmdCopyImageToBuffer CmdCopyImageToBuffer;
- PFN_vkCmdUpdateBuffer CmdUpdateBuffer;
- PFN_vkCmdFillBuffer CmdFillBuffer;
- PFN_vkCmdClearColorImage CmdClearColorImage;
- PFN_vkCmdClearDepthStencilImage CmdClearDepthStencilImage;
- PFN_vkCmdClearAttachments CmdClearAttachments;
- PFN_vkCmdResolveImage CmdResolveImage;
- PFN_vkCmdSetEvent CmdSetEvent;
- PFN_vkCmdResetEvent CmdResetEvent;
- PFN_vkCmdWaitEvents CmdWaitEvents;
- PFN_vkCmdPipelineBarrier CmdPipelineBarrier;
- PFN_vkCmdBeginQuery CmdBeginQuery;
- PFN_vkCmdEndQuery CmdEndQuery;
- PFN_vkCmdResetQueryPool CmdResetQueryPool;
- PFN_vkCmdWriteTimestamp CmdWriteTimestamp;
- PFN_vkCmdCopyQueryPoolResults CmdCopyQueryPoolResults;
- PFN_vkCmdPushConstants CmdPushConstants;
- PFN_vkCmdBeginRenderPass CmdBeginRenderPass;
- PFN_vkCmdNextSubpass CmdNextSubpass;
- PFN_vkCmdEndRenderPass CmdEndRenderPass;
- PFN_vkCmdExecuteCommands CmdExecuteCommands;
- PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
- PFN_vkDestroySwapchainKHR DestroySwapchainKHR;
- PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
- PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
- PFN_vkQueuePresentKHR QueuePresentKHR;
- // clang-format on
-};
-
struct DriverDispatchTable {
// clang-format off
PFN_vkDestroyInstance DestroyInstance;
@@ -194,6 +38,9 @@
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+ PFN_vkDestroyDevice DestroyDevice;
+ PFN_vkGetDeviceQueue GetDeviceQueue;
+ PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
PFN_vkCreateImage CreateImage;
PFN_vkDestroyImage DestroyImage;
PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
new file mode 100644
index 0000000..de9d1c6
--- /dev/null
+++ b/vulkan/libvulkan/driver.h
@@ -0,0 +1,165 @@
+/*
+ * 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 <type_traits>
+#include <log/log.h>
+
+#include <vulkan/vulkan.h>
+#include <hardware/hwvulkan.h>
+
+#include "api_gen.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 {
+
+struct InstanceData {
+ api::InstanceData opaque_api_data;
+
+ const VkAllocationCallbacks allocator;
+};
+
+struct DeviceData {
+ api::DeviceData opaque_api_data;
+
+ const VkAllocationCallbacks allocator;
+};
+
+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);
+// 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, VkQueue>::value ||
+ std::is_same<DispatchableType, VkCommandBuffer>::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(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 InstanceData& GetData(VkInstance instance) {
+ return *reinterpret_cast<InstanceData*>(GetDataInternal(instance));
+}
+
+inline InstanceData& GetData(VkPhysicalDevice physical_dev) {
+ return *reinterpret_cast<InstanceData*>(GetDataInternal(physical_dev));
+}
+
+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));
+}
+
+} // namespace driver
+} // namespace vulkan
+
+#endif // LIBVULKAN_DRIVER_H
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index d5cc280..65b09db 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -16,6 +16,7 @@
// module header
#include "loader.h"
+#include "driver.h"
// standard C headers
#include <dirent.h>
#include <dlfcn.h>
@@ -150,7 +151,7 @@
return ptr;
void* new_ptr = nullptr;
- if (posix_memalign(&new_ptr, alignment, size) != 0)
+ 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));
@@ -231,64 +232,47 @@
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));
+ : base{{}, *alloc_callbacks},
+ alloc(&base.allocator),
+ num_physical_devices(0) {
memset(physical_devices, 0, sizeof(physical_devices));
- drv.instance = VK_NULL_HANDLE;
+ enabled_extensions.reset();
memset(&drv.dispatch, 0, sizeof(drv.dispatch));
- drv.num_physical_devices = 0;
}
~Instance() {}
- const InstanceDispatchTable* dispatch_ptr;
- const VkInstance handle;
- InstanceDispatchTable dispatch;
+ driver::InstanceData base;
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));
+ : base{{}, *instance_->alloc}, instance(instance_) {
+ enabled_extensions.reset();
}
- DeviceDispatchTable dispatch;
+
+ driver::DeviceData base;
+
Instance* instance;
PFN_vkGetDeviceProcAddr get_device_proc_addr;
- Vector<LayerRef> active_layers;
+ DeviceExtensionSet enabled_extensions;
};
template <typename THandle>
@@ -324,230 +308,25 @@
typedef typename HandleTraits<THandle>::LoaderObjectType ObjectType;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winvalid-offsetof"
- const size_t kDispatchOffset = offsetof(ObjectType, dispatch);
+ const size_t kBaseOffset = offsetof(ObjectType, base);
#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;
+ const auto& base = driver::GetData(handle);
+ uintptr_t base_addr = reinterpret_cast<uintptr_t>(&base);
+ uintptr_t object_addr = base_addr - kBaseOffset;
return *reinterpret_cast<ObjectType*>(object_addr);
}
// -----------------------------------------------------------------------------
-void DestroyDevice(Device* device) {
- const VkAllocationCallbacks* alloc = device->instance->alloc;
+void DestroyDevice(Device* device, VkDevice vkdevice) {
+ const auto& instance = *device->instance;
+
+ if (vkdevice != VK_NULL_HANDLE)
+ instance.drv.dispatch.DestroyDevice(vkdevice, 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;
+ instance.alloc->pfnFree(instance.alloc->pUserData, device);
}
/*
@@ -578,16 +357,11 @@
// 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);
- }
+ const VkAllocationCallbacks* allocator,
+ VkInstance vkinstance) {
+ if (vkinstance != VK_NULL_HANDLE && instance->drv.dispatch.DestroyInstance)
+ instance->drv.dispatch.DestroyInstance(vkinstance, allocator);
+
instance->~Instance();
allocator->pfnFree(allocator->pUserData, instance);
}
@@ -605,23 +379,17 @@
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!");
+ if (!allocator)
+ allocator = &kDefaultAllocCallbacks;
- Instance& instance = GetDispatchParent(
- static_cast<VkInstance>(chain_info->u.instanceInfo.instance_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);
// Check that all enabled extensions are supported
- InstanceExtensionSet enabled_extensions;
uint32_t num_driver_extensions = 0;
for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
const char* name = create_info->ppEnabledExtensionNames[i];
@@ -629,11 +397,11 @@
if (id != kInstanceExtensionCount) {
if (g_driver_instance_extensions[id]) {
num_driver_extensions++;
- enabled_extensions.set(id);
+ instance.enabled_extensions.set(id);
continue;
}
if (id == kKHR_surface || id == kKHR_android_surface) {
- enabled_extensions.set(id);
+ instance.enabled_extensions.set(id);
continue;
}
// The loader natively supports debug report.
@@ -641,19 +409,6 @@
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;
@@ -682,60 +437,48 @@
"different answers!");
}
+ VkInstance drv_instance;
result = g_hwdevice->CreateInstance(&driver_create_info, instance.alloc,
- &instance.drv.instance);
+ &drv_instance);
if (result != VK_SUCCESS) {
- DestroyInstance_Bottom(instance.handle, allocator);
+ DestroyInstance(&instance, allocator, VK_NULL_HANDLE);
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);
+ if (!driver::SetData(drv_instance, instance.base)) {
+ DestroyInstance(&instance, allocator, drv_instance);
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,
- enabled_extensions, instance.drv.dispatch)) {
- DestroyInstance_Bottom(instance.handle, allocator);
+ if (!LoadDriverDispatchTable(drv_instance, g_hwdevice->GetInstanceProcAddr,
+ instance.enabled_extensions,
+ instance.drv.dispatch)) {
+ DestroyInstance(&instance, allocator, drv_instance);
return VK_ERROR_INITIALIZATION_FAILED;
}
uint32_t num_physical_devices = 0;
result = instance.drv.dispatch.EnumeratePhysicalDevices(
- instance.drv.instance, &num_physical_devices, nullptr);
+ drv_instance, &num_physical_devices, nullptr);
if (result != VK_SUCCESS) {
- DestroyInstance_Bottom(instance.handle, allocator);
+ DestroyInstance(&instance, allocator, drv_instance);
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);
+ drv_instance, &num_physical_devices, instance.physical_devices);
if (result != VK_SUCCESS) {
- DestroyInstance_Bottom(instance.handle, allocator);
+ DestroyInstance(&instance, allocator, drv_instance);
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);
+ if (!driver::SetData(instance.physical_devices[i], instance.base)) {
+ DestroyInstance(&instance, allocator, drv_instance);
return VK_ERROR_INITIALIZATION_FAILED;
}
- pdev_dispatch->vtbl = instance.dispatch_ptr;
uint32_t count;
if ((result = instance.drv.dispatch.EnumerateDeviceExtensionProperties(
@@ -749,7 +492,7 @@
extensions.resize(count);
} catch (std::bad_alloc&) {
ALOGE("instance creation failed: out of memory");
- DestroyInstance_Bottom(instance.handle, allocator);
+ DestroyInstance(&instance, allocator, drv_instance);
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
if ((result = instance.drv.dispatch.EnumerateDeviceExtensionProperties(
@@ -774,19 +517,116 @@
// 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;
+ instance.num_physical_devices = num_physical_devices;
- *vkinstance = instance.handle;
+ *vkinstance = drv_instance;
return VK_SUCCESS;
}
-PFN_vkVoidFunction GetInstanceProcAddr_Bottom(VkInstance, const char* name) {
+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;
+ return g_hwdevice->GetInstanceProcAddr(vkinstance, name);
}
VkResult EnumeratePhysicalDevices_Bottom(VkInstance vkinstance,
@@ -866,15 +706,38 @@
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;
+ VkPhysicalDevice pdev,
+ const char* layer_name,
+ uint32_t* properties_count,
+ VkExtensionProperties* properties) {
+ (void)layer_name;
+
+ Instance& instance = GetDispatchParent(pdev);
+
+ size_t gpu_idx = 0;
+ while (instance.physical_devices[gpu_idx] != pdev)
+ 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)));
+ uint32_t num_extensions = 0;
+ if (driver_extensions[kANDROID_native_buffer]) {
+ available[num_extensions++] = VkExtensionProperties{
+ VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_SPEC_VERSION};
+ }
+
+ if (!properties || *properties_count > num_extensions)
+ *properties_count = num_extensions;
+ if (properties)
+ std::copy(available, available + *properties_count, properties);
+
+ return *properties_count < num_extensions ? VK_INCOMPLETE : VK_SUCCESS;
}
// This is a no-op, the Top function returns the aggregate layer property
@@ -892,23 +755,24 @@
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);
+
+ // 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);
+
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);
@@ -924,6 +788,7 @@
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
@@ -933,21 +798,10 @@
[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;
@@ -956,25 +810,15 @@
VkResult result = instance.drv.dispatch.CreateDevice(
gpu, &driver_create_info, allocator, &drv_device);
if (result != VK_SUCCESS) {
+ DestroyDevice(device, VK_NULL_HANDLE);
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);
+ if (!driver::SetData(drv_device, device->base)) {
+ DestroyDevice(device, drv_device);
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"));
@@ -986,14 +830,55 @@
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;
+ VkAllocationCallbacks local_allocator;
+ if (!allocator) {
+ local_allocator = *instance.alloc;
+ allocator = &local_allocator;
}
+
+ DestroyInstance(&instance, allocator, vkinstance);
+}
+
+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,
@@ -1002,6 +887,30 @@
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;
@@ -1015,493 +924,36 @@
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;
+void DestroyDevice_Bottom(VkDevice vkdevice, const VkAllocationCallbacks*) {
+ DestroyDevice(&GetDispatchParent(vkdevice), vkdevice);
}
-VkResult EnumerateInstanceLayerProperties_Top(uint32_t* properties_count,
- VkLayerProperties* properties) {
- if (!EnsureInitialized())
- return VK_ERROR_INITIALIZATION_FAILED;
+void GetDeviceQueue_Bottom(VkDevice vkdevice,
+ uint32_t family,
+ uint32_t index,
+ VkQueue* queue_out) {
+ const auto& device = GetDispatchParent(vkdevice);
+ const auto& instance = *device.instance;
- 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;
+ instance.drv.dispatch.GetDeviceQueue(vkdevice, family, index, queue_out);
+ driver::SetData(*queue_out, device.base);
}
-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[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;
- }
- *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;
- }
-
- size_t gpu_idx = 0;
- while (instance.physical_devices[gpu_idx] != gpu)
- gpu_idx++;
-
- 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(
+VkResult AllocateCommandBuffers_Bottom(
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;
-}
+ const auto& device = GetDispatchParent(vkdevice);
+ const auto& instance = *device.instance;
-void DestroyDevice_Top(VkDevice vkdevice,
- const VkAllocationCallbacks* /*allocator*/) {
- if (!vkdevice)
- return;
- Device& device = GetDispatchParent(vkdevice);
- device.dispatch.DestroyDevice(vkdevice, device.instance->alloc);
- DestroyDevice(&device);
+ VkResult result = instance.drv.dispatch.AllocateCommandBuffers(
+ vkdevice, alloc_info, cmdbufs);
+ if (result == VK_SUCCESS) {
+ for (uint32_t i = 0; i < alloc_info->commandBufferCount; i++)
+ driver::SetData(cmdbufs[i], device.base);
+ }
+
+ return result;
}
// -----------------------------------------------------------------------------
@@ -1515,7 +967,7 @@
}
VkInstance GetDriverInstance(VkInstance instance) {
- return GetDispatchParent(instance).drv.instance;
+ return instance;
}
const DriverDispatchTable& GetDriverDispatch(VkInstance instance) {
@@ -1534,4 +986,60 @@
return GetDispatchParent(instance).debug_report_callbacks;
}
+namespace driver {
+
+bool Debuggable() {
+ return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
+}
+
+bool OpenHAL() {
+ if (!g_hwdevice)
+ LoadVulkanHAL();
+
+ return (g_hwdevice != nullptr);
+}
+
+const VkAllocationCallbacks& GetDefaultAllocator() {
+ return kDefaultAllocCallbacks;
+}
+
+PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
+ return GetInstanceProcAddr_Bottom(instance, pName);
+}
+
+PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
+ return GetDeviceProcAddr_Bottom(device, pName);
+}
+
+VkResult EnumerateInstanceExtensionProperties(
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties) {
+ (void)pLayerName;
+
+ VkExtensionProperties* available = static_cast<VkExtensionProperties*>(
+ alloca(kInstanceExtensionCount * sizeof(VkExtensionProperties)));
+ uint32_t num_extensions = 0;
+
+ 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};
+ }
+
+ if (!pProperties || *pPropertyCount > num_extensions)
+ *pPropertyCount = num_extensions;
+ if (pProperties)
+ std::copy(available, available + *pPropertyCount, pProperties);
+
+ return *pPropertyCount < num_extensions ? VK_INCOMPLETE : VK_SUCCESS;
+}
+
+} // namespace driver
+
} // namespace vulkan
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
index cec0ff6..0ec08b2 100644
--- a/vulkan/libvulkan/loader.h
+++ b/vulkan/libvulkan/loader.h
@@ -38,45 +38,10 @@
};
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,
@@ -86,19 +51,6 @@
// 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);
@@ -114,6 +66,9 @@
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);
+VKAPI_ATTR void DestroyDevice_Bottom(VkDevice device, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void GetDeviceQueue_Bottom(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
+VKAPI_ATTR VkResult AllocateCommandBuffers_Bottom(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
// clang-format on
const VkAllocationCallbacks* GetAllocator(VkInstance instance);
@@ -139,6 +94,18 @@
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
// -----------------------------------------------------------------------------