Merge "Expose service context name in denial." into stage-aosp-master am: 2834797055 am: b707b3e48e am: 8cf36ab3b7
am: c0a1d9a138

Change-Id: Ieca8234d053a47cee242021985f12a380d29ccf0
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 1a932c3..4f7cdf3 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,13 +4,16 @@
 [Builtin Hooks Options]
 # Only turn on clang-format check for the following subfolders.
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+               include/input/
                libs/binder/ndk/
                libs/graphicsenv/
                libs/gui/
+               libs/input/
                libs/renderengine/
                libs/ui/
                libs/vr/
                services/bufferhub/
+               services/inputflinger/
                services/surfaceflinger/
                services/vr/
 
diff --git a/cmds/dumpstate/README.md b/cmds/dumpstate/README.md
index c818c05..26dabbb 100644
--- a/cmds/dumpstate/README.md
+++ b/cmds/dumpstate/README.md
@@ -92,6 +92,12 @@
 adb shell setprop dumpstate.version default
 ```
 
+## To set Bugreport API workflow for bugreport
+
+```
+adb shell setprop settings_call_bugreport_api true
+```
+
 ## Code style and formatting
 
 Use the style defined at the
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 94fceb1..fe55fe7 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1989,12 +1989,12 @@
     }
 
     if (ds.options_->do_fb) {
-        ds.screenshot_path_ = ds.GetPath(".png");
+        ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-tmp.png" : ".png");
     }
     ds.tmp_path_ = ds.GetPath(".tmp");
     ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
 
-    std::string destination = ds.options_->bugreport_fd.get() != -1
+    std::string destination = ds.CalledByApi()
                                   ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
                                   : ds.bugreport_internal_dir_.c_str();
     MYLOGD(
@@ -2008,7 +2008,7 @@
         ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
 
     if (ds.options_->do_zip_file) {
-        ds.path_ = ds.GetPath(".zip");
+        ds.path_ = ds.GetPath(ds.CalledByApi() ? "-tmp.zip" : ".zip");
         MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
         create_parent_dirs(ds.path_.c_str());
         ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
@@ -2043,7 +2043,7 @@
         MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
         ds.name_ = name;
         if (!ds.screenshot_path_.empty()) {
-            std::string new_screenshot_path = ds.GetPath(".png");
+            std::string new_screenshot_path = ds.GetPath(ds.CalledByApi() ? "-tmp.png" : ".png");
             if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
                 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
                        new_screenshot_path.c_str(), strerror(errno));
@@ -2061,7 +2061,7 @@
         } else {
             do_text_file = false;
             // If the user has changed the suffix, we need to change the zip file name.
-            std::string new_path = ds.GetPath(".zip");
+            std::string new_path = ds.GetPath(ds.CalledByApi() ? "-tmp.zip" : ".zip");
             if (ds.path_ != new_path) {
                 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
                 if (rename(ds.path_.c_str(), new_path.c_str())) {
@@ -2716,6 +2716,10 @@
            ds.consent_callback_->getResult() == UserConsentResult::DENIED;
 }
 
+bool Dumpstate::CalledByApi() const {
+    return ds.options_->bugreport_fd.get() != -1 ? true : false;
+}
+
 void Dumpstate::CleanupFiles() {
     android::os::UnlinkAndLogOnError(tmp_path_);
     android::os::UnlinkAndLogOnError(screenshot_path_);
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index ae6a721..fe330df 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -341,6 +341,11 @@
     bool IsUserConsentDenied() const;
 
     /*
+     * Returns true if dumpstate is called by bugreporting API
+     */
+    bool CalledByApi() const;
+
+    /*
      * Structure to hold options that determine the behavior of dumpstate.
      */
     struct DumpOptions {
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 26e9984..d99bcc8 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -127,4 +127,6 @@
 
     const int FLAG_USE_QUOTA = 0x1000;
     const int FLAG_FORCE = 0x2000;
+
+    const int FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES = 0x20000;
 }
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index c70bc3e..792ff91 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -1,5 +1,6 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
+package android.surfaceflinger;
 
 message Trace {
     repeated Increment increment = 1;
@@ -46,6 +47,10 @@
         SecureFlagChange            secure_flag             = 14;
         DeferredTransactionChange   deferred_transaction    = 15;
         CornerRadiusChange          corner_radius           = 16;
+        ReparentChange              reparent                = 17;
+        RelativeParentChange        relative_parent         = 18;
+        DetachChildrenChange        detach_children         = 19;
+        ReparentChildrenChange      reparent_children       = 20;
     }
 }
 
@@ -177,3 +182,20 @@
     required int32  id   = 1;
     required int32  mode = 2;
 }
+
+message ReparentChange {
+    required int32 parent_id = 1;
+}
+
+message ReparentChildrenChange {
+    required int32 parent_id = 1;
+}
+
+message RelativeParentChange {
+    required int32 relative_parent_id = 1;
+    required int32 z = 2;
+}
+
+message DetachChildrenChange {
+    required bool detach_children = 1;
+}
diff --git a/cmds/surfacereplayer/replayer/Event.cpp b/cmds/surfacereplayer/replayer/Event.cpp
index 390d398..64db5f0 100644
--- a/cmds/surfacereplayer/replayer/Event.cpp
+++ b/cmds/surfacereplayer/replayer/Event.cpp
@@ -17,6 +17,7 @@
 #include "Event.h"
 
 using namespace android;
+using Increment = surfaceflinger::Increment;
 
 Event::Event(Increment::IncrementCase type) : mIncrementType(type) {}
 
diff --git a/cmds/surfacereplayer/replayer/Event.h b/cmds/surfacereplayer/replayer/Event.h
index 44b60f5..09a7c24 100644
--- a/cmds/surfacereplayer/replayer/Event.h
+++ b/cmds/surfacereplayer/replayer/Event.h
@@ -24,6 +24,8 @@
 
 namespace android {
 
+using Increment = surfaceflinger::Increment;
+
 class Event {
   public:
     Event(Increment::IncrementCase);
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 34886a9..a4a9b6a 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -412,6 +412,18 @@
                 setDeferredTransaction(transaction, change.id(),
                         change.deferred_transaction());
                 break;
+            case SurfaceChange::SurfaceChangeCase::kReparent:
+                setReparentChange(transaction, change.id(), change.reparent());
+                break;
+            case SurfaceChange::SurfaceChangeCase::kReparentChildren:
+                setReparentChildrenChange(transaction, change.id(), change.reparent_children());
+                break;
+            case SurfaceChange::SurfaceChangeCase::kRelativeParent:
+                setRelativeParentChange(transaction, change.id(), change.relative_parent());
+                break;
+            case SurfaceChange::SurfaceChangeCase::kDetachChildren:
+                setDetachChildrenChange(transaction, change.id(), change.detach_children());
+                break;
             default:
                 status = 1;
                 break;
@@ -680,3 +692,35 @@
     mComposerClient = new SurfaceComposerClient;
     return mComposerClient->initCheck();
 }
+
+void Replayer::setReparentChange(SurfaceComposerClient::Transaction& t,
+        layer_id id, const ReparentChange& c) {
+    sp<IBinder> newParentHandle = nullptr;
+    if (mLayers.count(c.parent_id()) != 0 && mLayers[c.parent_id()] != nullptr) {
+        newParentHandle = mLayers[c.parent_id()]->getHandle();
+    }
+    t.reparent(mLayers[id], newParentHandle);
+}
+
+void Replayer::setRelativeParentChange(SurfaceComposerClient::Transaction& t,
+        layer_id id, const RelativeParentChange& c) {
+    if (mLayers.count(c.relative_parent_id()) == 0 || mLayers[c.relative_parent_id()] == nullptr) {
+        ALOGE("Layer %d not found in set relative parent transaction", c.relative_parent_id());
+        return;
+    }
+    t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()]->getHandle(), c.z());
+}
+
+void Replayer::setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
+        layer_id id, const DetachChildrenChange& c) {
+    t.detachChildren(mLayers[id]);
+}
+
+void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
+        layer_id id, const ReparentChildrenChange& c) {
+    if (mLayers.count(c.parent_id()) == 0 || mLayers[c.parent_id()] == nullptr) {
+        ALOGE("Layer %d not found in reparent children transaction", c.parent_id());
+        return;
+    }
+    t.reparentChildren(mLayers[id], mLayers[c.parent_id()]->getHandle());
+}
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index ad807ee..3b94618 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -38,6 +38,8 @@
 #include <unordered_map>
 #include <utility>
 
+using namespace android::surfaceflinger;
+
 namespace android {
 
 const auto DEFAULT_PATH = "/data/local/tmp/SurfaceTrace.dat";
@@ -108,6 +110,14 @@
             layer_id id, const SecureFlagChange& sfc);
     void setDeferredTransaction(SurfaceComposerClient::Transaction& t,
             layer_id id, const DeferredTransactionChange& dtc);
+    void setReparentChange(SurfaceComposerClient::Transaction& t,
+            layer_id id, const ReparentChange& c);
+    void setRelativeParentChange(SurfaceComposerClient::Transaction& t,
+            layer_id id, const RelativeParentChange& c);
+    void setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
+            layer_id id, const DetachChildrenChange& c);
+    void setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
+            layer_id id, const ReparentChildrenChange& c);
 
     void setDisplaySurface(SurfaceComposerClient::Transaction& t,
             display_id id, const DispSurfaceChange& dsc);
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index 44883cc..1b589bc 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -83,7 +83,7 @@
  * Power a callback to be run on the next frame.  The data pointer provided will
  * be passed to the callback function when it's called.
  */
-void AChoreographer_postFrameCallback64(AChoreographer* chroreographer,
+void AChoreographer_postFrameCallback64(AChoreographer* choreographer,
                 AChoreographer_frameCallback64 callback, void* data) __INTRODUCED_IN(29);
 
 /**
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index ef2ad99..abb8368 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -130,7 +130,7 @@
 /**
  * Returns a sync fence that signals when the transaction has been presented.
  * The recipient of the callback takes ownership of the fence and is responsible for closing
- * it.
+ * it. If a device does not support present fences, a -1 will be returned.
  */
 int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* surface_transaction_stats)
                                                __INTRODUCED_IN(29);
diff --git a/include/input/Input.h b/include/input/Input.h
index 805957a..cbd1a41 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -24,12 +24,15 @@
  */
 
 #include <android/input.h>
+#include <math.h>
+#include <stdint.h>
 #include <utils/BitSet.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
 #include <utils/Timers.h>
 #include <utils/Vector.h>
-#include <stdint.h>
+
+#include <limits>
 
 /*
  * Additional private constants not defined in ndk/ui/input.h.
@@ -246,6 +249,13 @@
  */
 const char* motionClassificationToString(MotionClassification classification);
 
+/**
+ * Invalid value for cursor position. Used for non-mouse events, tests and injected events. Don't
+ * use it for direct comparison with any other value, because NaN isn't equal to itself according to
+ * IEEE 754. Use isnan() instead to check if a cursor position is valid.
+ */
+constexpr float AMOTION_EVENT_INVALID_CURSOR_POSITION = std::numeric_limits<float>::quiet_NaN();
+
 /*
  * Pointer coordinate data.
  */
@@ -459,6 +469,18 @@
 
     inline float getYPrecision() const { return mYPrecision; }
 
+    inline float getRawXCursorPosition() const { return mRawXCursorPosition; }
+
+    float getXCursorPosition() const;
+
+    inline float getRawYCursorPosition() const { return mRawYCursorPosition; }
+
+    float getYCursorPosition() const;
+
+    void setCursorPosition(float x, float y);
+
+    static inline bool isValidCursorPosition(float x, float y) { return !isnan(x) && !isnan(y); }
+
     inline nsecs_t getDownTime() const { return mDownTime; }
 
     inline void setDownTime(nsecs_t downTime) { mDownTime = downTime; }
@@ -600,26 +622,13 @@
 
     ssize_t findPointerIndex(int32_t pointerId) const;
 
-    void initialize(
-            int32_t deviceId,
-            int32_t source,
-            int32_t displayId,
-            int32_t action,
-            int32_t actionButton,
-            int32_t flags,
-            int32_t edgeFlags,
-            int32_t metaState,
-            int32_t buttonState,
-            MotionClassification classification,
-            float xOffset,
-            float yOffset,
-            float xPrecision,
-            float yPrecision,
-            nsecs_t downTime,
-            nsecs_t eventTime,
-            size_t pointerCount,
-            const PointerProperties* pointerProperties,
-            const PointerCoords* pointerCoords);
+    void initialize(int32_t deviceId, int32_t source, int32_t displayId, int32_t action,
+                    int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState,
+                    int32_t buttonState, MotionClassification classification, float xOffset,
+                    float yOffset, float xPrecision, float yPrecision, float rawXCursorPosition,
+                    float rawYCursorPosition, nsecs_t downTime, nsecs_t eventTime,
+                    size_t pointerCount, const PointerProperties* pointerProperties,
+                    const PointerCoords* pointerCoords);
 
     void copyFrom(const MotionEvent* other, bool keepHistory);
 
@@ -669,6 +678,8 @@
     float mYOffset;
     float mXPrecision;
     float mYPrecision;
+    float mRawXCursorPosition;
+    float mRawYCursorPosition;
     nsecs_t mDownTime;
     Vector<PointerProperties> mPointerProperties;
     Vector<nsecs_t> mSampleEventTimes;
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 63606e5..df23f61 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -113,6 +113,8 @@
             float yOffset;
             float xPrecision;
             float yPrecision;
+            float xCursorPosition;
+            float yCursorPosition;
             uint32_t pointerCount;
             uint32_t empty3;
             // Note that PointerCoords requires 8 byte alignment.
@@ -261,27 +263,14 @@
      * Returns BAD_VALUE if seq is 0 or if pointerCount is less than 1 or greater than MAX_POINTERS.
      * Other errors probably indicate that the channel is broken.
      */
-    status_t publishMotionEvent(
-            uint32_t seq,
-            int32_t deviceId,
-            int32_t source,
-            int32_t displayId,
-            int32_t action,
-            int32_t actionButton,
-            int32_t flags,
-            int32_t edgeFlags,
-            int32_t metaState,
-            int32_t buttonState,
-            MotionClassification classification,
-            float xOffset,
-            float yOffset,
-            float xPrecision,
-            float yPrecision,
-            nsecs_t downTime,
-            nsecs_t eventTime,
-            uint32_t pointerCount,
-            const PointerProperties* pointerProperties,
-            const PointerCoords* pointerCoords);
+    status_t publishMotionEvent(uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId,
+                                int32_t action, int32_t actionButton, int32_t flags,
+                                int32_t edgeFlags, int32_t metaState, int32_t buttonState,
+                                MotionClassification classification, float xOffset, float yOffset,
+                                float xPrecision, float yPrecision, float xCursorPosition,
+                                float yCursorPosition, nsecs_t downTime, nsecs_t eventTime,
+                                uint32_t pointerCount, const PointerProperties* pointerProperties,
+                                const PointerCoords* pointerCoords);
 
     /* Receives the finished signal from the consumer in reply to the original dispatch signal.
      * If a signal was received, returns the message sequence number,
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 0b9849a..85cf518 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -544,7 +544,7 @@
     return err == NO_ERROR;
 }
 
-uid_t Parcel::readCallingWorkSourceUid()
+uid_t Parcel::readCallingWorkSourceUid() const
 {
     if (!mRequestHeaderPresent) {
         return IPCThreadState::kUnsetWorkSource;
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 4e5f1aa..698fc07 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -384,7 +384,7 @@
     bool                replaceCallingWorkSourceUid(uid_t uid);
     // Returns the work source provided by the caller. This can only be trusted for trusted calling
     // uid.
-    uid_t               readCallingWorkSourceUid();
+    uid_t               readCallingWorkSourceUid() const;
     void                readRequestHeaders() const;
 
 private:
diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp
index 28cb138..9080ce1 100644
--- a/libs/cputimeinstate/Android.bp
+++ b/libs/cputimeinstate/Android.bp
@@ -19,7 +19,11 @@
     name: "libtimeinstate_test",
     srcs: ["testtimeinstate.cpp"],
     shared_libs: [
+        "libbase",
+        "libbpf",
+        "libbpf_android",
         "libtimeinstate",
+        "libnetdutils",
     ],
     cflags: [
         "-Werror",
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 5fd4a95..0e68e62 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -17,12 +17,14 @@
 #define LOG_TAG "libtimeinstate"
 
 #include "cputimeinstate.h"
+#include "timeinstate.h"
 
 #include <dirent.h>
 #include <errno.h>
 #include <inttypes.h>
 
 #include <mutex>
+#include <optional>
 #include <set>
 #include <string>
 #include <unordered_map>
@@ -37,23 +39,12 @@
 #include <libbpf.h>
 #include <log/log.h>
 
-#define BPF_FS_PATH "/sys/fs/bpf/"
-
 using android::base::StringPrintf;
 using android::base::unique_fd;
 
 namespace android {
 namespace bpf {
 
-struct time_key_t {
-    uint32_t uid;
-    uint32_t freq;
-};
-
-struct val_t {
-    uint64_t ar[100];
-};
-
 static std::mutex gInitializedMutex;
 static bool gInitialized = false;
 static uint32_t gNPolicies = 0;
@@ -62,19 +53,20 @@
 static std::set<uint32_t> gAllFreqs;
 static unique_fd gMapFd;
 
-static bool readNumbersFromFile(const std::string &path, std::vector<uint32_t> *out) {
+static std::optional<std::vector<uint32_t>> readNumbersFromFile(const std::string &path) {
     std::string data;
 
-    if (!android::base::ReadFileToString(path, &data)) return false;
+    if (!android::base::ReadFileToString(path, &data)) return {};
 
     auto strings = android::base::Split(data, " \n");
+    std::vector<uint32_t> ret;
     for (const auto &s : strings) {
         if (s.empty()) continue;
         uint32_t n;
-        if (!android::base::ParseUint(s, &n)) return false;
-        out->emplace_back(n);
+        if (!android::base::ParseUint(s, &n)) return {};
+        ret.emplace_back(n);
     }
-    return true;
+    return ret;
 }
 
 static int isPolicyFile(const struct dirent *d) {
@@ -111,20 +103,22 @@
         for (const auto &name : {"available", "boost"}) {
             std::string path =
                     StringPrintf("%s/%s/scaling_%s_frequencies", basepath, policy.c_str(), name);
-            if (!readNumbersFromFile(path, &freqs)) return false;
+            auto nums = readNumbersFromFile(path);
+            if (!nums) return false;
+            freqs.insert(freqs.end(), nums->begin(), nums->end());
         }
         std::sort(freqs.begin(), freqs.end());
         gPolicyFreqs.emplace_back(freqs);
 
         for (auto freq : freqs) gAllFreqs.insert(freq);
 
-        std::vector<uint32_t> cpus;
         std::string path = StringPrintf("%s/%s/%s", basepath, policy.c_str(), "related_cpus");
-        if (!readNumbersFromFile(path, &cpus)) return false;
-        gPolicyCpus.emplace_back(cpus);
+        auto cpus = readNumbersFromFile(path);
+        if (!cpus) return false;
+        gPolicyCpus.emplace_back(*cpus);
     }
 
-    gMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times")};
+    gMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times_map")};
     if (gMapFd < 0) return false;
 
     gInitialized = true;
@@ -151,17 +145,15 @@
 }
 
 // Retrieve the times in ns that uid spent running at each CPU frequency and store in freqTimes.
-// Returns false on error. Otherwise, returns true and populates freqTimes with a vector of vectors
-// using the format:
+// Return contains no value on error, otherwise it contains a vector of vectors using the format:
 // [[t0_0, t0_1, ...],
 //  [t1_0, t1_1, ...], ...]
 // where ti_j is the ns that uid spent running on the ith cluster at that cluster's jth lowest freq.
-bool getUidCpuFreqTimes(uint32_t uid, std::vector<std::vector<uint64_t>> *freqTimes) {
-    if (!gInitialized && !initGlobals()) return false;
+std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid) {
+    if (!gInitialized && !initGlobals()) return {};
     time_key_t key = {.uid = uid, .freq = 0};
 
-    freqTimes->clear();
-    freqTimes->resize(gNPolicies);
+    std::vector<std::vector<uint64_t>> out(gNPolicies);
     std::vector<uint32_t> idxs(gNPolicies, 0);
 
     val_t value;
@@ -172,32 +164,32 @@
             if (errno == ENOENT)
                 memset(&value.ar, 0, sizeof(value.ar));
             else
-                return false;
+                return {};
         }
         for (uint32_t i = 0; i < gNPolicies; ++i) {
             if (idxs[i] == gPolicyFreqs[i].size() || freq != gPolicyFreqs[i][idxs[i]]) continue;
             uint64_t time = 0;
             for (uint32_t cpu : gPolicyCpus[i]) time += value.ar[cpu];
             idxs[i] += 1;
-            (*freqTimes)[i].emplace_back(time);
+            out[i].emplace_back(time);
         }
     }
 
-    return true;
+    return out;
 }
 
 // Retrieve the times in ns that each uid spent running at each CPU freq and store in freqTimeMap.
-// Returns false on error. Otherwise, returns true and populates freqTimeMap with a map from uids to
-// vectors of vectors using the format:
+// Return contains no value on error, otherwise it contains a map from uids to vectors of vectors
+// using the format:
 // { uid0 -> [[t0_0_0, t0_0_1, ...], [t0_1_0, t0_1_1, ...], ...],
 //   uid1 -> [[t1_0_0, t1_0_1, ...], [t1_1_0, t1_1_1, ...], ...], ... }
 // where ti_j_k is the ns uid i spent running on the jth cluster at the cluster's kth lowest freq.
-bool getUidsCpuFreqTimes(
-        std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> *freqTimeMap) {
-    if (!gInitialized && !initGlobals()) return false;
+std::optional<std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>>>
+getUidsCpuFreqTimes() {
+    if (!gInitialized && !initGlobals()) return {};
 
-    int fd = bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times");
-    if (fd < 0) return false;
+    int fd = bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times_map");
+    if (fd < 0) return {};
     BpfMap<time_key_t, val_t> m(fd);
 
     std::vector<std::unordered_map<uint32_t, uint32_t>> policyFreqIdxs;
@@ -206,25 +198,26 @@
         for (size_t j = 0; j < gPolicyFreqs[i].size(); ++j) freqIdxs[gPolicyFreqs[i][j]] = j;
         policyFreqIdxs.emplace_back(freqIdxs);
     }
-
-    auto fn = [freqTimeMap, &policyFreqIdxs](const time_key_t &key, const val_t &val,
+    std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> map;
+    auto fn = [&map, &policyFreqIdxs](const time_key_t &key, const val_t &val,
                                              const BpfMap<time_key_t, val_t> &) {
-        if (freqTimeMap->find(key.uid) == freqTimeMap->end()) {
-            (*freqTimeMap)[key.uid].resize(gNPolicies);
+        if (map.find(key.uid) == map.end()) {
+            map[key.uid].resize(gNPolicies);
             for (uint32_t i = 0; i < gNPolicies; ++i) {
-                (*freqTimeMap)[key.uid][i].resize(gPolicyFreqs[i].size(), 0);
+                map[key.uid][i].resize(gPolicyFreqs[i].size(), 0);
             }
         }
 
         for (size_t policy = 0; policy < gNPolicies; ++policy) {
             for (const auto &cpu : gPolicyCpus[policy]) {
                 auto freqIdx = policyFreqIdxs[policy][key.freq];
-                (*freqTimeMap)[key.uid][policy][freqIdx] += val.ar[cpu];
+                map[key.uid][policy][freqIdx] += val.ar[cpu];
             }
         }
         return android::netdutils::status::ok;
     };
-    return isOk(m.iterateWithValue(fn));
+    if (isOk(m.iterateWithValue(fn))) return map;
+    return {};
 }
 
 // Clear all time in state data for a given uid. Returns false on error, true otherwise.
diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h
index 9f6103e..d7b4587 100644
--- a/libs/cputimeinstate/cputimeinstate.h
+++ b/libs/cputimeinstate/cputimeinstate.h
@@ -23,8 +23,9 @@
 namespace bpf {
 
 bool startTrackingUidCpuFreqTimes();
-bool getUidCpuFreqTimes(unsigned int uid, std::vector<std::vector<uint64_t>> *freqTimes);
-bool getUidsCpuFreqTimes(std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> *tisMap);
+std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid);
+std::optional<std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>>>
+    getUidsCpuFreqTimes();
 bool clearUidCpuFreqTimes(unsigned int uid);
 
 } // namespace bpf
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index 9837865..6347de1 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -1,57 +1,152 @@
 
+#include "timeinstate.h"
+
+#include <sys/sysinfo.h>
+
 #include <unordered_map>
 #include <vector>
 
 #include <gtest/gtest.h>
 
+#include <android-base/unique_fd.h>
+#include <bpf/BpfMap.h>
 #include <cputimeinstate.h>
+#include <libbpf.h>
 
 namespace android {
 namespace bpf {
 
+static constexpr uint64_t NSEC_PER_SEC = 1000000000;
+static constexpr uint64_t NSEC_PER_YEAR = NSEC_PER_SEC * 60 * 60 * 24 * 365;
+
 using std::vector;
 
 TEST(TimeInStateTest, SingleUid) {
-    vector<vector<uint64_t>> times;
-    ASSERT_TRUE(getUidCpuFreqTimes(0, &times));
-    EXPECT_FALSE(times.empty());
+    auto times = getUidCpuFreqTimes(0);
+    ASSERT_TRUE(times.has_value());
+    EXPECT_FALSE(times->empty());
 }
 
 TEST(TimeInStateTest, AllUid) {
     vector<size_t> sizes;
-    std::unordered_map<uint32_t, vector<vector<uint64_t>>> map;
-    ASSERT_TRUE(getUidsCpuFreqTimes(&map));
+    auto map = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map.has_value());
 
-    ASSERT_FALSE(map.empty());
+    ASSERT_FALSE(map->empty());
 
-    auto firstEntry = map.begin()->second;
+    auto firstEntry = map->begin()->second;
     for (const auto &subEntry : firstEntry) sizes.emplace_back(subEntry.size());
 
-    for (const auto &vec : map) {
+    for (const auto &vec : *map) {
         ASSERT_EQ(vec.second.size(), sizes.size());
         for (size_t i = 0; i < vec.second.size(); ++i) ASSERT_EQ(vec.second[i].size(), sizes[i]);
     }
 }
 
+TEST(TimeInStateTest, SingleAndAllUidConsistent) {
+    auto map = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map.has_value());
+    ASSERT_FALSE(map->empty());
+
+    for (const auto &kv : *map) {
+        uint32_t uid = kv.first;
+        auto times1 = kv.second;
+        auto times2 = getUidCpuFreqTimes(uid);
+        ASSERT_TRUE(times2.has_value());
+
+        ASSERT_EQ(times1.size(), times2->size());
+        for (uint32_t i = 0; i < times1.size(); ++i) {
+            ASSERT_EQ(times1[i].size(), (*times2)[i].size());
+            for (uint32_t j = 0; j < times1[i].size(); ++j) {
+                ASSERT_LE((*times2)[i][j] - times1[i][j], NSEC_PER_SEC);
+            }
+        }
+    }
+}
+
+void TestCheckDelta(uint64_t before, uint64_t after) {
+    // Times should never decrease
+    ASSERT_LE(before, after);
+    // UID can't have run for more than ~1s on each CPU
+    ASSERT_LE(after - before, NSEC_PER_SEC * 2 * get_nprocs_conf());
+}
+
+TEST(TimeInStateTest, AllUidMonotonic) {
+    auto map1 = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map1.has_value());
+    sleep(1);
+    auto map2 = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map2.has_value());
+
+    for (const auto &kv : *map1) {
+        uint32_t uid = kv.first;
+        auto times = kv.second;
+        ASSERT_NE(map2->find(uid), map2->end());
+        for (uint32_t policy = 0; policy < times.size(); ++policy) {
+            for (uint32_t freqIdx = 0; freqIdx < times[policy].size(); ++freqIdx) {
+                auto before = times[policy][freqIdx];
+                auto after = (*map2)[uid][policy][freqIdx];
+                ASSERT_NO_FATAL_FAILURE(TestCheckDelta(before, after));
+            }
+        }
+    }
+}
+
+TEST(TimeInStateTest, AllUidSanityCheck) {
+    auto map = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map.has_value());
+
+    bool foundLargeValue = false;
+    for (const auto &kv : *map) {
+        for (const auto &timeVec : kv.second) {
+            for (const auto &time : timeVec) {
+                ASSERT_LE(time, NSEC_PER_YEAR);
+                if (time > UINT32_MAX) foundLargeValue = true;
+            }
+        }
+    }
+    // UINT32_MAX nanoseconds is less than 5 seconds, so if every part of our pipeline is using
+    // uint64_t as expected, we should have some times higher than that.
+    ASSERT_TRUE(foundLargeValue);
+}
+
 TEST(TimeInStateTest, RemoveUid) {
-    vector<vector<uint64_t>> times, times2;
-    ASSERT_TRUE(getUidCpuFreqTimes(0, &times));
-    ASSERT_FALSE(times.empty());
+    uint32_t uid = 0;
+    {
+        // Find an unused UID
+        auto times = getUidsCpuFreqTimes();
+        ASSERT_TRUE(times.has_value());
+        ASSERT_FALSE(times->empty());
+        for (const auto &kv : *times) uid = std::max(uid, kv.first);
+        ++uid;
+    }
+    {
+        // Add a map entry for our fake UID by copying a real map entry
+        android::base::unique_fd fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times_map")};
+        ASSERT_GE(fd, 0);
+        time_key_t k;
+        ASSERT_FALSE(getFirstMapKey(fd, &k));
+        val_t val;
+        ASSERT_FALSE(findMapEntry(fd, &k, &val));
+        k.uid = uid;
+        ASSERT_FALSE(writeToMapEntry(fd, &k, &val, BPF_NOEXIST));
+    }
+    auto times = getUidCpuFreqTimes(uid);
+    ASSERT_TRUE(times.has_value());
+    ASSERT_FALSE(times->empty());
 
     uint64_t sum = 0;
-    for (size_t i = 0; i < times.size(); ++i) {
-        for (auto x : times[i]) sum += x;
+    for (size_t i = 0; i < times->size(); ++i) {
+        for (auto x : (*times)[i]) sum += x;
     }
     ASSERT_GT(sum, (uint64_t)0);
 
-    ASSERT_TRUE(clearUidCpuFreqTimes(0));
+    ASSERT_TRUE(clearUidCpuFreqTimes(uid));
 
-    ASSERT_TRUE(getUidCpuFreqTimes(0, &times2));
-    ASSERT_EQ(times2.size(), times.size());
-    for (size_t i = 0; i < times.size(); ++i) {
-        ASSERT_EQ(times2[i].size(), times[i].size());
-        for (size_t j = 0; j < times[i].size(); ++j) ASSERT_LE(times2[i][j], times[i][j]);
-    }
+    auto allTimes = getUidsCpuFreqTimes();
+    ASSERT_TRUE(allTimes.has_value());
+    ASSERT_FALSE(allTimes->empty());
+    ASSERT_EQ(allTimes->find(uid), allTimes->end());
 }
 
 } // namespace bpf
diff --git a/libs/cputimeinstate/timeinstate.h b/libs/cputimeinstate/timeinstate.h
new file mode 100644
index 0000000..cf66ae7
--- /dev/null
+++ b/libs/cputimeinstate/timeinstate.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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 <inttypes.h>
+
+#define BPF_FS_PATH "/sys/fs/bpf/"
+
+struct time_key_t {
+    uint32_t uid;
+    uint32_t freq;
+};
+
+struct val_t {
+    uint64_t ar[100];
+};
diff --git a/libs/graphicsenv/GpuStatsInfo.cpp b/libs/graphicsenv/GpuStatsInfo.cpp
index 4a801be..85137f5 100644
--- a/libs/graphicsenv/GpuStatsInfo.cpp
+++ b/libs/graphicsenv/GpuStatsInfo.cpp
@@ -86,6 +86,7 @@
     if ((status = parcel->writeInt64Vector(vkDriverLoadingTime)) != OK) return status;
     if ((status = parcel->writeInt64Vector(angleDriverLoadingTime)) != OK) return status;
     if ((status = parcel->writeBool(cpuVulkanInUse)) != OK) return status;
+    if ((status = parcel->writeBool(falsePrerotation)) != OK) return status;
     return OK;
 }
 
@@ -97,6 +98,7 @@
     if ((status = parcel->readInt64Vector(&vkDriverLoadingTime)) != OK) return status;
     if ((status = parcel->readInt64Vector(&angleDriverLoadingTime)) != OK) return status;
     if ((status = parcel->readBool(&cpuVulkanInUse)) != OK) return status;
+    if ((status = parcel->readBool(&falsePrerotation)) != OK) return status;
     return OK;
 }
 
@@ -105,6 +107,7 @@
     StringAppendF(&result, "appPackageName = %s\n", appPackageName.c_str());
     StringAppendF(&result, "driverVersionCode = %" PRIu64 "\n", driverVersionCode);
     StringAppendF(&result, "cpuVulkanInUse = %d\n", cpuVulkanInUse);
+    StringAppendF(&result, "falsePrerotation = %d\n", falsePrerotation);
     result.append("glDriverLoadingTime:");
     for (int32_t loadingTime : glDriverLoadingTime) {
         StringAppendF(&result, " %d", loadingTime);
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 24b6c2d..3e29e88 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -170,11 +170,11 @@
         std::lock_guard<std::mutex> lock(mStatsLock);
         if (mGpuStats.glDriverToSend) {
             mGpuStats.glDriverToSend = false;
-            sendGpuStatsLocked(GraphicsEnv::Api::API_GL, true, mGpuStats.glDriverLoadingTime);
+            sendGpuStatsLocked(GpuStatsInfo::Api::API_GL, true, mGpuStats.glDriverLoadingTime);
         }
         if (mGpuStats.vkDriverToSend) {
             mGpuStats.vkDriverToSend = false;
-            sendGpuStatsLocked(GraphicsEnv::Api::API_VK, true, mGpuStats.vkDriverLoadingTime);
+            sendGpuStatsLocked(GpuStatsInfo::Api::API_VK, true, mGpuStats.vkDriverLoadingTime);
         }
     });
     trySendGpuStatsThread.detach();
@@ -205,32 +205,32 @@
     mGpuStats.vulkanVersion = vulkanVersion;
 }
 
-void GraphicsEnv::setDriverToLoad(GraphicsEnv::Driver driver) {
+void GraphicsEnv::setDriverToLoad(GpuStatsInfo::Driver driver) {
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mStatsLock);
     switch (driver) {
-        case GraphicsEnv::Driver::GL:
-        case GraphicsEnv::Driver::GL_UPDATED:
-        case GraphicsEnv::Driver::ANGLE: {
-            if (mGpuStats.glDriverToLoad == GraphicsEnv::Driver::NONE) {
+        case GpuStatsInfo::Driver::GL:
+        case GpuStatsInfo::Driver::GL_UPDATED:
+        case GpuStatsInfo::Driver::ANGLE: {
+            if (mGpuStats.glDriverToLoad == GpuStatsInfo::Driver::NONE) {
                 mGpuStats.glDriverToLoad = driver;
                 break;
             }
 
-            if (mGpuStats.glDriverFallback == GraphicsEnv::Driver::NONE) {
+            if (mGpuStats.glDriverFallback == GpuStatsInfo::Driver::NONE) {
                 mGpuStats.glDriverFallback = driver;
             }
             break;
         }
-        case Driver::VULKAN:
-        case Driver::VULKAN_UPDATED: {
-            if (mGpuStats.vkDriverToLoad == GraphicsEnv::Driver::NONE) {
+        case GpuStatsInfo::Driver::VULKAN:
+        case GpuStatsInfo::Driver::VULKAN_UPDATED: {
+            if (mGpuStats.vkDriverToLoad == GpuStatsInfo::Driver::NONE) {
                 mGpuStats.vkDriverToLoad = driver;
                 break;
             }
 
-            if (mGpuStats.vkDriverFallback == GraphicsEnv::Driver::NONE) {
+            if (mGpuStats.vkDriverFallback == GpuStatsInfo::Driver::NONE) {
                 mGpuStats.vkDriverFallback = driver;
             }
             break;
@@ -240,13 +240,13 @@
     }
 }
 
-void GraphicsEnv::setDriverLoaded(GraphicsEnv::Api api, bool isDriverLoaded,
+void GraphicsEnv::setDriverLoaded(GpuStatsInfo::Api api, bool isDriverLoaded,
                                   int64_t driverLoadingTime) {
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mStatsLock);
     const bool doNotSend = mGpuStats.appPackageName.empty();
-    if (api == GraphicsEnv::Api::API_GL) {
+    if (api == GpuStatsInfo::Api::API_GL) {
         if (doNotSend) mGpuStats.glDriverToSend = true;
         mGpuStats.glDriverLoadingTime = driverLoadingTime;
     } else {
@@ -258,7 +258,7 @@
 }
 
 static sp<IGpuService> getGpuService() {
-    const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
+    static const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
     if (!binder) {
         ALOGE("Failed to get gpu service");
         return nullptr;
@@ -267,18 +267,18 @@
     return interface_cast<IGpuService>(binder);
 }
 
-void GraphicsEnv::setCpuVulkanInUse() {
+void GraphicsEnv::setTargetStats(const GpuStatsInfo::Stats stats, const uint64_t value) {
     ATRACE_CALL();
 
-    // Use the same stats lock to protect getGpuService() as well.
     std::lock_guard<std::mutex> lock(mStatsLock);
     const sp<IGpuService> gpuService = getGpuService();
     if (gpuService) {
-        gpuService->setCpuVulkanInUse(mGpuStats.appPackageName, mGpuStats.driverVersionCode);
+        gpuService->setTargetStats(mGpuStats.appPackageName, mGpuStats.driverVersionCode, stats,
+                                   value);
     }
 }
 
-void GraphicsEnv::sendGpuStatsLocked(GraphicsEnv::Api api, bool isDriverLoaded,
+void GraphicsEnv::sendGpuStatsLocked(GpuStatsInfo::Api api, bool isDriverLoaded,
                                      int64_t driverLoadingTime) {
     ATRACE_CALL();
 
@@ -299,16 +299,16 @@
           mGpuStats.driverVersionCode, mGpuStats.driverBuildTime, mGpuStats.appPackageName.c_str(),
           mGpuStats.vulkanVersion, static_cast<int32_t>(api), isDriverLoaded, driverLoadingTime);
 
-    GraphicsEnv::Driver driver = GraphicsEnv::Driver::NONE;
+    GpuStatsInfo::Driver driver = GpuStatsInfo::Driver::NONE;
     bool isIntendedDriverLoaded = false;
-    if (api == GraphicsEnv::Api::API_GL) {
+    if (api == GpuStatsInfo::Api::API_GL) {
         driver = mGpuStats.glDriverToLoad;
         isIntendedDriverLoaded =
-                isDriverLoaded && (mGpuStats.glDriverFallback == GraphicsEnv::Driver::NONE);
+                isDriverLoaded && (mGpuStats.glDriverFallback == GpuStatsInfo::Driver::NONE);
     } else {
         driver = mGpuStats.vkDriverToLoad;
         isIntendedDriverLoaded =
-                isDriverLoaded && (mGpuStats.vkDriverFallback == GraphicsEnv::Driver::NONE);
+                isDriverLoaded && (mGpuStats.vkDriverFallback == GpuStatsInfo::Driver::NONE);
     }
 
     const sp<IGpuService> gpuService = getGpuService();
diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp
index 5f96249..9f5b0ff 100644
--- a/libs/graphicsenv/IGpuService.cpp
+++ b/libs/graphicsenv/IGpuService.cpp
@@ -30,7 +30,7 @@
     virtual void setGpuStats(const std::string& driverPackageName,
                              const std::string& driverVersionName, uint64_t driverVersionCode,
                              int64_t driverBuildTime, const std::string& appPackageName,
-                             const int32_t vulkanVersion, GraphicsEnv::Driver driver,
+                             const int32_t vulkanVersion, GpuStatsInfo::Driver driver,
                              bool isDriverLoaded, int64_t driverLoadingTime) {
         Parcel data, reply;
         data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
@@ -92,15 +92,17 @@
         return reply.readParcelableVector(outStats);
     }
 
-    virtual void setCpuVulkanInUse(const std::string& appPackageName,
-                                   const uint64_t driverVersionCode) {
+    virtual void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                                const GpuStatsInfo::Stats stats, const uint64_t value) {
         Parcel data, reply;
         data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
 
         data.writeUtf8AsUtf16(appPackageName);
         data.writeUint64(driverVersionCode);
+        data.writeInt32(static_cast<int32_t>(stats));
+        data.writeUint64(value);
 
-        remote()->transact(BnGpuService::SET_CPU_VULKAN_IN_USE, data, &reply, IBinder::FLAG_ONEWAY);
+        remote()->transact(BnGpuService::SET_TARGET_STATS, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
 
@@ -143,7 +145,7 @@
             if ((status = data.readInt64(&driverLoadingTime)) != OK) return status;
 
             setGpuStats(driverPackageName, driverVersionName, driverVersionCode, driverBuildTime,
-                        appPackageName, vulkanVersion, static_cast<GraphicsEnv::Driver>(driver),
+                        appPackageName, vulkanVersion, static_cast<GpuStatsInfo::Driver>(driver),
                         isDriverLoaded, driverLoadingTime);
 
             return OK;
@@ -174,7 +176,7 @@
 
             return OK;
         }
-        case SET_CPU_VULKAN_IN_USE: {
+        case SET_TARGET_STATS: {
             CHECK_INTERFACE(IGpuService, data, reply);
 
             std::string appPackageName;
@@ -183,7 +185,14 @@
             uint64_t driverVersionCode;
             if ((status = data.readUint64(&driverVersionCode)) != OK) return status;
 
-            setCpuVulkanInUse(appPackageName, driverVersionCode);
+            int32_t stats;
+            if ((status = data.readInt32(&stats)) != OK) return status;
+
+            uint64_t value;
+            if ((status = data.readUint64(&value)) != OK) return status;
+
+            setTargetStats(appPackageName, driverVersionCode,
+                           static_cast<GpuStatsInfo::Stats>(stats), value);
 
             return OK;
         }
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
index edcccfe..7959652 100644
--- a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
+++ b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
@@ -70,6 +70,51 @@
     std::vector<int64_t> vkDriverLoadingTime = {};
     std::vector<int64_t> angleDriverLoadingTime = {};
     bool cpuVulkanInUse = false;
+    bool falsePrerotation = false;
+};
+
+/*
+ * class for holding the gpu stats in GraphicsEnv before sending to GpuService.
+ */
+class GpuStatsInfo {
+public:
+    enum Api {
+        API_GL = 0,
+        API_VK = 1,
+    };
+
+    enum Driver {
+        NONE = 0,
+        GL = 1,
+        GL_UPDATED = 2,
+        VULKAN = 3,
+        VULKAN_UPDATED = 4,
+        ANGLE = 5,
+    };
+
+    enum Stats {
+        CPU_VULKAN_IN_USE = 0,
+        FALSE_PREROTATION = 1,
+    };
+
+    GpuStatsInfo() = default;
+    GpuStatsInfo(const GpuStatsInfo&) = default;
+    virtual ~GpuStatsInfo() = default;
+
+    std::string driverPackageName = "";
+    std::string driverVersionName = "";
+    uint64_t driverVersionCode = 0;
+    int64_t driverBuildTime = 0;
+    std::string appPackageName = "";
+    int32_t vulkanVersion = 0;
+    Driver glDriverToLoad = Driver::NONE;
+    Driver glDriverFallback = Driver::NONE;
+    Driver vkDriverToLoad = Driver::NONE;
+    Driver vkDriverFallback = Driver::NONE;
+    bool glDriverToSend = false;
+    bool vkDriverToSend = false;
+    int64_t glDriverLoadingTime = 0;
+    int64_t vkDriverLoadingTime = 0;
 };
 
 } // namespace android
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index f5d19db..a47f468 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_UI_GRAPHICS_ENV_H
 #define ANDROID_UI_GRAPHICS_ENV_H 1
 
+#include <graphicsenv/GpuStatsInfo.h>
+
 #include <mutex>
 #include <string>
 #include <vector>
@@ -29,59 +31,14 @@
 
 class GraphicsEnv {
 public:
-    enum Api {
-        API_GL = 0,
-        API_VK = 1,
-    };
-
-    enum Driver {
-        NONE = 0,
-        GL = 1,
-        GL_UPDATED = 2,
-        VULKAN = 3,
-        VULKAN_UPDATED = 4,
-        ANGLE = 5,
-    };
-
-private:
-    struct GpuStats {
-        std::string driverPackageName;
-        std::string driverVersionName;
-        uint64_t driverVersionCode;
-        int64_t driverBuildTime;
-        std::string appPackageName;
-        int32_t vulkanVersion;
-        Driver glDriverToLoad;
-        Driver glDriverFallback;
-        Driver vkDriverToLoad;
-        Driver vkDriverFallback;
-        bool glDriverToSend;
-        bool vkDriverToSend;
-        int64_t glDriverLoadingTime;
-        int64_t vkDriverLoadingTime;
-
-        GpuStats()
-              : driverPackageName(""),
-                driverVersionName(""),
-                driverVersionCode(0),
-                driverBuildTime(0),
-                appPackageName(""),
-                vulkanVersion(0),
-                glDriverToLoad(Driver::NONE),
-                glDriverFallback(Driver::NONE),
-                vkDriverToLoad(Driver::NONE),
-                vkDriverFallback(Driver::NONE),
-                glDriverToSend(false),
-                vkDriverToSend(false),
-                glDriverLoadingTime(0),
-                vkDriverLoadingTime(0) {}
-    };
-
-public:
     static GraphicsEnv& getInstance();
 
+    // Check if device is debuggable.
     int getCanLoadSystemLibraries();
 
+    /*
+     * Apis for updatable driver
+     */
     // Set a search path for loading graphics drivers. The path is a list of
     // directories separated by ':'. A directory can be contained in a zip file
     // (drivers must be stored uncompressed and page aligned); such elements
@@ -91,17 +48,31 @@
     // graphics drivers. The string is a list of libraries separated by ':',
     // which is required by android_link_namespaces.
     void setDriverPathAndSphalLibraries(const std::string path, const std::string sphalLibraries);
+    // Get the updatable driver namespace.
     android_namespace_t* getDriverNamespace();
+
+    /*
+     * Apis for GpuStats
+     */
+    // Hint there's real activity launching on the app process.
     void hintActivityLaunch();
+    // Set the initial GpuStats.
     void setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName,
                      uint64_t versionCode, int64_t driverBuildTime,
                      const std::string& appPackageName, const int32_t vulkanVersion);
-    void setCpuVulkanInUse();
-    void setDriverToLoad(Driver driver);
-    void setDriverLoaded(Api api, bool isDriverLoaded, int64_t driverLoadingTime);
-    void sendGpuStatsLocked(Api api, bool isDriverLoaded, int64_t driverLoadingTime);
+    // Set stats for target GpuStatsInfo::Stats type.
+    void setTargetStats(const GpuStatsInfo::Stats stats, const uint64_t value = 0);
+    // Set which driver is intended to load.
+    void setDriverToLoad(GpuStatsInfo::Driver driver);
+    // Set which driver is actually loaded.
+    void setDriverLoaded(GpuStatsInfo::Api api, bool isDriverLoaded, int64_t driverLoadingTime);
 
+    /*
+     * Apis for ANGLE
+     */
+    // Check if the requested app should use ANGLE.
     bool shouldUseAngle(std::string appName);
+    // Check if this app process should use ANGLE.
     bool shouldUseAngle();
     // Set a search path for loading ANGLE libraries. The path is a list of
     // directories separated by ':'. A directory can be contained in a zip file
@@ -110,43 +81,75 @@
     //     /system/app/ANGLEPrebuilt/ANGLEPrebuilt.apk!/lib/arm64-v8a
     void setAngleInfo(const std::string path, const std::string appName, std::string devOptIn,
                       const int rulesFd, const long rulesOffset, const long rulesLength);
+    // Get the ANGLE driver namespace.
     android_namespace_t* getAngleNamespace();
+    // Get the app name for ANGLE debug message.
     std::string& getAngleAppName();
 
+    /*
+     * Apis for debug layer
+     */
+    // Set additional layer search paths.
     void setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths);
+    // Get the app namespace for loading layers.
     NativeLoaderNamespace* getAppNamespace();
-
+    // Get additional layer search paths.
     const std::string& getLayerPaths();
-
+    // Set the Vulkan debug layers.
     void setDebugLayers(const std::string layers);
+    // Set the GL debug layers.
     void setDebugLayersGLES(const std::string layers);
+    // Get the debug layers to load.
     const std::string& getDebugLayers();
+    // Get the debug layers to load.
     const std::string& getDebugLayersGLES();
 
 private:
     enum UseAngle { UNKNOWN, YES, NO };
 
+    // Load requested ANGLE library.
     void* loadLibrary(std::string name);
+    // Check ANGLE support with the rules.
     bool checkAngleRules(void* so);
+    // Update whether ANGLE should be used.
     void updateUseAngle();
+    // Link updatable driver namespace with llndk and vndk-sp libs.
     bool linkDriverNamespaceLocked(android_namespace_t* vndkNamespace);
+    // Send the initial complete GpuStats to GpuService.
+    void sendGpuStatsLocked(GpuStatsInfo::Api api, bool isDriverLoaded, int64_t driverLoadingTime);
 
     GraphicsEnv() = default;
+    // Path to updatable driver libs.
     std::string mDriverPath;
+    // Path to additional sphal libs linked to updatable driver namespace.
     std::string mSphalLibraries;
+    // This mutex protects mGpuStats and get gpuservice call.
     std::mutex mStatsLock;
-    GpuStats mGpuStats;
+    // Information bookkept for GpuStats.
+    GpuStatsInfo mGpuStats;
+    // Path to ANGLE libs.
     std::string mAnglePath;
+    // This App's name.
     std::string mAngleAppName;
+    // ANGLE developer opt in status.
     std::string mAngleDeveloperOptIn;
+    // ANGLE rules.
     std::vector<char> mRulesBuffer;
+    // Use ANGLE flag.
     UseAngle mUseAngle = UNKNOWN;
+    // Vulkan debug layers libs.
     std::string mDebugLayers;
+    // GL debug layers libs.
     std::string mDebugLayersGLES;
+    // Additional debug layers search path.
     std::string mLayerPaths;
+    // This mutex protects the namespace creation.
     std::mutex mNamespaceMutex;
+    // Updatable driver namespace.
     android_namespace_t* mDriverNamespace = nullptr;
+    // ANGLE namespace.
     android_namespace_t* mAngleNamespace = nullptr;
+    // This App's namespace.
     NativeLoaderNamespace* mAppNamespace = nullptr;
 };
 
diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h
index 34f1c7e..f523d58 100644
--- a/libs/graphicsenv/include/graphicsenv/IGpuService.h
+++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h
@@ -37,12 +37,12 @@
     virtual void setGpuStats(const std::string& driverPackageName,
                              const std::string& driverVersionName, uint64_t driverVersionCode,
                              int64_t driverBuildTime, const std::string& appPackageName,
-                             const int32_t vulkanVersion, GraphicsEnv::Driver driver,
+                             const int32_t vulkanVersion, GpuStatsInfo::Driver driver,
                              bool isDriverLoaded, int64_t driverLoadingTime) = 0;
 
-    // set CPU Vulkan in use signal from GraphicsEnvironment.
-    virtual void setCpuVulkanInUse(const std::string& appPackageName,
-                                   const uint64_t driverVersionCode) = 0;
+    // set target stats.
+    virtual void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                                const GpuStatsInfo::Stats stats, const uint64_t value = 0) = 0;
 
     // get GPU global stats from GpuStats module.
     virtual status_t getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const = 0;
@@ -57,7 +57,7 @@
         SET_GPU_STATS = IBinder::FIRST_CALL_TRANSACTION,
         GET_GPU_STATS_GLOBAL_INFO,
         GET_GPU_STATS_APP_INFO,
-        SET_CPU_VULKAN_IN_USE,
+        SET_TARGET_STATS,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index e3e63ee..beb13ad 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -15,6 +15,10 @@
     name: "libgui_headers",
     vendor_available: true,
     export_include_dirs: ["include"],
+
+    // we must build this module to get the required header as that is generated
+    export_shared_lib_headers: [ "android.hidl.token@1.0-utils" ],
+    shared_libs: [ "android.hidl.token@1.0-utils" ],
 }
 
 cc_library_shared {
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index e0e3431..b429d38 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -97,7 +97,9 @@
     mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
             HAL_DATASPACE_UNKNOWN),
     mLastQueuedSlot(INVALID_BUFFER_SLOT),
-    mUniqueId(getUniqueId())
+    mUniqueId(getUniqueId()),
+    mAutoPrerotation(false),
+    mTransformHintInUse(0)
 {
     int numStartingBuffers = getMaxBufferCountLocked();
     for (int s = 0; s < numStartingBuffers; s++) {
@@ -123,10 +125,12 @@
                             mQueueBufferCanDrop, mLegacyBufferDrop);
     outResult->appendFormat("%s  default-size=[%dx%d] default-format=%d ", prefix.string(),
                             mDefaultWidth, mDefaultHeight, mDefaultBufferFormat);
-    outResult->appendFormat("transform-hint=%02x frame-counter=%" PRIu64, mTransformHint,
-                            mFrameCounter);
+    outResult->appendFormat("%s  transform-hint=%02x frame-counter=%" PRIu64 "\n", prefix.string(),
+                            mTransformHint, mFrameCounter);
+    outResult->appendFormat("%s  mTransformHintInUse=%02x mAutoPrerotation=%d\n", prefix.string(),
+                            mTransformHintInUse, mAutoPrerotation);
 
-    outResult->appendFormat("\n%sFIFO(%zu):\n", prefix.string(), mQueue.size());
+    outResult->appendFormat("%sFIFO(%zu):\n", prefix.string(), mQueue.size());
     Fifo::const_iterator current(mQueue.begin());
     while (current != mQueue.end()) {
         double timestamp = current->mTimestamp / 1e9;
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 92ab410..d149674 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -408,6 +408,10 @@
         if (useDefaultSize) {
             width = mCore->mDefaultWidth;
             height = mCore->mDefaultHeight;
+            if (mCore->mAutoPrerotation &&
+                (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
+                std::swap(width, height);
+            }
         }
 
         int found = BufferItem::INVALID_BUFFER_SLOT;
@@ -960,7 +964,7 @@
 
         output->width = mCore->mDefaultWidth;
         output->height = mCore->mDefaultHeight;
-        output->transformHint = mCore->mTransformHint;
+        output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
         output->numPendingBuffers = static_cast<uint32_t>(mCore->mQueue.size());
         output->nextFrameNumber = mCore->mFrameCounter + 1;
 
@@ -1141,9 +1145,6 @@
         case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
             value = static_cast<int32_t>(mCore->mConsumerIsProtected);
             break;
-        case NATIVE_WINDOW_MAX_BUFFER_COUNT:
-            value = static_cast<int32_t>(mCore->mMaxBufferCount);
-            break;
         default:
             return BAD_VALUE;
     }
@@ -1203,11 +1204,12 @@
 
             output->width = mCore->mDefaultWidth;
             output->height = mCore->mDefaultHeight;
-            output->transformHint = mCore->mTransformHint;
+            output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
             output->numPendingBuffers =
                     static_cast<uint32_t>(mCore->mQueue.size());
             output->nextFrameNumber = mCore->mFrameCounter + 1;
             output->bufferReplaced = false;
+            output->maxBufferCount = mCore->mMaxBufferCount;
 
             if (listener != nullptr) {
                 // Set up a death notification so that we can disconnect
@@ -1307,6 +1309,7 @@
                     mCore->mConnectedPid = -1;
                     mCore->mSidebandStream.clear();
                     mCore->mDequeueCondition.notify_all();
+                    mCore->mAutoPrerotation = false;
                     listener = mCore->mConsumerListener;
                 } else if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
                     BQ_LOGE("disconnect: not connected (req=%d)", api);
@@ -1350,6 +1353,8 @@
 void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
         PixelFormat format, uint64_t usage) {
     ATRACE_CALL();
+
+    const bool useDefaultSize = !width && !height;
     while (true) {
         size_t newBufferCount = 0;
         uint32_t allocWidth = 0;
@@ -1376,6 +1381,11 @@
 
             allocWidth = width > 0 ? width : mCore->mDefaultWidth;
             allocHeight = height > 0 ? height : mCore->mDefaultHeight;
+            if (useDefaultSize && mCore->mAutoPrerotation &&
+                (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
+                std::swap(allocWidth, allocHeight);
+            }
+
             allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
             allocUsage = usage | mCore->mConsumerUsageBits;
             allocName.assign(mCore->mConsumerName.string(), mCore->mConsumerName.size());
@@ -1406,6 +1416,11 @@
             std::unique_lock<std::mutex> lock(mCore->mMutex);
             uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
             uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
+            if (useDefaultSize && mCore->mAutoPrerotation &&
+                (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
+                std::swap(checkWidth, checkHeight);
+            }
+
             PixelFormat checkFormat = format != 0 ?
                     format : mCore->mDefaultBufferFormat;
             uint64_t checkUsage = usage | mCore->mConsumerUsageBits;
@@ -1608,4 +1623,14 @@
     return NO_ERROR;
 }
 
+status_t BufferQueueProducer::setAutoPrerotation(bool autoPrerotation) {
+    ATRACE_CALL();
+    BQ_LOGV("setAutoPrerotation: %d", autoPrerotation);
+
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
+
+    mCore->mAutoPrerotation = autoPrerotation;
+    return NO_ERROR;
+}
+
 } // namespace android
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 8199c98..59f1bcd 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -46,7 +46,6 @@
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
-extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
 #define EGL_PROTECTED_CONTENT_EXT 0x32C0
 
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 0e03b7d..0009a57 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -73,6 +73,7 @@
     GET_UNIQUE_ID,
     GET_CONSUMER_USAGE,
     SET_LEGACY_BUFFER_DROP,
+    SET_AUTO_PREROTATION,
 };
 
 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -547,6 +548,17 @@
         }
         return actualResult;
     }
+
+    virtual status_t setAutoPrerotation(bool autoPrerotation) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeBool(autoPrerotation);
+        status_t result = remote()->transact(SET_AUTO_PREROTATION, data, &reply);
+        if (result == NO_ERROR) {
+            result = reply.readInt32();
+        }
+        return result;
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -675,6 +687,10 @@
     status_t getConsumerUsage(uint64_t* outUsage) const override {
         return mBase->getConsumerUsage(outUsage);
     }
+
+    status_t setAutoPrerotation(bool autoPrerotation) override {
+        return mBase->setAutoPrerotation(autoPrerotation);
+    }
 };
 
 IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer,
@@ -688,6 +704,12 @@
     return INVALID_OPERATION;
 }
 
+status_t IGraphicBufferProducer::setAutoPrerotation(bool autoPrerotation) {
+    // No-op for IGBP other than BufferQueue.
+    (void)autoPrerotation;
+    return INVALID_OPERATION;
+}
+
 status_t IGraphicBufferProducer::exportToParcel(Parcel* parcel) {
     status_t res = OK;
     res = parcel->writeUint32(USE_BUFFER_QUEUE);
@@ -1050,6 +1072,13 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
+        case SET_AUTO_PREROTATION: {
+            CHECK_INTERFACE(IGraphicBuffer, data, reply);
+            bool autoPrerotation = data.readBool();
+            status_t result = setAutoPrerotation(autoPrerotation);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
@@ -1141,12 +1170,8 @@
 
 // ----------------------------------------------------------------------------
 constexpr size_t IGraphicBufferProducer::QueueBufferOutput::minFlattenedSize() {
-    return sizeof(width) +
-            sizeof(height) +
-            sizeof(transformHint) +
-            sizeof(numPendingBuffers) +
-            sizeof(nextFrameNumber) +
-            sizeof(bufferReplaced);
+    return sizeof(width) + sizeof(height) + sizeof(transformHint) + sizeof(numPendingBuffers) +
+            sizeof(nextFrameNumber) + sizeof(bufferReplaced) + sizeof(maxBufferCount);
 }
 
 size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const {
@@ -1170,6 +1195,7 @@
     FlattenableUtils::write(buffer, size, numPendingBuffers);
     FlattenableUtils::write(buffer, size, nextFrameNumber);
     FlattenableUtils::write(buffer, size, bufferReplaced);
+    FlattenableUtils::write(buffer, size, maxBufferCount);
 
     return frameTimestamps.flatten(buffer, size, fds, count);
 }
@@ -1187,6 +1213,7 @@
     FlattenableUtils::read(buffer, size, numPendingBuffers);
     FlattenableUtils::read(buffer, size, nextFrameNumber);
     FlattenableUtils::read(buffer, size, bufferReplaced);
+    FlattenableUtils::read(buffer, size, maxBufferCount);
 
     return frameTimestamps.unflatten(buffer, size, fds, count);
 }
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 42eb921..be58b85 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -169,12 +169,10 @@
 }
 
 status_t ComposerState::write(Parcel& output) const {
-    output.writeStrongBinder(IInterface::asBinder(client));
     return state.write(output);
 }
 
 status_t ComposerState::read(const Parcel& input) {
-    client = interface_cast<ISurfaceComposerClient>(input.readStrongBinder());
     return state.read(input);
 }
 
@@ -267,8 +265,9 @@
     }
     if (other.what & eFlagsChanged) {
         what |= eFlagsChanged;
-        flags = other.flags;
-        mask = other.mask;
+        flags &= ~other.mask;
+        flags |= (other.flags & other.mask);
+        mask |= other.mask;
     }
     if (other.what & eLayerStackChanged) {
         what |= eLayerStackChanged;
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 9fe5de8..4e6a4e7 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -96,6 +96,7 @@
     mConnectedToCpu = false;
     mProducerControlledByApp = controlledByApp;
     mSwapIntervalZero = false;
+    mMaxBufferCount = 0;
 }
 
 Surface::~Surface() {
@@ -961,6 +962,10 @@
                 *value = static_cast<int>(mDataSpace);
                 return NO_ERROR;
             }
+            case NATIVE_WINDOW_MAX_BUFFER_COUNT: {
+                *value = mMaxBufferCount;
+                return NO_ERROR;
+            }
         }
     }
     return mGraphicBufferProducer->query(what, value);
@@ -1072,6 +1077,9 @@
     case NATIVE_WINDOW_GET_CONSUMER_USAGE64:
         res = dispatchGetConsumerUsage64(args);
         break;
+    case NATIVE_WINDOW_SET_AUTO_PREROTATION:
+        res = dispatchSetAutoPrerotation(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -1272,6 +1280,11 @@
     return getConsumerUsage(usage);
 }
 
+int Surface::dispatchSetAutoPrerotation(va_list args) {
+    bool autoPrerotation = va_arg(args, int);
+    return setAutoPrerotation(autoPrerotation);
+}
+
 bool Surface::transformToDisplayInverse() {
     return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) ==
             NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
@@ -1298,6 +1311,7 @@
         mDefaultWidth = output.width;
         mDefaultHeight = output.height;
         mNextFrameNumber = output.nextFrameNumber;
+        mMaxBufferCount = output.maxBufferCount;
 
         // Ignore transform hint if sticky transform is set or transform to display inverse flag is
         // set. Transform hint should be ignored if the client is expected to always submit buffers
@@ -1339,6 +1353,7 @@
         mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
         mTransform = 0;
         mStickyTransform = 0;
+        mAutoPrerotation = false;
 
         if (api == NATIVE_WINDOW_API_CPU) {
             mConnectedToCpu = false;
@@ -1951,4 +1966,22 @@
     return err;
 }
 
+int Surface::setAutoPrerotation(bool autoPrerotation) {
+    ATRACE_CALL();
+    ALOGV("Surface::setAutoPrerotation (%d)", autoPrerotation);
+    Mutex::Autolock lock(mMutex);
+
+    if (mAutoPrerotation == autoPrerotation) {
+        return OK;
+    }
+
+    status_t err = mGraphicBufferProducer->setAutoPrerotation(autoPrerotation);
+    if (err == NO_ERROR) {
+        mAutoPrerotation = autoPrerotation;
+    }
+    ALOGE_IF(err, "IGraphicBufferProducer::setAutoPrerotation(%d) returned %s", autoPrerotation,
+             strerror(-err));
+    return err;
+}
+
 }; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index def9fe9..e6b1beb 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -202,7 +202,8 @@
      * callbackIds to generate one super map that contains all the sp<IBinder> to sp<SurfaceControl>
      * that could possibly exist for the callbacks.
      */
-    std::unordered_map<sp<IBinder>, sp<SurfaceControl>, IBinderHash> surfaceControls;
+    std::unordered_map<sp<IBinder>, sp<SurfaceControl>, SurfaceComposerClient::IBinderHash>
+            surfaceControls;
     for (const auto& transactionStats : listenerStats.transactionStats) {
         for (auto callbackId : transactionStats.callbackIds) {
             auto& [callbackFunction, callbackSurfaceControls] = mCallbacks[callbackId];
@@ -322,21 +323,109 @@
         mTransactionNestCount(other.mTransactionNestCount),
         mAnimation(other.mAnimation),
         mEarlyWakeup(other.mEarlyWakeup),
+        mContainsBuffer(other.mContainsBuffer),
         mDesiredPresentTime(other.mDesiredPresentTime) {
     mDisplayStates = other.mDisplayStates;
     mComposerStates = other.mComposerStates;
     mInputWindowCommands = other.mInputWindowCommands;
+    mListenerCallbacks = other.mListenerCallbacks;
+}
+
+std::unique_ptr<SurfaceComposerClient::Transaction>
+SurfaceComposerClient::Transaction::createFromParcel(const Parcel* parcel) {
+    auto transaction = std::make_unique<Transaction>();
+    if (transaction->readFromParcel(parcel) == NO_ERROR) {
+        return transaction;
+    }
+    return nullptr;
+}
+
+status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel) {
+    const uint32_t forceSynchronous = parcel->readUint32();
+    const uint32_t transactionNestCount = parcel->readUint32();
+    const bool animation = parcel->readBool();
+    const bool earlyWakeup = parcel->readBool();
+    const bool containsBuffer = parcel->readBool();
+    const int64_t desiredPresentTime = parcel->readInt64();
+
+    size_t count = static_cast<size_t>(parcel->readUint32());
+    if (count > parcel->dataSize()) {
+        return BAD_VALUE;
+    }
+    SortedVector<DisplayState> displayStates;
+    displayStates.setCapacity(count);
+    for (size_t i = 0; i < count; i++) {
+        DisplayState displayState;
+        if (displayState.read(*parcel) == BAD_VALUE) {
+            return BAD_VALUE;
+        }
+        displayStates.add(displayState);
+    }
+
+    count = static_cast<size_t>(parcel->readUint32());
+    if (count > parcel->dataSize()) {
+        return BAD_VALUE;
+    }
+    std::unordered_map<sp<IBinder>, ComposerState, IBinderHash> composerStates;
+    composerStates.reserve(count);
+    for (size_t i = 0; i < count; i++) {
+        sp<IBinder> surfaceControlHandle = parcel->readStrongBinder();
+
+        ComposerState composerState;
+        if (composerState.read(*parcel) == BAD_VALUE) {
+            return BAD_VALUE;
+        }
+        composerStates[surfaceControlHandle] = composerState;
+    }
+
+    InputWindowCommands inputWindowCommands;
+    inputWindowCommands.read(*parcel);
+
+    // Parsing was successful. Update the object.
+    mForceSynchronous = forceSynchronous;
+    mTransactionNestCount = transactionNestCount;
+    mAnimation = animation;
+    mEarlyWakeup = earlyWakeup;
+    mContainsBuffer = containsBuffer;
+    mDesiredPresentTime = desiredPresentTime;
+    mDisplayStates = displayStates;
+    mComposerStates = composerStates;
+    mInputWindowCommands = inputWindowCommands;
+    // listener callbacks contain function pointer addresses and may not be safe to parcel.
+    mListenerCallbacks.clear();
+    return NO_ERROR;
+}
+
+status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const {
+    parcel->writeUint32(mForceSynchronous);
+    parcel->writeUint32(mTransactionNestCount);
+    parcel->writeBool(mAnimation);
+    parcel->writeBool(mEarlyWakeup);
+    parcel->writeBool(mContainsBuffer);
+    parcel->writeInt64(mDesiredPresentTime);
+    parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size()));
+    for (auto const& displayState : mDisplayStates) {
+        displayState.write(*parcel);
+    }
+
+    parcel->writeUint32(static_cast<uint32_t>(mComposerStates.size()));
+    for (auto const& [surfaceHandle, composerState] : mComposerStates) {
+        parcel->writeStrongBinder(surfaceHandle);
+        composerState.write(*parcel);
+    }
+
+    mInputWindowCommands.write(*parcel);
+    return NO_ERROR;
 }
 
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
-    for (auto const& kv : other.mComposerStates) {
-        if (mComposerStates.count(kv.first) == 0) {
-            mComposerStates[kv.first] = kv.second;
+    for (auto const& [surfaceHandle, composerState] : other.mComposerStates) {
+        if (mComposerStates.count(surfaceHandle) == 0) {
+            mComposerStates[surfaceHandle] = composerState;
         } else {
-            mComposerStates[kv.first].state.merge(kv.second.state);
+            mComposerStates[surfaceHandle].state.merge(composerState.state);
         }
     }
-    other.mComposerStates.clear();
 
     for (auto const& state : other.mDisplayStates) {
         ssize_t index = mDisplayStates.indexOf(state);
@@ -346,7 +435,6 @@
             mDisplayStates.editItemAt(static_cast<size_t>(index)).merge(state);
         }
     }
-    other.mDisplayStates.clear();
 
     for (const auto& [listener, callbackInfo] : other.mListenerCallbacks) {
         auto& [callbackIds, surfaceControls] = callbackInfo;
@@ -357,28 +445,34 @@
                 .surfaceControls.insert(std::make_move_iterator(surfaceControls.begin()),
                                         std::make_move_iterator(surfaceControls.end()));
     }
-    other.mListenerCallbacks.clear();
 
     mInputWindowCommands.merge(other.mInputWindowCommands);
-    other.mInputWindowCommands.clear();
 
     mContainsBuffer = other.mContainsBuffer;
-    other.mContainsBuffer = false;
-
     mEarlyWakeup = mEarlyWakeup || other.mEarlyWakeup;
-    other.mEarlyWakeup = false;
-
+    other.clear();
     return *this;
 }
 
-void SurfaceComposerClient::doDropReferenceTransaction(const sp<IBinder>& handle,
-        const sp<ISurfaceComposerClient>& client) {
+void SurfaceComposerClient::Transaction::clear() {
+    mComposerStates.clear();
+    mDisplayStates.clear();
+    mListenerCallbacks.clear();
+    mInputWindowCommands.clear();
+    mContainsBuffer = false;
+    mForceSynchronous = 0;
+    mTransactionNestCount = 0;
+    mAnimation = false;
+    mEarlyWakeup = false;
+    mDesiredPresentTime = -1;
+}
+
+void SurfaceComposerClient::doDropReferenceTransaction(const sp<IBinder>& handle) {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     Vector<ComposerState> composerStates;
     Vector<DisplayState> displayStates;
 
     ComposerState s;
-    s.client = client;
     s.state.surface = handle;
     s.state.what |= layer_state_t::eReparent;
     s.state.parentHandleForChild = nullptr;
@@ -405,8 +499,8 @@
     }
 
     size_t count = 0;
-    for (auto& [sc, cs] : mComposerStates) {
-        layer_state_t* s = getLayerState(sc);
+    for (auto& [handle, cs] : mComposerStates) {
+        layer_state_t* s = getLayerState(handle);
         if (!(s->what & layer_state_t::eBufferChanged)) {
             continue;
         }
@@ -545,16 +639,15 @@
     mEarlyWakeup = true;
 }
 
-layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp<SurfaceControl>& sc) {
-    if (mComposerStates.count(sc) == 0) {
+layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp<IBinder>& handle) {
+    if (mComposerStates.count(handle) == 0) {
         // we don't have it, add an initialized layer_state to our list
         ComposerState s;
-        s.client = sc->getClient()->mClient;
-        s.state.surface = sc->getHandle();
-        mComposerStates[sc] = s;
+        s.state.surface = handle;
+        mComposerStates[handle] = s;
     }
 
-    return &(mComposerStates[sc].state);
+    return &(mComposerStates[handle].state);
 }
 
 void SurfaceComposerClient::Transaction::registerSurfaceControlForCallback(
@@ -626,6 +719,7 @@
     layer_state_t* s = getLayerState(sc);
     if (!s) {
         mStatus = BAD_INDEX;
+        return *this;
     }
     s->what |= layer_state_t::eRelativeLayerChanged;
     s->what &= ~layer_state_t::eLayerChanged;
@@ -1055,6 +1149,7 @@
     layer_state_t* s = getLayerState(sc);
     if (!s) {
         mStatus = BAD_INDEX;
+        return *this;
     }
     s->what |= layer_state_t::eDetachChildren;
 
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 55488da..071314f 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -65,16 +65,8 @@
 {
     // Avoid reparenting the server-side surface to null if we are not the owner of it,
     // meaning that we retrieved it from another process.
-    if (mClient != nullptr && mHandle != nullptr && mOwned) {
-        SurfaceComposerClient::doDropReferenceTransaction(mHandle, mClient->getClient());
-    }
-    release();
-}
-
-void SurfaceControl::destroy()
-{
-    if (isValid()) {
-        SurfaceComposerClient::Transaction().reparent(this, nullptr).apply();
+    if (mHandle != nullptr && mOwned) {
+        SurfaceComposerClient::doDropReferenceTransaction(mHandle);
     }
     release();
 }
@@ -186,8 +178,7 @@
     parcel->writeStrongBinder(IGraphicBufferProducer::asBinder(mGraphicBufferProducer));
 }
 
-sp<SurfaceControl> SurfaceControl::readFromParcel(Parcel* parcel)
-{
+sp<SurfaceControl> SurfaceControl::readFromParcel(const Parcel* parcel) {
     sp<IBinder> client = parcel->readStrongBinder();
     sp<IBinder> handle = parcel->readStrongBinder();
     if (client == nullptr || handle == nullptr)
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index 690a85f..205e79c 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -348,6 +348,14 @@
 
     const uint64_t mUniqueId;
 
+    // When buffer size is driven by the consumer and mTransformHint specifies
+    // a 90 or 270 degree rotation, this indicates whether the width and height
+    // used by dequeueBuffer will be additionally swapped.
+    bool mAutoPrerotation;
+
+    // mTransformHintInUse is to cache the mTransformHint used by the producer.
+    uint32_t mTransformHintInUse;
+
 }; // class BufferQueueCore
 
 } // namespace android
diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
index d2a47a6..9ad92a6 100644
--- a/libs/gui/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -190,6 +190,9 @@
     // See IGraphicBufferProducer::getConsumerUsage
     virtual status_t getConsumerUsage(uint64_t* outUsage) const override;
 
+    // See IGraphicBufferProducer::setAutoPrerotation
+    virtual status_t setAutoPrerotation(bool autoPrerotation);
+
 private:
     // This is required by the IBinder::DeathRecipient interface
     virtual void binderDied(const wp<IBinder>& who);
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 3dde8c8..abe1e3f 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -412,6 +412,7 @@
         uint64_t nextFrameNumber{0};
         FrameEventHistoryDelta frameTimestamps;
         bool bufferReplaced{false};
+        int maxBufferCount{0};
     };
 
     virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
@@ -629,6 +630,14 @@
     // NATIVE_WINDOW_CONSUMER_USAGE_BITS attribute.
     virtual status_t getConsumerUsage(uint64_t* outUsage) const = 0;
 
+    // Enable/disable the auto prerotation at buffer allocation when the buffer
+    // size is driven by the consumer.
+    //
+    // When buffer size is driven by the consumer and the transform hint
+    // specifies a 90 or 270 degree rotation, if auto prerotation is enabled,
+    // the width and height used for dequeueBuffer will be additionally swapped.
+    virtual status_t setAutoPrerotation(bool autoPrerotation);
+
     // Static method exports any IGraphicBufferProducer object to a parcel. It
     // handles null producer as well.
     static status_t exportToParcel(const sp<IGraphicBufferProducer>& producer,
diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h
index 774ad46..cbfd365 100644
--- a/libs/gui/include/gui/ITransactionCompletedListener.h
+++ b/libs/gui/include/gui/ITransactionCompletedListener.h
@@ -106,6 +106,16 @@
                       const std::vector<CallbackId>& ids)
           : transactionCompletedListener(listener), callbackIds(ids) {}
 
+    bool operator==(const ListenerCallbacks& rhs) const {
+        if (transactionCompletedListener != rhs.transactionCompletedListener) {
+            return false;
+        }
+        if (callbackIds.empty()) {
+            return rhs.callbackIds.empty();
+        }
+        return callbackIds.front() == rhs.callbackIds.front();
+    }
+
     sp<ITransactionCompletedListener> transactionCompletedListener;
     std::vector<CallbackId> callbackIds;
 };
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index f438eb3..cbd1c85 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -206,7 +206,6 @@
 };
 
 struct ComposerState {
-    sp<ISurfaceComposerClient> client;
     layer_state_t state;
     status_t write(Parcel& output) const;
     status_t read(const Parcel& input);
@@ -274,8 +273,6 @@
 };
 
 static inline int compare_type(const ComposerState& lhs, const ComposerState& rhs) {
-    if (lhs.client < rhs.client) return -1;
-    if (lhs.client > rhs.client) return 1;
     if (lhs.state.surface < rhs.state.surface) return -1;
     if (lhs.state.surface > rhs.state.surface) return 1;
     return 0;
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 5c6a1ee..fe528b3 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -230,6 +230,7 @@
     int dispatchGetWideColorSupport(va_list args);
     int dispatchGetHdrSupport(va_list args);
     int dispatchGetConsumerUsage64(va_list args);
+    int dispatchSetAutoPrerotation(va_list args);
     bool transformToDisplayInverse();
 
 protected:
@@ -265,6 +266,7 @@
     virtual int setAsyncMode(bool async);
     virtual int setSharedBufferMode(bool sharedBufferMode);
     virtual int setAutoRefresh(bool autoRefresh);
+    virtual int setAutoPrerotation(bool autoPrerotation);
     virtual int setBuffersDimensions(uint32_t width, uint32_t height);
     virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
     virtual int unlockAndPost();
@@ -434,6 +436,7 @@
     // Caches the values that have been passed to the producer.
     bool mSharedBufferMode;
     bool mAutoRefresh;
+    bool mAutoPrerotation;
 
     // 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
@@ -466,6 +469,7 @@
 
     bool mReportRemovedBuffers = false;
     std::vector<sp<GraphicBuffer>> mRemovedBuffers;
+    int mMaxBufferCount;
 };
 
 } // namespace android
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 0e17c7b..22ab62d 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -163,8 +163,7 @@
      * Called from SurfaceControl d'tor to 'destroy' the surface (or rather, reparent it
      * to null), but without needing an sp<SurfaceControl> to avoid infinite ressurection.
      */
-    static void doDropReferenceTransaction(const sp<IBinder>& handle,
-            const sp<ISurfaceComposerClient>& client);
+    static void doDropReferenceTransaction(const sp<IBinder>& handle);
 
     /**
      * Uncaches a buffer in ISurfaceComposer. It must be uncached via a transaction so that it is
@@ -270,6 +269,12 @@
         }
     };
 
+    struct IBinderHash {
+        std::size_t operator()(const sp<IBinder>& iBinder) const {
+            return std::hash<IBinder*>{}(iBinder.get());
+        }
+    };
+
     struct TCLHash {
         std::size_t operator()(const sp<ITransactionCompletedListener>& tcl) const {
             return std::hash<IBinder*>{}((tcl) ? IInterface::asBinder(tcl).get() : nullptr);
@@ -285,8 +290,8 @@
         std::unordered_set<sp<SurfaceControl>, SCHash> surfaceControls;
     };
 
-    class Transaction {
-        std::unordered_map<sp<SurfaceControl>, ComposerState, SCHash> mComposerStates;
+    class Transaction : Parcelable {
+        std::unordered_map<sp<IBinder>, ComposerState, IBinderHash> mComposerStates;
         SortedVector<DisplayState > mDisplayStates;
         std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash>
                 mListenerCallbacks;
@@ -314,7 +319,10 @@
         InputWindowCommands mInputWindowCommands;
         int mStatus = NO_ERROR;
 
-        layer_state_t* getLayerState(const sp<SurfaceControl>& sc);
+        layer_state_t* getLayerState(const sp<IBinder>& surfaceHandle);
+        layer_state_t* getLayerState(const sp<SurfaceControl>& sc) {
+            return getLayerState(sc->getHandle());
+        }
         DisplayState& getDisplayState(const sp<IBinder>& token);
 
         void cacheBuffers();
@@ -325,6 +333,15 @@
         virtual ~Transaction() = default;
         Transaction(Transaction const& other);
 
+        // Factory method that creates a new Transaction instance from the parcel.
+        static std::unique_ptr<Transaction> createFromParcel(const Parcel* parcel);
+
+        status_t writeToParcel(Parcel* parcel) const override;
+        status_t readFromParcel(const Parcel* parcel) override;
+
+        // Clears the contents of the transaction without applying it.
+        void clear();
+
         status_t apply(bool synchronous = false);
         // Merge another transaction in to this one, clearing other
         // as if it had been applied.
@@ -551,15 +568,10 @@
 
     CallbackId mCallbackIdCounter GUARDED_BY(mMutex) = 1;
 
-    struct IBinderHash {
-        std::size_t operator()(const sp<IBinder>& iBinder) const {
-            return std::hash<IBinder*>{}(iBinder.get());
-        }
-    };
-
     struct CallbackTranslation {
         TransactionCompletedCallback callbackFunction;
-        std::unordered_map<sp<IBinder>, sp<SurfaceControl>, IBinderHash> surfaceControls;
+        std::unordered_map<sp<IBinder>, sp<SurfaceControl>, SurfaceComposerClient::IBinderHash>
+                surfaceControls;
     };
 
     std::unordered_map<CallbackId, CallbackTranslation> mCallbacks GUARDED_BY(mMutex);
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index 23bfc02..ae4a146 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -44,7 +44,7 @@
 class SurfaceControl : public RefBase
 {
 public:
-    static sp<SurfaceControl> readFromParcel(Parcel* parcel);
+    static sp<SurfaceControl> readFromParcel(const Parcel* parcel);
     void writeToParcel(Parcel* parcel);
 
     static bool isValid(const sp<SurfaceControl>& surface) {
@@ -81,7 +81,7 @@
     status_t getLayerFrameStats(FrameStats* outStats) const;
 
     sp<SurfaceComposerClient> getClient() const;
-    
+
     explicit SurfaceControl(const sp<SurfaceControl>& other);
 
     SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle,
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 119e888..98dc1e6 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -169,6 +169,18 @@
     ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
 }
 
+TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    mConsumer->consumerConnect(dc, false);
+    int bufferCount = 50;
+    mConsumer->setMaxBufferCount(bufferCount);
+
+    IGraphicBufferProducer::QueueBufferOutput output;
+    mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
+    ASSERT_EQ(output.maxBufferCount, bufferCount);
+}
+
 TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
     createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
diff --git a/libs/gui/tests/RegionSampling_test.cpp b/libs/gui/tests/RegionSampling_test.cpp
index d33ecfb..c9de37d 100644
--- a/libs/gui/tests/RegionSampling_test.cpp
+++ b/libs/gui/tests/RegionSampling_test.cpp
@@ -297,4 +297,70 @@
     composer->removeRegionSamplingListener(grayListener);
 }
 
+TEST_F(RegionSamplingTest, DISABLED_TestIfInvalidInputParameters) {
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<Listener> listener = new Listener();
+    const Rect sampleArea{100, 100, 200, 200};
+    // Invalid input sampleArea
+    EXPECT_EQ(BAD_VALUE,
+              composer->addRegionSamplingListener(Rect::INVALID_RECT, mTopLayer->getHandle(),
+                                                  listener));
+    listener->reset();
+    // Invalid input binder
+    EXPECT_EQ(NO_ERROR, composer->addRegionSamplingListener(sampleArea, NULL, listener));
+    // Invalid input listener
+    EXPECT_EQ(BAD_VALUE,
+              composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), NULL));
+    EXPECT_EQ(BAD_VALUE, composer->removeRegionSamplingListener(NULL));
+    // remove the listener
+    composer->removeRegionSamplingListener(listener);
+}
+
+TEST_F(RegionSamplingTest, DISABLED_TestCallbackAfterRemoveListener) {
+    fill_render(rgba_green);
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<Listener> listener = new Listener();
+    const Rect sampleArea{100, 100, 200, 200};
+    composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
+    fill_render(rgba_green);
+
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_green, error_margin);
+
+    listener->reset();
+    composer->removeRegionSamplingListener(listener);
+    fill_render(rgba_green);
+    EXPECT_FALSE(listener->wait_event(100ms))
+            << "callback should stop after remove the region sampling listener";
+}
+
+TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromMovingLayer) {
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<Listener> listener = new Listener();
+    Rect sampleArea{100, 100, 200, 200};
+
+    // Test: listener in (100, 100). See layer before move, no layer after move.
+    fill_render(rgba_blue);
+    composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_blue, error_margin);
+    listener->reset();
+    SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply();
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_gray, error_margin);
+    composer->removeRegionSamplingListener(listener);
+
+    // Test: listener offset to (600, 600). No layer before move, see layer after move.
+    fill_render(rgba_green);
+    sampleArea.offsetTo(600, 600);
+    composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_gray, error_margin);
+    listener->reset();
+    SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply();
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_green, error_margin);
+    composer->removeRegionSamplingListener(listener);
+}
+
 } // namespace android::test
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 65e09f2..c85e844 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -28,8 +28,6 @@
 #include <utils/Log.h>
 #include <utils/Thread.h>
 
-extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
-
 namespace android {
 
 class SurfaceTextureClientTest : public ::testing::Test {
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index d370858..7718bc1 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -1746,4 +1746,74 @@
     EXPECT_EQ(-1, outDisplayPresentTime);
 }
 
+TEST_F(SurfaceTest, DequeueWithConsumerDrivenSize) {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+    consumer->consumerConnect(dummyConsumer, false);
+    consumer->setDefaultBufferSize(10, 10);
+
+    sp<Surface> surface = new Surface(producer);
+    sp<ANativeWindow> window(surface);
+    native_window_api_connect(window.get(), NATIVE_WINDOW_API_CPU);
+    native_window_set_buffers_dimensions(window.get(), 0, 0);
+
+    int fence;
+    ANativeWindowBuffer* buffer;
+
+    // Buffer size is driven by the consumer
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(10, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+
+    // Buffer size is driven by the consumer
+    consumer->setDefaultBufferSize(10, 20);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(20, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+
+    // Transform hint isn't synced to producer before queueBuffer or connect
+    consumer->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_270);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(20, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
+
+    // Transform hint is synced to producer but no auto prerotation
+    consumer->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_270);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(20, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+
+    // Prerotation is driven by the consumer with the transform hint used by producer
+    native_window_set_auto_prerotation(window.get(), true);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(20, buffer->width);
+    EXPECT_EQ(10, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+
+    // Turn off auto prerotaton
+    native_window_set_auto_prerotation(window.get(), false);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(20, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+
+    // Test auto prerotation bit is disabled after disconnect
+    native_window_set_auto_prerotation(window.get(), true);
+    native_window_api_disconnect(window.get(), NATIVE_WINDOW_API_CPU);
+    native_window_api_connect(window.get(), NATIVE_WINDOW_API_CPU);
+    consumer->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_270);
+    native_window_set_buffers_dimensions(window.get(), 0, 0);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    EXPECT_EQ(10, buffer->width);
+    EXPECT_EQ(20, buffer->height);
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fence));
+}
+
 } // namespace android
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 9fd25f9..34b305e 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "Input"
 //#define LOG_NDEBUG 0
 
-#include <math.h>
 #include <limits.h>
 
 #include <input/Input.h>
@@ -235,26 +234,14 @@
 
 // --- MotionEvent ---
 
-void MotionEvent::initialize(
-        int32_t deviceId,
-        int32_t source,
-        int32_t displayId,
-        int32_t action,
-        int32_t actionButton,
-        int32_t flags,
-        int32_t edgeFlags,
-        int32_t metaState,
-        int32_t buttonState,
-        MotionClassification classification,
-        float xOffset,
-        float yOffset,
-        float xPrecision,
-        float yPrecision,
-        nsecs_t downTime,
-        nsecs_t eventTime,
-        size_t pointerCount,
-        const PointerProperties* pointerProperties,
-        const PointerCoords* pointerCoords) {
+void MotionEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId, int32_t action,
+                             int32_t actionButton, int32_t flags, int32_t edgeFlags,
+                             int32_t metaState, int32_t buttonState,
+                             MotionClassification classification, float xOffset, float yOffset,
+                             float xPrecision, float yPrecision, float rawXCursorPosition,
+                             float rawYCursorPosition, nsecs_t downTime, nsecs_t eventTime,
+                             size_t pointerCount, const PointerProperties* pointerProperties,
+                             const PointerCoords* pointerCoords) {
     InputEvent::initialize(deviceId, source, displayId);
     mAction = action;
     mActionButton = actionButton;
@@ -267,6 +254,8 @@
     mYOffset = yOffset;
     mXPrecision = xPrecision;
     mYPrecision = yPrecision;
+    mRawXCursorPosition = rawXCursorPosition;
+    mRawYCursorPosition = rawYCursorPosition;
     mDownTime = downTime;
     mPointerProperties.clear();
     mPointerProperties.appendArray(pointerProperties, pointerCount);
@@ -288,6 +277,8 @@
     mYOffset = other->mYOffset;
     mXPrecision = other->mXPrecision;
     mYPrecision = other->mYPrecision;
+    mRawXCursorPosition = other->mRawXCursorPosition;
+    mRawYCursorPosition = other->mRawYCursorPosition;
     mDownTime = other->mDownTime;
     mPointerProperties = other->mPointerProperties;
 
@@ -312,6 +303,21 @@
     mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
 }
 
+float MotionEvent::getXCursorPosition() const {
+    const float rawX = getRawXCursorPosition();
+    return rawX + mXOffset;
+}
+
+float MotionEvent::getYCursorPosition() const {
+    const float rawY = getRawYCursorPosition();
+    return rawY + mYOffset;
+}
+
+void MotionEvent::setCursorPosition(float x, float y) {
+    mRawXCursorPosition = x - mXOffset;
+    mRawYCursorPosition = y - mYOffset;
+}
+
 const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
     return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
 }
@@ -431,6 +437,15 @@
     float originX, originY;
     transformPoint(matrix, 0, 0, &originX, &originY);
 
+    // Apply the transformation to cursor position.
+    if (isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition)) {
+        float x = mRawXCursorPosition + oldXOffset;
+        float y = mRawYCursorPosition + oldYOffset;
+        transformPoint(matrix, x, y, &x, &y);
+        mRawXCursorPosition = x - mXOffset;
+        mRawYCursorPosition = y - mYOffset;
+    }
+
     // Apply the transformation to all samples.
     size_t numSamples = mSamplePointerCoords.size();
     for (size_t i = 0; i < numSamples; i++) {
@@ -470,6 +485,8 @@
     mYOffset = parcel->readFloat();
     mXPrecision = parcel->readFloat();
     mYPrecision = parcel->readFloat();
+    mRawXCursorPosition = parcel->readFloat();
+    mRawYCursorPosition = parcel->readFloat();
     mDownTime = parcel->readInt64();
 
     mPointerProperties.clear();
@@ -521,6 +538,8 @@
     parcel->writeFloat(mYOffset);
     parcel->writeFloat(mXPrecision);
     parcel->writeFloat(mYPrecision);
+    parcel->writeFloat(mRawXCursorPosition);
+    parcel->writeFloat(mRawYCursorPosition);
     parcel->writeInt64(mDownTime);
 
     for (size_t i = 0; i < pointerCount; i++) {
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index d02cb8e..904a6fe 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -191,6 +191,10 @@
             msg->body.motion.xPrecision = body.motion.xPrecision;
             // float yPrecision
             msg->body.motion.yPrecision = body.motion.yPrecision;
+            // float xCursorPosition
+            msg->body.motion.xCursorPosition = body.motion.xCursorPosition;
+            // float yCursorPosition
+            msg->body.motion.yCursorPosition = body.motion.yCursorPosition;
             // uint32_t pointerCount
             msg->body.motion.pointerCount = body.motion.pointerCount;
             //struct Pointer pointers[MAX_POINTERS]
@@ -465,26 +469,12 @@
 }
 
 status_t InputPublisher::publishMotionEvent(
-        uint32_t seq,
-        int32_t deviceId,
-        int32_t source,
-        int32_t displayId,
-        int32_t action,
-        int32_t actionButton,
-        int32_t flags,
-        int32_t edgeFlags,
-        int32_t metaState,
-        int32_t buttonState,
-        MotionClassification classification,
-        float xOffset,
-        float yOffset,
-        float xPrecision,
-        float yPrecision,
-        nsecs_t downTime,
-        nsecs_t eventTime,
-        uint32_t pointerCount,
-        const PointerProperties* pointerProperties,
-        const PointerCoords* pointerCoords) {
+        uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId, int32_t action,
+        int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState,
+        int32_t buttonState, MotionClassification classification, float xOffset, float yOffset,
+        float xPrecision, float yPrecision, float xCursorPosition, float yCursorPosition,
+        nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount,
+        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) {
     if (ATRACE_ENABLED()) {
         std::string message = StringPrintf(
                 "publishMotionEvent(inputChannel=%s, action=%" PRId32 ")",
@@ -532,6 +522,8 @@
     msg.body.motion.yOffset = yOffset;
     msg.body.motion.xPrecision = xPrecision;
     msg.body.motion.yPrecision = yPrecision;
+    msg.body.motion.xCursorPosition = xCursorPosition;
+    msg.body.motion.yCursorPosition = yCursorPosition;
     msg.body.motion.downTime = downTime;
     msg.body.motion.eventTime = eventTime;
     msg.body.motion.pointerCount = pointerCount;
@@ -1135,26 +1127,16 @@
         pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords);
     }
 
-    event->initialize(
-            msg->body.motion.deviceId,
-            msg->body.motion.source,
-            msg->body.motion.displayId,
-            msg->body.motion.action,
-            msg->body.motion.actionButton,
-            msg->body.motion.flags,
-            msg->body.motion.edgeFlags,
-            msg->body.motion.metaState,
-            msg->body.motion.buttonState,
-            msg->body.motion.classification,
-            msg->body.motion.xOffset,
-            msg->body.motion.yOffset,
-            msg->body.motion.xPrecision,
-            msg->body.motion.yPrecision,
-            msg->body.motion.downTime,
-            msg->body.motion.eventTime,
-            pointerCount,
-            pointerProperties,
-            pointerCoords);
+    event->initialize(msg->body.motion.deviceId, msg->body.motion.source,
+                      msg->body.motion.displayId, msg->body.motion.action,
+                      msg->body.motion.actionButton, msg->body.motion.flags,
+                      msg->body.motion.edgeFlags, msg->body.motion.metaState,
+                      msg->body.motion.buttonState, msg->body.motion.classification,
+                      msg->body.motion.xOffset, msg->body.motion.yOffset,
+                      msg->body.motion.xPrecision, msg->body.motion.yPrecision,
+                      msg->body.motion.xCursorPosition, msg->body.motion.yCursorPosition,
+                      msg->body.motion.downTime, msg->body.motion.eventTime, pointerCount,
+                      pointerProperties, pointerCoords);
 }
 
 void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) {
diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp
index 0c22bfe..56900c1 100644
--- a/libs/input/Keyboard.cpp
+++ b/libs/input/Keyboard.cpp
@@ -38,29 +38,29 @@
 KeyMap::~KeyMap() {
 }
 
-status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier,
+status_t KeyMap::load(const InputDeviceIdentifier& deviceIdentifier,
         const PropertyMap* deviceConfiguration) {
     // Use the configured key layout if available.
     if (deviceConfiguration) {
         String8 keyLayoutName;
         if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
                 keyLayoutName)) {
-            status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName.c_str());
+            status_t status = loadKeyLayout(deviceIdentifier, keyLayoutName.c_str());
             if (status == NAME_NOT_FOUND) {
                 ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
                         "it was not found.",
-                        deviceIdenfifier.name.c_str(), keyLayoutName.string());
+                        deviceIdentifier.name.c_str(), keyLayoutName.string());
             }
         }
 
         String8 keyCharacterMapName;
         if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),
                 keyCharacterMapName)) {
-            status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName.c_str());
+            status_t status = loadKeyCharacterMap(deviceIdentifier, keyCharacterMapName.c_str());
             if (status == NAME_NOT_FOUND) {
                 ALOGE("Configuration for keyboard device '%s' requested keyboard character "
                         "map '%s' but it was not found.",
-                        deviceIdenfifier.name.c_str(), keyLayoutName.string());
+                        deviceIdentifier.name.c_str(), keyCharacterMapName.string());
             }
         }
 
@@ -70,25 +70,25 @@
     }
 
     // Try searching by device identifier.
-    if (probeKeyMap(deviceIdenfifier, "")) {
+    if (probeKeyMap(deviceIdentifier, "")) {
         return OK;
     }
 
     // Fall back on the Generic key map.
     // TODO Apply some additional heuristics here to figure out what kind of
     //      generic key map to use (US English, etc.) for typical external keyboards.
-    if (probeKeyMap(deviceIdenfifier, "Generic")) {
+    if (probeKeyMap(deviceIdentifier, "Generic")) {
         return OK;
     }
 
     // Try the Virtual key map as a last resort.
-    if (probeKeyMap(deviceIdenfifier, "Virtual")) {
+    if (probeKeyMap(deviceIdentifier, "Virtual")) {
         return OK;
     }
 
     // Give up!
     ALOGE("Could not determine key map for device '%s' and no default key maps were found!",
-            deviceIdenfifier.name.c_str());
+            deviceIdentifier.name.c_str());
     return NAME_NOT_FOUND;
 }
 
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 2b75c82..b90857c 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -255,11 +255,11 @@
     pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27);
     pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
     event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0,
-            AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
-            AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
-            MotionClassification::NONE, X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
-            ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME,
-            2, pointerProperties, pointerCoords);
+                      AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, AMOTION_EVENT_EDGE_FLAG_TOP,
+                      AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY, MotionClassification::NONE,
+                      X_OFFSET, Y_OFFSET, 2.0f, 2.1f, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                      AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_DOWN_TIME,
+                      ARBITRARY_EVENT_TIME, 2, pointerProperties, pointerCoords);
 
     pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110);
     pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111);
@@ -571,10 +571,11 @@
     }
     MotionEvent event;
     event.initialize(0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE,
-            0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE,
-            AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
-            0 /*xOffset*/, 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
-            0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
+                     0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
+                     0 /*buttonState*/, MotionClassification::NONE, 0 /*xOffset*/, 0 /*yOffset*/,
+                     0 /*xPrecision*/, 0 /*yPrecision*/, 3 + RADIUS /*xCursorPosition*/,
+                     2 /*yCursorPosition*/, 0 /*downTime*/, 0 /*eventTime*/, pointerCount,
+                     pointerProperties, pointerCoords);
     float originalRawX = 0 + 3;
     float originalRawY = -RADIUS + 2;
 
@@ -602,6 +603,14 @@
         ASSERT_NEAR(tanf(angle), tanf(event.getOrientation(i)), 0.1);
     }
 
+    // Check cursor positions. The original cursor position is at (3 + RADIUS, 2), where the center
+    // of the circle is (3, 2), so the cursor position is to the right of the center of the circle.
+    // The choice of triangular functions in this test defines the angle of rotation clockwise
+    // relative to the y-axis. Therefore the cursor position's angle is 90 degrees. Here we swap the
+    // triangular function so that we don't have to add the 90 degrees.
+    ASSERT_NEAR(cosf(PI_180 * ROTATION) * RADIUS, event.getXCursorPosition(), 0.001);
+    ASSERT_NEAR(sinf(PI_180 * ROTATION) * RADIUS, event.getYCursorPosition(), 0.001);
+
     // Applying the transformation should preserve the raw X and Y of the first point.
     ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001);
     ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
@@ -626,11 +635,44 @@
 
     for (MotionClassification classification : classifications) {
         event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
-                AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0,
-                classification, 0, 0, 0, 0, 0 /*downTime*/, 0 /*eventTime*/,
-                pointerCount, pointerProperties, pointerCoords);
+                         AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
+                         0, classification, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                         AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/, 0 /*eventTime*/,
+                         pointerCount, pointerProperties, pointerCoords);
         ASSERT_EQ(classification, event.getClassification());
     }
 }
 
+TEST_F(MotionEventTest, Initialize_SetsCursorPosition) {
+    MotionEvent event;
+    constexpr size_t pointerCount = 1;
+    PointerProperties pointerProperties[pointerCount];
+    PointerCoords pointerCoords[pointerCount];
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerProperties[i].id = i;
+        pointerCoords[i].clear();
+    }
+
+    event.initialize(0 /*deviceId*/, AINPUT_SOURCE_MOUSE, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0,
+                     0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE, 0,
+                     0, 0, 0, 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 0 /*downTime*/,
+                     0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
+    event.offsetLocation(20, 60);
+    ASSERT_EQ(280, event.getRawXCursorPosition());
+    ASSERT_EQ(540, event.getRawYCursorPosition());
+    ASSERT_EQ(300, event.getXCursorPosition());
+    ASSERT_EQ(600, event.getYCursorPosition());
+}
+
+TEST_F(MotionEventTest, SetCursorPosition) {
+    MotionEvent event;
+    initializeEventWithHistory(&event);
+    event.setSource(AINPUT_SOURCE_MOUSE);
+
+    event.setCursorPosition(3, 4);
+    ASSERT_EQ(3, event.getXCursorPosition());
+    ASSERT_EQ(4, event.getYCursorPosition());
+}
+
 } // namespace android
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index f2cd1be..a362f32 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -146,6 +146,8 @@
     constexpr float yOffset = -20;
     constexpr float xPrecision = 0.25;
     constexpr float yPrecision = 0.5;
+    constexpr float xCursorPosition = 1.3;
+    constexpr float yCursorPosition = 50.6;
     constexpr nsecs_t downTime = 3;
     constexpr size_t pointerCount = 3;
     constexpr nsecs_t eventTime = 4;
@@ -168,10 +170,12 @@
         pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i);
     }
 
-    status = mPublisher->publishMotionEvent(seq, deviceId, source, displayId, action, actionButton,
-            flags, edgeFlags, metaState, buttonState, classification,
-            xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount,
-            pointerProperties, pointerCoords);
+    status =
+            mPublisher->publishMotionEvent(seq, deviceId, source, displayId, action, actionButton,
+                                           flags, edgeFlags, metaState, buttonState, classification,
+                                           xOffset, yOffset, xPrecision, yPrecision,
+                                           xCursorPosition, yCursorPosition, downTime, eventTime,
+                                           pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(OK, status)
             << "publisher publishMotionEvent should return OK";
 
@@ -199,6 +203,10 @@
     EXPECT_EQ(classification, motionEvent->getClassification());
     EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
     EXPECT_EQ(yPrecision, motionEvent->getYPrecision());
+    EXPECT_EQ(xCursorPosition, motionEvent->getRawXCursorPosition());
+    EXPECT_EQ(yCursorPosition, motionEvent->getRawYCursorPosition());
+    EXPECT_EQ(xCursorPosition + xOffset, motionEvent->getXCursorPosition());
+    EXPECT_EQ(yCursorPosition + yOffset, motionEvent->getYCursorPosition());
     EXPECT_EQ(downTime, motionEvent->getDownTime());
     EXPECT_EQ(eventTime, motionEvent->getEventTime());
     EXPECT_EQ(pointerCount, motionEvent->getPointerCount());
@@ -266,9 +274,11 @@
         pointerCoords[i].clear();
     }
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
-            pointerCount, pointerProperties, pointerCoords);
+    status =
+            mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE,
+                                           0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                           AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
+                                           pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
 }
@@ -279,9 +289,11 @@
     PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
-            pointerCount, pointerProperties, pointerCoords);
+    status =
+            mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE,
+                                           0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                           AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
+                                           pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
 }
@@ -297,9 +309,11 @@
         pointerCoords[i].clear();
     }
 
-    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
-            pointerCount, pointerProperties, pointerCoords);
+    status =
+            mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE,
+                                           0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                           AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
+                                           pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
 }
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 62023fb..8d8cf06 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -64,8 +64,10 @@
   CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 68);
   CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 72);
   CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 76);
-  CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 80);
-  CHECK_OFFSET(InputMessage::Body::Motion, pointers, 88);
+  CHECK_OFFSET(InputMessage::Body::Motion, xCursorPosition, 80);
+  CHECK_OFFSET(InputMessage::Body::Motion, yCursorPosition, 84);
+  CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 88);
+  CHECK_OFFSET(InputMessage::Body::Motion, pointers, 96);
 
   CHECK_OFFSET(InputMessage::Body::Finished, seq, 0);
   CHECK_OFFSET(InputMessage::Body::Finished, handled, 4);
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 368446f..968e2fa 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -176,12 +176,13 @@
         EXPECT_EQ(pointerIndex, pointerCount);
 
         MotionEvent event;
-        event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
-                action, 0 /*actionButton*/, 0 /*flags*/,
-                AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
-                MotionClassification::NONE,
-                0 /*xOffset*/, 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
-                0 /*downTime*/, entry.eventTime.count(), pointerCount, properties, coords);
+        event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, action,
+                         0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
+                         0 /*buttonState*/, MotionClassification::NONE, 0 /*xOffset*/,
+                         0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
+                         AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                         AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/,
+                         entry.eventTime.count(), pointerCount, properties, coords);
 
         events.emplace_back(event);
     }
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 8435dac..1751443 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -262,3 +262,7 @@
 int ANativeWindow_setAutoRefresh(ANativeWindow* window, bool autoRefresh) {
     return native_window_set_auto_refresh(window, autoRefresh);
 }
+
+int ANativeWindow_setAutoPrerotation(ANativeWindow* window, bool autoPrerotation) {
+    return native_window_set_auto_prerotation(window, autoPrerotation);
+}
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 61590e0..8cbf0a4 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -203,41 +203,42 @@
  */
 enum {
     // clang-format off
-    NATIVE_WINDOW_SET_USAGE                     =  0,   /* deprecated */
-    NATIVE_WINDOW_CONNECT                       =  1,   /* deprecated */
-    NATIVE_WINDOW_DISCONNECT                    =  2,   /* deprecated */
-    NATIVE_WINDOW_SET_CROP                      =  3,   /* private */
-    NATIVE_WINDOW_SET_BUFFER_COUNT              =  4,
-    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY          =  5,   /* deprecated */
-    NATIVE_WINDOW_SET_BUFFERS_TRANSFORM         =  6,
-    NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP         =  7,
-    NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS        =  8,
-    NATIVE_WINDOW_SET_BUFFERS_FORMAT            =  9,
-    NATIVE_WINDOW_SET_SCALING_MODE              = 10,   /* private */
-    NATIVE_WINDOW_LOCK                          = 11,   /* private */
-    NATIVE_WINDOW_UNLOCK_AND_POST               = 12,   /* private */
-    NATIVE_WINDOW_API_CONNECT                   = 13,   /* private */
-    NATIVE_WINDOW_API_DISCONNECT                = 14,   /* private */
-    NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS   = 15,   /* private */
-    NATIVE_WINDOW_SET_POST_TRANSFORM_CROP       = 16,   /* deprecated, unimplemented */
-    NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM  = 17,   /* private */
-    NATIVE_WINDOW_SET_SIDEBAND_STREAM           = 18,
-    NATIVE_WINDOW_SET_BUFFERS_DATASPACE         = 19,
-    NATIVE_WINDOW_SET_SURFACE_DAMAGE            = 20,   /* private */
-    NATIVE_WINDOW_SET_SHARED_BUFFER_MODE        = 21,
-    NATIVE_WINDOW_SET_AUTO_REFRESH              = 22,
-    NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION    = 23,
-    NATIVE_WINDOW_GET_NEXT_FRAME_ID             = 24,
-    NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS       = 25,
-    NATIVE_WINDOW_GET_COMPOSITOR_TIMING         = 26,
-    NATIVE_WINDOW_GET_FRAME_TIMESTAMPS          = 27,
-    NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT        = 28,
-    NATIVE_WINDOW_GET_HDR_SUPPORT               = 29,
-    NATIVE_WINDOW_SET_USAGE64                   = 30,
-    NATIVE_WINDOW_GET_CONSUMER_USAGE64          = 31,
-    NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA = 32,
-    NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA = 33,
+    NATIVE_WINDOW_SET_USAGE                       =  0,   /* deprecated */
+    NATIVE_WINDOW_CONNECT                         =  1,   /* deprecated */
+    NATIVE_WINDOW_DISCONNECT                      =  2,   /* deprecated */
+    NATIVE_WINDOW_SET_CROP                        =  3,   /* private */
+    NATIVE_WINDOW_SET_BUFFER_COUNT                =  4,
+    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY            =  5,   /* deprecated */
+    NATIVE_WINDOW_SET_BUFFERS_TRANSFORM           =  6,
+    NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP           =  7,
+    NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS          =  8,
+    NATIVE_WINDOW_SET_BUFFERS_FORMAT              =  9,
+    NATIVE_WINDOW_SET_SCALING_MODE                = 10,   /* private */
+    NATIVE_WINDOW_LOCK                            = 11,   /* private */
+    NATIVE_WINDOW_UNLOCK_AND_POST                 = 12,   /* private */
+    NATIVE_WINDOW_API_CONNECT                     = 13,   /* private */
+    NATIVE_WINDOW_API_DISCONNECT                  = 14,   /* private */
+    NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS     = 15,   /* private */
+    NATIVE_WINDOW_SET_POST_TRANSFORM_CROP         = 16,   /* deprecated, unimplemented */
+    NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM    = 17,   /* private */
+    NATIVE_WINDOW_SET_SIDEBAND_STREAM             = 18,
+    NATIVE_WINDOW_SET_BUFFERS_DATASPACE           = 19,
+    NATIVE_WINDOW_SET_SURFACE_DAMAGE              = 20,   /* private */
+    NATIVE_WINDOW_SET_SHARED_BUFFER_MODE          = 21,
+    NATIVE_WINDOW_SET_AUTO_REFRESH                = 22,
+    NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION      = 23,
+    NATIVE_WINDOW_GET_NEXT_FRAME_ID               = 24,
+    NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS         = 25,
+    NATIVE_WINDOW_GET_COMPOSITOR_TIMING           = 26,
+    NATIVE_WINDOW_GET_FRAME_TIMESTAMPS            = 27,
+    NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT          = 28,
+    NATIVE_WINDOW_GET_HDR_SUPPORT                 = 29,
+    NATIVE_WINDOW_SET_USAGE64                     = 30,
+    NATIVE_WINDOW_GET_CONSUMER_USAGE64            = 31,
+    NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA  = 32,
+    NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA   = 33,
     NATIVE_WINDOW_SET_BUFFERS_HDR10_PLUS_METADATA = 34,
+    NATIVE_WINDOW_SET_AUTO_PREROTATION            = 35,
     // clang-format on
 };
 
@@ -985,4 +986,18 @@
     return window->perform(window, NATIVE_WINDOW_GET_CONSUMER_USAGE64, outUsage);
 }
 
+/*
+ * native_window_set_auto_prerotation(..., autoPrerotation)
+ * Enable/disable the auto prerotation at buffer allocation when the buffer size
+ * is driven by the consumer.
+ *
+ * When buffer size is driven by the consumer and the transform hint specifies
+ * a 90 or 270 degree rotation, if auto prerotation is enabled, the width and
+ * height used for dequeueBuffer will be additionally swapped.
+ */
+static inline int native_window_set_auto_prerotation(struct ANativeWindow* window,
+                                                     bool autoPrerotation) {
+    return window->perform(window, NATIVE_WINDOW_SET_AUTO_PREROTATION, autoPrerotation);
+}
+
 __END_DECLS
diff --git a/libs/nativewindow/include/vndk/window.h b/libs/nativewindow/include/vndk/window.h
index 995ba44..500052c 100644
--- a/libs/nativewindow/include/vndk/window.h
+++ b/libs/nativewindow/include/vndk/window.h
@@ -316,6 +316,15 @@
  */
 int ANativeWindow_setAutoRefresh(ANativeWindow* window, bool autoRefresh);
 
+/*
+ * Enable/disable the auto prerotation at buffer allocation when the buffer size
+ * is driven by the consumer.
+ *
+ * When buffer size is driven by the consumer and the transform hint specifies
+ * a 90 or 270 degree rotation, if auto prerotation is enabled, the width and
+ * height used for dequeueBuffer will be additionally swapped.
+ */
+int ANativeWindow_setAutoPrerotation(ANativeWindow* window, bool autoPrerotation);
 
 /*****************************************************************************/
 
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index bad8b11..119a07d 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -28,6 +28,7 @@
     ANativeWindow_queryf; # vndk
     ANativeWindow_queueBuffer; # vndk
     ANativeWindow_release;
+    ANativeWindow_setAutoPrerotation; # vndk
     ANativeWindow_setAutoRefresh; # vndk
     ANativeWindow_setBufferCount; # vndk
     ANativeWindow_setBuffersDataSpace; # introduced=28
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 7caaef3..8bfd3dd 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -458,10 +458,6 @@
                                            mFeatureFlags & USE_COLOR_MANAGEMENT);
 }
 
-bool GLESRenderEngine::isCurrent() const {
-    return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
-}
-
 base::unique_fd GLESRenderEngine::flush() {
     ATRACE_CALL();
     if (!GLExtensions::getInstance().hasNativeFenceSync()) {
@@ -801,7 +797,6 @@
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0);
 
     uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-
     ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
              glStatus);
 
@@ -1022,33 +1017,6 @@
     return NO_ERROR;
 }
 
-void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
-                                                ui::Transform::orientation_flags rotation) {
-    setViewportAndProjection(Rect(vpw, vph), sourceCrop);
-
-    if (rotation == ui::Transform::ROT_0) {
-        return;
-    }
-
-    // Apply custom rotation to the projection.
-    float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
-    mat4 m = mState.projectionMatrix;
-    switch (rotation) {
-        case ui::Transform::ROT_90:
-            m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m;
-            break;
-        case ui::Transform::ROT_180:
-            m = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1)) * m;
-            break;
-        case ui::Transform::ROT_270:
-            m = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1)) * m;
-            break;
-        default:
-            break;
-    }
-    mState.projectionMatrix = m;
-}
-
 void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) {
     ATRACE_CALL();
     mVpWidth = viewport.getWidth();
@@ -1112,14 +1080,6 @@
     mState.textureEnabled = true;
 }
 
-void GLESRenderEngine::setupLayerBlackedOut() {
-    glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
-    Texture texture(Texture::TEXTURE_2D, mProtectedTexName);
-    texture.setDimensions(1, 1); // FIXME: we should get that from somewhere
-    mState.texture = texture;
-    mState.textureEnabled = true;
-}
-
 void GLESRenderEngine::setColorTransform(const mat4& colorTransform) {
     mState.colorMatrix = colorTransform;
 }
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index a011620..c8b45d2 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -50,7 +50,6 @@
 public:
     static std::unique_ptr<GLESRenderEngine> create(int hwcFormat, uint32_t featureFlags,
                                                     uint32_t imageCacheSize);
-    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
 
     GLESRenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
                      EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy,
@@ -58,17 +57,7 @@
                      uint32_t imageCacheSize);
     ~GLESRenderEngine() override EXCLUDES(mRenderingMutex);
 
-    std::unique_ptr<Framebuffer> createFramebuffer() override;
-    std::unique_ptr<Image> createImage() override;
-
     void primeCache() const override;
-    bool isCurrent() const override;
-    base::unique_fd flush() override;
-    bool finish() override;
-    bool waitFence(base::unique_fd fenceFd) override;
-    void clearWithColor(float red, float green, float blue, float alpha) override;
-    void fillRegionWithColor(const Region& region, float red, float green, float blue,
-                             float alpha) override;
     void genTextures(size_t count, uint32_t* names) override;
     void deleteTextures(size_t count, uint32_t const* names) override;
     void bindExternalTextureImage(uint32_t texName, const Image& image) override;
@@ -78,7 +67,6 @@
     void unbindExternalTextureBuffer(uint64_t bufferId) EXCLUDES(mRenderingMutex);
     status_t bindFrameBuffer(Framebuffer* framebuffer) override;
     void unbindFrameBuffer(Framebuffer* framebuffer) override;
-    void checkErrors() const override;
 
     bool isProtected() const override { return mInProtectedContext; }
     bool supportsProtectedContent() const override;
@@ -87,9 +75,7 @@
                         ANativeWindowBuffer* buffer, const bool useFramebufferCache,
                         base::unique_fd&& bufferFence, base::unique_fd* drawFence) override;
 
-    // internal to RenderEngine
     EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
-    EGLConfig getEGLConfig() const { return mEGLConfig; }
     // Creates an output image for rendering to
     EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected,
                                                bool useFramebufferCache)
@@ -106,27 +92,6 @@
     Framebuffer* getFramebufferForDrawing() override;
     void dump(std::string& result) override EXCLUDES(mRenderingMutex)
             EXCLUDES(mFramebufferImageCacheMutex);
-    void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
-                                  ui::Transform::orientation_flags rotation) override;
-    void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
-                            const half4& color, float cornerRadius) override;
-    void setupLayerTexturing(const Texture& texture) override;
-    void setupLayerBlackedOut() override;
-    void setupFillWithColor(float r, float g, float b, float a) override;
-    void setColorTransform(const mat4& colorTransform) override;
-    void disableTexturing() override;
-    void disableBlending() override;
-    void setupCornerRadiusCropSize(float width, float height) override;
-
-    // HDR and color management related functions and state
-    void setSourceY410BT2020(bool enable) override;
-    void setSourceDataSpace(ui::Dataspace source) override;
-    void setOutputDataSpace(ui::Dataspace dataspace) override;
-    void setDisplayMaxLuminance(const float maxLuminance) override;
-
-    // drawing
-    void drawMesh(const Mesh& mesh) override;
-
     size_t getMaxTextureSize() const override;
     size_t getMaxViewportDims() const override;
 
@@ -138,12 +103,16 @@
         GLES_VERSION_3_0 = 0x30000,
     };
 
+    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
     static GlesVersion parseGlesVersion(const char* str);
     static EGLContext createEglContext(EGLDisplay display, EGLConfig config,
                                        EGLContext shareContext, bool useContextPriority,
                                        Protection protection);
     static EGLSurface createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
                                                    int hwcFormat, Protection protection);
+    std::unique_ptr<Framebuffer> createFramebuffer();
+    std::unique_ptr<Image> createImage();
+    void checkErrors() const;
     void setScissor(const Rect& region);
     void disableScissor();
     bool waitSync(EGLSyncKHR sync, EGLint flags);
@@ -167,6 +136,28 @@
     // blending is an expensive operation, we want to turn off blending when it's not necessary.
     void handleRoundedCorners(const DisplaySettings& display, const LayerSettings& layer,
                               const Mesh& mesh);
+    base::unique_fd flush();
+    bool finish();
+    bool waitFence(base::unique_fd fenceFd);
+    void clearWithColor(float red, float green, float blue, float alpha);
+    void fillRegionWithColor(const Region& region, float red, float green, float blue, float alpha);
+    void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
+                            const half4& color, float cornerRadius);
+    void setupLayerTexturing(const Texture& texture);
+    void setupFillWithColor(float r, float g, float b, float a);
+    void setColorTransform(const mat4& colorTransform);
+    void disableTexturing();
+    void disableBlending();
+    void setupCornerRadiusCropSize(float width, float height);
+
+    // HDR and color management related functions and state
+    void setSourceY410BT2020(bool enable);
+    void setSourceDataSpace(ui::Dataspace source);
+    void setOutputDataSpace(ui::Dataspace dataspace);
+    void setDisplayMaxLuminance(const float maxLuminance);
+
+    // drawing
+    void drawMesh(const Mesh& mesh);
 
     EGLDisplay mEGLDisplay;
     EGLConfig mEGLConfig;
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index f92ccfb..1c480a7 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -77,10 +77,6 @@
     // This interface, while still in use until a suitable replacement is built,
     // should be considered deprecated, minus some methods which still may be
     // used to support legacy behavior.
-
-    virtual std::unique_ptr<Framebuffer> createFramebuffer() = 0;
-    virtual std::unique_ptr<Image> createImage() = 0;
-
     virtual void primeCache() const = 0;
 
     // dump the extension strings. always call the base class.
@@ -88,24 +84,6 @@
 
     virtual bool useNativeFenceSync() const = 0;
     virtual bool useWaitSync() const = 0;
-
-    virtual bool isCurrent() const = 0;
-
-    // helpers
-    // flush submits RenderEngine command stream for execution and returns a
-    // native fence fd that is signaled when the execution has completed.  It
-    // returns -1 on errors.
-    virtual base::unique_fd flush() = 0;
-    // finish waits until RenderEngine command stream has been executed.  It
-    // returns false on errors.
-    virtual bool finish() = 0;
-    // waitFence inserts a wait on an external fence fd to RenderEngine
-    // command stream.  It returns false on errors.
-    virtual bool waitFence(base::unique_fd fenceFd) = 0;
-
-    virtual void clearWithColor(float red, float green, float blue, float alpha) = 0;
-    virtual void fillRegionWithColor(const Region& region, float red, float green, float blue,
-                                     float alpha) = 0;
     virtual void genTextures(size_t count, uint32_t* names) = 0;
     virtual void deleteTextures(size_t count, uint32_t const* names) = 0;
     virtual void bindExternalTextureImage(uint32_t texName, const Image& image) = 0;
@@ -126,40 +104,6 @@
     virtual status_t bindFrameBuffer(Framebuffer* framebuffer) = 0;
     virtual void unbindFrameBuffer(Framebuffer* framebuffer) = 0;
 
-    // set-up
-    virtual void checkErrors() const = 0;
-    virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
-                                          ui::Transform::orientation_flags rotation) = 0;
-    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
-                                    const half4& color, float cornerRadius) = 0;
-    virtual void setupLayerTexturing(const Texture& texture) = 0;
-    virtual void setupLayerBlackedOut() = 0;
-    virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
-    // Sets up the crop size for corner radius clipping.
-    //
-    // Having corner radius will force GPU composition on the layer and its children, drawing it
-    // with a special shader. The shader will receive the radius and the crop rectangle as input,
-    // modifying the opacity of the destination texture, multiplying it by a number between 0 and 1.
-    // We query Layer#getRoundedCornerState() to retrieve the radius as well as the rounded crop
-    // rectangle to figure out how to apply the radius for this layer. The crop rectangle will be
-    // in local layer coordinate space, so we have to take the layer transform into account when
-    // walking up the tree.
-    virtual void setupCornerRadiusCropSize(float width, float height) = 0;
-
-    // Set a color transform matrix that is applied in linear space right before OETF.
-    virtual void setColorTransform(const mat4& /* colorTransform */) = 0;
-    virtual void disableTexturing() = 0;
-    virtual void disableBlending() = 0;
-
-    // HDR and color management support
-    virtual void setSourceY410BT2020(bool enable) = 0;
-    virtual void setSourceDataSpace(ui::Dataspace source) = 0;
-    virtual void setOutputDataSpace(ui::Dataspace dataspace) = 0;
-    virtual void setDisplayMaxLuminance(const float maxLuminance) = 0;
-
-    // drawing
-    virtual void drawMesh(const Mesh& mesh) = 0;
-
     // queries
     virtual size_t getMaxTextureSize() const = 0;
     virtual size_t getMaxViewportDims() const = 0;
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index e33bcfd..f099cd2 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -34,20 +34,12 @@
     RenderEngine();
     ~RenderEngine() override;
 
-    MOCK_METHOD0(createFramebuffer, std::unique_ptr<renderengine::Framebuffer>());
-    MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
     MOCK_METHOD0(getFramebufferForDrawing, Framebuffer*());
     MOCK_CONST_METHOD0(primeCache, void());
     MOCK_METHOD1(dump, void(std::string&));
     MOCK_CONST_METHOD0(useNativeFenceSync, bool());
     MOCK_CONST_METHOD0(useWaitSync, bool());
     MOCK_CONST_METHOD0(isCurrent, bool());
-    MOCK_METHOD0(flush, base::unique_fd());
-    MOCK_METHOD0(finish, bool());
-    MOCK_METHOD1(waitFence, bool(base::unique_fd*));
-    bool waitFence(base::unique_fd fd) override { return waitFence(&fd); };
-    MOCK_METHOD4(clearWithColor, void(float, float, float, float));
-    MOCK_METHOD5(fillRegionWithColor, void(const Region&, float, float, float, float));
     MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
     MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*));
     MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const renderengine::Image&));
@@ -55,22 +47,6 @@
     MOCK_METHOD3(bindExternalTextureBuffer,
                  status_t(uint32_t, const sp<GraphicBuffer>&, const sp<Fence>&));
     MOCK_METHOD1(unbindExternalTextureBuffer, void(uint64_t));
-    MOCK_CONST_METHOD0(checkErrors, void());
-    MOCK_METHOD4(setViewportAndProjection,
-                 void(size_t, size_t, Rect, ui::Transform::orientation_flags));
-    MOCK_METHOD5(setupLayerBlending, void(bool, bool, bool, const half4&, float));
-    MOCK_METHOD1(setupLayerTexturing, void(const Texture&));
-    MOCK_METHOD0(setupLayerBlackedOut, void());
-    MOCK_METHOD4(setupFillWithColor, void(float, float, float, float));
-    MOCK_METHOD2(setupCornerRadiusCropSize, void(float, float));
-    MOCK_METHOD1(setColorTransform, void(const mat4&));
-    MOCK_METHOD1(setSaturationMatrix, void(const mat4&));
-    MOCK_METHOD0(disableTexturing, void());
-    MOCK_METHOD0(disableBlending, void());
-    MOCK_METHOD1(setSourceY410BT2020, void(bool));
-    MOCK_METHOD1(setSourceDataSpace, void(ui::Dataspace));
-    MOCK_METHOD1(setOutputDataSpace, void(ui::Dataspace));
-    MOCK_METHOD1(setDisplayMaxLuminance, void(const float));
     MOCK_METHOD1(bindFrameBuffer, status_t(renderengine::Framebuffer*));
     MOCK_METHOD1(unbindFrameBuffer, void(renderengine::Framebuffer*));
     MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&));
diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp
index 5200545..8ed09f8 100644
--- a/libs/sensor/ISensorServer.cpp
+++ b/libs/sensor/ISensorServer.cpp
@@ -199,6 +199,10 @@
             int32_t type = data.readInt32();
             int32_t format = data.readInt32();
             native_handle_t *resource = data.readNativeHandle();
+            // Avoid a crash in native_handle_close if resource is nullptr
+            if (resource == nullptr) {
+                return BAD_VALUE;
+            }
             sp<ISensorEventConnection> ch =
                     createSensorDirectConnection(opPackageName, size, type, format, resource);
             native_handle_close(resource);
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index da91a97..1dfc1e9 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "BufferHubBuffer"
 #include <poll.h>
 
 #include <android-base/unique_fd.h>
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 3fc6a2d..579e68e 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -626,7 +626,7 @@
                            bufferHubBuffer->desc().layers, bufferHubBuffer->desc().usage,
                            bufferHubBuffer->desc().stride);
     mBufferId = bufferHubBuffer->id();
-    mBufferHubBuffer.reset(std::move(bufferHubBuffer.get()));
+    mBufferHubBuffer = std::move(bufferHubBuffer);
 
     return NO_ERROR;
 }
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 0861a1f..9c7d1fd 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -20,6 +20,7 @@
 
 #include <ui/GraphicBufferAllocator.h>
 
+#include <limits.h>
 #include <stdio.h>
 
 #include <grallocusage/GrallocUsageConversion.h>
@@ -114,6 +115,14 @@
     if (!width || !height)
         width = height = 1;
 
+    const uint32_t bpp = bytesPerPixel(format);
+    if (std::numeric_limits<size_t>::max() / width / height < static_cast<size_t>(bpp)) {
+        ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
+              "usage %" PRIx64 ": Requesting too large a buffer size",
+              width, height, layerCount, format, usage);
+        return BAD_VALUE;
+    }
+
     // Ensure that layerCount is valid.
     if (layerCount < 1)
         layerCount = 1;
@@ -126,7 +135,6 @@
     if (error == NO_ERROR) {
         Mutex::Autolock _l(sLock);
         KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
-        uint32_t bpp = bytesPerPixel(format);
         alloc_rec_t rec;
         rec.width = width;
         rec.height = height;
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 373fa4f..c5170d0 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -46,6 +46,24 @@
     cflags: ["-Wall", "-Werror"],
 }
 
+// This test has a main method, and requires a separate binary to be built.
+cc_test {
+    name: "GraphicBufferOverBinder_test",
+    srcs: ["GraphicBufferOverBinder_test.cpp"],
+    cflags: ["-Wall", "-Werror"],
+    header_libs: [
+        "libdvr_headers",
+    ],
+    shared_libs: [
+        "android.frameworks.bufferhub@1.0",
+        "libbinder",
+        "libgui",
+        "liblog",
+        "libui",
+        "libutils",
+    ],
+}
+
 cc_test {
     name: "BufferHub_test",
     header_libs: [
diff --git a/libs/ui/tests/GraphicBufferOverBinder_test.cpp b/libs/ui/tests/GraphicBufferOverBinder_test.cpp
new file mode 100644
index 0000000..7c0a44a
--- /dev/null
+++ b/libs/ui/tests/GraphicBufferOverBinder_test.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2019 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 LOG_TAG "GraphicBufferOverBinder_test"
+
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <gui/BufferQueue.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <ui/BufferHubBuffer.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/Log.h>
+
+namespace android {
+
+constexpr uint32_t kTestWidth = 1024;
+constexpr uint32_t kTestHeight = 1;
+constexpr uint32_t kTestFormat = HAL_PIXEL_FORMAT_BLOB;
+constexpr uint32_t kTestLayerCount = 1;
+constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN;
+static const String16 kTestServiceName = String16("GraphicBufferOverBinderTestService");
+enum GraphicBufferOverBinderTestServiceCode {
+    GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
+    GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER,
+};
+
+class GraphicBufferOverBinderTestService : public BBinder {
+public:
+    GraphicBufferOverBinderTestService() {
+        // GraphicBuffer
+        mGraphicBuffer = new GraphicBuffer(kTestWidth, kTestHeight, kTestFormat, kTestLayerCount,
+                                           kTestUsage);
+        ALOGI("mGraphicBuffer id %" PRIi32, mGraphicBuffer->getBufferId());
+
+        // BufferHub-backed GraphicBuffer
+        std::unique_ptr<BufferHubBuffer> bufferHubBuffer =
+                BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
+                                        kTestUsage, /*userMetadataSize=*/0);
+        mBufferhubBackedGraphicBuffer = new GraphicBuffer(std::move(bufferHubBuffer));
+        if (!mBufferhubBackedGraphicBuffer->isBufferHubBuffer()) {
+            ALOGE("Failed to back GraphicBuffer with BufferHub.");
+        }
+        if (bufferHubBuffer != nullptr) {
+            ALOGE("Failed to move BufferHubBuffer to GraphicBuffer");
+        }
+        ALOGI("mBufferhubBackedGraphicBuffer id %" PRIi32,
+              mBufferhubBackedGraphicBuffer->getBufferId());
+    }
+
+    ~GraphicBufferOverBinderTestService() = default;
+
+    virtual status_t onTransact(uint32_t code, const Parcel& /*data*/, Parcel* reply,
+                                uint32_t /*flags*/ = 0) {
+        switch (code) {
+            case GRAPHIC_BUFFER: {
+                return reply->write(*mGraphicBuffer);
+            }
+            case GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER: {
+                return reply->write(*mBufferhubBackedGraphicBuffer);
+            }
+            default:
+                return UNKNOWN_TRANSACTION;
+        };
+    }
+
+protected:
+    sp<GraphicBuffer> mGraphicBuffer;
+    sp<GraphicBuffer> mBufferhubBackedGraphicBuffer;
+};
+
+static int runBinderServer() {
+    ProcessState::self()->startThreadPool();
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<GraphicBufferOverBinderTestService> service = new GraphicBufferOverBinderTestService;
+    sm->addService(kTestServiceName, service, false);
+
+    ALOGI("Binder server running...");
+
+    while (true) {
+        int stat, retval;
+        retval = wait(&stat);
+        if (retval == -1 && errno == ECHILD) {
+            break;
+        }
+    }
+
+    ALOGI("Binder server exiting...");
+    return 0;
+}
+
+class GraphicBufferOverBinderTest : public ::testing::TestWithParam<uint32_t> {
+protected:
+    virtual void SetUp() {
+        mService = defaultServiceManager()->getService(kTestServiceName);
+        if (mService == nullptr) {
+            ALOGE("Failed to connect to the test service.");
+            return;
+        }
+
+        ALOGI("Binder service is ready for client.");
+    }
+
+    status_t GetGraphicBuffer(sp<GraphicBuffer>* outBuf, uint32_t opCode) {
+        Parcel data;
+        Parcel reply;
+        status_t error = mService->transact(opCode, data, &reply);
+        if (error != NO_ERROR) {
+            ALOGE("Failed to get graphic buffer over binder, error=%d.", error);
+            return error;
+        }
+
+        *outBuf = new GraphicBuffer();
+        return reply.read(**outBuf);
+    }
+
+private:
+    sp<IBinder> mService;
+};
+
+TEST_F(GraphicBufferOverBinderTest, SendGraphicBufferOverBinder) {
+    sp<GraphicBuffer> gb;
+    EXPECT_EQ(GetGraphicBuffer(&gb, GRAPHIC_BUFFER), OK);
+    EXPECT_NE(gb, nullptr);
+    EXPECT_FALSE(gb->isBufferHubBuffer());
+    void* vaddr;
+    EXPECT_EQ(gb->lock(kTestUsage, &vaddr), OK);
+    EXPECT_EQ(gb->unlock(), OK);
+}
+
+TEST_F(GraphicBufferOverBinderTest, SendGraphicBufferFromBufferHubBufferOverBinder) {
+    sp<GraphicBuffer> gb;
+    EXPECT_EQ(GetGraphicBuffer(&gb, GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER), NO_ERROR);
+    EXPECT_NE(gb, nullptr);
+    EXPECT_TRUE(gb->isBufferHubBuffer());
+    void* vaddr;
+    EXPECT_EQ(gb->lock(kTestUsage, &vaddr), OK);
+    EXPECT_EQ(gb->unlock(), OK);
+}
+
+} // namespace android
+
+int main(int argc, char** argv) {
+    pid_t pid = fork();
+    if (pid == 0) {
+        android::ProcessState::self()->startThreadPool();
+        ::testing::InitGoogleTest(&argc, argv);
+        return RUN_ALL_TESTS();
+
+    } else {
+        ALOGI("Test process pid: %d.", pid);
+        return android::runBinderServer();
+    }
+}
diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp
index a7c248c..127f7ee 100644
--- a/libs/ui/tests/GraphicBuffer_test.cpp
+++ b/libs/ui/tests/GraphicBuffer_test.cpp
@@ -35,6 +35,22 @@
 
 class GraphicBufferTest : public testing::Test {};
 
+TEST_F(GraphicBufferTest, AllocateNoError) {
+    PixelFormat format = PIXEL_FORMAT_RGBA_8888;
+    sp<GraphicBuffer> gb(new GraphicBuffer(kTestWidth, kTestHeight, format, kTestLayerCount,
+                                           kTestUsage, std::string("test")));
+    ASSERT_EQ(NO_ERROR, gb->initCheck());
+}
+
+TEST_F(GraphicBufferTest, AllocateBadDimensions) {
+    PixelFormat format = PIXEL_FORMAT_RGBA_8888;
+    uint32_t width, height;
+    width = height = std::numeric_limits<uint32_t>::max();
+    sp<GraphicBuffer> gb(new GraphicBuffer(width, height, format, kTestLayerCount, kTestUsage,
+                                           std::string("test")));
+    ASSERT_EQ(BAD_VALUE, gb->initCheck());
+}
+
 TEST_F(GraphicBufferTest, CreateFromBufferHubBuffer) {
     std::unique_ptr<BufferHubBuffer> b1 =
             BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp
index 115e866..7823e36 100644
--- a/libs/vr/libbufferhub/consumer_buffer.cpp
+++ b/libs/vr/libbufferhub/consumer_buffer.cpp
@@ -52,12 +52,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s Failed to acquire the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to acquire the buffer and modify the buffer state to "
-        "%" PRIx32 ". About to try again if the buffer is still posted.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
     if (!BufferHubDefs::isClientPosted(current_buffer_state,
                                        client_state_mask())) {
       ALOGE(
@@ -152,12 +146,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s: Failed to release the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to release the buffer and modify the buffer state to "
-        "%" PRIx32 ". About to try again.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
     // The failure of compare_exchange_weak updates current_buffer_state.
     updated_buffer_state = current_buffer_state & (~client_state_mask());
   }
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index 3d88ba5..aa9d072 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -96,13 +96,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s: Failed to post the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to post the buffer and modify the buffer state to "
-        "%" PRIx32
-        ". About to try again if the buffer is still gained by this client.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
     if (!BufferHubDefs::isClientGained(current_buffer_state,
                                        client_state_mask())) {
       ALOGE(
@@ -186,15 +179,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s: Failed to gain the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to gain the buffer and modify the buffer state to "
-        "%" PRIx32
-        ". About to try again if the buffer is still not read by other "
-        "clients.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
-
     if (BufferHubDefs::isAnyClientAcquired(current_buffer_state) ||
         BufferHubDefs::isAnyClientGained(current_buffer_state) ||
         (BufferHubDefs::isAnyClientPosted(
diff --git a/libs/vr/libdisplay/include/private/dvr/display_protocol.h b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
index 3786d1d..861dc6c 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_protocol.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
@@ -191,7 +191,8 @@
 enum class ConfigFileType : uint32_t {
   kLensMetrics,
   kDeviceMetrics,
-  kDeviceConfiguration
+  kDeviceConfiguration,
+  kDeviceEdid
 };
 
 struct DisplayProtocol {
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index e383bb2..b7abb99 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -85,6 +85,8 @@
   DVR_CONFIGURATION_DATA_DEVICE_METRICS = 1,
   // Request the per device configuration data file.
   DVR_CONFIGURATION_DATA_DEVICE_CONFIG = 2,
+  // Request the edid data for the display.
+  DVR_CONFIGURATION_DATA_DEVICE_EDID = 3,
 };
 
 // dvr_display_manager.h
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 87162c0..8980a92 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -44,6 +44,18 @@
            Endpoint::Create(display::DisplayProtocol::kClientPath)) {
     hardware_composer_.Initialize(
         hidl, primary_display_id, request_display_callback);
+
+    uint8_t port;
+    const auto error = hidl->getDisplayIdentificationData(
+        primary_display_id, &port, &display_identification_data_);
+    if (error != android::hardware::graphics::composer::V2_1::Error::NONE) {
+      if (error !=
+          android::hardware::graphics::composer::V2_1::Error::UNSUPPORTED) {
+        ALOGI("DisplayService: identification data error\n");
+      } else {
+        ALOGI("DisplayService: identification data unsupported\n");
+      }
+    }
 }
 
 bool DisplayService::IsInitialized() const {
@@ -204,6 +216,12 @@
     case display::ConfigFileType::kDeviceConfiguration:
       property_name = kDvrDeviceConfigProperty;
       break;
+    case display::ConfigFileType::kDeviceEdid:
+      if (display_identification_data_.size() == 0) {
+        return ErrorStatus(ENOENT);
+      }
+      return std::string(display_identification_data_.begin(),
+                         display_identification_data_.end());
     default:
       return ErrorStatus(EINVAL);
   }
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index e0f2edd..d45a61f 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -18,6 +18,8 @@
 #include "epoll_event_dispatcher.h"
 #include "hardware_composer.h"
 
+#include "DisplayHardware/DisplayIdentification.h"
+
 namespace android {
 namespace dvr {
 
@@ -117,6 +119,8 @@
 
   DisplayService(const DisplayService&) = delete;
   void operator=(const DisplayService&) = delete;
+
+  DisplayIdentificationData display_identification_data_;
 };
 
 }  // namespace dvr
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index abc7a72..8144c8a 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -162,7 +162,7 @@
         "libEGL_getProcAddress",
         "libEGL_blobCache",
     ],
-    ldflags: ["-Wl,--exclude-libs=ALL"],
+    ldflags: ["-Wl,--exclude-libs=ALL,--Bsymbolic-functions"],
     export_include_dirs: ["EGL/include"],
 }
 
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 038a432..23e11a8 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -311,7 +311,7 @@
     }
 
     if (!hnd) {
-        android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
+        android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL,
                                                             false, systemTime() - openTime);
     }
 
@@ -330,7 +330,7 @@
     }
 
     if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) {
-        android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
+        android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL,
                                                             false, systemTime() - openTime);
     }
 
@@ -340,7 +340,7 @@
     LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,
             "couldn't load system OpenGL ES wrapper libraries");
 
-    android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL, true,
+    android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL, true,
                                                         systemTime() - openTime);
 
     return (void*)hnd;
@@ -637,7 +637,7 @@
         return nullptr;
     }
 
-    android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::ANGLE);
+    android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
     driver_t* hnd = nullptr;
 
     // ANGLE doesn't ship with GLES library, and thus we skip GLES driver.
@@ -666,7 +666,7 @@
     }
 
     ALOGD("Load updated gl driver.");
-    android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL_UPDATED);
+    android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL_UPDATED);
     driver_t* hnd = nullptr;
     void* dso = load_updated_driver("GLES", ns);
     if (dso) {
@@ -697,7 +697,7 @@
 Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix,
                                                         const bool exact) {
     ATRACE_CALL();
-    android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL);
+    android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL);
     driver_t* hnd = nullptr;
     void* dso = load_system_driver("GLES", suffix, exact);
     if (dso) {
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
index dbb6ba6..7b8e0f8 100644
--- a/services/gpuservice/Android.bp
+++ b/services/gpuservice/Android.bp
@@ -59,9 +59,6 @@
 cc_defaults {
     name: "gpuservice_binary",
     defaults: ["gpuservice_defaults"],
-    whole_static_libs: [
-        "libsigchain",
-    ],
     shared_libs: [
         "libbinder",
         "libcutils",
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 8accf9d..e50dfca 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -28,7 +28,12 @@
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
+#include <array>
+#include <fstream>
+#include <sstream>
+#include <sys/types.h>
 #include <vkjson.h>
+#include <unistd.h>
 
 #include "gpustats/GpuStats.h"
 
@@ -40,6 +45,7 @@
 status_t cmdHelp(int out);
 status_t cmdVkjson(int out, int err);
 void dumpGameDriverInfo(std::string* result);
+void dumpMemoryInfo(std::string* result, const GpuMemoryMap& memories, uint32_t pid);
 } // namespace
 
 const String16 sDump("android.permission.DUMP");
@@ -51,35 +57,166 @@
 void GpuService::setGpuStats(const std::string& driverPackageName,
                              const std::string& driverVersionName, uint64_t driverVersionCode,
                              int64_t driverBuildTime, const std::string& appPackageName,
-                             const int32_t vulkanVersion, GraphicsEnv::Driver driver,
+                             const int32_t vulkanVersion, GpuStatsInfo::Driver driver,
                              bool isDriverLoaded, int64_t driverLoadingTime) {
-    ATRACE_CALL();
-
     mGpuStats->insert(driverPackageName, driverVersionName, driverVersionCode, driverBuildTime,
                       appPackageName, vulkanVersion, driver, isDriverLoaded, driverLoadingTime);
 }
 
 status_t GpuService::getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const {
-    ATRACE_CALL();
-
     mGpuStats->pullGlobalStats(outStats);
-
     return OK;
 }
 
 status_t GpuService::getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const {
-    ATRACE_CALL();
-
     mGpuStats->pullAppStats(outStats);
-
     return OK;
 }
 
-void GpuService::setCpuVulkanInUse(const std::string& appPackageName,
-                                   const uint64_t driverVersionCode) {
-    ATRACE_CALL();
+void GpuService::setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                                const GpuStatsInfo::Stats stats, const uint64_t value) {
+    mGpuStats->insertTargetStats(appPackageName, driverVersionCode, stats, value);
+}
 
-    mGpuStats->setCpuVulkanInUse(appPackageName, driverVersionCode);
+bool isExpectedFormat(const char* str) {
+    // Should match in order:
+    // gpuaddr useraddr size id flags type usage sglen mapsize eglsrf eglimg
+    std::istringstream iss;
+    iss.str(str);
+
+    std::string word;
+    iss >> word;
+    if (word != "gpuaddr") { return false; }
+    iss >> word;
+    if (word != "useraddr") { return false; }
+    iss >> word;
+    if (word != "size") { return false; }
+    iss >> word;
+    if (word != "id") { return false; }
+    iss >> word;
+    if (word != "flags") { return false; }
+    iss >> word;
+    if (word != "type") { return false; }
+    iss >> word;
+    if (word != "usage") { return false; }
+    iss >> word;
+    if (word != "sglen") { return false; }
+    iss >> word;
+    if (word != "mapsize") { return false; }
+    iss >> word;
+    if (word != "eglsrf") { return false; }
+    iss >> word;
+    if (word != "eglimg") { return false; }
+    return true;
+}
+
+
+// Queries gpu memory via Qualcomm's /d/kgsl/proc/*/mem interface.
+status_t GpuService::getQCommGpuMemoryInfo(GpuMemoryMap* memories, std::string* result, int32_t dumpPid) const {
+    const std::string kDirectoryPath = "/d/kgsl/proc";
+    DIR* directory = opendir(kDirectoryPath.c_str());
+    if (!directory) { return PERMISSION_DENIED; }
+
+    // File Format:
+    //          gpuaddr         useraddr     size id     flags   type          usage sglen mapsize eglsrf eglimg
+    // 0000000000000000 0000000000000000  8359936 23 --w--pY-- gpumem VK/others( 38)     0       0      0      0
+    // 0000000000000000 0000000000000000 16293888 24 --wL--N--    ion        surface    41       0      0      1
+
+    const bool dumpAll = dumpPid == 0;
+    static constexpr size_t kMaxLineLength = 1024;
+    static char line[kMaxLineLength];
+    while(dirent* subdir = readdir(directory)) {
+        // Skip "." and ".." in directory.
+        if (strcmp(subdir->d_name, ".") == 0 || strcmp(subdir->d_name, "..") == 0 ) { continue; }
+
+        std::string pid_str(subdir->d_name);
+        const uint32_t pid(stoi(pid_str));
+
+        if (!dumpAll && dumpPid != pid) {
+            continue;
+        }
+
+        std::string filepath(kDirectoryPath + "/" + pid_str + "/mem");
+        std::ifstream file(filepath);
+
+        // Check first line
+        file.getline(line, kMaxLineLength);
+        if (!isExpectedFormat(line)) {
+            continue;
+        }
+
+        if (result) {
+            StringAppendF(result, "%d:\n%s\n", pid, line);
+        }
+
+        while( file.getline(line, kMaxLineLength) ) {
+            if (result) {
+                StringAppendF(result, "%s\n", line);
+            }
+
+            std::istringstream iss;
+            iss.str(line);
+
+            // Skip gpuaddr, useraddr.
+            const char delimiter = ' ';
+            iss >> std::ws;
+            iss.ignore(kMaxLineLength, delimiter);
+            iss >> std::ws;
+            iss.ignore(kMaxLineLength, delimiter);
+
+            // Get size.
+            int64_t memsize;
+            iss >> memsize;
+
+            // Skip id, flags.
+            iss >> std::ws;
+            iss.ignore(kMaxLineLength, delimiter);
+            iss >> std::ws;
+            iss.ignore(kMaxLineLength, delimiter);
+
+            // Get type, usage.
+            std::string memtype;
+            std::string usage;
+            iss >> memtype >> usage;
+
+            // Adjust for the space in VK/others( #)
+            if (usage == "VK/others(") {
+              std::string vkTypeEnd;
+              iss >> vkTypeEnd;
+              usage.append(vkTypeEnd);
+            }
+
+            // Skip sglen.
+            iss >> std::ws;
+            iss.ignore(kMaxLineLength, delimiter);
+
+            // Get mapsize.
+            int64_t mapsize;
+            iss >> mapsize;
+
+            if (memsize == 0 && mapsize == 0) {
+                continue;
+            }
+
+            if (memtype == "gpumem") {
+                (*memories)[pid][usage].gpuMemory += memsize;
+            } else {
+                (*memories)[pid][usage].ionMemory += memsize;
+            }
+
+            if (mapsize > 0) {
+                (*memories)[pid][usage].mappedMemory += mapsize;
+            }
+        }
+
+        if (result) {
+            StringAppendF(result, "\n");
+        }
+    }
+
+    closedir(directory);
+
+    return OK;
 }
 
 status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) {
@@ -109,24 +246,44 @@
         StringAppendF(&result, "Permission Denial: can't dump gpu from pid=%d, uid=%d\n", pid, uid);
     } else {
         bool dumpAll = true;
-        size_t index = 0;
+        bool dumpDriverInfo = false;
+        bool dumpStats = false;
+        bool dumpMemory = false;
         size_t numArgs = args.size();
+        int32_t pid = 0;
 
         if (numArgs) {
-            if ((index < numArgs) && (args[index] == String16("--gpustats"))) {
-                index++;
-                mGpuStats->dump(args, &result);
-                dumpAll = false;
+            dumpAll = false;
+            for (size_t index = 0; index < numArgs; ++index) {
+                if (args[index] == String16("--gpustats")) {
+                    dumpStats = true;
+                } else if (args[index] == String16("--gpudriverinfo")) {
+                    dumpDriverInfo = true;
+                } else if (args[index] == String16("--gpumem")) {
+                    dumpMemory = true;
+                } else if (args[index].compare(String16("--gpumem=")) > 0) {
+                    dumpMemory = true;
+                    pid = atoi(String8(&args[index][9]));
+                }
             }
         }
 
-        if (dumpAll) {
+        if (dumpAll || dumpDriverInfo) {
             dumpGameDriverInfo(&result);
             result.append("\n");
-
+        }
+        if (dumpAll || dumpStats) {
             mGpuStats->dump(Vector<String16>(), &result);
             result.append("\n");
         }
+        if (dumpAll || dumpMemory) {
+            GpuMemoryMap memories;
+            // Currently only queries Qualcomm gpu memory. More will be added later.
+            if (getQCommGpuMemoryInfo(&memories, &result, pid) == OK) {
+                dumpMemoryInfo(&result, memories, pid);
+                result.append("\n");
+            }
+        }
     }
 
     write(fd, result.c_str(), result.size());
@@ -178,6 +335,34 @@
     StringAppendF(result, "Pre-release Game Driver: %s\n", preReleaseGameDriver);
 }
 
+// Read and print all memory info for each process from /d/kgsl/proc/<pid>/mem.
+void dumpMemoryInfo(std::string* result, const GpuMemoryMap& memories, uint32_t pid) {
+    if (!result) return;
+
+    // Write results.
+    StringAppendF(result, "GPU Memory Summary:\n");
+    for(auto& mem : memories) {
+        uint32_t process = mem.first;
+        if (pid != 0 && pid != process) {
+            continue;
+        }
+
+        StringAppendF(result, "%d:\n", process);
+        for(auto& memStruct : mem.second) {
+            StringAppendF(result, "  %s", memStruct.first.c_str());
+
+            if(memStruct.second.gpuMemory > 0)
+                StringAppendF(result, ", GPU memory = %" PRId64, memStruct.second.gpuMemory);
+            if(memStruct.second.mappedMemory > 0)
+                StringAppendF(result, ", Mapped memory = %" PRId64, memStruct.second.mappedMemory);
+            if(memStruct.second.ionMemory > 0)
+                StringAppendF(result, ", Ion memory = %" PRId64, memStruct.second.ionMemory);
+
+            StringAppendF(result, "\n");
+        }
+    }
+}
+
 } // anonymous namespace
 
 } // namespace android
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index 8226901..b3dc2e2 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -25,11 +25,22 @@
 
 #include <mutex>
 #include <vector>
+#include <unordered_map>
 
 namespace android {
 
 class GpuStats;
 
+struct MemoryStruct {
+  int64_t gpuMemory;
+  int64_t mappedMemory;
+  int64_t ionMemory;
+};
+
+// A map that keeps track of how much memory of each type is allocated by every process.
+// Format: map[pid][memoryType] = MemoryStruct()'
+using GpuMemoryMap = std::unordered_map<int32_t, std::unordered_map<std::string, MemoryStruct>>;
+
 class GpuService : public BnGpuService, public PriorityDumper {
 public:
     static const char* const SERVICE_NAME ANDROID_API;
@@ -46,12 +57,12 @@
     void setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName,
                      uint64_t driverVersionCode, int64_t driverBuildTime,
                      const std::string& appPackageName, const int32_t vulkanVersion,
-                     GraphicsEnv::Driver driver, bool isDriverLoaded,
+                     GpuStatsInfo::Driver driver, bool isDriverLoaded,
                      int64_t driverLoadingTime) override;
     status_t getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const override;
     status_t getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const override;
-    void setCpuVulkanInUse(const std::string& appPackageName,
-                           const uint64_t driverVersionCode) override;
+    void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                        const GpuStatsInfo::Stats stats, const uint64_t value) override;
 
     /*
      * IBinder interface
@@ -71,6 +82,8 @@
 
     status_t doDump(int fd, const Vector<String16>& args, bool asProto);
 
+    status_t getQCommGpuMemoryInfo(GpuMemoryMap* memories, std::string* result, int32_t dumpPid) const;
+
     /*
      * Attributes
      */
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 37c6abc..67babd4 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -27,20 +27,20 @@
 
 namespace android {
 
-static void addLoadingCount(GraphicsEnv::Driver driver, bool isDriverLoaded,
+static void addLoadingCount(GpuStatsInfo::Driver driver, bool isDriverLoaded,
                             GpuStatsGlobalInfo* const outGlobalInfo) {
     switch (driver) {
-        case GraphicsEnv::Driver::GL:
-        case GraphicsEnv::Driver::GL_UPDATED:
+        case GpuStatsInfo::Driver::GL:
+        case GpuStatsInfo::Driver::GL_UPDATED:
             outGlobalInfo->glLoadingCount++;
             if (!isDriverLoaded) outGlobalInfo->glLoadingFailureCount++;
             break;
-        case GraphicsEnv::Driver::VULKAN:
-        case GraphicsEnv::Driver::VULKAN_UPDATED:
+        case GpuStatsInfo::Driver::VULKAN:
+        case GpuStatsInfo::Driver::VULKAN_UPDATED:
             outGlobalInfo->vkLoadingCount++;
             if (!isDriverLoaded) outGlobalInfo->vkLoadingFailureCount++;
             break;
-        case GraphicsEnv::Driver::ANGLE:
+        case GpuStatsInfo::Driver::ANGLE:
             outGlobalInfo->angleLoadingCount++;
             if (!isDriverLoaded) outGlobalInfo->angleLoadingFailureCount++;
             break;
@@ -49,22 +49,22 @@
     }
 }
 
-static void addLoadingTime(GraphicsEnv::Driver driver, int64_t driverLoadingTime,
+static void addLoadingTime(GpuStatsInfo::Driver driver, int64_t driverLoadingTime,
                            GpuStatsAppInfo* const outAppInfo) {
     switch (driver) {
-        case GraphicsEnv::Driver::GL:
-        case GraphicsEnv::Driver::GL_UPDATED:
+        case GpuStatsInfo::Driver::GL:
+        case GpuStatsInfo::Driver::GL_UPDATED:
             if (outAppInfo->glDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
                 outAppInfo->glDriverLoadingTime.emplace_back(driverLoadingTime);
             }
             break;
-        case GraphicsEnv::Driver::VULKAN:
-        case GraphicsEnv::Driver::VULKAN_UPDATED:
+        case GpuStatsInfo::Driver::VULKAN:
+        case GpuStatsInfo::Driver::VULKAN_UPDATED:
             if (outAppInfo->vkDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
                 outAppInfo->vkDriverLoadingTime.emplace_back(driverLoadingTime);
             }
             break;
-        case GraphicsEnv::Driver::ANGLE:
+        case GpuStatsInfo::Driver::ANGLE:
             if (outAppInfo->angleDriverLoadingTime.size() < GpuStats::MAX_NUM_LOADING_TIMES) {
                 outAppInfo->angleDriverLoadingTime.emplace_back(driverLoadingTime);
             }
@@ -77,7 +77,7 @@
 void GpuStats::insert(const std::string& driverPackageName, const std::string& driverVersionName,
                       uint64_t driverVersionCode, int64_t driverBuildTime,
                       const std::string& appPackageName, const int32_t vulkanVersion,
-                      GraphicsEnv::Driver driver, bool isDriverLoaded, int64_t driverLoadingTime) {
+                      GpuStatsInfo::Driver driver, bool isDriverLoaded, int64_t driverLoadingTime) {
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mLock);
@@ -126,14 +126,28 @@
     addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
 }
 
-void GpuStats::setCpuVulkanInUse(const std::string& appPackageName,
-                                 const uint64_t driverVersionCode) {
+void GpuStats::insertTargetStats(const std::string& appPackageName,
+                                 const uint64_t driverVersionCode, const GpuStatsInfo::Stats stats,
+                                 const uint64_t /*value*/) {
+    ATRACE_CALL();
+
     const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
+
+    std::lock_guard<std::mutex> lock(mLock);
     if (!mAppStats.count(appStatsKey)) {
         return;
     }
 
-    mAppStats[appStatsKey].cpuVulkanInUse = true;
+    switch (stats) {
+        case GpuStatsInfo::Stats::CPU_VULKAN_IN_USE:
+            mAppStats[appStatsKey].cpuVulkanInUse = true;
+            break;
+        case GpuStatsInfo::Stats::FALSE_PREROTATION:
+            mAppStats[appStatsKey].falsePrerotation = true;
+            break;
+        default:
+            break;
+    }
 }
 
 void GpuStats::interceptSystemDriverStatsLocked() {
diff --git a/services/gpuservice/gpustats/GpuStats.h b/services/gpuservice/gpustats/GpuStats.h
index b293f59..656b181 100644
--- a/services/gpuservice/gpustats/GpuStats.h
+++ b/services/gpuservice/gpustats/GpuStats.h
@@ -36,9 +36,10 @@
     void insert(const std::string& driverPackageName, const std::string& driverVersionName,
                 uint64_t driverVersionCode, int64_t driverBuildTime,
                 const std::string& appPackageName, const int32_t vulkanVersion,
-                GraphicsEnv::Driver driver, bool isDriverLoaded, int64_t driverLoadingTime);
-    // Set CPU Vulkan in use signal into app stats.
-    void setCpuVulkanInUse(const std::string& appPackageName, const uint64_t driverVersionCode);
+                GpuStatsInfo::Driver driver, bool isDriverLoaded, int64_t driverLoadingTime);
+    // Insert target stats into app stats or potentially global stats as well.
+    void insertTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                           const GpuStatsInfo::Stats stats, const uint64_t value);
     // dumpsys interface
     void dump(const Vector<String16>& args, std::string* result);
     // Pull gpu global stats
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index ce56272..af02314 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -28,7 +28,6 @@
 #include <sys/limits.h>
 #include <sys/inotify.h>
 #include <sys/ioctl.h>
-#include <sys/utsname.h>
 #include <unistd.h>
 
 #define LOG_TAG "EventHub"
@@ -94,14 +93,6 @@
     return out;
 }
 
-static void getLinuxRelease(int* major, int* minor) {
-    struct utsname info;
-    if (uname(&info) || sscanf(info.release, "%d.%d", major, minor) <= 0) {
-        *major = 0, *minor = 0;
-        ALOGE("Could not get linux version: %s", strerror(errno));
-    }
-}
-
 /**
  * Return true if name matches "v4l-touch*"
  */
@@ -292,11 +283,6 @@
     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
             errno);
-
-    int major, minor;
-    getLinuxRelease(&major, &minor);
-    // EPOLLWAKEUP was introduced in kernel 3.5
-    mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);
 }
 
 EventHub::~EventHub(void) {
@@ -1487,28 +1473,13 @@
         }
     }
 
-    std::string wakeMechanism = "EPOLLWAKEUP";
-    if (!mUsingEpollWakeup) {
-#ifndef EVIOCSSUSPENDBLOCK
-        // uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels
-        // will use an epoll flag instead, so as long as we want to support
-        // this feature, we need to be prepared to define the ioctl ourselves.
-#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
-#endif
-        if (ioctl(device->fd, EVIOCSSUSPENDBLOCK, 1)) {
-            wakeMechanism = "<none>";
-        } else {
-            wakeMechanism = "EVIOCSSUSPENDBLOCK";
-        }
-    }
     // Tell the kernel that we want to use the monotonic clock for reporting timestamps
     // associated with input events.  This is important because the input system
     // uses the timestamps extensively and assumes they were recorded using the monotonic
     // clock.
     int clockId = CLOCK_MONOTONIC;
     bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
-    ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.c_str(),
-          toString(usingClockIoctl));
+    ALOGI("usingClockIoctl=%s", toString(usingClockIoctl));
 }
 
 void EventHub::openVideoDeviceLocked(const std::string& devicePath) {
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 63a20ef..6c3a4a2 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -146,12 +146,11 @@
  * which keys are currently down.  Finally, the event hub keeps track of the capabilities of
  * individual input devices, such as their class and the set of key codes that they support.
  */
-class EventHubInterface : public virtual RefBase {
-protected:
+class EventHubInterface {
+public:
     EventHubInterface() { }
     virtual ~EventHubInterface() { }
 
-public:
     // Synthetic raw event type codes produced when devices are added or removed.
     enum {
         // Sent when a device is added.
@@ -319,7 +318,6 @@
     virtual void dump(std::string& dump);
     virtual void monitor();
 
-protected:
     virtual ~EventHub();
 
 private:
@@ -479,8 +477,6 @@
     size_t mPendingEventCount;
     size_t mPendingEventIndex;
     bool mPendingINotify;
-
-    bool mUsingEpollWakeup;
 };
 
 }; // namespace android
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index 6a7f279..7c061c5 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -276,7 +276,7 @@
     bool eventAdded = mEvents.push(std::move(event));
     if (!eventAdded) {
         // If the queue is full, suspect the HAL is slow in processing the events.
-        ALOGE("Dropped event with eventTime %" PRId64, event.args->eventTime);
+        ALOGE("Could not add the event to the queue. Resetting");
         reset();
     }
 }
diff --git a/services/inputflinger/InputClassifierConverter.cpp b/services/inputflinger/InputClassifierConverter.cpp
index f82c8ef..fc8c7c3 100644
--- a/services/inputflinger/InputClassifierConverter.cpp
+++ b/services/inputflinger/InputClassifierConverter.cpp
@@ -358,6 +358,7 @@
     event.displayId = args.displayId;
     event.downTime = args.downTime;
     event.eventTime = args.eventTime;
+    event.deviceTimestamp = 0;
     event.action = getAction(args.action & AMOTION_EVENT_ACTION_MASK);
     event.actionIndex = getActionIndex(args.action);
     event.actionButton = getActionButton(args.actionButton);
@@ -375,7 +376,6 @@
     event.pointerProperties = pointerProperties;
     event.pointerCoords = pointerCoords;
 
-    event.deviceTimestamp = args.deviceTimestamp;
     event.frames = convertVideoFrames(args.videoFrames);
 
     return event;
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index c2ff4c9..019815c 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -253,23 +253,35 @@
     }
 }
 
-template<typename T, typename U>
-static T getValueByKey(std::unordered_map<U, T>& map, U key) {
-    typename std::unordered_map<U, T>::const_iterator it = map.find(key);
+/**
+ * Find the entry in std::unordered_map by key, and return it.
+ * If the entry is not found, return a default constructed entry.
+ *
+ * Useful when the entries are vectors, since an empty vector will be returned
+ * if the entry is not found.
+ * Also useful when the entries are sp<>. If an entry is not found, nullptr is returned.
+ */
+template <typename T, typename U>
+static T getValueByKey(const std::unordered_map<U, T>& map, U key) {
+    auto it = map.find(key);
     return it != map.end() ? it->second : T{};
 }
 
 
 // --- InputDispatcher ---
 
-InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
-    mPolicy(policy),
-    mPendingEvent(nullptr), mLastDropReason(DROP_REASON_NOT_DROPPED),
-    mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
-    mNextUnblockedEvent(nullptr),
-    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
-    mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
-    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
+InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
+      : mPolicy(policy),
+        mPendingEvent(nullptr),
+        mLastDropReason(DROP_REASON_NOT_DROPPED),
+        mAppSwitchSawKeyDown(false),
+        mAppSwitchDueTime(LONG_LONG_MAX),
+        mNextUnblockedEvent(nullptr),
+        mDispatchEnabled(false),
+        mDispatchFrozen(false),
+        mInputFilterEnabled(false),
+        mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
+        mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
     mLooper = new Looper(false);
     mReporter = createInputReporter();
 
@@ -703,7 +715,7 @@
         CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
 
         Command command = commandEntry->command;
-        (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
+        command(*this, commandEntry); // commands are implicitly 'LockedInterruptible'
 
         commandEntry->connection.clear();
         delete commandEntry;
@@ -797,8 +809,8 @@
     resetKeyRepeatLocked();
 
     // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doNotifyConfigurationChangedLockedInterruptible);
+    CommandEntry* commandEntry =
+            postCommandLocked(&InputDispatcher::doNotifyConfigurationChangedLockedInterruptible);
     commandEntry->eventTime = entry->eventTime;
     return true;
 }
@@ -872,7 +884,7 @@
     if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
         if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
             CommandEntry* commandEntry = postCommandLocked(
-                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
+                    &InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
             sp<InputWindowHandle> focusedWindowHandle =
                     getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(entry));
             if (focusedWindowHandle != nullptr) {
@@ -1326,6 +1338,7 @@
     bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN
             || maskedAction == AMOTION_EVENT_ACTION_SCROLL
             || isHoverAction);
+    const bool isFromMouse = entry->source == AINPUT_SOURCE_MOUSE;
     bool wrongDevice = false;
     if (newGesture) {
         bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
@@ -1361,11 +1374,17 @@
     if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
         /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
 
+        int32_t x;
+        int32_t y;
         int32_t pointerIndex = getMotionEventActionPointerIndex(action);
-        int32_t x = int32_t(entry->pointerCoords[pointerIndex].
-                getAxisValue(AMOTION_EVENT_AXIS_X));
-        int32_t y = int32_t(entry->pointerCoords[pointerIndex].
-                getAxisValue(AMOTION_EVENT_AXIS_Y));
+        // Always dispatch mouse events to cursor position.
+        if (isFromMouse) {
+            x = int32_t(entry->xCursorPosition);
+            y = int32_t(entry->yCursorPosition);
+        } else {
+            x = int32_t(entry->pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_X));
+            y = int32_t(entry->pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_Y));
+        }
         bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN;
         sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(
                 displayId, x, y, isDown /*addOutsideTargets*/, true /*addPortalWindows*/);
@@ -1377,8 +1396,8 @@
         // Figure out whether splitting will be allowed for this window.
         if (newTouchedWindowHandle != nullptr
                 && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
-            // New window supports splitting.
-            isSplit = true;
+            // New window supports splitting, but we should never split mouse events.
+            isSplit = !isFromMouse;
         } else if (isSplit) {
             // New window does not support splitting but we have already split events.
             // Ignore the new window.
@@ -1963,8 +1982,8 @@
     }
     }
 
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doPokeUserActivityLockedInterruptible);
+    CommandEntry* commandEntry =
+            postCommandLocked(&InputDispatcher::doPokeUserActivityLockedInterruptible);
     commandEntry->eventTime = eventEntry->eventTime;
     commandEntry->userActivityEventType = eventType;
 }
@@ -2181,8 +2200,8 @@
         return;
     }
 
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doOnPointerDownOutsideFocusLockedInterruptible);
+    CommandEntry* commandEntry =
+            postCommandLocked(&InputDispatcher::doOnPointerDownOutsideFocusLockedInterruptible);
     commandEntry->newToken = newToken;
 }
 
@@ -2256,15 +2275,21 @@
             }
 
             // Publish the motion event.
-            status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
-                    motionEntry->deviceId, motionEntry->source, motionEntry->displayId,
-                    dispatchEntry->resolvedAction, motionEntry->actionButton,
-                    dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
-                    motionEntry->metaState, motionEntry->buttonState, motionEntry->classification,
-                    xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
-                    motionEntry->downTime, motionEntry->eventTime,
-                    motionEntry->pointerCount, motionEntry->pointerProperties,
-                    usingCoords);
+            status =
+                    connection->inputPublisher
+                            .publishMotionEvent(dispatchEntry->seq, motionEntry->deviceId,
+                                                motionEntry->source, motionEntry->displayId,
+                                                dispatchEntry->resolvedAction,
+                                                motionEntry->actionButton,
+                                                dispatchEntry->resolvedFlags,
+                                                motionEntry->edgeFlags, motionEntry->metaState,
+                                                motionEntry->buttonState,
+                                                motionEntry->classification, xOffset, yOffset,
+                                                motionEntry->xPrecision, motionEntry->yPrecision,
+                                                motionEntry->xCursorPosition,
+                                                motionEntry->yCursorPosition, motionEntry->downTime,
+                                                motionEntry->eventTime, motionEntry->pointerCount,
+                                                motionEntry->pointerProperties, usingCoords);
             break;
         }
 
@@ -2590,24 +2615,17 @@
         }
     }
 
-    MotionEntry* splitMotionEntry = new MotionEntry(
-            originalMotionEntry->sequenceNum,
-            originalMotionEntry->eventTime,
-            originalMotionEntry->deviceId,
-            originalMotionEntry->source,
-            originalMotionEntry->displayId,
-            originalMotionEntry->policyFlags,
-            action,
-            originalMotionEntry->actionButton,
-            originalMotionEntry->flags,
-            originalMotionEntry->metaState,
-            originalMotionEntry->buttonState,
-            originalMotionEntry->classification,
-            originalMotionEntry->edgeFlags,
-            originalMotionEntry->xPrecision,
-            originalMotionEntry->yPrecision,
-            originalMotionEntry->downTime,
-            splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0);
+    MotionEntry* splitMotionEntry =
+            new MotionEntry(originalMotionEntry->sequenceNum, originalMotionEntry->eventTime,
+                            originalMotionEntry->deviceId, originalMotionEntry->source,
+                            originalMotionEntry->displayId, originalMotionEntry->policyFlags,
+                            action, originalMotionEntry->actionButton, originalMotionEntry->flags,
+                            originalMotionEntry->metaState, originalMotionEntry->buttonState,
+                            originalMotionEntry->classification, originalMotionEntry->edgeFlags,
+                            originalMotionEntry->xPrecision, originalMotionEntry->yPrecision,
+                            originalMotionEntry->xCursorPosition,
+                            originalMotionEntry->yCursorPosition, originalMotionEntry->downTime,
+                            splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0);
 
     if (originalMotionEntry->injectionState) {
         splitMotionEntry->injectionState = originalMotionEntry->injectionState;
@@ -2753,12 +2771,14 @@
 void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
 #if DEBUG_INBOUND_EVENT_DETAILS
     ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
-            ", policyFlags=0x%x, "
-            "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
-            "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
-            args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
-            args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
-            args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
+          ", policyFlags=0x%x, "
+          "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, "
+          "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, xCursorPosition=%f, "
+          "yCursorPosition=%f, downTime=%" PRId64,
+          args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
+          args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
+          args->edgeFlags, args->xPrecision, args->yPrecision, arg->xCursorPosition,
+          args->yCursorPosition, args->downTime);
     for (uint32_t i = 0; i < args->pointerCount; i++) {
         ALOGD("  Pointer %d: id=%d, toolType=%d, "
                 "x=%f, y=%f, pressure=%f, size=%f, "
@@ -2800,12 +2820,12 @@
             mLock.unlock();
 
             MotionEvent event;
-            event.initialize(args->deviceId, args->source, args->displayId,
-                    args->action, args->actionButton,
-                    args->flags, args->edgeFlags, args->metaState, args->buttonState,
-                    args->classification, 0, 0, args->xPrecision, args->yPrecision,
-                    args->downTime, args->eventTime,
-                    args->pointerCount, args->pointerProperties, args->pointerCoords);
+            event.initialize(args->deviceId, args->source, args->displayId, args->action,
+                             args->actionButton, args->flags, args->edgeFlags, args->metaState,
+                             args->buttonState, args->classification, 0, 0, args->xPrecision,
+                             args->yPrecision, args->xCursorPosition, args->yCursorPosition,
+                             args->downTime, args->eventTime, args->pointerCount,
+                             args->pointerProperties, args->pointerCoords);
 
             policyFlags |= POLICY_FLAG_FILTERED;
             if (!mPolicy->filterInputEvent(&event, policyFlags)) {
@@ -2816,12 +2836,14 @@
         }
 
         // Just enqueue a new motion event.
-        MotionEntry* newEntry = new MotionEntry(args->sequenceNum, args->eventTime,
-                args->deviceId, args->source, args->displayId, policyFlags,
-                args->action, args->actionButton, args->flags,
-                args->metaState, args->buttonState, args->classification,
-                args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
-                args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
+        MotionEntry* newEntry =
+                new MotionEntry(args->sequenceNum, args->eventTime, args->deviceId, args->source,
+                                args->displayId, policyFlags, args->action, args->actionButton,
+                                args->flags, args->metaState, args->buttonState,
+                                args->classification, args->edgeFlags, args->xPrecision,
+                                args->yPrecision, args->xCursorPosition, args->yCursorPosition,
+                                args->downTime, args->pointerCount, args->pointerProperties,
+                                args->pointerCoords, 0, 0);
 
         needWake = enqueueInboundEventLocked(newEntry);
         mLock.unlock();
@@ -2952,31 +2974,34 @@
         mLock.lock();
         const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
         const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
-        firstInjectedEntry = new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
-                motionEvent->getDeviceId(), motionEvent->getSource(), motionEvent->getDisplayId(),
-                policyFlags,
-                action, actionButton, motionEvent->getFlags(),
-                motionEvent->getMetaState(), motionEvent->getButtonState(),
-                motionEvent->getClassification(), motionEvent->getEdgeFlags(),
-                motionEvent->getXPrecision(), motionEvent->getYPrecision(),
-                motionEvent->getDownTime(),
-                uint32_t(pointerCount), pointerProperties, samplePointerCoords,
-                motionEvent->getXOffset(), motionEvent->getYOffset());
+        firstInjectedEntry =
+                new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
+                                motionEvent->getDeviceId(), motionEvent->getSource(),
+                                motionEvent->getDisplayId(), policyFlags, action, actionButton,
+                                motionEvent->getFlags(), motionEvent->getMetaState(),
+                                motionEvent->getButtonState(), motionEvent->getClassification(),
+                                motionEvent->getEdgeFlags(), motionEvent->getXPrecision(),
+                                motionEvent->getYPrecision(), motionEvent->getRawXCursorPosition(),
+                                motionEvent->getRawYCursorPosition(), motionEvent->getDownTime(),
+                                uint32_t(pointerCount), pointerProperties, samplePointerCoords,
+                                motionEvent->getXOffset(), motionEvent->getYOffset());
         lastInjectedEntry = firstInjectedEntry;
         for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
             sampleEventTimes += 1;
             samplePointerCoords += pointerCount;
-            MotionEntry* nextInjectedEntry = new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM,
-                    *sampleEventTimes,
-                    motionEvent->getDeviceId(), motionEvent->getSource(),
-                    motionEvent->getDisplayId(), policyFlags,
-                    action, actionButton, motionEvent->getFlags(),
-                    motionEvent->getMetaState(), motionEvent->getButtonState(),
-                    motionEvent->getClassification(), motionEvent->getEdgeFlags(),
-                    motionEvent->getXPrecision(), motionEvent->getYPrecision(),
-                    motionEvent->getDownTime(),
-                    uint32_t(pointerCount), pointerProperties, samplePointerCoords,
-                    motionEvent->getXOffset(), motionEvent->getYOffset());
+            MotionEntry* nextInjectedEntry =
+                    new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
+                                    motionEvent->getDeviceId(), motionEvent->getSource(),
+                                    motionEvent->getDisplayId(), policyFlags, action, actionButton,
+                                    motionEvent->getFlags(), motionEvent->getMetaState(),
+                                    motionEvent->getButtonState(), motionEvent->getClassification(),
+                                    motionEvent->getEdgeFlags(), motionEvent->getXPrecision(),
+                                    motionEvent->getYPrecision(),
+                                    motionEvent->getRawXCursorPosition(),
+                                    motionEvent->getRawYCursorPosition(),
+                                    motionEvent->getDownTime(), uint32_t(pointerCount),
+                                    pointerProperties, samplePointerCoords,
+                                    motionEvent->getXOffset(), motionEvent->getYOffset());
             lastInjectedEntry->next = nextInjectedEntry;
             lastInjectedEntry = nextInjectedEntry;
         }
@@ -3127,14 +3152,7 @@
 
 std::vector<sp<InputWindowHandle>> InputDispatcher::getWindowHandlesLocked(
         int32_t displayId) const {
-    std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>::const_iterator it =
-            mWindowHandlesByDisplay.find(displayId);
-    if(it != mWindowHandlesByDisplay.end()) {
-        return it->second;
-    }
-
-    // Return an empty one if nothing found.
-    return std::vector<sp<InputWindowHandle>>();
+    return getValueByKey(mWindowHandlesByDisplay, displayId);
 }
 
 sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
@@ -3176,6 +3194,63 @@
     return mInputChannelsByToken.at(token);
 }
 
+void InputDispatcher::updateWindowHandlesForDisplayLocked(
+        const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId) {
+    if (inputWindowHandles.empty()) {
+        // Remove all handles on a display if there are no windows left.
+        mWindowHandlesByDisplay.erase(displayId);
+        return;
+    }
+
+    // Since we compare the pointer of input window handles across window updates, we need
+    // to make sure the handle object for the same window stays unchanged across updates.
+    const std::vector<sp<InputWindowHandle>>& oldHandles = getWindowHandlesLocked(displayId);
+    std::unordered_map<sp<IBinder>, sp<InputWindowHandle>, IBinderHash> oldHandlesByTokens;
+    for (const sp<InputWindowHandle>& handle : oldHandles) {
+        oldHandlesByTokens[handle->getToken()] = handle;
+    }
+
+    std::vector<sp<InputWindowHandle>> newHandles;
+    for (const sp<InputWindowHandle>& handle : inputWindowHandles) {
+        if (!handle->updateInfo()) {
+            // handle no longer valid
+            continue;
+        }
+
+        const InputWindowInfo* info = handle->getInfo();
+        if ((getInputChannelLocked(handle->getToken()) == nullptr &&
+             info->portalToDisplayId == ADISPLAY_ID_NONE)) {
+            const bool noInputChannel =
+                    info->inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL;
+            const bool canReceiveInput =
+                    !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_TOUCHABLE) ||
+                    !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_FOCUSABLE);
+            if (canReceiveInput && !noInputChannel) {
+                ALOGE("Window handle %s has no registered input channel",
+                      handle->getName().c_str());
+            }
+            continue;
+        }
+
+        if (info->displayId != displayId) {
+            ALOGE("Window %s updated by wrong display %d, should belong to display %d",
+                  handle->getName().c_str(), displayId, info->displayId);
+            continue;
+        }
+
+        if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) {
+            const sp<InputWindowHandle> oldHandle = oldHandlesByTokens.at(handle->getToken());
+            oldHandle->updateFrom(handle);
+            newHandles.push_back(oldHandle);
+        } else {
+            newHandles.push_back(handle);
+        }
+    }
+
+    // Insert or replace
+    mWindowHandlesByDisplay[displayId] = newHandles;
+}
+
 /**
  * Called from InputManagerService, update window handle list by displayId that can receive input.
  * A window handle contains information about InputChannel, Touch Region, Types, Focused,...
@@ -3195,73 +3270,19 @@
         const std::vector<sp<InputWindowHandle>> oldWindowHandles =
                 getWindowHandlesLocked(displayId);
 
+        updateWindowHandlesForDisplayLocked(inputWindowHandles, displayId);
+
         sp<InputWindowHandle> newFocusedWindowHandle = nullptr;
         bool foundHoveredWindow = false;
-
-        if (inputWindowHandles.empty()) {
-            // Remove all handles on a display if there are no windows left.
-            mWindowHandlesByDisplay.erase(displayId);
-        } else {
-            // Since we compare the pointer of input window handles across window updates, we need
-            // to make sure the handle object for the same window stays unchanged across updates.
-            const std::vector<sp<InputWindowHandle>>& oldHandles =
-                    mWindowHandlesByDisplay[displayId];
-            std::unordered_map<sp<IBinder>, sp<InputWindowHandle>, IBinderHash> oldHandlesByTokens;
-            for (const sp<InputWindowHandle>& handle : oldHandles) {
-                oldHandlesByTokens[handle->getToken()] = handle;
+        for (const sp<InputWindowHandle>& windowHandle : getWindowHandlesLocked(displayId)) {
+            // Set newFocusedWindowHandle to the top most focused window instead of the last one
+            if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus &&
+                windowHandle->getInfo()->visible) {
+                newFocusedWindowHandle = windowHandle;
             }
-
-            std::vector<sp<InputWindowHandle>> newHandles;
-            for (const sp<InputWindowHandle>& handle : inputWindowHandles) {
-                if (!handle->updateInfo()) {
-                    // handle no longer valid
-                    continue;
-                }
-                const InputWindowInfo* info = handle->getInfo();
-
-                if ((getInputChannelLocked(handle->getToken()) == nullptr &&
-                     info->portalToDisplayId == ADISPLAY_ID_NONE)) {
-                    const bool noInputChannel =
-                            info->inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL;
-                    const bool canReceiveInput =
-                            !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_TOUCHABLE) ||
-                            !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_FOCUSABLE);
-                    if (canReceiveInput && !noInputChannel) {
-                        ALOGE("Window handle %s has no registered input channel",
-                              handle->getName().c_str());
-                    }
-                    continue;
-                }
-
-                if (info->displayId != displayId) {
-                    ALOGE("Window %s updated by wrong display %d, should belong to display %d",
-                          handle->getName().c_str(), displayId, info->displayId);
-                    continue;
-                }
-
-                if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) {
-                    const sp<InputWindowHandle> oldHandle =
-                            oldHandlesByTokens.at(handle->getToken());
-                    oldHandle->updateFrom(handle);
-                    newHandles.push_back(oldHandle);
-                } else {
-                    newHandles.push_back(handle);
-                }
+            if (windowHandle == mLastHoverWindowHandle) {
+                foundHoveredWindow = true;
             }
-
-            for (const sp<InputWindowHandle>& windowHandle : newHandles) {
-                // Set newFocusedWindowHandle to the top most focused window instead of the last one
-                if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus
-                        && windowHandle->getInfo()->visible) {
-                    newFocusedWindowHandle = windowHandle;
-                }
-                if (windowHandle == mLastHoverWindowHandle) {
-                    foundHoveredWindow = true;
-                }
-            }
-
-            // Insert or replace
-            mWindowHandlesByDisplay[displayId] = newHandles;
         }
 
         if (!foundHoveredWindow) {
@@ -4066,8 +4087,8 @@
 
 void InputDispatcher::onDispatchCycleFinishedLocked(
         nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) {
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
+    CommandEntry* commandEntry =
+            postCommandLocked(&InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
     commandEntry->connection = connection;
     commandEntry->eventTime = currentTime;
     commandEntry->seq = seq;
@@ -4079,8 +4100,8 @@
     ALOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
             connection->getInputChannelName().c_str());
 
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
+    CommandEntry* commandEntry =
+            postCommandLocked(&InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
     commandEntry->connection = connection;
 }
 
@@ -4088,8 +4109,8 @@
         const sp<InputWindowHandle>& newFocus) {
     sp<IBinder> oldToken = oldFocus != nullptr ? oldFocus->getToken() : nullptr;
     sp<IBinder> newToken = newFocus != nullptr ? newFocus->getToken() : nullptr;
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doNotifyFocusChangedLockedInterruptible);
+    CommandEntry* commandEntry =
+            postCommandLocked(&InputDispatcher::doNotifyFocusChangedLockedInterruptible);
     commandEntry->oldToken = oldToken;
     commandEntry->newToken = newToken;
 }
@@ -4121,8 +4142,8 @@
     mLastANRState += StringPrintf(INDENT2 "Reason: %s\n", reason);
     dumpDispatchStateLocked(mLastANRState);
 
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doNotifyANRLockedInterruptible);
+    CommandEntry* commandEntry =
+            postCommandLocked(&InputDispatcher::doNotifyANRLockedInterruptible);
     commandEntry->inputApplicationHandle = applicationHandle;
     commandEntry->inputChannel = windowHandle != nullptr ?
             getInputChannelLocked(windowHandle->getToken()) : nullptr;
@@ -4216,53 +4237,55 @@
 void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
         CommandEntry* commandEntry) {
     sp<Connection> connection = commandEntry->connection;
-    nsecs_t finishTime = commandEntry->eventTime;
+    const nsecs_t finishTime = commandEntry->eventTime;
     uint32_t seq = commandEntry->seq;
-    bool handled = commandEntry->handled;
+    const bool handled = commandEntry->handled;
 
     // Handle post-event policy actions.
     DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
-    if (dispatchEntry) {
-        nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
-        if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
-            std::string msg =
-                    StringPrintf("Window '%s' spent %0.1fms processing the last input event: ",
-                    connection->getWindowName().c_str(), eventDuration * 0.000001f);
-            dispatchEntry->eventEntry->appendDescription(msg);
-            ALOGI("%s", msg.c_str());
-        }
-
-        bool restartEvent;
-        if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
-            KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
-            restartEvent = afterKeyEventLockedInterruptible(connection,
-                    dispatchEntry, keyEntry, handled);
-        } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {
-            MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
-            restartEvent = afterMotionEventLockedInterruptible(connection,
-                    dispatchEntry, motionEntry, handled);
-        } else {
-            restartEvent = false;
-        }
-
-        // Dequeue the event and start the next cycle.
-        // Note that because the lock might have been released, it is possible that the
-        // contents of the wait queue to have been drained, so we need to double-check
-        // a few things.
-        if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
-            connection->waitQueue.dequeue(dispatchEntry);
-            traceWaitQueueLength(connection);
-            if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
-                connection->outboundQueue.enqueueAtHead(dispatchEntry);
-                traceOutboundQueueLength(connection);
-            } else {
-                releaseDispatchEntry(dispatchEntry);
-            }
-        }
-
-        // Start the next dispatch cycle for this connection.
-        startDispatchCycleLocked(now(), connection);
+    if (!dispatchEntry) {
+        return;
     }
+
+    nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
+    if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
+        std::string msg =
+                StringPrintf("Window '%s' spent %0.1fms processing the last input event: ",
+                             connection->getWindowName().c_str(), eventDuration * 0.000001f);
+        dispatchEntry->eventEntry->appendDescription(msg);
+        ALOGI("%s", msg.c_str());
+    }
+
+    bool restartEvent;
+    if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
+        KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
+        restartEvent =
+                afterKeyEventLockedInterruptible(connection, dispatchEntry, keyEntry, handled);
+    } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {
+        MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
+        restartEvent = afterMotionEventLockedInterruptible(connection, dispatchEntry, motionEntry,
+                                                           handled);
+    } else {
+        restartEvent = false;
+    }
+
+    // Dequeue the event and start the next cycle.
+    // Note that because the lock might have been released, it is possible that the
+    // contents of the wait queue to have been drained, so we need to double-check
+    // a few things.
+    if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
+        connection->waitQueue.dequeue(dispatchEntry);
+        traceWaitQueueLength(connection);
+        if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
+            connection->outboundQueue.enqueueAtHead(dispatchEntry);
+            traceOutboundQueueLength(connection);
+        } else {
+            releaseDispatchEntry(dispatchEntry);
+        }
+    }
+
+    // Start the next dispatch cycle for this connection.
+    startDispatchCycleLocked(now(), connection);
 }
 
 bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
@@ -4633,21 +4656,32 @@
 
 // --- InputDispatcher::MotionEntry ---
 
-InputDispatcher::MotionEntry::MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
-        uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
-        int32_t actionButton,
+InputDispatcher::MotionEntry::MotionEntry(
+        uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+        int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
         int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification,
-        int32_t edgeFlags, float xPrecision, float yPrecision, nsecs_t downTime,
-        uint32_t pointerCount,
+        int32_t edgeFlags, float xPrecision, float yPrecision, float xCursorPosition,
+        float yCursorPosition, nsecs_t downTime, uint32_t pointerCount,
         const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
-        float xOffset, float yOffset) :
-        EventEntry(sequenceNum, TYPE_MOTION, eventTime, policyFlags),
+        float xOffset, float yOffset)
+      : EventEntry(sequenceNum, TYPE_MOTION, eventTime, policyFlags),
         eventTime(eventTime),
-        deviceId(deviceId), source(source), displayId(displayId), action(action),
-        actionButton(actionButton), flags(flags), metaState(metaState), buttonState(buttonState),
-        classification(classification), edgeFlags(edgeFlags),
-        xPrecision(xPrecision), yPrecision(yPrecision),
-        downTime(downTime), pointerCount(pointerCount) {
+        deviceId(deviceId),
+        source(source),
+        displayId(displayId),
+        action(action),
+        actionButton(actionButton),
+        flags(flags),
+        metaState(metaState),
+        buttonState(buttonState),
+        classification(classification),
+        edgeFlags(edgeFlags),
+        xPrecision(xPrecision),
+        yPrecision(yPrecision),
+        xCursorPosition(xCursorPosition),
+        yCursorPosition(yCursorPosition),
+        downTime(downTime),
+        pointerCount(pointerCount) {
     for (uint32_t i = 0; i < pointerCount; i++) {
         this->pointerProperties[i].copyFrom(pointerProperties[i]);
         this->pointerCoords[i].copyFrom(pointerCoords[i]);
@@ -4662,11 +4696,14 @@
 
 void InputDispatcher::MotionEntry::appendDescription(std::string& msg) const {
     msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32
-            ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, "
-            "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, pointers=[",
-            deviceId, source, displayId, motionActionToString(action).c_str(), actionButton, flags,
-            metaState, buttonState, motionClassificationToString(classification), edgeFlags,
-            xPrecision, yPrecision);
+                        ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, "
+                        "buttonState=0x%08x, "
+                        "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, "
+                        "xCursorPosition=%0.1f, yCursorPosition=%0.1f, pointers=[",
+                        deviceId, source, displayId, motionActionToString(action).c_str(),
+                        actionButton, flags, metaState, buttonState,
+                        motionClassificationToString(classification), edgeFlags, xPrecision,
+                        yPrecision, xCursorPosition, yCursorPosition);
 
     for (uint32_t i = 0; i < pointerCount; i++) {
         if (i) {
@@ -4936,6 +4973,8 @@
     memento.flags = flags;
     memento.xPrecision = entry->xPrecision;
     memento.yPrecision = entry->yPrecision;
+    memento.xCursorPosition = entry->xCursorPosition;
+    memento.yCursorPosition = entry->yCursorPosition;
     memento.downTime = entry->downTime;
     memento.setPointers(entry);
     memento.hovering = hovering;
@@ -4966,13 +5005,16 @@
         if (shouldCancelMotion(memento, options)) {
             const int32_t action = memento.hovering ?
                     AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
-            outEvents.push_back(new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
-                    memento.deviceId, memento.source, memento.displayId, memento.policyFlags,
-                    action, 0 /*actionButton*/, memento.flags, AMETA_NONE, 0 /*buttonState*/,
-                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                    memento.xPrecision, memento.yPrecision, memento.downTime,
-                    memento.pointerCount, memento.pointerProperties, memento.pointerCoords,
-                    0 /*xOffset*/, 0 /*yOffset*/));
+            outEvents.push_back(
+                    new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime, memento.deviceId,
+                                    memento.source, memento.displayId, memento.policyFlags, action,
+                                    0 /*actionButton*/, memento.flags, AMETA_NONE,
+                                    0 /*buttonState*/, MotionClassification::NONE,
+                                    AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
+                                    memento.yPrecision, memento.xCursorPosition,
+                                    memento.yCursorPosition, memento.downTime, memento.pointerCount,
+                                    memento.pointerProperties, memento.pointerCoords, 0 /*xOffset*/,
+                                    0 /*yOffset*/));
         }
     }
 }
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 753b748..147437c 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -570,19 +570,21 @@
         int32_t edgeFlags;
         float xPrecision;
         float yPrecision;
+        float xCursorPosition;
+        float yCursorPosition;
         nsecs_t downTime;
         uint32_t pointerCount;
         PointerProperties pointerProperties[MAX_POINTERS];
         PointerCoords pointerCoords[MAX_POINTERS];
 
-        MotionEntry(uint32_t sequenceNum, nsecs_t eventTime,
-                int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
-                int32_t action, int32_t actionButton, int32_t flags,
-                int32_t metaState, int32_t buttonState, MotionClassification classification,
-                int32_t edgeFlags, float xPrecision, float yPrecision,
-                nsecs_t downTime, uint32_t pointerCount,
-                const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
-                float xOffset, float yOffset);
+        MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+                    int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
+                    int32_t flags, int32_t metaState, int32_t buttonState,
+                    MotionClassification classification, int32_t edgeFlags, float xPrecision,
+                    float yPrecision, float xCursorPosition, float yCursorPosition,
+                    nsecs_t downTime, uint32_t pointerCount,
+                    const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+                    float xOffset, float yOffset);
         virtual void appendDescription(std::string& msg) const;
 
     protected:
@@ -642,7 +644,7 @@
     //
     // Commands are implicitly 'LockedInterruptible'.
     struct CommandEntry;
-    typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
+    typedef std::function<void(InputDispatcher&, CommandEntry*)> Command;
 
     class Connection;
     struct CommandEntry : Link<CommandEntry> {
@@ -830,6 +832,8 @@
             int32_t flags;
             float xPrecision;
             float yPrecision;
+            float xCursorPosition;
+            float yCursorPosition;
             nsecs_t downTime;
             uint32_t pointerCount;
             PointerProperties pointerProperties[MAX_POINTERS];
@@ -1051,6 +1055,13 @@
     sp<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const REQUIRES(mLock);
     bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
 
+    /*
+     * Validate and update InputWindowHandles for a given display.
+     */
+    void updateWindowHandlesForDisplayLocked(
+            const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId)
+            REQUIRES(mLock);
+
     // Focus tracking for keys, trackball, etc.
     std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay
             GUARDED_BY(mLock);
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index 423b69c..de63977 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -21,6 +21,7 @@
 #include "InputListener.h"
 
 #include <android/log.h>
+#include <math.h>
 
 namespace android {
 
@@ -87,21 +88,32 @@
 
 // --- NotifyMotionArgs ---
 
-NotifyMotionArgs::NotifyMotionArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
-        uint32_t source, int32_t displayId, uint32_t policyFlags,
-        int32_t action, int32_t actionButton, int32_t flags, int32_t metaState,
-        int32_t buttonState, MotionClassification classification,
-        int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount,
-        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
-        float xPrecision, float yPrecision, nsecs_t downTime,
-        const std::vector<TouchVideoFrame>& videoFrames) :
-        NotifyArgs(sequenceNum, eventTime), deviceId(deviceId), source(source),
-        displayId(displayId), policyFlags(policyFlags),
-        action(action), actionButton(actionButton),
-        flags(flags), metaState(metaState), buttonState(buttonState),
-        classification(classification), edgeFlags(edgeFlags), deviceTimestamp(deviceTimestamp),
+NotifyMotionArgs::NotifyMotionArgs(
+        uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+        int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
+        int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification,
+        int32_t edgeFlags, uint32_t pointerCount, const PointerProperties* pointerProperties,
+        const PointerCoords* pointerCoords, float xPrecision, float yPrecision,
+        float xCursorPosition, float yCursorPosition, nsecs_t downTime,
+        const std::vector<TouchVideoFrame>& videoFrames)
+      : NotifyArgs(sequenceNum, eventTime),
+        deviceId(deviceId),
+        source(source),
+        displayId(displayId),
+        policyFlags(policyFlags),
+        action(action),
+        actionButton(actionButton),
+        flags(flags),
+        metaState(metaState),
+        buttonState(buttonState),
+        classification(classification),
+        edgeFlags(edgeFlags),
         pointerCount(pointerCount),
-        xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime),
+        xPrecision(xPrecision),
+        yPrecision(yPrecision),
+        xCursorPosition(xCursorPosition),
+        yCursorPosition(yCursorPosition),
+        downTime(downTime),
         videoFrames(videoFrames) {
     for (uint32_t i = 0; i < pointerCount; i++) {
         this->pointerProperties[i].copyFrom(pointerProperties[i]);
@@ -109,14 +121,25 @@
     }
 }
 
-NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) :
-        NotifyArgs(other.sequenceNum, other.eventTime), deviceId(other.deviceId),
-        source(other.source), displayId(other.displayId), policyFlags(other.policyFlags),
-        action(other.action), actionButton(other.actionButton), flags(other.flags),
-        metaState(other.metaState), buttonState(other.buttonState),
-        classification(other.classification), edgeFlags(other.edgeFlags),
-        deviceTimestamp(other.deviceTimestamp), pointerCount(other.pointerCount),
-        xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime),
+NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other)
+      : NotifyArgs(other.sequenceNum, other.eventTime),
+        deviceId(other.deviceId),
+        source(other.source),
+        displayId(other.displayId),
+        policyFlags(other.policyFlags),
+        action(other.action),
+        actionButton(other.actionButton),
+        flags(other.flags),
+        metaState(other.metaState),
+        buttonState(other.buttonState),
+        classification(other.classification),
+        edgeFlags(other.edgeFlags),
+        pointerCount(other.pointerCount),
+        xPrecision(other.xPrecision),
+        yPrecision(other.yPrecision),
+        xCursorPosition(other.xCursorPosition),
+        yCursorPosition(other.yCursorPosition),
+        downTime(other.downTime),
         videoFrames(other.videoFrames) {
     for (uint32_t i = 0; i < pointerCount; i++) {
         pointerProperties[i].copyFrom(other.pointerProperties[i]);
@@ -124,28 +147,23 @@
     }
 }
 
+static inline bool isCursorPositionEqual(float lhs, float rhs) {
+    return (isnan(lhs) && isnan(rhs)) || lhs == rhs;
+}
+
 bool NotifyMotionArgs::operator==(const NotifyMotionArgs& rhs) const {
-    bool equal =
-            sequenceNum == rhs.sequenceNum
-            && eventTime == rhs.eventTime
-            && deviceId == rhs.deviceId
-            && source == rhs.source
-            && displayId == rhs.displayId
-            && policyFlags == rhs.policyFlags
-            && action == rhs.action
-            && actionButton == rhs.actionButton
-            && flags == rhs.flags
-            && metaState == rhs.metaState
-            && buttonState == rhs.buttonState
-            && classification == rhs.classification
-            && edgeFlags == rhs.edgeFlags
-            && deviceTimestamp == rhs.deviceTimestamp
-            && pointerCount == rhs.pointerCount
+    bool equal = sequenceNum == rhs.sequenceNum && eventTime == rhs.eventTime &&
+            deviceId == rhs.deviceId && source == rhs.source && displayId == rhs.displayId &&
+            policyFlags == rhs.policyFlags && action == rhs.action &&
+            actionButton == rhs.actionButton && flags == rhs.flags && metaState == rhs.metaState &&
+            buttonState == rhs.buttonState && classification == rhs.classification &&
+            edgeFlags == rhs.edgeFlags &&
+            pointerCount == rhs.pointerCount
             // PointerProperties and PointerCoords are compared separately below
-            && xPrecision == rhs.xPrecision
-            && yPrecision == rhs.yPrecision
-            && downTime == rhs.downTime
-            && videoFrames == rhs.videoFrames;
+            && xPrecision == rhs.xPrecision && yPrecision == rhs.yPrecision &&
+            isCursorPositionEqual(xCursorPosition, rhs.xCursorPosition) &&
+            isCursorPositionEqual(yCursorPosition, rhs.yCursorPosition) &&
+            downTime == rhs.downTime && videoFrames == rhs.videoFrames;
     if (!equal) {
         return false;
     }
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index a45b8a5..3e236a9 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -260,12 +260,17 @@
 
 // --- InputReader ---
 
-InputReader::InputReader(const sp<EventHubInterface>& eventHub,
-        const sp<InputReaderPolicyInterface>& policy,
-        const sp<InputListenerInterface>& listener) :
-        mContext(this), mEventHub(eventHub), mPolicy(policy),
-        mNextSequenceNum(1), mGlobalMetaState(0), mGeneration(1),
-        mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
+InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
+                         const sp<InputReaderPolicyInterface>& policy,
+                         const sp<InputListenerInterface>& listener)
+      : mContext(this),
+        mEventHub(eventHub),
+        mPolicy(policy),
+        mNextSequenceNum(1),
+        mGlobalMetaState(0),
+        mGeneration(1),
+        mDisableVirtualKeysTimeout(LLONG_MIN),
+        mNextTimeout(LLONG_MAX),
         mConfigurationChangesToRefresh(0) {
     mQueuedListener = new QueuedInputListener(listener);
 
@@ -559,7 +564,8 @@
     mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
 
     if (changes) {
-        ALOGI("Reconfiguring input devices.  changes=0x%08x", changes);
+        ALOGI("Reconfiguring input devices, changes=%s",
+              InputReaderConfiguration::changesToString(changes).c_str());
         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
 
         if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
@@ -1093,8 +1099,8 @@
         }
 
         if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
-            ssize_t index = config->disabledDevices.indexOf(mId);
-            bool enabled = index < 0;
+            auto it = config->disabledDevices.find(mId);
+            bool enabled = it == config->disabledDevices.end();
             setEnabled(enabled, when);
         }
 
@@ -1731,10 +1737,12 @@
 
 // --- MultiTouchMotionAccumulator ---
 
-MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
-        mCurrentSlot(-1), mSlots(nullptr), mSlotCount(0), mUsingSlotsProtocol(false),
-        mHaveStylus(false), mDeviceTimestamp(0) {
-}
+MultiTouchMotionAccumulator::MultiTouchMotionAccumulator()
+      : mCurrentSlot(-1),
+        mSlots(nullptr),
+        mSlotCount(0),
+        mUsingSlotsProtocol(false),
+        mHaveStylus(false) {}
 
 MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
     delete[] mSlots;
@@ -1774,7 +1782,6 @@
     } else {
         clearSlots(-1);
     }
-    mDeviceTimestamp = 0;
 }
 
 void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
@@ -1868,8 +1875,6 @@
     } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
         // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
         mCurrentSlot += 1;
-    } else if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
-        mDeviceTimestamp = rawEvent->value;
     }
 }
 
@@ -2782,6 +2787,8 @@
     mPointerVelocityControl.move(when, &deltaX, &deltaY);
 
     int32_t displayId;
+    float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
+    float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
     if (mSource == AINPUT_SOURCE_MOUSE) {
         if (moved || scrolled || buttonsChanged) {
             mPointerController->setPresentation(
@@ -2798,10 +2805,9 @@
             mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
         }
 
-        float x, y;
-        mPointerController->getPosition(&x, &y);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+        mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
         displayId = mPointerController->getDisplayId();
@@ -2845,21 +2851,23 @@
                 int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
                 buttonState &= ~actionButton;
                 NotifyMotionArgs releaseArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                        mSource, displayId, policyFlags,
-                        AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
-                        metaState, buttonState,
-                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                        /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                        mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+                                             mSource, displayId, policyFlags,
+                                             AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
+                                             metaState, buttonState, MotionClassification::NONE,
+                                             AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+                                             &pointerCoords, mXPrecision, mYPrecision,
+                                             xCursorPosition, yCursorPosition, downTime,
+                                             /* videoFrames */ {});
                 getListener()->notifyMotion(&releaseArgs);
             }
         }
 
         NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
-                displayId, policyFlags, motionEventAction, 0, 0, metaState, currentButtonState,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+                              displayId, policyFlags, motionEventAction, 0, 0, metaState,
+                              currentButtonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
+                              mXPrecision, mYPrecision, xCursorPosition, yCursorPosition, downTime,
+                              /* videoFrames */ {});
         getListener()->notifyMotion(&args);
 
         if (buttonsPressed) {
@@ -2868,11 +2876,13 @@
                 int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
                 buttonState |= actionButton;
                 NotifyMotionArgs pressArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                        mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_BUTTON_PRESS,
-                        actionButton, 0, metaState, buttonState,
-                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                        /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                        mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+                                           mSource, displayId, policyFlags,
+                                           AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
+                                           metaState, buttonState, MotionClassification::NONE,
+                                           AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+                                           &pointerCoords, mXPrecision, mYPrecision,
+                                           xCursorPosition, yCursorPosition, downTime,
+                                           /* videoFrames */ {});
                 getListener()->notifyMotion(&pressArgs);
             }
         }
@@ -2882,12 +2892,12 @@
         // Send hover move after UP to tell the application that the mouse is hovering now.
         if (motionEventAction == AMOTION_EVENT_ACTION_UP
                 && (mSource == AINPUT_SOURCE_MOUSE)) {
-            NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                    mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
-                    metaState, currentButtonState,
-                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                    /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                    mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+            NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                                       displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
+                                       0, metaState, currentButtonState, MotionClassification::NONE,
+                                       AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+                                       &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
+                                       yCursorPosition, downTime, /* videoFrames */ {});
             getListener()->notifyMotion(&hoverArgs);
         }
 
@@ -2897,11 +2907,12 @@
             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
 
             NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                    mSource, displayId, policyFlags,
-                    AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState,
-                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                    /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                    mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
+                                        mSource, displayId, policyFlags,
+                                        AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
+                                        currentButtonState, MotionClassification::NONE,
+                                        AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+                                        &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
+                                        yCursorPosition, downTime, /* videoFrames */ {});
             getListener()->notifyMotion(&scrollArgs);
         }
     }
@@ -3041,12 +3052,12 @@
         int32_t metaState = mContext->getGlobalMetaState();
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
 
-        NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, /* buttonState */ 0,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                0, 0, 0, /* videoFrames */ {});
+        NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                                    displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
+                                    metaState, /* buttonState */ 0, MotionClassification::NONE,
+                                    AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
+                                    &pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                    AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
         getListener()->notifyMotion(&scrollArgs);
     }
 
@@ -4767,7 +4778,6 @@
         int32_t buttonState = mCurrentCookedState.buttonState;
         dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0,
                 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
-                mCurrentCookedState.deviceTimestamp,
                 mCurrentCookedState.cookedPointerData.pointerProperties,
                 mCurrentCookedState.cookedPointerData.pointerCoords,
                 mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4790,7 +4800,6 @@
             dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
                     AMOTION_EVENT_EDGE_FLAG_NONE,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4825,7 +4834,6 @@
 
             dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mLastCookedState.cookedPointerData.pointerProperties,
                     mLastCookedState.cookedPointerData.pointerCoords,
                     mLastCookedState.cookedPointerData.idToIndex,
@@ -4840,7 +4848,6 @@
             ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
             dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4859,7 +4866,6 @@
 
             dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4875,7 +4881,6 @@
         int32_t metaState = getContext()->getGlobalMetaState();
         dispatchMotion(when, policyFlags, mSource,
                 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastCookedState.buttonState, 0,
-                mLastCookedState.deviceTimestamp,
                 mLastCookedState.cookedPointerData.pointerProperties,
                 mLastCookedState.cookedPointerData.pointerCoords,
                 mLastCookedState.cookedPointerData.idToIndex,
@@ -4892,7 +4897,6 @@
         if (!mSentHoverEnter) {
             dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER,
                     0, 0, metaState, mCurrentRawState.buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4904,7 +4908,6 @@
         dispatchMotion(when, policyFlags, mSource,
                 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
                 mCurrentRawState.buttonState, 0,
-                mCurrentCookedState.deviceTimestamp,
                 mCurrentCookedState.cookedPointerData.pointerProperties,
                 mCurrentCookedState.cookedPointerData.pointerCoords,
                 mCurrentCookedState.cookedPointerData.idToIndex,
@@ -4924,7 +4927,6 @@
         dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton,
                     0, metaState, buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
@@ -4942,7 +4944,6 @@
         buttonState |= actionButton;
         dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton,
                     0, metaState, buttonState, 0,
-                    mCurrentCookedState.deviceTimestamp,
                     mCurrentCookedState.cookedPointerData.pointerProperties,
                     mCurrentCookedState.cookedPointerData.pointerCoords,
                     mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
@@ -4961,8 +4962,6 @@
     uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
 
     mCurrentCookedState.cookedPointerData.clear();
-    mCurrentCookedState.deviceTimestamp =
-            mCurrentRawState.deviceTimestamp;
     mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
     mCurrentCookedState.cookedPointerData.hoveringIdBits =
             mCurrentRawState.rawPointerData.hoveringIdBits;
@@ -5354,13 +5353,11 @@
     BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
     if (!dispatchedGestureIdBits.isEmpty()) {
         if (cancelPreviousGesture) {
-            dispatchMotion(when, policyFlags, mSource,
-                    AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
-                    AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                    mPointerGesture.lastGestureProperties,
-                    mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
-                    dispatchedGestureIdBits, -1, 0,
-                    0, mPointerGesture.downTime);
+            dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
+                           buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                           mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
+                           mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
+                           mPointerGesture.downTime);
 
             dispatchedGestureIdBits.clear();
         } else {
@@ -5377,7 +5374,6 @@
                 dispatchMotion(when, policyFlags, mSource,
                         AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
                         metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
-                        /* deviceTimestamp */ 0,
                         mPointerGesture.lastGestureProperties,
                         mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
                         dispatchedGestureIdBits, id,
@@ -5390,13 +5386,12 @@
 
     // Send motion events for all pointers that moved.
     if (moveNeeded) {
-        dispatchMotion(when, policyFlags, mSource,
-                AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
-                AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                mPointerGesture.currentGestureProperties,
-                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
-                dispatchedGestureIdBits, -1,
-                0, 0, mPointerGesture.downTime);
+        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
+                       buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                       mPointerGesture.currentGestureProperties,
+                       mPointerGesture.currentGestureCoords,
+                       mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
+                       mPointerGesture.downTime);
     }
 
     // Send motion events for all pointers that went down.
@@ -5413,7 +5408,6 @@
 
             dispatchMotion(when, policyFlags, mSource,
                     AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
-                    /* deviceTimestamp */ 0,
                     mPointerGesture.currentGestureProperties,
                     mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
                     dispatchedGestureIdBits, id,
@@ -5423,13 +5417,12 @@
 
     // Send motion events for hover.
     if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
-        dispatchMotion(when, policyFlags, mSource,
-                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
-                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                mPointerGesture.currentGestureProperties,
-                mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
-                mPointerGesture.currentGestureIdBits, -1,
-                0, 0, mPointerGesture.downTime);
+        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+                       buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                       mPointerGesture.currentGestureProperties,
+                       mPointerGesture.currentGestureCoords,
+                       mPointerGesture.currentGestureIdToIndex,
+                       mPointerGesture.currentGestureIdBits, -1, 0, 0, mPointerGesture.downTime);
     } else if (dispatchedGestureIdBits.isEmpty()
             && !mPointerGesture.lastGestureIdBits.isEmpty()) {
         // Synthesize a hover move event after all pointers go up to indicate that
@@ -5450,12 +5443,11 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
 
         const int32_t displayId = mPointerController->getDisplayId();
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
-                metaState, buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-                0, 0, mPointerGesture.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+                              metaState, buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
+                              0, 0, x, y, mPointerGesture.downTime, /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -5482,13 +5474,11 @@
     if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
         int32_t metaState = getContext()->getGlobalMetaState();
         int32_t buttonState = mCurrentRawState.buttonState;
-        dispatchMotion(when, policyFlags, mSource,
-                AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
-                AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                mPointerGesture.lastGestureProperties,
-                mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
-                mPointerGesture.lastGestureIdBits, -1,
-                0, 0, mPointerGesture.downTime);
+        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
+                       buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                       mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
+                       mPointerGesture.lastGestureIdToIndex, mPointerGesture.lastGestureIdBits, -1,
+                       0, 0, mPointerGesture.downTime);
     }
 
     // Reset the current pointer gesture.
@@ -6360,29 +6350,31 @@
     int32_t metaState = getContext()->getGlobalMetaState();
     int32_t displayId = mViewport.displayId;
 
-    if (mPointerController != nullptr) {
-        if (down || hovering) {
-            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
-            mPointerController->clearSpots();
-            mPointerController->setButtonState(mCurrentRawState.buttonState);
-            mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
-        } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
-            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-        }
-        displayId = mPointerController->getDisplayId();
+    if (down || hovering) {
+        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
+        mPointerController->clearSpots();
+        mPointerController->setButtonState(mCurrentRawState.buttonState);
+        mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
+    } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
+        mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
     }
+    displayId = mPointerController->getDisplayId();
+
+    float xCursorPosition;
+    float yCursorPosition;
+    mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
 
     if (mPointerSimple.down && !down) {
         mPointerSimple.down = false;
 
         // Send up.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
-                mOrientedXPrecision, mOrientedYPrecision,
-                mPointerSimple.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState,
+                              mLastRawState.buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
+                              &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
+                              xCursorPosition, yCursorPosition, mPointerSimple.downTime,
+                              /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -6390,13 +6382,13 @@
         mPointerSimple.hovering = false;
 
         // Send hover exit.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
-                mOrientedXPrecision, mOrientedYPrecision,
-                mPointerSimple.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0,
+                              metaState, mLastRawState.buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
+                              &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
+                              xCursorPosition, yCursorPosition, mPointerSimple.downTime,
+                              /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -6406,25 +6398,24 @@
             mPointerSimple.downTime = when;
 
             // Send down.
-            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                    mSource, displayId, policyFlags,
-                    AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState,
-                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
-                    /* deviceTimestamp */ 0,
-                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
-                    mOrientedXPrecision, mOrientedYPrecision,
-                    mPointerSimple.downTime, /* videoFrames */ {});
+            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                                  displayId, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, 0,
+                                  metaState, mCurrentRawState.buttonState,
+                                  MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+                                  &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+                                  mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
+                                  yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
             getListener()->notifyMotion(&args);
         }
 
         // Send move.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
-                mOrientedXPrecision, mOrientedYPrecision,
-                mPointerSimple.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
+                              mCurrentRawState.buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
+                              &mPointerSimple.currentCoords, mOrientedXPrecision,
+                              mOrientedYPrecision, xCursorPosition, yCursorPosition,
+                              mPointerSimple.downTime, /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -6433,26 +6424,24 @@
             mPointerSimple.hovering = true;
 
             // Send hover enter.
-            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                    mSource, displayId, policyFlags,
-                    AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
-                    mCurrentRawState.buttonState, MotionClassification::NONE,
-                    AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                    1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
-                    mOrientedXPrecision, mOrientedYPrecision,
-                    mPointerSimple.downTime, /* videoFrames */ {});
+            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                                  displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0,
+                                  metaState, mCurrentRawState.buttonState,
+                                  MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+                                  &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
+                                  mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
+                                  yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
             getListener()->notifyMotion(&args);
         }
 
         // Send hover move.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
-                mCurrentRawState.buttonState, MotionClassification::NONE,
-                AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
-                mOrientedXPrecision, mOrientedYPrecision,
-                mPointerSimple.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+                              metaState, mCurrentRawState.buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
+                              &mPointerSimple.currentCoords, mOrientedXPrecision,
+                              mOrientedYPrecision, xCursorPosition, yCursorPosition,
+                              mPointerSimple.downTime, /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -6468,13 +6457,13 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
 
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState,
-                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
-                1, &mPointerSimple.currentProperties, &pointerCoords,
-                mOrientedXPrecision, mOrientedYPrecision,
-                mPointerSimple.downTime, /* videoFrames */ {});
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                              displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
+                              mCurrentRawState.buttonState, MotionClassification::NONE,
+                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
+                              &pointerCoords, mOrientedXPrecision, mOrientedYPrecision,
+                              xCursorPosition, yCursorPosition, mPointerSimple.downTime,
+                              /* videoFrames */ {});
         getListener()->notifyMotion(&args);
     }
 
@@ -6495,11 +6484,12 @@
 }
 
 void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
-        int32_t action, int32_t actionButton, int32_t flags,
-        int32_t metaState, int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
-        const PointerProperties* properties, const PointerCoords* coords,
-        const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
-        float xPrecision, float yPrecision, nsecs_t downTime) {
+                                      int32_t action, int32_t actionButton, int32_t flags,
+                                      int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+                                      const PointerProperties* properties,
+                                      const PointerCoords* coords, const uint32_t* idToIndex,
+                                      BitSet32 idBits, int32_t changedId, float xPrecision,
+                                      float yPrecision, nsecs_t downTime) {
     PointerCoords pointerCoords[MAX_POINTERS];
     PointerProperties pointerProperties[MAX_POINTERS];
     uint32_t pointerCount = 0;
@@ -6531,16 +6521,21 @@
             ALOG_ASSERT(false);
         }
     }
+    float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
+    float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
+    if (mDeviceMode == DEVICE_MODE_POINTER) {
+        mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
+    }
     const int32_t displayId = getAssociatedDisplay().value_or(ADISPLAY_ID_NONE);
     const int32_t deviceId = getDeviceId();
     std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
     std::for_each(frames.begin(), frames.end(),
             [this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });
-    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId,
-            source, displayId, policyFlags,
-            action, actionButton, flags, metaState, buttonState, MotionClassification::NONE,
-            edgeFlags, deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
-            xPrecision, yPrecision, downTime, std::move(frames));
+    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId, source, displayId,
+                          policyFlags, action, actionButton, flags, metaState, buttonState,
+                          MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
+                          pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
+                          downTime, std::move(frames));
     getListener()->notifyMotion(&args);
 }
 
@@ -7023,7 +7018,6 @@
         outCount += 1;
     }
 
-    outState->deviceTimestamp = mMultiTouchMotionAccumulator.getDeviceTimestamp();
     outState->rawPointerData.pointerCount = outCount;
     mPointerIdBits = newPointerIdBits;
 
@@ -7462,10 +7456,12 @@
     uint32_t policyFlags = 0;
 
     NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-            AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
-            AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, MotionClassification::NONE,
-            AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
-            &pointerProperties, &pointerCoords, 0, 0, 0, /* videoFrames */ {});
+                          AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
+                          AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
+                          MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+                          &pointerProperties, &pointerCoords, 0, 0,
+                          AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                          AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
     getListener()->notifyMotion(&args);
 }
 
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 9777779..11ef934 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -114,9 +114,9 @@
  */
 class InputReader : public InputReaderInterface {
 public:
-    InputReader(const sp<EventHubInterface>& eventHub,
-            const sp<InputReaderPolicyInterface>& policy,
-            const sp<InputListenerInterface>& listener);
+    InputReader(std::shared_ptr<EventHubInterface> eventHub,
+                const sp<InputReaderPolicyInterface>& policy,
+                const sp<InputListenerInterface>& listener);
     virtual ~InputReader();
 
     virtual void dump(std::string& dump);
@@ -181,7 +181,10 @@
 
     Condition mReaderIsAliveCondition;
 
-    sp<EventHubInterface> mEventHub;
+    // This could be unique_ptr, but due to the way InputReader tests are written,
+    // it is made shared_ptr here. In the tests, an EventHub reference is retained by the test
+    // in parallel to passing it to the InputReader.
+    std::shared_ptr<EventHubInterface> mEventHub;
     sp<InputReaderPolicyInterface> mPolicy;
     sp<QueuedInputListener> mQueuedListener;
 
@@ -717,7 +720,6 @@
 
     inline size_t getSlotCount() const { return mSlotCount; }
     inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
-    inline uint32_t getDeviceTimestamp() const { return mDeviceTimestamp; }
 
 private:
     int32_t mCurrentSlot;
@@ -725,7 +727,6 @@
     size_t mSlotCount;
     bool mUsingSlotsProtocol;
     bool mHaveStylus;
-    uint32_t mDeviceTimestamp;
 
     void clearSlots(int32_t initialSlot);
 };
@@ -1174,7 +1175,6 @@
 
     struct RawState {
         nsecs_t when;
-        uint32_t deviceTimestamp;
 
         // Raw pointer sample data.
         RawPointerData rawPointerData;
@@ -1187,7 +1187,6 @@
 
         void copyFrom(const RawState& other) {
             when = other.when;
-            deviceTimestamp = other.deviceTimestamp;
             rawPointerData.copyFrom(other.rawPointerData);
             buttonState = other.buttonState;
             rawVScroll = other.rawVScroll;
@@ -1196,7 +1195,6 @@
 
         void clear() {
             when = 0;
-            deviceTimestamp = 0;
             rawPointerData.clear();
             buttonState = 0;
             rawVScroll = 0;
@@ -1205,7 +1203,6 @@
     };
 
     struct CookedState {
-        uint32_t deviceTimestamp;
         // Cooked pointer sample data.
         CookedPointerData cookedPointerData;
 
@@ -1217,7 +1214,6 @@
         int32_t buttonState;
 
         void copyFrom(const CookedState& other) {
-            deviceTimestamp = other.deviceTimestamp;
             cookedPointerData.copyFrom(other.cookedPointerData);
             fingerIdBits = other.fingerIdBits;
             stylusIdBits = other.stylusIdBits;
@@ -1226,7 +1222,6 @@
         }
 
         void clear() {
-            deviceTimestamp = 0;
             cookedPointerData.clear();
             fingerIdBits.clear();
             stylusIdBits.clear();
@@ -1634,7 +1629,6 @@
     void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
             int32_t action, int32_t actionButton,
             int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
-            uint32_t deviceTimestamp,
             const PointerProperties* properties, const PointerCoords* coords,
             const uint32_t* idToIndex, BitSet32 idBits,
             int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime);
diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp
index f48a645..bc53cf5 100644
--- a/services/inputflinger/InputReaderBase.cpp
+++ b/services/inputflinger/InputReaderBase.cpp
@@ -49,6 +49,44 @@
 
 // --- InputReaderConfiguration ---
 
+std::string InputReaderConfiguration::changesToString(uint32_t changes) {
+    if (changes == 0) {
+        return "<none>";
+    }
+    std::string result;
+    if (changes & CHANGE_POINTER_SPEED) {
+        result += "POINTER_SPEED | ";
+    }
+    if (changes & CHANGE_POINTER_GESTURE_ENABLEMENT) {
+        result += "POINTER_GESTURE_ENABLEMENT | ";
+    }
+    if (changes & CHANGE_DISPLAY_INFO) {
+        result += "DISPLAY_INFO | ";
+    }
+    if (changes & CHANGE_SHOW_TOUCHES) {
+        result += "SHOW_TOUCHES | ";
+    }
+    if (changes & CHANGE_KEYBOARD_LAYOUTS) {
+        result += "KEYBOARD_LAYOUTS | ";
+    }
+    if (changes & CHANGE_DEVICE_ALIAS) {
+        result += "DEVICE_ALIAS | ";
+    }
+    if (changes & CHANGE_TOUCH_AFFINE_TRANSFORMATION) {
+        result += "TOUCH_AFFINE_TRANSFORMATION | ";
+    }
+    if (changes & CHANGE_EXTERNAL_STYLUS_PRESENCE) {
+        result += "EXTERNAL_STYLUS_PRESENCE | ";
+    }
+    if (changes & CHANGE_ENABLED_STATE) {
+        result += "ENABLED_STATE | ";
+    }
+    if (changes & CHANGE_MUST_REOPEN) {
+        result += "MUST_REOPEN | ";
+    }
+    return result;
+}
+
 std::optional<DisplayViewport> InputReaderConfiguration::getDisplayViewportByUniqueId(
         const std::string& uniqueDisplayId) const {
     if (uniqueDisplayId.empty()) {
diff --git a/services/inputflinger/InputReaderFactory.cpp b/services/inputflinger/InputReaderFactory.cpp
index 3534f6b..072499b 100644
--- a/services/inputflinger/InputReaderFactory.cpp
+++ b/services/inputflinger/InputReaderFactory.cpp
@@ -22,7 +22,7 @@
 sp<InputReaderInterface> createInputReader(
         const sp<InputReaderPolicyInterface>& policy,
         const sp<InputListenerInterface>& listener) {
-    return new InputReader(new EventHub(), policy, listener);
+    return new InputReader(std::make_unique<EventHub>(), policy, listener);
 }
 
 } // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index b51dcb6..0dcd2f9 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -107,31 +107,32 @@
      */
     MotionClassification classification;
     int32_t edgeFlags;
-    /**
-     * A timestamp in the input device's time base, not the platform's.
-     * The units are microseconds since the last reset.
-     * This can only be compared to other device timestamps from the same device.
-     * This value will overflow after a little over an hour.
-     */
-    uint32_t deviceTimestamp;
+
     uint32_t pointerCount;
     PointerProperties pointerProperties[MAX_POINTERS];
     PointerCoords pointerCoords[MAX_POINTERS];
     float xPrecision;
     float yPrecision;
+    /**
+     * Mouse cursor position when this event is reported relative to the origin of the specified
+     * display. Only valid if this is a mouse event (originates from a mouse or from a trackpad in
+     * gestures enabled mode.
+     */
+    float xCursorPosition;
+    float yCursorPosition;
     nsecs_t downTime;
     std::vector<TouchVideoFrame> videoFrames;
 
     inline NotifyMotionArgs() { }
 
     NotifyMotionArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
-            int32_t displayId, uint32_t policyFlags,
-            int32_t action, int32_t actionButton, int32_t flags,
-            int32_t metaState, int32_t buttonState, MotionClassification classification,
-            int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount,
-            const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
-            float xPrecision, float yPrecision, nsecs_t downTime,
-            const std::vector<TouchVideoFrame>& videoFrames);
+                     int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
+                     int32_t flags, int32_t metaState, int32_t buttonState,
+                     MotionClassification classification, int32_t edgeFlags, uint32_t pointerCount,
+                     const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+                     float xPrecision, float yPrecision, float xCursorPosition,
+                     float yCursorPosition, nsecs_t downTime,
+                     const std::vector<TouchVideoFrame>& videoFrames);
 
     NotifyMotionArgs(const NotifyMotionArgs& other);
 
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 8ad5dd0..5d576b9 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -24,14 +24,13 @@
 #include <input/DisplayViewport.h>
 #include <input/VelocityControl.h>
 #include <input/VelocityTracker.h>
-#include <utils/KeyedVector.h>
 #include <utils/Thread.h>
 #include <utils/RefBase.h>
-#include <utils/SortedVector.h>
 
-#include <optional>
 #include <stddef.h>
 #include <unistd.h>
+#include <optional>
+#include <set>
 #include <unordered_map>
 #include <vector>
 
@@ -250,7 +249,7 @@
     bool pointerCapture;
 
     // The set of currently disabled input devices.
-    SortedVector<int32_t> disabledDevices;
+    std::set<int32_t> disabledDevices;
 
     InputReaderConfiguration() :
             virtualKeyQuietTime(0),
@@ -270,6 +269,8 @@
             pointerGestureZoomSpeedRatio(0.3f),
             showTouches(false), pointerCapture(false) { }
 
+    static std::string changesToString(uint32_t changes);
+
     std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const;
     std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueDisplayId)
             const;
diff --git a/services/inputflinger/tests/InputClassifierConverter_test.cpp b/services/inputflinger/tests/InputClassifierConverter_test.cpp
index 813b69e..f58b628 100644
--- a/services/inputflinger/tests/InputClassifierConverter_test.cpp
+++ b/services/inputflinger/tests/InputClassifierConverter_test.cpp
@@ -38,12 +38,15 @@
     coords.setAxisValue(AMOTION_EVENT_AXIS_Y, 2);
     coords.setAxisValue(AMOTION_EVENT_AXIS_SIZE, 0.5);
     static constexpr nsecs_t downTime = 2;
-    NotifyMotionArgs motionArgs(1/*sequenceNum*/, downTime/*eventTime*/, 3/*deviceId*/,
-            AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, 4/*policyFlags*/, AMOTION_EVENT_ACTION_DOWN,
-            0/*actionButton*/, 0/*flags*/, AMETA_NONE, 0/*buttonState*/, MotionClassification::NONE,
-            AMOTION_EVENT_EDGE_FLAG_NONE, 5/*deviceTimestamp*/,
-            1/*pointerCount*/, &properties, &coords, 0/*xPrecision*/, 0/*yPrecision*/,
-            downTime, {}/*videoFrames*/);
+    NotifyMotionArgs motionArgs(1 /*sequenceNum*/, downTime /*eventTime*/, 3 /*deviceId*/,
+                                AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, 4 /*policyFlags*/,
+                                AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, 0 /*flags*/,
+                                AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
+                                AMOTION_EVENT_EDGE_FLAG_NONE, 1 /*pointerCount*/, &properties,
+                                &coords, 0 /*xPrecision*/, 0 /*yPrecision*/,
+                                AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime,
+                                {} /*videoFrames*/);
     return motionArgs;
 }
 
diff --git a/services/inputflinger/tests/InputClassifier_test.cpp b/services/inputflinger/tests/InputClassifier_test.cpp
index 7cc17a2..40086ef 100644
--- a/services/inputflinger/tests/InputClassifier_test.cpp
+++ b/services/inputflinger/tests/InputClassifier_test.cpp
@@ -38,12 +38,15 @@
     coords.setAxisValue(AMOTION_EVENT_AXIS_X, 1);
     coords.setAxisValue(AMOTION_EVENT_AXIS_Y, 1);
     static constexpr nsecs_t downTime = 2;
-    NotifyMotionArgs motionArgs(1/*sequenceNum*/, downTime/*eventTime*/, 3/*deviceId*/,
-            AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, 4/*policyFlags*/, AMOTION_EVENT_ACTION_DOWN,
-            0/*actionButton*/, 0/*flags*/, AMETA_NONE, 0/*buttonState*/, MotionClassification::NONE,
-            AMOTION_EVENT_EDGE_FLAG_NONE, 5/*deviceTimestamp*/,
-            1/*pointerCount*/, &properties, &coords, 0/*xPrecision*/, 0/*yPrecision*/,
-            downTime, {}/*videoFrames*/);
+    NotifyMotionArgs motionArgs(1 /*sequenceNum*/, downTime /*eventTime*/, 3 /*deviceId*/,
+                                AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, 4 /*policyFlags*/,
+                                AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, 0 /*flags*/,
+                                AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
+                                AMOTION_EVENT_EDGE_FLAG_NONE, 1 /*pointerCount*/, &properties,
+                                &coords, 0 /*xPrecision*/, 0 /*yPrecision*/,
+                                AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime,
+                                {} /*videoFrames*/);
     return motionArgs;
 }
 
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 9fe6481..a86dcbc 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -249,8 +249,10 @@
 
     // Rejects undefined motion actions.
     event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+                     /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -258,18 +260,24 @@
 
     // Rejects pointer down with invalid index.
     event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+                     AMOTION_EVENT_ACTION_POINTER_DOWN |
+                             (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+                     0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer down index too large.";
 
     event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+                     AMOTION_EVENT_ACTION_POINTER_DOWN |
+                             (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+                     0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -277,36 +285,45 @@
 
     // Rejects pointer up with invalid index.
     event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+                     AMOTION_EVENT_ACTION_POINTER_UP |
+                             (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+                     0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer up index too large.";
 
     event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+                     AMOTION_EVENT_ACTION_POINTER_UP |
+                             (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+                     0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer up index too small.";
 
     // Rejects motion events with invalid number of pointers.
-    event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
+                     metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 0, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with 0 pointers.";
 
-    event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
+                     metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -314,18 +331,22 @@
 
     // Rejects motion events with invalid pointer ids.
     pointerProperties[0].id = -1;
-    event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
+                     metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer ids less than 0.";
 
     pointerProperties[0].id = MAX_POINTER_ID + 1;
-    event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
+                     metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -334,9 +355,11 @@
     // Rejects motion events with duplicate pointer ids.
     pointerProperties[0].id = 1;
     pointerProperties[1].id = 1;
-    event.initialize(DEVICE_ID, source, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
+                     metaState, 0, classification, 0, 0, 0, 0,
+                     AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                     ARBITRARY_TIME, ARBITRARY_TIME,
+                     /*pointerCount*/ 2, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -463,6 +486,7 @@
         mInfo.frameRight = mFrame.right;
         mInfo.frameBottom = mFrame.bottom;
         mInfo.globalScaleFactor = 1.0;
+        mInfo.touchableRegion.clear();
         mInfo.addTouchableRegion(mFrame);
         mInfo.visible = true;
         mInfo.canReceiveKeys = true;
@@ -521,8 +545,10 @@
             INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
 }
 
-static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
-        int32_t displayId, int32_t x = 100, int32_t y = 200) {
+static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
+                                 int32_t source, int32_t displayId, int32_t x, int32_t y,
+                                 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
     MotionEvent event;
     PointerProperties pointerProperties[1];
     PointerCoords pointerCoords[1];
@@ -537,12 +563,11 @@
 
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
     // Define a valid motion down event.
-    event.initialize(DEVICE_ID, source, displayId,
-            AMOTION_EVENT_ACTION_DOWN, /* actionButton */ 0, /* flags */ 0, /* edgeFlags */ 0,
-            AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
-            /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
-            /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
-            pointerCoords);
+    event.initialize(DEVICE_ID, source, displayId, action, /* actionButton */ 0, /* flags */ 0,
+                     /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
+                     /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
+                     /* yPrecision */ 0, xCursorPosition, yCursorPosition, currentTime, currentTime,
+                     /*pointerCount*/ 1, pointerProperties, pointerCoords);
 
     // Inject event until dispatch out.
     return dispatcher->injectInputEvent(
@@ -551,6 +576,11 @@
             INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
 }
 
+static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
+                                int32_t displayId, int32_t x = 100, int32_t y = 200) {
+    return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
+}
+
 static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
     // Define a valid key event.
@@ -576,11 +606,12 @@
     nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
     // Define a valid motion event.
     NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
-            POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
-            AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
-            AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1, pointerProperties,
-            pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0, currentTime,
-            /* videoFrames */ {});
+                          POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
+                          AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
+                          AMOTION_EVENT_EDGE_FLAG_NONE, 1, pointerProperties, pointerCoords,
+                          /* xPrecision */ 0, /* yPrecision */ 0,
+                          AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                          AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
 
     return args;
 }
@@ -704,6 +735,32 @@
     windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
 }
 
+TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
+    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+
+    sp<FakeWindowHandle> windowLeft =
+            new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+    windowLeft->setFrame(Rect(0, 0, 600, 800));
+    windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+    sp<FakeWindowHandle> windowRight =
+            new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+    windowRight->setFrame(Rect(600, 0, 1200, 800));
+    windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+
+    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+
+    std::vector<sp<InputWindowHandle>> inputWindowHandles{windowLeft, windowRight};
+    mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
+
+    // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
+    // left window. This event should be dispatched to the left window.
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+              injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
+                                ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
+    windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
+    windowRight->assertNoEvents();
+}
+
 /* Test InputDispatcher for MultiDisplay */
 class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
 public:
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index d353028..d95ac96 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -202,21 +202,9 @@
         mConfig.portAssociations.insert({inputPort, displayPort});
     }
 
-    void addDisabledDevice(int32_t deviceId) {
-        ssize_t index = mConfig.disabledDevices.indexOf(deviceId);
-        bool currentlyEnabled = index < 0;
-        if (currentlyEnabled) {
-            mConfig.disabledDevices.add(deviceId);
-        }
-    }
+    void addDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.insert(deviceId); }
 
-    void removeDisabledDevice(int32_t deviceId) {
-        ssize_t index = mConfig.disabledDevices.indexOf(deviceId);
-        bool currentlyEnabled = index < 0;
-        if (!currentlyEnabled) {
-            mConfig.disabledDevices.remove(deviceId);
-        }
-    }
+    void removeDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.erase(deviceId); }
 
     void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
         mPointerControllers.add(deviceId, controller);
@@ -337,14 +325,13 @@
     List<RawEvent> mEvents;
     std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> mVideoFrames;
 
-protected:
+public:
     virtual ~FakeEventHub() {
         for (size_t i = 0; i < mDevices.size(); i++) {
             delete mDevices.valueAt(i);
         }
     }
 
-public:
     FakeEventHub() { }
 
     void addDevice(int32_t deviceId, const std::string& name, uint32_t classes) {
@@ -772,7 +759,7 @@
 // --- FakeInputReaderContext ---
 
 class FakeInputReaderContext : public InputReaderContext {
-    sp<EventHubInterface> mEventHub;
+    std::shared_ptr<EventHubInterface> mEventHub;
     sp<InputReaderPolicyInterface> mPolicy;
     sp<InputListenerInterface> mListener;
     int32_t mGlobalMetaState;
@@ -781,12 +768,14 @@
     uint32_t mNextSequenceNum;
 
 public:
-    FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
-            const sp<InputReaderPolicyInterface>& policy,
-            const sp<InputListenerInterface>& listener) :
-            mEventHub(eventHub), mPolicy(policy), mListener(listener),
-            mGlobalMetaState(0), mNextSequenceNum(1) {
-    }
+    FakeInputReaderContext(std::shared_ptr<EventHubInterface> eventHub,
+                           const sp<InputReaderPolicyInterface>& policy,
+                           const sp<InputListenerInterface>& listener)
+          : mEventHub(eventHub),
+            mPolicy(policy),
+            mListener(listener),
+            mGlobalMetaState(0),
+            mNextSequenceNum(1) {}
 
     virtual ~FakeInputReaderContext() { }
 
@@ -1011,12 +1000,10 @@
     InputDevice* mNextDevice;
 
 public:
-    InstrumentedInputReader(const sp<EventHubInterface>& eventHub,
-            const sp<InputReaderPolicyInterface>& policy,
-            const sp<InputListenerInterface>& listener) :
-            InputReader(eventHub, policy, listener),
-            mNextDevice(nullptr) {
-    }
+    InstrumentedInputReader(std::shared_ptr<EventHubInterface> eventHub,
+                            const sp<InputReaderPolicyInterface>& policy,
+                            const sp<InputListenerInterface>& listener)
+          : InputReader(eventHub, policy, listener), mNextDevice(nullptr) {}
 
     virtual ~InstrumentedInputReader() {
         if (mNextDevice) {
@@ -1244,11 +1231,11 @@
 protected:
     sp<TestInputListener> mFakeListener;
     sp<FakeInputReaderPolicy> mFakePolicy;
-    sp<FakeEventHub> mFakeEventHub;
+    std::shared_ptr<FakeEventHub> mFakeEventHub;
     sp<InstrumentedInputReader> mReader;
 
     virtual void SetUp() {
-        mFakeEventHub = new FakeEventHub();
+        mFakeEventHub = std::make_unique<FakeEventHub>();
         mFakePolicy = new FakeInputReaderPolicy();
         mFakeListener = new TestInputListener();
 
@@ -1260,7 +1247,6 @@
 
         mFakeListener.clear();
         mFakePolicy.clear();
-        mFakeEventHub.clear();
     }
 
     void addDevice(int32_t deviceId, const std::string& name, uint32_t classes,
@@ -1587,7 +1573,7 @@
     static const int32_t DEVICE_CONTROLLER_NUMBER;
     static const uint32_t DEVICE_CLASSES;
 
-    sp<FakeEventHub> mFakeEventHub;
+    std::shared_ptr<FakeEventHub> mFakeEventHub;
     sp<FakeInputReaderPolicy> mFakePolicy;
     sp<TestInputListener> mFakeListener;
     FakeInputReaderContext* mFakeContext;
@@ -1595,7 +1581,7 @@
     InputDevice* mDevice;
 
     virtual void SetUp() {
-        mFakeEventHub = new FakeEventHub();
+        mFakeEventHub = std::make_unique<FakeEventHub>();
         mFakePolicy = new FakeInputReaderPolicy();
         mFakeListener = new TestInputListener();
         mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
@@ -1613,7 +1599,6 @@
         delete mFakeContext;
         mFakeListener.clear();
         mFakePolicy.clear();
-        mFakeEventHub.clear();
     }
 };
 
@@ -1782,14 +1767,14 @@
     static const int32_t DEVICE_CONTROLLER_NUMBER;
     static const uint32_t DEVICE_CLASSES;
 
-    sp<FakeEventHub> mFakeEventHub;
+    std::shared_ptr<FakeEventHub> mFakeEventHub;
     sp<FakeInputReaderPolicy> mFakePolicy;
     sp<TestInputListener> mFakeListener;
     FakeInputReaderContext* mFakeContext;
     InputDevice* mDevice;
 
     virtual void SetUp() {
-        mFakeEventHub = new FakeEventHub();
+        mFakeEventHub = std::make_unique<FakeEventHub>();
         mFakePolicy = new FakeInputReaderPolicy();
         mFakeListener = new TestInputListener();
         mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
@@ -1807,7 +1792,6 @@
         delete mFakeContext;
         mFakeListener.clear();
         mFakePolicy.clear();
-        mFakeEventHub.clear();
     }
 
     void addConfigurationProperty(const char* key, const char* value) {
@@ -4688,7 +4672,6 @@
     void processSlot(MultiTouchInputMapper* mapper, int32_t slot);
     void processToolType(MultiTouchInputMapper* mapper, int32_t toolType);
     void processKey(MultiTouchInputMapper* mapper, int32_t code, int32_t value);
-    void processTimestamp(MultiTouchInputMapper* mapper, uint32_t value);
     void processMTSync(MultiTouchInputMapper* mapper);
     void processSync(MultiTouchInputMapper* mapper);
 };
@@ -4804,10 +4787,6 @@
     process(mapper, ARBITRARY_TIME, EV_KEY, code, value);
 }
 
-void MultiTouchInputMapperTest::processTimestamp(MultiTouchInputMapper* mapper, uint32_t value) {
-    process(mapper, ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, value);
-}
-
 void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper* mapper) {
     process(mapper, ARBITRARY_TIME, EV_SYN, SYN_MT_REPORT, 0);
 }
@@ -6190,64 +6169,6 @@
             toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
 }
 
-TEST_F(MultiTouchInputMapperTest, Process_HandlesTimestamp) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-
-    addConfigurationProperty("touch.deviceType", "touchScreen");
-    prepareDisplay(DISPLAY_ORIENTATION_0);
-    prepareAxes(POSITION);
-    addMapperAndConfigure(mapper);
-    NotifyMotionArgs args;
-
-    // By default, deviceTimestamp should be zero
-    processPosition(mapper, 100, 100);
-    processMTSync(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(0U, args.deviceTimestamp);
-
-    // Now the timestamp of 1000 is reported by evdev and should appear in MotionArgs
-    processPosition(mapper, 0, 0);
-    processTimestamp(mapper, 1000);
-    processMTSync(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(1000U, args.deviceTimestamp);
-}
-
-TEST_F(MultiTouchInputMapperTest, WhenMapperIsReset_TimestampIsCleared) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-
-    addConfigurationProperty("touch.deviceType", "touchScreen");
-    prepareDisplay(DISPLAY_ORIENTATION_0);
-    prepareAxes(POSITION);
-    addMapperAndConfigure(mapper);
-    NotifyMotionArgs args;
-
-    // Send a touch event with a timestamp
-    processPosition(mapper, 100, 100);
-    processTimestamp(mapper, 1);
-    processMTSync(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(1U, args.deviceTimestamp);
-
-    // Since the data accumulates, and new timestamp has not arrived, deviceTimestamp won't change
-    processPosition(mapper, 100, 200);
-    processMTSync(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(1U, args.deviceTimestamp);
-
-    mapper->reset(/* when */ 0);
-    // After the mapper is reset, deviceTimestamp should become zero again
-    processPosition(mapper, 100, 300);
-    processMTSync(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(0U, args.deviceTimestamp);
-}
-
 /**
  * Set the input device port <--> display port associations, and check that the
  * events are routed to the display that matches the display port.
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 5b298b4..965d8f4 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -149,7 +149,7 @@
         "Scheduler/DispSyncSource.cpp",
         "Scheduler/EventControlThread.cpp",
         "Scheduler/EventThread.cpp",
-        "Scheduler/IdleTimer.cpp",
+        "Scheduler/OneShotTimer.cpp",
         "Scheduler/LayerHistory.cpp",
         "Scheduler/LayerInfo.cpp",
         "Scheduler/MessageQueue.cpp",
@@ -187,9 +187,6 @@
     cflags: [
         "-DLOG_TAG=\"SurfaceFlinger\"",
     ],
-    whole_static_libs: [
-        "libsigchain",
-    ],
     shared_libs: [
         "android.frameworks.displayservice@1.0",
         "android.hardware.configstore-utils",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index f51fbb4..59ea9af 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -25,6 +25,7 @@
 #include <compositionengine/Display.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/LayerCreationArgs.h>
+#include <compositionengine/LayerFECompositionState.h>
 #include <compositionengine/OutputLayer.h>
 #include <compositionengine/impl/LayerCompositionState.h>
 #include <compositionengine/impl/OutputLayerCompositionState.h>
@@ -253,90 +254,20 @@
             mActiveBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
 }
 
-void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice,
-                                  const ui::Transform& transform, const Rect& viewport,
-                                  int32_t supportedPerFrameMetadata,
-                                  const ui::Dataspace targetDataspace) {
-    RETURN_IF_NO_HWC_LAYER(displayDevice);
-
-    // Apply this display's projection's viewport to the visible region
-    // before giving it to the HWC HAL.
-    Region visible = transform.transform(visibleRegion.intersect(viewport));
-
-    const auto outputLayer = findOutputLayerForDisplay(displayDevice);
-    LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc);
-
-    auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
-    auto error = hwcLayer->setVisibleRegion(visible);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
-              to_string(error).c_str(), static_cast<int32_t>(error));
-        visible.dump(LOG_TAG);
-    }
-    outputLayer->editState().visibleRegion = visible;
-
-    auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
-
-    error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(),
-              to_string(error).c_str(), static_cast<int32_t>(error));
-        surfaceDamageRegion.dump(LOG_TAG);
-    }
-    layerCompositionState.surfaceDamage = surfaceDamageRegion;
+void BufferLayer::latchPerFrameState(
+        compositionengine::LayerFECompositionState& compositionState) const {
+    Layer::latchPerFrameState(compositionState);
 
     // Sideband layers
-    if (layerCompositionState.sidebandStream.get()) {
-        setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::SIDEBAND);
-        ALOGV("[%s] Requesting Sideband composition", mName.string());
-        error = hwcLayer->setSidebandStream(layerCompositionState.sidebandStream->handle());
-        if (error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(),
-                  layerCompositionState.sidebandStream->handle(), to_string(error).c_str(),
-                  static_cast<int32_t>(error));
-        }
-        layerCompositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
-        return;
-    }
-
-    // Device or Cursor layers
-    if (mPotentialCursor) {
-        ALOGV("[%s] Requesting Cursor composition", mName.string());
-        setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::CURSOR);
+    if (compositionState.sidebandStream.get()) {
+        compositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
     } else {
-        ALOGV("[%s] Requesting Device composition", mName.string());
-        setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::DEVICE);
+        // Normal buffer layers
+        compositionState.hdrMetadata = getDrawingHdrMetadata();
+        compositionState.compositionType = mPotentialCursor
+                ? Hwc2::IComposerClient::Composition::CURSOR
+                : Hwc2::IComposerClient::Composition::DEVICE;
     }
-
-    ui::Dataspace dataspace = isColorSpaceAgnostic() && targetDataspace != ui::Dataspace::UNKNOWN
-            ? targetDataspace
-            : mCurrentDataSpace;
-    error = hwcLayer->setDataspace(dataspace);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), dataspace,
-              to_string(error).c_str(), static_cast<int32_t>(error));
-    }
-
-    const HdrMetadata& metadata = getDrawingHdrMetadata();
-    error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata, metadata);
-    if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) {
-        ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(),
-              to_string(error).c_str(), static_cast<int32_t>(error));
-    }
-
-    error = hwcLayer->setColorTransform(getColorTransform());
-    if (error == HWC2::Error::Unsupported) {
-        // If per layer color transform is not supported, we use GPU composition.
-        setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::CLIENT);
-    } else if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(),
-                to_string(error).c_str(), static_cast<int32_t>(error));
-    }
-    layerCompositionState.dataspace = mCurrentDataSpace;
-    layerCompositionState.colorTransform = getColorTransform();
-    layerCompositionState.hdrMetadata = metadata;
-
-    setHwcLayerBuffer(displayDevice);
 }
 
 bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) {
@@ -395,7 +326,8 @@
     return true;
 }
 
-bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+                              nsecs_t expectedPresentTime) {
     ATRACE_CALL();
 
     bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);
@@ -430,12 +362,12 @@
     const bool oldOpacity = isOpaque(s);
     sp<GraphicBuffer> oldBuffer = mActiveBuffer;
 
-    if (!allTransactionsSignaled()) {
+    if (!allTransactionsSignaled(expectedPresentTime)) {
         mFlinger->setTransactionFlags(eTraversalNeeded);
         return false;
     }
 
-    status_t err = updateTexImage(recomputeVisibleRegions, latchTime);
+    status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime);
     if (err != NO_ERROR) {
         return false;
     }
@@ -540,10 +472,10 @@
 }
 
 // transaction
-void BufferLayer::notifyAvailableFrames() {
-    const auto headFrameNumber = getHeadFrameNumber();
+void BufferLayer::notifyAvailableFrames(nsecs_t expectedPresentTime) {
+    const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime);
     const bool headFenceSignaled = fenceHasSignaled();
-    const bool presentTimeIsCurrent = framePresentTimeIsCurrent();
+    const bool presentTimeIsCurrent = framePresentTimeIsCurrent(expectedPresentTime);
     Mutex::Autolock lock(mLocalSyncPointMutex);
     for (auto& point : mLocalSyncPoints) {
         if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled &&
@@ -591,8 +523,8 @@
 }
 
 // h/w composer set-up
-bool BufferLayer::allTransactionsSignaled() {
-    auto headFrameNumber = getHeadFrameNumber();
+bool BufferLayer::allTransactionsSignaled(nsecs_t expectedPresentTime) {
+    const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime);
     bool matchingFramesFound = false;
     bool allTransactionsApplied = true;
     Mutex::Autolock lock(mLocalSyncPointMutex);
@@ -658,9 +590,9 @@
             sourceCrop.getWidth() != displayFrame.getWidth();
 }
 
-uint64_t BufferLayer::getHeadFrameNumber() const {
+uint64_t BufferLayer::getHeadFrameNumber(nsecs_t expectedPresentTime) const {
     if (hasFrameUpdate()) {
-        return getFrameNumber();
+        return getFrameNumber(expectedPresentTime);
     } else {
         return mCurrentFrameNumber;
     }
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index b679380..bb0205d 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -82,10 +82,6 @@
 
     bool isHdrY410() const override;
 
-    void setPerFrameData(const sp<const DisplayDevice>& display, const ui::Transform& transform,
-                         const Rect& viewport, int32_t supportedPerFrameMetadata,
-                         const ui::Dataspace targetDataspace) override;
-
     bool onPreComposition(nsecs_t refreshStartTime) override;
     bool onPostComposition(const std::optional<DisplayId>& displayId,
                            const std::shared_ptr<FenceTime>& glDoneFence,
@@ -96,11 +92,12 @@
     // the visible regions need to be recomputed (this is a fairly heavy
     // operation, so this should be set only if needed). Typically this is used
     // to figure out if the content or size of a surface has changed.
-    bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+    bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+                     nsecs_t expectedPresentTime) override;
 
     bool isBufferLatched() const override { return mRefreshPending; }
 
-    void notifyAvailableFrames() override;
+    void notifyAvailableFrames(nsecs_t expectedPresentTime) override;
 
     bool hasReadyFrame() const override;
 
@@ -114,7 +111,7 @@
     // -----------------------------------------------------------------------
 private:
     virtual bool fenceHasSignaled() const = 0;
-    virtual bool framePresentTimeIsCurrent() const = 0;
+    virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0;
 
     virtual nsecs_t getDesiredPresentTime() = 0;
     virtual std::shared_ptr<FenceTime> getCurrentFenceTime() const = 0;
@@ -129,7 +126,7 @@
     virtual int getDrawingApi() const = 0;
     virtual PixelFormat getPixelFormat() const = 0;
 
-    virtual uint64_t getFrameNumber() const = 0;
+    virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0;
 
     virtual bool getAutoRefresh() const = 0;
     virtual bool getSidebandStreamChanged() const = 0;
@@ -142,21 +139,22 @@
     virtual void setFilteringEnabled(bool enabled) = 0;
 
     virtual status_t bindTextureImage() = 0;
-    virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0;
+    virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+                                    nsecs_t expectedPresentTime) = 0;
 
     virtual status_t updateActiveBuffer() = 0;
     virtual status_t updateFrameNumber(nsecs_t latchTime) = 0;
 
-    virtual void setHwcLayerBuffer(const sp<const DisplayDevice>& displayDevice) = 0;
-
 protected:
+    void latchPerFrameState(compositionengine::LayerFECompositionState& outState) const override;
+
     // Loads the corresponding system property once per process
     static bool latchUnsignaledBuffers();
 
     // Check all of the local sync points to ensure that all transactions
     // which need to have been applied prior to the frame which is about to
     // be latched have signaled
-    bool allTransactionsSignaled();
+    bool allTransactionsSignaled(nsecs_t expectedPresentTime);
 
     static bool getOpacityForFormat(uint32_t format);
 
@@ -175,7 +173,7 @@
     // Returns true if this layer requires filtering
     bool needsFiltering(const sp<const DisplayDevice>& displayDevice) const;
 
-    uint64_t getHeadFrameNumber() const;
+    uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
 
     uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE};
 
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index bd9bd81..5e994b7 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -428,30 +428,6 @@
     return mCurrentFenceTime;
 }
 
-status_t BufferLayerConsumer::doFenceWaitLocked() const {
-    if (mCurrentFence->isValid()) {
-        if (mRE.useWaitSync()) {
-            base::unique_fd fenceFd(mCurrentFence->dup());
-            if (fenceFd == -1) {
-                BLC_LOGE("doFenceWait: error dup'ing fence fd: %d", errno);
-                return -errno;
-            }
-            if (!mRE.waitFence(std::move(fenceFd))) {
-                BLC_LOGE("doFenceWait: failed to wait on fence fd");
-                return UNKNOWN_ERROR;
-            }
-        } else {
-            status_t err = mCurrentFence->waitForever("BufferLayerConsumer::doFenceWaitLocked");
-            if (err != NO_ERROR) {
-                BLC_LOGE("doFenceWait: error waiting for fence: %d", err);
-                return err;
-            }
-        }
-    }
-
-    return NO_ERROR;
-}
-
 void BufferLayerConsumer::freeBufferLocked(int slotIndex) {
     BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
     std::lock_guard<std::mutex> lock(mImagesMutex);
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index 901556a..8536f6b 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -255,11 +255,6 @@
     // mCurrentTextureImage must not be nullptr.
     void computeCurrentTransformMatrixLocked();
 
-    // doFenceWaitLocked inserts a wait command into the RenderEngine command
-    // stream to ensure that it is safe for future RenderEngine commands to
-    // access the current texture buffer.
-    status_t doFenceWaitLocked() const;
-
     // getCurrentCropLocked returns the cropping rectangle of the current buffer.
     Rect getCurrentCropLocked() const;
 
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index f35a4fd..12be00f 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -137,13 +137,13 @@
     return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
 }
 
-bool BufferQueueLayer::framePresentTimeIsCurrent() const {
+bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const {
     if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
         return true;
     }
 
     Mutex::Autolock lock(mQueueItemLock);
-    return mQueueItems[0].mTimestamp <= mFlinger->getExpectedPresentTime();
+    return mQueueItems[0].mTimestamp <= expectedPresentTime;
 }
 
 nsecs_t BufferQueueLayer::getDesiredPresentTime() {
@@ -196,13 +196,11 @@
     return mFormat;
 }
 
-uint64_t BufferQueueLayer::getFrameNumber() const {
+uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const {
     Mutex::Autolock lock(mQueueItemLock);
     uint64_t frameNumber = mQueueItems[0].mFrameNumber;
 
     // The head of the queue will be dropped if there are signaled and timely frames behind it
-    nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime();
-
     if (isRemovedFromCurrentState()) {
         expectedPresentTime = 0;
     }
@@ -268,7 +266,8 @@
     return mConsumer->bindTextureImage();
 }
 
-status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+                                          nsecs_t expectedPresentTime) {
     // 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 shared
@@ -279,8 +278,6 @@
                     getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
                     getTransformToDisplayInverse(), mFreezeGeometryUpdates);
 
-    nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime();
-
     if (isRemovedFromCurrentState()) {
         expectedPresentTime = 0;
     }
@@ -379,7 +376,6 @@
     mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence);
     auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
     layerCompositionState.buffer = mActiveBuffer;
-    layerCompositionState.bufferSlot = mActiveBufferSlot;
 
     if (mActiveBuffer == nullptr) {
         // this can only happen if the very first buffer was rejected.
@@ -399,32 +395,17 @@
     return NO_ERROR;
 }
 
-void BufferQueueLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) {
-    const auto outputLayer = findOutputLayerForDisplay(display);
-    LOG_FATAL_IF(!outputLayer);
-    LOG_FATAL_IF(!outputLayer->getState.hwc);
-    auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
-
-    uint32_t hwcSlot = 0;
-    sp<GraphicBuffer> hwcBuffer;
-
-    // INVALID_BUFFER_SLOT is used to identify BufferStateLayers.  Default to 0
-    // for BufferQueueLayers
-    int slot = (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot;
-    (*outputLayer->editState().hwc)
-            .hwcBufferCache.getHwcBuffer(slot, mActiveBuffer, &hwcSlot, &hwcBuffer);
-
-    auto acquireFence = mConsumer->getCurrentFence();
-    auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), mActiveBuffer->handle,
-              to_string(error).c_str(), static_cast<int32_t>(error));
+void BufferQueueLayer::latchPerFrameState(
+        compositionengine::LayerFECompositionState& compositionState) const {
+    BufferLayer::latchPerFrameState(compositionState);
+    if (compositionState.compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) {
+        return;
     }
 
-    auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
-    layerCompositionState.bufferSlot = mActiveBufferSlot;
-    layerCompositionState.buffer = mActiveBuffer;
-    layerCompositionState.acquireFence = acquireFence;
+    compositionState.buffer = mActiveBuffer;
+    compositionState.bufferSlot =
+            (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot;
+    compositionState.acquireFence = mConsumer->getCurrentFence();
 }
 
 // -----------------------------------------------------------------------
@@ -434,7 +415,7 @@
 void BufferQueueLayer::fakeVsync() {
     mRefreshPending = false;
     bool ignored = false;
-    latchBuffer(ignored, systemTime());
+    latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */);
     usleep(16000);
     releasePendingBuffer(systemTime());
 }
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 7def33a..231a531 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -61,7 +61,7 @@
     // -----------------------------------------------------------------------
 public:
     bool fenceHasSignaled() const override;
-    bool framePresentTimeIsCurrent() const override;
+    bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override;
 
 private:
     nsecs_t getDesiredPresentTime() override;
@@ -77,7 +77,7 @@
     int getDrawingApi() const override;
     PixelFormat getPixelFormat() const override;
 
-    uint64_t getFrameNumber() const override;
+    uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
 
     bool getAutoRefresh() const override;
     bool getSidebandStreamChanged() const override;
@@ -89,12 +89,13 @@
     void setFilteringEnabled(bool enabled) override;
 
     status_t bindTextureImage() override;
-    status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+    status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+                            nsecs_t expectedPresentTime) override;
 
     status_t updateActiveBuffer() override;
     status_t updateFrameNumber(nsecs_t latchTime) override;
 
-    void setHwcLayerBuffer(const sp<const DisplayDevice>& displayDevice) override;
+    void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
 
     // -----------------------------------------------------------------------
     // Interface implementation for BufferLayerConsumer::ContentsChangedListener
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 2abc1a7..0f26211 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -85,7 +85,7 @@
 }
 
 void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) {
-    mFlinger->getTransactionCompletedThread().addPresentedCallbackHandles(
+    mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
             mDrawingState.callbackHandles);
 
     mDrawingState.callbackHandles = {};
@@ -216,7 +216,7 @@
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
-    mFlinger->mTimeStats->setPostTime(getSequence(), getFrameNumber(), getName().c_str(), postTime);
+    mFlinger->mTimeStats->setPostTime(getSequence(), mFrameNumber, getName().c_str(), postTime);
     mDesiredPresentTime = desiredPresentTime;
 
     if (mFlinger->mUseSmart90ForVideo) {
@@ -310,7 +310,7 @@
 
         } else { // If this layer will NOT need to be relatched and presented this frame
             // Notify the transaction completed thread this handle is done
-            mFlinger->getTransactionCompletedThread().addUnpresentedCallbackHandle(handle);
+            mFlinger->getTransactionCompletedThread().registerUnpresentedCallbackHandle(handle);
         }
     }
 
@@ -369,12 +369,12 @@
     return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
 }
 
-bool BufferStateLayer::framePresentTimeIsCurrent() const {
+bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const {
     if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
         return true;
     }
 
-    return mDesiredPresentTime <= mFlinger->getExpectedPresentTime();
+    return mDesiredPresentTime <= expectedPresentTime;
 }
 
 nsecs_t BufferStateLayer::getDesiredPresentTime() {
@@ -446,7 +446,7 @@
     return mActiveBuffer->format;
 }
 
-uint64_t BufferStateLayer::getFrameNumber() const {
+uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const {
     return mFrameNumber;
 }
 
@@ -494,7 +494,8 @@
     return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence);
 }
 
-status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) {
+status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
+                                          nsecs_t /*expectedPresentTime*/) {
     const State& s(getDrawingState());
 
     if (!s.buffer) {
@@ -528,7 +529,7 @@
         ALOGE("[%s] rejecting buffer: "
               "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}",
               mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h);
-        mFlinger->mTimeStats->removeTimeRecord(layerID, getFrameNumber());
+        mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber);
         return BAD_VALUE;
     }
 
@@ -550,8 +551,8 @@
         }
     }
 
-    mFlinger->mTimeStats->setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime());
-    mFlinger->mTimeStats->setLatchTime(layerID, getFrameNumber(), latchTime);
+    mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime());
+    mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime);
 
     mCurrentStateModified = false;
 
@@ -569,7 +570,6 @@
     mActiveBufferFence = s.acquireFence;
     auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
     layerCompositionState.buffer = mActiveBuffer;
-    layerCompositionState.bufferSlot = 0;
 
     return NO_ERROR;
 }
@@ -580,24 +580,18 @@
     return NO_ERROR;
 }
 
-void BufferStateLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) {
-    const auto outputLayer = findOutputLayerForDisplay(display);
-    LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc);
-    auto& hwcInfo = *outputLayer->editState().hwc;
-    auto& hwcLayer = hwcInfo.hwcLayer;
+void BufferStateLayer::latchPerFrameState(
+        compositionengine::LayerFECompositionState& compositionState) const {
+    BufferLayer::latchPerFrameState(compositionState);
+    if (compositionState.compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) {
+        return;
+    }
 
     const State& s(getDrawingState());
 
-    uint32_t hwcSlot;
-    sp<GraphicBuffer> buffer;
-    hwcInfo.hwcBufferCache.getHwcBuffer(mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId),
-                                        s.buffer, &hwcSlot, &buffer);
-
-    auto error = hwcLayer->setBuffer(hwcSlot, buffer, s.acquireFence);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
-              s.buffer->handle, to_string(error).c_str(), static_cast<int32_t>(error));
-    }
+    compositionState.buffer = s.buffer;
+    compositionState.bufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId);
+    compositionState.acquireFence = s.acquireFence;
 
     mFrameNumber++;
 }
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index db8ae0d..5e5b9b0 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -100,7 +100,7 @@
     // Interface implementation for BufferLayer
     // -----------------------------------------------------------------------
     bool fenceHasSignaled() const override;
-    bool framePresentTimeIsCurrent() const override;
+    bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override;
 
     // Inherit from ClientCache::ErasedRecipient
     void bufferErased(const client_cache_t& clientCacheId) override;
@@ -119,7 +119,7 @@
     int getDrawingApi() const override;
     PixelFormat getPixelFormat() const override;
 
-    uint64_t getFrameNumber() const override;
+    uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
 
     bool getAutoRefresh() const override;
     bool getSidebandStreamChanged() const override;
@@ -131,12 +131,13 @@
     void setFilteringEnabled(bool enabled) override;
 
     status_t bindTextureImage() override;
-    status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+    status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+                            nsecs_t expectedPresentTime) override;
 
     status_t updateActiveBuffer() override;
     status_t updateFrameNumber(nsecs_t latchTime) override;
 
-    void setHwcLayerBuffer(const sp<const DisplayDevice>& display) override;
+    void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
 
 private:
     friend class SlotGenerationTest;
@@ -151,11 +152,11 @@
 
     std::atomic<bool> mSidebandStreamChanged{false};
 
-    uint32_t mFrameNumber{0};
+    mutable uint32_t mFrameNumber{0};
 
     sp<Fence> mPreviousReleaseFence;
 
-    bool mCurrentStateModified = false;
+    mutable bool mCurrentStateModified = false;
     bool mReleasePreviousBuffer = false;
     nsecs_t mCallbackHandleAcquireTime = -1;
 
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index fcc2d97..f15957a 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -18,6 +18,8 @@
 #undef LOG_TAG
 #define LOG_TAG "ColorLayer"
 
+#include "ColorLayer.h"
+
 #include <stdint.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -26,6 +28,7 @@
 #include <compositionengine/Display.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/LayerCreationArgs.h>
+#include <compositionengine/LayerFECompositionState.h>
 #include <compositionengine/OutputLayer.h>
 #include <compositionengine/impl/LayerCompositionState.h>
 #include <compositionengine/impl/OutputLayerCompositionState.h>
@@ -34,7 +37,6 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
-#include "ColorLayer.h"
 #include "DisplayDevice.h"
 #include "SurfaceFlinger.h"
 
@@ -91,75 +93,12 @@
     return true;
 }
 
-void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& display,
-                                 const ui::Transform& transform, const Rect& viewport,
-                                 int32_t /* supportedPerFrameMetadata */,
-                                 const ui::Dataspace targetDataspace) {
-    RETURN_IF_NO_HWC_LAYER(display);
+void ColorLayer::latchPerFrameState(
+        compositionengine::LayerFECompositionState& compositionState) const {
+    Layer::latchPerFrameState(compositionState);
 
-    Region visible = transform.transform(visibleRegion.intersect(viewport));
-
-    const auto outputLayer = findOutputLayerForDisplay(display);
-    LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc);
-
-    auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
-
-    auto error = hwcLayer->setVisibleRegion(visible);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
-              to_string(error).c_str(), static_cast<int32_t>(error));
-        visible.dump(LOG_TAG);
-    }
-    outputLayer->editState().visibleRegion = visible;
-
-    setCompositionType(display, Hwc2::IComposerClient::Composition::SOLID_COLOR);
-
-    const ui::Dataspace dataspace =
-            isColorSpaceAgnostic() && targetDataspace != ui::Dataspace::UNKNOWN ? targetDataspace
-                                                                                : mCurrentDataSpace;
-    error = hwcLayer->setDataspace(dataspace);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), dataspace,
-              to_string(error).c_str(), static_cast<int32_t>(error));
-    }
-
-    auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
-    layerCompositionState.dataspace = mCurrentDataSpace;
-
-    half4 color = getColor();
-    error = hwcLayer->setColor({static_cast<uint8_t>(std::round(255.0f * color.r)),
-                                static_cast<uint8_t>(std::round(255.0f * color.g)),
-                                static_cast<uint8_t>(std::round(255.0f * color.b)), 255});
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(),
-              static_cast<int32_t>(error));
-    }
-    layerCompositionState.color = {static_cast<uint8_t>(std::round(255.0f * color.r)),
-                                   static_cast<uint8_t>(std::round(255.0f * color.g)),
-                                   static_cast<uint8_t>(std::round(255.0f * color.b)), 255};
-
-    // Clear out the transform, because it doesn't make sense absent a source buffer
-    error = hwcLayer->setTransform(HWC2::Transform::None);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), to_string(error).c_str(),
-              static_cast<int32_t>(error));
-    }
-    outputLayer->editState().bufferTransform = static_cast<Hwc2::Transform>(0);
-
-    error = hwcLayer->setColorTransform(getColorTransform());
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(),
-                to_string(error).c_str(), static_cast<int32_t>(error));
-    }
-    layerCompositionState.colorTransform = getColorTransform();
-
-    error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
-    if (error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(),
-              to_string(error).c_str(), static_cast<int32_t>(error));
-        surfaceDamageRegion.dump(LOG_TAG);
-    }
-    layerCompositionState.surfaceDamage = surfaceDamageRegion;
+    compositionState.color = getColor();
+    compositionState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
 }
 
 void ColorLayer::commitTransaction(const State& stateToCommit) {
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index 53d5b5b..2483ff0 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -37,10 +37,6 @@
 
     bool setDataspace(ui::Dataspace dataspace) override;
 
-    void setPerFrameData(const sp<const DisplayDevice>& display, const ui::Transform& transform,
-                         const Rect& viewport, int32_t supportedPerFrameMetadata,
-                         const ui::Dataspace targetDataspace) override;
-
     void commitTransaction(const State& stateToCommit) override;
 
     bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; }
@@ -52,6 +48,8 @@
                                     renderengine::LayerSettings& layer);
 
 private:
+    void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
+
     std::shared_ptr<compositionengine::Layer> mCompositionLayer;
 };
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
index 896f8aa..31d6365 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
@@ -18,6 +18,8 @@
 
 #include <memory>
 
+#include <utils/Timers.h>
+
 namespace android {
 
 class HWComposer;
@@ -31,6 +33,7 @@
 class Display;
 class Layer;
 
+struct CompositionRefreshArgs;
 struct DisplayCreationArgs;
 struct LayerCreationArgs;
 
@@ -51,6 +54,12 @@
 
     virtual renderengine::RenderEngine& getRenderEngine() const = 0;
     virtual void setRenderEngine(std::unique_ptr<renderengine::RenderEngine>) = 0;
+
+    virtual bool needsAnotherUpdate() const = 0;
+    virtual nsecs_t getLastFrameRefreshTimestamp() const = 0;
+
+    // TODO(b/121291683): These will become private/internal
+    virtual void preComposition(CompositionRefreshArgs&) = 0;
 };
 
 } // namespace compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
new file mode 100644
index 0000000..20f131e
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include <compositionengine/Display.h>
+#include <compositionengine/Layer.h>
+
+namespace android::compositionengine {
+
+using Layers = std::vector<std::shared_ptr<compositionengine::Layer>>;
+using Outputs = std::vector<std::shared_ptr<compositionengine::Output>>;
+
+/**
+ * A parameter object for refreshing a set of outputs
+ */
+struct CompositionRefreshArgs {
+    // All the outputs being refreshed
+    Outputs outputs;
+
+    // All the layers that are potentially visible in the outputs. The order of
+    // the layers is important, and should be in traversal order from back to
+    // front.
+    Layers layers;
+};
+
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h
index e2a0d42..d93bfa3 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <cstdint>
+#include <string>
 
 #include <ui/GraphicTypes.h>
 
@@ -75,6 +76,13 @@
     // Gets the supported HDR capabilities for the profile
     virtual const HdrCapabilities& getHdrCapabilities() const = 0;
 
+    // Returns true if HWC for this profile supports the dataspace
+    virtual bool isDataspaceSupported(ui::Dataspace) const = 0;
+
+    // Returns the target dataspace for picked color mode and dataspace
+    virtual ui::Dataspace getTargetDataspace(ui::ColorMode, ui::Dataspace,
+                                             ui::Dataspace colorSpaceAgnosticDataspace) const = 0;
+
     // Debugging
     virtual void dump(std::string&) const = 0;
 };
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h
index 8cb9203..451608b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h
@@ -21,11 +21,7 @@
 
 #include <utils/StrongPointer.h>
 
-namespace android {
-
-typedef int64_t nsecs_t;
-
-namespace compositionengine {
+namespace android::compositionengine {
 
 class Display;
 class LayerFE;
@@ -62,5 +58,4 @@
     virtual void dump(std::string& result) const = 0;
 };
 
-} // namespace compositionengine
-} // namespace android
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
index 9f635b9..1f2cae9 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <utils/RefBase.h>
+#include <utils/Timers.h>
 
 namespace android {
 
@@ -30,6 +31,11 @@
 // of the front-end layer
 class LayerFE : public virtual RefBase {
 public:
+    // Called before composition starts. Should return true if this layer has
+    // pending updates which would require an extra display refresh cycle to
+    // process.
+    virtual bool onPreComposition(nsecs_t refreshStartTime) = 0;
+
     // Latches the output-independent state. If includeGeometry is false, the
     // geometry state can be skipped.
     virtual void latchCompositionState(LayerFECompositionState&, bool includeGeometry) const = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index e6ee078..d96d58c 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -36,9 +36,9 @@
  * Used by LayerFE::getCompositionState
  */
 struct LayerFECompositionState {
-    // TODO(lpique): b/121291683 Remove this one we are sure we don't need the
-    // value recomputed / set every frame.
-    Region geomVisibleRegion;
+    // If set to true, forces client composition on all output layers until
+    // the next geometry change.
+    bool forceClientComposition{false};
 
     /*
      * Geometry state
@@ -56,6 +56,10 @@
     Region geomActiveTransparentRegion;
     FloatRect geomLayerBounds;
 
+    // TODO(lpique): b/121291683 Remove this one we are sure we don't need the
+    // value recomputed / set every frame.
+    Region geomVisibleRegion;
+
     /*
      * Presentation
      */
@@ -93,12 +97,16 @@
     sp<NativeHandle> sidebandStream;
 
     // The color for this layer
-    Hwc2::IComposerClient::Color color;
+    half4 color;
 
     /*
      * Per-frame presentation state
      */
 
+    // If true, this layer will use the dataspace chosen for the output and
+    // ignore the dataspace value just below
+    bool isColorspaceAgnostic{false};
+
     // The dataspace for this layer
     ui::Dataspace dataspace{ui::Dataspace::UNKNOWN};
 
@@ -107,6 +115,7 @@
 
     // The color transform
     mat4 colorTransform;
+    bool colorTransformIsIdentity{true};
 };
 
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 54e6bd6..ebfda1f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -19,8 +19,10 @@
 #include <cstdint>
 #include <optional>
 #include <string>
+#include <unordered_map>
 
 #include <math/mat4.h>
+#include <ui/Fence.h>
 #include <ui/GraphicTypes.h>
 #include <ui/Region.h>
 #include <ui/Transform.h>
@@ -28,6 +30,10 @@
 
 #include "DisplayHardware/DisplayIdentification.h"
 
+namespace HWC2 {
+class Layer;
+} // namespace HWC2
+
 namespace android::compositionengine {
 
 class DisplayColorProfile;
@@ -46,6 +52,13 @@
 class Output {
 public:
     using OutputLayers = std::vector<std::unique_ptr<compositionengine::OutputLayer>>;
+    using ReleasedLayers = std::vector<wp<LayerFE>>;
+
+    struct FrameFences {
+        sp<Fence> presentFence{Fence::NO_FENCE};
+        sp<Fence> clientTargetAcquireFence{Fence::NO_FENCE};
+        std::unordered_map<HWC2::Layer*, sp<Fence>> layerFences;
+    };
 
     virtual ~Output();
 
@@ -71,7 +84,8 @@
     virtual void setColorTransform(const mat4&) = 0;
 
     // Sets the output color mode
-    virtual void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent) = 0;
+    virtual void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent,
+                              ui::Dataspace colorSpaceAgnosticDataspace) = 0;
 
     // Outputs a string with a state dump
     virtual void dump(std::string&) const = 0;
@@ -130,9 +144,23 @@
     // Gets the ordered set of output layers for this output
     virtual const OutputLayers& getOutputLayersOrderedByZ() const = 0;
 
+    // Sets the new set of layers being released this frame
+    virtual void setReleasedLayers(ReleasedLayers&&) = 0;
+
+    // Takes (moves) the set of layers being released this frame.
+    virtual ReleasedLayers takeReleasedLayers() = 0;
+
+    // Prepares a frame for display
+    virtual void prepareFrame() = 0;
+
+    // Posts the new frame, and sets release fences.
+    virtual void postFramebuffer() = 0;
+
 protected:
     virtual void setDisplayColorProfile(std::unique_ptr<DisplayColorProfile>) = 0;
     virtual void setRenderSurface(std::unique_ptr<RenderSurface>) = 0;
+    virtual void chooseCompositionStrategy() = 0;
+    virtual FrameFences presentAndGetFrameFences() = 0;
 };
 
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index cd63b57..d7f00a9 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -21,8 +21,13 @@
 
 #include <utils/StrongPointer.h>
 
+#include "DisplayHardware/ComposerHal.h"
 #include "DisplayHardware/DisplayIdentification.h"
 
+namespace HWC2 {
+class Layer;
+} // namespace HWC2
+
 namespace android {
 
 namespace compositionengine {
@@ -71,7 +76,22 @@
     // Writes the geometry state to the HWC, or does nothing if this layer does
     // not use the HWC. If includeGeometry is false, the geometry state can be
     // skipped.
-    virtual void writeStateToHWC(bool includeGeometry) const = 0;
+    virtual void writeStateToHWC(bool includeGeometry) = 0;
+
+    // Returns the HWC2::Layer associated with this layer, if it exists
+    virtual HWC2::Layer* getHwcLayer() const = 0;
+
+    // Returns true if the current layer state requires client composition
+    virtual bool requiresClientComposition() const = 0;
+
+    // Applies a HWC device requested composition type change
+    virtual void applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition) = 0;
+
+    // Prepares to apply any HWC device layer requests
+    virtual void prepareForDeviceLayerRequests() = 0;
+
+    // Applies a HWC device layer request
+    virtual void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) = 0;
 
     // Debugging
     virtual void dump(std::string& result) const = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index e21128c..6859846 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -71,7 +71,7 @@
     virtual status_t beginFrame(bool mustRecompose) = 0;
 
     // Prepares the frame for rendering
-    virtual status_t prepareFrame() = 0;
+    virtual void prepareFrame(bool usesClientComposition, bool usesDeviceComposition) = 0;
 
     // Allocates a buffer as scratch space for GPU composition
     virtual sp<GraphicBuffer> dequeueBuffer(base::unique_fd* bufferFence) = 0;
@@ -83,10 +83,6 @@
     // Called after the HWC calls are made to present the display
     virtual void onPresentDisplayCompleted() = 0;
 
-    // Called to set the viewport and projection state for rendering into this
-    // surface
-    virtual void setViewportAndProjection() = 0;
-
     // Called after the surface has been rendering to signal the surface should
     // be made ready for displaying
     virtual void flip() = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
index b01eb64..96e609d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
@@ -36,9 +36,19 @@
     renderengine::RenderEngine& getRenderEngine() const override;
     void setRenderEngine(std::unique_ptr<renderengine::RenderEngine>) override;
 
+    bool needsAnotherUpdate() const override;
+    nsecs_t getLastFrameRefreshTimestamp() const override;
+
+    void preComposition(CompositionRefreshArgs&) override;
+
+    // Testing
+    void setNeedsAnotherUpdateForTest(bool);
+
 private:
     std::unique_ptr<HWComposer> mHwComposer;
     std::unique_ptr<renderengine::RenderEngine> mRenderEngine;
+    bool mNeedsAnotherUpdate = false;
+    nsecs_t mRefreshStartTime = 0;
 };
 
 std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine();
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index 0e20c43..795061a 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -16,12 +16,13 @@
 
 #pragma once
 
-#include <memory>
-
 #include <compositionengine/Display.h>
 #include <compositionengine/impl/Output.h>
 
+#include <memory>
+
 #include "DisplayHardware/DisplayIdentification.h"
+#include "DisplayHardware/HWComposer.h"
 
 namespace android::compositionengine {
 
@@ -39,7 +40,9 @@
     // compositionengine::Output overrides
     void dump(std::string&) const override;
     void setColorTransform(const mat4&) override;
-    void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent) override;
+    void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace) override;
+    void chooseCompositionStrategy() override;
+    compositionengine::Output::FrameFences presentAndGetFrameFences() override;
 
     // compositionengine::Display overrides
     const std::optional<DisplayId>& getId() const override;
@@ -49,12 +52,22 @@
     void createDisplayColorProfile(compositionengine::DisplayColorProfileCreationArgs&&) override;
     void createRenderSurface(compositionengine::RenderSurfaceCreationArgs&&) override;
 
+    // Internal helpers used by chooseCompositionStrategy()
+    using ChangedTypes = android::HWComposer::DeviceRequestedChanges::ChangedTypes;
+    using DisplayRequests = android::HWComposer::DeviceRequestedChanges::DisplayRequests;
+    using LayerRequests = android::HWComposer::DeviceRequestedChanges::LayerRequests;
+    virtual bool anyLayersRequireClientComposition() const;
+    virtual bool allLayersRequireClientComposition() const;
+    virtual void applyChangedTypesToLayers(const ChangedTypes&);
+    virtual void applyDisplayRequests(const DisplayRequests&);
+    virtual void applyLayerRequestsToLayers(const LayerRequests&);
+
 private:
     const bool mIsVirtual;
     std::optional<DisplayId> mId;
 };
 
-std::shared_ptr<compositionengine::Display> createDisplay(
-        const compositionengine::CompositionEngine&, compositionengine::DisplayCreationArgs&&);
+std::shared_ptr<Display> createDisplay(const compositionengine::CompositionEngine&,
+                                       compositionengine::DisplayCreationArgs&&);
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h
index 49c2d2c..e84a36e 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h
@@ -54,6 +54,8 @@
     bool hasDolbyVisionSupport() const override;
 
     const HdrCapabilities& getHdrCapabilities() const override;
+    bool isDataspaceSupported(ui::Dataspace) const override;
+    ui::Dataspace getTargetDataspace(ui::ColorMode, ui::Dataspace, ui::Dataspace) const override;
 
     void dump(std::string&) const override;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index b1d1f42..b454212 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -45,7 +45,7 @@
     void setLayerStackFilter(uint32_t layerStackId, bool isInternal) override;
 
     void setColorTransform(const mat4&) override;
-    void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent) override;
+    void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace) override;
 
     void dump(std::string&) const override;
 
@@ -72,12 +72,20 @@
     void setOutputLayersOrderedByZ(OutputLayers&&) override;
     const OutputLayers& getOutputLayersOrderedByZ() const override;
 
+    void setReleasedLayers(ReleasedLayers&&) override;
+    ReleasedLayers takeReleasedLayers() override;
+
+    void prepareFrame() override;
+    void postFramebuffer() override;
+
     // Testing
     void setDisplayColorProfileForTest(std::unique_ptr<compositionengine::DisplayColorProfile>);
     void setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface>);
 
 protected:
     const CompositionEngine& getCompositionEngine() const;
+    void chooseCompositionStrategy() override;
+    compositionengine::Output::FrameFences presentAndGetFrameFences() override;
     void dumpBase(std::string&) const;
 
 private:
@@ -93,6 +101,7 @@
     std::unique_ptr<compositionengine::RenderSurface> mRenderSurface;
 
     OutputLayers mOutputLayersOrderedByZ;
+    ReleasedLayers mReleasedLayers;
 };
 
 } // namespace impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index 0c47eb5..1078f11 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -35,6 +35,16 @@
     // If false, this output is not considered secure
     bool isSecure{false};
 
+    // If true, the current frame on this output uses client composition
+    bool usesClientComposition{false};
+
+    // If true, the current frame on this output uses device composition
+    bool usesDeviceComposition{false};
+
+    // If true, the client target should be flipped when performing client
+    // composition
+    bool flipClientTarget{false};
+
     // If true, this output displays layers that are internal-only
     bool layerStackInternal{false};
 
@@ -88,9 +98,12 @@
     // Current active render intent
     ui::RenderIntent renderIntent{ui::RenderIntent::COLORIMETRIC};
 
-    // Current active dstaspace
+    // Current active dataspace
     ui::Dataspace dataspace{ui::Dataspace::UNKNOWN};
 
+    // Current target dataspace
+    ui::Dataspace targetDataspace{ui::Dataspace::UNKNOWN};
+
     // Debugging
     void dump(std::string& result) const;
 };
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index 6a4818f..d8ad02a 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -26,7 +26,11 @@
 
 #include "DisplayHardware/DisplayIdentification.h"
 
-namespace android::compositionengine::impl {
+namespace android::compositionengine {
+
+struct LayerFECompositionState;
+
+namespace impl {
 
 class OutputLayer : public compositionengine::OutputLayer {
 public:
@@ -44,7 +48,13 @@
     OutputLayerCompositionState& editState() override;
 
     void updateCompositionState(bool) override;
-    void writeStateToHWC(bool) const override;
+    void writeStateToHWC(bool) override;
+
+    HWC2::Layer* getHwcLayer() const override;
+    bool requiresClientComposition() const override;
+    void applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition) override;
+    void prepareForDeviceLayerRequests() override;
+    void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) override;
 
     void dump(std::string& result) const override;
 
@@ -54,6 +64,16 @@
 
 private:
     Rect calculateInitialCrop() const;
+    void writeOutputDependentGeometryStateToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition);
+    void writeOutputIndependentGeometryStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
+    void writeOutputDependentPerFrameStateToHWC(HWC2::Layer*);
+    void writeOutputIndependentPerFrameStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
+    void writeSolidColorStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
+    void writeSidebandStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
+    void writeBufferStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
+    void writeCompositionTypeToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition);
+    void detectDisallowedCompositionTypeChange(Hwc2::IComposerClient::Composition from,
+                                               Hwc2::IComposerClient::Composition to) const;
 
     const compositionengine::Output& mOutput;
     std::shared_ptr<compositionengine::Layer> mLayer;
@@ -66,4 +86,5 @@
         const CompositionEngine&, std::optional<DisplayId>, const compositionengine::Output&,
         std::shared_ptr<compositionengine::Layer>, sp<compositionengine::LayerFE>);
 
-} // namespace android::compositionengine::impl
+} // namespace impl
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index b78e9e0..de0f08a 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -23,6 +23,7 @@
 #include <compositionengine/impl/HwcBufferCache.h>
 #include <renderengine/Mesh.h>
 #include <ui/FloatRect.h>
+#include <ui/GraphicTypes.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
 
@@ -57,6 +58,9 @@
     // The buffer transform to use for this layer o on this output.
     Hwc2::Transform bufferTransform{static_cast<Hwc2::Transform>(0)};
 
+    // The dataspace for this layer
+    ui::Dataspace dataspace{ui::Dataspace::UNKNOWN};
+
     // The Z order index of this layer on this output
     uint32_t z;
 
@@ -70,7 +74,7 @@
         // The HWC Layer backing this layer
         std::shared_ptr<HWC2::Layer> hwcLayer;
 
-        // The HWC composition type for this layer
+        // The most recently set HWC composition type for this layer
         Hwc2::IComposerClient::Composition hwcCompositionType{
                 Hwc2::IComposerClient::Composition::INVALID};
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index 0f57315..0a04462 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -52,11 +52,10 @@
     void setDisplaySize(const ui::Size&) override;
     void setProtected(bool useProtected) override;
     status_t beginFrame(bool mustRecompose) override;
-    status_t prepareFrame() override;
+    void prepareFrame(bool usesClientComposition, bool usesDeviceComposition) override;
     sp<GraphicBuffer> dequeueBuffer(base::unique_fd* bufferFence) override;
     void queueBuffer(base::unique_fd&& readyFence) override;
     void onPresentDisplayCompleted() override;
-    void setViewportAndProjection() override;
     void flip() override;
 
     // Debugging
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
index 0f57685..82ecec5 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <compositionengine/CompositionEngine.h>
+#include <compositionengine/CompositionRefreshArgs.h>
 #include <compositionengine/DisplayCreationArgs.h>
 #include <compositionengine/LayerCreationArgs.h>
 #include <gmock/gmock.h>
@@ -39,6 +40,11 @@
 
     MOCK_CONST_METHOD0(getRenderEngine, renderengine::RenderEngine&());
     MOCK_METHOD1(setRenderEngine, void(std::unique_ptr<renderengine::RenderEngine>));
+
+    MOCK_CONST_METHOD0(needsAnotherUpdate, bool());
+    MOCK_CONST_METHOD0(getLastFrameRefreshTimestamp, nsecs_t());
+
+    MOCK_METHOD1(preComposition, void(CompositionRefreshArgs&));
 };
 
 } // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplayColorProfile.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplayColorProfile.h
index 8056c9d..1aaebea 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplayColorProfile.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplayColorProfile.h
@@ -42,6 +42,9 @@
     MOCK_CONST_METHOD0(hasDolbyVisionSupport, bool());
 
     MOCK_CONST_METHOD0(getHdrCapabilities, const HdrCapabilities&());
+    MOCK_CONST_METHOD1(isDataspaceSupported, bool(ui::Dataspace));
+    MOCK_CONST_METHOD3(getTargetDataspace,
+                       ui::Dataspace(ui::ColorMode, ui::Dataspace, ui::Dataspace));
 
     MOCK_CONST_METHOD1(dump, void(std::string&));
 };
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
index aab18db..952f702 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
@@ -30,6 +30,8 @@
     LayerFE();
     virtual ~LayerFE();
 
+    MOCK_METHOD1(onPreComposition, bool(nsecs_t));
+
     MOCK_CONST_METHOD2(latchCompositionState, void(LayerFECompositionState&, bool));
     MOCK_METHOD1(onLayerDisplayed, void(const sp<Fence>&));
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index d0e7b19..8aaebc2 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -41,17 +41,18 @@
     MOCK_METHOD2(setLayerStackFilter, void(uint32_t, bool));
 
     MOCK_METHOD1(setColorTransform, void(const mat4&));
-    MOCK_METHOD3(setColorMode, void(ui::ColorMode, ui::Dataspace, ui::RenderIntent));
+    MOCK_METHOD4(setColorMode, void(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace));
 
     MOCK_CONST_METHOD1(dump, void(std::string&));
     MOCK_CONST_METHOD0(getName, const std::string&());
     MOCK_METHOD1(setName, void(const std::string&));
 
-    MOCK_CONST_METHOD0(getDisplayColorProfile, DisplayColorProfile*());
-    MOCK_METHOD1(setDisplayColorProfile, void(std::unique_ptr<DisplayColorProfile>));
+    MOCK_CONST_METHOD0(getDisplayColorProfile, compositionengine::DisplayColorProfile*());
+    MOCK_METHOD1(setDisplayColorProfile,
+                 void(std::unique_ptr<compositionengine::DisplayColorProfile>));
 
-    MOCK_CONST_METHOD0(getRenderSurface, RenderSurface*());
-    MOCK_METHOD1(setRenderSurface, void(std::unique_ptr<RenderSurface>));
+    MOCK_CONST_METHOD0(getRenderSurface, compositionengine::RenderSurface*());
+    MOCK_METHOD1(setRenderSurface, void(std::unique_ptr<compositionengine::RenderSurface>));
 
     MOCK_CONST_METHOD0(getState, const OutputCompositionState&());
     MOCK_METHOD0(editState, OutputCompositionState&());
@@ -65,8 +66,18 @@
                  std::unique_ptr<compositionengine::OutputLayer>(
                          std::optional<DisplayId>, std::shared_ptr<compositionengine::Layer>,
                          sp<compositionengine::LayerFE>));
+
     MOCK_METHOD1(setOutputLayersOrderedByZ, void(OutputLayers&&));
     MOCK_CONST_METHOD0(getOutputLayersOrderedByZ, OutputLayers&());
+
+    MOCK_METHOD1(setReleasedLayers, void(ReleasedLayers&&));
+    MOCK_METHOD0(takeReleasedLayers, ReleasedLayers());
+
+    MOCK_METHOD0(prepareFrame, void());
+    MOCK_METHOD0(chooseCompositionStrategy, void());
+
+    MOCK_METHOD0(postFramebuffer, void());
+    MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences());
 };
 
 } // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index 29cd08a..195648f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -39,7 +39,13 @@
     MOCK_METHOD0(editState, impl::OutputLayerCompositionState&());
 
     MOCK_METHOD1(updateCompositionState, void(bool));
-    MOCK_CONST_METHOD1(writeStateToHWC, void(bool));
+    MOCK_METHOD1(writeStateToHWC, void(bool));
+
+    MOCK_CONST_METHOD0(getHwcLayer, HWC2::Layer*());
+    MOCK_CONST_METHOD0(requiresClientComposition, bool());
+    MOCK_METHOD1(applyDeviceCompositionTypeChange, void(Hwc2::IComposerClient::Composition));
+    MOCK_METHOD0(prepareForDeviceLayerRequests, void());
+    MOCK_METHOD1(applyDeviceLayerRequest, void(Hwc2::IComposerClient::LayerRequest request));
 
     MOCK_CONST_METHOD1(dump, void(std::string&));
 };
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index ca2299a..ba6746a 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -37,11 +37,10 @@
     MOCK_METHOD1(setProtected, void(bool));
     MOCK_METHOD1(setBufferDataspace, void(ui::Dataspace));
     MOCK_METHOD1(beginFrame, status_t(bool mustRecompose));
-    MOCK_METHOD0(prepareFrame, status_t());
+    MOCK_METHOD2(prepareFrame, void(bool, bool));
     MOCK_METHOD1(dequeueBuffer, sp<GraphicBuffer>(base::unique_fd*));
     MOCK_METHOD1(queueBuffer, void(base::unique_fd&&));
     MOCK_METHOD0(onPresentDisplayCompleted, void());
-    MOCK_METHOD0(setViewportAndProjection, void());
     MOCK_METHOD0(flip, void());
     MOCK_CONST_METHOD1(dump, void(std::string& result));
     MOCK_CONST_METHOD0(getPageFlipCount, std::uint32_t());
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index cb08b81..9558266 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
+#include <compositionengine/CompositionRefreshArgs.h>
+#include <compositionengine/LayerFE.h>
 #include <compositionengine/impl/CompositionEngine.h>
 #include <compositionengine/impl/Display.h>
 #include <compositionengine/impl/Layer.h>
 #include <renderengine/RenderEngine.h>
+#include <utils/Trace.h>
 
 #include "DisplayHardware/HWComposer.h"
 
@@ -59,5 +62,35 @@
     mRenderEngine = std::move(renderEngine);
 }
 
+bool CompositionEngine::needsAnotherUpdate() const {
+    return mNeedsAnotherUpdate;
+}
+
+nsecs_t CompositionEngine::getLastFrameRefreshTimestamp() const {
+    return mRefreshStartTime;
+}
+
+void CompositionEngine::preComposition(CompositionRefreshArgs& args) {
+    ATRACE_CALL();
+    ALOGV(__FUNCTION__);
+
+    bool needsAnotherUpdate = false;
+
+    mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
+
+    for (auto& layer : args.layers) {
+        sp<compositionengine::LayerFE> layerFE = layer->getLayerFE();
+        if (layerFE && layerFE->onPreComposition(mRefreshStartTime)) {
+            needsAnotherUpdate = true;
+        }
+    }
+
+    mNeedsAnotherUpdate = needsAnotherUpdate;
+}
+
+void CompositionEngine::setNeedsAnotherUpdateForTest(bool value) {
+    mNeedsAnotherUpdate = value;
+}
+
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index f9d70e3..6831901 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -21,13 +21,15 @@
 #include <compositionengine/impl/Display.h>
 #include <compositionengine/impl/DisplayColorProfile.h>
 #include <compositionengine/impl/DumpHelpers.h>
+#include <compositionengine/impl/OutputLayer.h>
 #include <compositionengine/impl/RenderSurface.h>
+#include <utils/Trace.h>
 
 #include "DisplayHardware/HWComposer.h"
 
 namespace android::compositionengine::impl {
 
-std::shared_ptr<compositionengine::Display> createDisplay(
+std::shared_ptr<Display> createDisplay(
         const compositionengine::CompositionEngine& compositionEngine,
         compositionengine::DisplayCreationArgs&& args) {
     return std::make_shared<Display>(compositionEngine, std::move(args));
@@ -74,9 +76,14 @@
 }
 
 void Display::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace,
-                           ui::RenderIntent renderIntent) {
+                           ui::RenderIntent renderIntent,
+                           ui::Dataspace colorSpaceAgnosticDataspace) {
+    ui::Dataspace targetDataspace =
+            getDisplayColorProfile()->getTargetDataspace(mode, dataspace,
+                                                         colorSpaceAgnosticDataspace);
+
     if (mode == getState().colorMode && dataspace == getState().dataspace &&
-        renderIntent == getState().renderIntent) {
+        renderIntent == getState().renderIntent && targetDataspace == getState().targetDataspace) {
         return;
     }
 
@@ -85,7 +92,7 @@
         return;
     }
 
-    Output::setColorMode(mode, dataspace, renderIntent);
+    Output::setColorMode(mode, dataspace, renderIntent, colorSpaceAgnosticDataspace);
 
     auto& hwc = getCompositionEngine().getHwComposer();
     hwc.setActiveColorMode(*mId, mode, renderIntent);
@@ -119,4 +126,118 @@
                                                                   std::move(args)));
 }
 
+void Display::chooseCompositionStrategy() {
+    ATRACE_CALL();
+    ALOGV(__FUNCTION__);
+
+    // Default to the base settings -- client composition only.
+    Output::chooseCompositionStrategy();
+
+    // If we don't have a HWC display, then we are done
+    if (!mId) {
+        return;
+    }
+
+    // Get any composition changes requested by the HWC device, and apply them.
+    std::optional<android::HWComposer::DeviceRequestedChanges> changes;
+    auto& hwc = getCompositionEngine().getHwComposer();
+    if (status_t result = hwc.getDeviceCompositionChanges(*mId, anyLayersRequireClientComposition(),
+                                                          &changes);
+        result != NO_ERROR) {
+        ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result,
+              strerror(-result));
+        return;
+    }
+    if (changes) {
+        applyChangedTypesToLayers(changes->changedTypes);
+        applyDisplayRequests(changes->displayRequests);
+        applyLayerRequestsToLayers(changes->layerRequests);
+    }
+
+    // Determine what type of composition we are doing from the final state
+    auto& state = editState();
+    state.usesClientComposition = anyLayersRequireClientComposition();
+    state.usesDeviceComposition = !allLayersRequireClientComposition();
+}
+
+bool Display::anyLayersRequireClientComposition() const {
+    const auto& layers = getOutputLayersOrderedByZ();
+    return std::any_of(layers.cbegin(), layers.cend(),
+                       [](const auto& layer) { return layer->requiresClientComposition(); });
+}
+
+bool Display::allLayersRequireClientComposition() const {
+    const auto& layers = getOutputLayersOrderedByZ();
+    return std::all_of(layers.cbegin(), layers.cend(),
+                       [](const auto& layer) { return layer->requiresClientComposition(); });
+}
+
+void Display::applyChangedTypesToLayers(const ChangedTypes& changedTypes) {
+    if (changedTypes.empty()) {
+        return;
+    }
+
+    for (auto& layer : getOutputLayersOrderedByZ()) {
+        auto hwcLayer = layer->getHwcLayer();
+        if (!hwcLayer) {
+            continue;
+        }
+
+        if (auto it = changedTypes.find(hwcLayer); it != changedTypes.end()) {
+            layer->applyDeviceCompositionTypeChange(
+                    static_cast<Hwc2::IComposerClient::Composition>(it->second));
+        }
+    }
+}
+
+void Display::applyDisplayRequests(const DisplayRequests& displayRequests) {
+    auto& state = editState();
+    state.flipClientTarget = (static_cast<uint32_t>(displayRequests) &
+                              static_cast<uint32_t>(HWC2::DisplayRequest::FlipClientTarget)) != 0;
+    // Note: HWC2::DisplayRequest::WriteClientTargetToOutput is currently ignored.
+}
+
+void Display::applyLayerRequestsToLayers(const LayerRequests& layerRequests) {
+    for (auto& layer : getOutputLayersOrderedByZ()) {
+        layer->prepareForDeviceLayerRequests();
+
+        auto hwcLayer = layer->getHwcLayer();
+        if (!hwcLayer) {
+            continue;
+        }
+
+        if (auto it = layerRequests.find(hwcLayer); it != layerRequests.end()) {
+            layer->applyDeviceLayerRequest(
+                    static_cast<Hwc2::IComposerClient::LayerRequest>(it->second));
+        }
+    }
+}
+
+compositionengine::Output::FrameFences Display::presentAndGetFrameFences() {
+    auto result = impl::Output::presentAndGetFrameFences();
+
+    if (!mId) {
+        return result;
+    }
+
+    auto& hwc = getCompositionEngine().getHwComposer();
+    hwc.presentAndGetReleaseFences(*mId);
+
+    result.presentFence = hwc.getPresentFence(*mId);
+
+    // TODO(b/121291683): Change HWComposer call to return entire map
+    for (const auto& layer : getOutputLayersOrderedByZ()) {
+        auto hwcLayer = layer->getHwcLayer();
+        if (!hwcLayer) {
+            continue;
+        }
+
+        result.layerFences.emplace(hwcLayer, hwc.getLayerReleaseFence(*mId, hwcLayer));
+    }
+
+    hwc.clearReleaseFences(*mId);
+
+    return result;
+}
+
 } // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp b/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp
index 130ab1d..5ef9097 100644
--- a/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp
@@ -64,6 +64,12 @@
         RenderIntent::TONE_MAP_COLORIMETRIC,
 };
 
+// Returns true if the given colorMode is considered an HDR color mode
+bool isHdrColorMode(const ColorMode colorMode) {
+    return std::any_of(std::begin(sHdrColorModes), std::end(sHdrColorModes),
+                       [colorMode](ColorMode hdrColorMode) { return hdrColorMode == colorMode; });
+}
+
 // map known color mode to dataspace
 Dataspace colorModeToDataspace(ColorMode mode) {
     switch (mode) {
@@ -90,13 +96,7 @@
     candidates.push_back(mode);
 
     // check if mode is HDR
-    bool isHdr = false;
-    for (auto hdrMode : sHdrColorModes) {
-        if (hdrMode == mode) {
-            isHdr = true;
-            break;
-        }
-    }
+    bool isHdr = isHdrColorMode(mode);
 
     // add other HDR candidates when mode is HDR
     if (isHdr) {
@@ -376,6 +376,32 @@
     }
 }
 
+bool DisplayColorProfile::isDataspaceSupported(Dataspace dataspace) const {
+    switch (dataspace) {
+        case Dataspace::BT2020_PQ:
+        case Dataspace::BT2020_ITU_PQ:
+            return hasHDR10Support();
+
+        case Dataspace::BT2020_HLG:
+        case Dataspace::BT2020_ITU_HLG:
+            return hasHLGSupport();
+
+        default:
+            return true;
+    }
+}
+
+ui::Dataspace DisplayColorProfile::getTargetDataspace(ColorMode mode, Dataspace dataspace,
+                                                      Dataspace colorSpaceAgnosticDataspace) const {
+    if (isHdrColorMode(mode)) {
+        return Dataspace::UNKNOWN;
+    }
+    if (colorSpaceAgnosticDataspace != ui::Dataspace::UNKNOWN) {
+        return colorSpaceAgnosticDataspace;
+    }
+    return dataspace;
+}
+
 void DisplayColorProfile::dump(std::string& out) const {
     out.append("   Composition Display Color State:");
 
diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
index 40c4da9..37d6eaa 100644
--- a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
@@ -24,9 +24,10 @@
 
 using android::compositionengine::impl::dumpVal;
 
-void dumpVal(std::string& out, const char* name, Hwc2::IComposerClient::Color value) {
+void dumpVal(std::string& out, const char* name, half4 value) {
     using android::base::StringAppendF;
-    StringAppendF(&out, "%s=[%d %d %d] ", name, value.r, value.g, value.b);
+    StringAppendF(&out, "%s=[%f %f %f] ", name, static_cast<float>(value.r),
+                  static_cast<float>(value.g), static_cast<float>(value.b));
 }
 
 void dumpFrontEnd(std::string& out, const LayerFECompositionState& state) {
@@ -60,8 +61,8 @@
     dumpVal(out, "composition type", toString(state.compositionType), state.compositionType);
 
     out.append("\n      buffer: ");
+    dumpVal(out, "bufferSlot", state.bufferSlot);
     dumpVal(out, "buffer", state.buffer.get());
-    dumpVal(out, "slot", state.bufferSlot);
 
     out.append("\n      ");
     dumpVal(out, "sideband stream", state.sidebandStream.get());
@@ -70,6 +71,7 @@
     dumpVal(out, "color", state.color);
 
     out.append("\n      ");
+    dumpVal(out, "isColorspaceAgnostic", state.isColorspaceAgnostic);
     dumpVal(out, "dataspace", toString(state.dataspace), state.dataspace);
     dumpVal(out, "hdr metadata types", state.hdrMetadata.validTypes);
     dumpVal(out, "colorTransform", state.colorTransform);
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 01b5781..6d060e4 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -22,6 +22,7 @@
 #include <compositionengine/impl/Output.h>
 #include <compositionengine/impl/OutputLayer.h>
 #include <ui/DebugUtils.h>
+#include <utils/Trace.h>
 
 namespace android::compositionengine {
 
@@ -104,15 +105,21 @@
 }
 
 void Output::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace,
-                          ui::RenderIntent renderIntent) {
+                          ui::RenderIntent renderIntent,
+                          ui::Dataspace colorSpaceAgnosticDataspace) {
+    ui::Dataspace targetDataspace =
+            getDisplayColorProfile()->getTargetDataspace(mode, dataspace,
+                                                         colorSpaceAgnosticDataspace);
+
     if (mState.colorMode == mode && mState.dataspace == dataspace &&
-        mState.renderIntent == renderIntent) {
+        mState.renderIntent == renderIntent && mState.targetDataspace == targetDataspace) {
         return;
     }
 
     mState.colorMode = mode;
     mState.dataspace = dataspace;
     mState.renderIntent = renderIntent;
+    mState.targetDataspace = targetDataspace;
 
     mRenderSurface->setBufferDataspace(dataspace);
 
@@ -236,9 +243,95 @@
     return mOutputLayersOrderedByZ;
 }
 
+void Output::setReleasedLayers(Output::ReleasedLayers&& layers) {
+    mReleasedLayers = std::move(layers);
+}
+
+Output::ReleasedLayers Output::takeReleasedLayers() {
+    return std::move(mReleasedLayers);
+}
+
+void Output::prepareFrame() {
+    ATRACE_CALL();
+    ALOGV(__FUNCTION__);
+
+    if (!mState.isEnabled) {
+        return;
+    }
+
+    chooseCompositionStrategy();
+
+    mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition);
+}
+
+void Output::postFramebuffer() {
+    ATRACE_CALL();
+    ALOGV(__FUNCTION__);
+
+    if (!getState().isEnabled) {
+        return;
+    }
+
+    mRenderSurface->onPresentDisplayCompleted();
+
+    auto frame = presentAndGetFrameFences();
+
+    for (auto& layer : getOutputLayersOrderedByZ()) {
+        // The layer buffer from the previous frame (if any) is released
+        // by HWC only when the release fence from this frame (if any) is
+        // signaled.  Always get the release fence from HWC first.
+        sp<Fence> releaseFence = Fence::NO_FENCE;
+
+        if (auto hwcLayer = layer->getHwcLayer()) {
+            if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
+                releaseFence = f->second;
+            }
+        }
+
+        // If the layer was client composited in the previous frame, we
+        // need to merge with the previous client target acquire fence.
+        // Since we do not track that, always merge with the current
+        // client target acquire fence when it is available, even though
+        // this is suboptimal.
+        // TODO(b/121291683): Track previous frame client target acquire fence.
+        if (mState.usesClientComposition) {
+            releaseFence =
+                    Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
+        }
+
+        layer->getLayerFE().onLayerDisplayed(releaseFence);
+    }
+
+    // We've got a list of layers needing fences, that are disjoint with
+    // getOutputLayersOrderedByZ.  The best we can do is to
+    // supply them with the present fence.
+    for (auto& weakLayer : mReleasedLayers) {
+        if (auto layer = weakLayer.promote(); layer != nullptr) {
+            layer->onLayerDisplayed(frame.presentFence);
+        }
+    }
+
+    // Clear out the released layers now that we're done with them.
+    mReleasedLayers.clear();
+}
+
 void Output::dirtyEntireOutput() {
     mState.dirtyRegion.set(mState.bounds);
 }
 
+void Output::chooseCompositionStrategy() {
+    // The base output implementation can only do client composition
+    mState.usesClientComposition = true;
+    mState.usesDeviceComposition = false;
+}
+
+compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
+    compositionengine::Output::FrameFences result;
+    if (mState.usesClientComposition) {
+        result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
+    }
+    return result;
+}
+
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
index 9549054..3e47fe2 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
@@ -24,6 +24,10 @@
     dumpVal(out, "isEnabled", isEnabled);
     dumpVal(out, "isSecure", isSecure);
 
+    dumpVal(out, "usesClientComposition", usesClientComposition);
+    dumpVal(out, "usesDeviceComposition", usesDeviceComposition);
+    dumpVal(out, "flipClientTarget", flipClientTarget);
+
     dumpVal(out, "layerStack", layerStackId);
     dumpVal(out, "layerStackInternal", layerStackInternal);
 
@@ -44,6 +48,7 @@
     dumpVal(out, "renderIntent", toString(renderIntent), renderIntent);
     dumpVal(out, "dataspace", toString(dataspace), dataspace);
     dumpVal(out, "colorTransform", colorTransform);
+    dumpVal(out, "target dataspace", toString(targetDataspace), targetDataspace);
 
     out.append("\n");
 }
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 5ce72b0..6e744b9 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/stringprintf.h>
 #include <compositionengine/CompositionEngine.h>
+#include <compositionengine/DisplayColorProfile.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/LayerFE.h>
 #include <compositionengine/Output.h>
@@ -290,20 +291,43 @@
 } // namespace impl
 
 void OutputLayer::updateCompositionState(bool includeGeometry) {
+    const auto& layerFEState = mLayer->getState().frontEnd;
+    const auto& outputState = mOutput.getState();
+    const auto& profile = *mOutput.getDisplayColorProfile();
+
     if (includeGeometry) {
         mState.displayFrame = calculateOutputDisplayFrame();
         mState.sourceCrop = calculateOutputSourceCrop();
         mState.bufferTransform =
                 static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform());
 
-        if ((mLayer->getState().frontEnd.isSecure && !mOutput.getState().isSecure) ||
+        if ((layerFEState.isSecure && !outputState.isSecure) ||
             (mState.bufferTransform & ui::Transform::ROT_INVALID)) {
             mState.forceClientComposition = true;
         }
     }
+
+    // Determine the output dependent dataspace for this layer. If it is
+    // colorspace agnostic, it just uses the dataspace chosen for the output to
+    // avoid the need for color conversion.
+    mState.dataspace = layerFEState.isColorspaceAgnostic &&
+                    outputState.targetDataspace != ui::Dataspace::UNKNOWN
+            ? outputState.targetDataspace
+            : layerFEState.dataspace;
+
+    // TODO(lpique): b/121291683 Remove this one we are sure we don't need the
+    // value recomputed / set every frame.
+    mState.visibleRegion = outputState.transform.transform(
+            layerFEState.geomVisibleRegion.intersect(outputState.viewport));
+
+    // These are evaluated every frame as they can potentially change at any
+    // time.
+    if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(mState.dataspace)) {
+        mState.forceClientComposition = true;
+    }
 }
 
-void OutputLayer::writeStateToHWC(bool includeGeometry) const {
+void OutputLayer::writeStateToHWC(bool includeGeometry) {
     // Skip doing this if there is no HWC interface
     if (!mState.hwc) {
         return;
@@ -316,63 +340,277 @@
         return;
     }
 
+    const auto& outputIndependentState = mLayer->getState().frontEnd;
+    auto requestedCompositionType = outputIndependentState.compositionType;
+
     if (includeGeometry) {
-        // Output dependent state
+        writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType);
+        writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), outputIndependentState);
+    }
 
-        if (auto error = hwcLayer->setDisplayFrame(mState.displayFrame);
-            error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
-                  mLayerFE->getDebugName(), mState.displayFrame.left, mState.displayFrame.top,
-                  mState.displayFrame.right, mState.displayFrame.bottom, to_string(error).c_str(),
-                  static_cast<int32_t>(error));
-        }
+    writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
+    writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), outputIndependentState);
 
-        if (auto error = hwcLayer->setSourceCrop(mState.sourceCrop); error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
-                  "%s (%d)",
-                  mLayerFE->getDebugName(), mState.sourceCrop.left, mState.sourceCrop.top,
-                  mState.sourceCrop.right, mState.sourceCrop.bottom, to_string(error).c_str(),
-                  static_cast<int32_t>(error));
-        }
+    writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType);
+}
 
-        if (auto error = hwcLayer->setZOrder(mState.z); error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to set Z %u: %s (%d)", mLayerFE->getDebugName(), mState.z,
+void OutputLayer::writeOutputDependentGeometryStateToHWC(
+        HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
+    const auto& outputDependentState = getState();
+
+    if (auto error = hwcLayer->setDisplayFrame(outputDependentState.displayFrame);
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
+              mLayerFE->getDebugName(), outputDependentState.displayFrame.left,
+              outputDependentState.displayFrame.top, outputDependentState.displayFrame.right,
+              outputDependentState.displayFrame.bottom, to_string(error).c_str(),
+              static_cast<int32_t>(error));
+    }
+
+    if (auto error = hwcLayer->setSourceCrop(outputDependentState.sourceCrop);
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
+              "%s (%d)",
+              mLayerFE->getDebugName(), outputDependentState.sourceCrop.left,
+              outputDependentState.sourceCrop.top, outputDependentState.sourceCrop.right,
+              outputDependentState.sourceCrop.bottom, to_string(error).c_str(),
+              static_cast<int32_t>(error));
+    }
+
+    if (auto error = hwcLayer->setZOrder(outputDependentState.z); error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set Z %u: %s (%d)", mLayerFE->getDebugName(), outputDependentState.z,
+              to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+
+    // Solid-color layers should always use an identity transform.
+    const auto bufferTransform =
+            requestedCompositionType != Hwc2::IComposerClient::Composition::SOLID_COLOR
+            ? outputDependentState.bufferTransform
+            : static_cast<Hwc2::Transform>(0);
+    if (auto error = hwcLayer->setTransform(static_cast<HWC2::Transform>(bufferTransform));
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set transform %s: %s (%d)", mLayerFE->getDebugName(),
+              toString(outputDependentState.bufferTransform).c_str(), to_string(error).c_str(),
+              static_cast<int32_t>(error));
+    }
+}
+
+void OutputLayer::writeOutputIndependentGeometryStateToHWC(
+        HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
+    if (auto error = hwcLayer->setBlendMode(
+                static_cast<HWC2::BlendMode>(outputIndependentState.blendMode));
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set blend mode %s: %s (%d)", mLayerFE->getDebugName(),
+              toString(outputIndependentState.blendMode).c_str(), to_string(error).c_str(),
+              static_cast<int32_t>(error));
+    }
+
+    if (auto error = hwcLayer->setPlaneAlpha(outputIndependentState.alpha);
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", mLayerFE->getDebugName(),
+              outputIndependentState.alpha, to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+
+    if (auto error = hwcLayer->setInfo(outputIndependentState.type, outputIndependentState.appId);
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set info %s (%d)", mLayerFE->getDebugName(), to_string(error).c_str(),
+              static_cast<int32_t>(error));
+    }
+}
+
+void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) {
+    const auto& outputDependentState = getState();
+
+    // TODO(lpique): b/121291683 visibleRegion is output-dependent geometry
+    // state and should not change every frame.
+    if (auto error = hwcLayer->setVisibleRegion(outputDependentState.visibleRegion);
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set visible region: %s (%d)", mLayerFE->getDebugName(),
+              to_string(error).c_str(), static_cast<int32_t>(error));
+        outputDependentState.visibleRegion.dump(LOG_TAG);
+    }
+
+    if (auto error = hwcLayer->setDataspace(outputDependentState.dataspace);
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mLayerFE->getDebugName(),
+              outputDependentState.dataspace, to_string(error).c_str(),
+              static_cast<int32_t>(error));
+    }
+}
+
+void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
+        HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
+    switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
+        case HWC2::Error::None:
+            break;
+        case HWC2::Error::Unsupported:
+            editState().forceClientComposition = true;
+            break;
+        default:
+            ALOGE("[%s] Failed to set color transform: %s (%d)", mLayerFE->getDebugName(),
                   to_string(error).c_str(), static_cast<int32_t>(error));
-        }
+    }
 
-        if (auto error =
-                    hwcLayer->setTransform(static_cast<HWC2::Transform>(mState.bufferTransform));
+    if (auto error = hwcLayer->setSurfaceDamage(outputIndependentState.surfaceDamage);
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set surface damage: %s (%d)", mLayerFE->getDebugName(),
+              to_string(error).c_str(), static_cast<int32_t>(error));
+        outputIndependentState.surfaceDamage.dump(LOG_TAG);
+    }
+
+    // Content-specific per-frame state
+    switch (outputIndependentState.compositionType) {
+        case Hwc2::IComposerClient::Composition::SOLID_COLOR:
+            writeSolidColorStateToHWC(hwcLayer, outputIndependentState);
+            break;
+        case Hwc2::IComposerClient::Composition::SIDEBAND:
+            writeSidebandStateToHWC(hwcLayer, outputIndependentState);
+            break;
+        case Hwc2::IComposerClient::Composition::CURSOR:
+        case Hwc2::IComposerClient::Composition::DEVICE:
+            writeBufferStateToHWC(hwcLayer, outputIndependentState);
+            break;
+        case Hwc2::IComposerClient::Composition::INVALID:
+        case Hwc2::IComposerClient::Composition::CLIENT:
+            // Ignored
+            break;
+    }
+}
+
+void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer,
+                                            const LayerFECompositionState& outputIndependentState) {
+    hwc_color_t color = {static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.r)),
+                         static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.g)),
+                         static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.b)),
+                         255};
+
+    if (auto error = hwcLayer->setColor(color); error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set color: %s (%d)", mLayerFE->getDebugName(),
+              to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+}
+
+void OutputLayer::writeSidebandStateToHWC(HWC2::Layer* hwcLayer,
+                                          const LayerFECompositionState& outputIndependentState) {
+    if (auto error = hwcLayer->setSidebandStream(outputIndependentState.sidebandStream->handle());
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mLayerFE->getDebugName(),
+              outputIndependentState.sidebandStream->handle(), to_string(error).c_str(),
+              static_cast<int32_t>(error));
+    }
+}
+
+void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer,
+                                        const LayerFECompositionState& outputIndependentState) {
+    auto supportedPerFrameMetadata =
+            mOutput.getDisplayColorProfile()->getSupportedPerFrameMetadata();
+    if (auto error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata,
+                                                   outputIndependentState.hdrMetadata);
+        error != HWC2::Error::None && error != HWC2::Error::Unsupported) {
+        ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mLayerFE->getDebugName(),
+              to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+
+    uint32_t hwcSlot = 0;
+    sp<GraphicBuffer> hwcBuffer;
+    // We need access to the output-dependent state for the buffer cache there,
+    // though otherwise the buffer is not output-dependent.
+    editState().hwc->hwcBufferCache.getHwcBuffer(outputIndependentState.bufferSlot,
+                                                 outputIndependentState.buffer, &hwcSlot,
+                                                 &hwcBuffer);
+
+    if (auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, outputIndependentState.acquireFence);
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set buffer %p: %s (%d)", mLayerFE->getDebugName(),
+              outputIndependentState.buffer->handle, to_string(error).c_str(),
+              static_cast<int32_t>(error));
+    }
+}
+
+void OutputLayer::writeCompositionTypeToHWC(
+        HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
+    auto& outputDependentState = editState();
+
+    // If we are forcing client composition, we need to tell the HWC
+    if (outputDependentState.forceClientComposition) {
+        requestedCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
+    }
+
+    // Set the requested composition type with the HWC whenever it changes
+    if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType) {
+        outputDependentState.hwc->hwcCompositionType = requestedCompositionType;
+
+        if (auto error = hwcLayer->setCompositionType(
+                    static_cast<HWC2::Composition>(requestedCompositionType));
             error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to set transform %s: %s (%d)", mLayerFE->getDebugName(),
-                  toString(mState.bufferTransform).c_str(), to_string(error).c_str(),
+            ALOGE("[%s] Failed to set composition type %s: %s (%d)", mLayerFE->getDebugName(),
+                  toString(requestedCompositionType).c_str(), to_string(error).c_str(),
                   static_cast<int32_t>(error));
         }
+    }
+}
 
-        // Output independent state
+HWC2::Layer* OutputLayer::getHwcLayer() const {
+    return mState.hwc ? mState.hwc->hwcLayer.get() : nullptr;
+}
 
-        const auto& outputIndependentState = mLayer->getState().frontEnd;
+bool OutputLayer::requiresClientComposition() const {
+    return !mState.hwc ||
+            mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT;
+}
 
-        if (auto error = hwcLayer->setBlendMode(
-                    static_cast<HWC2::BlendMode>(outputIndependentState.blendMode));
-            error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to set blend mode %s: %s (%d)", mLayerFE->getDebugName(),
-                  toString(outputIndependentState.blendMode).c_str(), to_string(error).c_str(),
-                  static_cast<int32_t>(error));
-        }
+void OutputLayer::detectDisallowedCompositionTypeChange(
+        Hwc2::IComposerClient::Composition from, Hwc2::IComposerClient::Composition to) const {
+    bool result = false;
+    switch (from) {
+        case Hwc2::IComposerClient::Composition::INVALID:
+        case Hwc2::IComposerClient::Composition::CLIENT:
+            result = false;
+            break;
 
-        if (auto error = hwcLayer->setPlaneAlpha(outputIndependentState.alpha);
-            error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", mLayerFE->getDebugName(),
-                  outputIndependentState.alpha, to_string(error).c_str(),
-                  static_cast<int32_t>(error));
-        }
+        case Hwc2::IComposerClient::Composition::DEVICE:
+        case Hwc2::IComposerClient::Composition::SOLID_COLOR:
+            result = (to == Hwc2::IComposerClient::Composition::CLIENT);
+            break;
 
-        if (auto error =
-                    hwcLayer->setInfo(outputIndependentState.type, outputIndependentState.appId);
-            error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to set info %s (%d)", mLayerFE->getDebugName(),
-                  to_string(error).c_str(), static_cast<int32_t>(error));
-        }
+        case Hwc2::IComposerClient::Composition::CURSOR:
+        case Hwc2::IComposerClient::Composition::SIDEBAND:
+            result = (to == Hwc2::IComposerClient::Composition::CLIENT ||
+                      to == Hwc2::IComposerClient::Composition::DEVICE);
+            break;
+    }
+
+    if (!result) {
+        ALOGE("[%s] Invalid device requested composition type change: %s (%d) --> %s (%d)",
+              mLayerFE->getDebugName(), toString(from).c_str(), static_cast<int>(from),
+              toString(to).c_str(), static_cast<int>(to));
+    }
+}
+
+void OutputLayer::applyDeviceCompositionTypeChange(
+        Hwc2::IComposerClient::Composition compositionType) {
+    LOG_FATAL_IF(!mState.hwc);
+    auto& hwcState = *mState.hwc;
+
+    detectDisallowedCompositionTypeChange(hwcState.hwcCompositionType, compositionType);
+
+    hwcState.hwcCompositionType = compositionType;
+}
+
+void OutputLayer::prepareForDeviceLayerRequests() {
+    mState.clearClientTarget = false;
+}
+
+void OutputLayer::applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) {
+    switch (request) {
+        case Hwc2::IComposerClient::LayerRequest::CLEAR_CLIENT_TARGET:
+            mState.clearClientTarget = true;
+            break;
+
+        default:
+            ALOGE("[%s] Unknown device layer request %s (%d)", mLayerFE->getDebugName(),
+                  toString(request).c_str(), static_cast<int>(request));
+            break;
     }
 }
 
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
index 861ea57..e320bee 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
@@ -47,6 +47,7 @@
     dumpVal(out, "displayFrame", displayFrame);
     dumpVal(out, "sourceCrop", sourceCrop);
     dumpVal(out, "bufferTransform", toString(bufferTransform), bufferTransform);
+    dumpVal(out, "dataspace", toString(dataspace), dataspace);
     dumpVal(out, "z-index", z);
 
     if (hwc) {
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index 3fcd9d1..1ce6b4c 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -23,6 +23,7 @@
 #include <compositionengine/DisplaySurface.h>
 #include <compositionengine/RenderSurfaceCreationArgs.h>
 #include <compositionengine/impl/DumpHelpers.h>
+#include <compositionengine/impl/OutputCompositionState.h>
 #include <compositionengine/impl/RenderSurface.h>
 #include <log/log.h>
 #include <renderengine/RenderEngine.h>
@@ -110,24 +111,13 @@
     return mDisplaySurface->beginFrame(mustRecompose);
 }
 
-status_t RenderSurface::prepareFrame() {
-    auto& hwc = mCompositionEngine.getHwComposer();
-    const auto id = mDisplay.getId();
-    if (id) {
-        status_t error = hwc.prepare(*id, mDisplay);
-        if (error != NO_ERROR) {
-            return error;
-        }
-    }
-
+void RenderSurface::prepareFrame(bool usesClientComposition, bool usesDeviceComposition) {
     DisplaySurface::CompositionType compositionType;
-    const bool hasClient = hwc.hasClientComposition(id);
-    const bool hasDevice = hwc.hasDeviceComposition(id);
-    if (hasClient && hasDevice) {
+    if (usesClientComposition && usesDeviceComposition) {
         compositionType = DisplaySurface::COMPOSITION_MIXED;
-    } else if (hasClient) {
+    } else if (usesClientComposition) {
         compositionType = DisplaySurface::COMPOSITION_GLES;
-    } else if (hasDevice) {
+    } else if (usesDeviceComposition) {
         compositionType = DisplaySurface::COMPOSITION_HWC;
     } else {
         // Nothing to do -- when turning the screen off we get a frame like
@@ -135,7 +125,11 @@
         // will do a prepare/set cycle.
         compositionType = DisplaySurface::COMPOSITION_HWC;
     }
-    return mDisplaySurface->prepareFrame(compositionType);
+
+    if (status_t result = mDisplaySurface->prepareFrame(compositionType); result != NO_ERROR) {
+        ALOGE("updateCompositionType failed for %s: %d (%s)", mDisplay.getName().c_str(), result,
+              strerror(-result));
+    }
 }
 
 sp<GraphicBuffer> RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) {
@@ -163,10 +157,9 @@
 }
 
 void RenderSurface::queueBuffer(base::unique_fd&& readyFence) {
-    auto& hwc = mCompositionEngine.getHwComposer();
-    const auto id = mDisplay.getId();
+    auto& state = mDisplay.getState();
 
-    if (hwc.hasClientComposition(id) || hwc.hasFlipClientTargetRequest(id)) {
+    if (state.usesClientComposition || state.flipClientTarget) {
         // hasFlipClientTargetRequest could return true even if we haven't
         // dequeued a buffer before. Try dequeueing one if we don't have a
         // buffer ready.
@@ -215,13 +208,6 @@
     mDisplaySurface->onFrameCommitted();
 }
 
-void RenderSurface::setViewportAndProjection() {
-    auto& renderEngine = mCompositionEngine.getRenderEngine();
-    Rect sourceCrop = Rect(mSize);
-    renderEngine.setViewportAndProjection(mSize.width, mSize.height, sourceCrop,
-                                          ui::Transform::ROT_0);
-}
-
 void RenderSurface::flip() {
     mPageFlipCount++;
 }
diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
index 3766f27..0dbf8f0 100644
--- a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
@@ -14,7 +14,11 @@
  * limitations under the License.
  */
 
+#include <compositionengine/CompositionRefreshArgs.h>
 #include <compositionengine/impl/CompositionEngine.h>
+#include <compositionengine/mock/Layer.h>
+#include <compositionengine/mock/LayerFE.h>
+#include <compositionengine/mock/Output.h>
 #include <gtest/gtest.h>
 #include <renderengine/mock/RenderEngine.h>
 
@@ -23,19 +27,19 @@
 namespace android::compositionengine {
 namespace {
 
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SaveArg;
 using ::testing::StrictMock;
 
 class CompositionEngineTest : public testing::Test {
 public:
-    ~CompositionEngineTest() override;
-    mock::HWComposer* mHwc = new StrictMock<mock::HWComposer>();
+    android::mock::HWComposer* mHwc = new StrictMock<android::mock::HWComposer>();
     renderengine::mock::RenderEngine* mRenderEngine =
             new StrictMock<renderengine::mock::RenderEngine>();
     impl::CompositionEngine mEngine;
 };
 
-CompositionEngineTest::~CompositionEngineTest() = default;
-
 TEST_F(CompositionEngineTest, canInstantiateCompositionEngine) {
     auto engine = impl::createCompositionEngine();
     EXPECT_TRUE(engine.get() != nullptr);
@@ -53,5 +57,84 @@
     EXPECT_EQ(mRenderEngine, &mEngine.getRenderEngine());
 }
 
+/*
+ * CompositionEngine::preComposition
+ */
+
+class PreCompositionTest : public CompositionEngineTest {
+public:
+    PreCompositionTest() {
+        EXPECT_CALL(*mLayer1, getLayerFE()).WillRepeatedly(Return(mLayer1FE));
+        EXPECT_CALL(*mLayer2, getLayerFE()).WillRepeatedly(Return(mLayer2FE));
+        EXPECT_CALL(*mLayer3, getLayerFE()).WillRepeatedly(Return(mLayer3FE));
+        // getLayerFE() can return nullptr. Ensure that this is handled.
+        EXPECT_CALL(*mLayer4, getLayerFE()).WillRepeatedly(Return(nullptr));
+
+        mRefreshArgs.outputs = {mOutput};
+        mRefreshArgs.layers = {mLayer1, mLayer2, mLayer3, mLayer4};
+    }
+
+    std::shared_ptr<mock::Output> mOutput{std::make_shared<StrictMock<mock::Output>>()};
+    std::shared_ptr<mock::Layer> mLayer1{std::make_shared<StrictMock<mock::Layer>>()};
+    std::shared_ptr<mock::Layer> mLayer2{std::make_shared<StrictMock<mock::Layer>>()};
+    std::shared_ptr<mock::Layer> mLayer3{std::make_shared<StrictMock<mock::Layer>>()};
+    std::shared_ptr<mock::Layer> mLayer4{std::make_shared<StrictMock<mock::Layer>>()};
+    sp<StrictMock<mock::LayerFE>> mLayer1FE{new StrictMock<mock::LayerFE>()};
+    sp<StrictMock<mock::LayerFE>> mLayer2FE{new StrictMock<mock::LayerFE>()};
+    sp<StrictMock<mock::LayerFE>> mLayer3FE{new StrictMock<mock::LayerFE>()};
+
+    CompositionRefreshArgs mRefreshArgs;
+};
+
+TEST_F(PreCompositionTest, preCompositionSetsFrameTimestamp) {
+    const nsecs_t before = systemTime(SYSTEM_TIME_MONOTONIC);
+    CompositionRefreshArgs emptyArgs;
+    mEngine.preComposition(emptyArgs);
+    const nsecs_t after = systemTime(SYSTEM_TIME_MONOTONIC);
+
+    // The frame timestamp should be between the before and after timestamps
+    EXPECT_GE(mEngine.getLastFrameRefreshTimestamp(), before);
+    EXPECT_LE(mEngine.getLastFrameRefreshTimestamp(), after);
+}
+
+TEST_F(PreCompositionTest, preCompositionInvokesLayerPreCompositionWithFrameTimestamp) {
+    nsecs_t ts1 = 0;
+    nsecs_t ts2 = 0;
+    nsecs_t ts3 = 0;
+    EXPECT_CALL(*mLayer1FE, onPreComposition(_)).WillOnce(DoAll(SaveArg<0>(&ts1), Return(false)));
+    EXPECT_CALL(*mLayer2FE, onPreComposition(_)).WillOnce(DoAll(SaveArg<0>(&ts2), Return(false)));
+    EXPECT_CALL(*mLayer3FE, onPreComposition(_)).WillOnce(DoAll(SaveArg<0>(&ts3), Return(false)));
+
+    mEngine.preComposition(mRefreshArgs);
+
+    // Each of the onPreComposition calls should used the same refresh timestamp
+    EXPECT_EQ(ts1, mEngine.getLastFrameRefreshTimestamp());
+    EXPECT_EQ(ts2, mEngine.getLastFrameRefreshTimestamp());
+    EXPECT_EQ(ts3, mEngine.getLastFrameRefreshTimestamp());
+}
+
+TEST_F(PreCompositionTest, preCompositionDefaultsToNoUpdateNeeded) {
+    EXPECT_CALL(*mLayer1FE, onPreComposition(_)).WillOnce(Return(false));
+    EXPECT_CALL(*mLayer2FE, onPreComposition(_)).WillOnce(Return(false));
+    EXPECT_CALL(*mLayer3FE, onPreComposition(_)).WillOnce(Return(false));
+
+    mEngine.setNeedsAnotherUpdateForTest(true);
+
+    mEngine.preComposition(mRefreshArgs);
+
+    // The call should have cleared the needsAnotherUpdate flag
+    EXPECT_FALSE(mEngine.needsAnotherUpdate());
+}
+
+TEST_F(PreCompositionTest, preCompositionSetsNeedsAnotherUpdateIfAtLeastOneLayerRequestsIt) {
+    EXPECT_CALL(*mLayer1FE, onPreComposition(_)).WillOnce(Return(true));
+    EXPECT_CALL(*mLayer2FE, onPreComposition(_)).WillOnce(Return(false));
+    EXPECT_CALL(*mLayer3FE, onPreComposition(_)).WillOnce(Return(false));
+
+    mEngine.preComposition(mRefreshArgs);
+
+    EXPECT_TRUE(mEngine.needsAnotherUpdate());
+}
+
 } // namespace
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp
index 9215884..c07dfbb 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp
@@ -638,5 +638,66 @@
     checkGetBestColorMode(profile, expectedResults);
 }
 
+/*
+ * RenderSurface::isDataspaceSupported()
+ */
+
+TEST_F(DisplayColorProfileTest, isDataspaceSupportedWorksForProfileWithNoHdrSupport) {
+    auto profile = ProfileFactory::createProfileWithNoColorModeSupport();
+
+    EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::UNKNOWN));
+    EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::V0_SRGB));
+    EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_PQ));
+    EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_PQ));
+    EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_HLG));
+    EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_HLG));
+}
+
+TEST_F(DisplayColorProfileTest, isDataspaceSupportedWorksForProfileWithHdr10Support) {
+    auto profile = ProfileFactory::createProfileWithSRGBColorModeSupport();
+
+    EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::UNKNOWN));
+    EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::V0_SRGB));
+    EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::BT2020_PQ));
+    EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_PQ));
+    EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_HLG));
+    EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_HLG));
+}
+
+TEST_F(DisplayColorProfileTest, isDataspaceSupportedWorksForProfileWithHlgSupport) {
+    auto profile = ProfileFactory::createProfileWithBT2100PQSupport();
+
+    EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::UNKNOWN));
+    EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::V0_SRGB));
+    EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_PQ));
+    EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_PQ));
+    EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::BT2020_HLG));
+    EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_HLG));
+}
+
+/*
+ * RenderSurface::getTargetDataspace()
+ */
+
+TEST_F(DisplayColorProfileTest, getTargetDataspaceWorks) {
+    auto profile = ProfileFactory::createProfileWithNoColorModeSupport();
+
+    // For a non-HDR colorspace with no colorSpaceAgnosticDataspace override,
+    // the input dataspace should be returned.
+    EXPECT_EQ(Dataspace::DISPLAY_P3,
+              profile.getTargetDataspace(ColorMode::DISPLAY_P3, Dataspace::DISPLAY_P3,
+                                         Dataspace::UNKNOWN));
+
+    // If colorSpaceAgnosticDataspace is set, its value should be returned
+    EXPECT_EQ(Dataspace::V0_SRGB,
+              profile.getTargetDataspace(ColorMode::DISPLAY_P3, Dataspace::DISPLAY_P3,
+                                         Dataspace::V0_SRGB));
+
+    // For an HDR colorspace, Dataspace::UNKNOWN should be returned.
+    EXPECT_EQ(Dataspace::UNKNOWN,
+              profile.getTargetDataspace(ColorMode::BT2100_PQ, Dataspace::BT2020_PQ,
+                                         Dataspace::UNKNOWN));
+}
+
 } // namespace
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 33444a5..e3be0d7 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -22,33 +22,56 @@
 #include <compositionengine/RenderSurfaceCreationArgs.h>
 #include <compositionengine/impl/Display.h>
 #include <compositionengine/mock/CompositionEngine.h>
+#include <compositionengine/mock/DisplayColorProfile.h>
 #include <compositionengine/mock/NativeWindow.h>
+#include <compositionengine/mock/OutputLayer.h>
 #include <compositionengine/mock/RenderSurface.h>
 #include <gtest/gtest.h>
 
+#include "MockHWC2.h"
 #include "MockHWComposer.h"
 
 namespace android::compositionengine {
 namespace {
 
+using testing::_;
+using testing::DoAll;
 using testing::Return;
 using testing::ReturnRef;
+using testing::Sequence;
+using testing::SetArgPointee;
 using testing::StrictMock;
 
 constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
 
-class DisplayTest : public testing::Test {
-public:
-    ~DisplayTest() override = default;
+struct DisplayTest : public testing::Test {
+    DisplayTest() {
+        EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
+        EXPECT_CALL(*mLayer1, getHwcLayer()).WillRepeatedly(Return(&mHWC2Layer1));
+        EXPECT_CALL(*mLayer2, getHwcLayer()).WillRepeatedly(Return(&mHWC2Layer2));
+        EXPECT_CALL(*mLayer3, getHwcLayer()).WillRepeatedly(Return(nullptr));
+
+        std::vector<std::unique_ptr<OutputLayer>> layers;
+        layers.emplace_back(mLayer1);
+        layers.emplace_back(mLayer2);
+        layers.emplace_back(mLayer3);
+        mDisplay.setOutputLayersOrderedByZ(std::move(layers));
+    }
 
     StrictMock<android::mock::HWComposer> mHwComposer;
     StrictMock<mock::CompositionEngine> mCompositionEngine;
     sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>();
+    StrictMock<HWC2::mock::Layer> mHWC2Layer1;
+    StrictMock<HWC2::mock::Layer> mHWC2Layer2;
+    StrictMock<HWC2::mock::Layer> mHWC2LayerUnknown;
+    mock::OutputLayer* mLayer1 = new StrictMock<mock::OutputLayer>();
+    mock::OutputLayer* mLayer2 = new StrictMock<mock::OutputLayer>();
+    mock::OutputLayer* mLayer3 = new StrictMock<mock::OutputLayer>();
     impl::Display mDisplay{mCompositionEngine,
                            DisplayCreationArgsBuilder().setDisplayId(DEFAULT_DISPLAY_ID).build()};
 };
 
-/* ------------------------------------------------------------------------
+/*
  * Basic construction
  */
 
@@ -88,13 +111,11 @@
     }
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Display::disconnect()
  */
 
 TEST_F(DisplayTest, disconnectDisconnectsDisplay) {
-    EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
-
     // The first call to disconnect will disconnect the display with the HWC and
     // set mHwcId to -1.
     EXPECT_CALL(mHwComposer, disconnectDisplay(DEFAULT_DISPLAY_ID)).Times(1);
@@ -107,7 +128,7 @@
     EXPECT_FALSE(mDisplay.getId());
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Display::setColorTransform()
  */
 
@@ -115,8 +136,6 @@
     // Identity matrix sets an identity state value
     const mat4 identity;
 
-    EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
-
     EXPECT_CALL(mHwComposer, setColorTransform(DEFAULT_DISPLAY_ID, identity)).Times(1);
 
     mDisplay.setColorTransform(identity);
@@ -133,28 +152,33 @@
     EXPECT_EQ(HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX, mDisplay.getState().colorTransform);
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Display::setColorMode()
  */
 
 TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) {
     mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
     mDisplay.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface));
+    mock::DisplayColorProfile* colorProfile = new StrictMock<mock::DisplayColorProfile>();
+    mDisplay.setDisplayColorProfileForTest(std::unique_ptr<DisplayColorProfile>(colorProfile));
 
-    EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
+    EXPECT_CALL(*colorProfile, getTargetDataspace(_, _, _))
+            .WillRepeatedly(Return(ui::Dataspace::UNKNOWN));
 
     // These values are expected to be the initial state.
     ASSERT_EQ(ui::ColorMode::NATIVE, mDisplay.getState().colorMode);
     ASSERT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().dataspace);
     ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay.getState().renderIntent);
+    ASSERT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace);
 
-    // Otherwise if the values are unchanged, nothing happens
+    // If the set values are unchanged, nothing happens
     mDisplay.setColorMode(ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
-                          ui::RenderIntent::COLORIMETRIC);
+                          ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN);
 
     EXPECT_EQ(ui::ColorMode::NATIVE, mDisplay.getState().colorMode);
     EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().dataspace);
     EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay.getState().renderIntent);
+    EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace);
 
     // Otherwise if the values are different, updates happen
     EXPECT_CALL(*renderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
@@ -164,26 +188,37 @@
             .Times(1);
 
     mDisplay.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
-                          ui::RenderIntent::TONE_MAP_COLORIMETRIC);
+                          ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN);
 
     EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mDisplay.getState().colorMode);
     EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mDisplay.getState().dataspace);
     EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mDisplay.getState().renderIntent);
+    EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace);
 }
 
 TEST_F(DisplayTest, setColorModeDoesNothingForVirtualDisplay) {
     impl::Display virtualDisplay{mCompositionEngine,
                                  DisplayCreationArgs{false, true, DEFAULT_DISPLAY_ID}};
 
+    mock::DisplayColorProfile* colorProfile = new StrictMock<mock::DisplayColorProfile>();
+    virtualDisplay.setDisplayColorProfileForTest(
+            std::unique_ptr<DisplayColorProfile>(colorProfile));
+
+    EXPECT_CALL(*colorProfile,
+                getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
+                                   ui::Dataspace::UNKNOWN))
+            .WillOnce(Return(ui::Dataspace::UNKNOWN));
+
     virtualDisplay.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
-                                ui::RenderIntent::TONE_MAP_COLORIMETRIC);
+                                ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN);
 
     EXPECT_EQ(ui::ColorMode::NATIVE, virtualDisplay.getState().colorMode);
     EXPECT_EQ(ui::Dataspace::UNKNOWN, virtualDisplay.getState().dataspace);
     EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, virtualDisplay.getState().renderIntent);
+    EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace);
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Display::createDisplayColorProfile()
  */
 
@@ -195,7 +230,7 @@
     EXPECT_TRUE(mDisplay.getDisplayColorProfile() != nullptr);
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Display::createRenderSurface()
  */
 
@@ -206,5 +241,266 @@
     EXPECT_TRUE(mDisplay.getRenderSurface() != nullptr);
 }
 
+/*
+ * Display::chooseCompositionStrategy()
+ */
+
+struct DisplayChooseCompositionStrategyTest : public testing::Test {
+    struct DisplayPartialMock : public impl::Display {
+        DisplayPartialMock(const compositionengine::CompositionEngine& compositionEngine,
+                           compositionengine::DisplayCreationArgs&& args)
+              : impl::Display(compositionEngine, std::move(args)) {}
+
+        // Sets up the helper functions called by chooseCompositionStrategy to
+        // use a mock implementations.
+        MOCK_CONST_METHOD0(anyLayersRequireClientComposition, bool());
+        MOCK_CONST_METHOD0(allLayersRequireClientComposition, bool());
+        MOCK_METHOD1(applyChangedTypesToLayers, void(const impl::Display::ChangedTypes&));
+        MOCK_METHOD1(applyDisplayRequests, void(const impl::Display::DisplayRequests&));
+        MOCK_METHOD1(applyLayerRequestsToLayers, void(const impl::Display::LayerRequests&));
+    };
+
+    DisplayChooseCompositionStrategyTest() {
+        EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
+    }
+
+    StrictMock<android::mock::HWComposer> mHwComposer;
+    StrictMock<mock::CompositionEngine> mCompositionEngine;
+    StrictMock<DisplayPartialMock>
+            mDisplay{mCompositionEngine,
+                     DisplayCreationArgsBuilder().setDisplayId(DEFAULT_DISPLAY_ID).build()};
+};
+
+TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutIfNotAHwcDisplay) {
+    impl::Display nonHwcDisplay{mCompositionEngine, DisplayCreationArgsBuilder().build()};
+    EXPECT_FALSE(nonHwcDisplay.getId());
+
+    nonHwcDisplay.chooseCompositionStrategy();
+
+    auto& state = nonHwcDisplay.getState();
+    EXPECT_TRUE(state.usesClientComposition);
+    EXPECT_FALSE(state.usesDeviceComposition);
+}
+
+TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutOnHwcError) {
+    EXPECT_CALL(mDisplay, anyLayersRequireClientComposition()).WillOnce(Return(false));
+    EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(DEFAULT_DISPLAY_ID, false, _))
+            .WillOnce(Return(INVALID_OPERATION));
+
+    mDisplay.chooseCompositionStrategy();
+
+    auto& state = mDisplay.getState();
+    EXPECT_TRUE(state.usesClientComposition);
+    EXPECT_FALSE(state.usesDeviceComposition);
+}
+
+TEST_F(DisplayChooseCompositionStrategyTest, normalOperation) {
+    // Since two calls are made to anyLayersRequireClientComposition with different return values,
+    // use a Sequence to control the matching so the values are returned in a known order.
+    Sequence s;
+    EXPECT_CALL(mDisplay, anyLayersRequireClientComposition()).InSequence(s).WillOnce(Return(true));
+    EXPECT_CALL(mDisplay, anyLayersRequireClientComposition())
+            .InSequence(s)
+            .WillOnce(Return(false));
+
+    EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(DEFAULT_DISPLAY_ID, true, _))
+            .WillOnce(Return(NO_ERROR));
+    EXPECT_CALL(mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false));
+
+    mDisplay.chooseCompositionStrategy();
+
+    auto& state = mDisplay.getState();
+    EXPECT_FALSE(state.usesClientComposition);
+    EXPECT_TRUE(state.usesDeviceComposition);
+}
+
+TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) {
+    android::HWComposer::DeviceRequestedChanges changes{
+            {{nullptr, HWC2::Composition::Client}},
+            HWC2::DisplayRequest::FlipClientTarget,
+            {{nullptr, HWC2::LayerRequest::ClearClientTarget}},
+    };
+
+    // Since two calls are made to anyLayersRequireClientComposition with different return values,
+    // use a Sequence to control the matching so the values are returned in a known order.
+    Sequence s;
+    EXPECT_CALL(mDisplay, anyLayersRequireClientComposition()).InSequence(s).WillOnce(Return(true));
+    EXPECT_CALL(mDisplay, anyLayersRequireClientComposition())
+            .InSequence(s)
+            .WillOnce(Return(false));
+
+    EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(DEFAULT_DISPLAY_ID, true, _))
+            .WillOnce(DoAll(SetArgPointee<2>(changes), Return(NO_ERROR)));
+    EXPECT_CALL(mDisplay, applyChangedTypesToLayers(changes.changedTypes)).Times(1);
+    EXPECT_CALL(mDisplay, applyDisplayRequests(changes.displayRequests)).Times(1);
+    EXPECT_CALL(mDisplay, applyLayerRequestsToLayers(changes.layerRequests)).Times(1);
+    EXPECT_CALL(mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false));
+
+    mDisplay.chooseCompositionStrategy();
+
+    auto& state = mDisplay.getState();
+    EXPECT_FALSE(state.usesClientComposition);
+    EXPECT_TRUE(state.usesDeviceComposition);
+}
+
+/*
+ * Display::anyLayersRequireClientComposition()
+ */
+
+TEST_F(DisplayTest, anyLayersRequireClientCompositionReturnsFalse) {
+    EXPECT_CALL(*mLayer1, requiresClientComposition()).WillOnce(Return(false));
+    EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(false));
+    EXPECT_CALL(*mLayer3, requiresClientComposition()).WillOnce(Return(false));
+
+    EXPECT_FALSE(mDisplay.anyLayersRequireClientComposition());
+}
+
+TEST_F(DisplayTest, anyLayersRequireClientCompositionReturnsTrue) {
+    EXPECT_CALL(*mLayer1, requiresClientComposition()).WillOnce(Return(false));
+    EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(true));
+
+    EXPECT_TRUE(mDisplay.anyLayersRequireClientComposition());
+}
+
+/*
+ * Display::allLayersRequireClientComposition()
+ */
+
+TEST_F(DisplayTest, allLayersRequireClientCompositionReturnsTrue) {
+    EXPECT_CALL(*mLayer1, requiresClientComposition()).WillOnce(Return(true));
+    EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(true));
+    EXPECT_CALL(*mLayer3, requiresClientComposition()).WillOnce(Return(true));
+
+    EXPECT_TRUE(mDisplay.allLayersRequireClientComposition());
+}
+
+TEST_F(DisplayTest, allLayersRequireClientCompositionReturnsFalse) {
+    EXPECT_CALL(*mLayer1, requiresClientComposition()).WillOnce(Return(true));
+    EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(false));
+
+    EXPECT_FALSE(mDisplay.allLayersRequireClientComposition());
+}
+
+/*
+ * Display::applyChangedTypesToLayers()
+ */
+
+TEST_F(DisplayTest, applyChangedTypesToLayersTakesEarlyOutIfNoChangedLayers) {
+    mDisplay.applyChangedTypesToLayers(impl::Display::ChangedTypes());
+}
+
+TEST_F(DisplayTest, applyChangedTypesToLayersAppliesChanges) {
+    EXPECT_CALL(*mLayer1,
+                applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::CLIENT))
+            .Times(1);
+    EXPECT_CALL(*mLayer2,
+                applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::DEVICE))
+            .Times(1);
+
+    mDisplay.applyChangedTypesToLayers(impl::Display::ChangedTypes{
+            {&mHWC2Layer1, HWC2::Composition::Client},
+            {&mHWC2Layer2, HWC2::Composition::Device},
+            {&mHWC2LayerUnknown, HWC2::Composition::SolidColor},
+    });
+}
+
+/*
+ * Display::applyDisplayRequests()
+ */
+
+TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesNoRequests) {
+    mDisplay.applyDisplayRequests(static_cast<HWC2::DisplayRequest>(0));
+
+    auto& state = mDisplay.getState();
+    EXPECT_FALSE(state.flipClientTarget);
+}
+
+TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesFlipClientTarget) {
+    mDisplay.applyDisplayRequests(HWC2::DisplayRequest::FlipClientTarget);
+
+    auto& state = mDisplay.getState();
+    EXPECT_TRUE(state.flipClientTarget);
+}
+
+TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesWriteClientTargetToOutput) {
+    mDisplay.applyDisplayRequests(HWC2::DisplayRequest::WriteClientTargetToOutput);
+
+    auto& state = mDisplay.getState();
+    EXPECT_FALSE(state.flipClientTarget);
+}
+
+TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesAllRequestFlagsSet) {
+    mDisplay.applyDisplayRequests(static_cast<HWC2::DisplayRequest>(~0));
+
+    auto& state = mDisplay.getState();
+    EXPECT_TRUE(state.flipClientTarget);
+}
+
+/*
+ * Display::applyLayerRequestsToLayers()
+ */
+
+TEST_F(DisplayTest, applyLayerRequestsToLayersPreparesAllLayers) {
+    EXPECT_CALL(*mLayer1, prepareForDeviceLayerRequests()).Times(1);
+    EXPECT_CALL(*mLayer2, prepareForDeviceLayerRequests()).Times(1);
+    EXPECT_CALL(*mLayer3, prepareForDeviceLayerRequests()).Times(1);
+
+    mDisplay.applyLayerRequestsToLayers(impl::Display::LayerRequests());
+}
+
+TEST_F(DisplayTest, applyLayerRequestsToLayers2) {
+    EXPECT_CALL(*mLayer1, prepareForDeviceLayerRequests()).Times(1);
+    EXPECT_CALL(*mLayer2, prepareForDeviceLayerRequests()).Times(1);
+    EXPECT_CALL(*mLayer3, prepareForDeviceLayerRequests()).Times(1);
+
+    EXPECT_CALL(*mLayer1,
+                applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest::CLEAR_CLIENT_TARGET))
+            .Times(1);
+
+    mDisplay.applyLayerRequestsToLayers(impl::Display::LayerRequests{
+            {&mHWC2Layer1, HWC2::LayerRequest::ClearClientTarget},
+            {&mHWC2LayerUnknown, HWC2::LayerRequest::ClearClientTarget},
+    });
+}
+
+/*
+ * Display::presentAndGetFrameFences()
+ */
+
+TEST_F(DisplayTest, presentAndGetFrameFencesReturnsNoFencesOnNonHwcDisplay) {
+    auto nonHwcDisplay{
+            impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())};
+
+    auto result = nonHwcDisplay->presentAndGetFrameFences();
+
+    ASSERT_TRUE(result.presentFence.get());
+    EXPECT_FALSE(result.presentFence->isValid());
+    EXPECT_EQ(0u, result.layerFences.size());
+}
+
+TEST_F(DisplayTest, presentAndGetFrameFencesReturnsPresentAndLayerFences) {
+    sp<Fence> presentFence = new Fence();
+    sp<Fence> layer1Fence = new Fence();
+    sp<Fence> layer2Fence = new Fence();
+
+    EXPECT_CALL(mHwComposer, presentAndGetReleaseFences(DEFAULT_DISPLAY_ID)).Times(1);
+    EXPECT_CALL(mHwComposer, getPresentFence(DEFAULT_DISPLAY_ID)).WillOnce(Return(presentFence));
+    EXPECT_CALL(mHwComposer, getLayerReleaseFence(DEFAULT_DISPLAY_ID, &mHWC2Layer1))
+            .WillOnce(Return(layer1Fence));
+    EXPECT_CALL(mHwComposer, getLayerReleaseFence(DEFAULT_DISPLAY_ID, &mHWC2Layer2))
+            .WillOnce(Return(layer2Fence));
+    EXPECT_CALL(mHwComposer, clearReleaseFences(DEFAULT_DISPLAY_ID)).Times(1);
+
+    auto result = mDisplay.presentAndGetFrameFences();
+
+    EXPECT_EQ(presentFence, result.presentFence);
+
+    EXPECT_EQ(2u, result.layerFences.size());
+    ASSERT_EQ(1, result.layerFences.count(&mHWC2Layer1));
+    EXPECT_EQ(layer1Fence, result.layerFences[&mHWC2Layer1]);
+    ASSERT_EQ(1, result.layerFences.count(&mHWC2Layer2));
+    EXPECT_EQ(layer2Fence, result.layerFences[&mHWC2Layer2]);
+}
+
 } // namespace
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h b/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h
new file mode 100644
index 0000000..6741cc9
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <android-base/stringprintf.h>
+#include <gmock/gmock.h>
+
+namespace {
+
+using android::base::StringAppendF;
+using FloatRect = android::FloatRect;
+
+void dumpFloatRect(const FloatRect& rect, std::string& result, const char* name) {
+    StringAppendF(&result, "%s (%f %f %f %f) ", name, rect.left, rect.top, rect.right, rect.bottom);
+}
+
+// Checks for a region match
+MATCHER_P(FloatRectEq, expected, "") {
+    std::string buf;
+    buf.append("FloatRects are not equal\n");
+    dumpFloatRect(expected, buf, "expected rect");
+    dumpFloatRect(arg, buf, "actual rect");
+    *result_listener << buf;
+
+    const float TOLERANCE = 1e-3f;
+    return (std::fabs(expected.left - arg.left) < TOLERANCE) &&
+            (std::fabs(expected.top - arg.top) < TOLERANCE) &&
+            (std::fabs(expected.right - arg.right) < TOLERANCE) &&
+            (std::fabs(expected.bottom - arg.bottom) < TOLERANCE);
+}
+
+} // namespace
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 94349de..5cfec77 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -40,7 +40,9 @@
                  std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*));
     MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId));
     MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*));
-    MOCK_METHOD2(prepare, status_t(DisplayId, const compositionengine::Output&));
+    MOCK_METHOD3(getDeviceCompositionChanges,
+                 status_t(DisplayId, bool,
+                          std::optional<android::HWComposer::DeviceRequestedChanges>*));
     MOCK_METHOD5(setClientTarget,
                  status_t(DisplayId, uint32_t, const sp<Fence>&, const sp<GraphicBuffer>&,
                           ui::Dataspace));
@@ -50,8 +52,6 @@
     MOCK_METHOD2(setColorTransform, status_t(DisplayId, const mat4&));
     MOCK_METHOD1(disconnectDisplay, void(DisplayId));
     MOCK_CONST_METHOD1(hasDeviceComposition, bool(const std::optional<DisplayId>&));
-    MOCK_CONST_METHOD1(hasFlipClientTargetRequest, bool(const std::optional<DisplayId>&));
-    MOCK_CONST_METHOD1(hasClientComposition, bool(const std::optional<DisplayId>&));
     MOCK_CONST_METHOD1(getPresentFence, sp<Fence>(DisplayId));
     MOCK_CONST_METHOD2(getLayerReleaseFence, sp<Fence>(DisplayId, HWC2::Layer*));
     MOCK_METHOD3(setOutputBuffer, status_t(DisplayId, const sp<Fence>&, const sp<GraphicBuffer>&));
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 2060c5a..a5428ad 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -16,14 +16,17 @@
 
 #include <compositionengine/impl/OutputLayer.h>
 #include <compositionengine/mock/CompositionEngine.h>
+#include <compositionengine/mock/DisplayColorProfile.h>
 #include <compositionengine/mock/Layer.h>
 #include <compositionengine/mock/LayerFE.h>
 #include <compositionengine/mock/Output.h>
 #include <gtest/gtest.h>
 
+#include "FloatRectMatcher.h"
 #include "MockHWC2.h"
 #include "MockHWComposer.h"
 #include "RectMatcher.h"
+#include "RegionMatcher.h"
 
 namespace android::compositionengine {
 namespace {
@@ -44,8 +47,16 @@
 
 const std::string kOutputName{"Test Output"};
 
-class OutputLayerTest : public testing::Test {
-public:
+MATCHER_P(ColorEq, expected, "") {
+    *result_listener << "Colors are not equal\n";
+    *result_listener << "expected " << expected.r << " " << expected.g << " " << expected.b << " "
+                     << expected.a << "\n";
+    *result_listener << "actual " << arg.r << " " << arg.g << " " << arg.b << " " << arg.a << "\n";
+
+    return expected.r == arg.r && expected.g == arg.g && expected.b == arg.b && expected.a == arg.a;
+}
+
+struct OutputLayerTest : public testing::Test {
     OutputLayerTest() {
         EXPECT_CALL(*mLayerFE, getDebugName()).WillRepeatedly(Return("Test LayerFE"));
         EXPECT_CALL(mOutput, getName()).WillRepeatedly(ReturnRef(kOutputName));
@@ -54,8 +65,6 @@
         EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState));
     }
 
-    ~OutputLayerTest() override = default;
-
     compositionengine::mock::Output mOutput;
     std::shared_ptr<compositionengine::mock::Layer> mLayer{
             new StrictMock<compositionengine::mock::Layer>()};
@@ -106,6 +115,114 @@
 }
 
 /*
+ * OutputLayer::calculateOutputSourceCrop()
+ */
+
+struct OutputLayerSourceCropTest : public OutputLayerTest {
+    OutputLayerSourceCropTest() {
+        // Set reasonable default values for a simple case. Each test will
+        // set one specific value to something different.
+        mLayerState.frontEnd.geomUsesSourceCrop = true;
+        mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 1920, 1080};
+        mLayerState.frontEnd.geomActiveTransparentRegion = Region{};
+        mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f};
+        mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT};
+        mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080};
+        mLayerState.frontEnd.geomBufferTransform = TR_IDENT;
+
+        mOutputState.viewport = Rect{0, 0, 1920, 1080};
+    }
+
+    FloatRect calculateOutputSourceCrop() {
+        mLayerState.frontEnd.geomInverseLayerTransform =
+                mLayerState.frontEnd.geomLayerTransform.inverse();
+
+        return mOutputLayer.calculateOutputSourceCrop();
+    }
+};
+
+TEST_F(OutputLayerSourceCropTest, computesEmptyIfSourceCropNotUsed) {
+    mLayerState.frontEnd.geomUsesSourceCrop = false;
+
+    const FloatRect expected{};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, correctForSimpleDefaultCase) {
+    const FloatRect expected{0.f, 0.f, 1920.f, 1080.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewport) {
+    mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f};
+
+    const FloatRect expected{0.f, 0.f, 1920.f, 1080.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewportRotated) {
+    mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f};
+    mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080);
+
+    const FloatRect expected{0.f, 0.f, 1080.f, 1080.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformedBuffer) {
+    struct Entry {
+        uint32_t bufferInvDisplay;
+        uint32_t buffer;
+        uint32_t display;
+        FloatRect expected;
+    };
+    // Not an exhaustive list of cases, but hopefully enough.
+    const std::array<Entry, 12> testData = {
+            // clang-format off
+            //             inv      buffer      display     expected
+            /*  0 */ Entry{false,   TR_IDENT,   TR_IDENT,   FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  1 */ Entry{false,   TR_IDENT,   TR_ROT_90,  FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  2 */ Entry{false,   TR_IDENT,   TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  3 */ Entry{false,   TR_IDENT,   TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+
+            /*  4 */ Entry{true,    TR_IDENT,   TR_IDENT,   FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  5 */ Entry{true,    TR_IDENT,   TR_ROT_90,  FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  6 */ Entry{true,    TR_IDENT,   TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  7 */ Entry{true,    TR_IDENT,   TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+
+            /*  8 */ Entry{false,   TR_IDENT,   TR_IDENT,   FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  9 */ Entry{false,   TR_ROT_90,  TR_ROT_90,  FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /* 10 */ Entry{false,   TR_ROT_180, TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /* 11 */ Entry{false,   TR_ROT_270, TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+
+            // clang-format on
+    };
+
+    for (size_t i = 0; i < testData.size(); i++) {
+        const auto& entry = testData[i];
+
+        mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = entry.bufferInvDisplay;
+        mLayerState.frontEnd.geomBufferTransform = entry.buffer;
+        mOutputState.orientation = entry.display;
+
+        EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(entry.expected)) << "entry " << i;
+    }
+}
+
+TEST_F(OutputLayerSourceCropTest, geomContentCropAffectsCrop) {
+    mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 960, 540};
+
+    const FloatRect expected{0.f, 0.f, 960.f, 540.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, viewportAffectsCrop) {
+    mOutputState.viewport = Rect{0, 0, 960, 540};
+
+    const FloatRect expected{0.f, 0.f, 960.f, 540.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+/*
  * OutputLayer::calculateOutputDisplayFrame()
  */
 
@@ -163,7 +280,7 @@
     EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
 }
 
-TEST_F(OutputLayerDisplayFrameTest, geomLayerSnapToBoundsAffectsFrame) {
+TEST_F(OutputLayerDisplayFrameTest, geomLayerBoundsAffectsFrame) {
     mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f};
     const Rect expected{0, 0, 960, 540};
     EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
@@ -242,6 +359,201 @@
     }
 }
 
+TEST_F(OutputLayerTest,
+       calculateOutputRelativeBufferTransformTestWithOfBufferUsesDisplayInverseTransform) {
+    mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = true;
+
+    struct Entry {
+        uint32_t layer;
+        uint32_t buffer;
+        uint32_t display;
+        uint32_t expected;
+    };
+    // Not an exhaustive list of cases, but hopefully enough.
+    const std::array<Entry, 24> testData = {
+            // clang-format off
+            //             layer       buffer      display     expected
+            /*  0 */ Entry{TR_IDENT,   TR_IDENT,   TR_IDENT,   TR_IDENT},
+            /*  1 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_90,  TR_IDENT},
+            /*  2 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_180, TR_IDENT},
+            /*  3 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_270, TR_IDENT},
+
+            /*  4 */ Entry{TR_IDENT,   TR_FLP_H,   TR_IDENT,   TR_FLP_H},
+            /*  5 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
+            /*  6 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_180, TR_FLP_H},
+            /*  7 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_270, TR_FLP_H},
+
+            /*  8 */ Entry{TR_IDENT,   TR_FLP_V,   TR_IDENT,   TR_FLP_V},
+            /*  9 */ Entry{TR_IDENT,   TR_ROT_90,  TR_ROT_90,  TR_ROT_90},
+            /* 10 */ Entry{TR_IDENT,   TR_ROT_180, TR_ROT_180, TR_ROT_180},
+            /* 11 */ Entry{TR_IDENT,   TR_ROT_270, TR_ROT_270, TR_ROT_270},
+
+            /* 12 */ Entry{TR_ROT_90,  TR_IDENT,   TR_IDENT,   TR_IDENT},
+            /* 13 */ Entry{TR_ROT_90,  TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
+            /* 14 */ Entry{TR_ROT_90,  TR_IDENT,   TR_ROT_180, TR_IDENT},
+            /* 15 */ Entry{TR_ROT_90,  TR_FLP_H,   TR_ROT_270, TR_FLP_H},
+
+            /* 16 */ Entry{TR_ROT_180, TR_FLP_H,   TR_IDENT,   TR_FLP_H},
+            /* 17 */ Entry{TR_ROT_180, TR_IDENT,   TR_ROT_90,  TR_IDENT},
+            /* 18 */ Entry{TR_ROT_180, TR_FLP_H,   TR_ROT_180, TR_FLP_H},
+            /* 19 */ Entry{TR_ROT_180, TR_IDENT,   TR_ROT_270, TR_IDENT},
+
+            /* 20 */ Entry{TR_ROT_270, TR_IDENT,   TR_IDENT,   TR_IDENT},
+            /* 21 */ Entry{TR_ROT_270, TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
+            /* 22 */ Entry{TR_ROT_270, TR_FLP_H,   TR_ROT_180, TR_FLP_H},
+            /* 23 */ Entry{TR_ROT_270, TR_IDENT,   TR_ROT_270, TR_IDENT},
+            // clang-format on
+    };
+
+    for (size_t i = 0; i < testData.size(); i++) {
+        const auto& entry = testData[i];
+
+        mLayerState.frontEnd.geomLayerTransform = ui::Transform{entry.layer};
+        mLayerState.frontEnd.geomBufferTransform = entry.buffer;
+        mOutputState.orientation = entry.display;
+
+        auto actual = mOutputLayer.calculateOutputRelativeBufferTransform();
+        EXPECT_EQ(entry.expected, actual) << "entry " << i;
+    }
+}
+
+/*
+ * OutputLayer::updateCompositionState()
+ */
+
+struct OutputLayerPartialMockForUpdateCompositionState : public impl::OutputLayer {
+    OutputLayerPartialMockForUpdateCompositionState(const compositionengine::Output& output,
+                                                    std::shared_ptr<compositionengine::Layer> layer,
+                                                    sp<compositionengine::LayerFE> layerFE)
+          : impl::OutputLayer(output, layer, layerFE) {}
+    // Mock everything called by updateCompositionState to simplify testing it.
+    MOCK_CONST_METHOD0(calculateOutputSourceCrop, FloatRect());
+    MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect());
+    MOCK_CONST_METHOD0(calculateOutputRelativeBufferTransform, uint32_t());
+};
+
+struct OutputLayerUpdateCompositionStateTest : public OutputLayerTest {
+public:
+    OutputLayerUpdateCompositionStateTest() {
+        EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState));
+        EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState));
+        EXPECT_CALL(mOutput, getDisplayColorProfile())
+                .WillRepeatedly(Return(&mDisplayColorProfile));
+        EXPECT_CALL(mDisplayColorProfile, isDataspaceSupported(_)).WillRepeatedly(Return(true));
+    }
+
+    ~OutputLayerUpdateCompositionStateTest() = default;
+
+    void setupGeometryChildCallValues() {
+        EXPECT_CALL(mOutputLayer, calculateOutputSourceCrop()).WillOnce(Return(kSourceCrop));
+        EXPECT_CALL(mOutputLayer, calculateOutputDisplayFrame()).WillOnce(Return(kDisplayFrame));
+        EXPECT_CALL(mOutputLayer, calculateOutputRelativeBufferTransform())
+                .WillOnce(Return(mBufferTransform));
+    }
+
+    void validateComputedGeometryState() {
+        const auto& state = mOutputLayer.getState();
+        EXPECT_EQ(kSourceCrop, state.sourceCrop);
+        EXPECT_EQ(kDisplayFrame, state.displayFrame);
+        EXPECT_EQ(static_cast<Hwc2::Transform>(mBufferTransform), state.bufferTransform);
+    }
+
+    const FloatRect kSourceCrop{1.f, 2.f, 3.f, 4.f};
+    const Rect kDisplayFrame{11, 12, 13, 14};
+    uint32_t mBufferTransform{21};
+
+    using OutputLayer = OutputLayerPartialMockForUpdateCompositionState;
+    StrictMock<OutputLayer> mOutputLayer{mOutput, mLayer, mLayerFE};
+    StrictMock<mock::DisplayColorProfile> mDisplayColorProfile;
+};
+
+TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) {
+    mLayerState.frontEnd.isSecure = true;
+    mOutputState.isSecure = true;
+
+    setupGeometryChildCallValues();
+
+    mOutputLayer.updateCompositionState(true);
+
+    validateComputedGeometryState();
+
+    EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest,
+       alsoSetsForceCompositionIfSecureLayerOnNonsecureOutput) {
+    mLayerState.frontEnd.isSecure = true;
+    mOutputState.isSecure = false;
+
+    setupGeometryChildCallValues();
+
+    mOutputLayer.updateCompositionState(true);
+
+    validateComputedGeometryState();
+
+    EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest,
+       alsoSetsForceCompositionIfUnsupportedBufferTransform) {
+    mLayerState.frontEnd.isSecure = true;
+    mOutputState.isSecure = true;
+
+    mBufferTransform = ui::Transform::ROT_INVALID;
+
+    setupGeometryChildCallValues();
+
+    mOutputLayer.updateCompositionState(true);
+
+    validateComputedGeometryState();
+
+    EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly) {
+    mLayerState.frontEnd.dataspace = ui::Dataspace::DISPLAY_P3;
+    mOutputState.targetDataspace = ui::Dataspace::V0_SCRGB;
+
+    // If the layer is not colorspace agnostic, the output layer dataspace
+    // should use the layers requested colorspace.
+    mLayerState.frontEnd.isColorspaceAgnostic = false;
+
+    mOutputLayer.updateCompositionState(false);
+
+    EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutputLayer.getState().dataspace);
+
+    // If the layer is colorspace agnostic, the output layer dataspace
+    // should use the colorspace chosen for the whole output.
+    mLayerState.frontEnd.isColorspaceAgnostic = true;
+
+    mOutputLayer.updateCompositionState(false);
+
+    EXPECT_EQ(ui::Dataspace::V0_SCRGB, mOutputLayer.getState().dataspace);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotRequested) {
+    mOutputLayer.updateCompositionState(false);
+
+    EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest, clientCompositionForcedFromFrontEndFlagAtAnyTime) {
+    mLayerState.frontEnd.forceClientComposition = true;
+
+    mOutputLayer.updateCompositionState(false);
+
+    EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest,
+       clientCompositionForcedFromUnsupportedDataspaceAtAnyTime) {
+    EXPECT_CALL(mDisplayColorProfile, isDataspaceSupported(_)).WillRepeatedly(Return(false));
+
+    mOutputLayer.updateCompositionState(false);
+
+    EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
+}
+
 /*
  * OutputLayer::writeStateToHWC()
  */
@@ -256,8 +568,19 @@
     static constexpr float kAlpha = 51.f;
     static constexpr uint32_t kType = 61u;
     static constexpr uint32_t kAppId = 62u;
+    static constexpr ui::Dataspace kDataspace = static_cast<ui::Dataspace>(71);
+    static constexpr int kSupportedPerFrameMetadata = 101;
+    static constexpr int kExpectedHwcSlot = 0;
 
+    static const half4 kColor;
     static const Rect kDisplayFrame;
+    static const Region kVisibleRegion;
+    static const mat4 kColorTransform;
+    static const Region kSurfaceDamage;
+    static const HdrMetadata kHdrMetadata;
+    static native_handle_t* kSidebandStreamHandle;
+    static const sp<GraphicBuffer> kBuffer;
+    static const sp<Fence> kFence;
 
     OutputLayerWriteStateToHWCTest() {
         auto& outputLayerState = mOutputLayer.editState();
@@ -267,13 +590,31 @@
         outputLayerState.sourceCrop = kSourceCrop;
         outputLayerState.z = kZOrder;
         outputLayerState.bufferTransform = static_cast<Hwc2::Transform>(kBufferTransform);
+        outputLayerState.visibleRegion = kVisibleRegion;
+        outputLayerState.dataspace = kDataspace;
 
         mLayerState.frontEnd.blendMode = kBlendMode;
         mLayerState.frontEnd.alpha = kAlpha;
         mLayerState.frontEnd.type = kType;
         mLayerState.frontEnd.appId = kAppId;
+        mLayerState.frontEnd.colorTransform = kColorTransform;
+        mLayerState.frontEnd.color = kColor;
+        mLayerState.frontEnd.surfaceDamage = kSurfaceDamage;
+        mLayerState.frontEnd.hdrMetadata = kHdrMetadata;
+        mLayerState.frontEnd.sidebandStream = NativeHandle::create(kSidebandStreamHandle, false);
+        mLayerState.frontEnd.buffer = kBuffer;
+        mLayerState.frontEnd.bufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
+        mLayerState.frontEnd.acquireFence = kFence;
+
+        EXPECT_CALL(mOutput, getDisplayColorProfile())
+                .WillRepeatedly(Return(&mDisplayColorProfile));
+        EXPECT_CALL(mDisplayColorProfile, getSupportedPerFrameMetadata())
+                .WillRepeatedly(Return(kSupportedPerFrameMetadata));
     }
 
+    // Some tests may need to simulate unsupported HWC calls
+    enum class SimulateUnsupported { None, ColorTransform };
+
     void expectGeometryCommonCalls() {
         EXPECT_CALL(*mHwcLayer, setDisplayFrame(kDisplayFrame)).WillOnce(Return(kError));
         EXPECT_CALL(*mHwcLayer, setSourceCrop(kSourceCrop)).WillOnce(Return(kError));
@@ -287,10 +628,62 @@
         EXPECT_CALL(*mHwcLayer, setInfo(kType, kAppId)).WillOnce(Return(kError));
     }
 
+    void expectPerFrameCommonCalls(SimulateUnsupported unsupported = SimulateUnsupported::None) {
+        EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(kVisibleRegion)))
+                .WillOnce(Return(kError));
+        EXPECT_CALL(*mHwcLayer, setDataspace(kDataspace)).WillOnce(Return(kError));
+        EXPECT_CALL(*mHwcLayer, setColorTransform(kColorTransform))
+                .WillOnce(Return(unsupported == SimulateUnsupported::ColorTransform
+                                         ? HWC2::Error::Unsupported
+                                         : HWC2::Error::None));
+        EXPECT_CALL(*mHwcLayer, setSurfaceDamage(RegionEq(kSurfaceDamage)))
+                .WillOnce(Return(kError));
+    }
+
+    void expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition compositionType) {
+        EXPECT_CALL(*mHwcLayer, setCompositionType(static_cast<HWC2::Composition>(compositionType)))
+                .WillOnce(Return(kError));
+    }
+
+    void expectNoSetCompositionTypeCall() {
+        EXPECT_CALL(*mHwcLayer, setCompositionType(_)).Times(0);
+    }
+
+    void expectSetColorCall() {
+        hwc_color_t color = {static_cast<uint8_t>(std::round(kColor.r * 255)),
+                             static_cast<uint8_t>(std::round(kColor.g * 255)),
+                             static_cast<uint8_t>(std::round(kColor.b * 255)), 255};
+
+        EXPECT_CALL(*mHwcLayer, setColor(ColorEq(color))).WillOnce(Return(kError));
+    }
+
+    void expectSetSidebandHandleCall() {
+        EXPECT_CALL(*mHwcLayer, setSidebandStream(kSidebandStreamHandle));
+    }
+
+    void expectSetHdrMetadataAndBufferCalls() {
+        EXPECT_CALL(*mHwcLayer, setPerFrameMetadata(kSupportedPerFrameMetadata, kHdrMetadata));
+        EXPECT_CALL(*mHwcLayer, setBuffer(kExpectedHwcSlot, kBuffer, kFence));
+    }
+
     std::shared_ptr<HWC2::mock::Layer> mHwcLayer{std::make_shared<StrictMock<HWC2::mock::Layer>>()};
+    StrictMock<mock::DisplayColorProfile> mDisplayColorProfile;
 };
 
+const half4 OutputLayerWriteStateToHWCTest::kColor{81.f / 255.f, 82.f / 255.f, 83.f / 255.f,
+                                                   84.f / 255.f};
 const Rect OutputLayerWriteStateToHWCTest::kDisplayFrame{1001, 1002, 1003, 10044};
+const Region OutputLayerWriteStateToHWCTest::kVisibleRegion{Rect{1005, 1006, 1007, 1008}};
+const mat4 OutputLayerWriteStateToHWCTest::kColorTransform{
+        1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016,
+        1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024,
+};
+const Region OutputLayerWriteStateToHWCTest::kSurfaceDamage{Rect{1025, 1026, 1027, 1028}};
+const HdrMetadata OutputLayerWriteStateToHWCTest::kHdrMetadata{{/* LightFlattenable */}, 1029};
+native_handle_t* OutputLayerWriteStateToHWCTest::kSidebandStreamHandle =
+        reinterpret_cast<native_handle_t*>(1031);
+const sp<GraphicBuffer> OutputLayerWriteStateToHWCTest::kBuffer;
+const sp<Fence> OutputLayerWriteStateToHWCTest::kFence;
 
 TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCState) {
     mOutputLayer.editState().hwc.reset();
@@ -304,11 +697,183 @@
     mOutputLayer.writeStateToHWC(true);
 }
 
-TEST_F(OutputLayerWriteStateToHWCTest, canSetsAllState) {
+TEST_F(OutputLayerWriteStateToHWCTest, canSetAllState) {
     expectGeometryCommonCalls();
+    expectPerFrameCommonCalls();
+
+    expectNoSetCompositionTypeCall();
 
     mOutputLayer.writeStateToHWC(true);
 }
 
+TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) {
+    mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+
+    expectPerFrameCommonCalls();
+    expectSetColorCall();
+    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::SOLID_COLOR);
+
+    mOutputLayer.writeStateToHWC(false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) {
+    mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
+
+    expectPerFrameCommonCalls();
+    expectSetSidebandHandleCall();
+    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::SIDEBAND);
+
+    mOutputLayer.writeStateToHWC(false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) {
+    mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::CURSOR;
+
+    expectPerFrameCommonCalls();
+    expectSetHdrMetadataAndBufferCalls();
+    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CURSOR);
+
+    mOutputLayer.writeStateToHWC(false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForDevice) {
+    mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+
+    expectPerFrameCommonCalls();
+    expectSetHdrMetadataAndBufferCalls();
+    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+
+    mOutputLayer.writeStateToHWC(false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) {
+    (*mOutputLayer.editState().hwc).hwcCompositionType =
+            Hwc2::IComposerClient::Composition::SOLID_COLOR;
+
+    mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+
+    expectPerFrameCommonCalls();
+    expectSetColorCall();
+    expectNoSetCompositionTypeCall();
+
+    mOutputLayer.writeStateToHWC(false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransformNotSupported) {
+    mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+
+    expectPerFrameCommonCalls(SimulateUnsupported::ColorTransform);
+    expectSetColorCall();
+    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
+
+    mOutputLayer.writeStateToHWC(false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfClientCompositionForced) {
+    mOutputLayer.editState().forceClientComposition = true;
+
+    mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+
+    expectPerFrameCommonCalls();
+    expectSetColorCall();
+    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
+
+    mOutputLayer.writeStateToHWC(false);
+}
+
+/*
+ * OutputLayer::getHwcLayer()
+ */
+
+TEST_F(OutputLayerTest, getHwcLayerHandlesNoHwcState) {
+    mOutputLayer.editState().hwc.reset();
+
+    EXPECT_TRUE(mOutputLayer.getHwcLayer() == nullptr);
+}
+
+TEST_F(OutputLayerTest, getHwcLayerHandlesNoHwcLayer) {
+    mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
+
+    EXPECT_TRUE(mOutputLayer.getHwcLayer() == nullptr);
+}
+
+TEST_F(OutputLayerTest, getHwcLayerReturnsHwcLayer) {
+    auto hwcLayer = std::make_shared<StrictMock<HWC2::mock::Layer>>();
+    mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{hwcLayer};
+
+    EXPECT_EQ(hwcLayer.get(), mOutputLayer.getHwcLayer());
+}
+
+/*
+ * OutputLayer::requiresClientComposition()
+ */
+
+TEST_F(OutputLayerTest, requiresClientCompositionReturnsTrueIfNoHWC2State) {
+    mOutputLayer.editState().hwc.reset();
+
+    EXPECT_TRUE(mOutputLayer.requiresClientComposition());
+}
+
+TEST_F(OutputLayerTest, requiresClientCompositionReturnsTrueIfSetToClientComposition) {
+    mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
+    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
+
+    EXPECT_TRUE(mOutputLayer.requiresClientComposition());
+}
+
+TEST_F(OutputLayerTest, requiresClientCompositionReturnsFalseIfSetToDeviceComposition) {
+    mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
+    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;
+
+    EXPECT_FALSE(mOutputLayer.requiresClientComposition());
+}
+
+/*
+ * OutputLayer::applyDeviceCompositionTypeChange()
+ */
+
+TEST_F(OutputLayerTest, applyDeviceCompositionTypeChangeSetsNewType) {
+    mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
+    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;
+
+    mOutputLayer.applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::CLIENT);
+
+    ASSERT_TRUE(mOutputLayer.getState().hwc);
+    EXPECT_EQ(Hwc2::IComposerClient::Composition::CLIENT,
+              mOutputLayer.getState().hwc->hwcCompositionType);
+}
+
+/*
+ * OutputLayer::prepareForDeviceLayerRequests()
+ */
+
+TEST_F(OutputLayerTest, prepareForDeviceLayerRequestsResetsRequestState) {
+    mOutputLayer.editState().clearClientTarget = true;
+
+    mOutputLayer.prepareForDeviceLayerRequests();
+
+    EXPECT_FALSE(mOutputLayer.getState().clearClientTarget);
+}
+
+/*
+ * OutputLayer::applyDeviceLayerRequest()
+ */
+
+TEST_F(OutputLayerTest, applyDeviceLayerRequestHandlesClearClientTarget) {
+    mOutputLayer.editState().clearClientTarget = false;
+
+    mOutputLayer.applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest::CLEAR_CLIENT_TARGET);
+
+    EXPECT_TRUE(mOutputLayer.getState().clearClientTarget);
+}
+
+TEST_F(OutputLayerTest, applyDeviceLayerRequestHandlesUnknownRequest) {
+    mOutputLayer.editState().clearClientTarget = false;
+
+    mOutputLayer.applyDeviceLayerRequest(static_cast<Hwc2::IComposerClient::LayerRequest>(0));
+
+    EXPECT_FALSE(mOutputLayer.getState().clearClientTarget);
+}
+
 } // namespace
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index fee0c11..aa35d25 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -17,6 +17,7 @@
 #include <cmath>
 
 #include <compositionengine/impl/Output.h>
+#include <compositionengine/impl/OutputCompositionState.h>
 #include <compositionengine/mock/CompositionEngine.h>
 #include <compositionengine/mock/DisplayColorProfile.h>
 #include <compositionengine/mock/Layer.h>
@@ -37,8 +38,7 @@
 using testing::ReturnRef;
 using testing::StrictMock;
 
-class OutputTest : public testing::Test {
-public:
+struct OutputTest : public testing::Test {
     OutputTest() {
         mOutput.setDisplayColorProfileForTest(
                 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
@@ -46,7 +46,6 @@
 
         mOutput.editState().bounds = kDefaultDisplaySize;
     }
-    ~OutputTest() override = default;
 
     static const Rect kDefaultDisplaySize;
 
@@ -58,7 +57,7 @@
 
 const Rect OutputTest::kDefaultDisplaySize{100, 200};
 
-/* ------------------------------------------------------------------------
+/*
  * Basic construction
  */
 
@@ -77,7 +76,7 @@
     EXPECT_FALSE(mOutput.isValid());
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Output::setCompositionEnabled()
  */
 
@@ -108,7 +107,7 @@
     EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Output::setProjection()
  */
 
@@ -130,7 +129,7 @@
     EXPECT_EQ(needsFiltering, mOutput.getState().needsFiltering);
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Output::setBounds()
  */
 
@@ -147,7 +146,7 @@
     EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Output::setLayerStackFilter()
  */
 
@@ -161,7 +160,7 @@
     EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Output::setColorTransform
  */
 
@@ -200,34 +199,46 @@
     EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Output::setColorMode
  */
 
 TEST_F(OutputTest, setColorModeSetsStateAndDirtiesOutputIfChanged) {
+    EXPECT_CALL(*mDisplayColorProfile,
+                getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
+                                   ui::Dataspace::UNKNOWN))
+            .WillOnce(Return(ui::Dataspace::UNKNOWN));
     EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
 
     mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
-                         ui::RenderIntent::TONE_MAP_COLORIMETRIC);
+                         ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN);
 
     EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput.getState().colorMode);
     EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput.getState().dataspace);
     EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput.getState().renderIntent);
+    EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput.getState().targetDataspace);
+
     EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
 }
 
 TEST_F(OutputTest, setColorModeDoesNothingIfNoChange) {
+    EXPECT_CALL(*mDisplayColorProfile,
+                getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
+                                   ui::Dataspace::UNKNOWN))
+            .WillOnce(Return(ui::Dataspace::UNKNOWN));
+
     mOutput.editState().colorMode = ui::ColorMode::DISPLAY_P3;
     mOutput.editState().dataspace = ui::Dataspace::DISPLAY_P3;
     mOutput.editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
+    mOutput.editState().targetDataspace = ui::Dataspace::UNKNOWN;
 
     mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
-                         ui::RenderIntent::TONE_MAP_COLORIMETRIC);
+                         ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN);
 
     EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Output::setRenderSurface()
  */
 
@@ -242,7 +253,7 @@
     EXPECT_EQ(Rect(newDisplaySize), mOutput.getState().bounds);
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Output::getDirtyRegion()
  */
 
@@ -271,7 +282,7 @@
     }
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Output::belongsInOutput()
  */
 
@@ -298,7 +309,7 @@
     EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, false));
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Output::getOutputLayerForLayer()
  */
 
@@ -330,7 +341,7 @@
     EXPECT_EQ(nullptr, mOutput.getOutputLayerForLayer(&layer));
 }
 
-/* ------------------------------------------------------------------------
+/*
  * Output::getOrCreateOutputLayer()
  */
 
@@ -377,5 +388,63 @@
     }
 }
 
+/*
+ * Output::prepareFrame()
+ */
+
+struct OutputPrepareFrameTest : public testing::Test {
+    struct OutputPartialMock : public impl::Output {
+        OutputPartialMock(const compositionengine::CompositionEngine& compositionEngine)
+              : impl::Output(compositionEngine) {}
+
+        // Sets up the helper functions called by prepareFrame to use a mock
+        // implementations.
+        MOCK_METHOD0(chooseCompositionStrategy, void());
+    };
+
+    OutputPrepareFrameTest() {
+        mOutput.setDisplayColorProfileForTest(
+                std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
+        mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
+    }
+
+    StrictMock<mock::CompositionEngine> mCompositionEngine;
+    mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
+    mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
+    StrictMock<OutputPartialMock> mOutput{mCompositionEngine};
+};
+
+TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
+    mOutput.editState().isEnabled = false;
+
+    mOutput.prepareFrame();
+}
+
+TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
+    mOutput.editState().isEnabled = true;
+    mOutput.editState().usesClientComposition = false;
+    mOutput.editState().usesDeviceComposition = true;
+
+    EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
+    EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
+
+    mOutput.prepareFrame();
+}
+
+// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
+// base chooseCompositionStrategy() is invoked.
+TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
+    mOutput.editState().isEnabled = true;
+    mOutput.editState().usesClientComposition = false;
+    mOutput.editState().usesDeviceComposition = true;
+
+    EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
+
+    mOutput.prepareFrame();
+
+    EXPECT_TRUE(mOutput.getState().usesClientComposition);
+    EXPECT_FALSE(mOutput.getState().usesDeviceComposition);
+}
+
 } // namespace
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index f75a4dc..da3f4fb 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -18,6 +18,7 @@
 #include <cstdint>
 
 #include <compositionengine/RenderSurfaceCreationArgs.h>
+#include <compositionengine/impl/OutputCompositionState.h>
 #include <compositionengine/impl/RenderSurface.h>
 #include <compositionengine/mock/CompositionEngine.h>
 #include <compositionengine/mock/Display.h>
@@ -27,15 +28,9 @@
 #include <gtest/gtest.h>
 #include <renderengine/mock/RenderEngine.h>
 
-#include "MockHWComposer.h"
-
 namespace android::compositionengine {
 namespace {
 
-/* ------------------------------------------------------------------------
- * RenderSurfaceTest
- */
-
 constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1920;
 constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1080;
 constexpr std::optional<DisplayId> DEFAULT_DISPLAY_ID = std::make_optional(DisplayId{123u});
@@ -55,14 +50,11 @@
     RenderSurfaceTest() {
         EXPECT_CALL(mDisplay, getId()).WillRepeatedly(ReturnRef(DEFAULT_DISPLAY_ID));
         EXPECT_CALL(mDisplay, getName()).WillRepeatedly(ReturnRef(DEFAULT_DISPLAY_NAME));
-        EXPECT_CALL(mCompositionEngine, getHwComposer).WillRepeatedly(ReturnRef(mHwComposer));
         EXPECT_CALL(mCompositionEngine, getRenderEngine).WillRepeatedly(ReturnRef(mRenderEngine));
         EXPECT_CALL(*mNativeWindow, disconnect(NATIVE_WINDOW_API_EGL))
                 .WillRepeatedly(Return(NO_ERROR));
     }
-    ~RenderSurfaceTest() override = default;
 
-    StrictMock<android::mock::HWComposer> mHwComposer;
     StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
     StrictMock<mock::CompositionEngine> mCompositionEngine;
     StrictMock<mock::Display> mDisplay;
@@ -74,7 +66,7 @@
                                                            mDisplaySurface}};
 };
 
-/* ------------------------------------------------------------------------
+/*
  * Basic construction
  */
 
@@ -82,7 +74,7 @@
     EXPECT_TRUE(mSurface.isValid());
 }
 
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::initialize()
  */
 
@@ -95,7 +87,7 @@
     mSurface.initialize();
 }
 
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::getSize()
  */
 
@@ -105,7 +97,7 @@
     EXPECT_EQ(expected, mSurface.getSize());
 }
 
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::getClientTargetAcquireFence()
  */
 
@@ -117,7 +109,7 @@
     EXPECT_EQ(fence.get(), mSurface.getClientTargetAcquireFence().get());
 }
 
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::setDisplaySize()
  */
 
@@ -127,7 +119,7 @@
     mSurface.setDisplaySize(ui::Size(640, 480));
 }
 
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::setBufferDataspace()
  */
 
@@ -138,7 +130,7 @@
     mSurface.setBufferDataspace(ui::Dataspace::DISPLAY_P3);
 }
 
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::setProtected()
  */
 
@@ -179,7 +171,7 @@
     EXPECT_FALSE(mSurface.isProtected());
 }
 
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::beginFrame()
  */
 
@@ -189,73 +181,39 @@
     EXPECT_EQ(NO_ERROR, mSurface.beginFrame(true));
 }
 
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::prepareFrame()
  */
 
-TEST_F(RenderSurfaceTest, prepareFramePassesOutputLayersToHwc) {
-    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
-            .WillOnce(Return(INVALID_OPERATION));
-
-    EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame());
-}
-
-TEST_F(RenderSurfaceTest, prepareFrameTakesEarlyOutOnHwcError) {
-    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
-            .WillOnce(Return(INVALID_OPERATION));
-
-    EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame());
-}
-
 TEST_F(RenderSurfaceTest, prepareFrameHandlesMixedComposition) {
-    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
-            .WillOnce(Return(NO_ERROR));
-    EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
-    EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
-
     EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_MIXED))
-            .WillOnce(Return(INVALID_OPERATION));
+            .WillOnce(Return(NO_ERROR));
 
-    EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame());
+    mSurface.prepareFrame(true, true);
 }
 
 TEST_F(RenderSurfaceTest, prepareFrameHandlesOnlyGlesComposition) {
-    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
-            .WillOnce(Return(NO_ERROR));
-    EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
-    EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
-
     EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_GLES))
             .WillOnce(Return(NO_ERROR));
 
-    EXPECT_EQ(NO_ERROR, mSurface.prepareFrame());
+    mSurface.prepareFrame(true, false);
 }
 
 TEST_F(RenderSurfaceTest, prepareFrameHandlesOnlyHwcComposition) {
-    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
-            .WillOnce(Return(NO_ERROR));
-    EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
-    EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
-
     EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_HWC))
             .WillOnce(Return(NO_ERROR));
 
-    EXPECT_EQ(NO_ERROR, mSurface.prepareFrame());
+    mSurface.prepareFrame(false, true);
 }
 
 TEST_F(RenderSurfaceTest, prepareFrameHandlesNoComposition) {
-    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
-            .WillOnce(Return(NO_ERROR));
-    EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
-    EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
-
     EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_HWC))
             .WillOnce(Return(NO_ERROR));
 
-    EXPECT_EQ(NO_ERROR, mSurface.prepareFrame());
+    mSurface.prepareFrame(false, false);
 }
 
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::dequeueBuffer()
  */
 
@@ -272,7 +230,7 @@
     EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get());
 }
 
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::queueBuffer()
  */
 
@@ -280,9 +238,11 @@
     sp<GraphicBuffer> buffer = new GraphicBuffer();
     mSurface.mutableGraphicBufferForTest() = buffer;
 
-    EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
-    EXPECT_CALL(mHwComposer, hasFlipClientTargetRequest(DEFAULT_DISPLAY_ID))
-            .WillOnce(Return(false));
+    impl::OutputCompositionState state;
+    state.usesClientComposition = false;
+    state.flipClientTarget = false;
+
+    EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state));
     EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1);
 
     mSurface.queueBuffer(base::unique_fd());
@@ -294,7 +254,11 @@
     sp<GraphicBuffer> buffer = new GraphicBuffer();
     mSurface.mutableGraphicBufferForTest() = buffer;
 
-    EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
+    impl::OutputCompositionState state;
+    state.usesClientComposition = true;
+    state.flipClientTarget = false;
+
+    EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state));
     EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1))
             .WillOnce(Return(NO_ERROR));
     EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1);
@@ -308,8 +272,11 @@
     sp<GraphicBuffer> buffer = new GraphicBuffer();
     mSurface.mutableGraphicBufferForTest() = buffer;
 
-    EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
-    EXPECT_CALL(mHwComposer, hasFlipClientTargetRequest(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
+    impl::OutputCompositionState state;
+    state.usesClientComposition = false;
+    state.flipClientTarget = true;
+
+    EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state));
     EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1))
             .WillOnce(Return(NO_ERROR));
     EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1);
@@ -322,8 +289,11 @@
 TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferYetDequeued) {
     sp<GraphicBuffer> buffer = new GraphicBuffer();
 
-    EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
-    EXPECT_CALL(mHwComposer, hasFlipClientTargetRequest(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
+    impl::OutputCompositionState state;
+    state.usesClientComposition = false;
+    state.flipClientTarget = true;
+
+    EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state));
     EXPECT_CALL(*mNativeWindow, dequeueBuffer(_, _))
             .WillOnce(
                     DoAll(SetArgPointee<0>(buffer.get()), SetArgPointee<1>(-1), Return(NO_ERROR)));
@@ -340,7 +310,10 @@
     sp<GraphicBuffer> buffer = new GraphicBuffer();
     mSurface.mutableGraphicBufferForTest() = buffer;
 
-    EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
+    impl::OutputCompositionState state;
+    state.usesClientComposition = true;
+
+    EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state));
     EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1))
             .WillOnce(Return(INVALID_OPERATION));
     EXPECT_CALL(mDisplay, isVirtual()).WillOnce(Return(true));
@@ -353,7 +326,7 @@
     EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get());
 }
 
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::onPresentDisplayCompleted()
  */
 
@@ -363,21 +336,7 @@
     mSurface.onPresentDisplayCompleted();
 }
 
-/* ------------------------------------------------------------------------
- * RenderSurface::setViewportAndProjection()
- */
-
-TEST_F(RenderSurfaceTest, setViewportAndProjectionAppliesChang) {
-    mSurface.setSizeForTest(ui::Size(100, 200));
-
-    EXPECT_CALL(mRenderEngine,
-                setViewportAndProjection(100, 200, Rect(100, 200), ui::Transform::ROT_0))
-            .Times(1);
-
-    mSurface.setViewportAndProjection();
-}
-
-/* ------------------------------------------------------------------------
+/*
  * RenderSurface::flip()
  */
 
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index 7927fa9..3a5f3fa 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -39,7 +39,4 @@
     return !isHiddenByPolicy();
 }
 
-void ContainerLayer::setPerFrameData(const sp<const DisplayDevice>&, const ui::Transform&,
-                                     const Rect&, int32_t, const ui::Dataspace) {}
-
 } // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index 7222a3e..57267c7 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -33,10 +33,6 @@
 
     bool canReceiveInput() const override;
 
-    void setPerFrameData(const sp<const DisplayDevice>& display, const ui::Transform& transform,
-                         const Rect& viewport, int32_t supportedPerFrameMetadata,
-                         const ui::Dataspace targetDataspace) override;
-
     bool isCreatedFromMainThread() const override { return true; }
 
     bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; }
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 4a13bfb..d136562 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -126,14 +126,6 @@
     return mVisibleLayersSortedByZ;
 }
 
-void DisplayDevice::setLayersNeedingFences(const Vector< sp<Layer> >& layers) {
-    mLayersNeedingFences = layers;
-}
-
-const Vector< sp<Layer> >& DisplayDevice::getLayersNeedingFences() const {
-    return mLayersNeedingFences;
-}
-
 // ----------------------------------------------------------------------------
 void DisplayDevice::setPowerMode(int mode) {
     mPowerMode = mode;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 0067b50..8bc19d4 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -88,8 +88,6 @@
 
     void                    setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers);
     const Vector< sp<Layer> >& getVisibleLayersSortedByZ() const;
-    void                    setLayersNeedingFences(const Vector< sp<Layer> >& layers);
-    const Vector< sp<Layer> >& getLayersNeedingFences() const;
 
     void                    setLayerStack(uint32_t stack);
     void                    setDisplaySize(const int newWidth, const int newHeight);
@@ -182,8 +180,6 @@
 
     // list of visible layers on that display
     Vector< sp<Layer> > mVisibleLayersSortedByZ;
-    // list of layers needing fences
-    Vector< sp<Layer> > mLayersNeedingFences;
 
     /*
      * Transaction state
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 1099041..d480f7c 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -20,6 +20,8 @@
 #define LOG_TAG "HWComposer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
+#include "HWComposer.h"
+
 #include <compositionengine/Output.h>
 #include <compositionengine/OutputLayer.h>
 #include <compositionengine/impl/OutputLayerCompositionState.h>
@@ -29,12 +31,10 @@
 #include <utils/Errors.h>
 #include <utils/Trace.h>
 
-#include "HWComposer.h"
-#include "HWC2.h"
-#include "ComposerHal.h"
-
-#include "../Layer.h"           // needed only for debugging
+#include "../Layer.h" // needed only for debugging
 #include "../SurfaceFlinger.h"
+#include "ComposerHal.h"
+#include "HWC2.h"
 
 #define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \
     ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
@@ -113,31 +113,6 @@
     return mDisplayData.at(*displayId).hwcDisplay->getCapabilities().count(capability) > 0;
 }
 
-void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) {
-    bool valid = true;
-    switch (from) {
-        case HWC2::Composition::Client:
-            valid = false;
-            break;
-        case HWC2::Composition::Device:
-        case HWC2::Composition::SolidColor:
-            valid = (to == HWC2::Composition::Client);
-            break;
-        case HWC2::Composition::Cursor:
-        case HWC2::Composition::Sideband:
-            valid = (to == HWC2::Composition::Client ||
-                    to == HWC2::Composition::Device);
-            break;
-        default:
-            break;
-    }
-
-    if (!valid) {
-        ALOGE("Invalid layer type change: %s --> %s", to_string(from).c_str(),
-                to_string(to).c_str());
-    }
-}
-
 std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId,
                                                                HWC2::Connection connection) {
     std::optional<DisplayIdentificationInfo> info;
@@ -399,7 +374,9 @@
     return NO_ERROR;
 }
 
-status_t HWComposer::prepare(DisplayId displayId, const compositionengine::Output& output) {
+status_t HWComposer::getDeviceCompositionChanges(
+        DisplayId displayId, bool frameUsesClientComposition,
+        std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
     ATRACE_CALL();
 
     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
@@ -419,12 +396,8 @@
     // composition.  When there is client composition, since we haven't
     // rendered to the client target yet, we should not attempt to skip
     // validate.
-    //
-    // displayData.hasClientComposition hasn't been updated for this frame.
-    // The check below is incorrect.  We actually rely on HWC here to fall
-    // back to validate when there is any client layer.
     displayData.validateWasSkipped = false;
-    if (!displayData.hasClientComposition) {
+    if (!frameUsesClientComposition) {
         sp<Fence> outPresentFence;
         uint32_t state = UINT32_MAX;
         error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
@@ -449,58 +422,19 @@
         RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
     }
 
-    std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes;
+    android::HWComposer::DeviceRequestedChanges::ChangedTypes changedTypes;
     changedTypes.reserve(numTypes);
     error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
     RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
 
-    displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0);
-    std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests;
+    auto displayRequests = static_cast<HWC2::DisplayRequest>(0);
+    android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
     layerRequests.reserve(numRequests);
-    error = hwcDisplay->getRequests(&displayData.displayRequests,
-            &layerRequests);
+    error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
     RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
 
-    displayData.hasClientComposition = false;
-    displayData.hasDeviceComposition = false;
-    for (auto& outputLayer : output.getOutputLayersOrderedByZ()) {
-        auto& state = outputLayer->editState();
-        LOG_FATAL_IF(!state.hwc.);
-        auto hwcLayer = (*state.hwc).hwcLayer;
-
-        if (auto it = changedTypes.find(hwcLayer.get()); it != changedTypes.end()) {
-            auto newCompositionType = it->second;
-            validateChange(static_cast<HWC2::Composition>((*state.hwc).hwcCompositionType),
-                           newCompositionType);
-            (*state.hwc).hwcCompositionType =
-                    static_cast<Hwc2::IComposerClient::Composition>(newCompositionType);
-        }
-
-        switch ((*state.hwc).hwcCompositionType) {
-            case Hwc2::IComposerClient::Composition::CLIENT:
-                displayData.hasClientComposition = true;
-                break;
-            case Hwc2::IComposerClient::Composition::DEVICE:
-            case Hwc2::IComposerClient::Composition::SOLID_COLOR:
-            case Hwc2::IComposerClient::Composition::CURSOR:
-            case Hwc2::IComposerClient::Composition::SIDEBAND:
-                displayData.hasDeviceComposition = true;
-                break;
-            default:
-                break;
-        }
-
-        state.clearClientTarget = false;
-        if (auto it = layerRequests.find(hwcLayer.get()); it != layerRequests.end()) {
-            auto request = it->second;
-            if (request == HWC2::LayerRequest::ClearClientTarget) {
-                state.clearClientTarget = true;
-            } else {
-                LOG_DISPLAY_ERROR(displayId,
-                                  ("Unknown layer request " + to_string(request)).c_str());
-            }
-        }
-    }
+    outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
+                                               std::move(layerRequests)});
 
     error = hwcDisplay->acceptChanges();
     RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
@@ -508,40 +442,6 @@
     return NO_ERROR;
 }
 
-bool HWComposer::hasDeviceComposition(const std::optional<DisplayId>& displayId) const {
-    if (!displayId) {
-        // Displays without a corresponding HWC display are never composed by
-        // the device
-        return false;
-    }
-
-    RETURN_IF_INVALID_DISPLAY(*displayId, false);
-    return mDisplayData.at(*displayId).hasDeviceComposition;
-}
-
-bool HWComposer::hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const {
-    if (!displayId) {
-        // Displays without a corresponding HWC display are never composed by
-        // the device
-        return false;
-    }
-
-    RETURN_IF_INVALID_DISPLAY(*displayId, false);
-    return ((static_cast<uint32_t>(mDisplayData.at(*displayId).displayRequests) &
-             static_cast<uint32_t>(HWC2::DisplayRequest::FlipClientTarget)) != 0);
-}
-
-bool HWComposer::hasClientComposition(const std::optional<DisplayId>& displayId) const {
-    if (!displayId) {
-        // Displays without a corresponding HWC display are always composed by
-        // the client
-        return true;
-    }
-
-    RETURN_IF_INVALID_DISPLAY(*displayId, true);
-    return mDisplayData.at(*displayId).hasClientComposition;
-}
-
 sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const {
     RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
     return mDisplayData.at(displayId).lastPresentFence;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index de863b8..e87c5c3 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -71,8 +71,26 @@
     // Destroy a previously created layer
     virtual void destroyLayer(DisplayId displayId, HWC2::Layer* layer) = 0;
 
-    // Asks the HAL what it can do
-    virtual status_t prepare(DisplayId displayId, const compositionengine::Output&) = 0;
+    struct DeviceRequestedChanges {
+        using ChangedTypes = std::unordered_map<HWC2::Layer*, HWC2::Composition>;
+        using DisplayRequests = HWC2::DisplayRequest;
+        using LayerRequests = std::unordered_map<HWC2::Layer*, HWC2::LayerRequest>;
+
+        ChangedTypes changedTypes;
+        DisplayRequests displayRequests;
+        LayerRequests layerRequests;
+    };
+
+    // Gets any required composition change requests from the HWC device.
+    //
+    // Note that frameUsesClientComposition must be set correctly based on
+    // whether the current frame appears to use client composition. If it is
+    // false some internal optimizations are allowed to present the display
+    // with fewer handshakes, but this does not work if client composition is
+    // expected.
+    virtual status_t getDeviceCompositionChanges(
+            DisplayId, bool frameUsesClientComposition,
+            std::optional<DeviceRequestedChanges>* outChanges) = 0;
 
     virtual status_t setClientTarget(DisplayId displayId, uint32_t slot,
                                      const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
@@ -93,15 +111,6 @@
     // reset state when an external, non-virtual display is disconnected
     virtual void disconnectDisplay(DisplayId displayId) = 0;
 
-    // does this display have layers handled by HWC
-    virtual bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const = 0;
-
-    // does this display have pending request to flip client target
-    virtual bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const = 0;
-
-    // does this display have layers handled by GLES
-    virtual bool hasClientComposition(const std::optional<DisplayId>& displayId) const = 0;
-
     // get the present fence received from the last call to present.
     virtual sp<Fence> getPresentFence(DisplayId displayId) const = 0;
 
@@ -210,8 +219,9 @@
     // Destroy a previously created layer
     void destroyLayer(DisplayId displayId, HWC2::Layer* layer) override;
 
-    // Asks the HAL what it can do
-    status_t prepare(DisplayId displayId, const compositionengine::Output&) override;
+    status_t getDeviceCompositionChanges(
+            DisplayId, bool frameUsesClientComposition,
+            std::optional<DeviceRequestedChanges>* outChanges) override;
 
     status_t setClientTarget(DisplayId displayId, uint32_t slot, const sp<Fence>& acquireFence,
                              const sp<GraphicBuffer>& target, ui::Dataspace dataspace) override;
@@ -231,15 +241,6 @@
     // reset state when an external, non-virtual display is disconnected
     void disconnectDisplay(DisplayId displayId) override;
 
-    // does this display have layers handled by HWC
-    bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const override;
-
-    // does this display have pending request to flip client target
-    bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const override;
-
-    // does this display have layers handled by GLES
-    bool hasClientComposition(const std::optional<DisplayId>& displayId) const override;
-
     // get the present fence received from the last call to present.
     sp<Fence> getPresentFence(DisplayId displayId) const override;
 
@@ -326,14 +327,10 @@
 
     std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId);
 
-    static void validateChange(HWC2::Composition from, HWC2::Composition to);
-
     struct DisplayData {
         bool isVirtual = false;
-        bool hasClientComposition = false;
-        bool hasDeviceComposition = false;
+
         HWC2::Display* hwcDisplay = nullptr;
-        HWC2::DisplayRequest displayRequests;
         sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires
         std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
         buffer_handle_t outbufHandle = nullptr;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d6e86eb..8150ca7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -153,7 +153,6 @@
     mRemoteSyncPoints.clear();
 
     {
-        Mutex::Autolock pendingStateLock(mPendingStateMutex);
         for (State pendingState : mPendingStates) {
             pendingState.barrierLayer_legacy = nullptr;
         }
@@ -242,20 +241,6 @@
 // h/w composer set-up
 // ---------------------------------------------------------------------------
 
-bool Layer::hasHwcLayer(const sp<const DisplayDevice>& displayDevice) {
-    auto outputLayer = findOutputLayerForDisplay(displayDevice);
-    LOG_FATAL_IF(!outputLayer);
-    return outputLayer->getState().hwc && (*outputLayer->getState().hwc).hwcLayer != nullptr;
-}
-
-HWC2::Layer* Layer::getHwcLayer(const sp<const DisplayDevice>& displayDevice) {
-    auto outputLayer = findOutputLayerForDisplay(displayDevice);
-    if (!outputLayer || !outputLayer->getState().hwc) {
-        return nullptr;
-    }
-    return (*outputLayer->getState().hwc).hwcLayer.get();
-}
-
 Rect Layer::getContentCrop() const {
     // this is the crop rectangle that applies to the buffer
     // itself (as opposed to the window)
@@ -430,7 +415,7 @@
         auto& parentState = parent->getDrawingState();
         const int parentType = parentState.metadata.getInt32(METADATA_WINDOW_TYPE, 0);
         const int parentAppId = parentState.metadata.getInt32(METADATA_OWNER_UID, 0);
-        if (parentType >= 0 || parentAppId >= 0) {
+        if (parentType > 0 && parentAppId > 0) {
             type = parentType;
             appId = parentAppId;
         }
@@ -454,29 +439,38 @@
     compositionState.appId = appId;
 }
 
+void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compositionState) const {
+    compositionState.forceClientComposition = false;
+
+    // TODO(lpique): b/121291683 Remove this one we are sure we don't need the
+    // value recomputed / set every frame.
+    compositionState.geomVisibleRegion = visibleRegion;
+
+    compositionState.isColorspaceAgnostic = isColorSpaceAgnostic();
+    compositionState.dataspace = mCurrentDataSpace;
+    compositionState.colorTransform = getColorTransform();
+    compositionState.colorTransformIsIdentity = !hasColorTransform();
+    compositionState.surfaceDamage = surfaceDamageRegion;
+
+    // Force client composition for special cases known only to the front-end.
+    if (isHdrY410() || getRoundedCornerState().radius > 0.0f) {
+        compositionState.forceClientComposition = true;
+    }
+}
+
 void Layer::latchCompositionState(compositionengine::LayerFECompositionState& compositionState,
                                   bool includeGeometry) const {
     if (includeGeometry) {
         latchGeometry(compositionState);
     }
+
+    latchPerFrameState(compositionState);
 }
 
 const char* Layer::getDebugName() const {
     return mName.string();
 }
 
-void Layer::forceClientComposition(const sp<DisplayDevice>& display) {
-    const auto outputLayer = findOutputLayerForDisplay(display);
-    LOG_FATAL_IF(!outputLayer);
-    outputLayer->editState().forceClientComposition = true;
-}
-
-bool Layer::getForceClientComposition(const sp<DisplayDevice>& display) {
-    const auto outputLayer = findOutputLayerForDisplay(display);
-    LOG_FATAL_IF(!outputLayer);
-    return outputLayer->getState().forceClientComposition;
-}
-
 void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) {
     const auto outputLayer = findOutputLayerForDisplay(display);
     LOG_FATAL_IF(!outputLayer);
@@ -563,29 +557,6 @@
     return true;
 }
 
-void Layer::setCompositionType(const sp<const DisplayDevice>& display,
-                               Hwc2::IComposerClient::Composition type) {
-    const auto outputLayer = findOutputLayerForDisplay(display);
-    LOG_FATAL_IF(!outputLayer);
-    LOG_FATAL_IF(!outputLayer->getState().hwc);
-    auto& compositionState = outputLayer->editState();
-
-    ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", ((*compositionState.hwc).hwcLayer)->getId(),
-          toString(type).c_str(), 1);
-    if ((*compositionState.hwc).hwcCompositionType != type) {
-        ALOGV("    actually setting");
-        (*compositionState.hwc).hwcCompositionType = type;
-
-        auto error = (*compositionState.hwc)
-                             .hwcLayer->setCompositionType(static_cast<HWC2::Composition>(type));
-        ALOGE_IF(error != HWC2::Error::None,
-                 "[%s] Failed to set "
-                 "composition type %s: %s (%d)",
-                 mName.string(), toString(type).c_str(), to_string(error).c_str(),
-                 static_cast<int32_t>(error));
-    }
-}
-
 Hwc2::IComposerClient::Composition Layer::getCompositionType(
         const sp<const DisplayDevice>& display) const {
     const auto outputLayer = findOutputLayerForDisplay(display);
@@ -619,32 +590,6 @@
 // local state
 // ----------------------------------------------------------------------------
 
-void Layer::computeGeometry(const RenderArea& renderArea,
-                            renderengine::Mesh& mesh,
-                            bool useIdentityTransform) const {
-    const ui::Transform renderAreaTransform(renderArea.getTransform());
-    FloatRect win = getBounds();
-
-    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);
-
-    ui::Transform layerTransform = getTransform();
-    if (!useIdentityTransform) {
-        lt = layerTransform.transform(lt);
-        lb = layerTransform.transform(lb);
-        rb = layerTransform.transform(rb);
-        rt = layerTransform.transform(rt);
-    }
-
-    renderengine::Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
-    position[0] = renderAreaTransform.transform(lt);
-    position[1] = renderAreaTransform.transform(lb);
-    position[2] = renderAreaTransform.transform(rb);
-    position[3] = renderAreaTransform.transform(rt);
-}
-
 bool Layer::isSecure() const {
     const State& s(mDrawingState);
     return (s.flags & layer_state_t::eLayerSecure);
@@ -907,6 +852,7 @@
 
     // Commit the transaction
     commitTransaction(c);
+    mPendingStatesSnapshot = mPendingStates;
     mCurrentState.callbackHandles = {};
     return flags;
 }
@@ -1874,14 +1820,61 @@
     setTransactionFlags(eTransactionNeeded);
 }
 
-void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet,
-                         uint32_t traceFlags) {
+void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) const {
+    ui::Transform transform = getTransform();
+
+    if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
+        for (const auto& pendingState : mPendingStatesSnapshot) {
+            auto barrierLayer = pendingState.barrierLayer_legacy.promote();
+            if (barrierLayer != nullptr) {
+                BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
+                barrierLayerProto->set_id(barrierLayer->sequence);
+                barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
+            }
+        }
+
+        auto buffer = mActiveBuffer;
+        if (buffer != nullptr) {
+            LayerProtoHelper::writeToProto(buffer,
+                                           [&]() { return layerInfo->mutable_active_buffer(); });
+            LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
+                                           layerInfo->mutable_buffer_transform());
+        }
+        layerInfo->set_invalidate(contentDirty);
+        layerInfo->set_is_protected(isProtected());
+        layerInfo->set_dataspace(
+                dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace)));
+        layerInfo->set_queued_frames(getQueuedFrameCount());
+        layerInfo->set_refresh_pending(isBufferLatched());
+        layerInfo->set_curr_frame(mCurrentFrameNumber);
+        layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
+
+        layerInfo->set_corner_radius(getRoundedCornerState().radius);
+        LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
+        LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
+                                               [&]() { return layerInfo->mutable_position(); });
+        LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
+        LayerProtoHelper::writeToProto(visibleRegion,
+                                       [&]() { return layerInfo->mutable_visible_region(); });
+        LayerProtoHelper::writeToProto(surfaceDamageRegion,
+                                       [&]() { return layerInfo->mutable_damage_region(); });
+    }
+
+    if (traceFlags & SurfaceTracing::TRACE_EXTRA) {
+        LayerProtoHelper::writeToProto(mSourceBounds,
+                                       [&]() { return layerInfo->mutable_source_bounds(); });
+        LayerProtoHelper::writeToProto(mScreenBounds,
+                                       [&]() { return layerInfo->mutable_screen_bounds(); });
+    }
+}
+
+void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
+                                    uint32_t traceFlags) const {
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
     const State& state = useDrawing ? mDrawingState : mCurrentState;
 
     ui::Transform requestedTransform = state.active_legacy.transform;
-    ui::Transform transform = getTransform();
 
     if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
         layerInfo->set_id(sequence);
@@ -1901,17 +1894,10 @@
 
         LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy,
                                        [&]() { return layerInfo->mutable_transparent_region(); });
-        LayerProtoHelper::writeToProto(visibleRegion,
-                                       [&]() { return layerInfo->mutable_visible_region(); });
-        LayerProtoHelper::writeToProto(surfaceDamageRegion,
-                                       [&]() { return layerInfo->mutable_damage_region(); });
 
         layerInfo->set_layer_stack(getLayerStack());
         layerInfo->set_z(state.z);
 
-        LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
-                                               [&]() { return layerInfo->mutable_position(); });
-
         LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(),
                                                [&]() {
                                                    return layerInfo->mutable_requested_position();
@@ -1922,15 +1908,9 @@
 
         LayerProtoHelper::writeToProto(state.crop_legacy,
                                        [&]() { return layerInfo->mutable_crop(); });
-        layerInfo->set_corner_radius(getRoundedCornerState().radius);
 
         layerInfo->set_is_opaque(isOpaque(state));
-        layerInfo->set_invalidate(contentDirty);
-        layerInfo->set_is_protected(isProtected());
 
-        // XXX (b/79210409) mCurrentDataSpace is not protected
-        layerInfo->set_dataspace(
-                dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace)));
 
         layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat()));
         LayerProtoHelper::writeToProto(getColor(), [&]() { return layerInfo->mutable_color(); });
@@ -1938,7 +1918,6 @@
                                        [&]() { return layerInfo->mutable_requested_color(); });
         layerInfo->set_flags(state.flags);
 
-        LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
         LayerProtoHelper::writeToProto(requestedTransform,
                                        layerInfo->mutable_requested_transform());
 
@@ -1955,29 +1934,6 @@
         } else {
             layerInfo->set_z_order_relative_of(-1);
         }
-
-        auto buffer = mActiveBuffer;
-        if (buffer != nullptr) {
-            LayerProtoHelper::writeToProto(buffer,
-                                           [&]() { return layerInfo->mutable_active_buffer(); });
-            LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
-                                           layerInfo->mutable_buffer_transform());
-        }
-
-        layerInfo->set_queued_frames(getQueuedFrameCount());
-        layerInfo->set_refresh_pending(isBufferLatched());
-        layerInfo->set_curr_frame(mCurrentFrameNumber);
-        layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
-
-        for (const auto& pendingState : mPendingStates) {
-            auto barrierLayer = pendingState.barrierLayer_legacy.promote();
-            if (barrierLayer != nullptr) {
-                BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
-                barrierLayerProto->set_id(barrierLayer->sequence);
-                barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
-            }
-        }
-        LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
     }
 
     if (traceFlags & SurfaceTracing::TRACE_INPUT) {
@@ -1990,23 +1946,19 @@
         for (const auto& entry : state.metadata.mMap) {
             (*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend());
         }
-        LayerProtoHelper::writeToProto(mEffectiveTransform,
-                                       layerInfo->mutable_effective_transform());
-        LayerProtoHelper::writeToProto(mSourceBounds,
-                                       [&]() { return layerInfo->mutable_source_bounds(); });
-        LayerProtoHelper::writeToProto(mScreenBounds,
-                                       [&]() { return layerInfo->mutable_screen_bounds(); });
     }
 }
 
-void Layer::writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
-                         uint32_t traceFlags) {
+void Layer::writeToProtoCompositionState(LayerProto* layerInfo,
+                                         const sp<DisplayDevice>& displayDevice,
+                                         uint32_t traceFlags) const {
     auto outputLayer = findOutputLayerForDisplay(displayDevice);
     if (!outputLayer) {
         return;
     }
 
-    writeToProto(layerInfo, LayerVector::StateSet::Drawing, traceFlags);
+    writeToProtoDrawingState(layerInfo, traceFlags);
+    writeToProtoCommonState(layerInfo, LayerVector::StateSet::Drawing, traceFlags);
 
     const auto& compositionState = outputLayer->getState();
 
@@ -2024,13 +1976,6 @@
             static_cast<int32_t>(compositionState.hwc ? (*compositionState.hwc).hwcCompositionType
                                                       : Hwc2::IComposerClient::Composition::CLIENT);
     layerInfo->set_hwc_composition_type(compositionType);
-
-    if (std::strcmp(getTypeId(), "BufferLayer") == 0 &&
-        static_cast<BufferLayer*>(this)->isProtected()) {
-        layerInfo->set_is_protected(true);
-    } else {
-        layerInfo->set_is_protected(false);
-    }
 }
 
 bool Layer::isRemovedFromCurrentState() const  {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index ec7389e..aa7e2f1 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -357,8 +357,6 @@
         return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay);
     }
 
-    void computeGeometry(const RenderArea& renderArea, renderengine::Mesh& mesh,
-                         bool useIdentityTransform) const;
     FloatRect getBounds(const Region& activeTransparentRegion) const;
     FloatRect getBounds() const;
 
@@ -437,11 +435,21 @@
 
     bool isRemovedFromCurrentState() const;
 
-    void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet,
-                      uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
-
-    void writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
-                      uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
+    // Write states that are modified by the main thread. This includes drawing
+    // state as well as buffer data. This should be called in the main or tracing
+    // thread.
+    void writeToProtoDrawingState(LayerProto* layerInfo,
+                                  uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+    // Write states that are modified by the main thread. This includes drawing
+    // state as well as buffer data and composition data for layers on the specified
+    // display. This should be called in the main or tracing thread.
+    void writeToProtoCompositionState(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
+                                      uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+    // Write drawing or current state. If writing current state, the caller should hold the
+    // external mStateLock. If writing drawing state, this function should be called on the
+    // main or tracing thread.
+    void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
+                                 uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
 
     virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; }
     virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; }
@@ -471,23 +479,13 @@
 
 protected:
     void latchGeometry(compositionengine::LayerFECompositionState& outState) const;
+    virtual void latchPerFrameState(compositionengine::LayerFECompositionState& outState) const;
 
 public:
     virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {}
 
     virtual bool isHdrY410() const { return false; }
 
-    void forceClientComposition(const sp<DisplayDevice>& display);
-    bool getForceClientComposition(const sp<DisplayDevice>& display);
-    virtual void setPerFrameData(const sp<const DisplayDevice>& display,
-                                 const ui::Transform& transform, const Rect& viewport,
-                                 int32_t supportedPerFrameMetadata,
-                                 const ui::Dataspace targetDataspace) = 0;
-
-    // callIntoHwc exists so we can update our local state and call
-    // acceptDisplayChanges without unnecessarily updating the device's state
-    void setCompositionType(const sp<const DisplayDevice>& display,
-                            Hwc2::IComposerClient::Composition type);
     Hwc2::IComposerClient::Composition getCompositionType(
             const sp<const DisplayDevice>& display) const;
     bool getClearClientTarget(const sp<const DisplayDevice>& display) const;
@@ -497,12 +495,6 @@
     virtual void setTransformHint(uint32_t /*orientation*/) const { }
 
     /*
-     * called before composition.
-     * returns true if the layer has pending updates.
-     */
-    virtual bool onPreComposition(nsecs_t refreshStartTime) = 0;
-
-    /*
      * called after composition.
      * returns true if the layer latched a new buffer this frame.
      */
@@ -563,8 +555,9 @@
      * operation, so this should be set only if needed). Typically this is used
      * to figure out if the content or size of a surface has changed.
      */
-    virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/) {
-        return {};
+    virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
+                             nsecs_t /*expectedPresentTime*/) {
+        return false;
     }
 
     virtual bool isBufferLatched() const { return false; }
@@ -609,10 +602,6 @@
     virtual int32_t getQueuedFrameCount() const { return 0; }
 
     // -----------------------------------------------------------------------
-
-    bool hasHwcLayer(const sp<const DisplayDevice>& displayDevice);
-    HWC2::Layer* getHwcLayer(const sp<const DisplayDevice>& displayDevice);
-
     inline const State& getDrawingState() const { return mDrawingState; }
     inline const State& getCurrentState() const { return mCurrentState; }
     inline State& getCurrentState() { return mCurrentState; }
@@ -814,7 +803,7 @@
     // this to be called once.
     sp<IBinder> getHandle();
     const String8& getName() const;
-    virtual void notifyAvailableFrames() {}
+    virtual void notifyAvailableFrames(nsecs_t /*expectedPresentTime*/) {}
     virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; }
     bool getPremultipledAlpha() const;
 
@@ -834,13 +823,15 @@
 
     bool mPrimaryDisplayOnly = false;
 
-    // these are protected by an external lock
-    State mCurrentState;
+    // These are only accessed by the main thread or the tracing thread.
     State mDrawingState;
-    std::atomic<uint32_t> mTransactionFlags{0};
+    // Store a copy of the pending state so that the drawing thread can access the
+    // states without a lock.
+    Vector<State> mPendingStatesSnapshot;
 
-    // Accessed from main thread and binder threads
-    Mutex mPendingStateMutex;
+    // these are protected by an external lock (mStateLock)
+    State mCurrentState;
+    std::atomic<uint32_t> mTransactionFlags{0};
     Vector<State> mPendingStates;
 
     // Timestamp history for UIAutomation. Thread safe.
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index c60421b..7a959f7 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -154,6 +154,10 @@
     return mProducer->getConsumerUsage(outUsage);
 }
 
+status_t MonitoredProducer::setAutoPrerotation(bool autoPrerotation) {
+    return mProducer->setAutoPrerotation(autoPrerotation);
+}
+
 IBinder* MonitoredProducer::onAsBinder() {
     return this;
 }
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index d346f82..788919b 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -70,6 +70,7 @@
     virtual void getFrameTimestamps(FrameEventHistoryDelta *outDelta) override;
     virtual status_t getUniqueId(uint64_t* outId) const override;
     virtual status_t getConsumerUsage(uint64_t* outUsage) const override;
+    virtual status_t setAutoPrerotation(bool autoPrerotation) override;
 
     // The Layer which created this producer, and on which queued Buffer's will be displayed.
     sp<Layer> getLayer() const;
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
index 96ffe20..99c07c2 100644
--- a/services/surfaceflinger/RegionSamplingThread.h
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -27,7 +27,7 @@
 #include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
 #include <utils/StrongPointer.h>
-#include "Scheduler/IdleTimer.h"
+#include "Scheduler/OneShotTimer.h"
 
 namespace android {
 
@@ -107,7 +107,7 @@
     SurfaceFlinger& mFlinger;
     Scheduler& mScheduler;
     const TimingTunables mTunables;
-    scheduler::IdleTimer mIdleTimer;
+    scheduler::OneShotTimer mIdleTimer;
 
     std::unique_ptr<SamplingOffsetCallback> const mPhaseCallback;
 
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 0c94052..ad5eb33 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -64,7 +64,7 @@
     DispSyncThread(const char* name, bool showTraceDetailedInfo)
           : mName(name),
             mStop(false),
-            mModelLocked(false),
+            mModelLocked("DispSync:ModelLocked", false),
             mPeriod(0),
             mPhase(0),
             mReferenceTime(0),
@@ -121,13 +121,11 @@
     void lockModel() {
         Mutex::Autolock lock(mMutex);
         mModelLocked = true;
-        ATRACE_INT("DispSync:ModelLocked", mModelLocked);
     }
 
     void unlockModel() {
         Mutex::Autolock lock(mMutex);
         mModelLocked = false;
-        ATRACE_INT("DispSync:ModelLocked", mModelLocked);
     }
 
     virtual bool threadLoop() {
@@ -431,7 +429,7 @@
     const char* const mName;
 
     bool mStop;
-    bool mModelLocked;
+    TracedOrdinal<bool> mModelLocked;
 
     nsecs_t mPeriod;
     nsecs_t mPhase;
@@ -454,15 +452,14 @@
 
 class ZeroPhaseTracer : public DispSync::Callback {
 public:
-    ZeroPhaseTracer() : mParity(false) {}
+    ZeroPhaseTracer() : mParity("ZERO_PHASE_VSYNC", false) {}
 
     virtual void onDispSyncEvent(nsecs_t /*when*/) {
         mParity = !mParity;
-        ATRACE_INT("ZERO_PHASE_VSYNC", mParity ? 1 : 0);
     }
 
 private:
-    bool mParity;
+    TracedOrdinal<bool> mParity;
 };
 
 DispSync::DispSync(const char* name) : mName(name), mRefreshSkipCount(0) {
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 5faf46e..571c9ca 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -31,19 +31,16 @@
                                nsecs_t offsetThresholdForNextVsync, bool traceVsync,
                                const char* name)
       : mName(name),
+        mValue(base::StringPrintf("VSYNC-%s", name), 0),
         mTraceVsync(traceVsync),
         mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
-        mVsyncEventLabel(base::StringPrintf("VSYNC-%s", name)),
-        mVsyncOffsetLabel(base::StringPrintf("VsyncOffset-%s", name)),
-        mVsyncNegativeOffsetLabel(base::StringPrintf("VsyncNegativeOffset-%s", name)),
         mDispSync(dispSync),
-        mPhaseOffset(phaseOffset),
+        mPhaseOffset(base::StringPrintf("VsyncOffset-%s", name), phaseOffset),
         mOffsetThresholdForNextVsync(offsetThresholdForNextVsync) {}
 
 void DispSyncSource::setVSyncEnabled(bool enable) {
     std::lock_guard lock(mVsyncMutex);
     if (enable) {
-        tracePhaseOffset();
         status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
                                                    static_cast<DispSync::Callback*>(this),
                                                    mLastCallbackTime);
@@ -83,7 +80,6 @@
     }
 
     mPhaseOffset = phaseOffset;
-    tracePhaseOffset();
 
     // If we're not enabled, we don't need to mess with the listeners
     if (!mEnabled) {
@@ -106,7 +102,6 @@
 
     if (mTraceVsync) {
         mValue = (mValue + 1) % 2;
-        ATRACE_INT(mVsyncEventLabel.c_str(), mValue);
     }
 
     if (callback != nullptr) {
@@ -114,14 +109,4 @@
     }
 }
 
-void DispSyncSource::tracePhaseOffset() {
-    if (mPhaseOffset > 0) {
-        ATRACE_INT(mVsyncOffsetLabel.c_str(), mPhaseOffset);
-        ATRACE_INT(mVsyncNegativeOffsetLabel.c_str(), 0);
-    } else {
-        ATRACE_INT(mVsyncOffsetLabel.c_str(), 0);
-        ATRACE_INT(mVsyncNegativeOffsetLabel.c_str(), -mPhaseOffset);
-    }
-}
-
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index 50560a5..740c8c4 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -20,6 +20,7 @@
 
 #include "DispSync.h"
 #include "EventThread.h"
+#include "TracedOrdinal.h"
 
 namespace android {
 
@@ -39,16 +40,11 @@
     // The following method is the implementation of the DispSync::Callback.
     virtual void onDispSyncEvent(nsecs_t when);
 
-    void tracePhaseOffset() REQUIRES(mVsyncMutex);
-
     const char* const mName;
-    int mValue = 0;
+    TracedOrdinal<int> mValue;
 
     const bool mTraceVsync;
     const std::string mVsyncOnLabel;
-    const std::string mVsyncEventLabel;
-    const std::string mVsyncOffsetLabel;
-    const std::string mVsyncNegativeOffsetLabel;
     nsecs_t mLastCallbackTime GUARDED_BY(mVsyncMutex) = 0;
 
     DispSync* mDispSync;
@@ -57,7 +53,7 @@
     VSyncSource::Callback* mCallback GUARDED_BY(mCallbackMutex) = nullptr;
 
     std::mutex mVsyncMutex;
-    nsecs_t mPhaseOffset GUARDED_BY(mVsyncMutex);
+    TracedOrdinal<nsecs_t> mPhaseOffset GUARDED_BY(mVsyncMutex);
     const nsecs_t mOffsetThresholdForNextVsync;
     bool mEnabled GUARDED_BY(mVsyncMutex) = false;
 };
diff --git a/services/surfaceflinger/Scheduler/IdleTimer.cpp b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
similarity index 88%
rename from services/surfaceflinger/Scheduler/IdleTimer.cpp
rename to services/surfaceflinger/Scheduler/OneShotTimer.cpp
index 37fdfc7..4870a3b 100644
--- a/services/surfaceflinger/Scheduler/IdleTimer.cpp
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "IdleTimer.h"
+#include "OneShotTimer.h"
 
 #include <chrono>
 #include <thread>
@@ -22,23 +22,23 @@
 namespace android {
 namespace scheduler {
 
-IdleTimer::IdleTimer(const Interval& interval, const ResetCallback& resetCallback,
-                     const TimeoutCallback& timeoutCallback)
+OneShotTimer::OneShotTimer(const Interval& interval, const ResetCallback& resetCallback,
+                           const TimeoutCallback& timeoutCallback)
       : mInterval(interval), mResetCallback(resetCallback), mTimeoutCallback(timeoutCallback) {}
 
-IdleTimer::~IdleTimer() {
+OneShotTimer::~OneShotTimer() {
     stop();
 }
 
-void IdleTimer::start() {
+void OneShotTimer::start() {
     {
         std::lock_guard<std::mutex> lock(mMutex);
         mState = TimerState::RESET;
     }
-    mThread = std::thread(&IdleTimer::loop, this);
+    mThread = std::thread(&OneShotTimer::loop, this);
 }
 
-void IdleTimer::stop() {
+void OneShotTimer::stop() {
     {
         std::lock_guard<std::mutex> lock(mMutex);
         mState = TimerState::STOPPED;
@@ -49,7 +49,7 @@
     }
 }
 
-void IdleTimer::loop() {
+void OneShotTimer::loop() {
     while (true) {
         bool triggerReset = false;
         bool triggerTimeout = false;
@@ -100,7 +100,7 @@
     }
 } // namespace scheduler
 
-void IdleTimer::reset() {
+void OneShotTimer::reset() {
     {
         std::lock_guard<std::mutex> lock(mMutex);
         mState = TimerState::RESET;
diff --git a/services/surfaceflinger/Scheduler/IdleTimer.h b/services/surfaceflinger/Scheduler/OneShotTimer.h
similarity index 93%
rename from services/surfaceflinger/Scheduler/IdleTimer.h
rename to services/surfaceflinger/Scheduler/OneShotTimer.h
index 2646688..fd1aa02 100644
--- a/services/surfaceflinger/Scheduler/IdleTimer.h
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.h
@@ -29,15 +29,15 @@
  * Class that sets off a timer for a given interval, and fires a callback when the
  * interval expires.
  */
-class IdleTimer {
+class OneShotTimer {
 public:
     using Interval = std::chrono::milliseconds;
     using ResetCallback = std::function<void()>;
     using TimeoutCallback = std::function<void()>;
 
-    IdleTimer(const Interval& interval, const ResetCallback& resetCallback,
-              const TimeoutCallback& timeoutCallback);
-    ~IdleTimer();
+    OneShotTimer(const Interval& interval, const ResetCallback& resetCallback,
+                 const TimeoutCallback& timeoutCallback);
+    ~OneShotTimer();
 
     // Initializes and turns on the idle timer.
     void start();
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 8a2604f..9f8567d 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -18,115 +18,102 @@
 
 #include <cutils/properties.h>
 
+#include <optional>
+
 #include "SurfaceFlingerProperties.h"
 
-namespace android {
-using namespace android::sysprop;
+namespace {
 
-namespace scheduler {
+std::optional<int> getProperty(const char* name) {
+    char value[PROPERTY_VALUE_MAX];
+    property_get(name, value, "-1");
+    if (const int i = atoi(value); i != -1) return i;
+    return std::nullopt;
+}
 
-using RefreshRateType = RefreshRateConfigs::RefreshRateType;
+} // namespace
+
+namespace android::scheduler {
+
 PhaseOffsets::~PhaseOffsets() = default;
 
 namespace impl {
+
 PhaseOffsets::PhaseOffsets() {
-    int64_t vsyncPhaseOffsetNs = vsync_event_phase_offset_ns(1000000);
-
-    int64_t sfVsyncPhaseOffsetNs = vsync_sf_event_phase_offset_ns(1000000);
-
-    char value[PROPERTY_VALUE_MAX];
-    property_get("debug.sf.early_phase_offset_ns", value, "-1");
-    const int earlySfOffsetNs = atoi(value);
-
-    property_get("debug.sf.early_gl_phase_offset_ns", value, "-1");
-    const int earlyGlSfOffsetNs = atoi(value);
-
-    property_get("debug.sf.early_app_phase_offset_ns", value, "-1");
-    const int earlyAppOffsetNs = atoi(value);
-
-    property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1");
-    const int earlyGlAppOffsetNs = atoi(value);
-
-    property_get("debug.sf.high_fps_early_phase_offset_ns", value, "-1");
-    const int highFpsEarlySfOffsetNs = atoi(value);
-
-    property_get("debug.sf.high_fps_early_gl_phase_offset_ns", value, "-1");
-    const int highFpsEarlyGlSfOffsetNs = atoi(value);
-
-    property_get("debug.sf.high_fps_early_app_phase_offset_ns", value, "-1");
-    const int highFpsEarlyAppOffsetNs = atoi(value);
-
-    property_get("debug.sf.high_fps_early_gl_app_phase_offset_ns", value, "-1");
-    const int highFpsEarlyGlAppOffsetNs = atoi(value);
-
-    // TODO(b/122905996): Define these in device.mk.
-    property_get("debug.sf.high_fps_late_app_phase_offset_ns", value, "2000000");
-    const int highFpsLateAppOffsetNs = atoi(value);
-
-    property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "1000000");
-    const int highFpsLateSfOffsetNs = atoi(value);
-
     // Below defines the threshold when an offset is considered to be negative, i.e. targeting
     // for the N+2 vsync instead of N+1. This means that:
     // For offset < threshold, SF wake up (vsync_duration - offset) before HW vsync.
     // For offset >= threshold, SF wake up (2 * vsync_duration - offset) before HW vsync.
-    property_get("debug.sf.phase_offset_threshold_for_next_vsync_ns", value, "-1");
-    const int phaseOffsetThresholdForNextVsyncNs = atoi(value);
+    const nsecs_t thresholdForNextVsync =
+            getProperty("debug.sf.phase_offset_threshold_for_next_vsync_ns")
+                    .value_or(std::numeric_limits<nsecs_t>::max());
 
-    Offsets defaultOffsets;
-    Offsets highFpsOffsets;
-    defaultOffsets.early = {RefreshRateType::DEFAULT,
-                            earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs,
-                            earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs};
-    defaultOffsets.earlyGl = {RefreshRateType::DEFAULT,
-                              earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs,
-                              earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs};
-    defaultOffsets.late = {RefreshRateType::DEFAULT, sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs};
-
-    highFpsOffsets.early = {RefreshRateType::PERFORMANCE,
-                            highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs
-                                                         : highFpsLateSfOffsetNs,
-                            highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs
-                                                          : highFpsLateAppOffsetNs};
-    highFpsOffsets.earlyGl = {RefreshRateType::PERFORMANCE,
-                              highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs
-                                                             : highFpsLateSfOffsetNs,
-                              highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
-                                                              : highFpsLateAppOffsetNs};
-    highFpsOffsets.late = {RefreshRateType::PERFORMANCE, highFpsLateSfOffsetNs,
-                           highFpsLateAppOffsetNs};
+    const Offsets defaultOffsets = getDefaultOffsets(thresholdForNextVsync);
+    const Offsets highFpsOffsets = getHighFpsOffsets(thresholdForNextVsync);
 
     mOffsets.insert({RefreshRateType::POWER_SAVING, defaultOffsets});
     mOffsets.insert({RefreshRateType::DEFAULT, defaultOffsets});
     mOffsets.insert({RefreshRateType::PERFORMANCE, highFpsOffsets});
-
-    mOffsetThresholdForNextVsync = phaseOffsetThresholdForNextVsyncNs != -1
-            ? phaseOffsetThresholdForNextVsyncNs
-            : std::numeric_limits<nsecs_t>::max();
 }
 
 PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(
-        android::scheduler::RefreshRateConfigs::RefreshRateType refreshRateType) const {
+        RefreshRateType refreshRateType) const {
     return mOffsets.at(refreshRateType);
 }
 
 void PhaseOffsets::dump(std::string& result) const {
-    const auto [early, earlyGl, late] = getCurrentOffsets();
+    const auto [early, earlyGl, late, threshold] = getCurrentOffsets();
     base::StringAppendF(&result,
                         "         app phase: %9" PRId64 " ns\t         SF phase: %9" PRId64 " ns\n"
                         "   early app phase: %9" PRId64 " ns\t   early SF phase: %9" PRId64 " ns\n"
-                        "GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n",
-                        late.app, late.sf, early.app, early.sf, earlyGl.app, earlyGl.sf);
+                        "GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n"
+                        "threshold for next VSYNC: %" PRId64 " ns\n",
+                        late.app, late.sf, early.app, early.sf, earlyGl.app, earlyGl.sf, threshold);
 }
 
-nsecs_t PhaseOffsets::getCurrentAppOffset() {
-    return getCurrentOffsets().late.app;
+PhaseOffsets::Offsets PhaseOffsets::getDefaultOffsets(nsecs_t thresholdForNextVsync) {
+    const int64_t vsyncPhaseOffsetNs = sysprop::vsync_event_phase_offset_ns(1000000);
+    const int64_t sfVsyncPhaseOffsetNs = sysprop::vsync_sf_event_phase_offset_ns(1000000);
+
+    const auto earlySfOffsetNs = getProperty("debug.sf.early_phase_offset_ns");
+    const auto earlyGlSfOffsetNs = getProperty("debug.sf.early_gl_phase_offset_ns");
+    const auto earlyAppOffsetNs = getProperty("debug.sf.early_app_phase_offset_ns");
+    const auto earlyGlAppOffsetNs = getProperty("debug.sf.early_gl_app_phase_offset_ns");
+
+    return {{RefreshRateType::DEFAULT, earlySfOffsetNs.value_or(sfVsyncPhaseOffsetNs),
+             earlyAppOffsetNs.value_or(vsyncPhaseOffsetNs)},
+
+            {RefreshRateType::DEFAULT, earlyGlSfOffsetNs.value_or(sfVsyncPhaseOffsetNs),
+             earlyGlAppOffsetNs.value_or(vsyncPhaseOffsetNs)},
+
+            {RefreshRateType::DEFAULT, sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs},
+
+            thresholdForNextVsync};
 }
 
-nsecs_t PhaseOffsets::getCurrentSfOffset() {
-    return getCurrentOffsets().late.sf;
+PhaseOffsets::Offsets PhaseOffsets::getHighFpsOffsets(nsecs_t thresholdForNextVsync) {
+    // TODO(b/122905996): Define these in device.mk.
+    const int highFpsLateAppOffsetNs =
+            getProperty("debug.sf.high_fps_late_app_phase_offset_ns").value_or(2000000);
+    const int highFpsLateSfOffsetNs =
+            getProperty("debug.sf.high_fps_late_sf_phase_offset_ns").value_or(1000000);
+
+    const auto highFpsEarlySfOffsetNs = getProperty("debug.sf.high_fps_early_phase_offset_ns");
+    const auto highFpsEarlyGlSfOffsetNs = getProperty("debug.sf.high_fps_early_gl_phase_offset_ns");
+    const auto highFpsEarlyAppOffsetNs = getProperty("debug.sf.high_fps_early_app_phase_offset_ns");
+    const auto highFpsEarlyGlAppOffsetNs =
+            getProperty("debug.sf.high_fps_early_gl_app_phase_offset_ns");
+
+    return {{RefreshRateType::PERFORMANCE, highFpsEarlySfOffsetNs.value_or(highFpsLateSfOffsetNs),
+             highFpsEarlyAppOffsetNs.value_or(highFpsLateAppOffsetNs)},
+
+            {RefreshRateType::PERFORMANCE, highFpsEarlyGlSfOffsetNs.value_or(highFpsLateSfOffsetNs),
+             highFpsEarlyGlAppOffsetNs.value_or(highFpsLateAppOffsetNs)},
+
+            {RefreshRateType::PERFORMANCE, highFpsLateSfOffsetNs, highFpsLateAppOffsetNs},
+
+            thresholdForNextVsync};
 }
 
 } // namespace impl
-} // namespace scheduler
-} // namespace android
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
index 2b5c2f1..2c52432 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.h
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -16,14 +16,12 @@
 
 #pragma once
 
-#include <cinttypes>
 #include <unordered_map>
 
 #include "RefreshRateConfigs.h"
 #include "VSyncModulator.h"
 
-namespace android {
-namespace scheduler {
+namespace android::scheduler {
 
 /*
  * This class encapsulates offsets for different refresh rates. Depending
@@ -33,35 +31,33 @@
  */
 class PhaseOffsets {
 public:
-    struct Offsets {
-        VSyncModulator::Offsets early;
-        VSyncModulator::Offsets earlyGl;
-        VSyncModulator::Offsets late;
-    };
+    using Offsets = VSyncModulator::OffsetsConfig;
+    using RefreshRateType = RefreshRateConfigs::RefreshRateType;
 
     virtual ~PhaseOffsets();
 
-    virtual nsecs_t getCurrentAppOffset() = 0;
-    virtual nsecs_t getCurrentSfOffset() = 0;
-    virtual Offsets getOffsetsForRefreshRate(
-            RefreshRateConfigs::RefreshRateType refreshRateType) const = 0;
+    nsecs_t getCurrentAppOffset() const { return getCurrentOffsets().late.app; }
+    nsecs_t getCurrentSfOffset() const { return getCurrentOffsets().late.sf; }
+    nsecs_t getOffsetThresholdForNextVsync() const {
+        return getCurrentOffsets().thresholdForNextVsync;
+    }
+
     virtual Offsets getCurrentOffsets() const = 0;
-    virtual void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) = 0;
-    virtual nsecs_t getOffsetThresholdForNextVsync() const = 0;
+    virtual Offsets getOffsetsForRefreshRate(RefreshRateType) const = 0;
+
+    virtual void setRefreshRateType(RefreshRateType) = 0;
+
     virtual void dump(std::string& result) const = 0;
 };
 
 namespace impl {
+
 class PhaseOffsets : public scheduler::PhaseOffsets {
 public:
     PhaseOffsets();
 
-    nsecs_t getCurrentAppOffset() override;
-    nsecs_t getCurrentSfOffset() override;
-
     // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate.
-    Offsets getOffsetsForRefreshRate(
-            RefreshRateConfigs::RefreshRateType refreshRateType) const override;
+    Offsets getOffsetsForRefreshRate(RefreshRateType) const override;
 
     // Returns early, early GL, and late offsets for Apps and SF.
     Offsets getCurrentOffsets() const override {
@@ -70,23 +66,21 @@
 
     // This function should be called when the device is switching between different
     // refresh rates, to properly update the offsets.
-    void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) override {
+    void setRefreshRateType(RefreshRateType refreshRateType) override {
         mRefreshRateType = refreshRateType;
     }
 
-    nsecs_t getOffsetThresholdForNextVsync() const override { return mOffsetThresholdForNextVsync; }
-
     // Returns current offsets in human friendly format.
     void dump(std::string& result) const override;
 
 private:
-    std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType =
-            RefreshRateConfigs::RefreshRateType::DEFAULT;
+    static Offsets getDefaultOffsets(nsecs_t thresholdForNextVsync);
+    static Offsets getHighFpsOffsets(nsecs_t thresholdForNextVsync);
 
-    std::unordered_map<RefreshRateConfigs::RefreshRateType, Offsets> mOffsets;
-    nsecs_t mOffsetThresholdForNextVsync;
+    std::atomic<RefreshRateType> mRefreshRateType = RefreshRateType::DEFAULT;
+
+    std::unordered_map<RefreshRateType, Offsets> mOffsets;
 };
-} // namespace impl
 
-} // namespace scheduler
-} // namespace android
+} // namespace impl
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index a194106..952643c 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -38,9 +38,9 @@
 #include "DispSyncSource.h"
 #include "EventControlThread.h"
 #include "EventThread.h"
-#include "IdleTimer.h"
 #include "InjectVSyncSource.h"
 #include "LayerInfo.h"
+#include "OneShotTimer.h"
 #include "SchedulerUtils.h"
 #include "SurfaceFlingerProperties.h"
 
@@ -87,45 +87,39 @@
 
     if (mSetIdleTimerMs > 0) {
         if (mSupportKernelTimer) {
-            mIdleTimer =
-                    std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(
-                                                                   mSetIdleTimerMs),
-                                                           [this] { resetKernelTimerCallback(); },
-                                                           [this] {
-                                                               expiredKernelTimerCallback();
-                                                           });
+            mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
+                    std::chrono::milliseconds(mSetIdleTimerMs),
+                    [this] { kernelIdleTimerCallback(TimerState::Reset); },
+                    [this] { kernelIdleTimerCallback(TimerState::Expired); });
         } else {
-            mIdleTimer = std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(
-                                                                        mSetIdleTimerMs),
-                                                                [this] { resetTimerCallback(); },
-                                                                [this] { expiredTimerCallback(); });
+            mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
+                    std::chrono::milliseconds(mSetIdleTimerMs),
+                    [this] { idleTimerCallback(TimerState::Reset); },
+                    [this] { idleTimerCallback(TimerState::Expired); });
         }
         mIdleTimer->start();
     }
 
     if (mSetTouchTimerMs > 0) {
         // Touch events are coming to SF every 100ms, so the timer needs to be higher than that
-        mTouchTimer =
-                std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(mSetTouchTimerMs),
-                                                       [this] { resetTouchTimerCallback(); },
-                                                       [this] { expiredTouchTimerCallback(); });
+        mTouchTimer = std::make_unique<scheduler::OneShotTimer>(
+                std::chrono::milliseconds(mSetTouchTimerMs),
+                [this] { touchTimerCallback(TimerState::Reset); },
+                [this] { touchTimerCallback(TimerState::Expired); });
         mTouchTimer->start();
     }
 
     if (mSetDisplayPowerTimerMs > 0) {
-        mDisplayPowerTimer =
-                std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(
-                                                               mSetDisplayPowerTimerMs),
-                                                       [this] { resetDisplayPowerTimerCallback(); },
-                                                       [this] {
-                                                           expiredDisplayPowerTimerCallback();
-                                                       });
+        mDisplayPowerTimer = std::make_unique<scheduler::OneShotTimer>(
+                std::chrono::milliseconds(mSetDisplayPowerTimerMs),
+                [this] { displayPowerTimerCallback(TimerState::Reset); },
+                [this] { displayPowerTimerCallback(TimerState::Expired); });
         mDisplayPowerTimer->start();
     }
 }
 
 Scheduler::~Scheduler() {
-    // Ensure the IdleTimer thread is joined before we start destroying state.
+    // Ensure the OneShotTimer threads are joined before we start destroying state.
     mDisplayPowerTimer.reset();
     mTouchTimer.reset();
     mIdleTimer.reset();
@@ -371,23 +365,22 @@
     RefreshRateType newRefreshRateType;
     {
         std::lock_guard<std::mutex> lock(mFeatureStateLock);
-        if (mContentRefreshRate == refreshRateRound && mIsHDRContent == isHDR) {
+        if (mFeatures.contentRefreshRate == refreshRateRound && mFeatures.isHDRContent == isHDR) {
             return;
         }
-        mContentRefreshRate = refreshRateRound;
-        ATRACE_INT("ContentFPS", mContentRefreshRate);
+        mFeatures.contentRefreshRate = refreshRateRound;
+        ATRACE_INT("ContentFPS", refreshRateRound);
 
-        mIsHDRContent = isHDR;
-        ATRACE_INT("ContentHDR", mIsHDRContent);
+        mFeatures.isHDRContent = isHDR;
+        ATRACE_INT("ContentHDR", isHDR);
 
-        mCurrentContentFeatureState = refreshRateRound > 0
-                ? ContentFeatureState::CONTENT_DETECTION_ON
-                : ContentFeatureState::CONTENT_DETECTION_OFF;
+        mFeatures.contentDetection =
+                refreshRateRound > 0 ? ContentDetectionState::On : ContentDetectionState::Off;
         newRefreshRateType = calculateRefreshRateType();
-        if (mRefreshRateType == newRefreshRateType) {
+        if (mFeatures.refreshRateType == newRefreshRateType) {
             return;
         }
-        mRefreshRateType = newRefreshRateType;
+        mFeatures.refreshRateType = newRefreshRateType;
     }
     changeRefreshRate(newRefreshRateType, ConfigEvent::Changed);
 }
@@ -441,7 +434,7 @@
 void Scheduler::setDisplayPowerState(bool normal) {
     {
         std::lock_guard<std::mutex> lock(mFeatureStateLock);
-        mIsDisplayPowerStateNormal = normal;
+        mFeatures.isDisplayPowerStateNormal = normal;
     }
 
     if (mDisplayPowerTimer) {
@@ -453,60 +446,41 @@
     mLayerHistory.clearHistory();
 }
 
-void Scheduler::resetTimerCallback() {
-    handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::RESET, false);
-    ATRACE_INT("ExpiredIdleTimer", 0);
-}
+void Scheduler::kernelIdleTimerCallback(TimerState state) {
+    ATRACE_INT("ExpiredKernelIdleTimer", static_cast<int>(state));
 
-void Scheduler::resetKernelTimerCallback() {
-    ATRACE_INT("ExpiredKernelIdleTimer", 0);
     std::lock_guard<std::mutex> lock(mCallbackLock);
-    if (mGetVsyncPeriod && mGetCurrentRefreshRateTypeCallback) {
+    if (!mGetCurrentRefreshRateTypeCallback || !mGetVsyncPeriod) return;
+
+    const auto type = mGetCurrentRefreshRateTypeCallback();
+    if (state == TimerState::Reset && type == RefreshRateType::PERFORMANCE) {
         // If we're not in performance mode then the kernel timer shouldn't do
         // anything, as the refresh rate during DPU power collapse will be the
         // same.
-        if (mGetCurrentRefreshRateTypeCallback() == Scheduler::RefreshRateType::PERFORMANCE) {
-            resyncToHardwareVsync(true, mGetVsyncPeriod());
-        }
+        resyncToHardwareVsync(true /* makeAvailable */, mGetVsyncPeriod());
+    } else if (state == TimerState::Expired && type != RefreshRateType::PERFORMANCE) {
+        // Disable HW VSYNC if the timer expired, as we don't need it enabled if
+        // we're not pushing frames, and if we're in PERFORMANCE mode then we'll
+        // need to update the DispSync model anyway.
+        disableHardwareVsync(false /* makeUnavailable */);
     }
 }
 
-void Scheduler::expiredTimerCallback() {
-    handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::EXPIRED, false);
-    ATRACE_INT("ExpiredIdleTimer", 1);
+void Scheduler::idleTimerCallback(TimerState state) {
+    handleTimerStateChanged(&mFeatures.idleTimer, state, false /* eventOnContentDetection */);
+    ATRACE_INT("ExpiredIdleTimer", static_cast<int>(state));
 }
 
-void Scheduler::resetTouchTimerCallback() {
-    handleTimerStateChanged(&mCurrentTouchState, TouchState::ACTIVE, true);
-    ATRACE_INT("TouchState", 1);
+void Scheduler::touchTimerCallback(TimerState state) {
+    const TouchState touch = state == TimerState::Reset ? TouchState::Active : TouchState::Inactive;
+    handleTimerStateChanged(&mFeatures.touch, touch, true /* eventOnContentDetection */);
+    ATRACE_INT("TouchState", static_cast<int>(touch));
 }
 
-void Scheduler::expiredTouchTimerCallback() {
-    handleTimerStateChanged(&mCurrentTouchState, TouchState::INACTIVE, true);
-    ATRACE_INT("TouchState", 0);
-}
-
-void Scheduler::resetDisplayPowerTimerCallback() {
-    handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::RESET, true);
-    ATRACE_INT("ExpiredDisplayPowerTimer", 0);
-}
-
-void Scheduler::expiredDisplayPowerTimerCallback() {
-    handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::EXPIRED, true);
-    ATRACE_INT("ExpiredDisplayPowerTimer", 1);
-}
-
-void Scheduler::expiredKernelTimerCallback() {
-    std::lock_guard<std::mutex> lock(mCallbackLock);
-    ATRACE_INT("ExpiredKernelIdleTimer", 1);
-    if (mGetCurrentRefreshRateTypeCallback) {
-        if (mGetCurrentRefreshRateTypeCallback() != Scheduler::RefreshRateType::PERFORMANCE) {
-            // Disable HW Vsync if the timer expired, as we don't need it
-            // enabled if we're not pushing frames, and if we're in PERFORMANCE
-            // mode then we'll need to re-update the DispSync model anyways.
-            disableHardwareVsync(false);
-        }
-    }
+void Scheduler::displayPowerTimerCallback(TimerState state) {
+    handleTimerStateChanged(&mFeatures.displayPowerTimer, state,
+                            true /* eventOnContentDetection */);
+    ATRACE_INT("ExpiredDisplayPowerTimer", static_cast<int>(state));
 }
 
 std::string Scheduler::doDump() {
@@ -527,12 +501,11 @@
         }
         *currentState = newState;
         newRefreshRateType = calculateRefreshRateType();
-        if (mRefreshRateType == newRefreshRateType) {
+        if (mFeatures.refreshRateType == newRefreshRateType) {
             return;
         }
-        mRefreshRateType = newRefreshRateType;
-        if (eventOnContentDetection &&
-            mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_ON) {
+        mFeatures.refreshRateType = newRefreshRateType;
+        if (eventOnContentDetection && mFeatures.contentDetection == ContentDetectionState::On) {
             event = ConfigEvent::Changed;
         }
     }
@@ -541,37 +514,38 @@
 
 Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() {
     // HDR content is not supported on PERFORMANCE mode
-    if (mForceHDRContentToDefaultRefreshRate && mIsHDRContent) {
+    if (mForceHDRContentToDefaultRefreshRate && mFeatures.isHDRContent) {
         return RefreshRateType::DEFAULT;
     }
 
     // If Display Power is not in normal operation we want to be in performance mode.
     // When coming back to normal mode, a grace period is given with DisplayPowerTimer
-    if (!mIsDisplayPowerStateNormal || mDisplayPowerTimerState == DisplayPowerTimerState::RESET) {
+    if (!mFeatures.isDisplayPowerStateNormal || mFeatures.displayPowerTimer == TimerState::Reset) {
         return RefreshRateType::PERFORMANCE;
     }
 
     // As long as touch is active we want to be in performance mode
-    if (mCurrentTouchState == TouchState::ACTIVE) {
+    if (mFeatures.touch == TouchState::Active) {
         return RefreshRateType::PERFORMANCE;
     }
 
     // If timer has expired as it means there is no new content on the screen
-    if (mCurrentIdleTimerState == IdleTimerState::EXPIRED) {
+    if (mFeatures.idleTimer == TimerState::Expired) {
         return RefreshRateType::DEFAULT;
     }
 
     // If content detection is off we choose performance as we don't know the content fps
-    if (mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_OFF) {
+    if (mFeatures.contentDetection == ContentDetectionState::Off) {
         return RefreshRateType::PERFORMANCE;
     }
 
     // Content detection is on, find the appropriate refresh rate with minimal error
+    const float rate = static_cast<float>(mFeatures.contentRefreshRate);
     auto iter = min_element(mRefreshRateConfigs.getRefreshRates().cbegin(),
                             mRefreshRateConfigs.getRefreshRates().cend(),
-                            [rate = mContentRefreshRate](const auto& l, const auto& r) -> bool {
-                                return std::abs(l.second->fps - static_cast<float>(rate)) <
-                                        std::abs(r.second->fps - static_cast<float>(rate));
+                            [rate](const auto& lhs, const auto& rhs) -> bool {
+                                return std::abs(lhs.second->fps - rate) <
+                                        std::abs(rhs.second->fps - rate);
                             });
     RefreshRateType currRefreshRateType = iter->first;
 
@@ -579,11 +553,10 @@
     // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't
     // align well with both
     constexpr float MARGIN = 0.05f;
-    float ratio = mRefreshRateConfigs.getRefreshRate(currRefreshRateType)->fps /
-            float(mContentRefreshRate);
+    float ratio = mRefreshRateConfigs.getRefreshRate(currRefreshRateType)->fps / rate;
     if (std::abs(std::round(ratio) - ratio) > MARGIN) {
         while (iter != mRefreshRateConfigs.getRefreshRates().cend()) {
-            ratio = iter->second->fps / float(mContentRefreshRate);
+            ratio = iter->second->fps / rate;
 
             if (std::abs(std::round(ratio) - ratio) <= MARGIN) {
                 currRefreshRateType = iter->first;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 5d8bb4c..0d9d7aa 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -26,9 +26,9 @@
 #include "DispSync.h"
 #include "EventControlThread.h"
 #include "EventThread.h"
-#include "IdleTimer.h"
 #include "InjectVSyncSource.h"
 #include "LayerHistory.h"
+#include "OneShotTimer.h"
 #include "RefreshRateConfigs.h"
 #include "SchedulerUtils.h"
 
@@ -200,10 +200,9 @@
 
     // In order to make sure that the features don't override themselves, we need a state machine
     // to keep track which feature requested the config change.
-    enum class ContentFeatureState { CONTENT_DETECTION_ON, CONTENT_DETECTION_OFF };
-    enum class IdleTimerState { EXPIRED, RESET };
-    enum class TouchState { INACTIVE, ACTIVE };
-    enum class DisplayPowerTimerState { EXPIRED, RESET };
+    enum class ContentDetectionState { Off, On };
+    enum class TimerState { Reset, Expired };
+    enum class TouchState { Inactive, Active };
 
     // Creates a connection on the given EventThread and forwards the given callbacks.
     sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&,
@@ -212,26 +211,12 @@
     nsecs_t calculateAverage() const;
     void updateFrameSkipping(const int64_t skipCount);
 
-    // Function that is called when the timer resets.
-    void resetTimerCallback();
-    // Function that is called when the timer expires.
-    void expiredTimerCallback();
-    // Function that is called when the timer resets when paired with a display
-    // driver timeout in the kernel. This enables hardware vsync when we move
-    // out from idle.
-    void resetKernelTimerCallback();
-    // Function that is called when the timer expires when paired with a display
-    // driver timeout in the kernel. This disables hardware vsync when we move
-    // into idle.
-    void expiredKernelTimerCallback();
-    // Function that is called when the touch timer resets.
-    void resetTouchTimerCallback();
-    // Function that is called when the touch timer expires.
-    void expiredTouchTimerCallback();
-    // Function that is called when the display power timer resets.
-    void resetDisplayPowerTimerCallback();
-    // Function that is called when the display power timer expires.
-    void expiredDisplayPowerTimerCallback();
+    // Update feature state machine to given state when corresponding timer resets or expires.
+    void kernelIdleTimerCallback(TimerState);
+    void idleTimerCallback(TimerState);
+    void touchTimerCallback(TimerState);
+    void displayPowerTimerCallback(TimerState);
+
     // Sets vsync period.
     void setVsyncPeriod(const nsecs_t period);
     // handles various timer features to change the refresh rate.
@@ -283,18 +268,18 @@
     // Timer that records time between requests for next vsync. If the time is higher than a given
     // interval, a callback is fired. Set this variable to >0 to use this feature.
     int64_t mSetIdleTimerMs = 0;
-    std::unique_ptr<scheduler::IdleTimer> mIdleTimer;
+    std::unique_ptr<scheduler::OneShotTimer> mIdleTimer;
     // Enables whether to use idle timer callbacks that support the kernel
     // timer.
     bool mSupportKernelTimer;
 
     // Timer used to monitor touch events.
     int64_t mSetTouchTimerMs = 0;
-    std::unique_ptr<scheduler::IdleTimer> mTouchTimer;
+    std::unique_ptr<scheduler::OneShotTimer> mTouchTimer;
 
     // Timer used to monitor display power mode.
     int64_t mSetDisplayPowerTimerMs = 0;
-    std::unique_ptr<scheduler::IdleTimer> mDisplayPowerTimer;
+    std::unique_ptr<scheduler::OneShotTimer> mDisplayPowerTimer;
 
     std::mutex mCallbackLock;
     GetCurrentRefreshRateTypeCallback mGetCurrentRefreshRateTypeCallback GUARDED_BY(mCallbackLock);
@@ -304,16 +289,19 @@
     // In order to make sure that the features don't override themselves, we need a state machine
     // to keep track which feature requested the config change.
     std::mutex mFeatureStateLock;
-    ContentFeatureState mCurrentContentFeatureState GUARDED_BY(mFeatureStateLock) =
-            ContentFeatureState::CONTENT_DETECTION_OFF;
-    IdleTimerState mCurrentIdleTimerState GUARDED_BY(mFeatureStateLock) = IdleTimerState::RESET;
-    TouchState mCurrentTouchState GUARDED_BY(mFeatureStateLock) = TouchState::INACTIVE;
-    DisplayPowerTimerState mDisplayPowerTimerState GUARDED_BY(mFeatureStateLock) =
-            DisplayPowerTimerState::EXPIRED;
-    uint32_t mContentRefreshRate GUARDED_BY(mFeatureStateLock);
-    RefreshRateType mRefreshRateType GUARDED_BY(mFeatureStateLock);
-    bool mIsHDRContent GUARDED_BY(mFeatureStateLock) = false;
-    bool mIsDisplayPowerStateNormal GUARDED_BY(mFeatureStateLock) = true;
+
+    struct {
+        ContentDetectionState contentDetection = ContentDetectionState::Off;
+        TimerState idleTimer = TimerState::Reset;
+        TouchState touch = TouchState::Inactive;
+        TimerState displayPowerTimer = TimerState::Expired;
+
+        RefreshRateType refreshRateType = RefreshRateType::DEFAULT;
+        uint32_t contentRefreshRate = 0;
+
+        bool isHDRContent = false;
+        bool isDisplayPowerStateNormal = true;
+    } mFeatures GUARDED_BY(mFeatureStateLock);
 
     const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
 
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.cpp b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
index 7a3bf8e..f267c99 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
@@ -24,25 +24,24 @@
 #include <cinttypes>
 #include <mutex>
 
-namespace android {
+namespace android::scheduler {
 
-using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
-VSyncModulator::VSyncModulator() {
+VSyncModulator::VSyncModulator(Scheduler& scheduler,
+                               const sp<Scheduler::ConnectionHandle>& appConnectionHandle,
+                               const sp<Scheduler::ConnectionHandle>& sfConnectionHandle,
+                               const OffsetsConfig& config)
+      : mScheduler(scheduler),
+        mAppConnectionHandle(appConnectionHandle),
+        mSfConnectionHandle(sfConnectionHandle),
+        mOffsetsConfig(config) {
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sf.vsync_trace_detailed_info", value, "0");
     mTraceDetailedInfo = atoi(value);
-    // Populate the offset map with some default offsets.
-    const Offsets defaultOffsets = {RefreshRateType::DEFAULT, 0, 0};
-    setPhaseOffsets(defaultOffsets, defaultOffsets, defaultOffsets, 0);
 }
 
-void VSyncModulator::setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
-                                     nsecs_t thresholdForNextVsync) {
+void VSyncModulator::setPhaseOffsets(const OffsetsConfig& config) {
     std::lock_guard<std::mutex> lock(mMutex);
-    mOffsetMap.insert_or_assign(OffsetType::Early, early);
-    mOffsetMap.insert_or_assign(OffsetType::EarlyGl, earlyGl);
-    mOffsetMap.insert_or_assign(OffsetType::Late, late);
-    mThresholdForNextVsync = thresholdForNextVsync;
+    mOffsetsConfig = config;
     updateOffsetsLocked();
 }
 
@@ -100,25 +99,21 @@
     }
 }
 
-VSyncModulator::Offsets VSyncModulator::getOffsets() {
+VSyncModulator::Offsets VSyncModulator::getOffsets() const {
     std::lock_guard<std::mutex> lock(mMutex);
     return mOffsets;
 }
 
-VSyncModulator::Offsets VSyncModulator::getNextOffsets() {
-    return mOffsetMap.at(getNextOffsetType());
-}
-
-VSyncModulator::OffsetType VSyncModulator::getNextOffsetType() {
+const VSyncModulator::Offsets& VSyncModulator::getNextOffsets() const {
     // Early offsets are used if we're in the middle of a refresh rate
     // change, or if we recently begin a transaction.
     if (mTransactionStart == Scheduler::TransactionStart::EARLY || mRemainingEarlyFrameCount > 0 ||
         mRefreshRateChangePending) {
-        return OffsetType::Early;
+        return mOffsetsConfig.early;
     } else if (mRemainingRenderEngineUsageCount > 0) {
-        return OffsetType::EarlyGl;
+        return mOffsetsConfig.earlyGl;
     } else {
-        return OffsetType::Late;
+        return mOffsetsConfig.late;
     }
 }
 
@@ -128,37 +123,29 @@
 }
 
 void VSyncModulator::updateOffsetsLocked() {
-    const Offsets desired = getNextOffsets();
+    const Offsets& offsets = getNextOffsets();
 
-    if (mSfConnectionHandle != nullptr) {
-        mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf);
-    }
+    mScheduler.setPhaseOffset(mSfConnectionHandle, offsets.sf);
+    mScheduler.setPhaseOffset(mAppConnectionHandle, offsets.app);
 
-    if (mAppConnectionHandle != nullptr) {
-        mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app);
-    }
+    mOffsets = offsets;
 
-    flushOffsets();
-}
-
-void VSyncModulator::flushOffsets() {
-    OffsetType type = getNextOffsetType();
-    mOffsets = mOffsetMap.at(type);
     if (!mTraceDetailedInfo) {
         return;
     }
-    ATRACE_INT("Vsync-EarlyOffsetsOn",
-               mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Early);
-    ATRACE_INT("Vsync-EarlyGLOffsetsOn",
-               mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::EarlyGl);
-    ATRACE_INT("Vsync-LateOffsetsOn",
-               mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Late);
-    ATRACE_INT("Vsync-HighFpsEarlyOffsetsOn",
-               mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Early);
-    ATRACE_INT("Vsync-HighFpsEarlyGLOffsetsOn",
-               mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::EarlyGl);
-    ATRACE_INT("Vsync-HighFpsLateOffsetsOn",
-               mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Late);
+
+    const bool isDefault = mOffsets.fpsMode == RefreshRateType::DEFAULT;
+    const bool isPerformance = mOffsets.fpsMode == RefreshRateType::PERFORMANCE;
+    const bool isEarly = &offsets == &mOffsetsConfig.early;
+    const bool isEarlyGl = &offsets == &mOffsetsConfig.earlyGl;
+    const bool isLate = &offsets == &mOffsetsConfig.late;
+
+    ATRACE_INT("Vsync-EarlyOffsetsOn", isDefault && isEarly);
+    ATRACE_INT("Vsync-EarlyGLOffsetsOn", isDefault && isEarlyGl);
+    ATRACE_INT("Vsync-LateOffsetsOn", isDefault && isLate);
+    ATRACE_INT("Vsync-HighFpsEarlyOffsetsOn", isPerformance && isEarly);
+    ATRACE_INT("Vsync-HighFpsEarlyGLOffsetsOn", isPerformance && isEarlyGl);
+    ATRACE_INT("Vsync-HighFpsLateOffsetsOn", isPerformance && isLate);
 }
 
-} // namespace android
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index ddbd221..636c8c8 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -16,12 +16,11 @@
 
 #pragma once
 
-#include <cinttypes>
 #include <mutex>
 
 #include "Scheduler.h"
 
-namespace android {
+namespace android::scheduler {
 
 /*
  * Modulates the vsync-offsets depending on current SurfaceFlinger state.
@@ -31,51 +30,36 @@
     // Number of frames we'll keep the early phase offsets once they are activated for a
     // transaction. This acts as a low-pass filter in case the client isn't quick enough in
     // sending new transactions.
-    const int MIN_EARLY_FRAME_COUNT_TRANSACTION = 2;
+    static constexpr int MIN_EARLY_FRAME_COUNT_TRANSACTION = 2;
 
     // Number of frames we'll keep the early gl phase offsets once they are activated.
     // This acts as a low-pass filter to avoid scenarios where we rapidly
     // switch in and out of gl composition.
-    const int MIN_EARLY_GL_FRAME_COUNT_TRANSACTION = 2;
+    static constexpr int MIN_EARLY_GL_FRAME_COUNT_TRANSACTION = 2;
+
+    using RefreshRateType = RefreshRateConfigs::RefreshRateType;
 
 public:
-    VSyncModulator();
-
     // Wrapper for a collection of surfaceflinger/app offsets for a particular
-    // configuration .
+    // configuration.
     struct Offsets {
-        scheduler::RefreshRateConfigs::RefreshRateType fpsMode;
+        RefreshRateType fpsMode;
         nsecs_t sf;
         nsecs_t app;
     };
 
-    enum class OffsetType {
-        Early,
-        EarlyGl,
-        Late,
+    struct OffsetsConfig {
+        Offsets early;   // For transactions with the eEarlyWakeup flag.
+        Offsets earlyGl; // As above but while compositing with GL.
+        Offsets late;    // Default.
+
+        nsecs_t thresholdForNextVsync;
     };
 
-    // Sets the phase offsets
-    //
-    // sfEarly: The phase offset when waking up SF early, which happens when marking a transaction
-    //          as early. May be the same as late, in which case we don't shift offsets.
-    // sfEarlyGl: Like sfEarly, but only if we used GL composition. If we use both GL composition
-    //            and the transaction was marked as early, we'll use sfEarly.
-    // sfLate: The regular SF vsync phase offset.
-    // appEarly: Like sfEarly, but for the app-vsync
-    // appEarlyGl: Like sfEarlyGl, but for the app-vsync.
-    // appLate: The regular app vsync phase offset.
-    void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
-                         nsecs_t thresholdForNextVsync) EXCLUDES(mMutex);
+    VSyncModulator(Scheduler&, const sp<Scheduler::ConnectionHandle>& appConnectionHandle,
+                   const sp<Scheduler::ConnectionHandle>& sfConnectionHandle, const OffsetsConfig&);
 
-    // Sets the scheduler and vsync connection handlers.
-    void setSchedulerAndHandles(Scheduler* scheduler,
-                                Scheduler::ConnectionHandle* appConnectionHandle,
-                                Scheduler::ConnectionHandle* sfConnectionHandle) {
-        mScheduler = scheduler;
-        mAppConnectionHandle = appConnectionHandle;
-        mSfConnectionHandle = sfConnectionHandle;
-    }
+    void setPhaseOffsets(const OffsetsConfig&) EXCLUDES(mMutex);
 
     // Signals that a transaction has started, and changes offsets accordingly.
     void setTransactionStart(Scheduler::TransactionStart transactionStart);
@@ -98,28 +82,23 @@
     void onRefreshed(bool usedRenderEngine);
 
     // Returns the offsets that we are currently using
-    Offsets getOffsets() EXCLUDES(mMutex);
+    Offsets getOffsets() const EXCLUDES(mMutex);
 
 private:
     // Returns the next offsets that we should be using
-    Offsets getNextOffsets() REQUIRES(mMutex);
-    // Returns the next offset type that we should use.
-    OffsetType getNextOffsetType();
+    const Offsets& getNextOffsets() const REQUIRES(mMutex);
     // Updates offsets and persists them into the scheduler framework.
     void updateOffsets() EXCLUDES(mMutex);
     void updateOffsetsLocked() REQUIRES(mMutex);
-    // Updates the internal offsets and offset type.
-    void flushOffsets() REQUIRES(mMutex);
+
+    Scheduler& mScheduler;
+    const sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
+    const sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
 
     mutable std::mutex mMutex;
-    std::unordered_map<OffsetType, Offsets> mOffsetMap GUARDED_BY(mMutex);
-    nsecs_t mThresholdForNextVsync;
+    OffsetsConfig mOffsetsConfig GUARDED_BY(mMutex);
 
-    Scheduler* mScheduler = nullptr;
-    Scheduler::ConnectionHandle* mAppConnectionHandle = nullptr;
-    Scheduler::ConnectionHandle* mSfConnectionHandle = nullptr;
-
-    Offsets mOffsets GUARDED_BY(mMutex) = {Scheduler::RefreshRateType::DEFAULT, 0, 0};
+    Offsets mOffsets GUARDED_BY(mMutex){mOffsetsConfig.late};
 
     std::atomic<Scheduler::TransactionStart> mTransactionStart =
             Scheduler::TransactionStart::NORMAL;
@@ -130,4 +109,4 @@
     bool mTraceDetailedInfo = false;
 };
 
-} // namespace android
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d829337..d158467 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -38,6 +38,7 @@
 #include <binder/PermissionCache.h>
 
 #include <compositionengine/CompositionEngine.h>
+#include <compositionengine/CompositionRefreshArgs.h>
 #include <compositionengine/Display.h>
 #include <compositionengine/DisplayColorProfile.h>
 #include <compositionengine/Layer.h>
@@ -162,28 +163,6 @@
     return false;
 }
 
-bool isHdrColorMode(const ColorMode colorMode) {
-    switch (colorMode) {
-        case ColorMode::BT2100_PQ:
-        case ColorMode::BT2100_HLG:
-            return true;
-        case ColorMode::DISPLAY_P3:
-        case ColorMode::ADOBE_RGB:
-        case ColorMode::DCI_P3:
-        case ColorMode::BT2020:
-        case ColorMode::DISPLAY_BT2020:
-        case ColorMode::NATIVE:
-        case ColorMode::STANDARD_BT601_625:
-        case ColorMode::STANDARD_BT601_625_UNADJUSTED:
-        case ColorMode::STANDARD_BT601_525:
-        case ColorMode::STANDARD_BT601_525_UNADJUSTED:
-        case ColorMode::STANDARD_BT709:
-        case ColorMode::SRGB:
-            return false;
-    }
-    return false;
-}
-
 ui::Transform::orientation_flags fromSurfaceComposerRotation(ISurfaceComposer::Rotation rotation) {
     switch (rotation) {
         case ISurfaceComposer::eRotateNone:
@@ -276,11 +255,11 @@
 
 SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
       : mFactory(factory),
-        mPhaseOffsets(mFactory.createPhaseOffsets()),
         mInterceptor(mFactory.createSurfaceInterceptor(this)),
         mTimeStats(mFactory.createTimeStats()),
         mEventQueue(mFactory.createMessageQueue()),
-        mCompositionEngine(mFactory.createCompositionEngine()) {}
+        mCompositionEngine(mFactory.createCompositionEngine()),
+        mPhaseOffsets(mFactory.createPhaseOffsets()) {}
 
 SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) {
     ALOGI("SurfaceFlinger is starting");
@@ -386,10 +365,6 @@
     property_get("debug.sf.luma_sampling", value, "1");
     mLumaSampling = atoi(value);
 
-    const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-    mVsyncModulator.setPhaseOffsets(early, gl, late,
-                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
-
     // We should be reading 'persist.sys.sf.color_saturation' here
     // but since /data may be encrypted, we need to wait until after vold
     // comes online to attempt to read the property. The property is
@@ -616,7 +591,7 @@
     ALOGI(  "SurfaceFlinger's main thread ready to run. "
             "Initializing graphics H/W...");
 
-    ALOGI("Phase offset NS: %" PRId64 "", mPhaseOffsets->getCurrentAppOffset());
+    ALOGI("Phase offset: %" PRId64 " ns", mPhaseOffsets->getCurrentAppOffset());
 
     Mutex::Autolock _l(mStateLock);
     // start the EventThread
@@ -627,20 +602,21 @@
             mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
 
     mAppConnectionHandle =
-            mScheduler->createConnection("app", mVsyncModulator.getOffsets().app,
+            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
                                          mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                          resyncCallback,
                                          impl::EventThread::InterceptVSyncsCallback());
     mSfConnectionHandle =
-            mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
+            mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
                                          mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                          resyncCallback, [this](nsecs_t timestamp) {
                                              mInterceptor->saveVSyncEvent(timestamp);
                                          });
 
     mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
-    mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
-                                           mSfConnectionHandle.get());
+
+    mVSyncModulator.emplace(*mScheduler, mAppConnectionHandle, mSfConnectionHandle,
+                            mPhaseOffsets->getCurrentOffsets());
 
     mRegionSamplingThread =
             new RegionSamplingThread(*this, *mScheduler,
@@ -703,7 +679,11 @@
     // set initial conditions (e.g. unblank default device)
     initializeDisplays();
 
-    getRenderEngine().primeCache();
+    char primeShaderCache[PROPERTY_VALUE_MAX];
+    property_get("service.sf.prime_shader_cache", primeShaderCache, "1");
+    if (atoi(primeShaderCache)) {
+        getRenderEngine().primeCache();
+    }
 
     // Inform native graphics APIs whether the present timestamp is supported:
 
@@ -969,14 +949,11 @@
         mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
         // As we called to set period, we will call to onRefreshRateChangeCompleted once
         // DispSync model is locked.
-        mVsyncModulator.onRefreshRateChangeInitiated();
+        mVSyncModulator->onRefreshRateChangeInitiated();
         mPhaseOffsets->setRefreshRateType(info.type);
-        const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-        mVsyncModulator.setPhaseOffsets(early, gl, late,
-                                        mPhaseOffsets->getOffsetThresholdForNextVsync());
+        mVSyncModulator->setPhaseOffsets(mPhaseOffsets->getCurrentOffsets());
     }
     mDesiredActiveConfigChanged = true;
-    ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
 
     if (mRefreshRateOverlay) {
         mRefreshRateOverlay->changeRefreshRate(mDesiredActiveConfig.type);
@@ -1006,9 +983,7 @@
     display->setActiveConfig(mUpcomingActiveConfig.configId);
 
     mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type);
-    const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-    mVsyncModulator.setPhaseOffsets(early, gl, late,
-                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
+    mVSyncModulator->setPhaseOffsets(mPhaseOffsets->getCurrentOffsets());
     ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);
 
     if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) {
@@ -1021,13 +996,10 @@
     std::lock_guard<std::mutex> lock(mActiveConfigLock);
     mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
     mDesiredActiveConfigChanged = false;
-    ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
 
     mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
     mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type);
-    const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-    mVsyncModulator.setPhaseOffsets(early, gl, late,
-                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
+    mVSyncModulator->setPhaseOffsets(mPhaseOffsets->getCurrentOffsets());
 }
 
 bool SurfaceFlinger::performSetActiveConfig() {
@@ -1160,7 +1132,8 @@
                   decodeColorMode(mode).c_str(), mode);
         } else {
             display->getCompositionDisplay()->setColorMode(mode, Dataspace::UNKNOWN,
-                                                           RenderIntent::COLORIMETRIC);
+                                                           RenderIntent::COLORIMETRIC,
+                                                           Dataspace::UNKNOWN);
         }
     }));
 
@@ -1494,7 +1467,7 @@
     bool periodFlushed = false;
     mScheduler->addResyncSample(timestamp, &periodFlushed);
     if (periodFlushed) {
-        mVsyncModulator.onRefreshRateChangeCompleted();
+        mVSyncModulator->onRefreshRateChangeCompleted();
     }
 }
 
@@ -1503,7 +1476,7 @@
     *compositorTiming = getBE().mCompositorTiming;
 }
 
-bool SurfaceFlinger::isDisplayConfigAllowed(int32_t configId) {
+bool SurfaceFlinger::isDisplayConfigAllowed(int32_t configId) const {
     return mAllowedDisplayConfigs.empty() || mAllowedDisplayConfigs.count(configId);
 }
 
@@ -1686,22 +1659,22 @@
     // woken up before the actual vsync but targeting the next vsync, we need to check
     // fence N-2
     const sp<Fence>& fence =
-            mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync()
+            mVSyncModulator->getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync()
             ? mPreviousPresentFences[0]
             : mPreviousPresentFences[1];
 
     return fence != Fence::NO_FENCE && (fence->getStatus() == Fence::Status::Unsignaled);
 }
 
-void SurfaceFlinger::populateExpectedPresentTime() NO_THREAD_SAFETY_ANALYSIS {
+void SurfaceFlinger::populateExpectedPresentTime() {
     DisplayStatInfo stats;
     mScheduler->getDisplayStatInfo(&stats);
     const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime();
     // Inflate the expected present time if we're targetting the next vsync.
-    mExpectedPresentTime =
-            mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync()
-            ? presentTime
-            : presentTime + stats.vsyncPeriod;
+    mExpectedPresentTime.store(mVSyncModulator->getOffsets().sf <
+                                               mPhaseOffsets->getOffsetThresholdForNextVsync()
+                                       ? presentTime
+                                       : presentTime + stats.vsyncPeriod);
 }
 
 void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {
@@ -1713,12 +1686,12 @@
             // seeing this same value.
             populateExpectedPresentTime();
 
-            bool frameMissed = previousFrameMissed();
-            bool hwcFrameMissed = mHadDeviceComposition && frameMissed;
-            bool gpuFrameMissed = mHadClientComposition && frameMissed;
-            ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
-            ATRACE_INT("HwcFrameMissed", static_cast<int>(hwcFrameMissed));
-            ATRACE_INT("GpuFrameMissed", static_cast<int>(gpuFrameMissed));
+            const TracedOrdinal<bool> frameMissed = {"FrameMissed", previousFrameMissed()};
+            const TracedOrdinal<bool> hwcFrameMissed = {"HwcFrameMissed",
+                                                        mHadDeviceComposition && frameMissed};
+            const TracedOrdinal<bool> gpuFrameMissed = {"GpuFrameMissed",
+                                                        mHadClientComposition && frameMissed};
+
             if (frameMissed) {
                 mFrameMissedCount++;
                 mTimeStats->incrementMissedFrames();
@@ -1804,13 +1777,22 @@
 
     mRefreshPending = false;
 
+    compositionengine::CompositionRefreshArgs refreshArgs;
+    for (const auto& [_, display] : mDisplays) {
+        refreshArgs.outputs.push_back(display->getCompositionDisplay());
+    }
+    mDrawingState.traverseInZOrder([&refreshArgs](Layer* layer) {
+        auto compositionLayer = layer->getCompositionLayer();
+        if (compositionLayer) refreshArgs.layers.push_back(compositionLayer);
+    });
+
     const bool repaintEverything = mRepaintEverything.exchange(false);
-    preComposition();
+    mCompositionEngine->preComposition(refreshArgs);
     rebuildLayerStacks();
     calculateWorkingSet();
     for (const auto& [token, display] : mDisplays) {
         beginFrame(display);
-        prepareFrame(display);
+        display->getCompositionDisplay()->prepareFrame();
         doDebugFlashRegions(display, repaintEverything);
         doComposition(display, repaintEverything);
     }
@@ -1820,20 +1802,30 @@
     postFrame();
     postComposition();
 
-    mHadClientComposition = false;
-    mHadDeviceComposition = false;
-    for (const auto& [token, displayDevice] : mDisplays) {
-        auto display = displayDevice->getCompositionDisplay();
-        const auto displayId = display->getId();
-        mHadClientComposition =
-                mHadClientComposition || getHwComposer().hasClientComposition(displayId);
-        mHadDeviceComposition =
-                mHadDeviceComposition || getHwComposer().hasDeviceComposition(displayId);
-    }
+    mHadClientComposition =
+            std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) {
+                auto& displayDevice = tokenDisplayPair.second;
+                return displayDevice->getCompositionDisplay()->getState().usesClientComposition;
+            });
+    mHadDeviceComposition =
+            std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) {
+                auto& displayDevice = tokenDisplayPair.second;
+                return displayDevice->getCompositionDisplay()->getState().usesDeviceComposition;
+            });
 
-    mVsyncModulator.onRefreshed(mHadClientComposition);
+    mVSyncModulator->onRefreshed(mHadClientComposition);
 
     mLayersWithQueuedFrames.clear();
+    if (mVisibleRegionsDirty) {
+        mVisibleRegionsDirty = false;
+        if (mTracingEnabled) {
+            mTracing.notify("visibleRegionsDirty");
+        }
+    }
+
+    if (mCompositionEngine->needsAnotherUpdate()) {
+        signalLayerUpdate();
+    }
 }
 
 
@@ -1843,9 +1835,6 @@
 
     if (mVisibleRegionsDirty) {
         computeLayerBounds();
-        if (mTracingEnabled) {
-            mTracing.notify("visibleRegionsDirty");
-        }
     }
 
     for (auto& layer : mLayersPendingRefresh) {
@@ -1861,104 +1850,80 @@
     ATRACE_CALL();
     ALOGV(__FUNCTION__);
 
-    // build the h/w work list
-    if (CC_UNLIKELY(mGeometryInvalid)) {
-        mGeometryInvalid = false;
+    const bool updatingGeometryThisFrame = mGeometryInvalid;
+    mGeometryInvalid = false;
+
+    {
+        // Use a map so that we latch the state of each front-end layer once.
+        std::unordered_map<compositionengine::LayerFE*, compositionengine::LayerFECompositionState*>
+                uniqueVisibleLayers;
+
+        // Figure out which frontend layers are being composed, and build the unique
+        // set of them (and the corresponding composition layer)
         for (const auto& [token, displayDevice] : mDisplays) {
             auto display = displayDevice->getCompositionDisplay();
+            for (auto& layer : display->getOutputLayersOrderedByZ()) {
+                uniqueVisibleLayers.insert(std::make_pair(&layer->getLayerFE(),
+                                                          &layer->getLayer().editState().frontEnd));
+            }
+        }
 
+        // Update the composition state from each front-end layer.
+        for (auto& [layerFE, state] : uniqueVisibleLayers) {
+            layerFE->latchCompositionState(*state, updatingGeometryThisFrame);
+        }
+    }
+
+    if (CC_UNLIKELY(updatingGeometryThisFrame)) {
+        for (const auto& [token, displayDevice] : mDisplays) {
+            auto display = displayDevice->getCompositionDisplay();
             uint32_t zOrder = 0;
 
             for (auto& layer : display->getOutputLayersOrderedByZ()) {
-                auto& compositionState = layer->editState();
-                compositionState.forceClientComposition = false;
-                if (!compositionState.hwc || mDebugDisableHWC || mDebugRegion) {
-                    compositionState.forceClientComposition = true;
-                }
-
-                // The output Z order is set here based on a simple counter.
-                compositionState.z = zOrder++;
-
-                // Update the display independent composition state. This goes
-                // to the general composition layer state structure.
-                // TODO: Do this once per compositionengine::CompositionLayer.
-                layer->getLayerFE().latchCompositionState(layer->getLayer().editState().frontEnd,
-                                                          true);
-
-                // Recalculate the geometry state of the output layer.
-                layer->updateCompositionState(true);
-
-                // Write the updated geometry state to the HWC
-                layer->writeStateToHWC(true);
+                // Assign a simple Z order sequence to each visible layer.
+                layer->editState().z = zOrder++;
             }
         }
     }
 
-    // Set the per-frame data
+    // Determine the color configuration of each output
     for (const auto& [token, displayDevice] : mDisplays) {
         auto display = displayDevice->getCompositionDisplay();
-        const auto displayId = display->getId();
-        if (!displayId) {
-            continue;
-        }
-        auto* profile = display->getDisplayColorProfile();
 
-        if (mDrawingState.colorMatrixChanged) {
+        ColorMode colorMode = ColorMode::NATIVE;
+        Dataspace dataspace = Dataspace::UNKNOWN;
+        RenderIntent renderIntent = RenderIntent::COLORIMETRIC;
+        if (useColorManagement) {
+            pickColorMode(displayDevice, &colorMode, &dataspace, &renderIntent);
+        }
+        display->setColorMode(colorMode, dataspace, renderIntent, mColorSpaceAgnosticDataspace);
+    }
+
+    for (const auto& [token, displayDevice] : mDisplays) {
+        auto display = displayDevice->getCompositionDisplay();
+
+        for (auto& layer : display->getOutputLayersOrderedByZ()) {
+            // Update the composition state of the output layer, as needed
+            // recomputing it from the state given by the front-end layer.
+            layer->updateCompositionState(updatingGeometryThisFrame);
+        }
+    }
+
+    for (const auto& [token, displayDevice] : mDisplays) {
+        auto display = displayDevice->getCompositionDisplay();
+
+        for (auto& layer : display->getOutputLayersOrderedByZ()) {
+            // Send the updated state to the HWC, if appropriate.
+            layer->writeStateToHWC(updatingGeometryThisFrame);
+        }
+    }
+
+    if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) {
+        for (const auto& [token, displayDevice] : mDisplays) {
+            auto display = displayDevice->getCompositionDisplay();
             display->setColorTransform(mDrawingState.colorMatrix);
         }
-        Dataspace targetDataspace = Dataspace::UNKNOWN;
-        if (useColorManagement) {
-            ColorMode colorMode;
-            RenderIntent renderIntent;
-            pickColorMode(displayDevice, &colorMode, &targetDataspace, &renderIntent);
-            display->setColorMode(colorMode, targetDataspace, renderIntent);
-
-            if (isHdrColorMode(colorMode)) {
-                targetDataspace = Dataspace::UNKNOWN;
-            } else if (mColorSpaceAgnosticDataspace != Dataspace::UNKNOWN) {
-                targetDataspace = mColorSpaceAgnosticDataspace;
-            }
-        }
-
-        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
-            if (layer->isHdrY410()) {
-                layer->forceClientComposition(displayDevice);
-            } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
-                        layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
-                       !profile->hasHDR10Support()) {
-                layer->forceClientComposition(displayDevice);
-            } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
-                        layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
-                       !profile->hasHLGSupport()) {
-                layer->forceClientComposition(displayDevice);
-            }
-
-            if (layer->getRoundedCornerState().radius > 0.0f) {
-                layer->forceClientComposition(displayDevice);
-            }
-
-            if (layer->getForceClientComposition(displayDevice)) {
-                ALOGV("[%s] Requesting Client composition", layer->getName().string());
-                layer->setCompositionType(displayDevice,
-                                          Hwc2::IComposerClient::Composition::CLIENT);
-                continue;
-            }
-
-            const auto& displayState = display->getState();
-            layer->setPerFrameData(displayDevice, displayState.transform, displayState.viewport,
-                                   displayDevice->getSupportedPerFrameMetadata(), targetDataspace);
-        }
-    }
-
-    mDrawingState.colorMatrixChanged = false;
-
-    for (const auto& [token, displayDevice] : mDisplays) {
-        auto display = displayDevice->getCompositionDisplay();
-        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
-            auto& layerState = layer->getCompositionLayer()->editState().frontEnd;
-            layerState.compositionType = static_cast<Hwc2::IComposerClient::Composition>(
-                    layer->getCompositionType(displayDevice));
-        }
+        mDrawingState.colorMatrixChanged = false;
     }
 }
 
@@ -1983,13 +1948,13 @@
         }
     }
 
-    postFramebuffer(displayDevice);
+    displayDevice->getCompositionDisplay()->postFramebuffer();
 
     if (mDebugRegion > 1) {
         usleep(mDebugRegion * 1000);
     }
 
-    prepareFrame(displayDevice);
+    displayDevice->getCompositionDisplay()->prepareFrame();
 }
 
 void SurfaceFlinger::logLayerStats() {
@@ -2006,25 +1971,6 @@
     }
 }
 
-void SurfaceFlinger::preComposition()
-{
-    ATRACE_CALL();
-    ALOGV("preComposition");
-
-    mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    bool needExtraInvalidate = false;
-    mDrawingState.traverseInZOrder([&](Layer* layer) {
-        if (layer->onPreComposition(mRefreshStartTime)) {
-            needExtraInvalidate = true;
-        }
-    });
-
-    if (needExtraInvalidate) {
-        signalLayerUpdate();
-    }
-}
-
 void SurfaceFlinger::updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
                                             std::shared_ptr<FenceTime>& presentFenceTime) {
     // Update queue of past composite+present times and determine the
@@ -2097,7 +2043,7 @@
 
     getBE().mGlCompositionDoneTimeline.updateSignalTimes();
     std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
-    if (displayDevice && getHwComposer().hasClientComposition(displayDevice->getId())) {
+    if (displayDevice && displayDevice->getCompositionDisplay()->getState().usesClientComposition) {
         glCompositionDoneFenceTime =
                 std::make_shared<FenceTime>(displayDevice->getCompositionDisplay()
                                                     ->getRenderSurface()
@@ -2118,10 +2064,11 @@
     DisplayStatInfo stats;
     mScheduler->getDisplayStatInfo(&stats);
 
-    // We use the mRefreshStartTime which might be sampled a little later than
-    // when we started doing work for this frame, but that should be okay
-    // since updateCompositorTiming has snapping logic.
-    updateCompositorTiming(stats, mRefreshStartTime, presentFenceTime);
+    // We use the CompositionEngine::getLastFrameRefreshTimestamp() which might
+    // be sampled a little later than when we started doing work for this frame,
+    // but that should be okay since updateCompositorTiming has snapping logic.
+    updateCompositorTiming(stats, mCompositionEngine->getLastFrameRefreshTimestamp(),
+                           presentFenceTime);
     CompositorTiming compositorTiming;
     {
         std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
@@ -2210,14 +2157,7 @@
     }
 
     mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
-
-    // Lock the mStateLock in case SurfaceFlinger is in the middle of applying a transaction.
-    // If we do not lock here, a callback could be sent without all of its SurfaceControls and
-    // metrics.
-    {
-        Mutex::Autolock _l(mStateLock);
-        mTransactionCompletedThread.sendCallbacks();
-    }
+    mTransactionCompletedThread.sendCallbacks();
 
     if (mLumaSampling && mRegionSamplingThread) {
         mRegionSamplingThread->notifyNewContent();
@@ -2252,7 +2192,6 @@
     // rebuild the visible layer list per screen
     if (CC_UNLIKELY(mVisibleRegionsDirty)) {
         ATRACE_NAME("rebuildLayerStacks VR Dirty");
-        mVisibleRegionsDirty = false;
         invalidateHwcGeometry();
 
         for (const auto& pair : mDisplays) {
@@ -2262,8 +2201,8 @@
             Region opaqueRegion;
             Region dirtyRegion;
             compositionengine::Output::OutputLayers layersSortedByZ;
+            compositionengine::Output::ReleasedLayers releasedLayers;
             Vector<sp<Layer>> deprecated_layersSortedByZ;
-            Vector<sp<Layer>> layersNeedingFences;
             const ui::Transform& tr = displayState.transform;
             const Rect bounds = displayState.bounds;
             if (displayState.isEnabled) {
@@ -2311,16 +2250,16 @@
                                                          layer) != mLayersWithQueuedFrames.cend();
 
                         if (hasExistingOutputLayer && hasQueuedFrames) {
-                            layersNeedingFences.add(layer);
+                            releasedLayers.push_back(layer);
                         }
                     }
                 });
             }
 
             display->setOutputLayersOrderedByZ(std::move(layersSortedByZ));
+            display->setReleasedLayers(std::move(releasedLayers));
 
             displayDevice->setVisibleLayersSortedByZ(deprecated_layersSortedByZ);
-            displayDevice->setLayersNeedingFences(layersNeedingFences);
 
             Region undefinedRegion{bounds};
             undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
@@ -2363,7 +2302,8 @@
             case Dataspace::BT2020_ITU_PQ:
                 bestDataSpace = Dataspace::DISPLAY_P3;
                 *outHdrDataSpace = Dataspace::BT2020_PQ;
-                *outIsHdrClientComposition = layer->getForceClientComposition(display);
+                *outIsHdrClientComposition =
+                        layer->getCompositionLayer()->getState().frontEnd.forceClientComposition;
                 break;
             case Dataspace::BT2020_HLG:
             case Dataspace::BT2020_ITU_HLG:
@@ -2465,19 +2405,6 @@
     }
 }
 
-void SurfaceFlinger::prepareFrame(const sp<DisplayDevice>& displayDevice) {
-    auto display = displayDevice->getCompositionDisplay();
-    const auto& displayState = display->getState();
-
-    if (!displayState.isEnabled) {
-        return;
-    }
-
-    status_t result = display->getRenderSurface()->prepareFrame();
-    ALOGE_IF(result != NO_ERROR, "prepareFrame failed for %s: %d (%s)",
-             displayDevice->getDebugName().c_str(), result, strerror(-result));
-}
-
 void SurfaceFlinger::doComposition(const sp<DisplayDevice>& displayDevice, bool repaintEverything) {
     ATRACE_CALL();
     ALOGV("doComposition");
@@ -2495,7 +2422,7 @@
         display->editState().dirtyRegion.clear();
         display->getRenderSurface()->flip();
     }
-    postFramebuffer(displayDevice);
+    displayDevice->getCompositionDisplay()->postFramebuffer();
 }
 
 void SurfaceFlinger::postFrame()
@@ -2510,65 +2437,6 @@
     }
 }
 
-void SurfaceFlinger::postFramebuffer(const sp<DisplayDevice>& displayDevice) {
-    ATRACE_CALL();
-    ALOGV("postFramebuffer");
-
-    auto display = displayDevice->getCompositionDisplay();
-    const auto& displayState = display->getState();
-    const auto displayId = display->getId();
-
-    if (displayState.isEnabled) {
-        if (displayId) {
-            getHwComposer().presentAndGetReleaseFences(*displayId);
-        }
-        display->getRenderSurface()->onPresentDisplayCompleted();
-        for (auto& layer : display->getOutputLayersOrderedByZ()) {
-            sp<Fence> releaseFence = Fence::NO_FENCE;
-            bool usedClientComposition = true;
-
-            // The layer buffer from the previous frame (if any) is released
-            // by HWC only when the release fence from this frame (if any) is
-            // signaled.  Always get the release fence from HWC first.
-            if (layer->getState().hwc) {
-                const auto& hwcState = *layer->getState().hwc;
-                releaseFence =
-                        getHwComposer().getLayerReleaseFence(*displayId, hwcState.hwcLayer.get());
-                usedClientComposition =
-                        hwcState.hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT;
-            }
-
-            // If the layer was client composited in the previous frame, we
-            // need to merge with the previous client target acquire fence.
-            // Since we do not track that, always merge with the current
-            // client target acquire fence when it is available, even though
-            // this is suboptimal.
-            if (usedClientComposition) {
-                releaseFence =
-                        Fence::merge("LayerRelease", releaseFence,
-                                     display->getRenderSurface()->getClientTargetAcquireFence());
-            }
-
-            layer->getLayerFE().onLayerDisplayed(releaseFence);
-        }
-
-        // We've got a list of layers needing fences, that are disjoint with
-        // display->getVisibleLayersSortedByZ.  The best we can do is to
-        // supply them with the present fence.
-        if (!displayDevice->getLayersNeedingFences().isEmpty()) {
-            sp<Fence> presentFence =
-                    displayId ? getHwComposer().getPresentFence(*displayId) : Fence::NO_FENCE;
-            for (auto& layer : displayDevice->getLayersNeedingFences()) {
-                layer->getCompositionLayer()->getLayerFE()->onLayerDisplayed(presentFence);
-            }
-        }
-
-        if (displayId) {
-            getHwComposer().clearReleaseFences(*displayId);
-        }
-    }
-}
-
 void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
 {
     ATRACE_CALL();
@@ -2588,7 +2456,7 @@
     // with mStateLock held to guarantee that mCurrentState won't change
     // until the transaction is committed.
 
-    mVsyncModulator.onTransactionHandled();
+    mVSyncModulator->onTransactionHandled();
     transactionFlags = getTransactionFlags(eTransactionMask);
     handleTransactionLocked(transactionFlags);
 
@@ -2704,7 +2572,7 @@
         defaultDataSpace = Dataspace::V0_SRGB;
     }
     display->getCompositionDisplay()->setColorMode(defaultColorMode, defaultDataSpace,
-                                                   RenderIntent::COLORIMETRIC);
+                                                   RenderIntent::COLORIMETRIC, Dataspace::UNKNOWN);
     if (!state.isVirtual()) {
         LOG_ALWAYS_FATAL_IF(!displayId);
         display->setActiveConfig(getHwComposer().getActiveConfigIndex(*displayId));
@@ -2861,9 +2729,11 @@
 
 void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
 {
+    const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
+
     // Notify all layers of available frames
-    mCurrentState.traverseInZOrder([](Layer* layer) {
-        layer->notifyAvailableFrames();
+    mCurrentState.traverseInZOrder([expectedPresentTime](Layer* layer) {
+        layer->notifyAvailableFrames(expectedPresentTime);
     });
 
     /*
@@ -3062,7 +2932,7 @@
 void SurfaceFlinger::latchAndReleaseBuffer(const sp<Layer>& layer) {
     if (layer->hasReadyFrame()) {
         bool ignored = false;
-        layer->latchBuffer(ignored, systemTime());
+        layer->latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */);
     }
     layer->releasePendingBuffer(systemTime());
 }
@@ -3310,6 +3180,8 @@
     bool frameQueued = false;
     bool newDataLatched = false;
 
+    const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
+
     // Store the set of layers that need updates. This set must not change as
     // buffers are being latched, as this could result in a deadlock.
     // Example: Two producers share the same command stream and:
@@ -3322,7 +3194,6 @@
     mDrawingState.traverseInZOrder([&](Layer* layer) {
         if (layer->hasReadyFrame()) {
             frameQueued = true;
-            const nsecs_t expectedPresentTime = getExpectedPresentTime();
             if (layer->shouldPresentNow(expectedPresentTime)) {
                 mLayersWithQueuedFrames.push_back(layer);
             } else {
@@ -3340,7 +3211,7 @@
         Mutex::Autolock lock(mStateLock);
 
         for (auto& layer : mLayersWithQueuedFrames) {
-            if (layer->latchBuffer(visibleRegions, latchTime)) {
+            if (layer->latchBuffer(visibleRegions, latchTime, expectedPresentTime)) {
                 mLayersPendingRefresh.push_back(layer);
             }
             layer->useSurfaceDamage();
@@ -3407,9 +3278,8 @@
 
     const Region bounds(displayState.bounds);
     const DisplayRenderArea renderArea(displayDevice);
-    const bool hasClientComposition = getHwComposer().hasClientComposition(displayId);
-    ATRACE_INT("hasClientComposition", hasClientComposition);
-
+    const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
+                                                      displayState.usesClientComposition};
     bool applyColorMatrix = false;
 
     renderengine::DisplaySettings clientCompositionDisplay;
@@ -3462,7 +3332,7 @@
         clientCompositionDisplay.maxLuminance =
                 profile->getHdrCapabilities().getDesiredMaxLuminance();
 
-        const bool hasDeviceComposition = getHwComposer().hasDeviceComposition(displayId);
+        const bool hasDeviceComposition = displayState.usesDeviceComposition;
         const bool skipClientColorTransform =
                 getHwComposer()
                         .hasDisplayCapability(displayId,
@@ -3570,11 +3440,6 @@
     return true;
 }
 
-void SurfaceFlinger::drawWormhole(const Region& region) const {
-    auto& engine(getRenderEngine());
-    engine.fillRegionWithColor(region, 0, 0, 0, 0);
-}
-
 status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
                                         const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
                                         const sp<IBinder>& parentHandle,
@@ -3643,7 +3508,7 @@
 uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags,
                                              Scheduler::TransactionStart transactionStart) {
     uint32_t old = mTransactionFlags.fetch_or(flags);
-    mVsyncModulator.setTransactionStart(transactionStart);
+    mVSyncModulator->setTransactionStart(transactionStart);
     if ((old & flags)==0) { // wake the server up
         signalTransaction();
     }
@@ -3666,6 +3531,7 @@
             while (!transactionQueue.empty()) {
                 const auto& transaction = transactionQueue.front();
                 if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime,
+                                                   true /* useCachedExpectedPresentTime */,
                                                    transaction.states)) {
                     setTransactionFlags(eTransactionFlushNeeded);
                     break;
@@ -3695,31 +3561,14 @@
     return !mTransactionQueues.empty();
 }
 
-bool SurfaceFlinger::containsAnyInvalidClientState(const Vector<ComposerState>& states) {
-    for (const ComposerState& state : states) {
-        // Here we need to check that the interface we're given is indeed
-        // one of our own. A malicious client could give us a nullptr
-        // IInterface, or one of its own or even one of our own but a
-        // different type. All these situations would cause us to crash.
-        if (state.client == nullptr) {
-            return true;
-        }
-
-        sp<IBinder> binder = IInterface::asBinder(state.client);
-        if (binder == nullptr) {
-            return true;
-        }
-
-        if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) == nullptr) {
-            return true;
-        }
-    }
-    return false;
-}
 
 bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
+                                                   bool useCachedExpectedPresentTime,
                                                    const Vector<ComposerState>& states) {
-    nsecs_t expectedPresentTime = getExpectedPresentTime();
+    if (!useCachedExpectedPresentTime)
+        populateExpectedPresentTime();
+
+    const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
     // Do not present if the desiredPresentTime has not passed unless it is more than one second
     // in the future. We ignore timestamps more than 1 second in the future for stability reasons.
     if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime &&
@@ -3754,10 +3603,6 @@
 
     Mutex::Autolock _l(mStateLock);
 
-    if (containsAnyInvalidClientState(states)) {
-        return;
-    }
-
     // If its TransactionQueue already has a pending TransactionState or if it is pending
     auto itr = mTransactionQueues.find(applyToken);
     // if this is an animation frame, wait until prior animation frame has
@@ -3774,8 +3619,10 @@
             itr = mTransactionQueues.find(applyToken);
         }
     }
-    if (itr != mTransactionQueues.end() ||
-        !transactionIsReadyToBeApplied(desiredPresentTime, states)) {
+
+    // Expected present time is computed and cached on invalidate, so it may be stale.
+    if (itr != mTransactionQueues.end() || !transactionIsReadyToBeApplied(
+            desiredPresentTime, false /* useCachedExpectedPresentTime */, states)) {
         mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime,
                                                uncacheBuffer, listenerCallbacks, postTime,
                                                privileged);
@@ -3823,8 +3670,8 @@
     if (!listenerCallbacks.empty()) {
         mTransactionCompletedThread.run();
     }
-    for (const auto& [listener, callbackIds] : listenerCallbacks) {
-        mTransactionCompletedThread.addCallback(listener, callbackIds);
+    for (const auto& listenerCallback : listenerCallbacks) {
+        mTransactionCompletedThread.startRegistration(listenerCallback);
     }
 
     uint32_t clientStateFlags = 0;
@@ -3833,6 +3680,10 @@
                                                  postTime, privileged);
     }
 
+    for (const auto& listenerCallback : listenerCallbacks) {
+        mTransactionCompletedThread.endRegistration(listenerCallback);
+    }
+
     // If the state doesn't require a traversal and there are callbacks, send them now
     if (!(clientStateFlags & eTraversalNeeded) && !listenerCallbacks.empty()) {
         mTransactionCompletedThread.sendCallbacks();
@@ -3965,10 +3816,14 @@
         const std::vector<ListenerCallbacks>& listenerCallbacks, int64_t postTime,
         bool privileged) {
     const layer_state_t& s = composerState.state;
-    sp<Client> client(static_cast<Client*>(composerState.client.get()));
 
-    sp<Layer> layer(client->getLayerUser(s.surface));
+    sp<Layer> layer(fromHandle(s.surface));
     if (layer == nullptr) {
+        for (auto& listenerCallback : listenerCallbacks) {
+            mTransactionCompletedThread.registerUnpresentedCallbackHandle(
+                    new CallbackHandle(listenerCallback.transactionCompletedListener,
+                                       listenerCallback.callbackIds, s.surface));
+        }
         return 0;
     }
 
@@ -4645,18 +4500,22 @@
 
         if (const auto it = dumpers.find(flag); it != dumpers.end()) {
             (it->second)(args, asProto, result);
-        } else {
-            if (asProto) {
-                LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
-                result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
-            } else {
-                dumpAllLocked(args, result);
-            }
+        } else if (!asProto) {
+            dumpAllLocked(args, result);
         }
 
         if (locked) {
             mStateLock.unlock();
         }
+
+        LayersProto layersProto = dumpProtoFromMainThread();
+        if (asProto) {
+            result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
+        } else {
+            auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+            result.append(LayerProtoParser::layerTreeToString(layerTree));
+            result.append("\n");
+        }
     }
     write(fd, result.c_str(), result.size());
     return NO_ERROR;
@@ -4739,11 +4598,9 @@
     StringAppendF(&result, "+  Smart 90 for video detection: %s\n\n",
                   mUseSmart90ForVideo ? "on" : "off");
     StringAppendF(&result, "Allowed Display Configs: ");
-    for (int32_t configId : mAllowedDisplayConfigs) {
-        for (auto refresh : mRefreshRateConfigs.getRefreshRates()) {
-            if (refresh.second && refresh.second->configId == configId) {
-                StringAppendF(&result, "%dHz, ", refresh.second->fps);
-            }
+    for (auto refresh : mRefreshRateConfigs.getRefreshRates()) {
+        if (refresh.second && isDisplayConfigAllowed(refresh.second->configId)) {
+            StringAppendF(&result, "%dHz, ", refresh.second->fps);
         }
     }
     StringAppendF(&result, "(config override by backdoor: %s)\n\n",
@@ -4899,19 +4756,23 @@
     result.append("\n");
 }
 
-LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet,
-                                          uint32_t traceFlags) const {
+LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
     LayersProto layersProto;
-    const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
-    const State& state = useDrawing ? mDrawingState : mCurrentState;
-    state.traverseInZOrder([&](Layer* layer) {
+    mDrawingState.traverseInZOrder([&](Layer* layer) {
         LayerProto* layerProto = layersProto.add_layers();
-        layer->writeToProto(layerProto, stateSet, traceFlags);
+        layer->writeToProtoDrawingState(layerProto, traceFlags);
+        layer->writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
     });
 
     return layersProto;
 }
 
+LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) {
+    LayersProto layersProto;
+    postMessageSync(new LambdaMessage([&]() { layersProto = dumpDrawingStateProto(traceFlags); }));
+    return layersProto;
+}
+
 LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(
         const sp<DisplayDevice>& displayDevice) const {
     LayersProto layersProto;
@@ -4932,7 +4793,7 @@
     mDrawingState.traverseInZOrder([&](Layer* layer) {
         if (!layer->visibleRegion.isEmpty() && !display->getOutputLayersOrderedByZ().empty()) {
             LayerProto* layerProto = layersProto.add_layers();
-            layer->writeToProto(layerProto, displayDevice);
+            layer->writeToProtoCompositionState(layerProto, displayDevice);
         }
     });
 
@@ -4997,13 +4858,6 @@
     colorizer.reset(result);
 
     {
-        LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
-        auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
-        result.append(LayerProtoParser::layerTreeToString(layerTree));
-        result.append("\n");
-    }
-
-    {
         StringAppendF(&result, "Composition layers\n");
         mDrawingState.traverseInZOrder([&](Layer* layer) {
             auto compositionLayer = layer->getCompositionLayer();
@@ -5224,7 +5078,18 @@
         case SET_DISPLAY_BRIGHTNESS: {
             return OK;
         }
-        case CAPTURE_LAYERS:
+        case CAPTURE_LAYERS: {
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int pid = ipc->getCallingPid();
+            const int uid = ipc->getCallingUid();
+            // allow media to capture layer for video thumbnails
+            if ((uid != AID_GRAPHICS && uid != AID_MEDIA) &&
+                !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
+                ALOGE("Permission Denial: can't capture layer pid=%d, uid=%d", pid, uid);
+                return PERMISSION_DENIED;
+            }
+            return OK;
+        }
         case CAPTURE_SCREEN:
         case ADD_REGION_SAMPLING_LISTENER:
         case REMOVE_REGION_SAMPLING_LISTENER: {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6b35649..5f13c8d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -60,6 +60,7 @@
 #include "Scheduler/VSyncModulator.h"
 #include "SurfaceFlingerFactory.h"
 #include "SurfaceTracing.h"
+#include "TracedOrdinal.h"
 #include "TransactionCompletedThread.h"
 
 #include <atomic>
@@ -68,6 +69,7 @@
 #include <map>
 #include <memory>
 #include <mutex>
+#include <optional>
 #include <queue>
 #include <set>
 #include <string>
@@ -263,7 +265,8 @@
     status_t postMessageAsync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0);
 
     // post a synchronous message to the main thread
-    status_t postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0);
+    status_t postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0)
+            EXCLUDES(mStateLock);
 
     // force full composition on all displays
     void repaintEverything();
@@ -295,18 +298,13 @@
 
     // main thread function to enable/disable h/w composer event
     void setPrimaryVsyncEnabledInternal(bool enabled);
+    void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled);
 
     // called on the main thread by MessageQueue when an internal message
     // is received
     // TODO: this should be made accessible only to MessageQueue
     void onMessageReceived(int32_t what);
 
-    // populates the expected present time for this frame.
-    // When we are in negative offsets, we perform a correction so that the
-    // predicted vsync for the *next* frame is used instead.
-    void populateExpectedPresentTime();
-    nsecs_t getExpectedPresentTime() const { return mExpectedPresentTime; }
-
     // for debugging only
     // TODO: this should be made accessible only to HWComposer
     const Vector<sp<Layer>>& getLayerSortedByZForHwcDisplay(DisplayId displayId);
@@ -583,8 +581,8 @@
     void latchAndReleaseBuffer(const sp<Layer>& layer);
     void commitTransaction() REQUIRES(mStateLock);
     void commitOffscreenLayers();
-    bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
     bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
+                                       bool useCachedExpectedPresentTime,
                                        const Vector<ComposerState>& states);
     uint32_t setClientStateLocked(const ComposerState& composerState, int64_t desiredPresentTime,
                                   const std::vector<ListenerCallbacks>& listenerCallbacks,
@@ -748,7 +746,6 @@
     void computeVisibleRegions(const sp<const DisplayDevice>& display, Region& dirtyRegion,
                                Region& opaqueRegion);
 
-    void preComposition();
     void postComposition();
     void getCompositorTiming(CompositorTiming* compositorTiming);
     void updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
@@ -773,11 +770,6 @@
      * CompositionInfo
      */
     void beginFrame(const sp<DisplayDevice>& display);
-    /* prepareFrame - This function will call into the DisplayDevice to prepare a
-     * frame after CompositionInfo has been programmed.   This provides a mechanism
-     * to prepare the hardware composer
-     */
-    void prepareFrame(const sp<DisplayDevice>& display);
     void doComposition(const sp<DisplayDevice>& display, bool repainEverything);
     void doDebugFlashRegions(const sp<DisplayDevice>& display, bool repaintEverything);
     void logLayerStats();
@@ -789,9 +781,7 @@
     bool doComposeSurfaces(const sp<DisplayDevice>& display, const Region& debugRegionm,
                            base::unique_fd* readyFence);
 
-    void postFramebuffer(const sp<DisplayDevice>& display);
     void postFrame();
-    void drawWormhole(const Region& region) const;
 
     /* ------------------------------------------------------------------------
      * Display management
@@ -815,7 +805,13 @@
     // the desired refresh rate.
     void setRefreshRateTo(RefreshRateType, Scheduler::ConfigEvent event) REQUIRES(mStateLock);
 
-    bool isDisplayConfigAllowed(int32_t configId) REQUIRES(mStateLock);
+    bool isDisplayConfigAllowed(int32_t configId) const REQUIRES(mStateLock);
+
+    bool previousFrameMissed();
+
+    // Populates the expected present time for this frame. For negative offsets, performs a
+    // correction using the predicted vsync for the next frame instead.
+    void populateExpectedPresentTime();
 
     /*
      * Display identification
@@ -845,9 +841,6 @@
         return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt;
     }
 
-    bool previousFrameMissed();
-    void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled);
-
     /*
      * Debugging & dumpsys
      */
@@ -897,8 +890,9 @@
     void dumpBufferingStats(std::string& result) const;
     void dumpDisplayIdentificationData(std::string& result) const;
     void dumpWideColorInfo(std::string& result) const;
-    LayersProto dumpProtoInfo(LayerVector::StateSet stateSet,
-                              uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+    LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+    LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL)
+            EXCLUDES(mStateLock);
     void withTracingLock(std::function<void()> operation) REQUIRES(mStateLock);
     LayersProto dumpVisibleLayersProtoInfo(const sp<DisplayDevice>& display) const;
 
@@ -964,11 +958,6 @@
     std::unique_ptr<EventThread> mInjectorEventThread;
     std::unique_ptr<InjectVSyncSource> mVSyncInjector;
 
-    // Calculates correct offsets.
-    VSyncModulator mVsyncModulator;
-    // Keeps track of all available phase offsets for different refresh types.
-    const std::unique_ptr<scheduler::PhaseOffsets> mPhaseOffsets;
-
     // Can only accessed from the main thread, these members
     // don't need synchronization
     State mDrawingState{LayerVector::StateSet::Drawing};
@@ -1133,9 +1122,17 @@
     sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
     sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
 
+    // Stores phase offsets configured per refresh rate.
+    const std::unique_ptr<scheduler::PhaseOffsets> mPhaseOffsets;
+
+    // Optional to defer construction until scheduler connections are created.
+    std::optional<scheduler::VSyncModulator> mVSyncModulator;
+
     scheduler::RefreshRateConfigs mRefreshRateConfigs;
     scheduler::RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, *mTimeStats};
 
+    std::atomic<nsecs_t> mExpectedPresentTime = 0;
+
     // All configs are allowed if the set is empty.
     using DisplayConfigs = std::set<int32_t>;
     DisplayConfigs mAllowedDisplayConfigs GUARDED_BY(mStateLock);
@@ -1149,7 +1146,8 @@
     ActiveConfigInfo mDesiredActiveConfig GUARDED_BY(mActiveConfigLock);
 
     // below flags are set by main thread only
-    bool mDesiredActiveConfigChanged GUARDED_BY(mActiveConfigLock) = false;
+    TracedOrdinal<bool> mDesiredActiveConfigChanged
+            GUARDED_BY(mActiveConfigLock) = {"DesiredActiveConfigChanged", false};
     bool mCheckPendingFence = false;
 
     bool mLumaSampling = true;
@@ -1189,8 +1187,6 @@
     // Flags to capture the state of Vsync in HWC
     HWC2::Vsync mHWCVsyncState = HWC2::Vsync::Disable;
     HWC2::Vsync mHWCVsyncPendingState = HWC2::Vsync::Disable;
-
-    nsecs_t mExpectedPresentTime;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 7bfe033..a02d14c 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -116,7 +116,14 @@
                                   layer->mCurrentState.frameNumber_legacy);
     }
     addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode());
-    addFlagsLocked(transaction, layerId, layer->mCurrentState.flags);
+    addFlagsLocked(transaction, layerId, layer->mCurrentState.flags,
+                   layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque |
+                           layer_state_t::eLayerSecure);
+    addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentParent));
+    addDetachChildrenLocked(transaction, layerId, layer->isLayerDetached());
+    addRelativeParentLocked(transaction, layerId,
+                            getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf),
+                            layer->mCurrentState.z);
 }
 
 void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment,
@@ -150,7 +157,7 @@
     return NO_ERROR;
 }
 
-const sp<const Layer> SurfaceInterceptor::getLayer(const wp<const IBinder>& weakHandle) {
+const sp<const Layer> SurfaceInterceptor::getLayer(const wp<const IBinder>& weakHandle) const {
     const sp<const IBinder>& handle(weakHandle.promote());
     const auto layerHandle(static_cast<const Layer::Handle*>(handle.get()));
     const sp<const Layer> layer(layerHandle->owner.promote());
@@ -158,14 +165,31 @@
     return layer;
 }
 
-const std::string SurfaceInterceptor::getLayerName(const sp<const Layer>& layer) {
+const std::string SurfaceInterceptor::getLayerName(const sp<const Layer>& layer) const {
     return layer->getName().string();
 }
 
-int32_t SurfaceInterceptor::getLayerId(const sp<const Layer>& layer) {
+int32_t SurfaceInterceptor::getLayerId(const sp<const Layer>& layer) const {
     return layer->sequence;
 }
 
+int32_t SurfaceInterceptor::getLayerIdFromWeakRef(const wp<const Layer>& layer) const {
+    if (layer == nullptr) {
+        return -1;
+    }
+    auto strongLayer = layer.promote();
+    return strongLayer == nullptr ? -1 : getLayerId(strongLayer);
+}
+
+int32_t SurfaceInterceptor::getLayerIdFromHandle(const sp<const IBinder>& handle) const {
+    if (handle == nullptr) {
+        return -1;
+    }
+    const auto layerHandle(static_cast<const Layer::Handle*>(handle.get()));
+    const sp<const Layer> layer(layerHandle->owner.promote());
+    return layer == nullptr ? -1 : getLayerId(layer);
+}
+
 Increment* SurfaceInterceptor::createTraceIncrementLocked() {
     Increment* increment(mTrace.add_increment());
     increment->set_time_stamp(systemTime());
@@ -252,24 +276,23 @@
     }
 }
 
-void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId,
-        uint8_t flags)
-{
+void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags,
+                                        uint8_t mask) {
     // There can be multiple flags changed
-    if (flags & layer_state_t::eLayerHidden) {
+    if (mask & layer_state_t::eLayerHidden) {
         SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
         HiddenFlagChange* flagChange(change->mutable_hidden_flag());
-        flagChange->set_hidden_flag(true);
+        flagChange->set_hidden_flag(flags & layer_state_t::eLayerHidden);
     }
-    if (flags & layer_state_t::eLayerOpaque) {
+    if (mask & layer_state_t::eLayerOpaque) {
         SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
         OpaqueFlagChange* flagChange(change->mutable_opaque_flag());
-        flagChange->set_opaque_flag(true);
+        flagChange->set_opaque_flag(flags & layer_state_t::eLayerOpaque);
     }
-    if (flags & layer_state_t::eLayerSecure) {
+    if (mask & layer_state_t::eLayerSecure) {
         SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
         SecureFlagChange* flagChange(change->mutable_secure_flag());
-        flagChange->set_secure_flag(true);
+        flagChange->set_secure_flag(flags & layer_state_t::eLayerSecure);
     }
 }
 
@@ -320,6 +343,35 @@
     overrideChange->set_override_scaling_mode(overrideScalingMode);
 }
 
+void SurfaceInterceptor::addReparentLocked(Transaction* transaction, int32_t layerId,
+                                           int32_t parentId) {
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
+    ReparentChange* overrideChange(change->mutable_reparent());
+    overrideChange->set_parent_id(parentId);
+}
+
+void SurfaceInterceptor::addReparentChildrenLocked(Transaction* transaction, int32_t layerId,
+                                                   int32_t parentId) {
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
+    ReparentChildrenChange* overrideChange(change->mutable_reparent_children());
+    overrideChange->set_parent_id(parentId);
+}
+
+void SurfaceInterceptor::addDetachChildrenLocked(Transaction* transaction, int32_t layerId,
+                                                 bool detached) {
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
+    DetachChildrenChange* overrideChange(change->mutable_detach_children());
+    overrideChange->set_detach_children(detached);
+}
+
+void SurfaceInterceptor::addRelativeParentLocked(Transaction* transaction, int32_t layerId,
+                                                 int32_t parentId, int z) {
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
+    RelativeParentChange* overrideChange(change->mutable_relative_parent());
+    overrideChange->set_relative_parent_id(parentId);
+    overrideChange->set_z(z);
+}
+
 void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction,
         const layer_state_t& state)
 {
@@ -351,7 +403,7 @@
         addTransparentRegionLocked(transaction, layerId, state.transparentRegion);
     }
     if (state.what & layer_state_t::eFlagsChanged) {
-        addFlagsLocked(transaction, layerId, state.flags);
+        addFlagsLocked(transaction, layerId, state.flags, state.mask);
     }
     if (state.what & layer_state_t::eLayerStackChanged) {
         addLayerStackLocked(transaction, layerId, state.layerStack);
@@ -380,6 +432,19 @@
     if (state.what & layer_state_t::eOverrideScalingModeChanged) {
         addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode);
     }
+    if (state.what & layer_state_t::eReparent) {
+        addReparentLocked(transaction, layerId, getLayerIdFromHandle(state.parentHandleForChild));
+    }
+    if (state.what & layer_state_t::eReparentChildren) {
+        addReparentChildrenLocked(transaction, layerId, getLayerIdFromHandle(state.reparentHandle));
+    }
+    if (state.what & layer_state_t::eDetachChildren) {
+        addDetachChildrenLocked(transaction, layerId, true);
+    }
+    if (state.what & layer_state_t::eRelativeLayerChanged) {
+        addRelativeParentLocked(transaction, layerId,
+                                getLayerIdFromHandle(state.relativeLayerHandle), state.z);
+    }
 }
 
 void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction,
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 563a44c..fdc6c58 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -39,6 +39,12 @@
 struct DisplayDeviceState;
 struct DisplayState;
 struct layer_state_t;
+using Transaction = surfaceflinger::Transaction;
+using Trace = surfaceflinger::Trace;
+using Rectangle = surfaceflinger::Rectangle;
+using SurfaceChange = surfaceflinger::SurfaceChange;
+using Increment = surfaceflinger::Increment;
+using DisplayChange = surfaceflinger::DisplayChange;
 
 constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat";
 
@@ -116,9 +122,11 @@
     void addInitialDisplayStateLocked(Increment* increment, const DisplayDeviceState& display);
 
     status_t writeProtoFileLocked();
-    const sp<const Layer> getLayer(const wp<const IBinder>& weakHandle);
-    const std::string getLayerName(const sp<const Layer>& layer);
-    int32_t getLayerId(const sp<const Layer>& layer);
+    const sp<const Layer> getLayer(const wp<const IBinder>& weakHandle) const;
+    const std::string getLayerName(const sp<const Layer>& layer) const;
+    int32_t getLayerId(const sp<const Layer>& layer) const;
+    int32_t getLayerIdFromWeakRef(const wp<const Layer>& layer) const;
+    int32_t getLayerIdFromHandle(const sp<const IBinder>& weakHandle) const;
 
     Increment* createTraceIncrementLocked();
     void addSurfaceCreationLocked(Increment* increment, const sp<const Layer>& layer);
@@ -141,7 +149,7 @@
             const layer_state_t::matrix22_t& matrix);
     void addTransparentRegionLocked(Transaction* transaction, int32_t layerId,
             const Region& transRegion);
-    void addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags);
+    void addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags, uint8_t mask);
     void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack);
     void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
     void addCornerRadiusLocked(Transaction* transaction, int32_t layerId, float cornerRadius);
@@ -153,6 +161,11 @@
     void addTransactionLocked(Increment* increment, const Vector<ComposerState>& stateUpdates,
             const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays,
             const Vector<DisplayState>& changedDisplays, uint32_t transactionFlags);
+    void addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
+    void addReparentChildrenLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
+    void addDetachChildrenLocked(Transaction* transaction, int32_t layerId, bool detached);
+    void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId,
+                                 int z);
 
     // Add display transactions to the trace
     DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t sequenceId);
@@ -176,6 +189,7 @@
 };
 
 } // namespace impl
+
 } // namespace android
 
 #endif // ANDROID_SURFACEINTERCEPTOR_H
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index c4ab066..9053f2c 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -162,7 +162,7 @@
     LayersTraceProto entry;
     entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
     entry.set_where(where);
-    LayersProto layers(mFlinger.dumpProtoInfo(LayerVector::StateSet::Drawing, mTraceFlags));
+    LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
     entry.mutable_layers()->Swap(&layers);
 
     return entry;
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 4773307..18524f0 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -61,7 +61,7 @@
     void setTraceFlags(uint32_t flags);
 
 private:
-    static constexpr auto kDefaultBufferCapInByte = 100_MB;
+    static constexpr auto kDefaultBufferCapInByte = 5_MB;
     static constexpr auto kDefaultFileName = "/data/misc/wmtrace/layers_trace.pb";
 
     class LayersTraceBuffer { // ring buffer
diff --git a/services/surfaceflinger/TracedOrdinal.h b/services/surfaceflinger/TracedOrdinal.h
new file mode 100644
index 0000000..c145a39
--- /dev/null
+++ b/services/surfaceflinger/TracedOrdinal.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+#include <android-base/stringprintf.h>
+#include <utils/Trace.h>
+#include <cmath>
+#include <string>
+
+template <typename T>
+class TracedOrdinal {
+public:
+    static_assert(std::is_same<bool, T>() || (std::is_signed<T>() && std::is_integral<T>()),
+                  "Type is not supported. Please test it with systrace before adding "
+                  "it to the list.");
+
+    TracedOrdinal(const std::string& name, T initialValue)
+          : mName(name),
+            mNameNegative(android::base::StringPrintf("%sNegative", name.c_str())),
+            mHasGoneNegative(std::signbit(initialValue)),
+            mData(initialValue) {
+        trace();
+    }
+
+    operator T() const { return mData; }
+
+    TracedOrdinal& operator=(T other) {
+        mData = other;
+        mHasGoneNegative = mHasGoneNegative || std::signbit(mData);
+        trace();
+        return *this;
+    }
+
+private:
+    void trace() {
+        if (!std::signbit(mData)) {
+            ATRACE_INT64(mName.c_str(), int64_t(mData));
+            if (mHasGoneNegative) {
+                ATRACE_INT64(mNameNegative.c_str(), 0);
+            }
+        } else {
+            ATRACE_INT64(mNameNegative.c_str(), -int64_t(mData));
+            ATRACE_INT64(mName.c_str(), 0);
+        }
+    }
+
+    const std::string mName;
+    const std::string mNameNegative;
+    bool mHasGoneNegative;
+    T mData;
+};
diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
index fd466de..c519f8d 100644
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ b/services/surfaceflinger/TransactionCompletedThread.cpp
@@ -75,14 +75,15 @@
     mThread = std::thread(&TransactionCompletedThread::threadMain, this);
 }
 
-status_t TransactionCompletedThread::addCallback(const sp<ITransactionCompletedListener>& listener,
-                                                 const std::vector<CallbackId>& callbackIds) {
+status_t TransactionCompletedThread::startRegistration(const ListenerCallbacks& listenerCallbacks) {
     std::lock_guard lock(mMutex);
     if (!mRunning) {
         ALOGE("cannot add callback because the callback thread isn't running");
         return BAD_VALUE;
     }
 
+    auto& [listener, callbackIds] = listenerCallbacks;
+
     if (mCompletedTransactions.count(listener) == 0) {
         status_t err = IInterface::asBinder(listener)->linkToDeath(mDeathRecipient);
         if (err != NO_ERROR) {
@@ -91,11 +92,41 @@
         }
     }
 
+    mRegisteringTransactions.insert(listenerCallbacks);
+
     auto& transactionStatsDeque = mCompletedTransactions[listener];
     transactionStatsDeque.emplace_back(callbackIds);
+
     return NO_ERROR;
 }
 
+status_t TransactionCompletedThread::endRegistration(const ListenerCallbacks& listenerCallbacks) {
+    std::lock_guard lock(mMutex);
+    if (!mRunning) {
+        ALOGE("cannot add callback because the callback thread isn't running");
+        return BAD_VALUE;
+    }
+
+    auto itr = mRegisteringTransactions.find(listenerCallbacks);
+    if (itr == mRegisteringTransactions.end()) {
+        ALOGE("cannot end a registration that does not exist");
+        return BAD_VALUE;
+    }
+
+    mRegisteringTransactions.erase(itr);
+
+    return NO_ERROR;
+}
+
+bool TransactionCompletedThread::isRegisteringTransaction(
+        const sp<ITransactionCompletedListener>& transactionListener,
+        const std::vector<CallbackId>& callbackIds) {
+    ListenerCallbacks listenerCallbacks(transactionListener, callbackIds);
+
+    auto itr = mRegisteringTransactions.find(listenerCallbacks);
+    return itr != mRegisteringTransactions.end();
+}
+
 status_t TransactionCompletedThread::registerPendingCallbackHandle(
         const sp<CallbackHandle>& handle) {
     std::lock_guard lock(mMutex);
@@ -105,7 +136,7 @@
     }
 
     // If we can't find the transaction stats something has gone wrong. The client should call
-    // addCallback before trying to register a pending callback handle.
+    // startRegistration before trying to register a pending callback handle.
     TransactionStats* transactionStats;
     status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
     if (err != NO_ERROR) {
@@ -117,7 +148,7 @@
     return NO_ERROR;
 }
 
-status_t TransactionCompletedThread::addPresentedCallbackHandles(
+status_t TransactionCompletedThread::finalizePendingCallbackHandles(
         const std::deque<sp<CallbackHandle>>& handles) {
     std::lock_guard lock(mMutex);
     if (!mRunning) {
@@ -158,7 +189,7 @@
     return NO_ERROR;
 }
 
-status_t TransactionCompletedThread::addUnpresentedCallbackHandle(
+status_t TransactionCompletedThread::registerUnpresentedCallbackHandle(
         const sp<CallbackHandle>& handle) {
     std::lock_guard lock(mMutex);
     if (!mRunning) {
@@ -189,7 +220,7 @@
 
 status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
     // If we can't find the transaction stats something has gone wrong. The client should call
-    // addCallback before trying to add a presnted callback handle.
+    // startRegistration before trying to add a callback handle.
     TransactionStats* transactionStats;
     status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
     if (err != NO_ERROR) {
@@ -239,6 +270,13 @@
             while (transactionStatsItr != transactionStatsDeque.end()) {
                 auto& transactionStats = *transactionStatsItr;
 
+                // If this transaction is still registering, it is not safe to send a callback
+                // because there could be surface controls that haven't been added to
+                // transaction stats or mPendingTransactions.
+                if (isRegisteringTransaction(listener, transactionStats.callbackIds)) {
+                    break;
+                }
+
                 // If we are still waiting on the callback handles for this transaction, stop
                 // here because all transaction callbacks for the same listener must come in order
                 auto pendingTransactions = mPendingTransactions.find(listener);
diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h
index e849f71..e255e50 100644
--- a/services/surfaceflinger/TransactionCompletedThread.h
+++ b/services/surfaceflinger/TransactionCompletedThread.h
@@ -21,6 +21,7 @@
 #include <mutex>
 #include <thread>
 #include <unordered_map>
+#include <unordered_set>
 
 #include <android-base/thread_annotations.h>
 
@@ -30,6 +31,12 @@
 
 namespace android {
 
+struct ITransactionCompletedListenerHash {
+    std::size_t operator()(const sp<ITransactionCompletedListener>& listener) const {
+        return std::hash<IBinder*>{}((listener) ? IInterface::asBinder(listener).get() : nullptr);
+    }
+};
+
 struct CallbackIdsHash {
     // CallbackId vectors have several properties that let us get away with this simple hash.
     // 1) CallbackIds are never 0 so if something has gone wrong and our CallbackId vector is
@@ -42,6 +49,22 @@
     }
 };
 
+struct ListenerCallbacksHash {
+    std::size_t HashCombine(size_t value1, size_t value2) const {
+        return value1 ^ (value2 + 0x9e3779b9 + (value1 << 6) + (value1 >> 2));
+    }
+
+    std::size_t operator()(const ListenerCallbacks& listenerCallbacks) const {
+        struct ITransactionCompletedListenerHash listenerHasher;
+        struct CallbackIdsHash callbackIdsHasher;
+
+        std::size_t listenerHash = listenerHasher(listenerCallbacks.transactionCompletedListener);
+        std::size_t callbackIdsHash = callbackIdsHasher(listenerCallbacks.callbackIds);
+
+        return HashCombine(listenerHash, callbackIdsHash);
+    }
+};
+
 class CallbackHandle : public RefBase {
 public:
     CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
@@ -64,10 +87,12 @@
     void run();
 
     // Adds listener and callbackIds in case there are no SurfaceControls that are supposed
-    // to be included in the callback. This functions should be call before attempting to add any
-    // callback handles.
-    status_t addCallback(const sp<ITransactionCompletedListener>& transactionListener,
-                         const std::vector<CallbackId>& callbackIds);
+    // to be included in the callback. This functions should be call before attempting to register
+    // any callback handles.
+    status_t startRegistration(const ListenerCallbacks& listenerCallbacks);
+    // Ends the registration. After this is called, no more CallbackHandles will be registered.
+    // It is safe to send a callback if the Transaction doesn't have any Pending callback handles.
+    status_t endRegistration(const ListenerCallbacks& listenerCallbacks);
 
     // Informs the TransactionCompletedThread that there is a Transaction with a CallbackHandle
     // that needs to be latched and presented this frame. This function should be called once the
@@ -76,11 +101,11 @@
     // presented.
     status_t registerPendingCallbackHandle(const sp<CallbackHandle>& handle);
     // Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented.
-    status_t addPresentedCallbackHandles(const std::deque<sp<CallbackHandle>>& handles);
+    status_t finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>>& handles);
 
     // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and
     // presented this frame.
-    status_t addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle);
+    status_t registerUnpresentedCallbackHandle(const sp<CallbackHandle>& handle);
 
     void addPresentFence(const sp<Fence>& presentFence);
 
@@ -89,6 +114,9 @@
 private:
     void threadMain();
 
+    bool isRegisteringTransaction(const sp<ITransactionCompletedListener>& transactionListener,
+                                  const std::vector<CallbackId>& callbackIds) REQUIRES(mMutex);
+
     status_t findTransactionStats(const sp<ITransactionCompletedListener>& listener,
                                   const std::vector<CallbackId>& callbackIds,
                                   TransactionStats** outTransactionStats) REQUIRES(mMutex);
@@ -106,13 +134,6 @@
     };
     sp<ThreadDeathRecipient> mDeathRecipient;
 
-    struct ITransactionCompletedListenerHash {
-        std::size_t operator()(const sp<ITransactionCompletedListener>& listener) const {
-            return std::hash<IBinder*>{}((listener) ? IInterface::asBinder(listener).get()
-                                                    : nullptr);
-        }
-    };
-
     // Protects the creation and destruction of mThread
     std::mutex mThreadMutex;
 
@@ -121,11 +142,15 @@
     std::mutex mMutex;
     std::condition_variable_any mConditionVariable;
 
+    std::unordered_set<ListenerCallbacks, ListenerCallbacksHash> mRegisteringTransactions
+            GUARDED_BY(mMutex);
+
     std::unordered_map<
             sp<ITransactionCompletedListener>,
             std::unordered_map<std::vector<CallbackId>, uint32_t /*count*/, CallbackIdsHash>,
             ITransactionCompletedListenerHash>
             mPendingTransactions GUARDED_BY(mMutex);
+
     std::unordered_map<sp<ITransactionCompletedListener>, std::deque<TransactionStats>,
                        ITransactionCompletedListenerHash>
             mCompletedTransactions GUARDED_BY(mMutex);
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index 74baf37..56ab4e3 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -36,7 +36,7 @@
 prop {
     api_name: "vsync_event_phase_offset_ns"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
 }
@@ -44,7 +44,7 @@
 prop {
     api_name: "vsync_sf_event_phase_offset_ns"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
 }
@@ -53,7 +53,7 @@
 prop {
     api_name: "use_context_priority"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_context_priority"
 }
@@ -62,7 +62,7 @@
 prop {
     api_name: "max_frame_buffer_acquired_buffers"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
 }
@@ -80,7 +80,7 @@
 prop {
     api_name: "has_wide_color_display"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.has_wide_color_display"
 }
@@ -90,7 +90,7 @@
 prop {
     api_name: "running_without_sync_framework"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.running_without_sync_framework"
 }
@@ -108,7 +108,7 @@
 prop {
     api_name: "has_HDR_display"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.has_HDR_display"
 }
@@ -117,7 +117,7 @@
 prop {
     api_name: "present_time_offset_from_vsync_ns"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
 }
@@ -129,7 +129,7 @@
 prop {
     api_name: "force_hwc_copy_for_virtual_displays"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
 }
@@ -139,7 +139,7 @@
 prop {
     api_name: "max_virtual_display_dimension"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.max_virtual_display_dimension"
 }
@@ -151,7 +151,7 @@
 prop {
     api_name: "use_vr_flinger"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_vr_flinger"
 }
@@ -161,7 +161,7 @@
 prop {
     api_name: "start_graphics_allocator_service"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.start_graphics_allocator_service"
 }
@@ -171,7 +171,7 @@
     api_name: "primary_display_orientation"
     type: Enum
     enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.primary_display_orientation"
 }
@@ -182,7 +182,7 @@
 prop {
     api_name: "use_color_management"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_color_management"
 }
@@ -209,7 +209,7 @@
 prop {
     api_name: "default_composition_dataspace"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.default_composition_dataspace"
 }
@@ -220,7 +220,7 @@
 prop {
     api_name: "default_composition_pixel_format"
     type: Integer
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.default_composition_pixel_format"
 }
@@ -235,7 +235,7 @@
 prop {
     api_name: "wcg_composition_dataspace"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.wcg_composition_dataspace"
 }
@@ -246,7 +246,7 @@
 prop {
     api_name: "wcg_composition_pixel_format"
     type: Integer
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
 }
@@ -272,7 +272,7 @@
 prop {
     api_name: "display_primary_red"
     type: DoubleList
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_red"
 }
@@ -280,7 +280,7 @@
 prop {
     api_name: "display_primary_green"
     type: DoubleList
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_green"
 }
@@ -288,7 +288,7 @@
 prop {
     api_name: "display_primary_blue"
     type: DoubleList
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_blue"
 }
@@ -296,7 +296,7 @@
 prop {
     api_name: "display_primary_white"
     type: DoubleList
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_white"
 }
@@ -307,7 +307,7 @@
 prop {
     api_name: "set_idle_timer_ms"
     type: Integer
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.set_idle_timer_ms"
 }
@@ -318,7 +318,7 @@
 prop {
     api_name: "set_touch_timer_ms"
     type: Integer
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.set_touch_timer_ms"
 }
@@ -340,7 +340,7 @@
 prop {
     api_name: "use_smart_90_for_video"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_smart_90_for_video"
 }
@@ -348,7 +348,7 @@
 prop {
     api_name: "enable_protected_contents"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.protected_contents"
 }
@@ -358,7 +358,7 @@
 prop {
     api_name: "support_kernel_idle_timer"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.support_kernel_idle_timer"
 }
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 5cc946a..bc5f1aa 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -36,6 +36,9 @@
 namespace android {
 
 using Transaction = SurfaceComposerClient::Transaction;
+using SurfaceChange = surfaceflinger::SurfaceChange;
+using Trace = surfaceflinger::Trace;
+using Increment = surfaceflinger::Increment;
 
 constexpr int32_t SCALING_UPDATE = 1;
 constexpr uint32_t BUFFER_UPDATES = 18;
@@ -43,14 +46,17 @@
 constexpr uint32_t SIZE_UPDATE = 134;
 constexpr uint32_t STACK_UPDATE = 1;
 constexpr uint64_t DEFERRED_UPDATE = 0;
+constexpr int32_t RELATIVE_Z = 42;
 constexpr float ALPHA_UPDATE = 0.29f;
 constexpr float CORNER_RADIUS_UPDATE = 0.2f;
 constexpr float POSITION_UPDATE = 121;
 const Rect CROP_UPDATE(16, 16, 32, 32);
 
 const String8 DISPLAY_NAME("SurfaceInterceptor Display Test");
-constexpr auto TEST_SURFACE_NAME = "BG Interceptor Test Surface";
-constexpr auto UNIQUE_TEST_SURFACE_NAME = "BG Interceptor Test Surface#0";
+constexpr auto TEST_BG_SURFACE_NAME = "BG Interceptor Test Surface";
+constexpr auto TEST_FG_SURFACE_NAME = "FG Interceptor Test Surface";
+constexpr auto UNIQUE_TEST_BG_SURFACE_NAME = "BG Interceptor Test Surface#0";
+constexpr auto UNIQUE_TEST_FG_SURFACE_NAME = "FG Interceptor Test Surface#0";
 constexpr auto LAYER_NAME = "Layer Create and Delete Test";
 constexpr auto UNIQUE_LAYER_NAME = "Layer Create and Delete Test#0";
 
@@ -136,12 +142,15 @@
     void TearDown() override {
         mComposerClient->dispose();
         mBGSurfaceControl.clear();
+        mFGSurfaceControl.clear();
         mComposerClient.clear();
     }
 
     sp<SurfaceComposerClient> mComposerClient;
     sp<SurfaceControl> mBGSurfaceControl;
+    sp<SurfaceControl> mFGSurfaceControl;
     int32_t mBGLayerId;
+    int32_t mFGLayerId;
 
 public:
     using TestTransactionAction = void (SurfaceInterceptorTest::*)(Transaction&);
@@ -177,6 +186,10 @@
     bool opaqueFlagUpdateFound(const SurfaceChange& change, bool foundOpaqueFlag);
     bool secureFlagUpdateFound(const SurfaceChange& change, bool foundSecureFlag);
     bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred);
+    bool reparentUpdateFound(const SurfaceChange& change, bool found);
+    bool relativeParentUpdateFound(const SurfaceChange& change, bool found);
+    bool detachChildrenUpdateFound(const SurfaceChange& change, bool found);
+    bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found);
     bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase);
 
     // Find all of the updates in the single trace
@@ -209,6 +222,10 @@
     void opaqueFlagUpdate(Transaction&);
     void secureFlagUpdate(Transaction&);
     void deferredTransactionUpdate(Transaction&);
+    void reparentUpdate(Transaction&);
+    void relativeParentUpdate(Transaction&);
+    void detachChildrenUpdate(Transaction&);
+    void reparentChildrenUpdate(Transaction&);
     void surfaceCreation(Transaction&);
     void displayCreation(Transaction&);
     void displayDeletion(Transaction&);
@@ -250,21 +267,30 @@
     ssize_t displayHeight = info.h;
 
     // Background surface
-    mBGSurfaceControl = mComposerClient->createSurface(
-            String8(TEST_SURFACE_NAME), displayWidth, displayHeight,
-            PIXEL_FORMAT_RGBA_8888, 0);
+    mBGSurfaceControl = mComposerClient->createSurface(String8(TEST_BG_SURFACE_NAME), displayWidth,
+                                                       displayHeight, PIXEL_FORMAT_RGBA_8888, 0);
     ASSERT_TRUE(mBGSurfaceControl != nullptr);
     ASSERT_TRUE(mBGSurfaceControl->isValid());
 
+    // Foreground surface
+    mFGSurfaceControl = mComposerClient->createSurface(String8(TEST_FG_SURFACE_NAME), displayWidth,
+                                                       displayHeight, PIXEL_FORMAT_RGBA_8888, 0);
+    ASSERT_TRUE(mFGSurfaceControl != nullptr);
+    ASSERT_TRUE(mFGSurfaceControl->isValid());
+
     Transaction t;
     t.setDisplayLayerStack(display, 0);
-    ASSERT_EQ(NO_ERROR, t.setLayer(mBGSurfaceControl, INT_MAX-3)
-            .show(mBGSurfaceControl)
-            .apply());
+    ASSERT_EQ(NO_ERROR,
+              t.setLayer(mBGSurfaceControl, INT_MAX - 3)
+                      .show(mBGSurfaceControl)
+                      .setLayer(mFGSurfaceControl, INT_MAX - 3)
+                      .show(mFGSurfaceControl)
+                      .apply());
 }
 
 void SurfaceInterceptorTest::preProcessTrace(const Trace& trace) {
-    mBGLayerId = getSurfaceId(trace, UNIQUE_TEST_SURFACE_NAME);
+    mBGLayerId = getSurfaceId(trace, UNIQUE_TEST_BG_SURFACE_NAME);
+    mFGLayerId = getSurfaceId(trace, UNIQUE_TEST_FG_SURFACE_NAME);
 }
 
 void SurfaceInterceptorTest::captureTest(TestTransactionAction action,
@@ -364,6 +390,22 @@
                                    DEFERRED_UPDATE);
 }
 
+void SurfaceInterceptorTest::reparentUpdate(Transaction& t) {
+    t.reparent(mBGSurfaceControl, mFGSurfaceControl->getHandle());
+}
+
+void SurfaceInterceptorTest::relativeParentUpdate(Transaction& t) {
+    t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl->getHandle(), RELATIVE_Z);
+}
+
+void SurfaceInterceptorTest::detachChildrenUpdate(Transaction& t) {
+    t.detachChildren(mBGSurfaceControl);
+}
+
+void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) {
+    t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl->getHandle());
+}
+
 void SurfaceInterceptorTest::displayCreation(Transaction&) {
     sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
     SurfaceComposerClient::destroyDisplay(testDisplay);
@@ -389,6 +431,10 @@
     runInTransaction(&SurfaceInterceptorTest::opaqueFlagUpdate);
     runInTransaction(&SurfaceInterceptorTest::secureFlagUpdate);
     runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate);
+    runInTransaction(&SurfaceInterceptorTest::reparentUpdate);
+    runInTransaction(&SurfaceInterceptorTest::reparentChildrenUpdate);
+    runInTransaction(&SurfaceInterceptorTest::detachChildrenUpdate);
+    runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate);
 }
 
 void SurfaceInterceptorTest::surfaceCreation(Transaction&) {
@@ -569,6 +615,46 @@
     return foundDeferred;
 }
 
+bool SurfaceInterceptorTest::reparentUpdateFound(const SurfaceChange& change, bool found) {
+    bool hasId(change.reparent().parent_id() == mFGLayerId);
+    if (hasId && !found) {
+        found = true;
+    } else if (hasId && found) {
+        []() { FAIL(); }();
+    }
+    return found;
+}
+
+bool SurfaceInterceptorTest::relativeParentUpdateFound(const SurfaceChange& change, bool found) {
+    bool hasId(change.relative_parent().relative_parent_id() == mFGLayerId);
+    if (hasId && !found) {
+        found = true;
+    } else if (hasId && found) {
+        []() { FAIL(); }();
+    }
+    return found;
+}
+
+bool SurfaceInterceptorTest::detachChildrenUpdateFound(const SurfaceChange& change, bool found) {
+    bool detachChildren(change.detach_children().detach_children());
+    if (detachChildren && !found) {
+        found = true;
+    } else if (detachChildren && found) {
+        []() { FAIL(); }();
+    }
+    return found;
+}
+
+bool SurfaceInterceptorTest::reparentChildrenUpdateFound(const SurfaceChange& change, bool found) {
+    bool hasId(change.reparent_children().parent_id() == mFGLayerId);
+    if (hasId && !found) {
+        found = true;
+    } else if (hasId && found) {
+        []() { FAIL(); }();
+    }
+    return found;
+}
+
 bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace,
         SurfaceChange::SurfaceChangeCase changeCase) {
     bool foundUpdate = false;
@@ -620,6 +706,18 @@
                         case SurfaceChange::SurfaceChangeCase::kDeferredTransaction:
                             foundUpdate = deferredTransactionUpdateFound(change, foundUpdate);
                             break;
+                        case SurfaceChange::SurfaceChangeCase::kReparent:
+                            foundUpdate = reparentUpdateFound(change, foundUpdate);
+                            break;
+                        case SurfaceChange::SurfaceChangeCase::kReparentChildren:
+                            foundUpdate = reparentChildrenUpdateFound(change, foundUpdate);
+                            break;
+                        case SurfaceChange::SurfaceChangeCase::kRelativeParent:
+                            foundUpdate = relativeParentUpdateFound(change, foundUpdate);
+                            break;
+                        case SurfaceChange::SurfaceChangeCase::kDetachChildren:
+                            foundUpdate = detachChildrenUpdateFound(change, foundUpdate);
+                            break;
                         case SurfaceChange::SurfaceChangeCase::SURFACECHANGE_NOT_SET:
                             break;
                     }
@@ -644,6 +742,10 @@
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOpaqueFlag));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kSecureFlag));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDeferredTransaction));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparent));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparentChildren));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kRelativeParent));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDetachChildren));
 }
 
 bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) {
@@ -798,6 +900,26 @@
             SurfaceChange::SurfaceChangeCase::kDeferredTransaction);
 }
 
+TEST_F(SurfaceInterceptorTest, InterceptReparentUpdateWorks) {
+    captureTest(&SurfaceInterceptorTest::reparentUpdate,
+                SurfaceChange::SurfaceChangeCase::kReparent);
+}
+
+TEST_F(SurfaceInterceptorTest, InterceptReparentChildrenUpdateWorks) {
+    captureTest(&SurfaceInterceptorTest::reparentChildrenUpdate,
+                SurfaceChange::SurfaceChangeCase::kReparentChildren);
+}
+
+TEST_F(SurfaceInterceptorTest, InterceptRelativeParentUpdateWorks) {
+    captureTest(&SurfaceInterceptorTest::relativeParentUpdate,
+                SurfaceChange::SurfaceChangeCase::kRelativeParent);
+}
+
+TEST_F(SurfaceInterceptorTest, InterceptDetachChildrenUpdateWorks) {
+    captureTest(&SurfaceInterceptorTest::detachChildrenUpdate,
+                SurfaceChange::SurfaceChangeCase::kDetachChildren);
+}
+
 TEST_F(SurfaceInterceptorTest, InterceptAllUpdatesWorks) {
     captureTest(&SurfaceInterceptorTest::runAllUpdates,
                 &SurfaceInterceptorTest::assertAllUpdatesFound);
@@ -861,5 +983,4 @@
     ASSERT_TRUE(bufferUpdatesFound(capturedTrace));
     ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceCreation));
 }
-
 }
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index c93e15e..c8f5618 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -4428,6 +4428,30 @@
     }
 }
 
+TEST_F(LayerUpdateTest, MergingTransactionFlags) {
+    Transaction().hide(mFGSurfaceControl).apply();
+    std::unique_ptr<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before merge");
+        ScreenCapture::captureScreen(&sc);
+        sc->expectBGColor(0, 12);
+        sc->expectBGColor(75, 75);
+        sc->expectBGColor(145, 145);
+    }
+
+    Transaction t1, t2;
+    t1.show(mFGSurfaceControl);
+    t2.setFlags(mFGSurfaceControl, 0 /* flags */, layer_state_t::eLayerSecure /* mask */);
+    t1.merge(std::move(t2));
+    t1.apply();
+
+    {
+        SCOPED_TRACE("after merge");
+        ScreenCapture::captureScreen(&sc);
+        sc->expectFGColor(75, 75);
+    }
+}
+
 class ChildLayerTest : public LayerUpdateTest {
 protected:
     void SetUp() override {
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index f842d61..4917bc2 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -42,7 +42,7 @@
         "DisplayTransactionTest.cpp",
         "EventControlThreadTest.cpp",
         "EventThreadTest.cpp",
-        "IdleTimerTest.cpp",
+        "OneShotTimerTest.cpp",
         "LayerHistoryTest.cpp",
         "LayerMetadataTest.cpp",
         "SchedulerTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 4f8ed1a..47243a9 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -296,18 +296,12 @@
         EXPECT_CALL(*test->mComposer,
                     setColorTransform(HWC_DISPLAY, _, Hwc2::ColorTransform::IDENTITY))
                 .Times(1);
-        EXPECT_CALL(*test->mComposer, presentOrValidateDisplay(HWC_DISPLAY, _, _, _, _)).Times(1);
         EXPECT_CALL(*test->mComposer, getDisplayRequests(HWC_DISPLAY, _, _, _)).Times(1);
         EXPECT_CALL(*test->mComposer, acceptDisplayChanges(HWC_DISPLAY)).Times(1);
         EXPECT_CALL(*test->mComposer, presentDisplay(HWC_DISPLAY, _)).Times(1);
         EXPECT_CALL(*test->mComposer, getReleaseFences(HWC_DISPLAY, _, _)).Times(1);
 
         EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
-        // TODO: remove once we verify that we can just grab the fence from the
-        // FramebufferSurface.
-        EXPECT_CALL(*test->mRenderEngine, flush()).WillRepeatedly(Invoke([]() {
-            return base::unique_fd();
-        }));
 
         EXPECT_CALL(*test->mDisplaySurface, onFrameCommitted()).Times(1);
         EXPECT_CALL(*test->mDisplaySurface, advanceFrame()).Times(1);
@@ -341,11 +335,21 @@
     }
 
     static void setupHwcCompositionCallExpectations(CompositionTest* test) {
+        EXPECT_CALL(*test->mComposer, presentOrValidateDisplay(HWC_DISPLAY, _, _, _, _)).Times(1);
+
         EXPECT_CALL(*test->mDisplaySurface,
                     prepareFrame(compositionengine::DisplaySurface::COMPOSITION_HWC))
                 .Times(1);
     }
 
+    static void setupHwcClientCompositionCallExpectations(CompositionTest* test) {
+        EXPECT_CALL(*test->mComposer, presentOrValidateDisplay(HWC_DISPLAY, _, _, _, _)).Times(1);
+    }
+
+    static void setupHwcForcedClientCompositionCallExpectations(CompositionTest* test) {
+        EXPECT_CALL(*test->mComposer, validateDisplay(HWC_DISPLAY, _, _)).Times(1);
+    }
+
     static void setupRECompositionCallExpectations(CompositionTest* test) {
         EXPECT_CALL(*test->mDisplaySurface,
                     prepareFrame(compositionengine::DisplaySurface::COMPOSITION_GLES))
@@ -419,6 +423,8 @@
     }
 
     static void setupHwcCompositionCallExpectations(CompositionTest*) {}
+    static void setupHwcClientCompositionCallExpectations(CompositionTest*) {}
+    static void setupHwcForcedClientCompositionCallExpectations(CompositionTest*) {}
 
     static void setupRECompositionCallExpectations(CompositionTest* test) {
         EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
@@ -507,7 +513,7 @@
 
         EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
         bool ignoredRecomputeVisibleRegions;
-        layer->latchBuffer(ignoredRecomputeVisibleRegions, 0);
+        layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, 0);
         Mock::VerifyAndClear(test->mRenderEngine);
     }
 
@@ -986,14 +992,25 @@
     template <typename Case>
     static void setupCallExpectations(CompositionTest* test) {
         Case::Display::setupNonEmptyFrameCompositionCallExpectations(test);
+        Case::Display::setupHwcClientCompositionCallExpectations(test);
         Case::Display::setupRECompositionCallExpectations(test);
         Case::Display::template setupRELayerCompositionCallExpectations<Case>(test);
     }
 };
 
-struct ForcedClientCompositionResultVariant : public RECompositionResultVariant {
+struct ForcedClientCompositionResultVariant : public CompositionResultBaseVariant {
     static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
-        layer->forceClientComposition(test->mDisplay);
+        const auto outputLayer = layer->findOutputLayerForDisplay(test->mDisplay);
+        LOG_FATAL_IF(!outputLayer);
+        outputLayer->editState().forceClientComposition = true;
+    }
+
+    template <typename Case>
+    static void setupCallExpectations(CompositionTest* test) {
+        Case::Display::setupNonEmptyFrameCompositionCallExpectations(test);
+        Case::Display::setupHwcForcedClientCompositionCallExpectations(test);
+        Case::Display::setupRECompositionCallExpectations(test);
+        Case::Display::template setupRELayerCompositionCallExpectations<Case>(test);
     }
 
     template <typename Case>
diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
index 1d75011..66c7f6b 100644
--- a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
+++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
@@ -20,42 +20,22 @@
 
 #include "Scheduler/PhaseOffsets.h"
 
-namespace android {
-namespace scheduler {
+namespace android::scheduler {
 
-using RefreshRateType = RefreshRateConfigs::RefreshRateType;
+struct FakePhaseOffsets : PhaseOffsets {
+    static constexpr nsecs_t FAKE_PHASE_OFFSET_NS = 0;
 
-class FakePhaseOffsets : public android::scheduler::PhaseOffsets {
-    nsecs_t FAKE_PHASE_OFFSET_NS = 0;
+    Offsets getOffsetsForRefreshRate(RefreshRateType) const override { return getCurrentOffsets(); }
 
-public:
-    FakePhaseOffsets() = default;
-    ~FakePhaseOffsets() = default;
-
-    nsecs_t getCurrentAppOffset() override { return FAKE_PHASE_OFFSET_NS; }
-    nsecs_t getCurrentSfOffset() override { return FAKE_PHASE_OFFSET_NS; }
-
-    PhaseOffsets::Offsets getOffsetsForRefreshRate(
-            RefreshRateType /*refreshRateType*/) const override {
-        return getCurrentOffsets();
+    Offsets getCurrentOffsets() const override {
+        return {{RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+                {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+                {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+                FAKE_PHASE_OFFSET_NS};
     }
 
-    // Returns early, early GL, and late offsets for Apps and SF.
-    PhaseOffsets::Offsets getCurrentOffsets() const override {
-        return Offsets{{RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
-                       {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
-                       {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}};
-    }
-
-    // This function should be called when the device is switching between different
-    // refresh rates, to properly update the offsets.
-    void setRefreshRateType(RefreshRateType /*refreshRateType*/) override {}
-
-    nsecs_t getOffsetThresholdForNextVsync() const override { return FAKE_PHASE_OFFSET_NS; }
-
-    // Returns current offsets in human friendly format.
-    void dump(std::string& /*result*/) const override {}
+    void setRefreshRateType(RefreshRateType) override {}
+    void dump(std::string&) const override {}
 };
 
-} // namespace scheduler
-} // namespace android
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/IdleTimerTest.cpp b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
similarity index 75%
rename from services/surfaceflinger/tests/unittests/IdleTimerTest.cpp
rename to services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
index eff22b6..0208728 100644
--- a/services/surfaceflinger/tests/unittests/IdleTimerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
@@ -21,17 +21,17 @@
 #include <utils/Log.h>
 
 #include "AsyncCallRecorder.h"
-#include "Scheduler/IdleTimer.h"
+#include "Scheduler/OneShotTimer.h"
 
 using namespace std::chrono_literals;
 
 namespace android {
 namespace scheduler {
 
-class IdleTimerTest : public testing::Test {
+class OneShotTimerTest : public testing::Test {
 protected:
-    IdleTimerTest() = default;
-    ~IdleTimerTest() override = default;
+    OneShotTimerTest() = default;
+    ~OneShotTimerTest() override = default;
 
     // This timeout should be used when a 3ms callback is expected.
     // While the tests typically request a callback after 3ms, the scheduler
@@ -46,7 +46,7 @@
     AsyncCallRecorder<void (*)()> mResetTimerCallback;
     AsyncCallRecorder<void (*)()> mExpiredTimerCallback;
 
-    std::unique_ptr<IdleTimer> mIdleTimer;
+    std::unique_ptr<OneShotTimer> mIdleTimer;
 
     void clearPendingCallbacks() {
         while (mExpiredTimerCallback.waitForCall(0us).has_value()) {
@@ -55,13 +55,14 @@
 };
 
 namespace {
-TEST_F(IdleTimerTest, createAndDestroyTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, [] {}, [] {});
+TEST_F(OneShotTimerTest, createAndDestroyTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
+            3ms, [] {}, [] {});
 }
 
-TEST_F(IdleTimerTest, startStopTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(30ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, startStopTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(30ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     auto startTime = std::chrono::steady_clock::now();
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
@@ -70,7 +71,7 @@
     bool callbackCalled = mExpiredTimerCallback.waitForCall(25ms).has_value();
     // Under ideal conditions there should be no event. But occasionally
     // it is possible that the wait just prior takes more than 30ms, and
-    // a callback is observed. We check the elapsed time since before the IdleTimer
+    // a callback is observed. We check the elapsed time since before the OneShotTimer
     // thread was started as a sanity check to not have a flakey test.
     EXPECT_FALSE(callbackCalled && std::chrono::steady_clock::now() - startTime < 30ms);
 
@@ -79,9 +80,9 @@
     mIdleTimer->stop();
 }
 
-TEST_F(IdleTimerTest, resetTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(20ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, resetTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
     // Observe any event that happens in about 25ms. We don't care if one was
@@ -104,9 +105,9 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, resetBackToBackTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(20ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, resetBackToBackTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
 
@@ -135,9 +136,9 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, startNotCalledTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, startNotCalledTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     // The start hasn't happened, so the callback does not happen.
     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
     EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value());
@@ -147,9 +148,9 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, idleTimerIdlesTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, idleTimerIdlesTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
 
@@ -167,18 +168,18 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, timeoutCallbackExecutionTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, timeoutCallbackExecutionTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
     EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value());
     mIdleTimer->stop();
 }
 
-TEST_F(IdleTimerTest, noCallbacksAfterStopAndResetTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, noCallbacksAfterStopAndResetTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
     EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value());
@@ -190,9 +191,9 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value());
 }
 
-TEST_F(IdleTimerTest, noCallbacksAfterStopTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, noCallbacksAfterStopTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
 
diff --git a/services/surfaceflinger/version-script32.txt b/services/surfaceflinger/version-script32.txt
deleted file mode 100644
index 2340785..0000000
--- a/services/surfaceflinger/version-script32.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-global:
-  EnsureFrontOfChain;
-  AddSpecialSignalHandlerFn;
-  RemoveSpecialSignalHandlerFn;
-  bsd_signal;
-  sigaction;
-  signal;
-  sigprocmask;
-local:
-  *;
-};
diff --git a/services/surfaceflinger/version-script64.txt b/services/surfaceflinger/version-script64.txt
deleted file mode 100644
index acf3630..0000000
--- a/services/surfaceflinger/version-script64.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-global:
-  EnsureFrontOfChain;
-  AddSpecialSignalHandlerFn;
-  RemoveSpecialSignalHandlerFn;
-  sigaction;
-  signal;
-  sigprocmask;
-local:
-  *;
-};
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index a7fd912..b71964b 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -350,7 +350,7 @@
     while (!buffer_state_->compare_exchange_weak(
         current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
         std::memory_order_acquire)) {
-      ALOGI(
+      ALOGV(
           "%s: Failed to post to the new consumer. "
           "Current buffer state was changed to %" PRIx32
           " when trying to acquire the buffer and modify the buffer state to "
diff --git a/services/vr/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp
index fb7932d..7323277 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.cpp
+++ b/services/vr/hardware_composer/impl/vr_hwc.cpp
@@ -994,6 +994,26 @@
   vsync_callback_->SetEventCallback(send_vsync ? event_callback_ : nullptr);
 }
 
+Return<void> VrHwc::debug(const hidl_handle& fd,
+                          const hidl_vec<hidl_string>& args) {
+  std::string result;
+
+  {
+    std::lock_guard<std::mutex> guard(mutex_);
+    for (const auto& pair : displays_) {
+      result += StringPrintf("Display id: %d\n", static_cast<int>(pair.first));
+      pair.second->dumpDebugInfo(&result);
+    }
+    result += "\n";
+  }
+
+  FILE* out = fdopen(dup(fd->data[0]), "w");
+  fprintf(out, "%s", result.c_str());
+  fclose(out);
+
+  return Void();
+}
+
 void HwcLayer::dumpDebugInfo(std::string* result) const {
   if (!result) {
     return;
diff --git a/services/vr/hardware_composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h
index e8c0212..15358c5 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.h
+++ b/services/vr/hardware_composer/impl/vr_hwc.h
@@ -295,6 +295,9 @@
   void RegisterObserver(Observer* observer) override;
   void UnregisterObserver(Observer* observer) override;
 
+  Return<void> debug(const hidl_handle& fd,
+                     const hidl_vec<hidl_string>& args) override;
+
  private:
   class VsyncCallback : public BnVsyncCallback {
    public:
diff --git a/services/vr/virtual_touchpad/virtual_touchpad.rc b/services/vr/virtual_touchpad/virtual_touchpad.rc
index 99315ef..0de0f9e 100644
--- a/services/vr/virtual_touchpad/virtual_touchpad.rc
+++ b/services/vr/virtual_touchpad/virtual_touchpad.rc
@@ -1,5 +1,5 @@
 service virtual_touchpad /system/bin/virtual_touchpad
   class core
   user system
-  group system input
+  group system input uhid
   writepid /dev/cpuset/system/tasks
diff --git a/vulkan/README.md b/vulkan/README.md
index 9fba728..0f66097 100644
--- a/vulkan/README.md
+++ b/vulkan/README.md
@@ -10,19 +10,8 @@
 
 ## Code Generation
 
-We generate several parts of the loader and tools from a Vulkan API description file, stored in `api/vulkan.api`. Code generation must be done manually because the generator tools aren't part of the platform toolchain (yet?). Files named `foo_gen.*` are generated from the API file and a template file named `foo.tmpl`.
+We generate several parts of the loader and tools driectly from the Vulkan Registry (external/vulkan-headers/registry/vk.xml). Code generation must be done manually because the generator is not part of the platform toolchain (yet?). Files named `foo_gen.*` are generated by the code generator.
 
  To run the generator:
-
-### One-time setup
-- Install [golang](https://golang.org/), if you don't have it already.
-- Create a directory (e.g. `$HOME/lib/go`) for local go sources and binaries and add it to `$GOPATH`.
-- `$ git clone https://android.googlesource.com/platform/tools/gpu $GOPATH/src/android.googlesource.com/platform/tools/gpu`
-- `$ go get android.googlesource.com/platform/tools/gpu/api/...`
-- You should now have `$GOPATH/bin/apic`. You might want to add `$GOPATH/bin` to your `$PATH`.
-
-### Generating code
-To generate `libvulkan/*_gen.*`,
-- `$ cd libvulkan`
-- `$ apic template ../api/vulkan.api code-generator.tmpl`
-Similar for `nulldrv/null_driver_gen.*`.
+- Install Python3 (if not already installed)
+- `$ ./<path to>/frameworks/native/vulkan/scripts/code_generator.py`
diff --git a/vulkan/api/platform.api b/vulkan/api/platform.api
deleted file mode 100644
index a7c4c30..0000000
--- a/vulkan/api/platform.api
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2015 The Khronos Group Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and/or associated documentation files (the
-// "Materials"), to deal in the Materials without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Materials, and to
-// permit persons to whom the Materials are furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Materials.
-//
-// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-
-// Platform types, as defined or included in vk_platform.h
-
-type u64 size_t
-
-// VK_USE_PLATFORM_XLIB_KHR
-@internal class Display {}
-@internal class Window {}
-@internal type u64 VisualID
-
-// VK_USE_PLATFORM_XCB_KHR
-@internal class xcb_connection_t {}
-@internal type u32 xcb_window_t
-@internal type u32 xcb_visualid_t
-
-// VK_USE_PLATFORM_WAYLAND_KHR
-@internal class wl_display {}
-@internal class wl_surface {}
-
-// VK_USE_PLATFORM_MIR_KHR
-@internal class MirConnection {}
-@internal class MirSurface {}
-
-// VK_USE_PLATFORM_ANDROID_KHR
-@internal class ANativeWindow {}
-@internal class AHardwareBuffer {}
-@internal type void* buffer_handle_t
-
-// VK_USE_PLATFORM_WIN32_KHR
-@internal type void* HINSTANCE
-@internal type void* HWND
-@internal type void* HANDLE
-@internal type u32   DWORD
-@internal type u16*  LPCWSTR
-@internal class SECURITY_ATTRIBUTES {}
-
-// VK_USE_PLATFORM_XLIB_XRANDR_EXT
-@internal type u64 RROutput
-
-// VK_USE_PLATFORM_FUCHSIA
-@internal type u32 zx_handle_t
\ No newline at end of file
diff --git a/vulkan/api/templates/asciidoc.tmpl b/vulkan/api/templates/asciidoc.tmpl
deleted file mode 100644
index 3009e19..0000000
--- a/vulkan/api/templates/asciidoc.tmpl
+++ /dev/null
@@ -1,151 +0,0 @@
-{{Include "vulkan_common.tmpl"}}
-{{if not (Global "AsciiDocPath")}}{{Global "AsciiDocPath" "../../doc/specs/vulkan/"}}{{end}}
-{{$ | Macro "AsciiDoc.Main"}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  AsciiDoc generation main entry point.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Main"}}
-  {{$docPath := Global "AsciiDocPath"}}
-
-  {{/* Generate AsciiDoc files for API enums and bitfields (flags). */}}
-  {{range $e := $.Enums}}
-    {{if not $e.IsBitfield}}
-      {{$filename := print $docPath "enums/" (Macro "EnumName" $e) ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Enum" $e) "File" $filename}}
-    {{else}}
-      {{$filename := print $docPath "flags/" (Macro "EnumName" $e) ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Flag" $e) "File" $filename}}
-    {{end}}
-  {{end}}
-
-  {{/* Generate AsciiDoc files for API commands (protos). */}}
-  {{range $f := (AllCommands $)}}
-    {{if not (GetAnnotation $f "pfn")}}
-      {{$filename := print $docPath "protos/" $f.Name ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Proto" $f) "File" $filename}}
-    {{end}}
-  {{end}}
-
-  {{/* Generate AsciiDoc files for API structs. */}}
-  {{range $c := $.Classes}}
-    {{if not (GetAnnotation $c "internal")}}
-      {{$filename := print $docPath "structs/" $c.Name ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Struct" $c) "File" $filename}}
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API enum.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Enum"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef enum {
-    {{range $i, $e := $.Entries}}
-      {{Macro "EnumEntry" $e}} = {{AsSigned $e.Value}}, {{Macro "Docs" $e.Docs}}
-    {{end}}
-  ¶
-    {{$name := Macro "EnumName" $ | TrimRight "ABCDEFGHIJKLMNOQRSTUVWXYZ" | SplitPascalCase | Upper | JoinWith "_"}}
-    {{$first := Macro "EnumFirstEntry" $}}
-    {{$last  := Macro "EnumLastEntry" $}}
-    {{$name}}_BEGIN_RANGE = {{$first}},
-    {{$name}}_END_RANGE = {{$last}},
-    {{$name}}_NUM = ({{$last}} - {{$first}} + 1),
-    {{$name}}_MAX_ENUM = 0x7FFFFFFF
-  } {{Macro "EnumName" $}};
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API bitfield.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Flag"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef VkFlags {{Macro "EnumName" $}};
-  {{if $.Entries}}
-  typedef enum {
-  {{range $e := $.Entries}}
-    {{Macro "BitfieldEntryName" $e}} = {{printf "%#.8x" $e.Value}}, {{Macro "Docs" $e.Docs}}
-  {{end}}
-  } {{Macro "EnumName" $ | TrimRight "s"}}Bits;
-  {{end}}
-{{end}}
-
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API class.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Struct"}}
-  {{AssertType $ "Class"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef {{if GetAnnotation $ "union"}}union{{else}}struct{{end}} {
-    {{range $f := $.Fields}}
-      {{Node "Type" $f}} {{$f.Name}}{{Macro "ArrayPostfix" (TypeOf $f)}}; {{Macro "Docs" $f.Docs}}
-    {{end}}
-  } {{Macro "StructName" $}};
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API function.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Proto"}}
-  {{AssertType $ "Function"}}
-
-  {{Macro "Docs" $.Docs}}
-  {{Node "Type" $.Return}} VKAPI {{Macro "FunctionName" $}}({{Macro "Parameters" $}});
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Wraps the specified Code in AsciiDoc source tags then writes to the specified File.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Write"}}
-  {{AssertType $.Code "string"}}
-  {{AssertType $.File "string"}}
-
-  {{$code := $.Code | Format (Global "clang-format")}}
-  {{JoinWith "\n" (Macro "AsciiDoc.Header") $code (Macro "AsciiDoc.Footer") ""| Write $.File}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits an AsciiDoc source header.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Header"}}
-[source,{basebackend@docbook:c++:cpp}]
-------------------------------------------------------------------------------
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits an AsciiDoc source footer.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Footer"}}
-------------------------------------------------------------------------------
-{{end}}
diff --git a/vulkan/api/templates/vk_xml.tmpl b/vulkan/api/templates/vk_xml.tmpl
deleted file mode 100644
index 893bde7..0000000
--- a/vulkan/api/templates/vk_xml.tmpl
+++ /dev/null
@@ -1,435 +0,0 @@
-{{Include "vulkan_common.tmpl"}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "vk.xml" | Reflow 4 | Write "vk.xml"}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Entry point
--------------------------------------------------------------------------------
-*/}}
-{{define "vk.xml"}}
-<?xml version="1.0" encoding="UTF-8"?>
-<registry>
-    »<comment>«
-Copyright (c) 2015 The Khronos Group Inc.

-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and/or associated documentation files (the
-"Materials"), to deal in the Materials without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Materials, and to
-permit persons to whom the Materials are furnished to do so, subject to
-the following conditions:

-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Materials.

-THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.

-------------------------------------------------------------------------

-This file, vk.xml, is the Vulkan API Registry.»
-    </comment>

-    <!-- SECTION: Vulkan type definitions -->
-    <types>»
-        <type name="vk_platform" category="include">#include "vk_platform.h"</type>

-        <type category="define">#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \
-    «((major &lt;&lt; 22) | (minor &lt;&lt; 12) | patch)</type>»

-        <type category="define">// Vulkan API version supported by this file««
-#define <name>VK_API_VERSION</name> <type>VK_MAKE_VERSION</type>({{Global "VERSION_MAJOR"}}, {{Global "VERSION_MINOR"}}, {{Global "VERSION_PATCH"}})</type>

-        »»<type category="define">««
-#if (_MSC_VER &gt;= 1800 || __cplusplus &gt;= 201103L)
-#define <name>VK_NONDISP_HANDLE_OPERATOR_BOOL</name>() explicit operator bool() const { return handle != 0; }
-#else
-#define VK_NONDISP_HANDLE_OPERATOR_BOOL()
-«#endif
-      »»»</type>

-      <type category="define">«««
-#define <name>VK_DEFINE_HANDLE</name>(obj) typedef struct obj##_T* obj;</type>
-      »»»<type category="define">«««
-#if defined(__cplusplus)
-    »»#if (_MSC_VER &gt;= 1800 || __cplusplus &gt;= 201103L)
-        »// The bool operator only works if there are no implicit conversions from an obj to
-        // a bool-compatible type, which can then be used to unintentionally violate type safety.
-        // C++11 and above supports the "explicit" keyword on conversion operators to stop this
-        // from happening. Otherwise users of C++ below C++11 won't get direct access to evaluating
-        // the object handle as a bool in expressions like:
-        //     if (obj) vkDestroy(obj);
-        #define VK_NONDISP_HANDLE_OPERATOR_BOOL() explicit operator bool() const { return handle != 0; }
-        #define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-            explicit obj(uint64_t x) : handle(x) { } \
-            obj(decltype(nullptr)) : handle(0) { }
-    «#else»
-        #define VK_NONDISP_HANDLE_OPERATOR_BOOL()
-        #define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-            obj(uint64_t x) : handle(x) { }
-    «#endif
-    #define <name>VK_DEFINE_NONDISP_HANDLE</name>(obj) \»
-        struct obj { \
-            obj() { } \
-            VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-            obj&amp; operator =(uint64_t x) { handle = x; return *this; } \
-            bool operator==(const obj&amp; other) const { return handle == other.handle; } \
-            bool operator!=(const obj&amp; other) const { return handle != other.handle; } \
-            bool operator!() const { return !handle; } \
-            VK_NONDISP_HANDLE_OPERATOR_BOOL() \
-            uint64_t handle; \
-        };
-««#else
-    »#define VK_DEFINE_NONDISP_HANDLE(obj) typedef struct obj##_T { uint64_t handle; } obj;«
-#endif
-        »»</type>

-        <type category="define">
-#if defined(__cplusplus) &amp;&amp; ((defined(_MSC_VER) &amp;&amp; _MSC_VER &gt;= 1800) || __cplusplus &gt;= 201103L)
-    »#define <name>VK_NULL_HANDLE</name> nullptr
-«#else
-    »#define VK_NULL_HANDLE 0
-«#endif
-        »»</type>

-        <type requires="vk_platform" name="VkDeviceSize"/>
-        <type requires="vk_platform" name="VkSampleMask"/>
-        <type requires="vk_platform" name="VkFlags"/>
-        <!-- Basic C types, pulled in via vk_platform.h -->
-        <type requires="vk_platform" name="char"/>
-        <type requires="vk_platform" name="float"/>
-        <type requires="vk_platform" name="VkBool32"/>
-        <type requires="vk_platform" name="uint8_t"/>
-        <type requires="vk_platform" name="uint32_t"/>
-        <type requires="vk_platform" name="uint64_t"/>
-        <type requires="vk_platform" name="int32_t"/>
-        <type requires="vk_platform" name="size_t"/>
-        <!-- Bitfield types -->
-        {{range $e := $.Enums}}
-          {{if $e.IsBitfield}}
-            {{$bits := print (Macro "EnumName" $e | TrimRight "s") "Bits"}}
-            <type{{if $e.Entries}} requires="{{$bits}}"{{end}} category="bitmask">typedef <type>VkFlags</type> <name>{{$e.Name}}</name>;</type>§
-            {{if $e.Entries}}{{Macro "XML.Docs" $e.Docs}}
-            {{else}}{{Macro "XML.Docs" (Strings $e.Docs "(no bits yet)")}}
-            {{end}}
-          {{end}}
-        {{end}}

-        <!-- Types which can be void pointers or class pointers, selected at compile time -->
-        {{range $i, $p := $.Pseudonyms}}
-          {{     if (GetAnnotation $p "dispatchHandle")}}
-            {{if Global "VK_DEFINE_HANDLE_TYPE_DEFINED"}}
-              <type category="handle">VK_DEFINE_HANDLE(<name>{{$p.Name}}</name>)</type>
-            {{else}}
-              {{Global "VK_DEFINE_HANDLE_TYPE_DEFINED" "YES"}}
-              <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>{{$p.Name}}</name>)</type>
-            {{end}}
-          {{else if (GetAnnotation $p "nonDispatchHandle")}}
-            {{if Global "VK_DEFINE_NONDISP_HANDLE_TYPE_DEFINED"}}
-              <type category="handle">VK_DEFINE_NONDISP_HANDLE(<name>{{$p.Name}}</name>)</type>
-            {{else}}
-              {{Global "VK_DEFINE_NONDISP_HANDLE_TYPE_DEFINED" "YES"}}
-              <type category="handle"><type>VK_DEFINE_NONDISP_HANDLE</type>(<name>{{$p.Name}}</name>)</type>
-            {{end}}
-          {{end}}
-        {{end}}

-        <!-- Types generated from corresponding <enums> tags below -->
-        {{range $e := SortBy $.Enums "EnumName"}}
-          {{if and $e.Entries (not (GetAnnotation $e "internal"))}}
-            {{if $e.IsBitfield}}
-              <type name="{{Macro "EnumName" $e | TrimRight "s"}}Bits" category="enum"/>
-            {{else}}
-              <type name="{{$e.Name}}" category="enum"/>
-            {{end}}
-          {{end}}
-        {{end}}

-        <!-- The PFN_vk*Function types are used by VkAllocCallbacks below -->
-        <type>typedef void* (VKAPI *<name>PFN_vkAllocFunction</name>)(«
-          void*                           pUserData,
-          size_t                          size,
-          size_t                          alignment,
-          <type>VkSystemAllocType</type>               allocType);</type>»
-        <type>typedef void (VKAPI *<name>PFN_vkFreeFunction</name>)(«
-          void*                           pUserData,
-          void*                           pMem);</type>»

-        <!-- The PFN_vkVoidFunction type are used by VkGet*ProcAddr below -->
-        <type>typedef void (VKAPI *<name>PFN_vkVoidFunction</name>)(void);</type>

-        <!-- Struct types -->
-        {{range $c := $.Classes}}
-          {{if not (GetAnnotation $c "internal")}}
-            {{Macro "Struct" $c}}
-          {{end}}
-        {{end}}
-    «</types>

-    <!-- SECTION: Vulkan enumerant (token) definitions. -->

-    <enums namespace="VK" comment="Misc. hardcoded constants - not an enumerated type">»
-            <!-- This is part of the header boilerplate -->
-      {{range $d := $.Definitions}}
-        {{if HasPrefix $d.Name "VK_"}}
-        <enum value="{{$d.Expression}}"        name="{{$d.Name}}"/>{{Macro "XML.Docs" $d.Docs}}
-        {{end}}
-      {{end}}
-        <enum value="1000.0f"  name="VK_LOD_CLAMP_NONE"/>
-        <enum value="(-0U)" name="VK_REMAINING_MIP_LEVELS"/>
-        <enum value="(~0U)" name="VK_REMAINING_ARRAY_LAYERS"/>
-        <enum value="(_0ULL)" name="VK_WHOLE_SIZE"/>
-        <enum value="(~0U)" name="VK_ATTACHMENT_UNUSED"/>
-        <enum value="(~0U)" name="VK_QUEUE_FAMILY_IGNORED"/>
-        <enum value="(~0U)" name="VK_SUBPASS_EXTERNAL"/>
-    «</enums>

-    <!-- Unlike OpenGL, most tokens in Vulkan are actual typed enumerants in»
-         their own numeric namespaces. The "name" attribute is the C enum
-         type name, and is pulled in from a <type> definition above
-         (slightly clunky, but retains the type / enum distinction). "type"
-         attributes of "enum" or "bitmask" indicate that these values should
-         be generated inside an appropriate definition. -->«

-    {{range $e := $.Enums}}
-      {{if not (or $e.IsBitfield (GetAnnotation $e "internal"))}}
-        {{Macro "XML.Enum" $e}}
-      {{end}}
-    {{end}}

-    <!-- Flags -->
-    {{range $e := $.Enums}}
-      {{if $e.IsBitfield}}
-        {{Macro "XML.Bitfield" $e}}
-      {{end}}
-    {{end}}

-    <!-- SECTION: Vulkan command definitions -->
-    <commands namespace="vk">»
-    {{range $f := AllCommands $}}
-      {{if not (GetAnnotation $f "pfn")}}
-        {{Macro "XML.Function" $f}}
-      {{end}}
-    {{end}}
-    «</commands>

-    <!-- SECTION: Vulkan API interface definitions -->
-    <feature api="vulkan" name="VK_VERSION_1_0" number="1.0">»
-        <require comment="Header boilerplate">»
-            <type name="vk_platform"/>
-        «</require>
-        <require comment="API version">»
-            <type name="VK_API_VERSION"/>
-        «</require>
-        <require comment="API constants">»
-            <enum name="VK_LOD_CLAMP_NONE"/>
-            <enum name="VK_REMAINING_MIP_LEVELS"/>
-            <enum name="VK_REMAINING_ARRAY_LAYERS"/>
-            <enum name="VK_WHOLE_SIZE"/>
-            <enum name="VK_ATTACHMENT_UNUSED"/>
-            <enum name="VK_TRUE"/>
-            <enum name="VK_FALSE"/>
-        «</require>
-        <require comment="All functions (TODO: split by type)">»
-        {{range $f := AllCommands $}}
-          {{if not (GetAnnotation $f "pfn")}}
-          <command name="{{$f.Name}}"/>
-          {{end}}
-        {{end}}
-        </require>
-        «<require comment="Types not directly used by the API">»
-            <!-- Include <type name="typename"/> here for e.g. structs that»
-                 are not parameter types of commands, but still need to be
-                 defined in the API.
-             «-->
-            <type name="VkBufferMemoryBarrier"/>
-            <type name="VkDispatchIndirectCmd"/>
-            <type name="VkDrawIndexedIndirectCmd"/>
-            <type name="VkDrawIndirectCmd"/>
-            <type name="VkImageMemoryBarrier"/>
-            <type name="VkMemoryBarrier"/>
-        «</require>
-    «</feature>

-    <!-- SECTION: Vulkan extension interface definitions (none yet) -->
-«</registry>
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified bitfield.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Bitfield"}}
-  {{AssertType $ "Enum"}}
-
-  {{if $.Entries}}
-  <enums namespace="VK" name="{{Macro "EnumName" $ | TrimRight "s"}}Bits" type="bitmask">»
-  {{range $e := $.Entries}}
-    {{$pos := Bitpos $e.Value}}
-    <enum §
-      {{if gt $pos -1}} bitpos="{{$pos}}"    §
-      {{else}}value="{{if $e.Value}}{{printf "0x%.8X" $e.Value}}{{else}}0{{end}}"    §
-      {{end}}name="{{Macro "BitfieldEntryName" $e}}" §
-      {{if $d := $e.Docs}} comment="{{$d | JoinWith "  "}}"{{end}}/>
-  {{end}}
-  «</enums>
-  {{end}}
-
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified enum.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Enum"}}
-  {{AssertType $ "Enum"}}
-
-  <enums namespace="VK" name="{{Macro "EnumName" $}}" type="enum" §
-         expand="{{Macro "EnumName" $ | SplitPascalCase | Upper | JoinWith "_"}}"{{if $.Docs}} comment="{{$.Docs | JoinWith "  "}}"{{end}}>»
-  {{range $i, $e := $.Entries}}
-    <enum value="{{AsSigned $e.Value}}"     name="{{Macro "BitfieldEntryName" $e}}"{{if $e.Docs}} comment="{{$e.Docs | JoinWith "  "}}"{{end}}/>
-  {{end}}
-  {{if $lu := GetAnnotation $ "lastUnused"}}
-    <unused start="{{index $lu.Arguments 0}}"/>
-  {{end}}
-  «</enums>
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "Struct"}}
-  {{AssertType $ "Class"}}
-
-  <type category="{{Macro "StructType" $}}" name="{{Macro "StructName" $}}"{{if $.Docs}} comment="{{$.Docs | JoinWith "  "}}"{{end}}>»
-    {{range $f := $.Fields}}
-    <member>{{Node "XML.Type" $f}}        <name>{{$f.Name}}</name>{{Macro "XML.ArrayPostfix" $f}}</member>{{Macro "XML.Docs" $f.Docs}}
-    {{end}}
-  «</type>
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits either 'struct' or 'union' for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "StructType"}}
-  {{AssertType $ "Class"}}
-
-  {{if GetAnnotation $ "union"}}union{{else}}struct{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C function pointer typedef declaration for the specified command.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Function"}}
-  {{AssertType $ "Function"}}
-
-    {{$ts := GetAnnotation $ "threadSafety"}}
-    <command{{if $ts}} threadsafe="{{index $ts.Arguments 0}}"{{end}}>»
-        <proto>{{Node "XML.Type" $.Return}} <name>{{$.Name}}</name></proto>
-        {{range $p := $.CallParameters}}
-          <param>{{Node "XML.Type" $p}} <name>{{$p.Name}}{{Macro "ArrayPostfix" $p}}</name></param>
-        {{end}}
-    «</command>
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the XML translation for the specified documentation block (string array).
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Docs"}}
-  {{if $}} <!-- {{JoinWith "  " $ | Replace "<" "" | Replace ">" ""}} -->{{end}}
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C translation for the specified type.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Type.Class"      }}<type>{{Macro "StructName" $.Type}}</type>{{end}}
-{{define "XML.Type.Pseudonym"  }}<type>{{$.Type.Name}}</type>{{end}}
-{{define "XML.Type.Enum"       }}<type>{{$.Type.Name}}</type>{{end}}
-{{define "XML.Type.StaticArray"}}{{Node "XML.Type" $.Type.ValueType}}{{end}}
-{{define "XML.Type.Pointer"    }}{{if $.Type.Const}}{{Node "XML.ConstType" $.Type.To}}{{else}}{{Node "XML.Type" $.Type.To}}{{end}}*{{end}}
-{{define "XML.Type.Slice"      }}<type>{{Node "XML.Type" $.Type.To}}</type>*{{end}}
-{{define "XML.Type#s8"         }}<type>int8_t</type>{{end}}
-{{define "XML.Type#u8"         }}<type>uint8_t</type>{{end}}
-{{define "XML.Type#s16"        }}<type>int16_t</type>{{end}}
-{{define "XML.Type#u16"        }}<type>uint16_t</type>{{end}}
-{{define "XML.Type#s32"        }}<type>int32_t</type>{{end}}
-{{define "XML.Type#u32"        }}<type>uint32_t</type>{{end}}
-{{define "XML.Type#f32"        }}<type>float</type>{{end}}
-{{define "XML.Type#s64"        }}<type>int64_t</type>{{end}}
-{{define "XML.Type#u64"        }}<type>uint64_t</type>{{end}}
-{{define "XML.Type#f64"        }}<type>double</type>{{end}}
-{{define "XML.Type#char"       }}<type>char</type>{{end}}
-{{define "XML.Type#void"       }}void{{end}}
-
-{{define "XML.ConstType_Default"}}const {{Node "XML.Type" $.Type}}{{end}}
-{{define "XML.ConstType.Pointer"}}{{Node "XML.Type" $.Type}} const{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a C type and name for the given parameter
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Parameter"}}
-  {{AssertType $ "Parameter"}}
-
-  <type>{{Macro "ParameterType" $}}</type> <name>{{$.Name}}{{Macro "ArrayPostfix" $}}</name>
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a comma-separated list of C type-name paired parameters for the given
-  command.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Parameters"}}
-  {{AssertType $ "Function"}}
-
-  {{ForEach $.CallParameters "XML.Parameter" | JoinWith ", "}}
-  {{if not $.CallParameters}}<type>void</type>{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the fixed-size-array postfix for pseudonym types annotated with @array
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.ArrayPostfix"}}{{Node "XML.ArrayPostfix" $}}{{end}}
-{{define "XML.ArrayPostfix.StaticArray"}}[{{Node "XML.NamedValue" $.Type.SizeExpr}}]{{end}}
-{{define "XML.ArrayPostfix_Default"}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the value of the given constant, or the <enum> tagged name if existant.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.NamedValue.Definition"}}<enum>{{$.Node.Name}}</enum>{{end}}
-{{define "XML.NamedValue.EnumEntry"}}<enum>{{$.Node.Name}}</enum>{{end}}
-{{define "XML.NamedValue_Default"}}{{$.Node}}{{end}}
diff --git a/vulkan/api/templates/vulkan_common.tmpl b/vulkan/api/templates/vulkan_common.tmpl
deleted file mode 100644
index f694c56..0000000
--- a/vulkan/api/templates/vulkan_common.tmpl
+++ /dev/null
@@ -1,223 +0,0 @@
-{{$clang_style := "{BasedOnStyle: Google, AccessModifierOffset: -4, ColumnLimit: 200, ContinuationIndentWidth: 8, IndentWidth: 4, AlignOperands: true, CommentPragmas: '.*'}"}}
-{{Global "clang-format" (Strings "clang-format" "-style" $clang_style)}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C translation for the specified type.
--------------------------------------------------------------------------------
-*/}}
-{{define "Type.Class"      }}{{if GetAnnotation $.Type "internal"}}struct {{end}}{{Macro "StructName" $.Type}}{{end}}
-{{define "Type.Pseudonym"  }}{{$.Type.Name}}{{end}}
-{{define "Type.Enum"       }}{{$.Type.Name}}{{end}}
-{{define "Type.StaticArray"}}{{Node "Type" $.Type.ValueType}}{{end}}
-{{define "Type.Pointer"    }}{{if $.Type.Const}}{{Node "ConstType" $.Type.To}}{{else}}{{Node "Type" $.Type.To}}{{end}}*{{end}}
-{{define "Type.Slice"      }}{{Log "%T %+v" $.Node $.Node}}{{Node "Type" $.Type.To}}*{{end}}
-{{define "Type#bool"       }}bool{{end}}
-{{define "Type#int"        }}int{{end}}
-{{define "Type#uint"       }}unsigned int{{end}}
-{{define "Type#s8"         }}int8_t{{end}}
-{{define "Type#u8"         }}uint8_t{{end}}
-{{define "Type#s16"        }}int16_t{{end}}
-{{define "Type#u16"        }}uint16_t{{end}}
-{{define "Type#s32"        }}int32_t{{end}}
-{{define "Type#u32"        }}uint32_t{{end}}
-{{define "Type#f32"        }}float{{end}}
-{{define "Type#s64"        }}int64_t{{end}}
-{{define "Type#u64"        }}uint64_t{{end}}
-{{define "Type#f64"        }}double{{end}}
-{{define "Type#void"       }}void{{end}}
-{{define "Type#char"       }}char{{end}}
-
-{{define "ConstType_Default"}}const {{Node "Type" $.Type}}{{end}}
-{{define "ConstType.Pointer"}}{{Node "Type" $.Type}} const{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C translation for the specified documentation block (string array).
--------------------------------------------------------------------------------
-*/}}
-{{define "Docs"}}
-  {{if $}}// {{$ | JoinWith "\n// "}}{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of a bitfield entry.
--------------------------------------------------------------------------------
-*/}}
-{{define "BitfieldEntryName"}}
-  {{AssertType $ "EnumEntry"}}
-
-  {{Macro "EnumEntry" $}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of an enum type.
--------------------------------------------------------------------------------
-*/}}
-{{define "EnumName"}}{{AssertType $ "Enum"}}{{$.Name}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of an enum entry.
--------------------------------------------------------------------------------
-*/}}
-{{define "EnumEntry"}}
-  {{AssertType $.Owner "Enum"}}
-  {{AssertType $.Name "string"}}
-
-  {{$.Name}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of the first entry of an enum.
--------------------------------------------------------------------------------
-*/}}
-{{define "EnumFirstEntry"}}
-  {{AssertType $ "Enum"}}
-
-  {{range $i, $e := $.Entries}}
-    {{if not $i}}{{$e.Name}}{{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of the last entry of an enum.
--------------------------------------------------------------------------------
-*/}}{{define "EnumLastEntry"}}
-  {{AssertType $ "Enum"}}
-
-  {{range $i, $e := $.Entries}}
-    {{if not (HasMore $i $.Entries)}}{{$e.Name}}{{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of a struct (class) type.
--------------------------------------------------------------------------------
-*/}}
-{{define "StructName"}}{{AssertType $ "Class"}}{{$.Name}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the name of a function.
--------------------------------------------------------------------------------
-*/}}
-{{define "FunctionName"}}{{AssertType $ "Function"}}{{$.Name}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the fixed-size-array postfix for pseudonym types annotated with @array
--------------------------------------------------------------------------------
-*/}}
-{{define "ArrayPostfix"}}{{Node "ArrayPostfix" $}}{{end}}
-{{define "ArrayPostfix.StaticArray"}}[{{$.Type.Size}}]{{end}}
-{{define "ArrayPostfix_Default"}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a C type and name for the given parameter
--------------------------------------------------------------------------------
-*/}}
-{{define "Parameter"}}
-  {{AssertType $ "Parameter"}}
-
-  {{if GetAnnotation $ "readonly"}}const {{end}}{{Macro "ParameterType" $}} {{$.Name}}{{Macro "ArrayPostfix" $}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a C name for the given parameter
--------------------------------------------------------------------------------
-*/}}
-{{define "ParameterName"}}
-  {{AssertType $ "Parameter"}}
-
-  {{$.Name}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a C type for the given parameter
--------------------------------------------------------------------------------
-*/}}
-{{define "ParameterType"}}{{AssertType $ "Parameter"}}{{Node "Type" $}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a comma-separated list of C type-name paired parameters for the given
-  command.
--------------------------------------------------------------------------------
-*/}}
-{{define "Parameters"}}
-  {{AssertType $ "Function"}}
-
-  {{ForEach $.CallParameters "Parameter" | JoinWith ", "}}
-  {{if not $.CallParameters}}void{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C function pointer name for the specified command.
--------------------------------------------------------------------------------
-*/}}
-{{define "FunctionPtrName"}}
-  {{AssertType $ "Function"}}
-
-  PFN_{{$.Name}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Parses const variables as text Globals.
--------------------------------------------------------------------------------
-*/}}
-{{define "DefineGlobals"}}
-  {{AssertType $ "API"}}
-
-  {{range $d := $.Definitions}}
-    {{Global $d.Name $d.Expression}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Given a function, return "Global", "Instance", or "Device" depending on which
-  dispatch table the function belongs to.
--------------------------------------------------------------------------------
-*/}}
-{{define "Vtbl#VkInstance"      }}Instance{{end}}
-{{define "Vtbl#VkPhysicalDevice"}}Instance{{end}}
-{{define "Vtbl#VkDevice"        }}Device{{end}}
-{{define "Vtbl#VkQueue"         }}Device{{end}}
-{{define "Vtbl#VkCommandBuffer" }}Device{{end}}
-{{define "Vtbl_Default"         }}Global{{end}}
-{{define "Vtbl"}}
-  {{AssertType $ "Function"}}
-
-  {{if gt (len $.CallParameters) 0}}
-    {{Node "Vtbl" (index $.CallParameters 0)}}
-  {{else}}Global
-  {{end}}
-{{end}}
diff --git a/vulkan/api/templates/vulkan_h.tmpl b/vulkan/api/templates/vulkan_h.tmpl
deleted file mode 100644
index 83a5e40..0000000
--- a/vulkan/api/templates/vulkan_h.tmpl
+++ /dev/null
@@ -1,295 +0,0 @@
-{{Include "vulkan_common.tmpl"}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "vulkan.h" | Format (Global "clang-format") | Write "../include/vulkan.h"}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Entry point
--------------------------------------------------------------------------------
-*/}}
-{{define "vulkan.h"}}
-#ifndef __vulkan_h_
-#define __vulkan_h_ 1

-#ifdef __cplusplus
-extern "C" {
-#endif

-/*
-** Copyright (c) 2015-2016 The Khronos Group Inc.
-**
-** Permission is hereby granted, free of charge, to any person obtaining a
-** copy of this software and/or associated documentation files (the
-** "Materials"), to deal in the Materials without restriction, including
-** without limitation the rights to use, copy, modify, merge, publish,
-** distribute, sublicense, and/or sell copies of the Materials, and to
-** permit persons to whom the Materials are furnished to do so, subject to
-** the following conditions:
-**
-** The above copyright notice and this permission notice shall be included
-** in all copies or substantial portions of the Materials.
-**
-** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-*/

-/*
-** This header is generated from the Khronos Vulkan API Registry.
-**
-*/

-#define VK_VERSION_1_0 1
-#include "vk_platform.h"

-#define VK_MAKE_VERSION(major, minor, patch) (((major) << 22) | ((minor) << 12) | (patch))

-// Vulkan API version supported by this file
-#define VK_API_VERSION \
-    VK_MAKE_VERSION({{Global "VERSION_MAJOR"}}, {{Global "VERSION_MINOR"}}, {{Global "VERSION_PATCH"}})

-#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)
-#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
-#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)

-#if defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1800 || __cplusplus >= 201103L)
-    #define VK_NULL_HANDLE nullptr
-#else
-    #define VK_NULL_HANDLE 0
-#endif

-#define VK_DEFINE_HANDLE(obj) typedef struct obj##_T* obj;

-#if defined(__cplusplus)
-#if ((defined(_MSC_VER) && _MSC_VER >= 1800 || __cplusplus >= 201103L)
-// The bool operator only works if there are no implicit conversions from an obj to
-// a bool-compatible type, which can then be used to unintentionally violate type safety.
-// C++11 and above supports the "explicit" keyword on conversion operators to stop this
-// from happening. Otherwise users of C++ below C++11 won't get direct access to evaluating
-// the object handle as a bool in expressions like:
-//     if (obj) vkDestroy(obj);
-#define VK_NONDISP_HANDLE_OPERATOR_BOOL() \
-    explicit operator bool() const { return handle != 0; }
-#define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-    explicit obj(uint64_t x) : handle(x) { } \
-    obj(decltype(nullptr)) : handle(0) { }
-#else
-#define VK_NONDISP_HANDLE_OPERATOR_BOOL()
-#define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-    obj(uint64_t x) : handle(x) { }
-#endif
-#define VK_DEFINE_NONDISP_HANDLE(obj)                                              \
-    struct obj {                                                                   \
-        obj() : handle(0) { }                                                      \
-        VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj)                             \
-        obj& operator=(uint64_t x) {                                               \
-            handle = x;                                                            \
-            return *this;                                                          \
-        }                                                                          \
-        bool operator==(const obj& other) const { return handle == other.handle; } \
-        bool operator!=(const obj& other) const { return handle != other.handle; } \
-        bool operator!() const { return !handle; }                                 \
-        VK_NONDISP_HANDLE_OPERATOR_BOOL()                                          \
-        uint64_t handle;                                                           \
-    };
-#else
-#define VK_DEFINE_NONDISP_HANDLE(obj) \
-    typedef struct obj##_T { uint64_t handle; } obj;
-#endif

-#define VK_LOD_CLAMP_NONE         1000.0f
-#define VK_REMAINING_MIP_LEVELS   (~0U)
-#define VK_REMAINING_ARRAY_LAYERS (~0U)
-#define VK_WHOLE_SIZE             (~0ULL)
-#define VK_ATTACHMENT_UNUSED      (~0U)
-define VK_QUEUE_FAMILY_IGNORED    (~0U)
-define VK_SUBPASS_EXTERNAL        (~0U)
-{{range $d := $.Definitions}}
-  {{if HasPrefix $d.Name "VK_"}}#define {{$d.Name}}  {{$d.Expression}}{{end}}
-{{end}}

-{{range $i, $p := $.Pseudonyms}}
-  {{if GetAnnotation $p "dispatchHandle"}}VK_DEFINE_HANDLE({{$p.Name}})
-  {{else if GetAnnotation $p "nonDispatchHandle"}}VK_DEFINE_NONDISP_HANDLE({{$p.Name}})
-  {{end}}
-{{end}}

-// ------------------------------------------------------------------------------------------------
-// Enumerations

-  {{range $e := $.Enums}}
-    {{if not $e.IsBitfield}}
-      {{Macro "Enum" $e}}
-    {{end}}
-  {{end}}

-// ------------------------------------------------------------------------------------------------
-// Flags

-  {{range $e := $.Enums}}
-    {{if $e.IsBitfield}}
-      {{Macro "Bitfield" $e}}
-    {{end}}
-  {{end}}

-// ------------------------------------------------------------------------------------------------
-// Vulkan structures

-  {{/* Function pointers */}}
-  {{range $f := AllCommands $}}
-    {{if GetAnnotation $f "pfn"}}
-      {{Macro "FunctionTypedef" $f}}
-    {{end}}
-  {{end}}

-  {{range $c := $.Classes}}
-    {{if not (GetAnnotation $c "internal")}}
-      {{Macro "Struct" $c}}
-    {{end}}
-  {{end}}

-// ------------------------------------------------------------------------------------------------
-// API functions

-  {{range $f := AllCommands $}}
-    {{if not (GetAnnotation $f "pfn")}}
-      {{Macro "FunctionTypedef" $f}}
-    {{end}}
-  {{end}}

-#ifdef VK_NO_PROTOTYPES

-  {{range $f := AllCommands $}}
-    {{if not (GetAnnotation $f "pfn")}}
-      {{Macro "FunctionDecl" $f}}
-    {{end}}
-  {{end}}

-#endif

-#ifdef __cplusplus
-}
-#endif

-#endif
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified bitfield.
--------------------------------------------------------------------------------
-*/}}
-{{define "Bitfield"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef VkFlags {{Macro "EnumName" $}};
-  {{if $.Entries}}
-  typedef enum {
-  {{range $b := $.Entries}}
-    {{Macro "BitfieldEntryName" $b}} = {{printf "0x%.8X" $b.Value}}, {{Macro "Docs" $b.Docs}}
-  {{end}}
-  } {{Macro "EnumName" $ | TrimRight "s"}}Bits;
-  {{end}}
-  ¶
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified enum.
--------------------------------------------------------------------------------
-*/}}
-{{define "Enum"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef enum {
-    {{range $i, $e := $.Entries}}
-      {{Macro "EnumEntry" $e}} = {{printf "0x%.8X" $e.Value}}, {{Macro "Docs" $e.Docs}}
-    {{end}}
-  ¶
-    {{$name  := Macro "EnumName" $ | TrimRight "ABCDEFGHIJKLMNOQRSTUVWXYZ" | SplitPascalCase | Upper | JoinWith "_"}}
-    {{if GetAnnotation $ "enumMaxOnly"}}
-      VK_MAX_ENUM({{$name | SplitOn "VK_"}})
-    {{else}}
-      {{$first := Macro "EnumFirstEntry" $ | SplitOn $name | TrimLeft "_"}}
-      {{$last  := Macro "EnumLastEntry" $  | SplitOn $name | TrimLeft "_"}}
-      VK_ENUM_RANGE({{$name | SplitOn "VK_"}}, {{$first}}, {{$last}})
-    {{end}}
-  } {{Macro "EnumName" $}};
-  ¶
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "Struct"}}
-  {{AssertType $ "Class"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef {{Macro "StructType" $}} {
-    {{ForEach $.Fields "Field" | JoinWith "\n"}}
-  } {{Macro "StructName" $}};
-  ¶
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified class field.
--------------------------------------------------------------------------------
-*/}}
-{{define "Field"}}
-  {{AssertType $ "Field"}}
-
-  {{Node "Type" $}} {{$.Name}}§
-  {{Macro "ArrayPostfix" (TypeOf $)}}; {{Macro "Docs" $.Docs}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits either 'struct' or 'union' for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "StructType"}}
-  {{AssertType $ "Class"}}
-
-  {{if GetAnnotation $ "union"}}union{{else}}struct{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C function pointer typedef declaration for the specified command.
--------------------------------------------------------------------------------
-*/}}
-{{define "FunctionTypedef"}}
-  {{AssertType $ "Function"}}
-
-  typedef {{Node "Type" $.Return}} (VKAPI* {{Macro "FunctionPtrName" $}})({{Macro "Parameters" $}});
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C function declaration for the specified command.
--------------------------------------------------------------------------------
-*/}}
-{{define "FunctionDecl"}}
-  {{AssertType $ "Function"}}
-
-  {{if not (GetAnnotation $ "fptr")}}
-    {{Macro "Docs" $.Docs}}
-    {{Node "Type" $.Return}} VKAPI {{Macro "FunctionName" $}}({{Macro "Parameters" $}});
-  {{end}}
-{{end}}
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
deleted file mode 100644
index 76503c8..0000000
--- a/vulkan/api/vulkan.api
+++ /dev/null
@@ -1,12163 +0,0 @@
-// Copyright (c) 2015 The Khronos Group Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and/or associated documentation files (the
-// "Materials"), to deal in the Materials without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Materials, and to
-// permit persons to whom the Materials are furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Materials.
-//
-// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-
-import platform "platform.api"
-
-///////////////
-// Constants //
-///////////////
-
-// API version (major.minor.patch)
-define VERSION_MAJOR 1
-define VERSION_MINOR 1
-define VERSION_PATCH 96
-
-// API limits
-define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
-define VK_UUID_SIZE                     16
-define VK_MAX_EXTENSION_NAME_SIZE       256
-define VK_MAX_DESCRIPTION_SIZE          256
-define VK_MAX_MEMORY_TYPES              32
-define VK_MAX_MEMORY_HEAPS              16    /// The maximum number of unique memory heaps, each of which supporting 1 or more memory types.
-@vulkan1_1
-define VK_MAX_DEVICE_GROUP_SIZE         32
-@vulkan1_1
-define VK_LUID_SIZE                     8
-@vulkan1_1
-define VK_QUEUE_FAMILY_EXTERNAL         -2
-@extension("VK_EXT_queue_family_foreign")
-define VK_QUEUE_FAMILY_FOREIGN_EXT      -3
-@extension("VK_MAX_DRIVER_NAME_SIZE_KHR") // 197
-define VK_MAX_DRIVER_NAME_SIZE_KHR      256
-@extension("VK_MAX_DRIVER_NAME_SIZE_KHR") // 197
-define VK_MAX_DRIVER_INFO_SIZE_KHR      256
-
-// API keywords
-define VK_TRUE        1
-define VK_FALSE       0
-
-// API keyword, but needs special handling by some templates
-define NULL_HANDLE 0
-
-// 1
-@extension("VK_KHR_surface") define VK_KHR_SURFACE_SPEC_VERSION                 25
-@extension("VK_KHR_surface") define VK_KHR_SURFACE_EXTENSION_NAME               "VK_KHR_surface"
-
-// 2
-@extension("VK_KHR_swapchain") define VK_KHR_SWAPCHAIN_SPEC_VERSION             70
-@extension("VK_KHR_swapchain") define VK_KHR_SWAPCHAIN_EXTENSION_NAME           "VK_KHR_swapchain"
-
-// 3
-@extension("VK_KHR_display") define VK_KHR_DISPLAY_SPEC_VERSION                 21
-@extension("VK_KHR_display") define VK_KHR_DISPLAY_EXTENSION_NAME               "VK_KHR_display"
-
-// 4
-@extension("VK_KHR_display_swapchain") define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION     9
-@extension("VK_KHR_display_swapchain") define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME   "VK_KHR_display_swapchain"
-
-// 5
-@extension("VK_KHR_xlib_surface") define VK_KHR_XLIB_SURFACE_SPEC_VERSION       6
-@extension("VK_KHR_xlib_surface") define VK_KHR_XLIB_SURFACE_NAME               "VK_KHR_xlib_surface"
-
-// 6
-@extension("VK_KHR_xcb_surface") define VK_KHR_XCB_SURFACE_SPEC_VERSION         6
-@extension("VK_KHR_xcb_surface") define VK_KHR_XCB_SURFACE_NAME                 "VK_KHR_xcb_surface"
-
-// 7
-@extension("VK_KHR_wayland_surface") define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6
-@extension("VK_KHR_wayland_surface") define VK_KHR_WAYLAND_SURFACE_NAME         "VK_KHR_wayland_surface"
-
-// 8 - VK_KHR_mir_surface removed
-
-// 9
-@extension("VK_KHR_android_surface") define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6
-@extension("VK_KHR_android_surface") define VK_KHR_ANDROID_SURFACE_NAME         "VK_KHR_android_surface"
-
-// 10
-@extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_SPEC_VERSION     6
-@extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_NAME             "VK_KHR_win32_surface"
-
-// 11
-@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION     8
-@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME             "VK_ANDROID_native_buffer"
-
-// 12
-@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION       9
-@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME               "VK_EXT_debug_report"
-
-// 13
-@extension("VK_NV_glsl_shader") define VK_NV_GLSL_SHADER_SPEC_VERSION           1
-@extension("VK_NV_glsl_shader") define VK_NV_GLSL_SHADER_NAME                   "VK_NV_glsl_shader"
-
-// 14
-@extension("VK_EXT_depth_range_unrestricted") define VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION   1
-@extension("VK_EXT_depth_range_unrestricted") define VK_EXT_DEPTH_RANGE_UNRESTRICTED_NAME           "VK_EXT_depth_range_unrestricted"
-
-// 15
-@extension("VK_KHR_sampler_mirror_clamp_to_edge") define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION   1
-@extension("VK_KHR_sampler_mirror_clamp_to_edge") define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_NAME           "VK_KHR_sampler_mirror_clamp_to_edge"
-
-// 16
-@extension("VK_IMG_filter_cubic") define VK_IMG_FILTER_CUBIC_SPEC_VERSION       1
-@extension("VK_IMG_filter_cubic") define VK_IMG_FILTER_CUBIC_NAME               "VK_IMG_filter_cubic"
-
-// 19
-@extension("VK_AMD_rasterization_order") define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION   1
-@extension("VK_AMD_rasterization_order") define VK_AMD_RASTERIZATION_ORDER_NAME           "VK_AMD_rasterization_order"
-
-// 21
-@extension("VK_AMD_shader_trinary_minmax") define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1
-@extension("VK_AMD_shader_trinary_minmax") define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax"
-
-// 22
-@extension("VK_AMD_shader_explicit_vertex_parameter") define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1
-@extension("VK_AMD_shader_explicit_vertex_parameter") define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter"
-
-// 23
-@extension("VK_EXT_debug_marker") define VK_EXT_DEBUG_MARKER_SPEC_VERSION       4
-@extension("VK_EXT_debug_marker") define VK_EXT_DEBUG_MARKER_NAME               "VK_EXT_debug_marker"
-
-// 26
-@extension("VK_AMD_gcn_shader") define VK_AMD_GCN_SHADER_SPEC_VERSION 1
-@extension("VK_AMD_gcn_shader") define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader"
-
-// 27
-@extension("VK_NV_dedicated_allocation") define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1
-@extension("VK_NV_dedicated_allocation") define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation"
-
-// 28
-@extension("VK_IMG_format_pvrtc") define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1
-@extension("VK_IMG_format_pvrtc") define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
-
-// 29
-@extension("VK_EXT_transform_feedback") define VK_EXT_TRANSFORM_FEEDBACK_SPEC_VERSION 1
-@extension("VK_EXT_transform_feedback") define VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME "VK_EXT_transform_feedback"
-
-// 34
-@extension("VK_AMD_draw_indirect_count") define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
-@extension("VK_AMD_draw_indirect_count") define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count"
-
-// 36
-@extension("VK_AMD_negative_viewport_height") define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1
-@extension("VK_AMD_negative_viewport_height") define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height"
-
-// 37
-@extension("VK_AMD_gpu_shader_half_float") define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 1
-@extension("VK_AMD_gpu_shader_half_float") define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float"
-
-// 38
-@extension("VK_AMD_shader_ballot") define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1
-@extension("VK_AMD_shader_ballot") define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot"
-
-// 42
-@extension("VK_AMD_texture_gather_bias_lod") define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1
-@extension("VK_AMD_texture_gather_bias_lod") define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod"
-
-// 43
-@extension("VK_AMD_shader_info") define VK_AMD_SHADER_INFO_SPEC_VERSION 1
-@extension("VK_AMD_shader_info") define VK_AMD_SHADER_INFO_EXTENSION_NAME "VK_AMD_shader_info"
-
-// 47
-@extension("VK_AMD_shader_image_load_store_lod") define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1
-@extension("VK_AMD_shader_image_load_store_lod") define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod"
-
-// 51
-@extension("VK_NV_corner_sampled_image") define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2
-@extension("VK_NV_corner_sampled_image") define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image"
-
-// 54
-@extension("VK_KHR_multiview") define VK_KHR_MULTIVIEW_SPEC_VERSION 1
-@extension("VK_KHR_multiview") define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview"
-
-// 56
-@extension("VK_NV_external_memory_capabilities") define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
-@extension("VK_NV_external_memory_capabilities") define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities"
-
-// 57
-@extension("VK_NV_external_memory") define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1
-@extension("VK_NV_external_memory") define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory"
-
-// 58
-@extension("VK_NV_external_memory_win32") define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
-@extension("VK_NV_external_memory_win32") define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32"
-
-// 59
-@extension("VK_NV_win32_keyed_mutex") define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 1
-@extension("VK_NV_win32_keyed_mutex") define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex"
-
-// 60
-@extension("VK_KHR_get_physical_device_properties2") define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 1
-@extension("VK_KHR_get_physical_device_properties2") define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2"
-
-// 61
-@extension("VK_KHR_device_group") define VK_KHR_DEVICE_GROUP_SPEC_VERSION 3
-@extension("VK_KHR_device_group") define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group"
-
-// 62
-@extension("VK_EXT_validation_flags") define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1
-@extension("VK_EXT_validation_flags") define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags"
-
-// 63
-@extension("VK_NN_vi_surface") define VK_NN_VI_SURFACE_SPEC_VERSION 1
-@extension("VK_NN_vi_surface") define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface"
-
-// 64
-@extension("VK_KHR_shader_draw_parameters") define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1
-@extension("VK_KHR_shader_draw_parameters") define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters"
-
-// 65
-@extension("VK_EXT_shader_subgroup_ballot") define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1
-@extension("VK_EXT_shader_subgroup_ballot") define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot"
-
-// 66
-@extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1
-@extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
-
-// 68
-@extension("VK_EXT_astc_decode_mode") define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1
-@extension("VK_EXT_astc_decode_mode") define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode"
-
-// 70
-@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_SPEC_VERSION 2
-@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
-
-// 71
-@extension("VK_KHR_device_group_creation") define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1
-@extension("VK_KHR_device_group_creation") define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation"
-
-// 72
-@extension("VK_KHR_external_memory_capabilities") define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
-@extension("VK_KHR_external_memory_capabilities") define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities"
-
-// 73
-@extension("VK_KHR_external_memory") define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1
-@extension("VK_KHR_external_memory") define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory"
-
-// 74
-@extension("VK_KHR_external_memory_win32") define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
-@extension("VK_KHR_external_memory_win32") define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32"
-
-// 75
-@extension("VK_KHR_external_memory_fd") define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1
-@extension("VK_KHR_external_memory_fd") define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd"
-
-// 76
-@extension("VK_KHR_win32_keyed_mutex") define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1
-@extension("VK_KHR_win32_keyed_mutex") define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex"
-
-// 77
-@extension("VK_KHR_external_semaphore_capabilities") define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1
-@extension("VK_KHR_external_semaphore_capabilities") define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities"
-
-// 78
-@extension("VK_KHR_external_semaphore") define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
-@extension("VK_KHR_external_semaphore") define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore"
-
-// 79
-@extension("VK_KHR_external_semaphore_win32") define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1
-@extension("VK_KHR_external_semaphore_win32") define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32"
-
-// 80
-@extension("VK_KHR_external_semaphore_fd") define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1
-@extension("VK_KHR_external_semaphore_fd") define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd"
-
-// 81
-@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2
-@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
-
-// 82
-@extension("VK_EXT_conditional_rendering") define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 1
-@extension("VK_EXT_conditional_rendering") define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering"
-
-// 83
-@extension("VK_KHR_shader_float16_int8") define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1
-@extension("VK_KHR_shader_float16_int8") define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8"
-
-// 84
-@extension("VK_KHR_16bit_storage") define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1
-@extension("VK_KHR_16bit_storage") define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage"
-
-// 85
-@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
-@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
-
-// 86
-@extension("VK_KHR_descriptor_update_template") define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1
-@extension("VK_KHR_descriptor_update_template") define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template"
-
-// 87
-@extension("VK_NVX_device_generated_commands") define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3
-@extension("VK_NVX_device_generated_commands") define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands"
-
-// 88
-@extension("VK_NV_clip_space_w_scaling") define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1
-@extension("VK_NV_clip_space_w_scaling") define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling"
-
-// 89
-@extension("VK_EXT_direct_mode_display") define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1
-@extension("VK_EXT_direct_mode_display") define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display"
-
-// 90
-@extension("VK_EXT_acquire_xlib_display") define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1
-@extension("VK_EXT_acquire_xlib_display") define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display"
-
-// 91
-@extension("VK_EXT_display_surface_counter") define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1
-@extension("VK_EXT_display_surface_counter") define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter"
-
-// 92
-@extension("VK_EXT_display_control") define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1
-@extension("VK_EXT_display_control") define VK_EXT_DISPLAY_CONTROL_COUNTER_EXTENSION_NAME "VK_EXT_display_control"
-
-// 93
-@extension("VK_GOOGLE_display_timing") define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1
-@extension("VK_GOOGLE_display_timing") define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing"
-
-// 95
-@extension("VK_NV_sample_mask_override_coverage") define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1
-@extension("VK_NV_sample_mask_override_coverage") define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage"
-
-// 96
-@extension("VK_NV_geometry_shader_passthrough") define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1
-@extension("VK_NV_geometry_shader_passthrough") define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough"
-
-// 97
-@extension("VK_NV_viewport_array2") define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION 1
-@extension("VK_NV_viewport_array2") define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME "VK_NV_viewport_array2"
-
-// 98
-@extension("VK_NVX_multiview_per_view_attributes") define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1
-@extension("VK_NVX_multiview_per_view_attributes") define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes"
-
-// 99
-@extension("VK_NV_viewport_swizzle") define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1
-@extension("VK_NV_viewport_swizzle") define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle"
-
-// 100
-@extension("VK_EXT_discard_rectangles") define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1
-@extension("VK_EXT_discard_rectangles") define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles"
-
-// 102
-@extension("VK_EXT_conservative_rasterization") define VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION 1
-@extension("VK_EXT_conservative_rasterization") define VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME "VK_EXT_conservative_rasterization"
-
-// 105
-@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_SPEC_VERSION 3
-@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
-
-// 106
-@extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_SPEC_VERSION 1
-@extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
-
-// 110
-@extension("VK_KHR_create_renderpass2") define VK_KHR_CREATE_RENDERPASS2_SPEC_VERSION 1
-@extension("VK_KHR_create_renderpass2") define VK_KHR_CREATE_RENDERPASS2_EXTENSION_NAME "VK_KHR_create_renderpass2"
-
-// 112
-@extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
-@extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
-
-// 113
-@extension("VK_KHR_external_fence_capabilities") define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1
-@extension("VK_KHR_external_fence_capabilities") define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities"
-
-// 114
-@extension("VK_KHR_external_fence") define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1
-@extension("VK_KHR_external_fence") define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence"
-
-// 115
-@extension("VK_KHR_external_fence_win32") define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1
-@extension("VK_KHR_external_fence_win32") define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32"
-
-// 116
-@extension("VK_KHR_external_fence_fd") define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1
-@extension("VK_KHR_external_fence_fd") define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd"
-
-// 118
-@extension("VK_KHR_maintenance2") define VK_KHR_MAINTENANCE2_SPEC_VERSION 1
-@extension("VK_KHR_maintenance2") define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2"
-
-// 120
-@extension("VK_KHR_get_surface_capabilities2") define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
-@extension("VK_KHR_get_surface_capabilities2") define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
-
-// 121
-@extension("VK_KHR_variable_pointers") define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1
-@extension("VK_KHR_variable_pointers") define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers"
-
-// 122
-@extension("VK_KHR_get_display_properties2") define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1
-@extension("VK_KHR_get_display_properties2") define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2"
-
-// 123
-@extension("VK_MVK_ios_surface") define VK_MVK_IOS_SURFACE_SPEC_VERSION 1
-@extension("VK_MVK_ios_surface") define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface"
-
-// 124
-@extension("VK_MVK_macos_surface") define VK_MVK_MACOS_SURFACE_SPEC_VERSION 1
-@extension("VK_MVK_macos_surface") define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface"
-
-// 126
-@extension("VK_EXT_external_memory_dma_buf") define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION 1
-@extension("VK_EXT_external_memory_dma_buf") define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME "VK_EXT_external_memory_dma_buf"
-
-// 127
-@extension("VK_EXT_queue_family_foreign") define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1
-@extension("VK_EXT_queue_family_foreign") define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign"
-
-// 128
-@extension("VK_KHR_dedicated_allocation") define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3
-@extension("VK_KHR_dedicated_allocation") define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation"
-
-// 128
-@extension("VK_EXT_debug_utils") define VK_EXT_DEBUG_UTILS_SPEC_VERSION 1
-@extension("VK_EXT_debug_utils") define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils"
-
-// 130
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 3
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer"
-
-// 131
-@extension("VK_EXT_sampler_filter_minmax") define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 1
-@extension("VK_EXT_sampler_filter_minmax") define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax"
-
-// 132
-@extension("VK_KHR_storage_buffer_storage_class") define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION 1
-@extension("VK_KHR_storage_buffer_storage_class") define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class"
-
-// 133
-@extension("VK_AMD_gpu_shader_int16") define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 1
-@extension("VK_AMD_gpu_shader_int16") define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16"
-
-// 137
-@extension("VK_AMD_mixed_attachment_samples") define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1
-@extension("VK_AMD_mixed_attachment_samples") define VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME "VK_AMD_mixed_attachment_samples"
-
-// 138
-@extension("VK_AMD_shader_fragment_mask") define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1
-@extension("VK_AMD_shader_fragment_mask") define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask"
-
-// 139
-@extension("VK_EXT_inline_uniform_block") define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1
-@extension("VK_EXT_inline_uniform_block") define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block"
-
-// 141
-@extension("VK_EXT_shader_stencil_export") define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1
-@extension("VK_EXT_shader_stencil_export") define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export"
-
-// 144
-@extension("VK_EXT_sample_locations") define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1
-@extension("VK_EXT_sample_locations") define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations"
-
-// 145
-@extension("VK_KHR_relaxed_block_layout") define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1
-@extension("VK_KHR_relaxed_block_layout") define VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME "VK_KHR_relaxed_block_layout"
-
-// 147
-@extension("VK_KHR_get_memory_requirements2") define VK_KHR_GET_MEMORY_REQUIREMENTS2_SPEC_VERSION 1
-@extension("VK_KHR_get_memory_requirements2") define VK_KHR_GET_MEMORY_REQUIREMENTS2_EXTENSION_NAME "VK_KHR_get_memory_requirements2"
-
-// 148
-@extension("VK_KHR_image_format_list") define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1
-@extension("VK_KHR_image_format_list") define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list"
-
-// 149
-@extension("VK_EXT_blend_operation_advanced") define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2
-@extension("VK_EXT_blend_operation_advanced") define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced"
-
-// 150
-@extension("VK_NV_fragment_coverage_to_color") define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1
-@extension("VK_NV_fragment_coverage_to_color") define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color"
-
-// 153
-@extension("VK_NV_framebuffer_mixed_samples") define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1
-@extension("VK_NV_framebuffer_mixed_samples") define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples"
-
-// 154
-@extension("VK_NV_fill_rectangle") define VK_NV_FILL_RECTANGLE_SPEC_VERSION 1
-@extension("VK_NV_fill_rectangle") define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle"
-
-// 156
-@extension("VK_EXT_post_depth_coverage") define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1
-@extension("VK_EXT_post_depth_coverage") define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage"
-
-// 157
-@extension("VK_KHR_sampler_ycbcr_conversion") define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 1
-@extension("VK_KHR_sampler_ycbcr_conversion") define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion"
-
-// 158
-@extension("VK_KHR_bind_memory2") define VK_KHR_BIND_MEMORY2_SPEC_VERSION 1
-@extension("VK_KHR_bind_memory2") define VK_KHR_BIND_MEMORY2_EXTENSION_NAME "VK_KHR_bind_memory2"
-
-// 159
-@extension("VK_EXT_image_drm_format_modifier") define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 1
-@extension("VK_EXT_image_drm_format_modifier") define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier"
-
-// 161
-@extension("VK_EXT_validation_cache") define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1
-@extension("VK_EXT_validation_cache") define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache"
-
-// 162
-@extension("VK_EXT_descriptor_indexing") define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2
-@extension("VK_EXT_descriptor_indexing") define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing"
-
-// 163
-@extension("VK_EXT_shader_viewport_index_layer") define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1
-@extension("VK_EXT_shader_viewport_index_layer") define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer"
-
-// 165
-@extension("VK_NV_shading_rate_image") define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3
-@extension("VK_NV_shading_rate_image") define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image"
-
-// 166
-@extension("VK_NV_ray_tracing") define VK_NV_RAY_TRACING_SPEC_VERSION 3
-@extension("VK_NV_ray_tracing") define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing"
-
-// 167
-@extension("VK_NV_representative_fragment_test") define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 1
-@extension("VK_NV_representative_fragment_test") define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test"
-
-// 169
-@extension("VK_KHR_maintenance3") define VK_KHR_MAINTENANCE3_SPEC_VERSION 1
-@extension("VK_KHR_maintenance3") define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3"
-
-// 170
-@extension("VK_KHR_draw_indirect_count") define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
-@extension("VK_KHR_draw_indirect_count") define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count"
-
-// 175
-@extension("VK_EXT_global_priority") define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 1
-@extension("VK_EXT_global_priority") define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority"
-
-// 178
-@extension("VK_KHR_8bit_storage") define VK_KHR_8BIT_STORAGE_SPEC_VERSION 1
-@extension("VK_KHR_8bit_storage") define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage"
-
-// 179
-@extension("VK_EXT_external_memory_host") define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1
-@extension("VK_EXT_external_memory_host") define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host"
-
-// 180
-@extension("VK_AMD_buffer_marker") define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1
-@extension("VK_AMD_buffer_marker") define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker"
-
-// 181
-@extension("VK_KHR_shader_atomic_int64") define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1
-@extension("VK_KHR_shader_atomic_int64") define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64"
-
-// 186
-@extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 1
-@extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties"
-
-// 190
-@extension("VK_AMD_memory_overallocation_behavior") define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1
-@extension("VK_AMD_memory_overallocation_behavior") define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior"
-
-// 191
-@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 2
-@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
-
-// 197
-@extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1
-@extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties"
-
-// 198
-@extension("VK_KHR_shader_float_controls") define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 1
-@extension("VK_KHR_shader_float_controls") define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls"
-
-// 199
-@extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1
-@extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned"
-
-// 201
-@extension("VK_KHR_swapchain_mutable_format") define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1
-@extension("VK_KHR_swapchain_mutable_format") define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format"
-
-// 202
-@extension("VK_NV_compute_shader_derivatives") define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1
-@extension("VK_NV_compute_shader_derivatives") define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives"
-
-// 203
-@extension("VK_NV_mesh_shader") define VK_NV_MESH_SHADER_SPEC_VERSION 1
-@extension("VK_NV_mesh_shader") define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader"
-
-// 204
-@extension("VK_NV_fragment_shader_barycentric") define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1
-@extension("VK_NV_fragment_shader_barycentric") define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric"
-
-// 205
-@extension("VK_NV_shader_image_footprint") define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 1
-@extension("VK_NV_shader_image_footprint") define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint"
-
-// 206
-@extension("VK_NV_scissor_exclusive") define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1
-@extension("VK_NV_scissor_exclusive") define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive"
-
-// 207
-@extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2
-@extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints"
-
-// 212
-@extension("VK_KHR_vulkan_memory_model") define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2
-@extension("VK_KHR_vulkan_memory_model") define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
-
-// 213
-@extension("VK_EXT_pci_bus_info") define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2
-@extension("VK_EXT_pci_bus_info") define VK_EXT_PCI_BUS_INFO_EXENSION_NAME "VK_EXT_pci_bus_info"
-
-// 215
-@extension("VK_FUCHSIA_imagepipe_surface") define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1
-@extension("VK_FUCHSIA_imagepipe_surface") define VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME "VK_FUCHSIA_imagepipe_surface"
-
-// 219
-@extension("VK_EXT_fragment_density_map") define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 1
-@extension("VK_EXT_fragment_density_map") define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map"
-
-// 222
-@extension("VK_EXT_scalar_block_layout") define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1
-@extension("VK_EXT_scalar_block_layout") define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout"
-
-// 224
-@extension("VK_GOOGLE_hlsl_functionality1") define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 1
-@extension("VK_GOOGLE_hlsl_functionality1") define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1"
-
-// 225
-@extension("VK_GOOGLE_decorate_string") define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1
-@extension("VK_GOOGLE_decorate_string") define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string"
-
-// 247
-@extension("VK_EXT_separate_stencil_usage") define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1
-@extension("VK_EXT_separate_stencil_usage") define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage"
-
-/////////////
-//  Types  //
-/////////////
-
-type u32 VkBool32
-type u32 VkFlags
-type u64 VkDeviceSize
-type u32 VkSampleMask
-
-/// Dispatchable handle types.
-@dispatchHandle type u64 VkInstance
-@dispatchHandle type u64 VkPhysicalDevice
-@dispatchHandle type u64 VkDevice
-@dispatchHandle type u64 VkQueue
-@dispatchHandle type u64 VkCommandBuffer
-
-/// Non dispatchable handle types.
-@nonDispatchHandle type u64 VkDeviceMemory
-@nonDispatchHandle type u64 VkCommandPool
-@nonDispatchHandle type u64 VkBuffer
-@nonDispatchHandle type u64 VkBufferView
-@nonDispatchHandle type u64 VkImage
-@nonDispatchHandle type u64 VkImageView
-@nonDispatchHandle type u64 VkShaderModule
-@nonDispatchHandle type u64 VkPipeline
-@nonDispatchHandle type u64 VkPipelineLayout
-@nonDispatchHandle type u64 VkSampler
-@nonDispatchHandle type u64 VkDescriptorSet
-@nonDispatchHandle type u64 VkDescriptorSetLayout
-@nonDispatchHandle type u64 VkDescriptorPool
-@nonDispatchHandle type u64 VkFence
-@nonDispatchHandle type u64 VkSemaphore
-@nonDispatchHandle type u64 VkEvent
-@nonDispatchHandle type u64 VkQueryPool
-@nonDispatchHandle type u64 VkFramebuffer
-@nonDispatchHandle type u64 VkRenderPass
-@nonDispatchHandle type u64 VkPipelineCache
-
-@vulkan1_1
-@nonDispatchHandle type u64 VkSamplerYcbcrConversion
-@nonDispatchHandle type u64 VkDescriptorUpdateTemplate
-
-// 1
-@extension("VK_KHR_surface")    @nonDispatchHandle type u64 VkSurfaceKHR
-
-// 2
-@extension("VK_KHR_swapchain")  @nonDispatchHandle type u64 VkSwapchainKHR
-
-// 3
-@extension("VK_KHR_display")    @nonDispatchHandle type u64 VkDisplayKHR
-@extension("VK_KHR_display")    @nonDispatchHandle type u64 VkDisplayModeKHR
-
-// 12
-@extension("VK_EXT_debug_report") @nonDispatchHandle type u64 VkDebugReportCallbackEXT
-
-// 86
-@extension("VK_KHR_descriptor_update_template") @nonDispatchHandle type u64 VkDescriptorUpdateTemplateKHR
-
-// 87
-@extension("VK_NVX_device_generated_commands") @nonDispatchHandle type u64 VkObjectTableNVX
-@extension("VK_NVX_device_generated_commands") @nonDispatchHandle type u64 VkIndirectCommandsLayoutNVX
-
-// 129
-@extension("VK_EXT_debug_utils") @nonDispatchHandle type u64 VkDebugUtilsMessengerEXT
-
-// 157
-@extension("VK_KHR_sampler_ycbcr_conversion") @nonDispatchHandle type u64 VkSamplerYcbcrConversionKHR
-
-// 161
-@extension("VK_EXT_validation_cache") @nonDispatchHandle type u64 VkValidationCacheEXT
-
-// 166
-@extension("VK_NV_ray_tracing") @nonDispatchHandle type u64 VkAccelerationStructureNV
-
-/////////////
-//  Enums  //
-/////////////
-
-enum VkImageLayout {
-    VK_IMAGE_LAYOUT_UNDEFINED                               = 0x00000000,   /// Implicit layout an image is when its contents are undefined due to various reasons (e.g. right after creation)
-    VK_IMAGE_LAYOUT_GENERAL                                 = 0x00000001,   /// General layout when image can be used for any kind of access
-    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                = 0x00000002,   /// Optimal layout when image is only used for color attachment read/write
-    VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL        = 0x00000003,   /// Optimal layout when image is only used for depth/stencil attachment read/write
-    VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL         = 0x00000004,   /// Optimal layout when image is used for read only depth/stencil attachment and shader access
-    VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL                = 0x00000005,   /// Optimal layout when image is used for read only shader access
-    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL                    = 0x00000006,   /// Optimal layout when image is used only as source of transfer operations
-    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL                    = 0x00000007,   /// Optimal layout when image is used only as destination of transfer operations
-    VK_IMAGE_LAYOUT_PREINITIALIZED                          = 0x00000008,   /// Initial layout used when the data is populated by the CPU
-
-    //@vulkan1_1
-    VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000,
-    VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001,
-
-    //@extension("VK_KHR_swapchain") // 2
-    VK_IMAGE_LAYOUT_PRESENT_SRC_KHR                         = 1000001002,
-
-    //@extension("VK_KHR_shared_presentable_image") // 112
-    VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR                      = 1000111000,
-
-    //@extension("VK_KHR_maintenance2") // 118
-    VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR  = 1000117000,
-    VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR  = 1000117001,
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV                 = 1000164003,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT        = 1000218000,
-}
-
-enum VkAttachmentLoadOp {
-    VK_ATTACHMENT_LOAD_OP_LOAD                              = 0x00000000,
-    VK_ATTACHMENT_LOAD_OP_CLEAR                             = 0x00000001,
-    VK_ATTACHMENT_LOAD_OP_DONT_CARE                         = 0x00000002,
-}
-
-enum VkAttachmentStoreOp {
-    VK_ATTACHMENT_STORE_OP_STORE                            = 0x00000000,
-    VK_ATTACHMENT_STORE_OP_DONT_CARE                        = 0x00000001,
-}
-
-enum VkImageType {
-    VK_IMAGE_TYPE_1D                                        = 0x00000000,
-    VK_IMAGE_TYPE_2D                                        = 0x00000001,
-    VK_IMAGE_TYPE_3D                                        = 0x00000002,
-}
-
-enum VkImageTiling {
-    VK_IMAGE_TILING_OPTIMAL                                 = 0x00000000,
-    VK_IMAGE_TILING_LINEAR                                  = 0x00000001,
-
-    //@extension("VK_EXT_image_drm_format_modifier") // 159
-    VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT                 = 1000158000,
-}
-
-enum VkImageViewType {
-    VK_IMAGE_VIEW_TYPE_1D                                   = 0x00000000,
-    VK_IMAGE_VIEW_TYPE_2D                                   = 0x00000001,
-    VK_IMAGE_VIEW_TYPE_3D                                   = 0x00000002,
-    VK_IMAGE_VIEW_TYPE_CUBE                                 = 0x00000003,
-    VK_IMAGE_VIEW_TYPE_1D_ARRAY                             = 0x00000004,
-    VK_IMAGE_VIEW_TYPE_2D_ARRAY                             = 0x00000005,
-    VK_IMAGE_VIEW_TYPE_CUBE_ARRAY                           = 0x00000006,
-}
-
-enum VkCommandBufferLevel {
-    VK_COMMAND_BUFFER_LEVEL_PRIMARY                         = 0x00000000,
-    VK_COMMAND_BUFFER_LEVEL_SECONDARY                       = 0x00000001,
-}
-
-enum VkComponentSwizzle {
-    VK_COMPONENT_SWIZZLE_IDENTITY                           = 0x00000000,
-    VK_COMPONENT_SWIZZLE_ZERO                               = 0x00000001,
-    VK_COMPONENT_SWIZZLE_ONE                                = 0x00000002,
-    VK_COMPONENT_SWIZZLE_R                                  = 0x00000003,
-    VK_COMPONENT_SWIZZLE_G                                  = 0x00000004,
-    VK_COMPONENT_SWIZZLE_B                                  = 0x00000005,
-    VK_COMPONENT_SWIZZLE_A                                  = 0x00000006,
-}
-
-enum VkDescriptorType {
-    VK_DESCRIPTOR_TYPE_SAMPLER                              = 0x00000000,
-    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER               = 0x00000001,
-    VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE                        = 0x00000002,
-    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE                        = 0x00000003,
-    VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER                 = 0x00000004,
-    VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER                 = 0x00000005,
-    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER                       = 0x00000006,
-    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER                       = 0x00000007,
-    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC               = 0x00000008,
-    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC               = 0x00000009,
-    VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT                     = 0x0000000a,
-
-    //@extension("VK_EXT_inline_uniform_block") // 139
-    VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT             = 1000138000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV            = 1000165000,
-}
-
-enum VkQueryType {
-    VK_QUERY_TYPE_OCCLUSION                                 = 0x00000000,
-    VK_QUERY_TYPE_PIPELINE_STATISTICS                       = 0x00000001, /// Optional
-    VK_QUERY_TYPE_TIMESTAMP                                 = 0x00000002,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT             = 1000028004,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV  = 1000165000,
-}
-
-enum VkBorderColor {
-    VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK                 = 0x00000000,
-    VK_BORDER_COLOR_INT_TRANSPARENT_BLACK                   = 0x00000001,
-    VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK                      = 0x00000002,
-    VK_BORDER_COLOR_INT_OPAQUE_BLACK                        = 0x00000003,
-    VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE                      = 0x00000004,
-    VK_BORDER_COLOR_INT_OPAQUE_WHITE                        = 0x00000005,
-}
-
-enum VkPipelineBindPoint {
-    VK_PIPELINE_BIND_POINT_GRAPHICS                         = 0x00000000,
-    VK_PIPELINE_BIND_POINT_COMPUTE                          = 0x00000001,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_PIPELINE_BIND_POINT_RAY_TRACING_NV                   = 1000165000,
-}
-
-enum VkPrimitiveTopology {
-    VK_PRIMITIVE_TOPOLOGY_POINT_LIST                        = 0x00000000,
-    VK_PRIMITIVE_TOPOLOGY_LINE_LIST                         = 0x00000001,
-    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP                        = 0x00000002,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST                     = 0x00000003,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP                    = 0x00000004,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN                      = 0x00000005,
-    VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY          = 0x00000006,
-    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY         = 0x00000007,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY      = 0x00000008,
-    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY     = 0x00000009,
-    VK_PRIMITIVE_TOPOLOGY_PATCH_LIST                        = 0x0000000a,
-}
-
-enum VkSharingMode {
-    VK_SHARING_MODE_EXCLUSIVE                               = 0x00000000,
-    VK_SHARING_MODE_CONCURRENT                              = 0x00000001,
-}
-
-enum VkIndexType {
-    VK_INDEX_TYPE_UINT16                                    = 0x00000000,
-    VK_INDEX_TYPE_UINT32                                    = 0x00000001,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_INDEX_TYPE_NONE_NV                                   = 1000165000,
-}
-
-enum VkFilter {
-    VK_FILTER_NEAREST                                       = 0x00000000,
-    VK_FILTER_LINEAR                                        = 0x00000001,
-
-    //@extension("VK_IMG_filter_cubic") // 16
-    VK_FILTER_CUBIC_IMG                                     = 1000015000,
-}
-
-enum VkSamplerMipmapMode {
-    VK_SAMPLER_MIPMAP_MODE_NEAREST                          = 0x00000001,   /// Choose nearest mip level
-    VK_SAMPLER_MIPMAP_MODE_LINEAR                           = 0x00000002,   /// Linear filter between mip levels
-}
-
-enum VkSamplerAddressMode {
-    VK_SAMPLER_ADDRESS_MODE_REPEAT                          = 0x00000000,
-    VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT                 = 0x00000001,
-    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE                   = 0x00000002,
-    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER                 = 0x00000003,
-    VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE            = 0x00000004,
-}
-
-enum VkCompareOp {
-    VK_COMPARE_OP_NEVER                                     = 0x00000000,
-    VK_COMPARE_OP_LESS                                      = 0x00000001,
-    VK_COMPARE_OP_EQUAL                                     = 0x00000002,
-    VK_COMPARE_OP_LESS_OR_EQUAL                             = 0x00000003,
-    VK_COMPARE_OP_GREATER                                   = 0x00000004,
-    VK_COMPARE_OP_NOT_EQUAL                                 = 0x00000005,
-    VK_COMPARE_OP_GREATER_OR_EQUAL                          = 0x00000006,
-    VK_COMPARE_OP_ALWAYS                                    = 0x00000007,
-}
-
-enum VkPolygonMode {
-    VK_POLYGON_MODE_FILL                                    = 0x00000000,
-    VK_POLYGON_MODE_LINE                                    = 0x00000001,
-    VK_POLYGON_MODE_POINT                                   = 0x00000002,
-
-    //@extension("VK_NV_fill_rectangle") // 154
-    VK_POLYGON_MODE_FILL_RECTANGLE_NV                       = 1000153000,
-}
-
-enum VkFrontFace {
-    VK_FRONT_FACE_COUNTER_CLOCKWISE                         = 0x00000000,
-    VK_FRONT_FACE_CLOCKWISE                                 = 0x00000001,
-}
-
-enum VkBlendFactor {
-    VK_BLEND_FACTOR_ZERO                                    = 0x00000000,
-    VK_BLEND_FACTOR_ONE                                     = 0x00000001,
-    VK_BLEND_FACTOR_SRC_COLOR                               = 0x00000002,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR                     = 0x00000003,
-    VK_BLEND_FACTOR_DST_COLOR                               = 0x00000004,
-    VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR                     = 0x00000005,
-    VK_BLEND_FACTOR_SRC_ALPHA                               = 0x00000006,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA                     = 0x00000007,
-    VK_BLEND_FACTOR_DST_ALPHA                               = 0x00000008,
-    VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA                     = 0x00000009,
-    VK_BLEND_FACTOR_CONSTANT_COLOR                          = 0x0000000a,
-    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR                = 0x0000000b,
-    VK_BLEND_FACTOR_CONSTANT_ALPHA                          = 0x0000000c,
-    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA                = 0x0000000d,
-    VK_BLEND_FACTOR_SRC_ALPHA_SATURATE                      = 0x0000000e,
-    VK_BLEND_FACTOR_SRC1_COLOR                              = 0x0000000f,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR                    = 0x00000010,
-    VK_BLEND_FACTOR_SRC1_ALPHA                              = 0x00000011,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA                    = 0x00000012,
-}
-
-enum VkBlendOp {
-    VK_BLEND_OP_ADD                                         = 0x00000000,
-    VK_BLEND_OP_SUBTRACT                                    = 0x00000001,
-    VK_BLEND_OP_REVERSE_SUBTRACT                            = 0x00000002,
-    VK_BLEND_OP_MIN                                         = 0x00000003,
-    VK_BLEND_OP_MAX                                         = 0x00000004,
-
-    //@extension("VK_EXT_blend_operation_advanced") // 149
-    VK_BLEND_OP_ZERO_EXT                                    = 1000148000,
-    VK_BLEND_OP_SRC_EXT                                     = 1000148001,
-    VK_BLEND_OP_DST_EXT                                     = 1000148002,
-    VK_BLEND_OP_SRC_OVER_EXT                                = 1000148003,
-    VK_BLEND_OP_DST_OVER_EXT                                = 1000148004,
-    VK_BLEND_OP_SRC_IN_EXT                                  = 1000148005,
-    VK_BLEND_OP_DST_IN_EXT                                  = 1000148006,
-    VK_BLEND_OP_SRC_OUT_EXT                                 = 1000148007,
-    VK_BLEND_OP_DST_OUT_EXT                                 = 1000148008,
-    VK_BLEND_OP_SRC_ATOP_EXT                                = 1000148009,
-    VK_BLEND_OP_DST_ATOP_EXT                                = 1000148010,
-    VK_BLEND_OP_XOR_EXT                                     = 1000148011,
-    VK_BLEND_OP_MULTIPLY_EXT                                = 1000148012,
-    VK_BLEND_OP_SCREEN_EXT                                  = 1000148013,
-    VK_BLEND_OP_OVERLAY_EXT                                 = 1000148014,
-    VK_BLEND_OP_DARKEN_EXT                                  = 1000148015,
-    VK_BLEND_OP_LIGHTEN_EXT                                 = 1000148016,
-    VK_BLEND_OP_COLORDODGE_EXT                              = 1000148017,
-    VK_BLEND_OP_COLORBURN_EXT                               = 1000148018,
-    VK_BLEND_OP_HARDLIGHT_EXT                               = 1000148019,
-    VK_BLEND_OP_SOFTLIGHT_EXT                               = 1000148020,
-    VK_BLEND_OP_DIFFERENCE_EXT                              = 1000148021,
-    VK_BLEND_OP_EXCLUSION_EXT                               = 1000148022,
-    VK_BLEND_OP_INVERT_EXT                                  = 1000148023,
-    VK_BLEND_OP_INVERT_RGB_EXT                              = 1000148024,
-    VK_BLEND_OP_LINEARDODGE_EXT                             = 1000148025,
-    VK_BLEND_OP_LINEARBURN_EXT                              = 1000148026,
-    VK_BLEND_OP_VIVIDLIGHT_EXT                              = 1000148027,
-    VK_BLEND_OP_LINEARLIGHT_EXT                             = 1000148028,
-    VK_BLEND_OP_PINLIGHT_EXT                                = 1000148029,
-    VK_BLEND_OP_HARDMIX_EXT                                 = 1000148030,
-    VK_BLEND_OP_HSL_HUE_EXT                                 = 1000148031,
-    VK_BLEND_OP_HSL_SATURATION_EXT                          = 1000148032,
-    VK_BLEND_OP_HSL_COLOR_EXT                               = 1000148033,
-    VK_BLEND_OP_HSL_LUMINOSITY_EXT                          = 1000148034,
-    VK_BLEND_OP_PLUS_EXT                                    = 1000148035,
-    VK_BLEND_OP_PLUS_CLAMPED_EXT                            = 1000148036,
-    VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT                      = 1000148037,
-    VK_BLEND_OP_PLUS_DARKER_EXT                             = 1000148038,
-    VK_BLEND_OP_MINUS_EXT                                   = 1000148039,
-    VK_BLEND_OP_MINUS_CLAMPED_EXT                           = 1000148040,
-    VK_BLEND_OP_CONTRAST_EXT                                = 1000148041,
-    VK_BLEND_OP_INVERT_OVG_EXT                              = 1000148042,
-    VK_BLEND_OP_RED_EXT                                     = 1000148043,
-    VK_BLEND_OP_GREEN_EXT                                   = 1000148044,
-    VK_BLEND_OP_BLUE_EXT                                    = 1000148045,
-}
-
-enum VkStencilOp {
-    VK_STENCIL_OP_KEEP                                      = 0x00000000,
-    VK_STENCIL_OP_ZERO                                      = 0x00000001,
-    VK_STENCIL_OP_REPLACE                                   = 0x00000002,
-    VK_STENCIL_OP_INCREMENT_AND_CLAMP                       = 0x00000003,
-    VK_STENCIL_OP_DECREMENT_AND_CLAMP                       = 0x00000004,
-    VK_STENCIL_OP_INVERT                                    = 0x00000005,
-    VK_STENCIL_OP_INCREMENT_AND_WRAP                        = 0x00000006,
-    VK_STENCIL_OP_DECREMENT_AND_WRAP                        = 0x00000007,
-}
-
-enum VkLogicOp {
-    VK_LOGIC_OP_CLEAR                                       = 0x00000000,
-    VK_LOGIC_OP_AND                                         = 0x00000001,
-    VK_LOGIC_OP_AND_REVERSE                                 = 0x00000002,
-    VK_LOGIC_OP_COPY                                        = 0x00000003,
-    VK_LOGIC_OP_AND_INVERTED                                = 0x00000004,
-    VK_LOGIC_OP_NO_OP                                       = 0x00000005,
-    VK_LOGIC_OP_XOR                                         = 0x00000006,
-    VK_LOGIC_OP_OR                                          = 0x00000007,
-    VK_LOGIC_OP_NOR                                         = 0x00000008,
-    VK_LOGIC_OP_EQUIVALENT                                  = 0x00000009,
-    VK_LOGIC_OP_INVERT                                      = 0x0000000a,
-    VK_LOGIC_OP_OR_REVERSE                                  = 0x0000000b,
-    VK_LOGIC_OP_COPY_INVERTED                               = 0x0000000c,
-    VK_LOGIC_OP_OR_INVERTED                                 = 0x0000000d,
-    VK_LOGIC_OP_NAND                                        = 0x0000000e,
-    VK_LOGIC_OP_SET                                         = 0x0000000f,
-}
-
-enum VkSystemAllocationScope {
-    VK_SYSTEM_ALLOCATION_SCOPE_COMMAND                      = 0x00000000,
-    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT                       = 0x00000001,
-    VK_SYSTEM_ALLOCATION_SCOPE_CACHE                        = 0x00000002,
-    VK_SYSTEM_ALLOCATION_SCOPE_DEVICE                       = 0x00000003,
-    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE                     = 0x00000004,
-}
-
-enum VkInternalAllocationType {
-    VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE                  = 0x00000000,
-}
-
-enum VkPhysicalDeviceType {
-    VK_PHYSICAL_DEVICE_TYPE_OTHER                           = 0x00000000,
-    VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU                  = 0x00000001,
-    VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU                    = 0x00000002,
-    VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU                     = 0x00000003,
-    VK_PHYSICAL_DEVICE_TYPE_CPU                             = 0x00000004,
-}
-
-enum VkVertexInputRate {
-    VK_VERTEX_INPUT_RATE_VERTEX                             = 0x00000000,
-    VK_VERTEX_INPUT_RATE_INSTANCE                           = 0x00000001,
-}
-
-/// Vulkan format definitions
-enum VkFormat {
-    VK_FORMAT_UNDEFINED                                     = 0,
-    VK_FORMAT_R4G4_UNORM_PACK8                              = 1,
-    VK_FORMAT_R4G4B4A4_UNORM_PACK16                         = 2,
-    VK_FORMAT_B4G4R4A4_UNORM_PACK16                         = 3,
-    VK_FORMAT_R5G6B5_UNORM_PACK16                           = 4,
-    VK_FORMAT_B5G6R5_UNORM_PACK16                           = 5,
-    VK_FORMAT_R5G5B5A1_UNORM_PACK16                         = 6,
-    VK_FORMAT_B5G5R5A1_UNORM_PACK16                         = 7,
-    VK_FORMAT_A1R5G5B5_UNORM_PACK16                         = 8,
-    VK_FORMAT_R8_UNORM                                      = 9,
-    VK_FORMAT_R8_SNORM                                      = 10,
-    VK_FORMAT_R8_USCALED                                    = 11,
-    VK_FORMAT_R8_SSCALED                                    = 12,
-    VK_FORMAT_R8_UINT                                       = 13,
-    VK_FORMAT_R8_SINT                                       = 14,
-    VK_FORMAT_R8_SRGB                                       = 15,
-    VK_FORMAT_R8G8_UNORM                                    = 16,
-    VK_FORMAT_R8G8_SNORM                                    = 17,
-    VK_FORMAT_R8G8_USCALED                                  = 18,
-    VK_FORMAT_R8G8_SSCALED                                  = 19,
-    VK_FORMAT_R8G8_UINT                                     = 20,
-    VK_FORMAT_R8G8_SINT                                     = 21,
-    VK_FORMAT_R8G8_SRGB                                     = 22,
-    VK_FORMAT_R8G8B8_UNORM                                  = 23,
-    VK_FORMAT_R8G8B8_SNORM                                  = 24,
-    VK_FORMAT_R8G8B8_USCALED                                = 25,
-    VK_FORMAT_R8G8B8_SSCALED                                = 26,
-    VK_FORMAT_R8G8B8_UINT                                   = 27,
-    VK_FORMAT_R8G8B8_SINT                                   = 28,
-    VK_FORMAT_R8G8B8_SRGB                                   = 29,
-    VK_FORMAT_B8G8R8_UNORM                                  = 30,
-    VK_FORMAT_B8G8R8_SNORM                                  = 31,
-    VK_FORMAT_B8G8R8_USCALED                                = 32,
-    VK_FORMAT_B8G8R8_SSCALED                                = 33,
-    VK_FORMAT_B8G8R8_UINT                                   = 34,
-    VK_FORMAT_B8G8R8_SINT                                   = 35,
-    VK_FORMAT_B8G8R8_SRGB                                   = 36,
-    VK_FORMAT_R8G8B8A8_UNORM                                = 37,
-    VK_FORMAT_R8G8B8A8_SNORM                                = 38,
-    VK_FORMAT_R8G8B8A8_USCALED                              = 39,
-    VK_FORMAT_R8G8B8A8_SSCALED                              = 40,
-    VK_FORMAT_R8G8B8A8_UINT                                 = 41,
-    VK_FORMAT_R8G8B8A8_SINT                                 = 42,
-    VK_FORMAT_R8G8B8A8_SRGB                                 = 43,
-    VK_FORMAT_B8G8R8A8_UNORM                                = 44,
-    VK_FORMAT_B8G8R8A8_SNORM                                = 45,
-    VK_FORMAT_B8G8R8A8_USCALED                              = 46,
-    VK_FORMAT_B8G8R8A8_SSCALED                              = 47,
-    VK_FORMAT_B8G8R8A8_UINT                                 = 48,
-    VK_FORMAT_B8G8R8A8_SINT                                 = 49,
-    VK_FORMAT_B8G8R8A8_SRGB                                 = 50,
-    VK_FORMAT_A8B8G8R8_UNORM_PACK32                         = 51,
-    VK_FORMAT_A8B8G8R8_SNORM_PACK32                         = 52,
-    VK_FORMAT_A8B8G8R8_USCALED_PACK32                       = 53,
-    VK_FORMAT_A8B8G8R8_SSCALED_PACK32                       = 54,
-    VK_FORMAT_A8B8G8R8_UINT_PACK32                          = 55,
-    VK_FORMAT_A8B8G8R8_SINT_PACK32                          = 56,
-    VK_FORMAT_A8B8G8R8_SRGB_PACK32                          = 57,
-    VK_FORMAT_A2R10G10B10_UNORM_PACK32                      = 58,
-    VK_FORMAT_A2R10G10B10_SNORM_PACK32                      = 59,
-    VK_FORMAT_A2R10G10B10_USCALED_PACK32                    = 60,
-    VK_FORMAT_A2R10G10B10_SSCALED_PACK32                    = 61,
-    VK_FORMAT_A2R10G10B10_UINT_PACK32                       = 62,
-    VK_FORMAT_A2R10G10B10_SINT_PACK32                       = 63,
-    VK_FORMAT_A2B10G10R10_UNORM_PACK32                      = 64,
-    VK_FORMAT_A2B10G10R10_SNORM_PACK32                      = 65,
-    VK_FORMAT_A2B10G10R10_USCALED_PACK32                    = 66,
-    VK_FORMAT_A2B10G10R10_SSCALED_PACK32                    = 67,
-    VK_FORMAT_A2B10G10R10_UINT_PACK32                       = 68,
-    VK_FORMAT_A2B10G10R10_SINT_PACK32                       = 69,
-    VK_FORMAT_R16_UNORM                                     = 70,
-    VK_FORMAT_R16_SNORM                                     = 71,
-    VK_FORMAT_R16_USCALED                                   = 72,
-    VK_FORMAT_R16_SSCALED                                   = 73,
-    VK_FORMAT_R16_UINT                                      = 74,
-    VK_FORMAT_R16_SINT                                      = 75,
-    VK_FORMAT_R16_SFLOAT                                    = 76,
-    VK_FORMAT_R16G16_UNORM                                  = 77,
-    VK_FORMAT_R16G16_SNORM                                  = 78,
-    VK_FORMAT_R16G16_USCALED                                = 79,
-    VK_FORMAT_R16G16_SSCALED                                = 80,
-    VK_FORMAT_R16G16_UINT                                   = 81,
-    VK_FORMAT_R16G16_SINT                                   = 82,
-    VK_FORMAT_R16G16_SFLOAT                                 = 83,
-    VK_FORMAT_R16G16B16_UNORM                               = 84,
-    VK_FORMAT_R16G16B16_SNORM                               = 85,
-    VK_FORMAT_R16G16B16_USCALED                             = 86,
-    VK_FORMAT_R16G16B16_SSCALED                             = 87,
-    VK_FORMAT_R16G16B16_UINT                                = 88,
-    VK_FORMAT_R16G16B16_SINT                                = 89,
-    VK_FORMAT_R16G16B16_SFLOAT                              = 90,
-    VK_FORMAT_R16G16B16A16_UNORM                            = 91,
-    VK_FORMAT_R16G16B16A16_SNORM                            = 92,
-    VK_FORMAT_R16G16B16A16_USCALED                          = 93,
-    VK_FORMAT_R16G16B16A16_SSCALED                          = 94,
-    VK_FORMAT_R16G16B16A16_UINT                             = 95,
-    VK_FORMAT_R16G16B16A16_SINT                             = 96,
-    VK_FORMAT_R16G16B16A16_SFLOAT                           = 97,
-    VK_FORMAT_R32_UINT                                      = 98,
-    VK_FORMAT_R32_SINT                                      = 99,
-    VK_FORMAT_R32_SFLOAT                                    = 100,
-    VK_FORMAT_R32G32_UINT                                   = 101,
-    VK_FORMAT_R32G32_SINT                                   = 102,
-    VK_FORMAT_R32G32_SFLOAT                                 = 103,
-    VK_FORMAT_R32G32B32_UINT                                = 104,
-    VK_FORMAT_R32G32B32_SINT                                = 105,
-    VK_FORMAT_R32G32B32_SFLOAT                              = 106,
-    VK_FORMAT_R32G32B32A32_UINT                             = 107,
-    VK_FORMAT_R32G32B32A32_SINT                             = 108,
-    VK_FORMAT_R32G32B32A32_SFLOAT                           = 109,
-    VK_FORMAT_R64_UINT                                      = 110,
-    VK_FORMAT_R64_SINT                                      = 111,
-    VK_FORMAT_R64_SFLOAT                                    = 112,
-    VK_FORMAT_R64G64_UINT                                   = 113,
-    VK_FORMAT_R64G64_SINT                                   = 114,
-    VK_FORMAT_R64G64_SFLOAT                                 = 115,
-    VK_FORMAT_R64G64B64_UINT                                = 116,
-    VK_FORMAT_R64G64B64_SINT                                = 117,
-    VK_FORMAT_R64G64B64_SFLOAT                              = 118,
-    VK_FORMAT_R64G64B64A64_UINT                             = 119,
-    VK_FORMAT_R64G64B64A64_SINT                             = 120,
-    VK_FORMAT_R64G64B64A64_SFLOAT                           = 121,
-    VK_FORMAT_B10G11R11_UFLOAT_PACK32                       = 122,
-    VK_FORMAT_E5B9G9R9_UFLOAT_PACK32                        = 123,
-    VK_FORMAT_D16_UNORM                                     = 124,
-    VK_FORMAT_X8_D24_UNORM_PACK32                           = 125,
-    VK_FORMAT_D32_SFLOAT                                    = 126,
-    VK_FORMAT_S8_UINT                                       = 127,
-    VK_FORMAT_D16_UNORM_S8_UINT                             = 128,
-    VK_FORMAT_D24_UNORM_S8_UINT                             = 129,
-    VK_FORMAT_D32_SFLOAT_S8_UINT                            = 130,
-    VK_FORMAT_BC1_RGB_UNORM_BLOCK                           = 131,
-    VK_FORMAT_BC1_RGB_SRGB_BLOCK                            = 132,
-    VK_FORMAT_BC1_RGBA_UNORM_BLOCK                          = 133,
-    VK_FORMAT_BC1_RGBA_SRGB_BLOCK                           = 134,
-    VK_FORMAT_BC2_UNORM_BLOCK                               = 135,
-    VK_FORMAT_BC2_SRGB_BLOCK                                = 136,
-    VK_FORMAT_BC3_UNORM_BLOCK                               = 137,
-    VK_FORMAT_BC3_SRGB_BLOCK                                = 138,
-    VK_FORMAT_BC4_UNORM_BLOCK                               = 139,
-    VK_FORMAT_BC4_SNORM_BLOCK                               = 140,
-    VK_FORMAT_BC5_UNORM_BLOCK                               = 141,
-    VK_FORMAT_BC5_SNORM_BLOCK                               = 142,
-    VK_FORMAT_BC6H_UFLOAT_BLOCK                             = 143,
-    VK_FORMAT_BC6H_SFLOAT_BLOCK                             = 144,
-    VK_FORMAT_BC7_UNORM_BLOCK                               = 145,
-    VK_FORMAT_BC7_SRGB_BLOCK                                = 146,
-    VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK                       = 147,
-    VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK                        = 148,
-    VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK                     = 149,
-    VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK                      = 150,
-    VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK                     = 151,
-    VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK                      = 152,
-    VK_FORMAT_EAC_R11_UNORM_BLOCK                           = 153,
-    VK_FORMAT_EAC_R11_SNORM_BLOCK                           = 154,
-    VK_FORMAT_EAC_R11G11_UNORM_BLOCK                        = 155,
-    VK_FORMAT_EAC_R11G11_SNORM_BLOCK                        = 156,
-    VK_FORMAT_ASTC_4x4_UNORM_BLOCK                          = 157,
-    VK_FORMAT_ASTC_4x4_SRGB_BLOCK                           = 158,
-    VK_FORMAT_ASTC_5x4_UNORM_BLOCK                          = 159,
-    VK_FORMAT_ASTC_5x4_SRGB_BLOCK                           = 160,
-    VK_FORMAT_ASTC_5x5_UNORM_BLOCK                          = 161,
-    VK_FORMAT_ASTC_5x5_SRGB_BLOCK                           = 162,
-    VK_FORMAT_ASTC_6x5_UNORM_BLOCK                          = 163,
-    VK_FORMAT_ASTC_6x5_SRGB_BLOCK                           = 164,
-    VK_FORMAT_ASTC_6x6_UNORM_BLOCK                          = 165,
-    VK_FORMAT_ASTC_6x6_SRGB_BLOCK                           = 166,
-    VK_FORMAT_ASTC_8x5_UNORM_BLOCK                          = 167,
-    VK_FORMAT_ASTC_8x5_SRGB_BLOCK                           = 168,
-    VK_FORMAT_ASTC_8x6_UNORM_BLOCK                          = 169,
-    VK_FORMAT_ASTC_8x6_SRGB_BLOCK                           = 170,
-    VK_FORMAT_ASTC_8x8_UNORM_BLOCK                          = 171,
-    VK_FORMAT_ASTC_8x8_SRGB_BLOCK                           = 172,
-    VK_FORMAT_ASTC_10x5_UNORM_BLOCK                         = 173,
-    VK_FORMAT_ASTC_10x5_SRGB_BLOCK                          = 174,
-    VK_FORMAT_ASTC_10x6_UNORM_BLOCK                         = 175,
-    VK_FORMAT_ASTC_10x6_SRGB_BLOCK                          = 176,
-    VK_FORMAT_ASTC_10x8_UNORM_BLOCK                         = 177,
-    VK_FORMAT_ASTC_10x8_SRGB_BLOCK                          = 178,
-    VK_FORMAT_ASTC_10x10_UNORM_BLOCK                        = 179,
-    VK_FORMAT_ASTC_10x10_SRGB_BLOCK                         = 180,
-    VK_FORMAT_ASTC_12x10_UNORM_BLOCK                        = 181,
-    VK_FORMAT_ASTC_12x10_SRGB_BLOCK                         = 182,
-    VK_FORMAT_ASTC_12x12_UNORM_BLOCK                        = 183,
-    VK_FORMAT_ASTC_12x12_SRGB_BLOCK                         = 184,
-
-    //@vulkan1_1
-    VK_FORMAT_G8B8G8R8_422_UNORM                            = 1000156000,
-    VK_FORMAT_B8G8R8G8_422_UNORM                            = 1000156001,
-    VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM                     = 1000156002,
-    VK_FORMAT_G8_B8R8_2PLANE_420_UNORM                      = 1000156003,
-    VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM                     = 1000156004,
-    VK_FORMAT_G8_B8R8_2PLANE_422_UNORM                      = 1000156005,
-    VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM                     = 1000156006,
-    VK_FORMAT_R10X6_UNORM_PACK16                            = 1000156007,
-    VK_FORMAT_R10X6G10X6_UNORM_2PACK16                      = 1000156008,
-    VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16            = 1000156009,
-    VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16        = 1000156010,
-    VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16        = 1000156011,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16    = 1000156012,
-    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16     = 1000156013,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16    = 1000156014,
-    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16     = 1000156015,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16    = 1000156016,
-    VK_FORMAT_R12X4_UNORM_PACK16                            = 1000156017,
-    VK_FORMAT_R12X4G12X4_UNORM_2PACK16                      = 1000156018,
-    VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16            = 1000156019,
-    VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16        = 1000156020,
-    VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16        = 1000156021,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16    = 1000156022,
-    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16     = 1000156023,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16    = 1000156024,
-    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16     = 1000156025,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16    = 1000156026,
-    VK_FORMAT_G16B16G16R16_422_UNORM                        = 1000156027,
-    VK_FORMAT_B16G16R16G16_422_UNORM                        = 1000156028,
-    VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM                  = 1000156029,
-    VK_FORMAT_G16_B16R16_2PLANE_420_UNORM                   = 1000156030,
-    VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM                  = 1000156031,
-    VK_FORMAT_G16_B16R16_2PLANE_422_UNORM                   = 1000156032,
-    VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM                  = 1000156033,
-
-    //@extension("VK_IMG_format_pvrtc") // 28
-    VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG                   = 1000054000,
-    VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG                   = 1000054001,
-    VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG                   = 1000054002,
-    VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG                   = 1000054003,
-    VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG                    = 1000054004,
-    VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG                    = 1000054005,
-    VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG                    = 1000054006,
-    VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG                    = 1000054007,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    VK_FORMAT_G8B8G8R8_422_UNORM_KHR                            = 1000156000,
-    VK_FORMAT_B8G8R8G8_422_UNORM_KHR                            = 1000156001,
-    VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR                     = 1000156002,
-    VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR                      = 1000156003,
-    VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR                     = 1000156004,
-    VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR                      = 1000156005,
-    VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR                     = 1000156006,
-    VK_FORMAT_R10X6_UNORM_PACK16_KHR                            = 1000156007,
-    VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR                      = 1000156008,
-    VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR            = 1000156009,
-    VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR        = 1000156010,
-    VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR        = 1000156011,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR    = 1000156012,
-    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR     = 1000156013,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR    = 1000156014,
-    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR     = 1000156015,
-    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR    = 1000156016,
-    VK_FORMAT_R12X4_UNORM_PACK16_KHR                            = 1000156017,
-    VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR                      = 1000156018,
-    VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR            = 1000156019,
-    VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR        = 1000156020,
-    VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR        = 1000156021,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR    = 1000156022,
-    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR     = 1000156023,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR    = 1000156024,
-    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR     = 1000156025,
-    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR    = 1000156026,
-    VK_FORMAT_G16B16G16R16_422_UNORM_KHR                        = 1000156027,
-    VK_FORMAT_B16G16R16G16_422_UNORM_KHR                        = 1000156028,
-    VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR                  = 1000156029,
-    VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR                   = 1000156030,
-    VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR                  = 1000156031,
-    VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR                   = 1000156032,
-    VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR                  = 1000156033,
-}
-
-/// Structure type enumerant
-enum VkStructureType {
-    VK_STRUCTURE_TYPE_APPLICATION_INFO                          = 0,
-    VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO                      = 1,
-    VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO                  = 2,
-    VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO                        = 3,
-    VK_STRUCTURE_TYPE_SUBMIT_INFO                               = 4,
-    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO                      = 5,
-    VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE                       = 6,
-    VK_STRUCTURE_TYPE_BIND_SPARSE_INFO                          = 7,
-    VK_STRUCTURE_TYPE_FENCE_CREATE_INFO                         = 8,
-    VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO                     = 9,
-    VK_STRUCTURE_TYPE_EVENT_CREATE_INFO                         = 10,
-    VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO                    = 11,
-    VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO                        = 12,
-    VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO                   = 13,
-    VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO                         = 14,
-    VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO                    = 15,
-    VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO                 = 16,
-    VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO                = 17,
-    VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO         = 18,
-    VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO   = 19,
-    VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20,
-    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO   = 21,
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO       = 22,
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO  = 23,
-    VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO    = 24,
-    VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO  = 25,
-    VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO    = 26,
-    VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO        = 27,
-    VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO             = 28,
-    VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO              = 29,
-    VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO               = 30,
-    VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO                       = 31,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO         = 32,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO               = 33,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO              = 34,
-    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET                      = 35,
-    VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET                       = 36,
-    VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO                   = 37,
-    VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO                   = 38,
-    VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO                  = 39,
-    VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO              = 40,
-    VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO           = 41,
-    VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO                 = 42,
-    VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO                    = 43,
-    VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER                     = 44,
-    VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER                      = 45,
-    VK_STRUCTURE_TYPE_MEMORY_BARRIER                            = 46,
-    VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO               = 47,
-    VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO                 = 48,
-
-    //@vulkan1_1
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES       = 1000094000,
-    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO                   = 1000157000,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO                    = 1000157001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES    = 1000083000,
-    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS             = 1000127000,
-    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO            = 1000127001,
-    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO                = 1000060000,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO       = 1000060003,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO    = 1000060004,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO                  = 1000060005,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO             = 1000060006,
-    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO      = 1000060013,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO       = 1000060014,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES          = 1000070000,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO           = 1000070001,
-    VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2         = 1000146000,
-    VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2          = 1000146001,
-    VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2   = 1000146002,
-    VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2                     = 1000146003,
-    VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2        = 1000146004,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2                = 1000059000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2              = 1000059001,
-    VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2                       = 1000059002,
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2                 = 1000059003,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2       = 1000059004,
-    VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2                 = 1000059005,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2       = 1000059006,
-    VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2          = 1000059007,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2            = 1000059008,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES             = 1000117000,
-    VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO       = 1000117001,
-    VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO                          = 1000117002,
-    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003,
-    VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO                 = 1000053000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES                = 1000053001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES              = 1000053002,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES         = 1000120000,
-    VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO                             = 1000145000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES         = 1000145001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES       = 1000145002,
-    VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2                               = 1000145003,
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO              = 1000156000,
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO                     = 1000156001,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO                      = 1000156002,
-    VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO              = 1000156003,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004,
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES  = 1000156005,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO            = 1000085000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO        = 1000071000,
-    VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES                  = 1000071001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO              = 1000071002,
-    VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES                        = 1000071003,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES                     = 1000071004,
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO                = 1000072000,
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO                 = 1000072001,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO                       = 1000072002,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO               = 1000112000,
-    VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES                         = 1000112001,
-    VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO                          = 1000113000,
-    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO                      = 1000077000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO           = 1000076000,
-    VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES                     = 1000076001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES          = 1000168000,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT                     = 1000168001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES    = 1000063000,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR             = 1000060007,
-
-    //@extension("VK_KHR_swapchain") // 2
-    VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR                 = 1000001000,
-    VK_STRUCTURE_TYPE_PRESENT_INFO_KHR                          = 1000001001,
-    // added as interaction from VK_KHR_device_group / VK 1.1
-    VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR           = 1000060008,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR      = 1000060009,
-    VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR               = 1000060010,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR             = 1000060011,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR    = 1000060012,
-
-    //@extension("VK_KHR_display") // 3
-    VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR              = 1000002000,
-    VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR           = 1000002001,
-
-    //@extension("VK_KHR_display_swapchain") // 4
-    VK_STRUCTURE_TYPE_DISPLAY_DISPLAY_PRESENT_INFO_KHR          = 1000003000,
-
-    //@extension("VK_KHR_xlib_surface") // 5
-    VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR              = 1000004000,
-
-    //@extension("VK_KHR_xcb_surface") // 6
-    VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR               = 1000005000,
-
-    //@extension("VK_KHR_wayland_surface") // 7
-    VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR           = 1000006000,
-
-    //@extension("VK_KHR_android_surface") // 9
-    VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR           = 1000008000,
-
-    //@extension("VK_KHR_win32_surface") // 10
-    VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR             = 1000009000,
-
-    //@extension("VK_ANDROID_native_buffer") // 11
-    VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID                     = 1000010000,
-    VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID       = 1000010001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID = 1000010002,
-
-    //@extension("VK_EXT_debug_report") // 12
-    VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT     = 1000011000,
-
-    //@extension("VK_AMD_rasterization_order") // 19
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000,
-
-    //@extension("VK_EXT_debug_marker") // 23
-    VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT         = 1000022000,
-    VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT          = 1000022001,
-    VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT              = 1000022002,
-
-    //@extension("VK_NV_dedicated_allocation") // 27
-    VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000,
-    VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
-    VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT       = 1000028000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT     = 1000028001,
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT   = 1000028002,
-
-    //@extension("VK_AMD_texture_gather_bias_lod") // 42
-    VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD  = 1000041000,
-
-    //@extension("VK_NV_corner_sampled_image") // 51
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV  = 1000050000,
-
-    //@extension("VK_KHR_multiview") // 54
-    VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR     = 1000053000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR    = 1000053001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR  = 1000053002,
-
-    //@extension("VK_NV_external_memory") // 57
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV      = 1000056000,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV            = 1000056001,
-
-    //@extension("VK_NV_external_memory_win32") // 58
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV        = 1000057000,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV        = 1000057001,
-
-    //@extension("VK_NV_win32_keyed_mutex") // 59
-    VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
-
-    //@extension("VK_KHR_get_physical_device_properties2") // 60
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR            = 1000059000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR          = 1000059001,
-    VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR                   = 1000059002,
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR             = 1000059003,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR   = 1000059004,
-    VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR             = 1000059005,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR   = 1000059006,
-    VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR      = 1000059007,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008,
-
-    //@extension("VK_KHR_device_group") // 61
-    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR            = 1000060000,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR   = 1000060003,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR = 1000060004,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR              = 1000060005,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR         = 1000060006,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR     = 1000060007,
-    // tokens 08-12 are listed with VK_KHR_swapchain
-    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR  = 1000060013,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR   = 1000060014,
-
-    //@extension("VK_EXT_validation_flags") // 62
-    VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT                      = 1000061000,
-
-    //@extension("VK_NN_vi_surface") // 63
-    VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN                 = 1000062000,
-
-    //@extension("VK_EXT_astc_decode_mode") // 68
-    VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT           = 1000067000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT  = 1000067001,
-
-    //@extension("VK_KHR_device_group_creation") // 71
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR      = 1000070000,
-    VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR       = 1000070001,
-
-    //@extension("VK_KHR_external_memory_capabilities") // 72
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR    = 1000071000,
-    VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR      = 1000071001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR  = 1000071002,
-    VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR            = 1000071003,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR         = 1000071004,
-
-    //@extension("VK_KHR_external_memory") // 73
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR    = 1000072000,
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR     = 1000072001,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR           = 1000072002,
-
-    //@extension("VK_KHR_external_memory_win32") // 74
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR       = 1000073000,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR       = 1000073001,
-    VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR        = 1000073002,
-
-    //@extension("VK_KHR_external_memory_fd") // 75
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR                 = 1000074000,
-    VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR                  = 1000074001,
-
-    //@extension("VK_KHR_win32_keyed_mutex") // 76
-    VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR    = 1000075000,
-
-    //@extension("VK_KHR_external_semaphore_capabilities") // 77
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR   = 1000076000,
-    VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR         = 1000076001,
-
-    //@extension("VK_KHR_external_semaphore") // 78
-    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR          = 1000077000,
-
-    //@extension("VK_KHR_external_semaphore_win32") // 79
-    VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR    = 1000078000,
-    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR    = 1000078001,
-    VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR               = 1000078002,
-
-    //@extension("VK_KHR_external_semaphore_fd") // 80
-    VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR              = 1000079000,
-    VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR                 = 1000079001,
-
-    //@extension("VK_KHR_push_descriptor") // 81
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR    = 1000080000,
-
-    //@extension("VK_KHR_16bit_storage") // 84
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR    = 1000083000,
-
-    //@extension("VK_KHR_incremental_present") // 85
-    VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR                       = 1000084000,
-
-    //@extension("VK_EXT_conditional_rendering") // 82
-    VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT        = 1000081001,
-    VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT                      = 1000081002,
-
-    //@extension("VK_KHR_shader_float16_int8") // 83
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR     = 1000082000,
-
-    //@extension("VK_KHR_descriptor_update_template") // 86
-    VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR    = 1000085000,
-
-    //@extension("VK_NVX_device_generated_commands") // 87
-    VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX              = 1000086000,
-    VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX  = 1000086001,
-    VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX             = 1000086002,
-    VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX   = 1000086003,
-    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX      = 1000086004,
-    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX    = 1000086005,
-
-    //@extension("VK_NV_clip_space_w_scaling") // 88
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV  = 1000087000,
-
-    //@extension("VK_EXT_display_surface_counter") // 91
-    VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT                = 1000090000,
-
-    //@extension("VK_EXT_display_control") // 92
-    VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT                    = 1000091000,
-    VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT                     = 1000091001,
-    VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT                    = 1000091002,
-    VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT         = 1000091003,
-
-    //@extension("VK_GOOGLE_display_timing") // 93
-    VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE                 = 1000092000,
-
-    //@extension("VK_NVX_multiview_per_view_attributes") // 98
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX  = 1000097000,
-
-    //@extension("VK_NV_viewport_swizzle") // 99
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV    = 1000098000,
-
-    //@extension("VK_EXT_discard_rectangles") // 100
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT  = 1000099000,
-    VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT  = 1000099001,
-
-    //@extension("VK_EXT_conservative_rasterization") // 102
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000,
-    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001,
-
-    //@extension("VK_KHR_create_renderpass2") // 110
-    VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR              = 1000109000,
-    VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR                = 1000109001,
-    VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR                 = 1000109002,
-    VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR                  = 1000109003,
-    VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR             = 1000109004,
-    VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR                    = 1000109005,
-    VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR                      = 1000109006,
-
-    //@extension("VK_EXT_hdr_metadata") // 106
-    VK_STRUCTURE_TYPE_HDR_METADATA_EXT                          = 1000105000,
-
-    //@extension("VK_KHR_shared_presentable_image") // 112
-    VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR   = 1000111000,
-
-    //@extension("VK_KHR_external_fence_capabilities") // 113
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR   = 1000112000,
-    VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR             = 1000112001,
-
-    //@extension("VK_KHR_external_fence") // 114
-    VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR              = 1000113000,
-
-    //@extension("VK_KHR_external_fence_win32") // 115
-    VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR        = 1000114000,
-    VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR        = 1000114001,
-    VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR           = 1000114002,
-
-    //@extension("VK_KHR_external_fence_fd") // 117
-    VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR                  = 1000115000,
-    VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR                     = 1000115001,
-
-    //@extension("VK_KHR_maintenance2") // 118
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR             = 1000117000,
-    VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR       = 1000117001,
-    VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR                          = 1000117002,
-    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = 1000117003,
-
-    //@extension("VK_KHR_get_surface_capabilities2") // 120
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR        = 1000119000,
-    VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR                = 1000119001,
-    VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR                      = 1000119002,
-
-    //@extension("VK_KHR_variable_pointers") // 121
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = 1000120000,
-
-    //@extension("VK_KHR_display_properties2") // 122
-    VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR                  = 1000121000,
-    VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR            = 1000121001,
-    VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR             = 1000121002,
-    VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR                  = 1000121003,
-    VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR          = 1000121004,
-
-    //@extension("VK_MVK_ios_surface") // 123
-    VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK               = 1000122000,
-
-    //@extension("VK_MVK_macos_surface") // 124
-    VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK             = 1000123000,
-
-    //@extension("VK_KHR_dedicated_allocation") // 128
-    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR         = 1000127000,
-    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR        = 1000127001,
-
-    //@extension("VK_EXT_debug_utils") // 129
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT          = 1000128000,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT           = 1000128001,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT                     = 1000128002,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT   = 1000128003,
-    VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT     = 1000128004,
-
-    //@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-    VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID             = 1000129000,
-    VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID        = 1000129001,
-    VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID = 1000129002,
-    VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID       = 1000129003,
-    VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID   = 1000129004,
-    VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID                           = 1000129005,
-
-    //@extension("VK_EXT_sampler_filter_minmax") // 131
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
-    VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
-
-    //@extension("VK_EXT_inline_uniform_block") // 139
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT     = 1000138000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT   = 1000138001,
-    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT         = 1000138002,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT  = 1000138003,
-
-    //@extension("VK_EXT_sample_locations") // 144
-    VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT                         = 1000143000,
-    VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT       = 1000143001,
-    VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT   = 1000143002,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT   = 1000143003,
-    VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT                        = 1000143004,
-
-    //@extension("VK_KHR_get_memory_requirements2") // 147
-    VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR         = 1000146000,
-    VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR          = 1000146001,
-    VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR   = 1000146002,
-    VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR                     = 1000146003,
-    VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR        = 1000146004,
-
-    //@extension("VK_KHR_image_format_list") // 148
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR             = 1000147000,
-
-    //@extension("VK_EXT_blend_operation_advanced") // 149
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001,
-    VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002,
-
-    //@extension("VK_NV_fragment_coverage_to_color") // 150
-    VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000,
-
-    //@extension("VK_NV_framebuffer_mixed_samples") // 153
-    VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR              = 1000156000,
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR                     = 1000156001,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR                      = 1000156002,
-    VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR              = 1000156003,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = 1000156004,
-    VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR  = 1000156005,
-
-    //@extension("VK_EXT_image_drm_format_modifier") // 159
-    VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT               = 1000158000,
-    VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT                    = 1000158001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT    = 1000158002,
-    VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT        = 1000158003,
-    VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT    = 1000158004,
-    VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT              = 1000158005,
-
-    //@extension("VK_KHR_bind_memory2") // 158
-    VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR                       = 1000157000,
-    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR                        = 1000157001,
-
-    //@extension("VK_EXT_validation_cache") // 161
-    VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT                  = 1000160000,
-    VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT    = 1000160001,
-
-    //@extension("VK_EXT_descriptor_indexing") // 162
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT           = 1000161000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT              = 1000161001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT            = 1000161002,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT    = 1000161003,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT   = 1000161004,
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002,
-    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV                   = 1000165000,
-    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV                 = 1000165001,
-    VK_STRUCTURE_TYPE_GEOMETRY_NV                                           = 1000165003,
-    VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV                                 = 1000165004,
-    VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV                                      = 1000165005,
-    VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV            = 1000165006,
-    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV        = 1000165007,
-    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV    = 1000165008,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV             = 1000165009,
-    VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV               = 1000165011,
-    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV                        = 1000165012,
-
-    //@extension("VK_NV_representative_fragment_test") // 167
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000,
-    VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001,
-
-    //@extension("VK_KHR_maintenance3") // 169
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR      = 1000168000,
-    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR                 = 1000168001,
-
-    //@extension("VK_EXT_global_priority") // 175
-    VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT      = 1000174000,
-
-    //@extension("VK_KHR_8bit_storage") // 178
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR         = 1000177000,
-
-    //@extension("VK_EXT_external_memory_host") // 179
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT                   = 1000178000,
-    VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT                    = 1000178001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT   = 1000178002,
-
-    //@extension("VK_KHR_shader_atomic_int64") // 181
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR  = 1000180000,
-
-    //@extension("VK_EXT_calibrated_timestamps") // 185
-    VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT                     = 1000184000,
-
-    //@extension("VK_KHR_driver_properties") // 197
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR             = 1000196000,
-
-    //@extension("VK_KHR_shader_float_controls") // 198
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR     = 1000197000,
-
-    //@extension("VK_AMD_shader_core_properties") // 186
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD        = 1000185000,
-
-    //@extension("VK_AMD_memory_overallocation_behavior") // 190
-    VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD      = 1000189000,
-
-    //@extension("VK_EXT_vertex_attribute_divisor") // 191
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT   = 1000190000,
-    VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT       = 1000190001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT     = 1000190002,
-
-    //@extension("VK_NV_device_diagnostic_checkpoints") // 207
-    VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV                        = 1000206000,
-    VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV     = 1000206001,
-
-    //@extension("VK_KHR_vulkan_memory_model") // 212
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
-
-    //@extension("VK_EXT_pci_bus_info") // 213
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT   = 1000212000,
-
-    //@extension("VK_FUCHSIA_imagepipe_surface") // 215
-    VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA     = 1000214000,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT     = 1000218000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT   = 1000218001,
-    VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT      = 1000218002,
-
-    //@extension("VK_EXT_scalar_block_layout")
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT  = 1000221000,
-
-    //@extension("VK_EXT_separate_stencil_usage") // 247
-    VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT       = 1000246000,
-}
-
-enum VkSubpassContents {
-    VK_SUBPASS_CONTENTS_INLINE                              = 0x00000000,
-    VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS           = 0x00000001,
-}
-
-enum VkPipelineCacheHeaderVersion {
-    VK_PIPELINE_CACHE_HEADER_VERSION_ONE                    = 1,
-}
-
-@lastUnused(-11)
-/// Error and return codes
-enum VkResult {
-    // Return codes for successful operation execution (positive values)
-    VK_SUCCESS                                              = 0,
-    VK_NOT_READY                                            = 1,
-    VK_TIMEOUT                                              = 2,
-    VK_EVENT_SET                                            = 3,
-    VK_EVENT_RESET                                          = 4,
-    VK_INCOMPLETE                                           = 5,
-
-    //@extension("VK_KHR_swapchain") // 2
-    VK_SUBOPTIMAL_KHR                                       = 1000001003,
-
-    // Error codes (negative values)
-    VK_ERROR_OUT_OF_HOST_MEMORY                             = 0xFFFFFFFF, // -1
-    VK_ERROR_OUT_OF_DEVICE_MEMORY                           = 0xFFFFFFFE, // -2
-    VK_ERROR_INITIALIZATION_FAILED                          = 0xFFFFFFFD, // -3
-    VK_ERROR_DEVICE_LOST                                    = 0xFFFFFFFC, // -4
-    VK_ERROR_MEMORY_MAP_FAILED                              = 0xFFFFFFFB, // -5
-    VK_ERROR_LAYER_NOT_PRESENT                              = 0xFFFFFFFA, // -6
-    VK_ERROR_EXTENSION_NOT_PRESENT                          = 0xFFFFFFF9, // -7
-    VK_ERROR_FEATURE_NOT_PRESENT                            = 0xFFFFFFF8, // -8
-    VK_ERROR_INCOMPATIBLE_DRIVER                            = 0xFFFFFFF7, // -9
-    VK_ERROR_TOO_MANY_OBJECTS                               = 0xFFFFFFF6, // -10
-    VK_ERROR_FORMAT_NOT_SUPPORTED                           = 0xFFFFFFF5, // -11
-    VK_ERROR_FRAGMENTED_POOL                                = 0xFFFFFFF4, // -12
-
-    //@vulkan1_1
-    VK_ERROR_OUT_OF_POOL_MEMORY                             = 0xC4642878, // -1000069000
-    VK_ERROR_INVALID_EXTERNAL_HANDLE                        = 0xC4641CBD, // -1000072003
-
-    //@extension("VK_KHR_surface") // 1
-    VK_ERROR_SURFACE_LOST_KHR                               = 0xC4653600, // -1000000000
-    VK_ERROR_NATIVE_WINDOW_IN_USE_KHR                       = 0xC46535FF, // -1000000001
-
-    //@extension("VK_KHR_swapchain") // 2
-    VK_ERROR_OUT_OF_DATE_KHR                                = 0xC4653214, // -1000001004
-
-    //@extension("VK_KHR_display_swapchain") // 4
-    VK_ERROR_INCOMPATIBLE_DISPLAY_KHR                       = 0xC4652A47, // -1000003001
-
-    //@extension("VK_EXT_debug_report") // 12
-    VK_ERROR_VALIDATION_FAILED_EXT                          = 0xC4650B07, // -1000011001
-
-    //@extension("VK_NV_glsl_shader") // 13
-    VK_ERROR_INVALID_SHADER_NV                              = 0xC4650720, // -1000012000
-
-    //@extension("VK_KHR_maintenance1") // 70
-    VK_ERROR_OUT_OF_POOL_MEMORY_KHR                         = 0xC4642878, // -1000069000
-
-    //@extension("VK_KHR_external_memory") // 73
-    VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR                    = 0xC4641CBD, // -1000072003
-
-    //@extension("VK_EXT_image_drm_format_modifier") // 159
-    VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT   = 0xC462CCD0, // -1000158000
-
-    //@extension("VK_EXT_descriptor_indexing") // 162
-    VK_ERROR_FRAGMENTATION_EXT                              = 0xc462c118, // -1000161000
-
-    //@extension("VK_EXT_global_priority") // 175
-    VK_ERROR_NOT_PERMITTED_EXT                              = 0xC4628E4F, // -1000174001
-}
-
-enum VkDynamicState {
-    VK_DYNAMIC_STATE_VIEWPORT                               = 0x00000000,
-    VK_DYNAMIC_STATE_SCISSOR                                = 0x00000001,
-    VK_DYNAMIC_STATE_LINE_WIDTH                             = 0x00000002,
-    VK_DYNAMIC_STATE_DEPTH_BIAS                             = 0x00000003,
-    VK_DYNAMIC_STATE_BLEND_CONSTANTS                        = 0x00000004,
-    VK_DYNAMIC_STATE_DEPTH_BOUNDS                           = 0x00000005,
-    VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK                   = 0x00000006,
-    VK_DYNAMIC_STATE_STENCIL_WRITE_MASK                     = 0x00000007,
-    VK_DYNAMIC_STATE_STENCIL_REFERENCE                      = 0x00000008,
-
-    //@extension("VK_NV_clip_space_w_scaling") // 88
-    VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV                  = 1000087000,
-
-    //@extension("VK_EXT_discard_rectangles") // 100
-    VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT                  = 1000099000,
-
-    //@extension("VK_EXT_sample_locations") // 144
-    VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT                   = 1000143000,
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV       = 1000164004,
-    VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV        = 1000164006,
-
-    //@extension("VK_NV_scissor_exclusive") // 206
-    VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV                   = 1000205001,
-}
-
-enum VkObjectType {
-    VK_OBJECT_TYPE_UNKNOWN                                  = 0,
-    VK_OBJECT_TYPE_INSTANCE                                 = 1,
-    VK_OBJECT_TYPE_PHYSICAL_DEVICE                          = 2,
-    VK_OBJECT_TYPE_DEVICE                                   = 3,
-    VK_OBJECT_TYPE_QUEUE                                    = 4,
-    VK_OBJECT_TYPE_SEMAPHORE                                = 5,
-    VK_OBJECT_TYPE_COMMAND_BUFFER                           = 6,
-    VK_OBJECT_TYPE_FENCE                                    = 7,
-    VK_OBJECT_TYPE_DEVICE_MEMORY                            = 8,
-    VK_OBJECT_TYPE_BUFFER                                   = 9,
-    VK_OBJECT_TYPE_IMAGE                                    = 10,
-    VK_OBJECT_TYPE_EVENT                                    = 11,
-    VK_OBJECT_TYPE_QUERY_POOL                               = 12,
-    VK_OBJECT_TYPE_BUFFER_VIEW                              = 13,
-    VK_OBJECT_TYPE_IMAGE_VIEW                               = 14,
-    VK_OBJECT_TYPE_SHADER_MODULE                            = 15,
-    VK_OBJECT_TYPE_PIPELINE_CACHE                           = 16,
-    VK_OBJECT_TYPE_PIPELINE_LAYOUT                          = 17,
-    VK_OBJECT_TYPE_RENDER_PASS                              = 18,
-    VK_OBJECT_TYPE_PIPELINE                                 = 19,
-    VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT                    = 20,
-    VK_OBJECT_TYPE_SAMPLER                                  = 21,
-    VK_OBJECT_TYPE_DESCRIPTOR_POOL                          = 22,
-    VK_OBJECT_TYPE_DESCRIPTOR_SET                           = 23,
-    VK_OBJECT_TYPE_FRAMEBUFFER                              = 24,
-    VK_OBJECT_TYPE_COMMAND_POOL                             = 25,
-
-    //@vulkan1_1
-    VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION                 = 1000156000,
-    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE               = 1000085000,
-
-    //@extension("VK_KHR_surface") // 1
-    VK_OBJECT_TYPE_SURFACE_KHR                              = 1000000000,
-
-    //@extension("VK_KHR_swapchain") // 2
-    VK_OBJECT_TYPE_SWAPCHAIN_KHR                            = 1000001000,
-
-    //@extension("VK_KHR_display") // 3
-    VK_OBJECT_TYPE_DISPLAY_KHR                              = 1000002000,
-    VK_OBJECT_TYPE_DISPLAY_MODE_KHR                         = 1000002001,
-
-    //@extension("VK_KHR_debug_report") // 12
-    VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT                = 1000011000,
-
-    //@extension("VK_KHR_descriptor_update_template") // 86
-    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR           = 1000085000,
-
-    //@extension("VK_NVX_device_generated_commands") // 87
-    VK_OBJECT_TYPE_OBJECT_TABLE_NVX                         = 1000086000,
-    VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX             = 1000086001,
-
-    //@extension("VK_EXT_debug_utils") // 129
-    VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT                = 1000128000,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR             = 1000156000,
-
-    //@extension("VK_EXT_validation_cache") // 161
-    VK_OBJECT_TYPE_VALIDATION_CACHE_EXT                     = 1000160000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV                = 1000165000,
-}
-
-
-//@vulkan1_1 enums
-
-enum VkPointClippingBehavior {
-    VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES              = 0,
-    VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY        = 1,
-}
-
-enum VkTessellationDomainOrigin {
-    VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT                = 0,
-    VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT                = 1,
-}
-
-enum VkSamplerYcbcrModelConversion {
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY          = 0,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY        = 1,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709             = 2,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601             = 3,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020            = 4,
-}
-
-enum VkSamplerYcbcrRange {
-    VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0,
-    VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1,
-}
-
-enum VkChromaLocation {
-    VK_CHROMA_LOCATION_COSITED_EVEN = 0,
-    VK_CHROMA_LOCATION_MIDPOINT = 1,
-}
-
-enum VkDescriptorUpdateTemplateType {
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0,
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
-}
-
-enum VkVendorId {
-    VK_VENDOR_ID_VIV                                        = 0x10001,
-    VK_VENDOR_ID_VSI                                        = 0x10002,
-    VK_VENDOR_ID_KAZAN                                      = 0x10003,
-}
-
-@extension("VK_KHR_surface") // 1
-enum VkPresentModeKHR {
-    VK_PRESENT_MODE_IMMEDIATE_KHR                           = 0x00000000,
-    VK_PRESENT_MODE_MAILBOX_KHR                             = 0x00000001,
-    VK_PRESENT_MODE_FIFO_KHR                                = 0x00000002,
-    VK_PRESENT_MODE_FIFO_RELAXED_KHR                        = 0x00000003,
-
-    //@extension("VK_KHR_shared_presentable_image") // 112
-    VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR               = 1000111000,
-    VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR           = 1000111001,
-}
-
-@extension("VK_KHR_surface") // 1
-enum VkColorSpaceKHR {
-    VK_COLOR_SPACE_SRGB_NONLINEAR_KHR                       = 0x00000000,
-
-    //@extension("VK_EXT_swapchain_colorspace") // 105
-    VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT                 = 1000104001,
-    VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT                 = 1000104002,
-    VK_COLOR_SPACE_DCI_P3_LINEAR_EXT                        = 1000104003,
-    VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT                     = 1000104004,
-    VK_COLOR_SPACE_BT709_LINEAR_EXT                         = 1000104005,
-    VK_COLOR_SPACE_BT709_NONLINEAR_EXT                      = 1000104006,
-    VK_COLOR_SPACE_BT2020_LINEAR_EXT                        = 1000104007,
-    VK_COLOR_SPACE_HDR10_ST2084_EXT                         = 1000104008,
-    VK_COLOR_SPACE_DOLBYVISION_EXT                          = 1000104009,
-    VK_COLOR_SPACE_HDR10_HLG_EXT                            = 1000104010,
-    VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT                      = 1000104011,
-    VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT                   = 1000104012,
-    VK_COLOR_SPACE_PASS_THROUGH_EXT                         = 1000104013,
-    VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT              = 1000104014,
-}
-
-@extension("VK_EXT_debug_report") // 12
-enum VkDebugReportObjectTypeEXT {
-    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT                 = 0,
-    VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT                = 1,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT         = 2,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT                  = 3,
-    VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT                   = 4,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT               = 5,
-    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT          = 6,
-    VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT                   = 7,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT           = 8,
-    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT                  = 9,
-    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT                   = 10,
-    VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT                   = 11,
-    VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT              = 12,
-    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT             = 13,
-    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT              = 14,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT           = 15,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT          = 16,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT         = 17,
-    VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT             = 18,
-    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT                = 19,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT   = 20,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT                 = 21,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT         = 22,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT          = 23,
-    VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT             = 24,
-    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT            = 25,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT             = 26,
-    VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT           = 27,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT             = 29,
-    VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT        = 30,
-    VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT        = 31,
-    VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
-
-    //extension("VK_EXT_validation_cache") // 161
-    VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT    = 33,
-
-    //extension("VK_KHR_descriptor_update_template") // 86
-    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = 1000156000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT   = 1000165000,
-}
-
-@extension("VK_AMD_rasterization_order") // 19
-enum VkRasterizationOrderAMD {
-    VK_RASTERIZATION_ORDER_STRICT_AMD                       = 0,
-    VK_RASTERIZATION_ORDER_RELAXED_AMD                      = 1,
-}
-
-@extension("VK_AMD_shader_info") // 43
-enum VkShaderInfoTypeAMD {
-    VK_SHADER_INFO_TYPE_STATISTICS_AMD                      = 0,
-    VK_SHADER_INFO_TYPE_BINARY_AMD                          = 1,
-    VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD                     = 2,
-}
-
-@extension("VK_EXT_validation_flags") // 62
-enum VkValidationCheckEXT {
-    VK_VALIDATION_CHECK_ALL_EXT                             = 0,
-    VK_VALIDATION_CHECK_SHADERS_EXT                         = 1,
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-enum VkDescriptorUpdateTemplateTypeKHR {
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR   = 0,
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-enum VkIndirectCommandsTokenTypeNVX {
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX            = 0,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX      = 1,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX        = 2,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX       = 3,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX       = 4,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX        = 5,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX                = 6,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX            = 7,
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-enum VkObjectEntryTypeNVX {
-    VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX                 = 0,
-    VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX                       = 1,
-    VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX                   = 2,
-    VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX                  = 3,
-    VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX                  = 4,
-}
-
-@extension("VK_EXT_display_control") // 92
-enum VkDisplayPowerStateEXT {
-    VK_DISPLAY_POWER_STATE_OFF_EXT                          = 0,
-    VK_DISPLAY_POWER_STATE_SUSPEND_EXT                      = 1,
-    VK_DISPLAY_POWER_STATE_ON_EXT                           = 2,
-}
-
-@extension("VK_EXT_display_control") // 92
-enum VkDeviceEventTypeEXT {
-    VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT                = 0,
-}
-
-@extension("VK_EXT_display_control") // 92
-enum VkDisplayEventTypeEXT {
-    VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT               = 0,
-}
-
-@extension("VK_NV_viewport_swizzle") // 99
-enum VkViewportCoordinateSwizzleNV {
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV            = 0,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV            = 1,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV            = 2,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV            = 3,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV            = 4,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV            = 5,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV            = 6,
-    VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV            = 7,
-}
-
-@extension("VK_EXT_discard_rectangles") // 100
-enum VkDiscardRectangleModeEXT {
-    VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0,
-    VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1,
-}
-
-@extension("VK_EXT_conservative_rasterization") // 102
-enum VkConservativeRasterizationModeEXT {
-    VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT         = 0,
-    VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT     = 1,
-    VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT    = 2,
-}
-
-@extension("VK_KHR_maintenance2") // 118
-enum VkPointClippingBehaviorKHR {
-    VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR          = 0,
-    VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR    = 1,
-}
-
-@extension("VK_KHR_maintenance2") // 118
-enum VkTessellationDomainOriginKHR {
-    VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR            = 0,
-    VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR            = 1,
-}
-
-@extension("VK_EXT_sampler_filter_minmax") // 131
-enum VkSamplerReductionModeEXT {
-    VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT          = 0,
-    VK_SAMPLER_REDUCTION_MODE_MIN_EXT                       = 1,
-    VK_SAMPLER_REDUCTION_MODE_MAX_EXT                       = 2,
-}
-
-@extension("VK_EXT_blend_operation_advanced") // 149
-enum VkBlendOverlapEXT {
-    VK_BLEND_OVERLAP_UNCORRELATED_EXT                       = 0,
-    VK_BLEND_OVERLAP_DISJOINT_EXT                           = 1,
-    VK_BLEND_OVERLAP_CONJOINT_EXT                           = 2,
-}
-
-@extension("VK_NV_framebuffer_mixed_samples") // 153
-enum VkCoverageModulationModeNV {
-    VK_COVERAGE_MODULATION_MODE_NONE_NV                     = 0,
-    VK_COVERAGE_MODULATION_MODE_RGB_NV                      = 1,
-    VK_COVERAGE_MODULATION_MODE_ALPHA_NV                    = 2,
-    VK_COVERAGE_MODULATION_MODE_RGBA_NV                     = 3,
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-enum VkSamplerYcbcrModelConversionKHR {
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR      = 0,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR    = 1,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR         = 2,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR         = 3,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR        = 4,
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-enum VkSamplerYcbcrRangeKHR {
-    VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR                     = 0,
-    VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR                   = 1,
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-enum VkChromaLocationKHR {
-    VK_CHROMA_LOCATION_COSITED_EVEN_KHR                     = 0,
-    VK_CHROMA_LOCATION_MIDPOINT_KHR                         = 1,
-}
-
-@extension("VK_EXT_validation_cache") // 161
-enum VkValidationCacheHeaderVersionEXT {
-    VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT              = 1,
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-enum VkShadingRatePaletteEntryNV {
-    VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV                 = 0,
-    VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV       = 1,
-    VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV        = 2,
-    VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV        = 3,
-    VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV        = 4,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV         = 5,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV    = 6,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV    = 7,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV    = 8,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV    = 9,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV    = 10,
-    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV    = 11,
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-enum VkCoarseSampleOrderTypeNV {
-    VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV                  = 0,
-    VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV                   = 1,
-    VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV              = 2,
-    VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV             = 3,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-enum VkRayTracingShaderGroupTypeNV {
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV                 = 0,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV     = 1,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV    = 2,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-enum VkGeometryTypeNV {
-    VK_GEOMETRY_TYPE_TRIANGLES_NV                           = 0,
-    VK_GEOMETRY_TYPE_AABBS_NV                               = 1,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-enum VkAccelerationStructureTypeNV {
-    VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV             = 0,
-    VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV          = 1,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-enum VkCopyAccelerationStructureModeNV {
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV            = 0,
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV          = 1,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-enum VkAccelerationStructureMemoryRequirementsTypeNV {
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV            = 0,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV     = 1,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV    = 2,
-}
-
-@extension("VK_EXT_global_priority") // 175
-enum VkQueueGlobalPriorityEXT {
-    VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT                        = 128,
-    VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT                     = 256,
-    VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT                       = 512,
-    VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT                   = 1024,
-}
-
-@extension("VK_EXT_calibrated_timestamps") // 185
-enum VkTimeDomainEXT {
-    VK_TIME_DOMAIN_DEVICE_EXT                               = 0,
-    VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT                      = 1,
-    VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT                  = 2,
-    VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT            = 3,
-}
-
-@extension("VK_AMD_memory_overallocation_behavior") // 190
-enum VkMemoryOverallocationBehaviorAMD {
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD           = 0,
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD           = 1,
-    VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD        = 2,
-}
-
-@extension("VK_KHR_driver_properties") // 197
-enum VkDriverIdKHR {
-    VK_DRIVER_ID_AMD_PROPRIETARY_KHR                        = 1,
-    VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR                        = 2,
-    VK_DRIVER_ID_MESA_RADV_KHR                              = 3,
-    VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR                     = 4,
-    VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR              = 5,
-    VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR                 = 6,
-    VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR                = 7,
-    VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR                   = 8,
-    VK_DRIVER_ID_ARM_PROPRIETARY_KHR                        = 9,
-    VK_DRIVER_ID_GOOGLE_PASTEL_KHR                          = 10,
-}
-
-/////////////////
-//  Bitfields  //
-/////////////////
-
-/// Queue capabilities
-type VkFlags VkQueueFlags
-bitfield VkQueueFlagBits {
-    VK_QUEUE_GRAPHICS_BIT                                   = 0x00000001,    /// Queue supports graphics operations
-    VK_QUEUE_COMPUTE_BIT                                    = 0x00000002,    /// Queue supports compute operations
-    VK_QUEUE_TRANSFER_BIT                                   = 0x00000004,    /// Queue supports transfer operations
-    VK_QUEUE_SPARSE_BINDING_BIT                             = 0x00000008,    /// Queue supports sparse resource memory management operations
-
-    //@vulkan1_1
-    VK_QUEUE_PROTECTED_BIT                                  = 0x00000010,
-}
-
-/// Memory properties passed into vkAllocMemory().
-type VkFlags VkMemoryPropertyFlags
-bitfield VkMemoryPropertyFlagBits {
-    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT                     = 0x00000001,
-    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT                     = 0x00000002,
-    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT                    = 0x00000004,
-    VK_MEMORY_PROPERTY_HOST_CACHED_BIT                      = 0x00000008,
-    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT                 = 0x00000010,
-
-    //@vulkan1_1
-    VK_MEMORY_PROPERTY_PROTECTED_BIT                        = 0x00000020,
-}
-
-/// Memory heap flags
-type VkFlags VkMemoryHeapFlags
-bitfield VkMemoryHeapFlagBits {
-    VK_MEMORY_HEAP_DEVICE_LOCAL_BIT                         = 0x00000001,
-
-    //@vulkan1_1
-    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT                       = 0x00000002,
-
-    //@extension("VK_KHR_device_group_creation") // 71
-    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR                   = 0x00000002,
-}
-
-/// Access flags
-type VkFlags VkAccessFlags
-bitfield VkAccessFlagBits {
-    VK_ACCESS_INDIRECT_COMMAND_READ_BIT                     = 0x00000001,
-    VK_ACCESS_INDEX_READ_BIT                                = 0x00000002,
-    VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT                     = 0x00000004,
-    VK_ACCESS_UNIFORM_READ_BIT                              = 0x00000008,
-    VK_ACCESS_INPUT_ATTACHMENT_READ_BIT                     = 0x00000010,
-    VK_ACCESS_SHADER_READ_BIT                               = 0x00000020,
-    VK_ACCESS_SHADER_WRITE_BIT                              = 0x00000040,
-    VK_ACCESS_COLOR_ATTACHMENT_READ_BIT                     = 0x00000080,
-    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT                    = 0x00000100,
-    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT             = 0x00000200,
-    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT            = 0x00000400,
-    VK_ACCESS_TRANSFER_READ_BIT                             = 0x00000800,
-    VK_ACCESS_TRANSFER_WRITE_BIT                            = 0x00001000,
-    VK_ACCESS_HOST_READ_BIT                                 = 0x00002000,
-    VK_ACCESS_HOST_WRITE_BIT                                = 0x00004000,
-    VK_ACCESS_MEMORY_READ_BIT                               = 0x00008000,
-    VK_ACCESS_MEMORY_WRITE_BIT                              = 0x00010000,
-
-    //@extension("VK_NVX_device_generated_commands") // 87
-    VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX                  = 0x00020000,
-    VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX                 = 0x00040000,
-
-    //@extension("VK_EXT_blend_operation_advanced") // 149
-    VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT     = 0x00080000,
-
-    //@extension("VK_EXT_conditional_rendering") // 82
-    VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT            = 0x00100000,
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV                = 0x00800000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV            = 0x00200000,
-    VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV           = 0x00400000,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT             = 0x01000000,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT              = 0x02000000,
-    VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT       = 0x04000000,
-    VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT      = 0x08000000,
-}
-
-/// Buffer usage flags
-type VkFlags VkBufferUsageFlags
-bitfield VkBufferUsageFlagBits {
-    VK_BUFFER_USAGE_TRANSFER_SRC_BIT                        = 0x00000001,    /// Can be used as a source of transfer operations
-    VK_BUFFER_USAGE_TRANSFER_DST_BIT                        = 0x00000002,    /// Can be used as a destination of transfer operations
-    VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT                = 0x00000004,    /// Can be used as TBO
-    VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT                = 0x00000008,    /// Can be used as IBO
-    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT                      = 0x00000010,    /// Can be used as UBO
-    VK_BUFFER_USAGE_STORAGE_BUFFER_BIT                      = 0x00000020,    /// Can be used as SSBO
-    VK_BUFFER_USAGE_INDEX_BUFFER_BIT                        = 0x00000040,    /// Can be used as source of fixed function index fetch (index buffer)
-    VK_BUFFER_USAGE_VERTEX_BUFFER_BIT                       = 0x00000080,    /// Can be used as source of fixed function vertex fetch (VBO)
-    VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT                     = 0x00000100,    /// Can be the source of indirect parameters (e.g. indirect buffer, parameter buffer)
-
-    //@extension("VK_EXT_conditional_rendering") // 82
-    VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT           = 0x00000200,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_BUFFER_USAGE_RAY_TRACING_BIT_NV                      = 0x00000400,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT           = 0x00000800,
-    VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT   = 0x00001000,
-}
-
-/// Buffer creation flags
-type VkFlags VkBufferCreateFlags
-bitfield VkBufferCreateFlagBits {
-    VK_BUFFER_CREATE_SPARSE_BINDING_BIT                     = 0x00000001,    /// Buffer should support sparse backing
-    VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT                   = 0x00000002,    /// Buffer should support sparse backing with partial residency
-    VK_BUFFER_CREATE_SPARSE_ALIASED_BIT                     = 0x00000004,    /// Buffer should support constent data access to physical memory blocks mapped into multiple locations of sparse buffers
-
-    //@vulkan1_1
-    VK_BUFFER_CREATE_PROTECTED_BIT                          = 0x00000008,
-}
-
-/// Shader stage flags
-type VkFlags VkShaderStageFlags
-bitfield VkShaderStageFlagBits {
-    VK_SHADER_STAGE_VERTEX_BIT                              = 0x00000001,
-    VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT                = 0x00000002,
-    VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT             = 0x00000004,
-    VK_SHADER_STAGE_GEOMETRY_BIT                            = 0x00000008,
-    VK_SHADER_STAGE_FRAGMENT_BIT                            = 0x00000010,
-    VK_SHADER_STAGE_COMPUTE_BIT                             = 0x00000020,
-    VK_SHADER_STAGE_ALL_GRAPHICS                            = 0x0000001F,
-
-    VK_SHADER_STAGE_ALL                                     = 0x7FFFFFFF,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_SHADER_STAGE_RAYGEN_BIT_NV                           = 0x00000100,
-    VK_SHADER_STAGE_ANY_HIT_BIT_NV                          = 0x00000200,
-    VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV                      = 0x00000400,
-    VK_SHADER_STAGE_MISS_BIT_NV                             = 0x00000800,
-    VK_SHADER_STAGE_INTERSECTION_BIT_NV                     = 0x00001000,
-    VK_SHADER_STAGE_CALLABLE_BIT_NV                         = 0x00002000,
-
-    //@extension("VK_NV_mesh_shader") // 203
-    VK_SHADER_STAGE_TASK_BIT_NV                             = 0x00000040,
-    VK_SHADER_STAGE_MESH_BIT_NV                             = 0x00000080,
-}
-
-/// Descriptor pool create flags
-type VkFlags VkDescriptorPoolCreateFlags
-bitfield VkDescriptorPoolCreateFlagBits {
-    VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT       = 0x00000001,
-
-    //@extension("VK_EXT_descriptor_indexing") // 162
-    VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT     = 0x00000002,
-}
-
-/// Descriptor pool reset flags
-type VkFlags VkDescriptorPoolResetFlags
-//bitfield VkDescriptorPoolResetFlagBits {
-//}
-
-/// Image usage flags
-type VkFlags VkImageUsageFlags
-bitfield VkImageUsageFlagBits {
-    VK_IMAGE_USAGE_TRANSFER_SRC_BIT                         = 0x00000001,    /// Can be used as a source of transfer operations
-    VK_IMAGE_USAGE_TRANSFER_DST_BIT                         = 0x00000002,    /// Can be used as a destination of transfer operations
-    VK_IMAGE_USAGE_SAMPLED_BIT                              = 0x00000004,    /// Can be sampled from (SAMPLED_IMAGE and COMBINED_IMAGE_SAMPLER descriptor types)
-    VK_IMAGE_USAGE_STORAGE_BIT                              = 0x00000008,    /// Can be used as storage image (STORAGE_IMAGE descriptor type)
-    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT                     = 0x00000010,    /// Can be used as framebuffer color attachment
-    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT             = 0x00000020,    /// Can be used as framebuffer depth/stencil attachment
-    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT                 = 0x00000040,    /// Image data not needed outside of rendering
-    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT                     = 0x00000080,    /// Can be used as framebuffer input attachment
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV                = 0x00000100,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT             = 0x00000200,
-}
-
-/// Image creation flags
-type VkFlags VkImageCreateFlags
-bitfield VkImageCreateFlagBits {
-    VK_IMAGE_CREATE_SPARSE_BINDING_BIT                      = 0x00000001,    /// Image should support sparse backing
-    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT                    = 0x00000002,    /// Image should support sparse backing with partial residency
-    VK_IMAGE_CREATE_SPARSE_ALIASED_BIT                      = 0x00000004,    /// Image should support constent data access to physical memory blocks mapped into multiple locations of sparse images
-    VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT                      = 0x00000008,    /// Allows image views to have different format than the base image
-    VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT                     = 0x00000010,    /// Allows creating image views with cube type from the created image
-
-    //@vulkan1_1
-    VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT                 = 0x00000020,
-    VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT         = 0x00000040,
-    VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT         = 0x00000080,
-    VK_IMAGE_CREATE_EXTENDED_USAGE_BIT                      = 0x00000100,
-    VK_IMAGE_CREATE_DISJOINT_BIT                            = 0x00000200,
-    VK_IMAGE_CREATE_ALIAS_BIT                               = 0x00000400,
-    VK_IMAGE_CREATE_PROTECTED_BIT                           = 0x00000800,
-
-    //@extension("VK_KHR_maintenance1") // 70
-    VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR             = 0x00000020,
-
-    //@extension("VK_KHR_device_group") // 61
-    VK_IMAGE_CREATE_BIND_SFR_BIT_KHR                        = 0x00000040,
-
-    //@extension("VK_KHR_maintenance2") // 118
-    VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR     = 0x00000080,
-    VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR                  = 0x00000100,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    VK_IMAGE_CREATE_DISJOINT_BIT_KHR                        = 0x00000200,
-
-    //@extension("VK_KHR_bind_memory2") // 158
-    VK_IMAGE_CREATE_ALIAS_BIT_KHR                           = 0x00000400,
-
-    //@extension("VK_EXT_sample_locations") // 144
-    VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
-
-    //@extension("VK_NV_corner_sampled_image") // 51
-    VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV                   = 0x00002000,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT                      = 0x00004000,
-}
-
-/// Image view creation flags
-type VkFlags VkImageViewCreateFlags
-bitfield VkImageViewCreateFlagBits {
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT   = 0x00000001,
-}
-
-/// Pipeline creation flags
-type VkFlags VkPipelineCreateFlags
-bitfield VkPipelineCreateFlagBits {
-    VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT             = 0x00000001,
-    VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT                = 0x00000002,
-    VK_PIPELINE_CREATE_DERIVATIVE_BIT                       = 0x00000004,
-
-    //@vulkan1_1
-    VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT     = 0x00000008,
-    VK_PIPELINE_CREATE_DISPATCH_BASE                        = 0x00000010,
-
-    //@extension("VK_KHR_device_group") // 61
-    VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = 0x00000008,
-    VK_PIPELINE_CREATE_DISPATCH_BASE_KHR                    = 0x00000010,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV                 = 0x00000020,
-}
-
-/// Color component flags
-type VkFlags VkColorComponentFlags
-bitfield VkColorComponentFlagBits {
-    VK_COLOR_COMPONENT_R_BIT                                = 0x00000001,
-    VK_COLOR_COMPONENT_G_BIT                                = 0x00000002,
-    VK_COLOR_COMPONENT_B_BIT                                = 0x00000004,
-    VK_COLOR_COMPONENT_A_BIT                                = 0x00000008,
-}
-
-/// Fence creation flags
-type VkFlags VkFenceCreateFlags
-bitfield VkFenceCreateFlagBits {
-    VK_FENCE_CREATE_SIGNALED_BIT                            = 0x00000001,
-}
-
-/// Semaphore creation flags
-type VkFlags VkSemaphoreCreateFlags
-//bitfield VkSemaphoreCreateFlagBits {
-//}
-
-/// Format capability flags
-type VkFlags VkFormatFeatureFlags
-bitfield VkFormatFeatureFlagBits {
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT                     = 0x00000001,    /// Format can be used for sampled images (SAMPLED_IMAGE and COMBINED_IMAGE_SAMPLER descriptor types)
-    VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT                     = 0x00000002,    /// Format can be used for storage images (STORAGE_IMAGE descriptor type)
-    VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT              = 0x00000004,    /// Format supports atomic operations in case it's used for storage images
-    VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT              = 0x00000008,    /// Format can be used for uniform texel buffers (TBOs)
-    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT              = 0x00000010,    /// Format can be used for storage texel buffers (IBOs)
-    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT       = 0x00000020,    /// Format supports atomic operations in case it's used for storage texel buffers
-    VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT                     = 0x00000040,    /// Format can be used for vertex buffers (VBOs)
-    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT                  = 0x00000080,    /// Format can be used for color attachment images
-    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT            = 0x00000100,    /// Format supports blending in case it's used for color attachment images
-    VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT          = 0x00000200,    /// Format can be used for depth/stencil attachment images
-    VK_FORMAT_FEATURE_BLIT_SRC_BIT                          = 0x00000400,    /// Format can be used as the source image of blits with vkCommandBlitImage
-    VK_FORMAT_FEATURE_BLIT_DST_BIT                          = 0x00000800,    /// Format can be used as the destination image of blits with vkCommandBlitImage
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT       = 0x00001000,
-
-    //@vulkan1_1
-    VK_FORMAT_FEATURE_TRANSFER_SRC_BIT                      = 0x00004000,
-    VK_FORMAT_FEATURE_TRANSFER_DST_BIT                      = 0x00008000,
-    VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT                                                   = 0x00020000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT                              = 0x00040000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT             = 0x00080000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT             = 0x00100000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT   = 0x00200000,
-    VK_FORMAT_FEATURE_DISJOINT_BIT                                                                  = 0x00400000,
-    VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT                                                    = 0x00800000,
-
-    //@extension("VK_IMG_filter_cubic") // 16
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG    = 0x00002000,
-
-    //@extension("VK_KHR_maintenance1") // 70
-    VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR                  = 0x00004000,
-    VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR                  = 0x00008000,
-
-    //@extension("VK_EXT_sampler_filter_minmax") // 131
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT   = 0x00010000,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR                                                   = 0x00020000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR                              = 0x00040000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR             = 0x00080000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR             = 0x00100000,
-    VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR   = 0x00200000,
-    VK_FORMAT_FEATURE_DISJOINT_BIT_KHR                                                                  = 0x00400000,
-    VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR                                                    = 0x00800000,
-}
-
-/// Query control flags
-type VkFlags VkQueryControlFlags
-bitfield VkQueryControlFlagBits {
-    VK_QUERY_CONTROL_PRECISE_BIT                            = 0x00000001,
-}
-
-/// Query result flags
-type VkFlags VkQueryResultFlags
-bitfield VkQueryResultFlagBits {
-    VK_QUERY_RESULT_64_BIT                                  = 0x00000001,   /// Results of the queries are written to the destination buffer as 64-bit values
-    VK_QUERY_RESULT_WAIT_BIT                                = 0x00000002,   /// Results of the queries are waited on before proceeding with the result copy
-    VK_QUERY_RESULT_WITH_AVAILABILITY_BIT                   = 0x00000004,   /// Besides the results of the query, the availability of the results is also written
-    VK_QUERY_RESULT_PARTIAL_BIT                             = 0x00000008,   /// Copy the partial results of the query even if the final results aren't available
-}
-
-/// Shader module creation flags
-type VkFlags VkShaderModuleCreateFlags
-//bitfield VkShaderModuleCreateFlagBits {
-//}
-
-/// Event creation flags
-type VkFlags VkEventCreateFlags
-//bitfield VkEventCreateFlagBits {
-//}
-
-/// Command buffer usage flags
-type VkFlags VkCommandBufferUsageFlags
-bitfield VkCommandBufferUsageFlagBits {
-    VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT             = 0x00000001,
-    VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT        = 0x00000002,
-    VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT            = 0x00000004,
-}
-
-/// Pipeline statistics flags
-type VkFlags VkQueryPipelineStatisticFlags
-bitfield VkQueryPipelineStatisticFlagBits {
-    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT                     = 0x00000001,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT                   = 0x00000002,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT                   = 0x00000004,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT                 = 0x00000008,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT                  = 0x00000010,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT                        = 0x00000020,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT                         = 0x00000040,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT                 = 0x00000080,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT         = 0x00000100,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT  = 0x00000200,  /// Optional
-    VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT                  = 0x00000400,  /// Optional
-}
-
-/// Memory mapping flags
-type VkFlags VkMemoryMapFlags
-//bitfield VkMemoryMapFlagBits {
-//}
-
-/// Bitfield of image aspects
-type VkFlags VkImageAspectFlags
-bitfield VkImageAspectFlagBits {
-    VK_IMAGE_ASPECT_COLOR_BIT                               = 0x00000001,
-    VK_IMAGE_ASPECT_DEPTH_BIT                               = 0x00000002,
-    VK_IMAGE_ASPECT_STENCIL_BIT                             = 0x00000004,
-    VK_IMAGE_ASPECT_METADATA_BIT                            = 0x00000008,
-
-    //@vulkan1_1
-    VK_IMAGE_ASPECT_PLANE_0_BIT                             = 0x00000010,
-    VK_IMAGE_ASPECT_PLANE_1_BIT                             = 0x00000020,
-    VK_IMAGE_ASPECT_PLANE_2_BIT                             = 0x00000040,
-
-    //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-    VK_IMAGE_ASPECT_PLANE_0_BIT_KHR                         = 0x00000010,
-    VK_IMAGE_ASPECT_PLANE_1_BIT_KHR                         = 0x00000020,
-    VK_IMAGE_ASPECT_PLANE_2_BIT_KHR                         = 0x00000040,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT                  = 0x00000080,
-    VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT                  = 0x00000100,
-    VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT                  = 0x00000200,
-    VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT                  = 0x00000400,
-}
-
-/// Sparse memory bind flags
-type VkFlags VkSparseMemoryBindFlags
-bitfield VkSparseMemoryBindFlagBits {
-    VK_SPARSE_MEMORY_BIND_METADATA_BIT                      = 0x00000001,
-}
-
-/// Sparse image memory requirements flags
-type VkFlags VkSparseImageFormatFlags
-bitfield VkSparseImageFormatFlagBits {
-    VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT                  = 0x00000001,  /// Image uses a single miptail region for all array slices
-    VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT                = 0x00000002,  /// Image requires mip levels to be an exact multiple of the sparse iamge block size for non-mip-tail levels.
-    VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT          = 0x00000004,  /// Image uses a non-standard sparse block size
-}
-
-/// Pipeline stages
-type VkFlags VkPipelineStageFlags
-bitfield VkPipelineStageFlagBits {
-    VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT                       = 0x00000001,  /// Before subsequent commands are processed
-    VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT                     = 0x00000002,  /// Draw/DispatchIndirect command fetch
-    VK_PIPELINE_STAGE_VERTEX_INPUT_BIT                      = 0x00000004,  /// Vertex/index fetch
-    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT                     = 0x00000008,  /// Vertex shading
-    VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT       = 0x00000010,  /// Tessellation control shading
-    VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT    = 0x00000020,  /// Tessellation evaluation shading
-    VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT                   = 0x00000040,  /// Geometry shading
-    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT                   = 0x00000080,  /// Fragment shading
-    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT              = 0x00000100,  /// Early fragment (depth/stencil) tests
-    VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT               = 0x00000200,  /// Late fragment (depth/stencil) tests
-    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT           = 0x00000400,  /// Color attachment writes
-    VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT                    = 0x00000800,  /// Compute shading
-    VK_PIPELINE_STAGE_TRANSFER_BIT                          = 0x00001000,  /// Transfer/copy operations
-    VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT                    = 0x00002000,
-    VK_PIPELINE_STAGE_HOST_BIT                              = 0x00004000,  /// Indicates host (CPU) is a source/sink of the dependency
-
-    VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT                      = 0x00008000,  /// All stages of the graphics pipeline
-    VK_PIPELINE_STAGE_ALL_COMMANDS_BIT                      = 0x00010000,  /// All graphics, compute, copy, and transition commands
-
-    //@extension("VK_NVX_device_generated_commands") // 87
-    VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX               = 0x00020000,
-
-    //@extension("VK_EXT_conditional_rendering") // 82
-    VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT         = 0x00040000,
-
-    //@extension("VK_NV_mesh_shader") // 203
-    VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV                    = 0x00080000,
-    VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV                    = 0x00100000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_PIPELINE_STAGE_RAY_TRACING_BIT_NV                    = 0x00200000,
-
-    //@extension("VK_NV_shading_rate_image") // 165
-    VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV             = 0x00400000,
-
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT      = 0x00800000,
-
-    //@extension("VK_EXT_transform_feedback") // 29
-    VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT            = 0x01000000,
-
-    //@extension("VK_NV_ray_tracing") // 166
-    VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV   = 0x02000000,
-}
-
-/// Render pass attachment description flags
-type VkFlags VkAttachmentDescriptionFlags
-bitfield VkAttachmentDescriptionFlagBits {
-    VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT                 = 0x00000001,  /// The attachment may alias physical memory of another attachment in the same renderpass
-}
-
-/// Subpass description flags
-type VkFlags VkSubpassDescriptionFlags
-bitfield VkSubpassDescriptionFlagBits {
-    //@extension("VK_NVX_multiview_per_view_attributes") // 98
-    VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX      = 0x00000001,
-    VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002,
-}
-
-/// Command pool creation flags
-type VkFlags VkCommandPoolCreateFlags
-bitfield VkCommandPoolCreateFlagBits {
-    VK_COMMAND_POOL_CREATE_TRANSIENT_BIT                    = 0x00000001,  /// Command buffers have a short lifetime
-    VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT         = 0x00000002,  /// Command buffers may release their memory individually
-
-    //@vulkan1_1
-    VK_COMMAND_POOL_CREATE_PROTECTED_BIT                    = 0x00000004,
-}
-
-/// Command pool reset flags
-type VkFlags VkCommandPoolResetFlags
-bitfield VkCommandPoolResetFlagBits {
-    VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT             = 0x00000001,  /// Release resources owned by the pool
-}
-
-type VkFlags VkCommandBufferResetFlags
-bitfield VkCommandBufferResetFlagBits {
-    VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT           = 0x00000001,  /// Release resources owned by the buffer
-}
-
-type VkFlags VkSampleCountFlags
-bitfield VkSampleCountFlagBits {
-    VK_SAMPLE_COUNT_1_BIT                                   = 0x00000001,
-    VK_SAMPLE_COUNT_2_BIT                                   = 0x00000002,
-    VK_SAMPLE_COUNT_4_BIT                                   = 0x00000004,
-    VK_SAMPLE_COUNT_8_BIT                                   = 0x00000008,
-    VK_SAMPLE_COUNT_16_BIT                                  = 0x00000010,
-    VK_SAMPLE_COUNT_32_BIT                                  = 0x00000020,
-    VK_SAMPLE_COUNT_64_BIT                                  = 0x00000040,
-}
-
-type VkFlags VkStencilFaceFlags
-bitfield VkStencilFaceFlagBits {
-    VK_STENCIL_FACE_FRONT_BIT                               = 0x00000001,   /// Front face
-    VK_STENCIL_FACE_BACK_BIT                                = 0x00000002,   /// Back face
-    VK_STENCIL_FRONT_AND_BACK                               = 0x00000003,
-}
-
-/// Instance creation flags
-type VkFlags VkInstanceCreateFlags
-//bitfield VkInstanceCreateFlagBits {
-//}
-
-/// Device creation flags
-type VkFlags VkDeviceCreateFlags
-//bitfield VkDeviceCreateFlagBits {
-//}
-
-/// Device queue creation flags
-type VkFlags VkDeviceQueueCreateFlags
-@vulkan1_1
-bitfield VkDeviceQueueCreateFlagBits {
-    VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT                    = 0x00000001,
-}
-
-/// Query pool creation flags
-type VkFlags VkQueryPoolCreateFlags
-//bitfield VkQueryPoolCreateFlagBits {
-//}
-
-/// Buffer view creation flags
-type VkFlags VkBufferViewCreateFlags
-//bitfield VkBufferViewCreateFlagBits {
-//}
-
-/// Pipeline cache creation flags
-type VkFlags VkPipelineCacheCreateFlags
-//bitfield VkPipelineCacheCreateFlagBits {
-//}
-
-/// Pipeline shader stage creation flags
-type VkFlags VkPipelineShaderStageCreateFlags
-//bitfield VkPipelineShaderStageCreateFlagBits {
-//}
-
-/// Descriptor set layout creation flags
-type VkFlags VkDescriptorSetLayoutCreateFlags
-bitfield VkDescriptorSetLayoutCreateFlagBits {
-    //@extension("VK_KHR_push_descriptor") // 81
-    VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR     = 0x00000001,
-
-    //@extension("VK_EXT_descriptor_indexing") // 162
-    VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT  = 0x00000002,
-}
-
-/// Pipeline vertex input state creation flags
-type VkFlags VkPipelineVertexInputStateCreateFlags
-//bitfield VkPipelineVertexInputStateCreateFlagBits {
-//}
-
-/// Pipeline input assembly state creation flags
-type VkFlags VkPipelineInputAssemblyStateCreateFlags
-//bitfield VkPipelineInputAssemblyStateCreateFlagBits {
-//}
-
-/// Tessellation state creation flags
-type VkFlags VkPipelineTessellationStateCreateFlags
-//bitfield VkPipelineTessellationStateCreateFlagBits {
-//}
-
-/// Viewport state creation flags
-type VkFlags VkPipelineViewportStateCreateFlags
-//bitfield VkPipelineViewportStateCreateFlagBits {
-//}
-
-/// Rasterization state creation flags
-type VkFlags VkPipelineRasterizationStateCreateFlags
-//bitfield VkPipelineRasterizationStateCreateFlagBits {
-//}
-
-/// Multisample state creation flags
-type VkFlags VkPipelineMultisampleStateCreateFlags
-//bitfield VkPipelineMultisampleStateCreateFlagBits {
-//}
-
-/// Color blend state creation flags
-type VkFlags VkPipelineColorBlendStateCreateFlags
-//bitfield VkPipelineColorBlendStateCreateFlagBits {
-//}
-
-/// Depth/stencil state creation flags
-type VkFlags VkPipelineDepthStencilStateCreateFlags
-//bitfield VkPipelineDepthStencilStateCreateFlagBits {
-//}
-
-/// Dynamic state creation flags
-type VkFlags VkPipelineDynamicStateCreateFlags
-//bitfield VkPipelineDynamicStateCreateFlagBits {
-//}
-
-/// Pipeline layout creation flags
-type VkFlags VkPipelineLayoutCreateFlags
-//bitfield VkPipelineLayoutCreateFlagBits {
-//}
-
-/// Sampler creation flags
-type VkFlags VkSamplerCreateFlags
-bitfield VkSamplerCreateFlagBits {
-    //@extension("VK_EXT_fragment_density_map") // 219
-    VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT                        = 0x00000001,
-    VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT  = 0x00000002,
-}
-
-/// Render pass creation flags
-type VkFlags VkRenderPassCreateFlags
-//bitfield VkRenderPassCreateFlagBits {
-//}
-
-/// Framebuffer creation flags
-type VkFlags VkFramebufferCreateFlags
-//bitfield VkFramebufferCreateFlagBits {
-//}
-
-/// Dependency flags
-type VkFlags VkDependencyFlags
-bitfield VkDependencyFlagBits {
-    VK_DEPENDENCY_BY_REGION_BIT                             = 0x00000001,
-
-    //@vulkan1_1
-    VK_DEPENDENCY_DEVICE_GROUP_BIT                          = 0x00000004,
-    VK_DEPENDENCY_VIEW_LOCAL_BIT                            = 0x00000002,
-
-    //@extension("VK_KHR_multiview") // 54
-    VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR                        = 0x00000002,
-
-    //@extension("VK_KHR_device_group") // 61
-    VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR                      = 0x00000004,
-}
-
-/// Cull mode flags
-type VkFlags VkCullModeFlags
-bitfield VkCullModeFlagBits {
-    VK_CULL_MODE_NONE                                       = 0x00000000,
-    VK_CULL_MODE_FRONT_BIT                                  = 0x00000001,
-    VK_CULL_MODE_BACK_BIT                                   = 0x00000002,
-    VK_CULL_MODE_FRONT_AND_BACK                             = 0x00000003,
-}
-
-//@vulkan1_1 flags
-
-/// Subgroup feature flags
-type VkFlags VkSubgroupFeatureFlags
-bitfield VkSubgroupFeatureFlagBits {
-    VK_SUBGROUP_FEATURE_BASIC_BIT                           = 0x00000001,
-    VK_SUBGROUP_FEATURE_VOTE_BIT                            = 0x00000002,
-    VK_SUBGROUP_FEATURE_ARITHMETIC_BIT                      = 0x00000004,
-    VK_SUBGROUP_FEATURE_BALLOT_BIT                          = 0x00000008,
-    VK_SUBGROUP_FEATURE_SHUFFLE_BIT                         = 0x00000010,
-    VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT                = 0x00000020,
-    VK_SUBGROUP_FEATURE_CLUSTERED_BIT                       = 0x00000040,
-    VK_SUBGROUP_FEATURE_QUAD_BIT                            = 0x00000080,
-
-    //@extension("VK_NV_shader_subgroup_partitioned") // 199
-    VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV                  = 0x00000100,
-}
-
-/// Peer memory feature flags
-type VkFlags VkPeerMemoryFeatureFlags
-bitfield VkPeerMemoryFeatureFlagBits {
-    VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT                     = 0x00000001,
-    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT                     = 0x00000002,
-    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT                  = 0x00000004,
-    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT                  = 0x00000008,
-}
-
-/// Memory allocation flags
-type VkFlags VkMemoryAllocateFlags
-bitfield VkMemoryAllocateFlagBits {
-    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT                      = 0x00000001,
-}
-
-type VkFlags VkCommandPoolTrimFlags
-//bitfield VkCommandPoolTrimFlagBits {
-//}
-
-type VkFlags VkDescriptorUpdateTemplateCreateFlags
-//bitfield VkDescriptorUpdateTemplateCreateFlagBits {
-//}
-
-/// External memory handle type flags
-type VkFlags VkExternalMemoryHandleTypeFlags
-bitfield VkExternalMemoryHandleTypeFlagBits {
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT            = 0x00000001,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT         = 0x00000002,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT     = 0x00000004,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT        = 0x00000008,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT    = 0x00000010,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT           = 0x00000020,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT       = 0x00000040,
-
-    //@extension("VK_EXT_external_memory_host") // 179
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT              = 0x00000080,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT   = 0x00000100,
-
-    //@extension("VK_EXT_external_memory_dma_buf") // 126
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT                      = 0x00000200,
-
-    //@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID  = 0x00000400,
-}
-
-/// External memory feature flags
-type VkFlags VkExternalMemoryFeatureFlags
-bitfield VkExternalMemoryFeatureFlagBits {
-    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT           = 0x00000001,
-    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT               = 0x00000002,
-    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT               = 0x00000004,
-}
-
-/// External fence handle type flags
-type VkFlags VkExternalFenceHandleTypeFlags
-bitfield VkExternalFenceHandleTypeFlagBits {
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT             = 0x00000001,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT          = 0x00000002,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT      = 0x00000004,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT               = 0x00000008,
-}
-
-/// External fence feature flags
-type VkFlags VkExternalFenceFeatureFlags
-bitfield VkExternalFenceFeatureFlagBits {
-    VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT                = 0x00000001,
-    VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT                = 0x00000002,
-}
-
-/// Fence import flags
-type VkFlags VkFenceImportFlags
-bitfield VkFenceImportFlagBits {
-    VK_FENCE_IMPORT_TEMPORARY_BIT                           = 0x00000001,
-}
-
-/// Semaphore import flags
-type VkFlags VkSemaphoreImportFlags
-bitfield VkSemaphoreImportFlagBits {
-    VK_SEMAPHORE_IMPORT_TEMPORARY_BIT                       = 0x00000001,
-}
-
-/// External semaphore handle type flags
-type VkFlags VkExternalSemaphoreHandleTypeFlags
-bitfield VkExternalSemaphoreHandleTypeFlagBits {
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT         = 0x00000001,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT      = 0x00000002,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT  = 0x00000004,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT       = 0x00000008,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT           = 0x00000010,
-}
-
-/// External semaphore feature flags
-type VkFlags VkExternalSemaphoreFeatureFlags
-bitfield VkExternalSemaphoreFeatureFlagBits {
-    VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT            = 0x00000001,
-    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT            = 0x00000002,
-}
-
-@extension("VK_KHR_surface") // 1
-type VkFlags VkSurfaceTransformFlagsKHR
-@extension("VK_KHR_surface") // 1
-bitfield VkSurfaceTransformFlagBitsKHR {
-    VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR                       = 0x00000001,
-    VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR                      = 0x00000002,
-    VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR                     = 0x00000004,
-    VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR                     = 0x00000008,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR              = 0x00000010,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR    = 0x00000020,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR   = 0x00000040,
-    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR   = 0x00000080,
-    VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR                        = 0x00000100,
-}
-
-@extension("VK_KHR_surface") // 1
-type VkFlags VkCompositeAlphaFlagsKHR
-@extension("VK_KHR_surface") // 1
-bitfield VkCompositeAlphaFlagBitsKHR {
-    VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR                       = 0x00000001,
-    VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR               = 0x00000002,
-    VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR              = 0x00000004,
-    VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR                      = 0x00000008,
-}
-
-@extension("VK_KHR_swapchain") // 2
-type VkFlags VkSwapchainCreateFlagsKHR
-@extension("VK_KHR_swapchain") // 2
-bitfield VkSwapchainCreateFlagBitsKHR {
-    //@vulkan1_1
-    VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001,
-    VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR                   = 0x00000002,
-
-    //@extension("VK_KHR_swapchain_mutable_format") // 201
-    VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR              = 0x00000004,
-}
-
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-type VkFlags VkDeviceGroupPresentModeFlagsKHR
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-bitfield VkDeviceGroupPresentModeFlagBitsKHR {
-    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR              = 0x00000001,
-    VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR             = 0x00000002,
-    VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR                = 0x00000004,
-    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0x00000008,
-}
-
-@extension("VK_KHR_display") // 3
-type VkFlags VkDisplayPlaneAlphaFlagsKHR
-@extension("VK_KHR_display") // 3
-bitfield VkDisplayPlaneAlphaFlagBitsKHR {
-    VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR                   = 0x00000001,
-    VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR                   = 0x00000002,
-    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR                = 0x00000004,
-    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR  = 0x00000008,
-}
-
-@extension("VK_KHR_display") // 3
-type VkFlags VkDisplaySurfaceCreateFlagsKHR
-//@extension("VK_KHR_display") // 3
-//bitfield VkDisplaySurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_display") // 3
-type VkFlags VkDisplayModeCreateFlagsKHR
-//@extension("VK_KHR_display") // 3
-//bitfield VkDisplayModeCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_xlib_surface") // 5
-type VkFlags VkXlibSurfaceCreateFlagsKHR
-//@extension("VK_KHR_xlib_surface") // 5
-//bitfield VkXlibSurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_xcb_surface") // 6
-type VkFlags VkXcbSurfaceCreateFlagsKHR
-//@extension("VK_KHR_xcb_surface") // 6
-//bitfield VkXcbSurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_wayland_surface") // 7
-type VkFlags VkWaylandSurfaceCreateFlagsKHR
-//@extension("VK_KHR_wayland_surface") // 7
-//bitfield VkWaylandSurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_android_surface") // 9
-type VkFlags VkAndroidSurfaceCreateFlagsKHR
-//@extension("VK_KHR_android_surface") // 9
-//bitfield VkAndroidSurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_KHR_win32_surface") // 10
-type VkFlags VkWin32SurfaceCreateFlagsKHR
-//@extension("VK_KHR_win32_surface") // 10
-//bitfield VkWin32SurfaceCreateFlagBitsKHR {
-//}
-
-@extension("VK_ANDROID_native_buffer") // 11
-type VkFlags VkSwapchainImageUsageFlagsANDROID
-@extension("VK_ANDROID_native_buffer") // 11
-bitfield VkSwapchainImageUsageFlagBitsANDROID {
-    VK_SWAPCHAIN_IMAGE_USAGE_FLAGS_SHARED_BIT_ANDROID = 0x00000001,
-}
-
-@extension("VK_EXT_debug_report") // 12
-type VkFlags VkDebugReportFlagsEXT
-@extension("VK_EXT_debug_report") // 12
-bitfield VkDebugReportFlagBitsEXT {
-    VK_DEBUG_REPORT_INFORMATION_BIT_EXT                     = 0x00000001,
-    VK_DEBUG_REPORT_WARNING_BIT_EXT                         = 0x00000002,
-    VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT             = 0x00000004,
-    VK_DEBUG_REPORT_ERROR_BIT_EXT                           = 0x00000008,
-    VK_DEBUG_REPORT_DEBUG_BIT_EXT                           = 0x00000010,
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-type VkFlags VkPipelineRasterizationStateStreamCreateFlagsEXT
-//@extension("VK_EXT_transform_feedback") // 29
-//bitfield VkPipelineRasterizationStateStreamCreateFlagBitsEXT {
-//}
-
-@extension("VK_NV_external_memory_capabilities") // 56
-type VkFlags VkExternalMemoryHandleTypeFlagsNV
-@extension("VK_NV_external_memory_capabilities") // 56
-bitfield VkExternalMemoryHandleTypeFlagBitsNV {
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV      = 0x00000001,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV  = 0x00000002,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV       = 0x00000004,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV   = 0x00000008,
-}
-
-@extension("VK_NV_external_memory_capabilities") // 56
-type VkFlags VkExternalMemoryFeatureFlagsNV
-@extension("VK_NV_external_memory_capabilities") // 56
-bitfield VkExternalMemoryFeatureFlagBitsNV {
-    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV        = 0x00000001,
-    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV            = 0x00000002,
-    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV            = 0x00000004,
-}
-
-@extension("VK_KHR_device_group") // 61
-type VkFlags VkPeerMemoryFeatureFlagsKHR
-@extension("VK_KHR_device_group") // 61
-bitfield VkPeerMemoryFeatureFlagBitsKHR {
-    VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHR                 = 0x00000001,
-    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR                 = 0x00000002,
-    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR              = 0x00000004,
-    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR              = 0x00000008,
-}
-
-@extension("VK_KHR_device_group") // 61
-type VkFlags VkMemoryAllocateFlagsKHR
-@extension("VK_KHR_device_group") // 61
-bitfield VkMemoryAllocateFlagBitsKHR {
-    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR                  = 0x00000001,
-}
-
-@extension("VK_NN_vi_surface") // 63
-type VkFlags VkViSurfaceCreateFlagsNN
-//@extension("VK_NN_vi_surface") // 63
-//bitfield VkViSurfaceCreateFlagBitsNN {
-//}
-
-@extension("VK_KHR_maintenance1") // 70
-type VkFlags VkCommandPoolTrimFlagsKHR
-//@extension("VK_KHR_maintenance1") // 70
-//bitfield VkCommandPoolTrimFlagBitsKHR {
-//}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-type VkFlags VkExternalMemoryHandleTypeFlagsKHR
-@extension("VK_KHR_external_memory_capabilities") // 72
-bitfield VkExternalMemoryHandleTypeFlagBitsKHR {
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR            = 0x00000001,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR         = 0x00000002,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR     = 0x00000004,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR        = 0x00000008,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR    = 0x00000010,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR           = 0x00000020,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR       = 0x00000040,
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-type VkFlags VkExternalMemoryFeatureFlagsKHR
-@extension("VK_KHR_external_memory_capabilities") // 72
-bitfield VkExternalMemoryFeatureFlagBitsKHR {
-    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR           = 0x00000001,
-    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR               = 0x00000002,
-    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR               = 0x00000004,
-}
-
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-type VkFlags VkExternalSemaphoreHandleTypeFlagsKHR
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-bitfield VkExternalSemaphoreHandleTypeFlagBitsKHR {
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR         = 0x00000001
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR      = 0x00000002
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR  = 0x00000004
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR       = 0x00000008
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHR          = 0x00000010
-}
-
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-type VkFlags VkExternalSemaphoreFeatureFlagsKHR
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-bitfield VkExternalSemaphoreFeatureFlagBitsKHR {
-    VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR            = 0x00000001,
-    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR            = 0x00000002,
-}
-
-@extension("VK_KHR_external_semaphore") // 78
-type VkFlags VkSemaphoreImportFlagsKHR
-@extension("VK_KHR_external_semaphore") // 78
-bitfield VkSemaphoreImportFlagBitsKHR {
-    VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR                       = 0x00000001,
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-type VkFlags VkConditionalRenderingFlagsEXT
-@extension("VK_EXT_conditional_rendering") // 82
-bitfield VkConditionalRenderingFlagBitsEXT {
-    VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT                   = 0x00000001,
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-type VkFlags VkDescriptorUpdateTemplateCreateFlagsKHR
-//@extension("VK_KHR_descriptor_update_template") // 86
-//bitfield VkDescriptorUpdateTemplateCreateFlagBitsKHR {
-//}
-
-@extension("VK_NVX_device_generated_commands") // 87
-type VkFlags VkIndirectCommandsLayoutUsageFlagsNVX
-@extension("VK_NVX_device_generated_commands") // 87
-bitfield VkIndirectCommandsLayoutUsageFlagBitsNVX {
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX   = 0x00000001,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX      = 0x00000002,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX      = 0x00000004,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX     = 0x00000008,
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-type VkFlags VkObjectEntryUsageFlagsNVX
-@extension("VK_NVX_device_generated_commands") // 87
-bitfield VkObjectEntryUsageFlagBitsNVX {
-    VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX                  = 0x00000001,
-    VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX                   = 0x00000002,
-}
-
-@extension("VK_EXT_display_surface_counter") // 91
-type VkFlags VkSurfaceCounterFlagsEXT
-@extension("VK_EXT_display_surface_counter") // 91
-bitfield VkSurfaceCounterFlagBitsEXT {
-    VK_SURFACE_COUNTER_VBLANK_EXT                           = 0x00000001,
-}
-
-@extension("VK_NV_viewport_swizzle") // 99
-type VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV
-//@extension("VK_NV_viewport_swizzle") // 99
-//bitfield VkPipelineViewportSwizzleStateCreateFlagBitsNV {
-//}
-
-@extension("VK_EXT_discard_rectangles") // 100
-type VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT
-//@extension("VK_EXT_discard_rectangles") // 100
-//bitfield VkPipelineDiscardRectangleStateCreateFlagBitsEXT {
-//}
-
-@extension("VK_EXT_conservative_rasterization") // 102
-type VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT
-//@extension("VK_EXT_conservative_rasterization") // 102
-//bitfield VkPipelineRasterizationConservativeStateCreateFlagBitsEXT {
-//}
-
-@extension("VK_KHR_external_fence_capabilities") // 113
-type VkFlags VkExternalFenceHandleTypeFlagsKHR
-@extension("VK_KHR_external_fence_capabilities") // 113
-bitfield VkExternalFenceHandleTypeFlagBitsKHR {
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR         = 0x00000001,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR      = 0x00000002,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR  = 0x00000004,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR           = 0x00000008,
-}
-
-@extension("VK_KHR_external_fence_capabilities") // 113
-type VkFlags VkExternalFenceFeatureFlagsKHR
-@extension("VK_KHR_external_fence_capabilities") // 113
-bitfield VkExternalFenceFeatureFlagBitsKHR {
-    VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR            = 0x00000001,
-    VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR            = 0x00000002,
-}
-
-@extension("VK_KHR_external_fence") // 114
-type VkFlags VkFenceImportFlagsKHR
-@extension("VK_KHR_external_fence") // 114
-bitfield VkFenceImportFlagBitsKHR {
-    VK_FENCE_IMPORT_TEMPORARY_BIT_KHR                       = 0x00000001,
-}
-
-@extension("VK_MVK_ios_surface") // 123
-type VkFlags VkIOSSurfaceCreateFlagsMVK
-//@extension("VK_MVK_ios_surface") // 123
-//bitfield VkIOSSurfaceCreateFlagBitsMVK {
-//}
-
-@extension("VK_MVK_macos_surface") // 124
-type VkFlags VkMacOSSurfaceCreateFlagsMVK
-//@extension("VK_MVK_macos_surface") // 124
-//bitfield VkMacOSSurfaceCreateFlagBitsMVK {
-//}
-
-@extension("VK_EXT_debug_utils") // 129
-type VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT
-//@extension("VK_EXT_debug_utils") // 129
-//bitfield VkDebugUtilsMessengerCallbackDataFlagBitsEXT {
-//}
-
-@extension("VK_EXT_debug_utils") // 129
-type VkFlags VkDebugUtilsMessengerCreateFlagsEXT
-//@extension("VK_EXT_debug_utils") // 129
-//bitfield VkDebugUtilsMessengerCreateFlagBitsEXT {
-//}
-
-@extension("VK_EXT_debug_utils") // 129
-type VkFlags VkDebugUtilsMessageSeverityFlagsEXT
-@extension("VK_EXT_debug_utils") // 129
-bitfield VkDebugUtilsMessageSeverityFlagBitsEXT {
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001,
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT    = 0x00000010,
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100,
-    VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT   = 0x00001000,
-}
-
-@extension("VK_EXT_debug_utils") // 129
-type VkFlags VkDebugUtilsMessageTypeFlagsEXT
-@extension("VK_EXT_debug_utils") // 129
-bitfield VkDebugUtilsMessageTypeFlagBitsEXT {
-    VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT     = 0x00000001,
-    VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT  = 0x00000002,
-    VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004,
-}
-
-@extension("VK_NV_fragment_coverage_to_color") // 150
-type VkFlags VkPipelineCoverageToColorStateCreateFlagsNV
-@extension("VK_NV_fragment_coverage_to_color") // 150
-//bitfield VkPipelineCoverageToColorStateCreateFlagBitsNV {
-//}
-
-@extension("VK_NV_framebuffer_mixed_samples") // 153
-type VkFlags VkPipelineCoverageModulationStateCreateFlagsNV
-@extension("VK_NV_framebuffer_mixed_samples") // 153
-//bitfield VkPipelineCoverageModulationStateCreateFlagBitsNV {
-//}
-
-@extension("VK_EXT_validation_cache") // 161
-type VkFlags VkValidationCacheCreateFlagsEXT
-@extension("VK_EXT_validation_cache") // 161
-//bitfield VkValidationCacheCreateFlagBitsEXT {
-//}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-type VkFlags VkDescriptorBindingFlagsEXT
-@extension("VK_EXT_descriptor_indexing") // 162
-bitfield VkDescriptorBindingFlagBitsEXT {
-    VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT             = 0x00000001,
-    VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT   = 0x00000002,
-    VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT               = 0x00000004,
-    VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT     = 0x00000008,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-type VkFlags VkGeometryFlagsNV
-@extension("VK_NV_ray_tracing") // 166
-bitfield VkGeometryFlagBitsNV {
-    VK_GEOMETRY_OPAQUE_BIT_NV                           = 0x00000001,
-    VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV  = 0x00000002,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-type VkFlags VkGeometryInstanceFlagsNV
-@extension("VK_NV_ray_tracing") // 166
-bitfield VkGeometryInstanceFlagBitsNV {
-    VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV           = 0x00000001,
-    VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = 0x00000002,
-    VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV                    = 0x00000004,
-    VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV                 = 0x00000008,
-}
-
-@extension("VK_NV_ray_tracing") // 166
-type VkFlags VkBuildAccelerationStructureFlagsNV
-@extension("VK_NV_ray_tracing") // 166
-bitfield VkBuildAccelerationStructureFlagBitsNV {
-    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV         = 0x00000001,
-    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV     = 0x00000002,
-    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV    = 0x00000004,
-    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV    = 0x00000008,
-    VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV           = 0x00000010,
-}
-
-@extension("VK_FUCHSIA_imagepipe_surface") // 215
-type VkFlags VkImagePipeSurfaceCreateFlagsFUCHSIA
-//@extension("VK_FUCHSIA_imagepipe_surface") // 215
-//bitfield VkImagePipeSurfaceCreateFlagBitsFUCHSIA {
-//}
-
-//////////////////
-//  Structures  //
-//////////////////
-
-class VkOffset2D {
-    s32                                         x
-    s32                                         y
-}
-
-class VkOffset3D {
-    s32                                         x
-    s32                                         y
-    s32                                         z
-}
-
-class VkExtent2D {
-    u32                                         width
-    u32                                         height
-}
-
-class VkExtent3D {
-    u32                                         width
-    u32                                         height
-    u32                                         depth
-}
-
-class VkViewport {
-    f32                                         x
-    f32                                         y
-    f32                                         width
-    f32                                         height
-    f32                                         minDepth
-    f32                                         maxDepth
-}
-
-class VkRect2D {
-    VkOffset2D                                  offset
-    VkExtent2D                                  extent
-}
-
-class VkClearRect {
-    VkRect2D                                    rect
-    u32                                         baseArrayLayer
-    u32                                         layerCount
-}
-
-class VkComponentMapping {
-    VkComponentSwizzle                          r
-    VkComponentSwizzle                          g
-    VkComponentSwizzle                          b
-    VkComponentSwizzle                          a
-}
-
-class VkPhysicalDeviceProperties {
-    u32                                         apiVersion
-    u32                                         driverVersion
-    u32                                         vendorID
-    u32                                         deviceID
-    VkPhysicalDeviceType                        deviceType
-    char[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]      deviceName
-    u8[VK_UUID_SIZE]                            pipelineCacheUUID
-    VkPhysicalDeviceLimits                      limits
-    VkPhysicalDeviceSparseProperties            sparseProperties
-}
-
-class VkExtensionProperties {
-    char[VK_MAX_EXTENSION_NAME_SIZE]            extensionName      /// extension name
-    u32                                         specVersion        /// version of the extension specification implemented
-}
-
-class VkLayerProperties {
-    char[VK_MAX_EXTENSION_NAME_SIZE]            layerName               /// layer name
-    u32                                         specVersion             /// version of the layer specification implemented
-    u32                                         implementationVersion   /// build or release version of the layer's library
-    char[VK_MAX_DESCRIPTION_SIZE]               description             /// Free-form description of the layer
-}
-
-class VkSubmitInfo {
-    VkStructureType                             sType              /// Type of structure. Should be VK_STRUCTURE_TYPE_SUBMIT_INFO
-    const void*                                 pNext              /// Next structure in chain
-    u32                                         waitSemaphoreCount
-    const VkSemaphore*                          pWaitSemaphores
-    const VkPipelineStageFlags*                 pWaitDstStageMask
-    u32                                         commandBufferCount
-    const VkCommandBuffer*                      pCommandBuffers
-    u32                                         signalSemaphoreCount
-    const VkSemaphore*                          pSignalSemaphores
-}
-
-class VkApplicationInfo {
-    VkStructureType                             sType              /// Type of structure. Should be VK_STRUCTURE_TYPE_APPLICATION_INFO
-    const void*                                 pNext              /// Next structure in chain
-    const char*                                 pApplicationName
-    u32                                         applicationVersion
-    const char*                                 pEngineName
-    u32                                         engineVersion
-    u32                                         apiVersion
-}
-
-class VkAllocationCallbacks {
-    void*                                       pUserData
-    PFN_vkAllocationFunction                    pfnAllocation
-    PFN_vkReallocationFunction                  pfnReallocation
-    PFN_vkFreeFunction                          pfnFree
-    PFN_vkInternalAllocationNotification        pfnInternalAllocation
-    PFN_vkInternalFreeNotification              pfnInternalFree
-}
-
-class VkDeviceQueueCreateInfo {
-    VkStructureType                             sStype                    /// Should be VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
-    const void*                                 pNext                     /// Pointer to next structure
-    VkDeviceQueueCreateFlags                    flags
-    u32                                         queueFamilyIndex
-    u32                                         queueCount
-    const f32*                                  pQueuePriorities
-}
-
-class VkDeviceCreateInfo {
-    VkStructureType                             sType                      /// Should be VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure
-    VkDeviceCreateFlags                         flags
-    u32                                         queueCreateInfoCount
-    const VkDeviceQueueCreateInfo*              pQueueCreateInfos
-    u32                                         enabledLayerCount
-    const char* const*                          ppEnabledLayerNames        /// Ordered list of layer names to be enabled
-    u32                                         enabledExtensionCount
-    const char* const*                          ppEnabledExtensionNames
-    const VkPhysicalDeviceFeatures*             pEnabledFeatures
-}
-
-class VkInstanceCreateInfo {
-    VkStructureType                             sType                      /// Should be VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure
-    VkInstanceCreateFlags                       flags
-    const VkApplicationInfo*                    pApplicationInfo
-    u32                                         enabledLayerCount
-    const char* const*                          ppEnabledLayerNames        /// Ordered list of layer names to be enabled
-    u32                                         enabledExtensionCount
-    const char* const*                          ppEnabledExtensionNames    /// Extension names to be enabled
-}
-
-class VkQueueFamilyProperties {
-    VkQueueFlags                                queueFlags                 /// Queue flags
-    u32                                         queueCount
-    u32                                         timestampValidBits
-    VkExtent3D                                  minImageTransferGranularity
-}
-
-class VkPhysicalDeviceMemoryProperties {
-    u32                                         memoryTypeCount
-    VkMemoryType[VK_MAX_MEMORY_TYPES]           memoryTypes
-    u32                                         memoryHeapCount
-    VkMemoryHeap[VK_MAX_MEMORY_HEAPS]           memoryHeaps
-}
-
-class VkMemoryAllocateInfo {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure
-    VkDeviceSize                                allocationSize             /// Size of memory allocation
-    u32                                         memoryTypeIndex            /// Index of the of the memory type to allocate from
-}
-
-class VkMemoryRequirements {
-    VkDeviceSize                                size                       /// Specified in bytes
-    VkDeviceSize                                alignment                  /// Specified in bytes
-    u32                                         memoryTypeBits             /// Bitfield of the allowed memory type indices into memoryTypes[] for this object
-}
-
-class VkSparseImageFormatProperties {
-    VkImageAspectFlagBits                       aspectMask
-    VkExtent3D                                  imageGranularity
-    VkSparseImageFormatFlags                    flags
-}
-
-class VkSparseImageMemoryRequirements {
-    VkSparseImageFormatProperties               formatProperties
-    u32                                         imageMipTailFirstLod
-    VkDeviceSize                                imageMipTailSize           /// Specified in bytes, must be a multiple of image block size / alignment
-    VkDeviceSize                                imageMipTailOffset         /// Specified in bytes, must be a multiple of image block size / alignment
-    VkDeviceSize                                imageMipTailStride         /// Specified in bytes, must be a multiple of image block size / alignment
-}
-
-class VkMemoryType {
-    VkMemoryPropertyFlags                       propertyFlags              /// Memory properties of this memory type
-    u32                                         heapIndex                  /// Index of the memory heap allocations of this memory type are taken from
-}
-
-class VkMemoryHeap {
-    VkDeviceSize                                size                       /// Available memory in the heap
-    VkMemoryHeapFlags                           flags                      /// Flags for the heap
-}
-
-class VkMappedMemoryRange {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE
-    const void*                                 pNext                      /// Pointer to next structure
-    VkDeviceMemory                              memory                     /// Mapped memory object
-    VkDeviceSize                                offset                     /// Offset within the mapped memory the range starts from
-    VkDeviceSize                                size                       /// Size of the range within the mapped memory
-}
-
-class VkFormatProperties {
-    VkFormatFeatureFlags                        linearTilingFeatures       /// Format features in case of linear tiling
-    VkFormatFeatureFlags                        optimalTilingFeatures      /// Format features in case of optimal tiling
-    VkFormatFeatureFlags                        bufferFeatures             /// Format features supported by buffers
-}
-
-class VkImageFormatProperties {
-    VkExtent3D                                  maxExtent                  /// max image dimensions for this resource type
-    u32                                         maxMipLevels               /// max number of mipmap levels for this resource type
-    u32                                         maxArrayLayers             /// max array layers for this resource type
-    VkSampleCountFlags                          sampleCounts               /// supported sample counts for this resource type
-    VkDeviceSize                                maxResourceSize            /// max size (in bytes) of this resource type
-}
-
-class VkDescriptorImageInfo {
-    VkSampler                                   sampler
-    VkImageView                                 imageView
-    VkImageLayout                               imageLayout
-}
-
-class VkDescriptorBufferInfo {
-    VkBuffer                                    buffer                     /// Buffer used for this descriptor when the descriptor is UNIFORM_BUFFER[_DYNAMIC]
-    VkDeviceSize                                offset                     /// Base offset from buffer start in bytes to update in the descriptor set.
-    VkDeviceSize                                range                      /// Size in bytes of the buffer resource for this descriptor update.
-}
-
-class VkWriteDescriptorSet {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET
-    const void*                                 pNext                      /// Pointer to next structure
-    VkDescriptorSet                             dstSet                     /// Destination descriptor set
-    u32                                         dstBinding                 /// Binding within the destination descriptor set to write
-    u32                                         dstArrayElement            /// Array element within the destination binding to write
-    u32                                         descriptorCount            /// Number of descriptors to write (determines the size of the array pointed by <pDescriptors>)
-    VkDescriptorType                            descriptorType             /// Descriptor type to write (determines which fields of the array pointed by <pDescriptors> are going to be used)
-    const VkDescriptorImageInfo*                pImageInfo
-    const VkDescriptorBufferInfo*               pBufferInfo
-    const VkBufferView*                         pTexelBufferView
-}
-
-class VkCopyDescriptorSet {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET
-    const void*                                 pNext                      /// Pointer to next structure
-    VkDescriptorSet                             srcSet                     /// Source descriptor set
-    u32                                         srcBinding                 /// Binding within the source descriptor set to copy from
-    u32                                         srcArrayElement            /// Array element within the source binding to copy from
-    VkDescriptorSet                             dstSet                     /// Destination descriptor set
-    u32                                         dstBinding                 /// Binding within the destination descriptor set to copy to
-    u32                                         dstArrayElement            /// Array element within the destination binding to copy to
-    u32                                         descriptorCount            /// Number of descriptors to copy
-}
-
-class VkBufferCreateInfo {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkBufferCreateFlags                         flags                      /// Buffer creation flags
-    VkDeviceSize                                size                       /// Specified in bytes
-    VkBufferUsageFlags                          usage                      /// Buffer usage flags
-    VkSharingMode                               sharingMode
-    u32                                         queueFamilyIndexCount
-    const u32*                                  pQueueFamilyIndices
-}
-
-class VkBufferViewCreateInfo {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkBufferViewCreateFlags                     flags
-    VkBuffer                                    buffer
-    VkFormat                                    format                     /// Optionally specifies format of elements
-    VkDeviceSize                                offset                     /// Specified in bytes
-    VkDeviceSize                                range                      /// View size specified in bytes
-}
-
-class VkImageSubresource {
-    VkImageAspectFlagBits                       aspectMask
-    u32                                         mipLevel
-    u32                                         arrayLayer
-}
-
-class VkImageSubresourceRange {
-    VkImageAspectFlags                          aspectMask
-    u32                                         baseMipLevel
-    u32                                         levelCount
-    u32                                         baseArrayLayer
-    u32                                         layerCount
-}
-
-class VkMemoryBarrier {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_MEMORY_BARRIER
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkAccessFlags                               srcAccessMask
-    VkAccessFlags                               dstAccessMask
-}
-
-class VkBufferMemoryBarrier {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkAccessFlags                               srcAccessMask
-    VkAccessFlags                               dstAccessMask
-    u32                                         srcQueueFamilyIndex        /// Queue family to transition ownership from
-    u32                                         dstQueueFamilyIndex        /// Queue family to transition ownership to
-    VkBuffer                                    buffer                     /// Buffer to sync
-    VkDeviceSize                                offset                     /// Offset within the buffer to sync
-    VkDeviceSize                                size                       /// Amount of bytes to sync
-}
-
-class VkImageMemoryBarrier {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkAccessFlags                               srcAccessMask
-    VkAccessFlags                               dstAccessMask
-    VkImageLayout                               oldLayout                  /// Current layout of the image
-    VkImageLayout                               newLayout                  /// New layout to transition the image to
-    u32                                         srcQueueFamilyIndex        /// Queue family to transition ownership from
-    u32                                         dstQueueFamilyIndex        /// Queue family to transition ownership to
-    VkImage                                     image                      /// Image to sync
-    VkImageSubresourceRange                     subresourceRange           /// Subresource range to sync
-}
-
-class VkImageCreateInfo {
-    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
-    const void*                                 pNext                      /// Pointer to next structure.
-    VkImageCreateFlags                          flags                      /// Image creation flags
-    VkImageType                                 imageType
-    VkFormat                                    format
-    VkExtent3D                                  extent
-    u32                                         mipLevels
-    u32                                         arrayLayers
-    VkSampleCountFlagBits                       samples
-    VkImageTiling                               tiling
-    VkImageUsageFlags                           usage                      /// Image usage flags
-    VkSharingMode                               sharingMode                /// Cross-queue-family sharing mode
-    u32                                         queueFamilyIndexCount      /// Number of queue families to share across
-    const u32*                                  pQueueFamilyIndices        /// Array of queue family indices to share across
-    VkImageLayout                               initialLayout              /// Initial image layout for all subresources
-}
-
-class VkSubresourceLayout {
-    VkDeviceSize                                offset                 /// Specified in bytes
-    VkDeviceSize                                size                   /// Specified in bytes
-    VkDeviceSize                                rowPitch               /// Specified in bytes
-    VkDeviceSize                                arrayPitch             /// Specified in bytes
-    VkDeviceSize                                depthPitch             /// Specified in bytes
-}
-
-class VkImageViewCreateInfo {
-    VkStructureType                             sType                  /// Must be VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
-    const void*                                 pNext                  /// Pointer to next structure
-    VkImageViewCreateFlags                      flags
-    VkImage                                     image
-    VkImageViewType                             viewType
-    VkFormat                                    format
-    VkComponentMapping                          components
-    VkImageSubresourceRange                     subresourceRange
-}
-
-class VkBufferCopy {
-    VkDeviceSize                                srcOffset              /// Specified in bytes
-    VkDeviceSize                                dstOffset              /// Specified in bytes
-    VkDeviceSize                                size                   /// Specified in bytes
-}
-
-class VkSparseMemoryBind {
-    VkDeviceSize                                resourceOffset        /// Specified in bytes
-    VkDeviceSize                                size                  /// Specified in bytes
-    VkDeviceMemory                              memory
-    VkDeviceSize                                memoryOffset          /// Specified in bytes
-    VkSparseMemoryBindFlags                     flags
-}
-
-class VkSparseImageMemoryBind {
-    VkImageSubresource                          subresource
-    VkOffset3D                                  offset
-    VkExtent3D                                  extent
-    VkDeviceMemory                              memory
-    VkDeviceSize                                memoryOffset          /// Specified in bytes
-    VkSparseMemoryBindFlags                     flags
-}
-
-class VkSparseBufferMemoryBindInfo {
-    VkBuffer                                    buffer
-    u32                                         bindCount
-    const VkSparseMemoryBind*                   pBinds
-}
-
-class VkSparseImageOpaqueMemoryBindInfo {
-    VkImage                                     image
-    u32                                         bindCount
-    const VkSparseMemoryBind*                   pBinds
-}
-
-class VkSparseImageMemoryBindInfo {
-    VkImage                                     image
-    u32                                         bindCount
-    const VkSparseMemoryBind*                   pBinds
-}
-
-class VkBindSparseInfo {
-    VkStructureType                             sType                 /// Must be VK_STRUCTURE_TYPE_BIND_SPARSE_INFO
-    const void*                                 pNext
-    u32                                         waitSemaphoreCount
-    const VkSemaphore*                          pWaitSemaphores
-    u32                                         numBufferBinds
-    const VkSparseBufferMemoryBindInfo*         pBufferBinds
-    u32                                         numImageOpaqueBinds
-    const VkSparseImageOpaqueMemoryBindInfo*    pImageOpaqueBinds
-    u32                                         numImageBinds
-    const VkSparseImageMemoryBindInfo*          pImageBinds
-    u32                                         signalSemaphoreCount
-    const VkSemaphore*                          pSignalSemaphores
-}
-
-class VkImageSubresourceLayers {
-    VkImageAspectFlags                          aspectMask
-    u32                                         mipLevel
-    u32                                         baseArrayLayer
-    u32                                         layerCount
-}
-
-class VkImageCopy {
-    VkImageSubresourceLayers                    srcSubresource
-    VkOffset3D                                  srcOffset             /// Specified in pixels for both compressed and uncompressed images
-    VkImageSubresourceLayers                    dstSubresource
-    VkOffset3D                                  dstOffset             /// Specified in pixels for both compressed and uncompressed images
-    VkExtent3D                                  extent                /// Specified in pixels for both compressed and uncompressed images
-}
-
-class VkImageBlit {
-    VkImageSubresourceLayers                    srcSubresource
-    VkOffset3D[2]                               srcOffsets
-    VkImageSubresourceLayers                    dstSubresource
-    VkOffset3D[2]                               dstOffsets
-}
-
-class VkBufferImageCopy {
-    VkDeviceSize                                bufferOffset           /// Specified in bytes
-    u32                                         bufferRowLength        /// Specified in texels
-    u32                                         bufferImageHeight
-    VkImageSubresourceLayers                    imageSubresource
-    VkOffset3D                                  imageOffset            /// Specified in pixels for both compressed and uncompressed images
-    VkExtent3D                                  imageExtent            /// Specified in pixels for both compressed and uncompressed images
-}
-
-class VkImageResolve {
-    VkImageSubresourceLayers                    srcSubresource
-    VkOffset3D                                  srcOffset
-    VkImageSubresourceLayers                    dstSubresource
-    VkOffset3D                                  dstOffset
-    VkExtent3D                                  extent
-}
-
-class VkShaderModuleCreateInfo {
-    VkStructureType                             sType                  /// Must be VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO
-    const void*                                 pNext                  /// Pointer to next structure
-    VkShaderModuleCreateFlags                   flags                  /// Reserved
-    platform.size_t                             codeSize               /// Specified in bytes
-    const u32*                                  pCode                  /// Binary code of size codeSize
-}
-
-class VkDescriptorSetLayoutBinding {
-    u32                                         binding
-    VkDescriptorType                            descriptorType     /// Type of the descriptors in this binding
-    u32                                         descriptorCount    /// Number of descriptors in this binding
-    VkShaderStageFlags                          stageFlags         /// Shader stages this binding is visible to
-    const VkSampler*                            pImmutableSamplers /// Immutable samplers (used if descriptor type is SAMPLER or COMBINED_IMAGE_SAMPLER, is either NULL or contains <count> number of elements)
-}
-
-class VkDescriptorSetLayoutCreateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkDescriptorSetLayoutCreateFlags            flags
-    u32                                         bindingCount       /// Number of bindings in the descriptor set layout
-    const VkDescriptorSetLayoutBinding*         pBindings          /// Array of descriptor set layout bindings
-}
-
-class VkDescriptorPoolSize {
-    VkDescriptorType                            type
-    u32                                         descriptorCount
-}
-
-class VkDescriptorPoolCreateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkDescriptorPoolCreateFlags                 flags
-    u32                                         maxSets
-    u32                                         poolSizeCount
-    const VkDescriptorPoolSize*                 pPoolSizes
-}
-
-class VkDescriptorSetAllocateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkDescriptorPool                            descriptorPool
-    u32                                         setCount
-    const VkDescriptorSetLayout*                pSetLayouts
-}
-
-class VkSpecializationMapEntry {
-    u32                                         constantID         /// The SpecConstant ID specified in the BIL
-    u32                                         offset             /// Offset of the value in the data block
-    platform.size_t                             size               /// Size in bytes of the SpecConstant
-}
-
-class VkSpecializationInfo {
-    u32                                         mapEntryCount      /// Number of entries in the map
-    const VkSpecializationMapEntry*             pMapEntries        /// Array of map entries
-    platform.size_t                             dataSize           /// Size in bytes of pData
-    const void*                                 pData              /// Pointer to SpecConstant data
-}
-
-class VkPipelineShaderStageCreateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkPipelineShaderStageCreateFlags            flags
-    VkShaderStageFlagBits                       stage
-    VkShaderModule                              module
-    const char*                                 pName
-    const VkSpecializationInfo*                 pSpecializationInfo
-}
-
-class VkComputePipelineCreateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkPipelineCreateFlags                       flags              /// Pipeline creation flags
-    VkPipelineShaderStageCreateInfo             stage
-    VkPipelineLayout                            layout             /// Interface layout of the pipeline
-    VkPipeline                                  basePipelineHandle /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of
-    s32                                         basePipelineIndex  /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of
-}
-
-class VkVertexInputBindingDescription {
-    u32                                         binding               /// Vertex buffer binding id
-    u32                                         stride                /// Distance between vertices in bytes (0 = no advancement)
-    VkVertexInputRate                           inputRate             /// Rate at which binding is incremented
-}
-
-class VkVertexInputAttributeDescription {
-    u32                                         location              /// location of the shader vertex attrib
-    u32                                         binding               /// Vertex buffer binding id
-    VkFormat                                    format                /// format of source data
-    u32                                         offset                /// Offset of first element in bytes from base of vertex
-}
-
-class VkPipelineVertexInputStateCreateInfo {
-    VkStructureType                             sType                           /// Should be VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO
-    const void*                                 pNext                           /// Pointer to next structure
-    VkPipelineVertexInputStateCreateFlags       flags
-    u32                                         vertexBindingDescriptionCount   /// number of bindings
-    const VkVertexInputBindingDescription*      pVertexBindingDescriptions
-    u32                                         vertexAttributeDescriptionCount /// number of attributes
-    const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
-}
-
-class VkPipelineInputAssemblyStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineInputAssemblyStateCreateFlags     flags
-    VkPrimitiveTopology                         topology
-    VkBool32                                    primitiveRestartEnable
-}
-
-class VkPipelineTessellationStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineTessellationStateCreateFlags      flags
-    u32                                         patchControlPoints
-}
-
-class VkPipelineViewportStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineViewportStateCreateFlags          flags
-    u32                                         viewportCount
-    const VkViewport*                           pViewports
-    u32                                         scissorCount
-    const VkRect2D*                             pScissors
-}
-
-class VkPipelineRasterizationStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineRasterizationStateCreateFlags     flags
-    VkBool32                                    depthClampEnable
-    VkBool32                                    rasterizerDiscardEnable
-    VkPolygonMode                               polygonMode                   /// optional (GL45)
-    VkCullModeFlags                             cullMode
-    VkFrontFace                                 frontFace
-    VkBool32                                    depthBiasEnable
-    f32                                         depthBiasConstantFactor
-    f32                                         depthBiasClamp
-    f32                                         depthBiasSlopeFactor
-    f32                                         lineWidth
-}
-
-class VkPipelineMultisampleStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineMultisampleStateCreateFlags       flags
-    VkSampleCountFlagBits                       rasterizationSamples       /// Number of samples used for rasterization
-    VkBool32                                    sampleShadingEnable        /// optional (GL45)
-    f32                                         minSampleShading           /// optional (GL45)
-    const VkSampleMask*                         pSampleMask
-    VkBool32                                    alphaToCoverageEnable
-    VkBool32                                    alphaToOneEnable
-}
-
-class VkPipelineColorBlendAttachmentState {
-    VkBool32                                    blendEnable
-    VkBlendFactor                               srcColorBlendFactor
-    VkBlendFactor                               dstColorBlendFactor
-    VkBlendOp                                   colorBlendOp
-    VkBlendFactor                               srcAlphaBlendFactor
-    VkBlendFactor                               dstAlphaBlendFactor
-    VkBlendOp                                   alphaBlendOp
-    VkColorComponentFlags                       colorWriteMask
-}
-
-class VkPipelineColorBlendStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineColorBlendStateCreateFlags        flags
-    VkBool32                                    logicOpEnable
-    VkLogicOp                                   logicOp
-    u32                                         attachmentCount    /// # of pAttachments
-    const VkPipelineColorBlendAttachmentState*  pAttachments
-    f32[4]                                      blendConstants
-}
-
-class VkStencilOpState {
-    VkStencilOp                                 failOp
-    VkStencilOp                                 passOp
-    VkStencilOp                                 depthFailOp
-    VkCompareOp                                 compareOp
-    u32                                         compareMask
-    u32                                         writeMask
-    u32                                         reference
-}
-
-class VkPipelineDepthStencilStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineDepthStencilStateCreateFlags      flags
-    VkBool32                                    depthTestEnable
-    VkBool32                                    depthWriteEnable
-    VkCompareOp                                 depthCompareOp
-    VkBool32                                    depthBoundsTestEnable  /// optional (depth_bounds_test)
-    VkBool32                                    stencilTestEnable
-    VkStencilOpState                            front
-    VkStencilOpState                            back
-    f32                                         minDepthBounds
-    f32                                         maxDepthBounds
-}
-
-class VkPipelineDynamicStateCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkPipelineDynamicStateCreateFlags           flags
-    u32                                         dynamicStateCount
-    const VkDynamicState*                       pDynamicStates
-}
-
-class VkGraphicsPipelineCreateInfo {
-    VkStructureType                                 sType               /// Must be VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO
-    const void*                                     pNext               /// Pointer to next structure
-    VkPipelineCreateFlags                           flags               /// Pipeline creation flags
-    u32                                             stageCount
-    const VkPipelineShaderStageCreateInfo*          pStages             /// One entry for each active shader stage
-    const VkPipelineVertexInputStateCreateInfo*     pVertexInputState
-    const VkPipelineInputAssemblyStateCreateInfo*   pInputAssemblyState
-    const VkPipelineTessellationStateCreateInfo*    pTessellationState
-    const VkPipelineViewportStateCreateInfo*        pViewportState
-    const VkPipelineRasterizationStateCreateInfo*   pRasterizationState
-    const VkPipelineMultisampleStateCreateInfo*     pMultisampleState
-    const VkPipelineDepthStencilStateCreateInfo*    pDepthStencilState
-    const VkPipelineColorBlendStateCreateInfo*      pColorBlendState
-    const VkPipelineDynamicStateCreateInfo*         pDynamicState
-    VkPipelineLayout                                layout              /// Interface layout of the pipeline
-    VkRenderPass                                    renderPass
-    u32                                             subpass
-    VkPipeline                                      basePipelineHandle  /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of
-    s32                                             basePipelineIndex   /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of
-}
-
-class VkPipelineCacheCreateInfo {
-    VkStructureType                             sType                 /// Must be VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO
-    const void*                                 pNext                 /// Pointer to next structure
-    VkPipelineCacheCreateFlags                  flags
-    platform.size_t                             initialDataSize       /// Size of initial data to populate cache, in bytes
-    const void*                                 pInitialData          /// Initial data to populate cache
-}
-
-class VkPushConstantRange {
-    VkShaderStageFlags                          stageFlags   /// Which stages use the range
-    u32                                         offset       /// Start of the range, in bytes
-    u32                                         size        /// Length of the range, in bytes
-}
-
-class VkPipelineLayoutCreateInfo {
-    VkStructureType                             sType                   /// Must be VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
-    const void*                                 pNext                   /// Pointer to next structure
-    VkPipelineLayoutCreateFlags                 flags
-    u32                                         descriptorSetCount      /// Number of descriptor sets interfaced by the pipeline
-    const VkDescriptorSetLayout*                pSetLayouts             /// Array of <setCount> number of descriptor set layout objects defining the layout of the
-    u32                                         pushConstantRangeCount  /// Number of push-constant ranges used by the pipeline
-    const VkPushConstantRange*                  pPushConstantRanges     /// Array of pushConstantRangeCount number of ranges used by various shader stages
-}
-
-class VkSamplerCreateInfo {
-    VkStructureType                             sType          /// Must be VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO
-    const void*                                 pNext          /// Pointer to next structure
-    VkSamplerCreateFlags                        flags
-    VkFilter                                    magFilter      /// Filter mode for magnification
-    VkFilter                                    minFilter      /// Filter mode for minifiation
-    VkSamplerMipmapMode                         mipmapMode     /// Mipmap selection mode
-    VkSamplerAddressMode                        addressModeU
-    VkSamplerAddressMode                        addressModeV
-    VkSamplerAddressMode                        addressModeW
-    f32                                         mipLodBias
-    VkBool32                                    anisotropyEnable
-    f32                                         maxAnisotropy
-    VkBool32                                    compareEnable
-    VkCompareOp                                 compareOp
-    f32                                         minLod
-    f32                                         maxLod
-    VkBorderColor                               borderColor
-    VkBool32                                    unnormalizedCoordinates
-}
-
-class VkCommandPoolCreateInfo {
-    VkStructureType                             sType            /// Must be VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
-    const void*                                 pNext            /// Pointer to next structure
-    VkCommandPoolCreateFlags                    flags            /// Command pool creation flags
-    u32                                         queueFamilyIndex
-}
-
-class VkCommandBufferAllocateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkCommandPool                               commandPool
-    VkCommandBufferLevel                        level
-    u32                                         commandBufferCount
-}
-
-class VkCommandBufferInheritanceInfo {
-    VkStructureType                             sType       /// Must be VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO
-    const void*                                 pNext       /// Pointer to next structure
-    VkRenderPass                                renderPass  /// Render pass for secondary command buffers
-    u32                                         subpass
-    VkFramebuffer                               framebuffer /// Framebuffer for secondary command buffers
-    VkBool32                                    occlusionQueryEnable
-    VkQueryControlFlags                         queryFlags
-    VkQueryPipelineStatisticFlags               pipelineStatistics
-}
-
-class VkCommandBufferBeginInfo {
-    VkStructureType                             sType       /// Must be VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
-    const void*                                 pNext       /// Pointer to next structure
-    VkCommandBufferUsageFlags                   flags       /// Command buffer usage flags
-    const VkCommandBufferInheritanceInfo*       pInheritanceInfo
-}
-
-class VkRenderPassBeginInfo {
-    VkStructureType                             sType       /// Must be VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO
-    const void*                                 pNext       /// Pointer to next structure
-    VkRenderPass                                renderPass
-    VkFramebuffer                               framebuffer
-    VkRect2D                                    renderArea
-    u32                                         clearValueCount
-    const VkClearValue*                         pClearValues
-}
-
-@union
-/// Union allowing specification of floating point, integer, or unsigned integer color data. Actual value selected is based on image/attachment being cleared.
-class VkClearColorValue {
-    f32[4]                                      float32
-    s32[4]                                      int32
-    u32[4]                                      uint32
-}
-
-class VkClearDepthStencilValue {
-    f32                                         depth
-    u32                                         stencil
-}
-
-@union
-/// Union allowing specification of color, depth, and stencil color values. Actual value selected is based on attachment being cleared.
-class VkClearValue {
-    VkClearColorValue                           color
-    VkClearDepthStencilValue                    depthStencil
-}
-
-class VkClearAttachment {
-    VkImageAspectFlags                          aspectMask
-    u32                                         colorAttachment
-    VkClearValue                                clearValue
-}
-
-class VkAttachmentDescription {
-    VkAttachmentDescriptionFlags                flags
-    VkFormat                                    format
-    VkSampleCountFlagBits                       samples
-    VkAttachmentLoadOp                          loadOp          /// Load op for color or depth data
-    VkAttachmentStoreOp                         storeOp         /// Store op for color or depth data
-    VkAttachmentLoadOp                          stencilLoadOp   /// Load op for stencil data
-    VkAttachmentStoreOp                         stencilStoreOp  /// Store op for stencil data
-    VkImageLayout                               initialLayout
-    VkImageLayout                               finalLayout
-}
-
-class VkAttachmentReference {
-    u32                                         attachment
-    VkImageLayout                               layout
-}
-
-class VkSubpassDescription {
-    VkSubpassDescriptionFlags                   flags
-    VkPipelineBindPoint                         pipelineBindPoint  /// Must be VK_PIPELINE_BIND_POINT_GRAPHICS for now
-    u32                                         inputAttachmentCount
-    const VkAttachmentReference*                pInputAttachments
-    u32                                         colorAttachmentCount
-    const VkAttachmentReference*                pColorAttachments
-    const VkAttachmentReference*                pResolveAttachments
-    const VkAttachmentReference*                pDepthStencilAttachment
-    u32                                         preserveAttachmentCount
-    const u32*                                  pPreserveAttachments
-}
-
-class VkSubpassDependency {
-    u32                                         srcSubpass
-    u32                                         dstSubpass
-    VkPipelineStageFlags                        srcStageMask
-    VkPipelineStageFlags                        dstStageMask
-    VkAccessFlags                               srcAccessMask
-    VkAccessFlags                               dstAccessMask
-    VkDependencyFlags                           dependencyFlags
-}
-
-class VkRenderPassCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkRenderPassCreateFlags                     flags
-    u32                                         attachmentCount
-    const VkAttachmentDescription*              pAttachments
-    u32                                         subpassCount
-    const VkSubpassDescription*                 pSubpasses
-    u32                                         dependencyCount
-    const VkSubpassDependency*                  pDependencies
-}
-
-class VkEventCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_EVENT_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkEventCreateFlags                          flags      /// Event creation flags
-}
-
-class VkFenceCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkFenceCreateFlags                          flags      /// Fence creation flags
-}
-
-class VkPhysicalDeviceFeatures {
-    VkBool32                                    robustBufferAccess                        /// out of bounds buffer accesses are well defined
-    VkBool32                                    fullDrawIndexUint32                       /// full 32-bit range of indices for indexed draw calls
-    VkBool32                                    imageCubeArray                            /// image views which are arrays of cube maps
-    VkBool32                                    independentBlend                          /// blending operations are controlled per-attachment
-    VkBool32                                    geometryShader                            /// geometry stage
-    VkBool32                                    tessellationShader                        /// tessellation control and evaluation stage
-    VkBool32                                    sampleRateShading                         /// per-sample shading and interpolation
-    VkBool32                                    dualSrcBlend                              /// blend operations which take two sources
-    VkBool32                                    logicOp                                   /// logic operations
-    VkBool32                                    multiDrawIndirect                         /// multi draw indirect
-    VkBool32                                    drawIndirectFirstInstance
-    VkBool32                                    depthClamp                                /// depth clamping
-    VkBool32                                    depthBiasClamp                            /// depth bias clamping
-    VkBool32                                    fillModeNonSolid                          /// point and wireframe fill modes
-    VkBool32                                    depthBounds                               /// depth bounds test
-    VkBool32                                    wideLines                                 /// lines with width greater than 1
-    VkBool32                                    largePoints                               /// points with size greater than 1
-    VkBool32                                    alphaToOne                                /// The fragment alpha channel can be forced to maximum representable alpha value
-    VkBool32                                    multiViewport
-    VkBool32                                    samplerAnisotropy
-    VkBool32                                    textureCompressionETC2                    /// ETC texture compression formats
-    VkBool32                                    textureCompressionASTC_LDR                /// ASTC LDR texture compression formats
-    VkBool32                                    textureCompressionBC                      /// BC1-7 texture compressed formats
-    VkBool32                                    occlusionQueryPrecise
-    VkBool32                                    pipelineStatisticsQuery                   /// pipeline statistics query
-    VkBool32                                    vertexPipelineStoresAndAtomics
-    VkBool32                                    fragmentStoresAndAtomics
-    VkBool32                                    shaderTessellationAndGeometryPointSize
-    VkBool32                                    shaderImageGatherExtended                 /// texture gather with run-time values and independent offsets
-    VkBool32                                    shaderStorageImageExtendedFormats         /// the extended set of formats can be used for storage images
-    VkBool32                                    shaderStorageImageMultisample             /// multisample images can be used for storage images
-    VkBool32                                    shaderStorageImageReadWithoutFormat
-    VkBool32                                    shaderStorageImageWriteWithoutFormat
-    VkBool32                                    shaderUniformBufferArrayDynamicIndexing   /// arrays of uniform buffers can be accessed with dynamically uniform indices
-    VkBool32                                    shaderSampledImageArrayDynamicIndexing    /// arrays of sampled images can be accessed with dynamically uniform indices
-    VkBool32                                    shaderStorageBufferArrayDynamicIndexing   /// arrays of storage buffers can be accessed with dynamically uniform indices
-    VkBool32                                    shaderStorageImageArrayDynamicIndexing    /// arrays of storage images can be accessed with dynamically uniform indices
-    VkBool32                                    shaderClipDistance                        /// clip distance in shaders
-    VkBool32                                    shaderCullDistance                        /// cull distance in shaders
-    VkBool32                                    shaderFloat64                             /// 64-bit floats (doubles) in shaders
-    VkBool32                                    shaderInt64                               /// 64-bit integers in shaders
-    VkBool32                                    shaderInt16                               /// 16-bit integers in shaders
-    VkBool32                                    shaderResourceResidency                   /// shader can use texture operations that return resource residency information (requires sparseNonResident support)
-    VkBool32                                    shaderResourceMinLod                      /// shader can use texture operations that specify minimum resource LOD
-    VkBool32                                    sparseBinding                             /// Sparse resources support: Resource memory can be managed at opaque page level rather than object level
-    VkBool32                                    sparseResidencyBuffer                     /// Sparse resources support: GPU can access partially resident buffers
-    VkBool32                                    sparseResidencyImage2D                    /// Sparse resources support: GPU can access partially resident 2D (non-MSAA non-DepthStencil) images
-    VkBool32                                    sparseResidencyImage3D                    /// Sparse resources support: GPU can access partially resident 3D images
-    VkBool32                                    sparseResidency2Samples                   /// Sparse resources support: GPU can access partially resident MSAA 2D images with 2 samples
-    VkBool32                                    sparseResidency4Samples                   /// Sparse resources support: GPU can access partially resident MSAA 2D images with 4 samples
-    VkBool32                                    sparseResidency8Samples                   /// Sparse resources support: GPU can access partially resident MSAA 2D images with 8 samples
-    VkBool32                                    sparseResidency16Samples                  /// Sparse resources support: GPU can access partially resident MSAA 2D images with 16 samples
-    VkBool32                                    sparseResidencyAliased                    /// Sparse resources support: GPU can correctly access data aliased into multiple locations (opt-in)
-    VkBool32                                    variableMultisampleRate
-    VkBool32                                    inheritedQueries
-}
-
-class VkPhysicalDeviceLimits {
-    /// resource maximum sizes
-    u32                                         maxImageDimension1D                       /// max 1D image dimension
-    u32                                         maxImageDimension2D                       /// max 2D image dimension
-    u32                                         maxImageDimension3D                       /// max 3D image dimension
-    u32                                         maxImageDimensionCube                     /// max cubemap image dimension
-    u32                                         maxImageArrayLayers                       /// max layers for image arrays
-    u32                                         maxTexelBufferElements
-    u32                                         maxUniformBufferRange                     /// max uniform buffer size (bytes)
-    u32                                         maxStorageBufferRange                     /// max storage buffer size (bytes)
-    u32                                         maxPushConstantsSize                      /// max size of the push constants pool (bytes)
-    /// memory limits
-    u32                                         maxMemoryAllocationCount                  /// max number of device memory allocations supported
-    u32                                         maxSamplerAllocationCount
-    VkDeviceSize                                bufferImageGranularity                    /// Granularity (in bytes) at which buffers and images can be bound to adjacent memory for simultaneous usage
-    VkDeviceSize                                sparseAddressSpaceSize                    /// Total address space available for sparse allocations (bytes)
-    /// descriptor set limits
-    u32                                         maxBoundDescriptorSets                    /// max number of descriptors sets that can be bound to a pipeline
-    u32                                         maxPerStageDescriptorSamplers             /// max num of samplers allowed per-stage in a descriptor set
-    u32                                         maxPerStageDescriptorUniformBuffers       /// max num of uniform buffers allowed per-stage in a descriptor set
-    u32                                         maxPerStageDescriptorStorageBuffers       /// max num of storage buffers allowed per-stage in a descriptor set
-    u32                                         maxPerStageDescriptorSampledImages        /// max num of sampled images allowed per-stage in a descriptor set
-    u32                                         maxPerStageDescriptorStorageImages        /// max num of storage images allowed per-stage in a descriptor set
-    u32                                         maxPerStageDescriptorInputAttachments
-    u32                                         maxPerStageResources
-    u32                                         maxDescriptorSetSamplers                  /// max num of samplers allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetUniformBuffers            /// max num of uniform buffers allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetUniformBuffersDynamic     /// max num of dynamic uniform buffers allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetStorageBuffers            /// max num of storage buffers allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetStorageBuffersDynamic     /// max num of dynamic storage buffers allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetSampledImages             /// max num of sampled images allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetStorageImages             /// max num of storage images allowed in all stages in a descriptor set
-    u32                                         maxDescriptorSetInputAttachments
-    /// vertex stage limits
-    u32                                         maxVertexInputAttributes                  /// max num of vertex input attribute slots
-    u32                                         maxVertexInputBindings                    /// max num of vertex input binding slots
-    u32                                         maxVertexInputAttributeOffset             /// max vertex input attribute offset added to vertex buffer offset
-    u32                                         maxVertexInputBindingStride               /// max vertex input binding stride
-    u32                                         maxVertexOutputComponents                 /// max num of output components written by vertex shader
-    /// tessellation control stage limits
-    u32                                         maxTessellationGenerationLevel                  /// max level supported by tess primitive generator
-    u32                                         maxTessellationPatchSize                        /// max patch size (vertices)
-    u32                                         maxTessellationControlPerVertexInputComponents  /// max num of input components per-vertex in TCS
-    u32                                         maxTessellationControlPerVertexOutputComponents /// max num of output components per-vertex in TCS
-    u32                                         maxTessellationControlPerPatchOutputComponents  /// max num of output components per-patch in TCS
-    u32                                         maxTessellationControlTotalOutputComponents     /// max total num of per-vertex and per-patch output components in TCS
-    u32                                         maxTessellationEvaluationInputComponents        /// max num of input components per vertex in TES
-    u32                                         maxTessellationEvaluationOutputComponents       /// max num of output components per vertex in TES
-    /// geometry stage limits
-    u32                                         maxGeometryShaderInvocations              /// max invocation count supported in geometry shader
-    u32                                         maxGeometryInputComponents                /// max num of input components read in geometry stage
-    u32                                         maxGeometryOutputComponents               /// max num of output components written in geometry stage
-    u32                                         maxGeometryOutputVertices                 /// max num of vertices that can be emitted in geometry stage
-    u32                                         maxGeometryTotalOutputComponents          /// max total num of components (all vertices) written in geometry stage
-    /// fragment stage limits
-    u32                                         maxFragmentInputComponents                /// max num of input compontents read in fragment stage
-    u32                                         maxFragmentOutputAttachments              /// max num of output attachments written in fragment stage
-    u32                                         maxFragmentDualSrcAttachments             /// max num of output attachments written when using dual source blending
-    u32                                         maxFragmentCombinedOutputResources        /// max total num of storage buffers, storage images and output buffers
-    /// compute stage limits
-    u32                                         maxComputeSharedMemorySize                /// max total storage size of work group local storage (bytes)
-    u32[3]                                      maxComputeWorkGroupCount                  /// max num of compute work groups that may be dispatched by a single command (x,y,z)
-    u32                                         maxComputeWorkGroupInvocations            /// max total compute invocations in a single local work group
-    u32[3]                                      maxComputeWorkGroupSize                   /// max local size of a compute work group (x,y,z)
-
-    u32                                         subPixelPrecisionBits                     /// num bits of subpixel precision in screen x and y
-    u32                                         subTexelPrecisionBits                     /// num bits of subtexel precision
-    u32                                         mipmapPrecisionBits                       /// num bits of mipmap precision
-
-    u32                                         maxDrawIndexedIndexValue                  /// max index value for indexed draw calls (for 32-bit indices)
-    u32                                         maxDrawIndirectCount
-
-    f32                                         maxSamplerLodBias                         /// max absolute sampler level of detail bias
-    f32                                         maxSamplerAnisotropy                      /// max degree of sampler anisotropy
-
-    u32                                         maxViewports                              /// max number of active viewports
-    u32[2]                                      maxViewportDimensions                     /// max viewport dimensions (x,y)
-    f32[2]                                      viewportBoundsRange                       /// viewport bounds range (min,max)
-    u32                                         viewportSubPixelBits                      /// num bits of subpixel precision for viewport
-
-    platform.size_t                             minMemoryMapAlignment                     /// min required alignment of pointers returned by MapMemory (bytes)
-    VkDeviceSize                                minTexelBufferOffsetAlignment             /// min required alignment for texel buffer offsets (bytes)
-    VkDeviceSize                                minUniformBufferOffsetAlignment           /// min required alignment for uniform buffer sizes and offsets (bytes)
-    VkDeviceSize                                minStorageBufferOffsetAlignment           /// min required alignment for storage buffer offsets (bytes)
-
-    s32                                         minTexelOffset                            /// min texel offset for OpTextureSampleOffset
-    u32                                         maxTexelOffset                            /// max texel offset for OpTextureSampleOffset
-    s32                                         minTexelGatherOffset                      /// min texel offset for OpTextureGatherOffset
-    u32                                         maxTexelGatherOffset                      /// max texel offset for OpTextureGatherOffset
-    f32                                         minInterpolationOffset                    /// furthest negative offset for interpolateAtOffset
-    f32                                         maxInterpolationOffset                    /// furthest positive offset for interpolateAtOffset
-    u32                                         subPixelInterpolationOffsetBits           /// num of subpixel bits for interpolateAtOffset
-
-    u32                                         maxFramebufferWidth                       /// max width for a framebuffer
-    u32                                         maxFramebufferHeight                      /// max height for a framebuffer
-    u32                                         maxFramebufferLayers                      /// max layer count for a layered framebuffer
-    VkSampleCountFlags                          framebufferColorSampleCounts
-    VkSampleCountFlags                          framebufferDepthSampleCounts
-    VkSampleCountFlags                          framebufferStencilSampleCounts
-    VkSampleCountFlags                          framebufferNoAttachmentSampleCounts
-    u32                                         maxColorAttachments                       /// max num of framebuffer color attachments
-
-    VkSampleCountFlags                          sampledImageColorSampleCounts
-    VkSampleCountFlags                          sampledImageIntegerSampleCounts
-    VkSampleCountFlags                          sampledImageDepthSampleCounts
-    VkSampleCountFlags                          sampledImageStencilSampleCounts
-    VkSampleCountFlags                          storageImageSampleCounts
-    u32                                         maxSampleMaskWords                        /// max num of sample mask words
-    VkBool32                                    timestampComputeAndGraphics
-
-    f32                                         timestampPeriod
-
-    u32                                         maxClipDistances                          /// max number of clip distances
-    u32                                         maxCullDistances                          /// max number of cull distances
-    u32                                         maxCombinedClipAndCullDistances           /// max combined number of user clipping
-
-    u32                                         discreteQueuePriorities
-
-    f32[2]                                      pointSizeRange                            /// range (min,max) of supported point sizes
-    f32[2]                                      lineWidthRange                            /// range (min,max) of supported line widths
-    f32                                         pointSizeGranularity                      /// granularity of supported point sizes
-    f32                                         lineWidthGranularity                      /// granularity of supported line widths
-    VkBool32                                    strictLines
-    VkBool32                                    standardSampleLocations
-
-    VkDeviceSize                                optimalBufferCopyOffsetAlignment
-    VkDeviceSize                                optimalBufferCopyRowPitchAlignment
-    VkDeviceSize                                nonCoherentAtomSize
-}
-
-class VkPhysicalDeviceSparseProperties {
-    VkBool32                                    residencyStandard2DBlockShape             /// Sparse resources support: GPU will access all 2D (single sample) sparse resources using the standard block shapes (based on pixel format)
-    VkBool32                                    residencyStandard2DMultisampleBlockShape  /// Sparse resources support: GPU will access all 2D (multisample) sparse resources using the standard block shapes (based on pixel format)
-    VkBool32                                    residencyStandard3DBlockShape             /// Sparse resources support: GPU will access all 3D sparse resources using the standard block shapes (based on pixel format)
-    VkBool32                                    residencyAlignedMipSize                   /// Sparse resources support: Images with mip-level dimensions that are NOT a multiple of the block size will be placed in the mip tail
-    VkBool32                                    residencyNonResidentStrict                /// Sparse resources support: GPU can safely access non-resident regions of a resource, all reads return as if data is 0, writes are discarded
-}
-
-class VkSemaphoreCreateInfo {
-    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
-    const void*                                 pNext      /// Pointer to next structure
-    VkSemaphoreCreateFlags                      flags      /// Semaphore creation flags
-}
-
-class VkQueryPoolCreateInfo {
-    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO
-    const void*                                 pNext              /// Pointer to next structure
-    VkQueryPoolCreateFlags                      flags
-    VkQueryType                                 queryType
-    u32                                         queryCount
-    VkQueryPipelineStatisticFlags               pipelineStatistics /// Optional
-}
-
-class VkFramebufferCreateInfo {
-    VkStructureType                             sType  /// Must be VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
-    const void*                                 pNext  /// Pointer to next structure
-    VkFramebufferCreateFlags                    flags
-    VkRenderPass                                renderPass
-    u32                                         attachmentCount
-    const VkImageView*                          pAttachments
-    u32                                         width
-    u32                                         height
-    u32                                         layers
-}
-
-class VkDrawIndirectCommand {
-    u32                                         vertexCount
-    u32                                         instanceCount
-    u32                                         firstVertex
-    u32                                         firstInstance
-}
-
-class VkDrawIndexedIndirectCommand {
-    u32                                         indexCount
-    u32                                         instanceCount
-    u32                                         firstIndex
-    s32                                         vertexOffset
-    u32                                         firstInstance
-}
-
-class VkDispatchIndirectCommand {
-    u32                                         x
-    u32                                         y
-    u32                                         z
-}
-
-class VkBaseOutStructure {
-    VkStructureType                             sType
-    void*                                       pNext
-}
-
-class VkBaseInStructure {
-    VkStructureType                             sType
-    const void*                                 pNext
-}
-
-//@vulkan1_1 structures
-
-class VkPhysicalDeviceSubgroupProperties {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         subgroupSize
-    VkShaderStageFlags                          supportedStages
-    VkSubgroupFeatureFlags                      supportedOperations
-    VkBool32                                    quadOperationsInAllStages
-}
-
-class VkBindBufferMemoryInfo {
-    VkStructureType    sType
-    const void*        pNext
-    VkBuffer           buffer
-    VkDeviceMemory     memory
-    VkDeviceSize       memoryOffset
-}
-
-class VkBindImageMemoryInfo {
-    VkStructureType    sType
-    const void*        pNext
-    VkImage            image
-    VkDeviceMemory     memory
-    VkDeviceSize       memoryOffset
-}
-
-class VkPhysicalDevice16BitStorageFeatures {
-    VkStructureType    sType
-    void*              pNext
-    VkBool32           storageBuffer16BitAccess
-    VkBool32           uniformAndStorageBuffer16BitAccess
-    VkBool32           storagePushConstant16
-    VkBool32           storageInputOutput16
-}
-
-class VkMemoryDedicatedRequirements {
-    VkStructureType    sType
-    void*              pNext
-    VkBool32           prefersDedicatedAllocation
-    VkBool32           requiresDedicatedAllocation
-}
-
-class VkMemoryDedicatedAllocateInfo {
-    VkStructureType    sType
-    const void*        pNext
-    VkImage            image
-    VkBuffer           buffer
-}
-
-class VkMemoryAllocateFlagsInfo {
-    VkStructureType          sType
-    const void*              pNext
-    VkMemoryAllocateFlags    flags
-    u32                      deviceMask
-}
-
-class VkDeviceGroupRenderPassBeginInfo {
-    VkStructureType    sType
-    const void*        pNext
-    u32                deviceMask
-    u32                deviceRenderAreaCount
-    const VkRect2D*    pDeviceRenderAreas
-}
-
-class VkDeviceGroupCommandBufferBeginInfo {
-    VkStructureType    sType
-    const void*        pNext
-    u32                deviceMask
-}
-
-class VkDeviceGroupSubmitInfo {
-    VkStructureType             sType
-    const void*                 pNext
-    u32                         waitSemaphoreCount
-    const u32*                  pWaitSemaphoreDeviceIndices
-    u32                         commandBufferCount
-    const u32*                  pCommandBufferDeviceMasks
-    u32                         signalSemaphoreCount
-    const u32*                  pSignalSemaphoreDeviceIndices
-}
-
-class VkDeviceGroupBindSparseInfo {
-    VkStructureType    sType
-    const void*        pNext
-    u32                resourceDeviceIndex
-    u32                memoryDeviceIndex
-}
-
-class VkBindBufferMemoryDeviceGroupInfo {
-    VkStructureType                     sType
-    const void*                         pNext
-    u32                                 deviceIndexCount
-    const u32*                          pDeviceIndices
-}
-
-class VkBindImageMemoryDeviceGroupInfo {
-    VkStructureType                     sType
-    const void*                         pNext
-    u32                                 deviceIndexCount
-    const u32*                          pDeviceIndices
-    u32                                 splitInstanceBindRegionCount
-    const VkRect2D*                     pSplitInstanceBindRegions
-}
-
-class VkPhysicalDeviceGroupProperties {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         physicalDeviceCount
-    VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE]  physicalDevices
-    VkBool32                                    subsetAllocation
-}
-
-class VkDeviceGroupDeviceCreateInfo {
-    VkStructureType            sType
-    const void*                pNext
-    u32                        physicalDeviceCount
-    const VkPhysicalDevice*    pPhysicalDevices
-}
-
-class VkBufferMemoryRequirementsInfo2 {
-    VkStructureType    sType
-    const void*        pNext
-    VkBuffer           buffer
-}
-
-class VkImageMemoryRequirementsInfo2 {
-    VkStructureType    sType
-    const void*        pNext
-    VkImage            image
-}
-
-class VkImageSparseMemoryRequirementsInfo2 {
-    VkStructureType    sType
-    const void*        pNext
-    VkImage            image
-}
-
-class VkMemoryRequirements2 {
-    VkStructureType         sType
-    void*                   pNext
-    VkMemoryRequirements    memoryRequirements
-}
-
-class VkSparseImageMemoryRequirements2 {
-    VkStructureType                    sType
-    void*                              pNext
-    VkSparseImageMemoryRequirements    memoryRequirements
-}
-
-class VkPhysicalDeviceFeatures2 {
-    VkStructureType             sType
-    void*                       pNext
-    VkPhysicalDeviceFeatures    features
-}
-
-class VkPhysicalDeviceProperties2 {
-    VkStructureType               sType
-    void*                         pNext
-    VkPhysicalDeviceProperties    properties
-}
-
-class VkFormatProperties2 {
-    VkStructureType       sType
-    void*                 pNext
-    VkFormatProperties    formatProperties
-}
-
-class VkImageFormatProperties2 {
-    VkStructureType            sType
-    void*                      pNext
-    VkImageFormatProperties    imageFormatProperties
-}
-
-class VkPhysicalDeviceImageFormatInfo2 {
-    VkStructureType       sType
-    const void*           pNext
-    VkFormat              format
-    VkImageType           type
-    VkImageTiling         tiling
-    VkImageUsageFlags     usage
-    VkImageCreateFlags    flags
-}
-
-class VkQueueFamilyProperties2 {
-    VkStructureType            sType
-    void*                      pNext
-    VkQueueFamilyProperties    queueFamilyProperties
-}
-
-class VkPhysicalDeviceMemoryProperties2 {
-    VkStructureType                     sType
-    void*                               pNext
-    VkPhysicalDeviceMemoryProperties    memoryProperties
-}
-
-class VkSparseImageFormatProperties2 {
-    VkStructureType                  sType
-    void*                            pNext
-    VkSparseImageFormatProperties    properties
-}
-
-class VkPhysicalDeviceSparseImageFormatInfo2 {
-    VkStructureType          sType
-    const void*              pNext
-    VkFormat                 format
-    VkImageType              type
-    VkSampleCountFlagBits    samples
-    VkImageUsageFlags        usage
-    VkImageTiling            tiling
-}
-
-class VkPhysicalDevicePointClippingProperties {
-    VkStructureType            sType
-    void*                      pNext
-    VkPointClippingBehavior    pointClippingBehavior
-}
-
-class VkInputAttachmentAspectReference {
-    u32                   subpass
-    u32                   inputAttachmentIndex
-    VkImageAspectFlags    aspectMask
-}
-
-class VkRenderPassInputAttachmentAspectCreateInfo {
-    VkStructureType                            sType
-    const void*                                pNext
-    u32                                        aspectReferenceCount
-    const VkInputAttachmentAspectReference*    pAspectReferences
-}
-
-class VkImageViewUsageCreateInfo {
-    VkStructureType      sType
-    const void*          pNext
-    VkImageUsageFlags    usage
-}
-
-class VkPipelineTessellationDomainOriginStateCreateInfo {
-    VkStructureType               sType
-    const void*                   pNext
-    VkTessellationDomainOrigin    domainOrigin
-}
-
-class VkRenderPassMultiviewCreateInfo {
-    VkStructureType    sType
-    const void*        pNext
-    u32                subpassCount
-    const u32*         pViewMasks
-    u32                dependencyCount
-    const s32*         pViewOffsets
-    u32                correlationMaskCount
-    const u32*         pCorrelationMasks
-}
-
-class VkPhysicalDeviceMultiviewFeatures {
-    VkStructureType    sType
-    void*              pNext
-    VkBool32           multiview
-    VkBool32           multiviewGeometryShader
-    VkBool32           multiviewTessellationShader
-}
-
-class VkPhysicalDeviceMultiviewProperties {
-    VkStructureType    sType
-    void*              pNext
-    u32                maxMultiviewViewCount
-    u32                maxMultiviewInstanceIndex
-}
-
-class VkPhysicalDeviceVariablePointerFeatures {
-    VkStructureType    sType
-    void*              pNext
-    VkBool32           variablePointersStorageBuffer
-    VkBool32           variablePointers
-}
-
-class VkPhysicalDeviceProtectedMemoryFeatures {
-    VkStructureType    sType
-    void*              pNext
-    VkBool32           protectedMemory
-}
-
-class VkPhysicalDeviceProtectedMemoryProperties {
-    VkStructureType    sType
-    void*              pNext
-    VkBool32           protectedNoFault
-}
-
-class VkDeviceQueueInfo2 {
-    VkStructureType             sType
-    const void*                 pNext
-    VkDeviceQueueCreateFlags    flags
-    u32                         queueFamilyIndex
-    u32                         queueIndex
-}
-
-class VkProtectedSubmitInfo {
-    VkStructureType    sType
-    const void*        pNext
-    VkBool32           protectedSubmit
-}
-
-class VkSamplerYcbcrConversionCreateInfo {
-    VkStructureType                  sType
-    const void*                      pNext
-    VkFormat                         format
-    VkSamplerYcbcrModelConversion    ycbcrModel
-    VkSamplerYcbcrRange              ycbcrRange
-    VkComponentMapping               components
-    VkChromaLocation                 xChromaOffset
-    VkChromaLocation                 yChromaOffset
-    VkFilter                         chromaFilter
-    VkBool32                         forceExplicitReconstruction
-}
-
-class VkSamplerYcbcrConversionInfo {
-    VkStructureType             sType
-    const void*                 pNext
-    VkSamplerYcbcrConversion    conversion
-}
-
-class VkBindImagePlaneMemoryInfo {
-    VkStructureType          sType
-    const void*              pNext
-    VkImageAspectFlagBits    planeAspect
-}
-
-class VkImagePlaneMemoryRequirementsInfo {
-    VkStructureType          sType
-    const void*              pNext
-    VkImageAspectFlagBits    planeAspect
-}
-
-class VkPhysicalDeviceSamplerYcbcrConversionFeatures {
-    VkStructureType    sType
-    void*              pNext
-    VkBool32           samplerYcbcrConversion
-}
-
-class VkSamplerYcbcrConversionImageFormatProperties {
-    VkStructureType    sType
-    void*              pNext
-    u32                combinedImageSamplerDescriptorCount
-}
-
-class VkDescriptorUpdateTemplateEntry {
-    u32                                 dstBinding
-    u32                                 dstArrayElement
-    u32                                 descriptorCount
-    VkDescriptorType                    descriptorType
-    platform.size_t                     offset
-    platform.size_t                     stride
-}
-
-class VkDescriptorUpdateTemplateCreateInfo {
-    VkStructureType                           sType
-    const void*                               pNext
-    VkDescriptorUpdateTemplateCreateFlags     flags
-    u32                                       descriptorUpdateEntryCount
-    const VkDescriptorUpdateTemplateEntry*    pDescriptorUpdateEntries
-    VkDescriptorUpdateTemplateType            templateType
-    VkDescriptorSetLayout                     descriptorSetLayout
-    VkPipelineBindPoint                       pipelineBindPoint
-    VkPipelineLayout                          pipelineLayout
-    u32                                       set
-}
-
-class VkExternalMemoryProperties {
-    VkExternalMemoryFeatureFlags       externalMemoryFeatures
-    VkExternalMemoryHandleTypeFlags    exportFromImportedHandleTypes
-    VkExternalMemoryHandleTypeFlags    compatibleHandleTypes
-}
-
-class VkPhysicalDeviceExternalImageFormatInfo {
-    VkStructureType                       sType
-    const void*                           pNext
-    VkExternalMemoryHandleTypeFlagBits    handleType
-}
-
-class VkExternalImageFormatProperties {
-    VkStructureType               sType
-    void*                         pNext
-    VkExternalMemoryProperties    externalMemoryProperties
-}
-
-class VkPhysicalDeviceExternalBufferInfo {
-    VkStructureType                       sType
-    const void*                           pNext
-    VkBufferCreateFlags                   flags
-    VkBufferUsageFlags                    usage
-    VkExternalMemoryHandleTypeFlagBits    handleType
-}
-
-class VkExternalBufferProperties {
-    VkStructureType               sType
-    void*                         pNext
-    VkExternalMemoryProperties    externalMemoryProperties
-}
-
-class VkPhysicalDeviceIDProperties {
-    VkStructureType    sType
-    void*              pNext
-    u8[VK_UUID_SIZE]   deviceUUID
-    u8[VK_UUID_SIZE]   driverUUID
-    u8[VK_LUID_SIZE]   deviceLUID
-    u32                deviceNodeMask
-    VkBool32           deviceLUIDValid
-}
-
-class VkExternalMemoryImageCreateInfo {
-    VkStructureType                    sType
-    const void*                        pNext
-    VkExternalMemoryHandleTypeFlags    handleTypes
-}
-
-class VkExternalMemoryBufferCreateInfo {
-    VkStructureType                    sType
-    const void*                        pNext
-    VkExternalMemoryHandleTypeFlags    handleTypes
-}
-
-class VkExportMemoryAllocateInfo {
-    VkStructureType                    sType
-    const void*                        pNext
-    VkExternalMemoryHandleTypeFlags    handleTypes
-}
-
-class VkPhysicalDeviceExternalFenceInfo {
-    VkStructureType                      sType
-    const void*                          pNext
-    VkExternalFenceHandleTypeFlagBits    handleType
-}
-
-class VkExternalFenceProperties {
-    VkStructureType                   sType
-    void*                             pNext
-    VkExternalFenceHandleTypeFlags    exportFromImportedHandleTypes
-    VkExternalFenceHandleTypeFlags    compatibleHandleTypes
-    VkExternalFenceFeatureFlags       externalFenceFeatures
-}
-
-class VkExportFenceCreateInfo {
-    VkStructureType                   sType
-    const void*                       pNext
-    VkExternalFenceHandleTypeFlags    handleTypes
-}
-
-class VkExportSemaphoreCreateInfo {
-    VkStructureType                       sType
-    const void*                           pNext
-    VkExternalSemaphoreHandleTypeFlags    handleTypes
-}
-
-class VkPhysicalDeviceExternalSemaphoreInfo {
-    VkStructureType                          sType
-    const void*                              pNext
-    VkExternalSemaphoreHandleTypeFlagBits    handleType
-}
-
-class VkExternalSemaphoreProperties {
-    VkStructureType                       sType
-    void*                                 pNext
-    VkExternalSemaphoreHandleTypeFlags    exportFromImportedHandleTypes
-    VkExternalSemaphoreHandleTypeFlags    compatibleHandleTypes
-    VkExternalSemaphoreFeatureFlags       externalSemaphoreFeatures
-}
-
-class VkPhysicalDeviceMaintenance3Properties {
-    VkStructureType    sType
-    void*              pNext
-    u32                maxPerSetDescriptors
-    VkDeviceSize       maxMemoryAllocationSize
-}
-
-class VkDescriptorSetLayoutSupport {
-    VkStructureType    sType
-    void*              pNext
-    VkBool32           supported
-}
-
-class VkPhysicalDeviceShaderDrawParameterFeatures {
-    VkStructureType    sType
-    void*              pNext
-    VkBool32           shaderDrawParameters
-}
-
-
-@extension("VK_KHR_surface") // 1
-class VkSurfaceCapabilitiesKHR {
-    u32                                         minImageCount
-    u32                                         maxImageCount
-    VkExtent2D                                  currentExtent
-    VkExtent2D                                  minImageExtent
-    VkExtent2D                                  maxImageExtent
-    u32                                         maxImageArrayLayers
-    VkSurfaceTransformFlagsKHR                  supportedTransforms
-    VkSurfaceTransformFlagBitsKHR               currentTransform
-    VkCompositeAlphaFlagsKHR                    supportedCompositeAlpha
-    VkImageUsageFlags                           supportedUsageFlags
-}
-
-@extension("VK_KHR_surface") // 1
-class VkSurfaceFormatKHR {
-    VkFormat                                    format
-    VkColorSpaceKHR                             colorSpace
-}
-
-@extension("VK_KHR_swapchain") // 2
-class VkSwapchainCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSwapchainCreateFlagsKHR                   flags
-    VkSurfaceKHR                                surface
-    u32                                         minImageCount
-    VkFormat                                    imageFormat
-    VkColorSpaceKHR                             imageColorSpace
-    VkExtent2D                                  imageExtent
-    u32                                         imageArrayLayers
-    VkImageUsageFlags                           imageUsage
-    VkSharingMode                               sharingMode
-    u32                                         queueFamilyIndexCount
-    const u32*                                  pQueueFamilyIndices
-    VkSurfaceTransformFlagBitsKHR               preTransform
-    VkCompositeAlphaFlagBitsKHR                 compositeAlpha
-    VkPresentModeKHR                            presentMode
-    VkBool32                                    clipped
-    VkSwapchainKHR                              oldSwapchain
-}
-
-@extension("VK_KHR_swapchain") // 2
-class VkPresentInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         waitSemaphoreCount
-    const VkSemaphore*                          pWaitSemaphores
-    u32                                         swapchainCount
-    const VkSwapchainKHR*                       pSwapchains
-    const u32*                                  pImageIndices
-    VkResult*                                   pResults
-}
-
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-class VkImageSwapchainCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSwapchainKHR                              swapchain
-}
-
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-class VkBindImageMemorySwapchainInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSwapchainKHR                              swapchain
-    u32                                         imageIndex
-}
-
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-class VkAcquireNextImageInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSwapchainKHR                              swapchain
-    u64                                         timeout
-    VkSemaphore                                 semaphore
-    VkFence                                     fence
-    u32                                         deviceMask
-}
-
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-class VkDeviceGroupPresentCapabilitiesKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32[VK_MAX_DEVICE_GROUP_SIZE]               presentMask
-    VkDeviceGroupPresentModeFlagsKHR            modes
-}
-
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-class VkDeviceGroupPresentInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         swapchainCount
-    const u32*                                  pDeviceMasks
-    VkDeviceGroupPresentModeFlagBitsKHR         mode
-}
-
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-class VkDeviceGroupSwapchainCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDeviceGroupPresentModeFlagsKHR            modes
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplayPropertiesKHR {
-    VkDisplayKHR                                display
-    const char*                                 displayName
-    VkExtent2D                                  physicalDimensions
-    VkExtent2D                                  physicalResolution
-    VkSurfaceTransformFlagsKHR                  supportedTransforms
-    VkBool32                                    planeReorderPossible
-    VkBool32                                    persistentContent
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplayModeParametersKHR {
-    VkExtent2D                                  visibleRegion
-    u32                                         refreshRate
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplayModePropertiesKHR {
-    VkDisplayModeKHR                            displayMode
-    VkDisplayModeParametersKHR                  parameters
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplayModeCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDisplayModeCreateFlagsKHR                 flags
-    VkDisplayModeParametersKHR                  parameters
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplayPlanePropertiesKHR {
-    VkDisplayKHR                                currentDisplay
-    u32                                         currentStackIndex
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplayPlaneCapabilitiesKHR {
-    VkDisplayPlaneAlphaFlagsKHR                 supportedAlpha
-    VkOffset2D                                  minSrcPosition
-    VkOffset2D                                  maxSrcPosition
-    VkExtent2D                                  minSrcExtent
-    VkExtent2D                                  maxSrcExtent
-    VkOffset2D                                  minDstPosition
-    VkOffset2D                                  maxDstPosition
-    VkExtent2D                                  minDstExtent
-    VkExtent2D                                  maxDstExtent
-}
-
-@extension("VK_KHR_display") // 3
-class VkDisplaySurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDisplaySurfaceCreateFlagsKHR              flags
-    VkDisplayModeKHR                            displayMode
-    u32                                         planeIndex
-    u32                                         planeStackIndex
-    VkSurfaceTransformFlagBitsKHR               transform
-    f32                                         globalAlpha
-    VkDisplayPlaneAlphaFlagBitsKHR              alphaMode
-    VkExtent2D                                  imageExtent
-}
-
-@extension("VK_KHR_display_swapchain") // 4
-class VkDisplayPresentInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkRect2D                                    srcRect
-    VkRect2D                                    dstRect
-    VkBool32                                    persistent
-}
-
-@extension("VK_KHR_xlib_surface") // 5
-class VkXlibSurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkXlibSurfaceCreateFlagsKHR                 flags
-    platform.Display*                           dpy
-    platform.Window                             window
-}
-
-@extension("VK_KHR_xcb_surface") // 6
-class VkXcbSurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkXcbSurfaceCreateFlagsKHR                  flags
-    platform.xcb_connection_t*                  connection
-    platform.xcb_window_t                       window
-}
-
-@extension("VK_KHR_wayland_surface") // 7
-class VkWaylandSurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkWaylandSurfaceCreateFlagsKHR              flags
-    platform.wl_display*                        display
-    platform.wl_surface*                        surface
-}
-
-@extension("VK_KHR_android_surface") // 9
-class VkAndroidSurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkAndroidSurfaceCreateFlagsKHR              flags
-    platform.ANativeWindow*                     window
-}
-
-@extension("VK_KHR_win32_surface") // 10
-class VkWin32SurfaceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkWin32SurfaceCreateFlagsKHR                flags
-    platform.HINSTANCE                          hinstance
-    platform.HWND                               hwnd
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-@internal class Gralloc1Usage {
-    u64                                         consumer
-    u64                                         producer
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-class VkNativeBufferANDROID {
-    VkStructureType                             sType
-    const void*                                 pNext
-    platform.buffer_handle_t                    handle
-    s32                                         stride
-    s32                                         format
-    s32                                         usage
-    Gralloc1Usage                               usage2
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-class VkSwapchainImageCreateInfoANDROID {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSwapchainImageUsageFlagsANDROID           flags
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-class VkPhysicalDevicePresentationPropertiesANDROID {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    sharedImage
-}
-
-@extension("VK_EXT_debug_report") // 12
-class VkDebugReportCallbackCreateInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDebugReportFlagsEXT                       flags
-    PFN_vkDebugReportCallbackEXT                pfnCallback
-    void*                                       pUserData
-}
-
-@extension("VK_AMD_rasterization_order") // 19
-class VkPipelineRasterizationStateRasterizationOrderAMD {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkRasterizationOrderAMD                     rasterizationOrder
-}
-
-@extension("VK_EXT_debug_marker") // 23
-class VkDebugMarkerObjectNameInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDebugReportObjectTypeEXT                  objectType
-    u64                                         object
-    const char*                                 pObjectName
-}
-
-@extension("VK_EXT_debug_marker") // 23
-class VkDebugMarkerObjectTagInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDebugReportObjectTypeEXT                  objectType
-    u64                                         object
-    u64                                         tagName
-    platform.size_t                             tagSize
-    const void*                                 pTag
-}
-
-@extension("VK_EXT_debug_marker") // 23
-class VkDebugMarkerMarkerInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    const char*                                 pMarkerName
-    f32[4]                                      color
-}
-
-@extension("VK_NV_dedicated_allocation") // 27
-class VkDedicatedAllocationImageCreateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBool32                                    dedicatedAllocation
-}
-
-@extension("VK_NV_dedicated_allocation") // 27
-class VkDedicatedAllocationBufferCreateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBool32                                    dedicatedAllocation
-}
-
-@extension("VK_NV_dedicated_allocation") // 27
-class VkDedicatedAllocationMemoryAllocateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkImage                                     image
-    VkBuffer                                    buffer
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-class VkPhysicalDeviceTransformFeedbackFeaturesEXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    transformFeedback
-    VkBool32                                    geometryStreams
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-class VkPhysicalDeviceTransformFeedbackPropertiesEXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         maxTransformFeedbackStreams
-    u32                                         maxTransformFeedbackBuffers
-    VkDeviceSize                                maxTransformFeedbackBufferSize
-    u32                                         maxTransformFeedbackStreamDataSize
-    u32                                         maxTransformFeedbackBufferDataSize
-    u32                                         maxTransformFeedbackBufferDataStride
-    VkBool32                                    transformFeedbackQueries
-    VkBool32                                    transformFeedbackStreamsLinesTriangles
-    VkBool32                                    transformFeedbackRasterizationStreamSelect
-    VkBool32                                    transformFeedbackDraw
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-class VkPipelineRasterizationStateStreamCreateInfoEXT {
-    VkStructureType                                     sType
-    const void*                                         pNext
-    VkPipelineRasterizationStateStreamCreateFlagsEXT    flags
-    u32                                                 rasterizationStream
-}
-
-@extension("VK_AMD_texture_gather_bias_lod") // 42
-class VkTextureLODGatherFormatPropertiesAMD {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    supportsTextureGatherLODBiasAMD
-}
-
-@extension("VK_AMD_shader_info") // 43
-class VkShaderResourceUsageAMD {
-    u32                                         numUsedVgprs
-    u32                                         numUsedSgprs
-    u32                                         ldsSizePerLocalWorkGroup
-    platform.size_t                             ldsUsageSizeInBytes
-    platform.size_t                             scratchMemUsageInBytes
-}
-
-@extension("VK_AMD_shader_info") // 43
-class VkShaderStatisticsInfoAMD {
-    VkShaderStageFlags                          shaderStageMask
-    VkShaderResourceUsageAMD                    resourceUsage
-    u32                                         numPhysicalVgprs
-    u32                                         numPhysicalSgprs
-    u32                                         numAvailableVgprs
-    u32                                         numAvailableSgprs
-    u32[3]                                      computeWorkGroupSize
-}
-
-@extension("VK_NV_corner_sampled_image") // 51
-class VkPhysicalDeviceCornerSampledImageFeaturesNV {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    cornerSampledImage
-}
-
-@extension("VK_KHR_multiview") // 54
-class VkRenderPassMultiviewCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         subpassCount
-    const u32*                                  pViewMasks
-    u32                                         dependencyCount
-    const s32*                                  pViewOffsets
-    u32                                         correlationMaskCount
-    const u32*                                  pCorrelationMasks
-}
-
-@extension("VK_KHR_multiview") // 54
-class VkPhysicalDeviceMultiviewFeaturesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    multiview
-    VkBool32                                    multiviewGeometryShader
-    VkBool32                                    multiviewTessellationShader
-}
-
-@extension("VK_KHR_multiview") // 54
-class VkPhysicalDeviceMultiviewPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         maxMultiviewViewCount
-    u32                                         maxMultiviewInstanceIndex
-}
-
-@extension("VK_NV_external_memory_capabilities") // 56
-class VkExternalImageFormatPropertiesNV {
-    VkImageFormatProperties                     imageFormatProperties
-    VkExternalMemoryFeatureFlagsNV              externalMemoryFeatures
-    VkExternalMemoryHandleTypeFlagsNV           exportFromImportedHandleTypes
-    VkExternalMemoryHandleTypeFlagsNV           compatibleHandleTypes
-}
-
-@extension("VK_NV_external_memory") // 57
-class VkExternalMemoryImageCreateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsNV           handleTypes
-}
-
-@extension("VK_NV_external_memory") // 57
-class VkExportMemoryAllocateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsNV           handleTypes
-}
-
-@extension("VK_NV_external_memory_win32") // 58
-class VkImportMemoryWin32HandleInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsNV           handleType
-    platform.HANDLE                             handle
-}
-
-@extension("VK_NV_external_memory_win32") // 58
-class VkExportMemoryWin32HandleInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    const platform.SECURITY_ATTRIBUTES*         pAttributes
-    platform.DWORD                              dwAccess
-}
-
-@extension("VK_NV_win32_keyed_mutex") // 59
-class VkWin32KeyedMutexAcquireReleaseInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         acquireCount
-    const VkDeviceMemory*                       pAcquireSyncs
-    const u64*                                  pAcquireKeys
-    const u32*                                  pAcquireTimeoutMilliseconds
-    u32                                         releaseCount
-    const VkDeviceMemory*                       pReleaseSyncs
-    const u64*                                  pReleaseKeys
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkPhysicalDeviceFeatures2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkPhysicalDeviceFeatures                    features
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkPhysicalDeviceProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkPhysicalDeviceProperties                  properties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkFormatProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkFormatProperties                          formatProperties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkImageFormatProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkImageFormatProperties                     imageFormatProperties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkPhysicalDeviceImageFormatInfo2KHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkFormat                                    format
-    VkImageType                                 type
-    VkImageTiling                               tiling
-    VkImageUsageFlags                           usage
-    VkImageCreateFlags                          flags
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkQueueFamilyProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkQueueFamilyProperties                     queueFamilyProperties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkPhysicalDeviceMemoryProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkPhysicalDeviceMemoryProperties            memoryProperties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkSparseImageFormatProperties2KHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkSparseImageFormatProperties               properties
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-class VkPhysicalDeviceSparseImageFormatInfo2KHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkFormat                                    format
-    VkImageType                                 type
-    VkSampleCountFlagBits                       samples
-    VkImageUsageFlags                           usage
-    VkImageTiling                               tiling
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkMemoryAllocateFlagsInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkMemoryAllocateFlagsKHR                    flags
-    u32                                         deviceMask
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkBindBufferMemoryDeviceGroupInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         deviceIndexCount
-    const u32*                                  pDeviceIndices
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkBindImageMemoryDeviceGroupInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         deviceIndexCount
-    const u32*                                  pDeviceIndices
-    u32                                         SFRRectCount
-    const VkRect2D*                             pSFRRects
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkDeviceGroupRenderPassBeginInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         deviceMask
-    u32                                         deviceRenderAreaCount
-    const VkRect2D*                             pDeviceRenderAreas
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkDeviceGroupCommandBufferBeginInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         deviceMask
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkDeviceGroupSubmitInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         waitSemaphoreCount
-    const u32*                                  pWaitSemaphoreDeviceIndices
-    u32                                         commandBufferCount
-    const u32*                                  pCommandBufferDeviceMasks
-    u32                                         signalSemaphoreCount
-    const u32*                                  pSignalSemaphoreDeviceIndices
-}
-
-@extension("VK_KHR_device_group") // 61
-class VkDeviceGroupBindSparseInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         resourceDeviceIndex
-    u32                                         memoryDeviceIndex
-}
-
-@extension("VK_EXT_validation_flags") // 62
-class VkValidationFlagsEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         disabledValidationCheckCount
-    const VkValidationCheckEXT*                 pDisabledValidationChecks
-}
-
-@extension("VK_NN_vi_surface") // 63
-class VkViSurfaceCreateInfoNN {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkViSurfaceCreateFlagsNN                    flags
-    void*                                       window
-}
-
-@extension("VK_EXT_astc_decode_mode") // 68
-class VkImageViewASTCDecodeModeEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkFormat                                    decodeMode
-}
-
-@extension("VK_EXT_astc_decode_mode") // 68
-class VkPhysicalDeviceASTCDecodeFeaturesEXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    decodeModeSharedExponent
-}
-
-@extension("VK_KHR_device_group_creation") // 71
-class VkPhysicalDeviceGroupPropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             physicalDeviceCount
-    VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE]      physicalDevices
-    VkBool32                                        subsetAllocation
-}
-
-@extension("VK_KHR_device_group_creation") // 71
-class VkDeviceGroupDeviceCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         physicalDeviceCount
-    const VkPhysicalDevice*                     pPhysicalDevices
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkExternalMemoryPropertiesKHR {
-    VkExternalMemoryFeatureFlagsKHR             externalMemoryFeatures
-    VkExternalMemoryHandleTypeFlagsKHR          exportFromImportedHandleTypes
-    VkExternalMemoryHandleTypeFlagsKHR          compatibleHandleTypes
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkPhysicalDeviceExternalImageFormatInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkExternalImageFormatPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkExternalMemoryPropertiesKHR               externalMemoryProperties
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkPhysicalDeviceExternalBufferInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBufferCreateFlags                         flags
-    VkBufferUsageFlags                          usage
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkExternalBufferPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkExternalMemoryPropertiesKHR               externalMemoryProperties
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-class VkPhysicalDeviceIDPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    u8[VK_UUID_SIZE]                            deviceUUID
-    u8[VK_UUID_SIZE]                            driverUUID
-    u8[VK_LUID_SIZE]                            deviceLUID
-    u32                                         deviceNodeMask
-    VkBool32                                    deviceLUIDValid
-}
-
-@extension("VK_KHR_external_memory") // 73
-class VkExternalMemoryImageCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsKHR          handleTypes
-}
-
-@extension("VK_KHR_external_memory") // 73
-class VkExternalMemoryBufferCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsKHR          handleTypes
-}
-
-@extension("VK_KHR_external_memory") // 73
-class VkExportMemoryAllocateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsKHR          handleTypes
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-class VkImportMemoryWin32HandleInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-    platform.HANDLE                             handle
-    platform.LPCWSTR                            name
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-class VkExportMemoryWin32HandleInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    const platform.SECURITY_ATTRIBUTES*         pAttributes
-    platform.DWORD                              dwAccess
-    platform.LPCWSTR                            name
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-class VkMemoryWin32HandlePropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         memoryTypeBits
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-class VkMemoryGetWin32HandleInfoKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkDeviceMemory                              memory
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-}
-
-@extension("VK_KHR_external_memory_fd") // 75
-class VkImportMemoryFdInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-    int                                         fd
-}
-
-@extension("VK_KHR_external_memory_fd") // 75
-class VkMemoryFdPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         memoryTypeBits
-}
-
-@extension("VK_KHR_external_memory_fd") // 75
-class VkMemoryGetFdInfoKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkDeviceMemory                              memory
-    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
-}
-
-@extension("VK_KHR_win32_keyed_mutex") // 76
-class VkWin32KeyedMutexAcquireReleaseInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         acquireCount
-    const VkDeviceMemory*                       pAcquireSyncs
-    const u64*                                  pAcquireKeys
-    const u32*                                  pAcquireTimeouts
-    u32                                         releaseCount
-    const VkDeviceMemory*                       pReleaseSyncs
-    const u64*                                  pReleaseKeys
-}
-
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-class VkPhysicalDeviceExternalSemaphoreInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType
-}
-
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-class VkExternalSemaphorePropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkExternalSemaphoreHandleTypeFlagsKHR       exportFromImportedHandleTypes
-    VkExternalSemaphoreHandleTypeFlagsKHR       compatibleHandleTypes
-    VkExternalSemaphoreFeatureFlagsKHR          externalSemaphoreFeatures
-}
-
-@extension("VK_KHR_external_semaphore") // 78
-class VkExportSemaphoreCreateInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkExternalSemaphoreHandleTypeFlagsKHR       handleTypes
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-class VkImportSemaphoreWin32HandleInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSemaphore                                 semaphore
-    VkSemaphoreImportFlagsKHR                   flags
-    VkExternalSemaphoreHandleTypeFlagsKHR       handleType
-    platform.HANDLE                             handle
-    platform.LPCWSTR                            name
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-class VkExportSemaphoreWin32HandleInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    const platform.SECURITY_ATTRIBUTES*         pAttributes
-    platform.DWORD                              dwAccess
-    platform.LPCWSTR                            name
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-class VkD3D12FenceSubmitInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         waitSemaphoreValuesCount
-    const u64*                                  pWaitSemaphoreValues
-    u32                                         signalSemaphoreValuesCount
-    const u64*                                  pSignalSemaphoreValues
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-class VkSemaphoreGetWin32HandleInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSemaphore                                 semaphore
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType
-}
-
-@extension("VK_KHR_external_semaphore_fd") // 80
-class VkImportSemaphoreFdInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSemaphore                                 semaphore
-    VkSemaphoreImportFlagsKHR                   flags
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType
-    s32                                         fd
-}
-
-@extension("VK_KHR_external_semaphore_fd") // 80
-class VkSemaphoreGetFdInfoKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSemaphore                                 semaphore
-    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType
-}
-
-@extension("VK_KHR_push_descriptor") // 81
-class VkPhysicalDevicePushDescriptorPropertiesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         maxPushDescriptors
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-class VkConditionalRenderingBeginInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBuffer                                    buffer
-    VkDeviceSize                                offset
-    VkConditionalRenderingFlagsEXT              flags
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-class VkPhysicalDeviceConditionalRenderingFeaturesEXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    conditionalRendering
-    VkBool32                                    inheritedConditionalRendering
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-class VkCommandBufferInheritanceConditionalRenderingInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBool32                                    conditionalRenderingEnable
-}
-
-@extension("VK_KHR_shader_float16_int8") // 83
-class VkPhysicalDeviceFloat16Int8FeaturesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    shaderFloat16
-    VkBool32                                    shaderInt8
-}
-
-@extension("VK_KHR_16bit_storage") // 84
-class VkPhysicalDevice16BitStorageFeaturesKHR {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    storageBuffer16BitAccess
-    VkBool32                                    uniformAndStorageBuffer16BitAccess
-    VkBool32                                    storagePushConstant16
-    VkBool32                                    storageInputOutput16
-}
-
-@extension("VK_KHR_incremental_present") // 85
-class VkRectLayerKHR {
-    VkOffset2D                                  offset
-    VkExtent2D                                  extent
-    u32                                         layer
-}
-
-@extension("VK_KHR_incremental_present") // 85
-class VkPresentRegionKHR {
-    u32                                         rectangleCount
-    const VkRectLayerKHR*                       pRectangles
-}
-
-@extension("VK_KHR_incremental_present") // 85
-class VkPresentRegionsKHR {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         swapchainCount
-    const VkPresentRegionKHR*                   pRegions
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-class VkDescriptorUpdateTemplateEntryKHR {
-    u32                                         dstBinding
-    u32                                         dstArrayElement
-    u32                                         descriptorCount
-    VkDescriptorType                            descriptorType
-    platform.size_t                             offset
-    platform.size_t                             stride
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-class VkDescriptorUpdateTemplateCreateInfoKHR {
-    VkStructureType                              sType
-    void*                                        pNext
-    VkDescriptorUpdateTemplateCreateFlagsKHR     flags
-    u32                                          descriptorUpdateEntryCount
-    const VkDescriptorUpdateTemplateEntryKHR*    pDescriptorUpdateEntries
-    VkDescriptorUpdateTemplateTypeKHR            templateType
-    VkDescriptorSetLayout                        descriptorSetLayout
-    VkPipelineBindPoint                          pipelineBindPoint
-    VkPipelineLayout                             pipelineLayout
-    u32                                          set
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkDeviceGeneratedCommandsFeaturesNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBool32                                    computeBindingPointSupport
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkDeviceGeneratedCommandsLimitsNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         maxIndirectCommandsLayoutTokenCount
-    u32                                         maxObjectEntryCounts
-    u32                                         minSequenceCountBufferOffsetAlignment
-    u32                                         minSequenceIndexBufferOffsetAlignment
-    u32                                         minCommandsTokenBufferOffsetAlignment
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkIndirectCommandsTokenNVX {
-    VkIndirectCommandsTokenTypeNVX              tokenType
-    VkBuffer                                    buffer
-    VkDeviceSize                                offset
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkIndirectCommandsLayoutTokenNVX {
-    VkIndirectCommandsTokenTypeNVX              tokenType
-    u32                                         bindingUnit
-    u32                                         dynamicCount
-    u32                                         divisor
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkIndirectCommandsLayoutCreateInfoNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkPipelineBindPoint                         pipelineBindPoint
-    VkIndirectCommandsLayoutUsageFlagsNVX       flags
-    u32                                         tokenCount
-    const VkIndirectCommandsLayoutTokenNVX*     pTokens
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkCmdProcessCommandsInfoNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkObjectTableNVX                            objectTable
-    VkIndirectCommandsLayoutNVX                 indirectCommandsLayout
-    u32                                         indirectCommandsTokenCount
-    const VkIndirectCommandsTokenNVX*           pIndirectCommandsTokens
-    u32                                         maxSequencesCount
-    VkCommandBuffer                             targetCommandBuffer
-    VkBuffer                                    sequencesCountBuffer
-    VkDeviceSize                                sequencesCountOffset
-    VkBuffer                                    sequencesIndexBuffer
-    VkDeviceSize                                sequencesIndexOffset
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkCmdReserveSpaceForCommandsInfoNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkObjectTableNVX                            objectTable
-    VkIndirectCommandsLayoutNVX                 indirectCommandsLayout
-    u32                                         maxSequencesCount
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTableCreateInfoNVX {
-    VkStructureType                             sType
-    const void*                                 pNext
-    u32                                         objectCount
-    const VkObjectEntryTypeNVX*                 pObjectEntryTypes
-    const u32*                                  pObjectEntryCounts
-    const VkObjectEntryUsageFlagsNVX*           pObjectEntryUsageFlags
-    u32                                         maxUniformBuffersPerDescriptor
-    u32                                         maxStorageBuffersPerDescriptor
-    u32                                         maxStorageImagesPerDescriptor
-    u32                                         maxSampledImagesPerDescriptor
-    u32                                         maxPipelineLayouts
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTableEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTablePipelineEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-    VkPipeline                                  pipeline
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTableDescriptorSetEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-    VkPipelineLayout                            pipelineLayout
-    VkDescriptorSet                             descriptorSet
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTableVertexBufferEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-    VkBuffer                                    buffer
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTableIndexBufferEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-    VkBuffer                                    buffer
-    VkIndexType                                 indexType
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-class VkObjectTablePushConstantEntryNVX {
-    VkObjectEntryTypeNVX                        type
-    VkObjectEntryUsageFlagsNVX                  flags
-    VkPipelineLayout                            pipelineLayout
-    VkShaderStageFlags                          stageFlags
-}
-
-@extension("VK_NV_clip_space_w_scaling") // 88
-class VkViewportWScalingNV {
-    f32                                         xcoeff
-    f32                                         ycoeff
-}
-
-@extension("VK_NV_clip_space_w_scaling") // 88
-class VkPipelineViewportWScalingStateCreateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkBool32                                    viewportWScalingEnable
-    u32                                         viewportCount
-    const VkViewportWScalingNV*                 pViewportWScalings
-}
-
-@extension("VK_EXT_display_surface_counter") // 91
-class VkSurfaceCapabilities2EXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         minImageCount
-    u32                                         maxImageCount
-    VkExtent2D                                  currentExtent
-    VkExtent2D                                  minImageExtent
-    VkExtent2D                                  maxImageExtent
-    u32                                         maxImageArrayLayers
-    VkSurfaceTransformFlagsKHR                  supportedTransforms
-    VkSurfaceTransformFlagBitsKHR               currentTransform
-    VkCompositeAlphaFlagsKHR                    supportedCompositeAlpha
-    VkImageUsageFlags                           supportedUsageFlags
-    VkSurfaceCounterFlagsEXT                    supportedSurfaceCounters
-}
-
-@extension("VK_EXT_display_control") // 92
-class VkDisplayPowerInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDisplayPowerStateEXT                      powerState
-}
-
-@extension("VK_EXT_display_control") // 92
-class VkDeviceEventInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDeviceEventTypeEXT                        deviceEvent
-}
-
-@extension("VK_EXT_display_control") // 92
-class VkDisplayEventInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkDisplayEventTypeEXT                       displayEvent
-}
-
-@extension("VK_EXT_display_control") // 92
-class VkSwapchainCounterCreateInfoEXT {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkSurfaceCounterFlagsEXT                    surfaceCounters
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-class VkRefreshCycleDurationGOOGLE {
-    u64                                             refreshDuration
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-class VkPastPresentationTimingGOOGLE {
-    u32                                             presentID
-    u64                                             desiredPresentTime
-    u64                                             actualPresentTime
-    u64                                             earliestPresentTime
-    u64                                             presentMargin
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-class VkPresentTimeGOOGLE {
-    u32                                             presentID
-    u64                                             desiredPresentTime
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-class VkPresentTimesInfoGOOGLE {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             swapchainCount
-    const VkPresentTimeGOOGLE*                      pTimes
-}
-
-@extension("VK_NVX_multiview_per_view_attributes") // 98
-class VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX {
-    VkStructureType                             sType
-    void*                                       pNext
-    VkBool32                                    perViewPositionAllComponents
-}
-
-@extension("VK_NV_viewport_swizzle") // 99
-class VkViewportSwizzleNV {
-    VkViewportCoordinateSwizzleNV               x
-    VkViewportCoordinateSwizzleNV               y
-    VkViewportCoordinateSwizzleNV               z
-    VkViewportCoordinateSwizzleNV               w
-}
-
-@extension("VK_NV_viewport_swizzle") // 99
-class VkPipelineViewportSwizzleStateCreateInfoNV {
-    VkStructureType                             sType
-    const void*                                 pNext
-    VkPipelineViewportSwizzleStateCreateFlagsNV flags
-    u32                                         viewportCount
-    const VkViewportSwizzleNV*                  pViewportSwizzles
-}
-
-@extension("VK_EXT_discard_rectangles") // 100
-class VkPhysicalDeviceDiscardRectanglePropertiesEXT {
-    VkStructureType                             sType
-    void*                                       pNext
-    u32                                         maxDiscardRectangles
-}
-
-@extension("VK_EXT_discard_rectangles") // 100
-class VkPipelineDiscardRectangleStateCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkPipelineDiscardRectangleStateCreateFlagsEXT   flags
-    VkDiscardRectangleModeEXT                       discardRectangleMode
-    u32                                             discardRectangleCount
-    const VkRect2D*                                 pDiscardRectangles
-}
-
-@extension("VK_EXT_conservative_rasterization") // 102
-class VkPhysicalDeviceConservativeRasterizationPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    f32                                             primitiveOverestimationSize
-    f32                                             maxExtraPrimitiveOverestimationSize
-    f32                                             extraPrimitiveOverestimationSizeGranularity
-    VkBool32                                        primitiveUnderestimation
-    VkBool32                                        conservativePointAndLineRasterization
-    VkBool32                                        degenerateTrianglesRasterized
-    VkBool32                                        degenerateLinesRasterized
-    VkBool32                                        fullyCoveredFragmentShaderInputVariable
-    VkBool32                                        conservativeRasterizationPostDepthCoverage
-}
-
-@extension("VK_EXT_conservative_rasterization") // 102
-class VkPipelineRasterizationConservativeStateCreateInfoEXT {
-    VkStructureType                                           sType
-    const void*                                               pNext
-    VkPipelineRasterizationConservativeStateCreateFlagsEXT    flags
-    VkConservativeRasterizationModeEXT                        conservativeRasterizationMode
-    f32                                                       extraPrimitiveOverestimationSize
-}
-
-@extension("VK_EXT_hdr_metadata") // 106
-class VkXYColorEXT {
-    f32                                             x
-    f32                                             y
-}
-
-@extension("VK_EXT_hdr_metadata") // 106
-class VkHdrMetadataEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkXYColorEXT                                    displayPrimaryRed
-    VkXYColorEXT                                    displayPrimaryGreen
-    VkXYColorEXT                                    displayPrimaryBlue
-    VkXYColorEXT                                    whitePoint
-    f32                                             maxLuminance
-    f32                                             minLuminance
-    f32                                             maxContentLightLevel
-    f32                                             maxFrameAverageLightLevel
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkAttachmentDescription2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkAttachmentDescriptionFlags                    flags
-    VkFormat                                        format
-    VkSampleCountFlagBits                           samples
-    VkAttachmentLoadOp                              loadOp
-    VkAttachmentStoreOp                             storeOp
-    VkAttachmentLoadOp                              stencilLoadOp
-    VkAttachmentStoreOp                             stencilStoreOp
-    VkImageLayout                                   initialLayout
-    VkImageLayout                                   finalLayout
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkAttachmentReference2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             attachment
-    VkImageLayout                                   layout
-    VkImageAspectFlags                              aspectMask
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkSubpassDescription2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSubpassDescriptionFlags                       flags
-    VkPipelineBindPoint                             pipelineBindPoint
-    u32                                             viewMask
-    u32                                             inputAttachmentCount
-    const VkAttachmentReference2KHR*                pInputAttachments
-    u32                                             colorAttachmentCount
-    const VkAttachmentReference2KHR*                pColorAttachments
-    const VkAttachmentReference2KHR*                pResolveAttachments
-    const VkAttachmentReference2KHR*                pDepthStencilAttachment
-    u32                                             preserveAttachmentCount
-    const u32*                                      pPreserveAttachments
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkSubpassDependency2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             srcSubpass
-    u32                                             dstSubpass
-    VkPipelineStageFlags                            srcStageMask
-    VkPipelineStageFlags                            dstStageMask
-    VkAccessFlags                                   srcAccessMask
-    VkAccessFlags                                   dstAccessMask
-    VkDependencyFlags                               dependencyFlags
-    s32                                             viewOffset
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkRenderPassCreateInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkRenderPassCreateFlags                         flags
-    u32                                             attachmentCount
-    const VkAttachmentDescription2KHR*              pAttachments
-    u32                                             subpassCount
-    const VkSubpassDescription2KHR*                 pSubpasses
-    u32                                             dependencyCount
-    const VkSubpassDependency2KHR*                  pDependencies
-    u32                                             correlatedViewMaskCount
-    const u32*                                      pCorrelatedViewMasks
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkSubpassBeginInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSubpassContents                               contents
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-class VkSubpassEndInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-}
-
-@extension("VK_KHR_shared_presentable_image") // 112
-class VkSharedPresentSurfaceCapabilitiesKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImageUsageFlags                               sharedPresentSupportedUsageFlags
-}
-
-@extension("VK_KHR_external_fence_capabilities") // 113
-class VkPhysicalDeviceExternalFenceInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkExternalFenceHandleTypeFlagBitsKHR            handleType
-}
-
-@extension("VK_KHR_external_fence_capabilities") // 113
-class VkExternalFencePropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkExternalFenceHandleTypeFlagsKHR               exportFromImportedHandleTypes
-    VkExternalFenceHandleTypeFlagsKHR               compatibleHandleTypes
-    VkExternalFenceFeatureFlagsKHR                  externalFenceFeatures
-}
-
-@extension("VK_KHR_external_fence") // 114
-class VkExportFenceCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkExternalFenceHandleTypeFlagsKHR               handleTypes
-}
-
-@extension("VK_KHR_external_fence_win32") // 115
-class VkImportFenceWin32HandleInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkFence                                         fence
-    VkFenceImportFlagsKHR                           flags
-    VkExternalFenceHandleTypeFlagBitsKHR            handleType
-    platform.HANDLE                                 handle
-    platform.LPCWSTR                                name
-}
-
-@extension("VK_KHR_external_fence_win32") // 115
-class VkExportFenceWin32HandleInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    const platform.SECURITY_ATTRIBUTES*             pAttributes
-    platform.DWORD                                  dwAccess
-    platform.LPCWSTR                                name
-}
-
-@extension("VK_KHR_external_fence_win32") // 115
-class VkFenceGetWin32HandleInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkFence                                         fence
-    VkExternalFenceHandleTypeFlagBitsKHR            handleType
-}
-
-@extension("VK_KHR_external_fence_fd") // 116
-class VkImportFenceFdInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkFence                                         fence
-    VkFenceImportFlagsKHR                           flags
-    VkExternalFenceHandleTypeFlagBitsKHR            handleType
-    int                                             fd
-}
-
-@extension("VK_KHR_external_fence_fd") // 116
-class VkFenceGetFdInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkFence                                         fence
-    VkExternalFenceHandleTypeFlagBitsKHR            handleType
-}
-
-@extension("VK_KHR_maintenance2") // 118
-class VkPhysicalDevicePointClippingPropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkPointClippingBehaviorKHR                      pointClippingBehavior
-}
-
-@extension("VK_KHR_maintenance2") // 118
-class VkInputAttachmentAspectReferenceKHR {
-    u32                                             subpass
-    u32                                             inputAttachmentIndex
-    VkImageAspectFlags                              aspectMask
-}
-
-@extension("VK_KHR_maintenance2") // 118
-class VkRenderPassInputAttachmentAspectCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             aspectReferenceCount
-    const VkInputAttachmentAspectReferenceKHR*      pAspectReferences
-}
-
-@extension("VK_KHR_maintenance2") // 118
-class VkImageViewUsageCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImageUsageFlags                               usage
-}
-
-@extension("VK_KHR_maintenance2") // 118
-class VkPipelineTessellationDomainOriginStateCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkTessellationDomainOriginKHR                   domainOrigin
-}
-
-@extension("VK_KHR_get_surface_capabilities2") // 120
-class VkPhysicalDeviceSurfaceInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSurfaceKHR                                    surface
-}
-
-@extension("VK_KHR_get_surface_capabilities2") // 120
-class VkSurfaceCapabilities2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkSurfaceCapabilitiesKHR                        surfaceCapabilities
-}
-
-@extension("VK_KHR_get_surface_capabilities2") // 120
-class VkSurfaceFormat2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkSurfaceFormatKHR                              surfaceFormat
-}
-
-@extension("VK_KHR_variable_pointers") // 121
-class VkPhysicalDeviceVariablePointerFeaturesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        variablePointersStorageBuffer
-    VkBool32                                        variablePointers
-}
-
-@extension("VK_KHR_display_properties2") // 122
-class VkDisplayProperties2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDisplayPropertiesKHR                          displayProperties
-}
-
-@extension("VK_KHR_display_properties2") // 122
-class VkDisplayPlaneProperties2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDisplayPlanePropertiesKHR                     displayPlaneProperties
-}
-
-@extension("VK_KHR_display_properties2") // 122
-class VkDisplayModeProperties2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDisplayModePropertiesKHR                      displayModeProperties
-}
-
-@extension("VK_KHR_display_properties2") // 122
-class VkDisplayPlaneInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkDisplayModeKHR                                mode
-    u32                                             planeIndex
-}
-
-@extension("VK_KHR_display_properties2") // 122
-class VkDisplayPlaneCapabilities2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDisplayPlaneCapabilitiesKHR                   capabilities
-}
-
-@extension("VK_MVK_ios_surface") // 123
-class VkIOSSurfaceCreateInfoMVK {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkIOSSurfaceCreateFlagsMVK                      flags
-    const void*                                     pView
-}
-
-@extension("VK_MVK_macos_surface") // 124
-class VkMacOSSurfaceCreateInfoMVK {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkMacOSSurfaceCreateFlagsMVK                    flags
-    const void*                                     pView
-}
-
-@extension("VK_KHR_dedicated_allocation") // 128
-class VkMemoryDedicatedRequirementsKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        prefersDedicatedAllocation
-    VkBool32                                        requiresDedicatedAllocation
-}
-
-@extension("VK_KHR_dedicated_allocation") // 128
-class VkMemoryDedicatedAllocateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImage                                         image
-    VkBuffer                                        buffer
-}
-
-@extension("VK_EXT_debug_utils") // 129
-class VkDebugUtilsObjectNameInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkObjectType                                    objectType
-    u64                                             objectHandle
-    const char*                                     pObjectName
-}
-
-@extension("VK_EXT_debug_utils") // 129
-class VkDebugUtilsObjectTagInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkObjectType                                    objectType
-    u64                                             objectHandle
-    u64                                             tagName
-    platform.size_t                                 tagSize
-    const void*                                     pTag
-}
-
-@extension("VK_EXT_debug_utils") // 129
-class VkDebugUtilsLabelEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    const char*                                     pLabelName
-    f32[4]                                          color
-}
-
-@extension("VK_EXT_debug_utils") // 129
-class VkDebugUtilsMessengerCallbackDataEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkDebugUtilsMessengerCallbackDataFlagsEXT       flags
-    const char*                                     pMessageIdName
-    s32                                             messageIdNumber
-    const char*                                     pMessage
-    u32                                             queueLabelCount
-    const VkDebugUtilsLabelEXT*                     pQueueLabels
-    u32                                             cmdBufLabelCount
-    const VkDebugUtilsLabelEXT*                     pCmdBufLabels
-    u32                                             objectCount
-    const VkDebugUtilsObjectNameInfoEXT*            pObjects
-}
-
-@extension("VK_EXT_debug_utils") // 129
-class VkDebugUtilsMessengerCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkDebugUtilsMessengerCreateFlagsEXT             flags
-    VkDebugUtilsMessageSeverityFlagsEXT             messageSeverity
-    VkDebugUtilsMessageTypeFlagsEXT                 messageTypes
-    PFN_vkDebugUtilsMessengerCallbackEXT            pfnUserCallback
-    void*                                           pUserData
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 131
-class VkAndroidHardwareBufferUsageANDROID {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u64                                             androidHardwareBufferUsage
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-class VkAndroidHardwareBufferPropertiesANDROID {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDeviceSize                                    allocationSize
-    u32                                             memoryTypeBits
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-class VkAndroidHardwareBufferFormatPropertiesANDROID {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkFormat                                        format
-    u64                                             externalFormat
-    VkFormatFeatureFlags                            formatFeatures
-    VkComponentMapping                              samplerYcbcrConversionComponents
-    VkSamplerYcbcrModelConversion                   suggestedYcbcrModel
-    VkSamplerYcbcrRange                             suggestedYcbcrRange
-    VkChromaLocation                                suggestedXChromaOffset
-    VkChromaLocation                                suggestedYChromaOffset
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-class VkImportAndroidHardwareBufferInfoANDROID {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    platform.AHardwareBuffer*                       buffer
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-class VkMemoryGetAndroidHardwareBufferInfoANDROID {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkDeviceMemory                                  memory
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-class VkExternalFormatANDROID {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u64                                             externalFormat
-}
-
-@extension("VK_EXT_sampler_filter_minmax") // 131
-class VkSamplerReductionModeCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSamplerReductionModeEXT                       reductionMode
-}
-
-@extension("VK_EXT_sampler_filter_minmax") // 131
-class VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        filterMinmaxSingleComponentFormats
-    VkBool32                                        filterMinmaxImageComponentMapping
-}
-
-@extension("VK_EXT_inline_uniform_block") // 139
-class VkPhysicalDeviceInlineUniformBlockFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        inlineUniformBlock
-    VkBool32                                        descriptorBindingInlineUniformBlockUpdateAfterBind
-}
-
-@extension("VK_EXT_inline_uniform_block") // 139
-class VkPhysicalDeviceInlineUniformBlockPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             maxInlineUniformBlockSize
-    u32                                             maxPerStageDescriptorInlineUniformBlocks
-    u32                                             maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks
-    u32                                             maxDescriptorSetInlineUniformBlocks
-    u32                                             maxDescriptorSetUpdateAfterBindInlineUniformBlocks
-}
-
-@extension("VK_EXT_inline_uniform_block") // 139
-class VkWriteDescriptorSetInlineUniformBlockEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             dataSize
-    const void*                                     pData
-}
-
-@extension("VK_EXT_inline_uniform_block") // 139
-class VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             maxInlineUniformBlockBindings
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkSampleLocationEXT {
-    f32                                             x
-    f32                                             y
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkSampleLocationsInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSampleCountFlagBits                           sampleLocationsPerPixel
-    VkExtent2D                                      sampleLocationGridSize
-    u32                                             sampleLocationsCount
-    const VkSampleLocationEXT*                      pSampleLocations
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkAttachmentSampleLocationsEXT {
-    u32                                             attachmentIndex
-    VkSampleLocationsInfoEXT                        sampleLocationsInfo
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkSubpassSampleLocationsEXT {
-    u32                                             subpassIndex
-    VkSampleLocationsInfoEXT                        sampleLocationsInfo
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkRenderPassSampleLocationsBeginInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             attachmentInitialSampleLocationsCount
-    const VkAttachmentSampleLocationsEXT*           pAttachmentInitialSampleLocations
-    u32                                             postSubpassSampleLocationsCount
-    const VkSubpassSampleLocationsEXT*              pPostSubpassSampleLocations
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkPipelineSampleLocationsStateCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBool32                                        sampleLocationsEnable
-    VkSampleLocationsInfoEXT                        sampleLocationsInfo
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkPhysicalDeviceSampleLocationsPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkSampleCountFlags                              sampleLocationSampleCounts
-    VkExtent2D                                      maxSampleLocationGridSize
-    f32[2]                                          sampleLocationCoordinateRange
-    u32                                             sampleLocationSubPixelBits
-    VkBool32                                        variableSampleLocations
-}
-
-@extension("VK_EXT_sample_locations") // 144
-class VkMultisamplePropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkExtent2D                                      maxSampleLocationGridSize
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-class VkBufferMemoryRequirementsInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBuffer                                        buffer
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-class VkImageMemoryRequirementsInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImage                                         image
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-class VkImageSparseMemoryRequirementsInfo2KHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImage                                         image
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-class VkMemoryRequirements2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkMemoryRequirements                            memoryRequirements
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-class VkSparseImageMemoryRequirements2KHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkSparseImageMemoryRequirements                 memoryRequirements
-}
-
-@extension("VK_KHR_image_format_list") // 148
-class VkImageFormatListCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             viewFormatCount
-    const VkFormat*                                 pViewFormats
-}
-
-@extension("VK_EXT_blend_operation_advanced") // 149
-class VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        advancedBlendCoherentOperations
-}
-
-@extension("VK_EXT_blend_operation_advanced") // 149
-class VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             advancedBlendMaxColorAttachments
-    VkBool32                                        advancedBlendIndependentBlend
-    VkBool32                                        advancedBlendNonPremultipliedSrcColor
-    VkBool32                                        advancedBlendNonPremultipliedDstColor
-    VkBool32                                        advancedBlendCorrelatedOverlap
-    VkBool32                                        advancedBlendAllOperations
-}
-
-@extension("VK_EXT_blend_operation_advanced") // 149
-class VkPipelineColorBlendAdvancedStateCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBool32                                        srcPremultiplied
-    VkBool32                                        dstPremultiplied
-    VkBlendOverlapEXT                               blendOverlap
-}
-
-@extension("VK_NV_fragment_coverage_to_color") // 150
-class VkPipelineCoverageToColorStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkPipelineCoverageToColorStateCreateFlagsNV     flags
-    VkBool32                                        coverageToColorEnable
-    u32                                             coverageToColorLocation
-}
-
-@extension("VK_NV_framebuffer_mixed_samples") // 153
-class VkPipelineCoverageModulationStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkPipelineCoverageModulationStateCreateFlagsNV  flags
-    VkCoverageModulationModeNV                      coverageModulationMode
-    VkBool32                                        coverageModulationTableEnable
-    u32                                             coverageModulationTableCount
-    const f32*                                      pCoverageModulationTable
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkSamplerYcbcrConversionCreateInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkFormat                                        format
-    VkSamplerYcbcrModelConversionKHR                ycbcrModel
-    VkSamplerYcbcrRangeKHR                          ycbcrRange
-    VkComponentMapping                              components
-    VkChromaLocationKHR                             xChromaOffset
-    VkChromaLocationKHR                             yChromaOffset
-    VkFilter                                        chromaFilter
-    VkBool32                                        forceExplicitReconstruction
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkSamplerYcbcrConversionInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkSamplerYcbcrConversionKHR                     conversion
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkBindImagePlaneMemoryInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImageAspectFlagBits                           planeAspect
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkImagePlaneMemoryRequirementsInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImageAspectFlagBits                           planeAspect
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        samplerYcbcrConversion
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-class VkSamplerYcbcrConversionImageFormatPropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             combinedImageSamplerDescriptorCount
-}
-
-@extension("VK_KHR_bind_memory2") // 158
-class VkBindBufferMemoryInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBuffer                                        buffer
-    VkDeviceMemory                                  memory
-    VkDeviceSize                                    memoryOffset
-}
-
-@extension("VK_KHR_bind_memory2") // 158
-class VkBindImageMemoryInfoKHR {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImage                                         image
-    VkDeviceMemory                                  memory
-    VkDeviceSize                                    memoryOffset
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkDrmFormatModifierPropertiesEXT {
-    u64                                             drmFormatModifier
-    u32                                             drmFormatModifierPlaneCount
-    VkFormatFeatureFlags                            drmFormatModifierTilingFeatures
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkDrmFormatModifierPropertiesListEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             drmFormatModifierCount
-    VkDrmFormatModifierPropertiesEXT*               pDrmFormatModifierProperties
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkPhysicalDeviceImageDrmFormatModifierInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u64                                             drmFormatModifier
-    VkSharingMode                                   sharingMode
-    u32                                             queueFamilyIndexCount
-    const u32*                                      pQueueFamilyIndices
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkImageDrmFormatModifierListCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             drmFormatModifierCount
-    const u64*                                      pDrmFormatModifiers
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkImageDrmFormatModifierExplicitCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u64                                             drmFormatModifier
-    u32                                             drmFormatModifierPlaneCount
-    const VkSubresourceLayout*                      pPlaneLayouts
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-class VkImageDrmFormatModifierPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u64                                             drmFormatModifier
-}
-
-@extension("VK_EXT_validation_cache") // 161
-class VkValidationCacheCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkValidationCacheCreateFlagsEXT                 flags
-    platform.size_t                                 initialDataSize
-    const void*                                     pInitialData
-}
-
-@extension("VK_EXT_validation_cache") // 161
-class VkShaderModuleValidationCacheCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkValidationCacheEXT                            validationCache
-}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-class VkDescriptorSetLayoutBindingFlagsCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             bindingCount
-    const VkDescriptorBindingFlagsEXT*              pBindingFlags
-}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-class VkPhysicalDeviceDescriptorIndexingFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        shaderInputAttachmentArrayDynamicIndexing
-    VkBool32                                        shaderUniformTexelBufferArrayDynamicIndexing
-    VkBool32                                        shaderStorageTexelBufferArrayDynamicIndexing
-    VkBool32                                        shaderUniformBufferArrayNonUniformIndexing
-    VkBool32                                        shaderSampledImageArrayNonUniformIndexing
-    VkBool32                                        shaderStorageBufferArrayNonUniformIndexing
-    VkBool32                                        shaderStorageImageArrayNonUniformIndexing
-    VkBool32                                        shaderInputAttachmentArrayNonUniformIndexing
-    VkBool32                                        shaderUniformTexelBufferArrayNonUniformIndexing
-    VkBool32                                        shaderStorageTexelBufferArrayNonUniformIndexing
-    VkBool32                                        descriptorBindingUniformBufferUpdateAfterBind
-    VkBool32                                        descriptorBindingSampledImageUpdateAfterBind
-    VkBool32                                        descriptorBindingStorageImageUpdateAfterBind
-    VkBool32                                        descriptorBindingStorageBufferUpdateAfterBind
-    VkBool32                                        descriptorBindingUniformTexelBufferUpdateAfterBind
-    VkBool32                                        descriptorBindingStorageTexelBufferUpdateAfterBind
-    VkBool32                                        descriptorBindingUpdateUnusedWhilePending
-    VkBool32                                        descriptorBindingPartiallyBound
-    VkBool32                                        descriptorBindingVariableDescriptorCount
-    VkBool32                                        runtimeDescriptorArray
-}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-class VkPhysicalDeviceDescriptorIndexingPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             maxUpdateAfterBindDescriptorsInAllPools
-    VkBool32                                        shaderUniformBufferArrayNonUniformIndexingNative
-    VkBool32                                        shaderSampledImageArrayNonUniformIndexingNative
-    VkBool32                                        shaderStorageBufferArrayNonUniformIndexingNative
-    VkBool32                                        shaderStorageImageArrayNonUniformIndexingNative
-    VkBool32                                        shaderInputAttachmentArrayNonUniformIndexingNative
-    VkBool32                                        robustBufferAccessUpdateAfterBind
-    VkBool32                                        quadDivergentImplicitLod
-    u32                                             maxPerStageDescriptorUpdateAfterBindSamplers
-    u32                                             maxPerStageDescriptorUpdateAfterBindUniformBuffers
-    u32                                             maxPerStageDescriptorUpdateAfterBindStorageBuffers
-    u32                                             maxPerStageDescriptorUpdateAfterBindSampledImages
-    u32                                             maxPerStageDescriptorUpdateAfterBindStorageImages
-    u32                                             maxPerStageDescriptorUpdateAfterBindInputAttachments
-    u32                                             maxPerStageUpdateAfterBindResources
-    u32                                             maxDescriptorSetUpdateAfterBindSamplers
-    u32                                             maxDescriptorSetUpdateAfterBindUniformBuffers
-    u32                                             maxDescriptorSetUpdateAfterBindUniformBuffersDynamic
-    u32                                             maxDescriptorSetUpdateAfterBindStorageBuffers
-    u32                                             maxDescriptorSetUpdateAfterBindStorageBuffersDynamic
-    u32                                             maxDescriptorSetUpdateAfterBindSampledImages
-    u32                                             maxDescriptorSetUpdateAfterBindStorageImages
-    u32                                             maxDescriptorSetUpdateAfterBindInputAttachments
-}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-class VkDescriptorSetVariableDescriptorCountAllocateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             descriptorSetCount
-    const u32*                                      pDescriptorCounts
-}
-
-@extension("VK_EXT_descriptor_indexing") // 162
-class VkDescriptorSetVariableDescriptorCountLayoutSupportEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             maxVariableDescriptorCount
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkShadingRatePaletteNV {
-    u32                                             shadingRatePaletteEntryCount
-    const VkShadingRatePaletteEntryNV*              pShadingRatePaletteEntries
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkPipelineViewportShadingRateImageStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBool32                                        shadingRateImageEnable
-    u32                                             viewportCount
-    const VkShadingRatePaletteNV*                   pShadingRatePalettes
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkPhysicalDeviceShadingRateImageFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        shadingRateImage
-    VkBool32                                        shadingRateCoarseSampleOrder
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkPhysicalDeviceShadingRateImagePropertiesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkExtent2D                                      shadingRateTexelSize
-    u32                                             shadingRatePaletteSize
-    u32                                             shadingRateMaxCoarseSamples
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkCoarseSampleLocationNV {
-    u32                                             pixelX
-    u32                                             pixelY
-    u32                                             sample
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkCoarseSampleOrderCustomNV {
-    VkShadingRatePaletteEntryNV                     shadingRate
-    u32                                             sampleCount
-    u32                                             sampleLocationCount
-    const VkCoarseSampleLocationNV*                 pSampleLocations
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-class VkPipelineViewportCoarseSampleOrderStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkCoarseSampleOrderTypeNV                       sampleOrderType
-    u32                                             customSampleOrderCount
-    const VkCoarseSampleOrderCustomNV*              pCustomSampleOrders
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkRayTracingShaderGroupCreateInfoNV {
-    VkStructureType                  sType
-    const void*                      pNext
-    VkRayTracingShaderGroupTypeNV    type
-    u32                              generalShader
-    u32                              closestHitShader
-    u32                              anyHitShader
-    u32                              intersectionShader
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkRayTracingPipelineCreateInfoNV {
-    VkStructureType                               sType
-    const void*                                   pNext
-    VkPipelineCreateFlags                         flags
-    u32                                           stageCount
-    const VkPipelineShaderStageCreateInfo*        pStages
-    u32                                           groupCount
-    const VkRayTracingShaderGroupCreateInfoNV*    pGroups
-    u32                                           maxRecursionDepth
-    VkPipelineLayout                              layout
-    VkPipeline                                    basePipelineHandle
-    s32                                           basePipelineIndex
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkGeometryTrianglesNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBuffer                                        vertexData
-    VkDeviceSize                                    vertexOffset
-    u32                                             vertexCount
-    VkDeviceSize                                    vertexStride
-    VkFormat                                        vertexFormat
-    VkBuffer                                        indexData
-    VkDeviceSize                                    indexOffset
-    u32                                             indexCount
-    VkIndexType                                     indexType
-    VkBuffer                                        transformData
-    VkDeviceSize                                    transformOffset
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkGeometryAABBNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBuffer                                        aabbData
-    u32                                             numAABBs
-    u32                                             stride
-    VkDeviceSize                                    offset
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkGeometryDataNV {
-    VkGeometryTrianglesNV                           triangles
-    VkGeometryAABBNV                                aabbs
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkGeometryNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkGeometryTypeNV                                geometryType
-    VkGeometryDataNV                                geometry
-    VkGeometryFlagsNV                               flags
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkAccelerationStructureInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkAccelerationStructureTypeNV                   type
-    VkBuildAccelerationStructureFlagsNV             flags
-    u32                                             instanceCount
-    u32                                             geometryCount
-    const VkGeometryNV*                             pGeometries
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkAccelerationStructureCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkDeviceSize                                    compactedSize
-    VkAccelerationStructureInfoNV                   info
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkBindAccelerationStructureMemoryInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkAccelerationStructureNV                       accelerationStructure
-    VkDeviceMemory                                  memory
-    VkDeviceSize                                    memoryOffset
-    u32                                             deviceIndexCount
-    const u32*                                      pDeviceIndices
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkDescriptorAccelerationStructureInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             accelerationStructureCount
-    const VkAccelerationStructureNV*                pAccelerationStructures
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkAccelerationStructureMemoryRequirementsInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkAccelerationStructureMemoryRequirementsTypeNV type
-    VkAccelerationStructureNV                       accelerationStructure
-}
-
-@extension("VK_NV_ray_tracing") // 166
-class VkPhysicalDeviceRaytracingPropertiesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             shaderGroupHandleSize
-    u32                                             maxRecursionDepth
-    u32                                             maxShaderGroupStride
-    u32                                             shaderGroupBaseAlignment
-    u64                                             maxGeometryCount
-    u64                                             maxInstanceCount
-    u64                                             maxTriangleCount
-    u32                                             maxDescriptorSetAccelerationStructures
-}
-
-@extension("VK_NV_representative_fragment_test") // 167
-class VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        representativeFragmentTest
-}
-
-@extension("VK_NV_representative_fragment_test") // 167
-class VkPipelineRepresentativeFragmentTestStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkBool32                                        representativeFragmentTestEnable
-}
-
-@extension("VK_KHR_maintenance3") // 169
-class VkPhysicalDeviceMaintenance3PropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             maxPerSetDescriptors
-    VkDeviceSize                                    maxMemoryAllocationSize
-}
-
-@extension("VK_KHR_maintenance3") // 169
-class VkDescriptorSetLayoutSupportKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        supported
-}
-
-@extension("VK_EXT_global_priority") // 175
-class VkDeviceQueueGlobalPriorityCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkQueueGlobalPriorityEXT                        globalPriority
-}
-
-@extension("VK_KHR_8bit_storage") // 178
-class VkPhysicalDevice8BitStorageFeaturesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        storageBuffer8BitAccess
-    VkBool32                                        uniformAndStorageBuffer8BitAccess
-    VkBool32                                        storagePushConstant8
-}
-
-@extension("VK_EXT_external_memory_host") // 179
-class VkImportMemoryHostPointerInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkExternalMemoryHandleTypeFlagBits              handleType
-    void*                                           pHostPointer
-}
-
-@extension("VK_EXT_external_memory_host") // 179
-class VkMemoryHostPointerPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             memoryTypeBits
-}
-
-@extension("VK_EXT_external_memory_host") // 179
-class VkPhysicalDeviceExternalMemoryHostPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDeviceSize                                    minImportedHostPointerAlignment
-}
-
-@extension("VK_KHR_shader_atomic_int64") // 181
-class VkPhysicalDeviceShaderAtomicInt64FeaturesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        shaderBufferInt64Atomics
-    VkBool32                                        shaderSharedInt64Atomics
-}
-
-@extension("VK_EXT_calibrated_timestamps") // 185
-class VkCalibratedTimestampInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkTimeDomainEXT                                 timeDomain
-}
-
-@extension("VK_AMD_shader_core_properties") // 186
-class VkPhysicalDeviceShaderCorePropertiesAMD {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             shaderEngineCount
-    u32                                             shaderArraysPerEngineCount
-    u32                                             computeUnitsPerShaderArray
-    u32                                             simdPerComputeUnit
-    u32                                             wavefrontsPerSimd
-    u32                                             wavefrontSize
-    u32                                             sgprsPerSimd
-    u32                                             minSgprAllocation
-    u32                                             maxSgprAllocation
-    u32                                             sgprAllocationGranularity
-    u32                                             vgprsPerSimd
-    u32                                             minVgprAllocation
-    u32                                             maxVgprAllocation
-    u32                                             vgprAllocationGranularity
-}
-
-@extension("VK_AMD_memory_overallocation_behavior") // 190
-class VkDeviceMemoryOverallocationCreateInfoAMD {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkMemoryOverallocationBehaviorAMD               overallocationBehavior
-}
-
-@extension("VK_EXT_vertex_attribute_divisor") // 191
-class VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             maxVertexAttribDivisor
-}
-
-@extension("VK_EXT_vertex_attribute_divisor") // 191
-class VkVertexInputBindingDivisorDescriptionEXT {
-    u32                                             binding
-    u32                                             divisor
-}
-
-@extension("VK_EXT_vertex_attribute_divisor") // 191
-class VkPipelineVertexInputDivisorStateCreateInfoEXT {
-    VkStructureType                                     sType
-    const void*                                         pNext
-    u32                                                 vertexBindingDivisorCount
-    const VkVertexInputBindingDivisorDescriptionEXT*    pVertexBindingDivisors
-}
-
-@extension("VK_EXT_vertex_attribute_divisor") // 191
-class VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        vertexAttributeInstanceRateDivisor
-    VkBool32                                        vertexAttributeInstanceRateZeroDivisor
-}
-
-@extension("VK_KHR_driver_properties") // 197
-class VkConformanceVersionKHR {
-    u8                                              major
-    u8                                              minor
-    u8                                              subminor
-    u8                                              patch
-}
-
-@extension("VK_KHR_driver_properties") // 197
-class VkPhysicalDeviceDriverPropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkDriverIdKHR                                   driverID
-    char[VK_MAX_DRIVER_NAME_SIZE_KHR]               driverName
-    char[VK_MAX_DRIVER_INFO_SIZE_KHR]               driverInfo
-    VkConformanceVersionKHR                         conformanceVersion
-}
-
-@extension("VK_KHR_shader_float_controls") // 198
-class VkPhysicalDeviceFloatControlsPropertiesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        separateDenormSettings
-    VkBool32                                        separateRoundingModeSettings
-    VkBool32                                        shaderSignedZeroInfNanPreserveFloat16
-    VkBool32                                        shaderSignedZeroInfNanPreserveFloat32
-    VkBool32                                        shaderSignedZeroInfNanPreserveFloat64
-    VkBool32                                        shaderDenormPreserveFloat16
-    VkBool32                                        shaderDenormPreserveFloat32
-    VkBool32                                        shaderDenormPreserveFloat64
-    VkBool32                                        shaderDenormFlushToZeroFloat16
-    VkBool32                                        shaderDenormFlushToZeroFloat32
-    VkBool32                                        shaderDenormFlushToZeroFloat64
-    VkBool32                                        shaderRoundingModeRTEFloat16
-    VkBool32                                        shaderRoundingModeRTEFloat32
-    VkBool32                                        shaderRoundingModeRTEFloat64
-    VkBool32                                        shaderRoundingModeRTZFloat16
-    VkBool32                                        shaderRoundingModeRTZFloat32
-    VkBool32                                        shaderRoundingModeRTZFloat64
-}
-
-@extension("VK_NV_compute_shader_derivatives") // 202
-class VkPhysicalDeviceComputeShaderDerivativesFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        computeDerivativeGroupQuads
-    VkBool32                                        computeDerivativeGroupLinear
-}
-
-@extension("VK_NV_mesh_shader") // 203
-class VkPhysicalDeviceMeshShaderFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        taskShader
-    VkBool32                                        meshShader
-}
-
-@extension("VK_NV_mesh_shader") // 203
-class VkPhysicalDeviceMeshShaderPropertiesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             maxDrawMeshTasksCount
-    u32                                             maxTaskWorkGroupInvocations
-    u32[3]                                          maxTaskWorkGroupSize
-    u32                                             maxTaskTotalMemorySize
-    u32                                             maxTaskOutputCount
-    u32                                             maxMeshWorkGroupInvocations
-    u32[3]                                          maxMeshWorkGroupSize
-    u32                                             maxMeshTotalMemorySize
-    u32                                             maxMeshOutputVertices
-    u32                                             maxMeshOutputPrimitives
-    u32                                             maxMeshMultiviewViewCount
-    u32                                             meshOutputPerVertexGranularity
-    u32                                             meshOutputPerPrimitiveGranularity
-}
-
-@extension("VK_NV_mesh_shader") // 203
-class VkDrawMeshTasksIndirectCommandNV {
-    u32                                             taskCount
-    u32                                             firstTask
-}
-
-@extension("VK_NV_fragment_shader_barycentric") // 204
-class VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        fragmentShaderBarycentric
-}
-
-@extension("VK_NV_shader_image_footprint") // 205
-class VkPhysicalDeviceShaderImageFootprintFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        imageFootprint
-}
-
-@extension("VK_NV_scissor_exclusive") // 206
-class VkPipelineViewportExclusiveScissorStateCreateInfoNV {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    u32                                             exclusiveScissorCount
-    const VkRect2D*                                 pExclusiveScissors
-}
-
-@extension("VK_NV_scissor_exclusive") // 206
-class VkPhysicalDeviceExclusiveScissorFeaturesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        exclusiveScissor
-}
-
-@extension("VK_NV_device_diagnostic_checkpoints") // 207
-class VkQueueFamilyCheckpointPropertiesNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkPipelineStageFlags                            checkpointExecutionStageMask
-}
-
-@extension("VK_NV_device_diagnostic_checkpoints") // 207
-class VkCheckpointDataNV {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkPipelineStageFlagBits                         stage
-    void*                                           pCheckpointMarker
-}
-
-@extension("VK_KHR_vulkan_memory_model") // 212
-class VkPhysicalDeviceVulkanMemoryModelFeaturesKHR {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        vulkanMemoryModel
-    VkBool32                                        vulkanMemoryModelDeviceScope
-}
-
-@extension("VK_EXT_pci_bus_info") // 213
-class VkPhysicalDevicePCIBusInfoPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    u32                                             pciDomain
-    u32                                             pciBus
-    u32                                             pciDevice
-    u32                                             pciFunction
-}
-
-@extension("VK_FUCHSIA_imagepipe_surface") // 215
-class VkImagePipeSurfaceCreateInfoFUCHSIA {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImagePipeSurfaceCreateFlagsFUCHSIA            flags
-    platform.zx_handle_t                            imagePipeHandle
-}
-
-@extension("VK_EXT_fragment_density_map") // 219
-class VkPhysicalDeviceFragmentDensityMapFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        fragmentDensityMap
-    VkBool32                                        fragmentDensityMapDynamic
-    VkBool32                                        fragmentDensityMapNonSubsampledImages
-}
-
-@extension("VK_EXT_fragment_density_map") // 219
-class VkPhysicalDeviceFragmentDensityMapPropertiesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkExtent2D                                      minFragmentDensityTexelSize
-    VkExtent2D                                      maxFragmentDensityTexelSize
-    VkBool32                                        fragmentDensityInvocations
-}
-
-@extension("VK_EXT_fragment_density_map") // 219
-class VkRenderPassFragmentDensityMapCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkAttachmentReference                           fragmentDensityMapAttachment
-}
-
-@extension("VK_EXT_scalar_block_layout") // 222
-class VkPhysicalDeviceScalarBlockLayoutFeaturesEXT {
-    VkStructureType                                 sType
-    void*                                           pNext
-    VkBool32                                        scalarBlockLayout
-}
-
-@extension("VK_EXT_separate_stencil_usage") // 247
-class VkImageStencilUsageCreateInfoEXT {
-    VkStructureType                                 sType
-    const void*                                     pNext
-    VkImageUsageFlags                               stencilUsage
-}
-
-
-////////////////
-//  Commands  //
-////////////////
-
-// Function pointers. TODO: add support for function pointers.
-
-@external type void* PFN_vkVoidFunction
-@pfn cmd void vkVoidFunction() {
-}
-
-@external type void* PFN_vkAllocationFunction
-@pfn cmd void* vkAllocationFunction(
-        void*                                       pUserData,
-        platform.size_t                             size,
-        platform.size_t                             alignment,
-        VkSystemAllocationScope                     allocationScope) {
-    return ?
-}
-
-@external type void* PFN_vkReallocationFunction
-@pfn cmd void* vkReallocationFunction(
-        void*                                       pUserData,
-        void*                                       pOriginal,
-        platform.size_t                             size,
-        platform.size_t                             alignment,
-        VkSystemAllocationScope                     allocationScope) {
-    return ?
-}
-
-@external type void* PFN_vkFreeFunction
-@pfn cmd void vkFreeFunction(
-        void*                                       pUserData,
-        void*                                       pMemory) {
-}
-
-@external type void* PFN_vkInternalAllocationNotification
-@pfn cmd void vkInternalAllocationNotification(
-        void*                                       pUserData,
-        platform.size_t                             size,
-        VkInternalAllocationType                    allocationType,
-        VkSystemAllocationScope                     allocationScope) {
-}
-
-@external type void* PFN_vkInternalFreeNotification
-@pfn cmd void vkInternalFreeNotification(
-        void*                                       pUserData,
-        platform.size_t                             size,
-        VkInternalAllocationType                    allocationType,
-        VkSystemAllocationScope                     allocationScope) {
-}
-
-// Global functions
-
-@threadSafety("system")
-cmd VkResult vkCreateInstance(
-        const VkInstanceCreateInfo*                 pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkInstance*                                 pInstance) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO)
-
-    instance := ?
-    pInstance[0] = instance
-    State.Instances[instance] = new!InstanceObject()
-
-    layers := pCreateInfo.ppEnabledLayerNames[0:pCreateInfo.enabledLayerCount]
-    extensions := pCreateInfo.ppEnabledExtensionNames[0:pCreateInfo.enabledExtensionCount]
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyInstance(
-        VkInstance                                  instance,
-        const VkAllocationCallbacks*                pAllocator) {
-    instanceObject := GetInstance(instance)
-
-    State.Instances[instance] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkEnumeratePhysicalDevices(
-        VkInstance                                  instance,
-        u32*                                        pPhysicalDeviceCount,
-        VkPhysicalDevice*                           pPhysicalDevices) {
-    instanceObject := GetInstance(instance)
-
-    physicalDeviceCount := as!u32(?)
-    pPhysicalDeviceCount[0] = physicalDeviceCount
-    physicalDevices := pPhysicalDevices[0:physicalDeviceCount]
-
-    for i in (0 .. physicalDeviceCount) {
-        physicalDevice := ?
-        physicalDevices[i] = physicalDevice
-        if !(physicalDevice in State.PhysicalDevices) {
-            State.PhysicalDevices[physicalDevice] = new!PhysicalDeviceObject(instance: instance)
-        }
-    }
-
-    return ?
-}
-
-cmd PFN_vkVoidFunction vkGetDeviceProcAddr(
-        VkDevice                                    device,
-        const char*                                 pName) {
-    if device != NULL_HANDLE {
-        device := GetDevice(device)
-    }
-
-    return ?
-}
-
-cmd PFN_vkVoidFunction vkGetInstanceProcAddr(
-        VkInstance                                  instance,
-        const char*                                 pName) {
-    if instance != NULL_HANDLE {
-        instanceObject := GetInstance(instance)
-    }
-
-    return ?
-}
-
-cmd void vkGetPhysicalDeviceProperties(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceProperties*                 pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    properties := ?
-    pProperties[0] = properties
-}
-
-cmd void vkGetPhysicalDeviceQueueFamilyProperties(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pQueueFamilyPropertyCount,
-        VkQueueFamilyProperties*                    pQueueFamilyProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    // TODO: Figure out how to express fetch-count-or-properties
-    // This version fails 'apic validate' with 'fence not allowed in
-    // *semantic.Branch'. Other attempts have failed with the same or other
-    // errors.
-    // if pQueueFamilyProperties != null {
-    //     queuesProperties := pQueueFamilyProperties[0:pCount[0]]
-    //     for i in (0 .. pCount[0]) {
-    //         queueProperties := as!VkQueueFamilyProperties(?)
-    //         queuesProperties[i] = queueProperties
-    //    }
-    // } else {
-    //     count := ?
-    //     pCount[0] = count
-    // }
-}
-
-cmd void vkGetPhysicalDeviceMemoryProperties(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceMemoryProperties*           pMemoryProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    memoryProperties := ?
-    pMemoryProperties[0] = memoryProperties
-}
-
-cmd void vkGetPhysicalDeviceFeatures(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceFeatures*                   pFeatures) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    features := ?
-    pFeatures[0] = features
-}
-
-cmd void vkGetPhysicalDeviceFormatProperties(
-        VkPhysicalDevice                            physicalDevice,
-        VkFormat                                    format,
-        VkFormatProperties*                         pFormatProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    formatProperties := ?
-    pFormatProperties[0] = formatProperties
-}
-
-cmd VkResult vkGetPhysicalDeviceImageFormatProperties(
-        VkPhysicalDevice                            physicalDevice,
-        VkFormat                                    format,
-        VkImageType                                 type,
-        VkImageTiling                               tiling,
-        VkImageUsageFlags                           usage,
-        VkImageCreateFlags                          flags,
-        VkImageFormatProperties*                    pImageFormatProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    imageFormatProperties := ?
-    pImageFormatProperties[0] = imageFormatProperties
-
-    return ?
-}
-
-
-// Device functions
-
-@threadSafety("system")
-cmd VkResult vkCreateDevice(
-        VkPhysicalDevice                            physicalDevice,
-        const VkDeviceCreateInfo*                   pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDevice*                                   pDevice) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO)
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    device := ?
-    pDevice[0] = device
-    State.Devices[device] = new!DeviceObject(physicalDevice: physicalDevice)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyDevice(
-        VkDevice                                    device,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-
-    State.Devices[device] = null
-}
-
-
-// Extension discovery functions
-
-cmd VkResult vkEnumerateInstanceLayerProperties(
-        u32*                                        pPropertyCount,
-        VkLayerProperties*                          pProperties) {
-    count := as!u32(?)
-    pPropertyCount[0] = count
-
-    properties := pProperties[0:count]
-    for i in (0 .. count) {
-        property := ?
-        properties[i] = property
-    }
-
-    return ?
-}
-
-cmd VkResult vkEnumerateInstanceExtensionProperties(
-        const char*                                 pLayerName,
-        u32*                                        pPropertyCount,
-        VkExtensionProperties*                      pProperties) {
-    count := as!u32(?)
-    pPropertyCount[0] = count
-
-    properties := pProperties[0:count]
-    for i in (0 .. count) {
-        property := ?
-        properties[i] = property
-    }
-
-    return ?
-}
-
-cmd VkResult vkEnumerateDeviceLayerProperties(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pPropertyCount,
-        VkLayerProperties*                          pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    count := as!u32(?)
-    pPropertyCount[0] = count
-
-    properties := pProperties[0:count]
-    for i in (0 .. count) {
-        property := ?
-        properties[i] = property
-    }
-
-    return ?
-}
-
-cmd VkResult vkEnumerateDeviceExtensionProperties(
-        VkPhysicalDevice                            physicalDevice,
-        const char*                                 pLayerName,
-        u32*                                        pPropertyCount,
-        VkExtensionProperties*                      pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    count := as!u32(?)
-    pPropertyCount[0] = count
-
-    properties := pProperties[0:count]
-    for i in (0 .. count) {
-        property := ?
-        properties[i] = property
-    }
-
-    return ?
-}
-
-
-// Queue functions
-
-@threadSafety("system")
-cmd void vkGetDeviceQueue(
-        VkDevice                                    device,
-        u32                                         queueFamilyIndex,
-        u32                                         queueIndex,
-        VkQueue*                                    pQueue) {
-    deviceObject := GetDevice(device)
-
-    queue := ?
-    pQueue[0] = queue
-
-    if !(queue in State.Queues) {
-        State.Queues[queue] = new!QueueObject(device: device)
-    }
-}
-
-@threadSafety("app")
-cmd VkResult vkQueueSubmit(
-        VkQueue                                     queue,
-        u32                                         submitCount,
-        const VkSubmitInfo*                         pSubmits,
-        VkFence                                     fence) {
-    queueObject := GetQueue(queue)
-
-    if fence != NULL_HANDLE {
-        fenceObject := GetFence(fence)
-        assert(fenceObject.device == queueObject.device)
-    }
-
-    // commandBuffers := pcommandBuffers[0:commandBufferCount]
-    // for i in (0 .. commandBufferCount) {
-    //    commandBuffer := commandBuffers[i]
-    //    commandBufferObject := GetCommandBuffer(commandBuffer)
-    //    assert(commandBufferObject.device == queueObject.device)
-    //
-    //    validate("QueueCheck", commandBufferObject.queueFlags in queueObject.flags,
-    //        "vkQueueSubmit: enqueued commandBuffer requires missing queue capabilities.")
-    // }
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkQueueWaitIdle(
-        VkQueue                                     queue) {
-    queueObject := GetQueue(queue)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkDeviceWaitIdle(
-        VkDevice                                    device) {
-    deviceObject := GetDevice(device)
-
-    return ?
-}
-
-
-// Memory functions
-
-@threadSafety("system")
-cmd VkResult vkAllocateMemory(
-        VkDevice                                    device,
-        const VkMemoryAllocateInfo*                 pAllocateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDeviceMemory*                             pMemory) {
-    assert(pAllocateInfo.sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO)
-    deviceObject := GetDevice(device)
-
-    memory := ?
-    pMemory[0] = memory
-    State.DeviceMemories[memory] = new!DeviceMemoryObject(
-        device: device,
-        allocationSize: pAllocateInfo[0].allocationSize)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkFreeMemory(
-        VkDevice                                    device,
-        VkDeviceMemory                              memory,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    memoryObject := GetDeviceMemory(memory)
-    assert(memoryObject.device == device)
-
-    // Check that no objects are still bound before freeing.
-    validate("MemoryCheck", len(memoryObject.boundObjects) == 0,
-        "vkFreeMemory: objects still bound")
-    validate("MemoryCheck", len(memoryObject.boundCommandBuffers) == 0,
-        "vkFreeMemory: commandBuffers still bound")
-    State.DeviceMemories[memory] = null
-}
-
-@threadSafety("app")
-cmd VkResult vkMapMemory(
-        VkDevice                                    device,
-        VkDeviceMemory                              memory,
-        VkDeviceSize                                offset,
-        VkDeviceSize                                size,
-        VkMemoryMapFlags                            flags,
-        void**                                      ppData) {
-    deviceObject := GetDevice(device)
-    memoryObject := GetDeviceMemory(memory)
-    assert(memoryObject.device == device)
-
-    assert(flags == as!VkMemoryMapFlags(0))
-    assert((offset + size) <= memoryObject.allocationSize)
-
-    return ?
-}
-
-@threadSafety("app")
-cmd void vkUnmapMemory(
-        VkDevice                                    device,
-        VkDeviceMemory                              memory) {
-    deviceObject := GetDevice(device)
-    memoryObject := GetDeviceMemory(memory)
-    assert(memoryObject.device == device)
-}
-
-cmd VkResult vkFlushMappedMemoryRanges(
-        VkDevice                                    device,
-        u32                                         memoryRangeCount
-        const VkMappedMemoryRange*                  pMemoryRanges) {
-    deviceObject := GetDevice(device)
-
-    memoryRanges := pMemoryRanges[0:memoryRangeCount]
-    for i in (0 .. memoryRangeCount) {
-        memoryRange := memoryRanges[i]
-        memoryObject := GetDeviceMemory(memoryRange.memory)
-        assert(memoryObject.device == device)
-        assert((memoryRange.offset + memoryRange.size) <= memoryObject.allocationSize)
-    }
-
-    return ?
-}
-
-cmd VkResult vkInvalidateMappedMemoryRanges(
-        VkDevice                                    device,
-        u32                                         memoryRangeCount,
-        const VkMappedMemoryRange*                  pMemoryRanges) {
-    deviceObject := GetDevice(device)
-
-    memoryRanges := pMemoryRanges[0:memoryRangeCount]
-    for i in (0 .. memoryRangeCount) {
-        memoryRange := memoryRanges[i]
-        memoryObject := GetDeviceMemory(memoryRange.memory)
-        assert(memoryObject.device == device)
-        assert((memoryRange.offset + memoryRange.size) <= memoryObject.allocationSize)
-    }
-
-    return ?
-}
-
-
-// Memory management API functions
-
-cmd void vkGetDeviceMemoryCommitment(
-        VkDevice                                    device,
-        VkDeviceMemory                              memory,
-        VkDeviceSize*                               pCommittedMemoryInBytes) {
-    deviceObject := GetDevice(device)
-
-    if memory != NULL_HANDLE {
-        memoryObject := GetDeviceMemory(memory)
-        assert(memoryObject.device == device)
-    }
-
-    committedMemoryInBytes := ?
-    pCommittedMemoryInBytes[0] = committedMemoryInBytes
-}
-
-cmd void vkGetBufferMemoryRequirements(
-        VkDevice                                    device,
-        VkBuffer                                    buffer,
-        VkMemoryRequirements*                       pMemoryRequirements) {
-    deviceObject := GetDevice(device)
-    bufferObject := GetBuffer(buffer)
-    assert(bufferObject.device == device)
-}
-
-cmd VkResult vkBindBufferMemory(
-        VkDevice                                    device,
-        VkBuffer                                    buffer,
-        VkDeviceMemory                              memory,
-        VkDeviceSize                                memoryOffset) {
-    deviceObject := GetDevice(device)
-    bufferObject := GetBuffer(buffer)
-    assert(bufferObject.device == device)
-
-    // Unbind buffer from previous memory object, if not VK_NULL_HANDLE.
-    if bufferObject.memory != NULL_HANDLE {
-        memoryObject := GetDeviceMemory(bufferObject.memory)
-        memoryObject.boundObjects[as!u64(buffer)] = null
-    }
-
-    // Bind buffer to given memory object, if not VK_NULL_HANDLE.
-    if memory != NULL_HANDLE {
-        memoryObject := GetDeviceMemory(memory)
-        assert(memoryObject.device == device)
-        memoryObject.boundObjects[as!u64(buffer)] = memoryOffset
-    }
-    bufferObject.memory = memory
-    bufferObject.memoryOffset = memoryOffset
-
-    return ?
-}
-
-cmd void vkGetImageMemoryRequirements(
-        VkDevice                                    device,
-        VkImage                                     image,
-        VkMemoryRequirements*                       pMemoryRequirements) {
-    deviceObject := GetDevice(device)
-    imageObject := GetImage(image)
-    assert(imageObject.device == device)
-}
-
-cmd VkResult vkBindImageMemory(
-        VkDevice                                    device,
-        VkImage                                     image,
-        VkDeviceMemory                              memory,
-        VkDeviceSize                                memoryOffset) {
-    deviceObject := GetDevice(device)
-    imageObject := GetImage(image)
-    assert(imageObject.device == device)
-
-    // Unbind image from previous memory object, if not VK_NULL_HANDLE.
-    if imageObject.memory != NULL_HANDLE {
-        memoryObject := GetDeviceMemory(imageObject.memory)
-        memoryObject.boundObjects[as!u64(image)] = null
-    }
-
-    // Bind image to given memory object, if not VK_NULL_HANDLE.
-    if memory != NULL_HANDLE {
-        memoryObject := GetDeviceMemory(memory)
-        assert(memoryObject.device == device)
-        memoryObject.boundObjects[as!u64(image)] = memoryOffset
-    }
-    imageObject.memory = memory
-    imageObject.memoryOffset = memoryOffset
-
-    return ?
-}
-
-cmd void vkGetImageSparseMemoryRequirements(
-        VkDevice                                    device,
-        VkImage                                     image,
-        u32*                                        pSparseMemoryRequirementCount,
-        VkSparseImageMemoryRequirements*            pSparseMemoryRequirements) {
-    deviceObject := GetDevice(device)
-    imageObject := GetImage(image)
-    assert(imageObject.device == device)
-}
-
-cmd void vkGetPhysicalDeviceSparseImageFormatProperties(
-        VkPhysicalDevice                            physicalDevice,
-        VkFormat                                    format,
-        VkImageType                                 type,
-        VkSampleCountFlagBits                       samples,
-        VkImageUsageFlags                           usage,
-        VkImageTiling                               tiling,
-        u32*                                        pPropertyCount,
-        VkSparseImageFormatProperties*              pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-}
-
-cmd VkResult vkQueueBindSparse(
-        VkQueue                                     queue,
-        u32                                         bindInfoCount,
-        const VkBindSparseInfo*                     pBindInfo,
-        VkFence                                     fence) {
-    queueObject := GetQueue(queue)
-
-    return ?
-}
-
-
-// Fence functions
-
-@threadSafety("system")
-cmd VkResult vkCreateFence(
-        VkDevice                                    device,
-        const VkFenceCreateInfo*                    pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkFence*                                    pFence) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    fence := ?
-    pFence[0] = fence
-    State.Fences[fence] = new!FenceObject(
-        device: device, signaled: (pCreateInfo.flags == as!VkFenceCreateFlags(VK_FENCE_CREATE_SIGNALED_BIT)))
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyFence(
-        VkDevice                                    device,
-        VkFence                                     fence,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    fenceObject := GetFence(fence)
-    assert(fenceObject.device == device)
-
-    State.Fences[fence] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkResetFences(
-        VkDevice                                    device,
-        u32                                         fenceCount,
-        const VkFence*                              pFences) {
-    deviceObject := GetDevice(device)
-
-    fences := pFences[0:fenceCount]
-    for i in (0 .. fenceCount) {
-        fence := fences[i]
-        fenceObject := GetFence(fence)
-        assert(fenceObject.device == device)
-        fenceObject.signaled = false
-    }
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkGetFenceStatus(
-        VkDevice                                    device,
-        VkFence                                     fence) {
-    deviceObject := GetDevice(device)
-    fenceObject := GetFence(fence)
-    assert(fenceObject.device == device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkWaitForFences(
-        VkDevice                                    device,
-        u32                                         fenceCount,
-        const VkFence*                              pFences,
-        VkBool32                                    waitAll,
-        u64                                         timeout) {  /// timeout in nanoseconds
-    deviceObject := GetDevice(device)
-
-    fences := pFences[0:fenceCount]
-    for i in (0 .. fenceCount) {
-        fence := fences[i]
-        fenceObject := GetFence(fence)
-        assert(fenceObject.device == device)
-    }
-
-    return ?
-}
-
-
-// Queue semaphore functions
-
-@threadSafety("system")
-cmd VkResult vkCreateSemaphore(
-        VkDevice                                    device,
-        const VkSemaphoreCreateInfo*                pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSemaphore*                                pSemaphore) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    semaphore := ?
-    pSemaphore[0] = semaphore
-    State.Semaphores[semaphore] = new!SemaphoreObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroySemaphore(
-        VkDevice                                    device,
-        VkSemaphore                                 semaphore,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    semaphoreObject := GetSemaphore(semaphore)
-    assert(semaphoreObject.device == device)
-
-    State.Semaphores[semaphore] = null
-}
-
-
-// Event functions
-
-@threadSafety("system")
-cmd VkResult vkCreateEvent(
-        VkDevice                                    device,
-        const VkEventCreateInfo*                    pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkEvent*                                    pEvent) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_EVENT_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    event := ?
-    pEvent[0] = event
-    State.Events[event] = new!EventObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyEvent(
-        VkDevice                                    device,
-        VkEvent                                     event,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    eventObject := GetEvent(event)
-    assert(eventObject.device == device)
-
-    State.Events[event] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkGetEventStatus(
-        VkDevice                                    device,
-        VkEvent                                     event) {
-    deviceObject := GetDevice(device)
-    eventObject := GetEvent(event)
-    assert(eventObject.device == device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkSetEvent(
-        VkDevice                                    device,
-        VkEvent                                     event) {
-    deviceObject := GetDevice(device)
-    eventObject := GetEvent(event)
-    assert(eventObject.device == device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd VkResult vkResetEvent(
-        VkDevice                                    device,
-        VkEvent                                     event) {
-    deviceObject := GetDevice(device)
-    eventObject := GetEvent(event)
-    assert(eventObject.device == device)
-
-    return ?
-}
-
-
-// Query functions
-
-@threadSafety("system")
-cmd VkResult vkCreateQueryPool(
-        VkDevice                                    device,
-        const VkQueryPoolCreateInfo*                pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkQueryPool*                                pQueryPool) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    queryPool := ?
-    pQueryPool[0] = queryPool
-    State.QueryPools[queryPool] = new!QueryPoolObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyQueryPool(
-        VkDevice                                    device,
-        VkQueryPool                                 queryPool,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(queryPoolObject.device == device)
-
-    State.QueryPools[queryPool] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkGetQueryPoolResults(
-        VkDevice                                    device,
-        VkQueryPool                                 queryPool,
-        u32                                         firstQuery,
-        u32                                         queryCount,
-        platform.size_t                             dataSize,
-        void*                                       pData,
-        VkDeviceSize                                stride,
-        VkQueryResultFlags                          flags) {
-    deviceObject := GetDevice(device)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(queryPoolObject.device == device)
-
-    data := pData[0:dataSize]
-
-    return ?
-}
-
-// Buffer functions
-
-@threadSafety("system")
-cmd VkResult vkCreateBuffer(
-        VkDevice                                    device,
-        const VkBufferCreateInfo*                   pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkBuffer*                                   pBuffer) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    buffer := ?
-    pBuffer[0] = buffer
-    State.Buffers[buffer] = new!BufferObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyBuffer(
-        VkDevice                                    device,
-        VkBuffer                                    buffer,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    bufferObject := GetBuffer(buffer)
-    assert(bufferObject.device == device)
-
-    assert(bufferObject.memory == 0)
-    State.Buffers[buffer] = null
-}
-
-
-// Buffer view functions
-
-@threadSafety("system")
-cmd VkResult vkCreateBufferView(
-        VkDevice                                    device,
-        const VkBufferViewCreateInfo*               pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkBufferView*                               pView) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    bufferObject := GetBuffer(pCreateInfo.buffer)
-    assert(bufferObject.device == device)
-
-    view := ?
-    pView[0] = view
-    State.BufferViews[view] = new!BufferViewObject(device: device, buffer: pCreateInfo.buffer)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyBufferView(
-        VkDevice                                    device,
-        VkBufferView                                bufferView,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    bufferViewObject := GetBufferView(bufferView)
-    assert(bufferViewObject.device == device)
-
-    State.BufferViews[bufferView] = null
-}
-
-
-// Image functions
-
-@threadSafety("system")
-cmd VkResult vkCreateImage(
-        VkDevice                                    device,
-        const VkImageCreateInfo*                    pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkImage*                                    pImage) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    image := ?
-    pImage[0] = image
-    State.Images[image] = new!ImageObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyImage(
-        VkDevice                                    device,
-        VkImage                                     image,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    imageObject := GetImage(image)
-    assert(imageObject.device == device)
-
-    assert(imageObject.memory == 0)
-    State.Images[image] = null
-}
-
-cmd void vkGetImageSubresourceLayout(
-        VkDevice                                    device,
-        VkImage                                     image,
-        const VkImageSubresource*                   pSubresource,
-        VkSubresourceLayout*                        pLayout) {
-    deviceObject := GetDevice(device)
-    imageObject := GetImage(image)
-    assert(imageObject.device == device)
-}
-
-
-// Image view functions
-
-@threadSafety("system")
-cmd VkResult vkCreateImageView(
-        VkDevice                                    device,
-        const VkImageViewCreateInfo*                pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkImageView*                                pView) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    imageObject := GetImage(pCreateInfo.image)
-    assert(imageObject.device == device)
-
-    view := ?
-    pView[0] = view
-    State.ImageViews[view] = new!ImageViewObject(device: device, image: pCreateInfo.image)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyImageView(
-        VkDevice                                    device,
-        VkImageView                                 imageView,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    imageViewObject := GetImageView(imageView)
-    assert(imageViewObject.device == device)
-
-    State.ImageViews[imageView] = null
-}
-
-
-// Shader functions
-
-cmd VkResult vkCreateShaderModule(
-        VkDevice                                    device,
-        const VkShaderModuleCreateInfo*             pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkShaderModule*                             pShaderModule) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    shaderModule := ?
-    pShaderModule[0] = shaderModule
-    State.ShaderModules[shaderModule] = new!ShaderModuleObject(device: device)
-
-    return ?
-}
-
-cmd void vkDestroyShaderModule(
-        VkDevice                                    device,
-        VkShaderModule                              shaderModule,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    shaderModuleObject := GetShaderModule(shaderModule)
-    assert(shaderModuleObject.device == device)
-
-    State.ShaderModules[shaderModule] = null
-}
-
-
-// Pipeline functions
-
-cmd VkResult vkCreatePipelineCache(
-        VkDevice                                    device,
-        const VkPipelineCacheCreateInfo*            pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkPipelineCache*                            pPipelineCache) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    pipelineCache := ?
-    pPipelineCache[0] = pipelineCache
-    State.PipelineCaches[pipelineCache] = new!PipelineCacheObject(device: device)
-
-    return ?
-}
-
-cmd void vkDestroyPipelineCache(
-        VkDevice                                    device,
-        VkPipelineCache                             pipelineCache,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    pipelineCacheObject := GetPipelineCache(pipelineCache)
-    assert(pipelineCacheObject.device == device)
-
-    State.PipelineCaches[pipelineCache] = null
-}
-
-cmd VkResult vkGetPipelineCacheData(
-        VkDevice                                    device,
-        VkPipelineCache                             pipelineCache,
-        platform.size_t*                            pDataSize,
-        void*                                       pData) {
-    deviceObject := GetDevice(device)
-    pipelineCacheObject := GetPipelineCache(pipelineCache)
-    assert(pipelineCacheObject.device == device)
-
-    return ?
-}
-
-cmd VkResult vkMergePipelineCaches(
-        VkDevice                                    device,
-        VkPipelineCache                             dstCache,
-        u32                                         srcCacheCount,
-        const VkPipelineCache*                      pSrcCaches) {
-    deviceObject := GetDevice(device)
-    dstCacheObject := GetPipelineCache(dstCache)
-    assert(dstCacheObject.device == device)
-
-    srcCaches := pSrcCaches[0:srcCacheCount]
-    for i in (0 .. srcCacheCount) {
-        srcCache := srcCaches[i]
-        srcCacheObject := GetPipelineCache(srcCache)
-        assert(srcCacheObject.device == device)
-    }
-
-    return ?
-}
-
-cmd VkResult vkCreateGraphicsPipelines(
-        VkDevice                                    device,
-        VkPipelineCache                             pipelineCache,
-        u32                                         createInfoCount,
-        const VkGraphicsPipelineCreateInfo*         pCreateInfos,
-        const VkAllocationCallbacks*                pAllocator,
-        VkPipeline*                                 pPipelines) {
-    deviceObject := GetDevice(device)
-    if pipelineCache != NULL_HANDLE {
-        pipelineCacheObject := GetPipelineCache(pipelineCache)
-        assert(pipelineCacheObject.device == device)
-    }
-
-    createInfos := pCreateInfos[0:createInfoCount]
-    pipelines := pPipelines[0:createInfoCount]
-    for i in (0 .. createInfoCount) {
-        pipeline := ?
-        pipelines[i] = pipeline
-        State.Pipelines[pipeline] = new!PipelineObject(device: device)
-    }
-
-    return ?
-}
-
-cmd VkResult vkCreateComputePipelines(
-        VkDevice                                    device,
-        VkPipelineCache                             pipelineCache,
-        u32                                         createInfoCount,
-        const VkComputePipelineCreateInfo*          pCreateInfos,
-        const VkAllocationCallbacks*                pAllocator,
-        VkPipeline*                                 pPipelines) {
-    deviceObject := GetDevice(device)
-    if pipelineCache != NULL_HANDLE {
-        pipelineCacheObject := GetPipelineCache(pipelineCache)
-        assert(pipelineCacheObject.device == device)
-    }
-
-    createInfos := pCreateInfos[0:createInfoCount]
-    pipelines := pPipelines[0:createInfoCount]
-    for i in (0 .. createInfoCount) {
-        pipeline := ?
-        pipelines[i] = pipeline
-        State.Pipelines[pipeline] = new!PipelineObject(device: device)
-    }
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyPipeline(
-        VkDevice                                    device,
-        VkPipeline                                  pipeline,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    pipelineObjects := GetPipeline(pipeline)
-    assert(pipelineObjects.device == device)
-
-    State.Pipelines[pipeline] = null
-}
-
-
-// Pipeline layout functions
-
-@threadSafety("system")
-cmd VkResult vkCreatePipelineLayout(
-        VkDevice                                    device,
-        const VkPipelineLayoutCreateInfo*           pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkPipelineLayout*                           pPipelineLayout) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    pipelineLayout := ?
-    pPipelineLayout[0] = pipelineLayout
-    State.PipelineLayouts[pipelineLayout] = new!PipelineLayoutObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyPipelineLayout(
-        VkDevice                                    device,
-        VkPipelineLayout                            pipelineLayout,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    pipelineLayoutObjects := GetPipelineLayout(pipelineLayout)
-    assert(pipelineLayoutObjects.device == device)
-
-    State.PipelineLayouts[pipelineLayout] = null
-}
-
-
-// Sampler functions
-
-@threadSafety("system")
-cmd VkResult vkCreateSampler(
-        VkDevice                                    device,
-        const VkSamplerCreateInfo*                  pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSampler*                                  pSampler) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    sampler := ?
-    pSampler[0] = sampler
-    State.Samplers[sampler] = new!SamplerObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroySampler(
-        VkDevice                                    device,
-        VkSampler                                   sampler,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    samplerObject := GetSampler(sampler)
-    assert(samplerObject.device == device)
-
-    State.Samplers[sampler] = null
-}
-
-
-// Descriptor set functions
-
-@threadSafety("system")
-cmd VkResult vkCreateDescriptorSetLayout(
-        VkDevice                                    device,
-        const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDescriptorSetLayout*                      pSetLayout) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    setLayout := ?
-    pSetLayout[0] = setLayout
-    State.DescriptorSetLayouts[setLayout] = new!DescriptorSetLayoutObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyDescriptorSetLayout(
-        VkDevice                                    device,
-        VkDescriptorSetLayout                       descriptorSetLayout,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    descriptorSetLayoutObject := GetDescriptorSetLayout(descriptorSetLayout)
-    assert(descriptorSetLayoutObject.device == device)
-
-    State.DescriptorSetLayouts[descriptorSetLayout] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkCreateDescriptorPool(
-        VkDevice                                    device,
-        const VkDescriptorPoolCreateInfo*           pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDescriptorPool*                           pDescriptorPool) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    descriptorPool := ?
-    pDescriptorPool[0] = descriptorPool
-    State.DescriptorPools[descriptorPool] = new!DescriptorPoolObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyDescriptorPool(
-        VkDevice                                    device,
-        VkDescriptorPool                            descriptorPool,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    descriptorPoolObject := GetDescriptorPool(descriptorPool)
-    assert(descriptorPoolObject.device == device)
-
-    State.DescriptorPools[descriptorPool] = null
-}
-
-@threadSafety("app")
-cmd VkResult vkResetDescriptorPool(
-        VkDevice                                    device,
-        VkDescriptorPool                            descriptorPool,
-        VkDescriptorPoolResetFlags                  flags) {
-    deviceObject := GetDevice(device)
-    descriptorPoolObject := GetDescriptorPool(descriptorPool)
-    assert(descriptorPoolObject.device == device)
-
-    return ?
-}
-
-@threadSafety("app")
-cmd VkResult vkAllocateDescriptorSets(
-        VkDevice                                    device,
-        const VkDescriptorSetAllocateInfo*          pAllocateInfo,
-        VkDescriptorSet*                            pDescriptorSets) {
-    deviceObject := GetDevice(device)
-    allocInfo := pAllocateInfo[0]
-    descriptorPoolObject := GetDescriptorPool(allocInfo.descriptorPool)
-
-    setLayouts := allocInfo.pSetLayouts[0:allocInfo.setCount]
-    for i in (0 .. allocInfo.setCount) {
-        setLayout := setLayouts[i]
-        setLayoutObject := GetDescriptorSetLayout(setLayout)
-        assert(setLayoutObject.device == device)
-    }
-
-    descriptorSets := pDescriptorSets[0:allocInfo.setCount]
-    for i in (0 .. allocInfo.setCount) {
-        descriptorSet := ?
-        descriptorSets[i] = descriptorSet
-        State.DescriptorSets[descriptorSet] = new!DescriptorSetObject(device: device)
-    }
-
-    return ?
-}
-
-cmd VkResult vkFreeDescriptorSets(
-        VkDevice                                    device,
-        VkDescriptorPool                            descriptorPool,
-        u32                                         descriptorSetCount,
-        const VkDescriptorSet*                      pDescriptorSets) {
-    deviceObject := GetDevice(device)
-    descriptorPoolObject := GetDescriptorPool(descriptorPool)
-
-    descriptorSets := pDescriptorSets[0:descriptorSetCount]
-    for i in (0 .. descriptorSetCount) {
-        descriptorSet := descriptorSets[i]
-        descriptorSetObject := GetDescriptorSet(descriptorSet)
-        assert(descriptorSetObject.device == device)
-        State.DescriptorSets[descriptorSet] = null
-    }
-
-    return ?
-}
-
-cmd void vkUpdateDescriptorSets(
-        VkDevice                                    device,
-        u32                                         descriptorWriteCount,
-        const VkWriteDescriptorSet*                 pDescriptorWrites,
-        u32                                         descriptorCopyCount,
-        const VkCopyDescriptorSet*                  pDescriptorCopies) {
-    deviceObject := GetDevice(device)
-
-    descriptorWrites := pDescriptorWrites[0:descriptorWriteCount]
-    for i in (0 .. descriptorWriteCount) {
-        descriptorWrite := descriptorWrites[i]
-        descriptorWriteObject := GetDescriptorSet(descriptorWrite.dstSet)
-        assert(descriptorWriteObject.device == device)
-    }
-
-    descriptorCopies := pDescriptorCopies[0:descriptorCopyCount]
-    for i in (0 .. descriptorCopyCount) {
-        descriptorCopy := descriptorCopies[i]
-        descriptorCopyObject := GetDescriptorSet(descriptorCopy.dstSet)
-        assert(descriptorCopyObject.device == device)
-    }
-}
-
-
-// Framebuffer functions
-
-@threadSafety("system")
-cmd VkResult vkCreateFramebuffer(
-        VkDevice                                    device,
-        const VkFramebufferCreateInfo*              pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkFramebuffer*                              pFramebuffer) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    framebuffer := ?
-    pFramebuffer[0] = framebuffer
-    State.Framebuffers[framebuffer] = new!FramebufferObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyFramebuffer(
-        VkDevice                                    device,
-        VkFramebuffer                               framebuffer,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    framebufferObject := GetFramebuffer(framebuffer)
-    assert(framebufferObject.device == device)
-
-    State.Framebuffers[framebuffer] = null
-}
-
-
-// Renderpass functions
-
-@threadSafety("system")
-cmd VkResult vkCreateRenderPass(
-        VkDevice                                    device,
-        const VkRenderPassCreateInfo*               pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkRenderPass*                               pRenderPass) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    renderpass := ?
-    pRenderPass[0] = renderpass
-    State.RenderPasses[renderpass] = new!RenderPassObject(device: device)
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkDestroyRenderPass(
-        VkDevice                                    device,
-        VkRenderPass                                renderPass,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    renderPassObject := GetRenderPass(renderPass)
-    assert(renderPassObject.device == device)
-
-    State.RenderPasses[renderPass] = null
-}
-
-cmd void vkGetRenderAreaGranularity(
-        VkDevice                                    device,
-        VkRenderPass                                renderPass,
-        VkExtent2D*                                 pGranularity) {
-    deviceObject := GetDevice(device)
-    renderPassObject := GetRenderPass(renderPass)
-
-    granularity := ?
-    pGranularity[0] = granularity
-}
-
-// Command pool functions
-
-cmd VkResult vkCreateCommandPool(
-        VkDevice                                    device,
-        const VkCommandPoolCreateInfo*              pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkCommandPool*                              pCommandPool) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO)
-    deviceObject := GetDevice(device)
-
-    commandPool := ?
-    pCommandPool[0] = commandPool
-    State.CommandPools[commandPool] = new!CommandPoolObject(device: device)
-
-    return ?
-}
-
-cmd void vkDestroyCommandPool(
-        VkDevice                                    device,
-        VkCommandPool                               commandPool,
-        const VkAllocationCallbacks*                pAllocator) {
-    deviceObject := GetDevice(device)
-    commandPoolObject := GetCommandPool(commandPool)
-    assert(commandPoolObject.device == device)
-
-    State.CommandPools[commandPool] = null
-}
-
-cmd VkResult vkResetCommandPool(
-        VkDevice                                    device,
-        VkCommandPool                               commandPool,
-        VkCommandPoolResetFlags                     flags) {
-    deviceObject := GetDevice(device)
-    commandPoolObject := GetCommandPool(commandPool)
-    assert(commandPoolObject.device == device)
-
-    return ?
-}
-
-// Command buffer functions
-
-macro void bindCommandBuffer(VkCommandBuffer commandBuffer, any obj, VkDeviceMemory memory) {
-    memoryObject := GetDeviceMemory(memory)
-    memoryObject.boundCommandBuffers[commandBuffer] = commandBuffer
-
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.boundObjects[as!u64(obj)] = memory
-}
-
-macro void unbindCommandBuffer(VkCommandBuffer commandBuffer, any obj, VkDeviceMemory memory) {
-    memoryObject := GetDeviceMemory(memory)
-    memoryObject.boundCommandBuffers[commandBuffer] = null
-
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.boundObjects[as!u64(obj)] = null
-}
-
-@threadSafety("system")
-cmd VkResult vkAllocateCommandBuffers(
-        VkDevice                                    device,
-        const VkCommandBufferAllocateInfo*          pAllocateInfo,
-        VkCommandBuffer*                            pCommandBuffers) {
-    assert(pAllocateInfo[0].sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO)
-
-    count := pAllocateInfo[0].commandBufferCount
-    commandBuffers := pCommandBuffers[0:count]
-    for i in (0 .. count) {
-        commandBuffer := ?
-        commandBuffers[i] = commandBuffer
-        State.CommandBuffers[commandBuffer] = new!CommandBufferObject(device: device)
-    }
-
-    return ?
-}
-
-@threadSafety("system")
-cmd void vkFreeCommandBuffers(
-        VkDevice                                    device,
-        VkCommandPool                               commandPool,
-        u32                                         commandBufferCount,
-        const VkCommandBuffer*                      pCommandBuffers) {
-    deviceObject := GetDevice(device)
-
-    commandBuffers := pCommandBuffers[0:commandBufferCount]
-    for i in (0 .. commandBufferCount) {
-        commandBufferObject := GetCommandBuffer(commandBuffers[i])
-        assert(commandBufferObject.device == device)
-        // TODO: iterate over boundObjects and clear memory bindings
-        State.CommandBuffers[commandBuffers[i]] = null
-    }
-}
-
-@threadSafety("app")
-cmd VkResult vkBeginCommandBuffer(
-        VkCommandBuffer                             commandBuffer,
-        const VkCommandBufferBeginInfo*             pBeginInfo) {
-    assert(pBeginInfo.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO)
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    // TODO: iterate over boundObjects and clear memory bindings
-
-    return ?
-}
-
-@threadSafety("app")
-cmd VkResult vkEndCommandBuffer(
-        VkCommandBuffer                             commandBuffer) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    return ?
-}
-
-@threadSafety("app")
-cmd VkResult vkResetCommandBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkCommandBufferResetFlags                   flags) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    // TODO: iterate over boundObjects and clear memory bindings
-
-    return ?
-}
-
-
-// Command buffer building functions
-
-@threadSafety("app")
-cmd void vkCmdBindPipeline(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineBindPoint                         pipelineBindPoint,
-        VkPipeline                                  pipeline) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    pipelineObject := GetPipeline(pipeline)
-    assert(commandBufferObject.device == pipelineObject.device)
-
-    queue := switch (pipelineBindPoint) {
-        case VK_PIPELINE_BIND_POINT_COMPUTE:  VK_QUEUE_COMPUTE_BIT
-        case VK_PIPELINE_BIND_POINT_GRAPHICS: VK_QUEUE_GRAPHICS_BIT
-    }
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, queue)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetViewport(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstViewport,
-        u32                                         viewportCount,
-        const VkViewport*                           pViewports) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetScissor(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstScissor,
-        u32                                         scissorCount,
-        const VkRect2D*                             pScissors) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetLineWidth(
-        VkCommandBuffer                             commandBuffer,
-        f32                                         lineWidth) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetDepthBias(
-        VkCommandBuffer                             commandBuffer,
-        f32                                         depthBiasConstantFactor,
-        f32                                         depthBiasClamp,
-        f32                                         depthBiasSlopeFactor) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetBlendConstants(
-        VkCommandBuffer                             commandBuffer,
-        // TODO(jessehall): apic only supports 'const' on pointer types. Using
-        // an annotation as a quick hack to pass this to the template without
-        // having to modify the AST and semantic model.
-        @readonly f32[4]                            blendConstants) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetDepthBounds(
-        VkCommandBuffer                             commandBuffer,
-        f32                                         minDepthBounds,
-        f32                                         maxDepthBounds) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetStencilCompareMask(
-        VkCommandBuffer                             commandBuffer,
-        VkStencilFaceFlags                          faceMask,
-        u32                                         compareMask) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetStencilWriteMask(
-        VkCommandBuffer                             commandBuffer,
-        VkStencilFaceFlags                          faceMask,
-        u32                                         writeMask) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetStencilReference(
-        VkCommandBuffer                             commandBuffer,
-        VkStencilFaceFlags                          faceMask,
-        u32                                         reference) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdBindDescriptorSets(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineBindPoint                         pipelineBindPoint,
-        VkPipelineLayout                            layout,
-        u32                                         firstSet,
-        u32                                         descriptorSetCount,
-        const VkDescriptorSet*                      pDescriptorSets,
-        u32                                         dynamicOffsetCount,
-        const u32*                                  pDynamicOffsets) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    descriptorSets := pDescriptorSets[0:descriptorSetCount]
-    for i in (0 .. descriptorSetCount) {
-        descriptorSet := descriptorSets[i]
-        descriptorSetObject := GetDescriptorSet(descriptorSet)
-        assert(commandBufferObject.device == descriptorSetObject.device)
-    }
-
-    dynamicOffsets := pDynamicOffsets[0:dynamicOffsetCount]
-    for i in (0 .. dynamicOffsetCount) {
-        dynamicOffset := dynamicOffsets[i]
-    }
-
-    queue := switch (pipelineBindPoint) {
-        case VK_PIPELINE_BIND_POINT_COMPUTE:  VK_QUEUE_COMPUTE_BIT
-        case VK_PIPELINE_BIND_POINT_GRAPHICS: VK_QUEUE_GRAPHICS_BIT
-    }
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, queue)
-}
-
-@threadSafety("app")
-cmd void vkCmdBindIndexBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkIndexType                                 indexType) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    bufferObject := GetBuffer(buffer)
-    assert(commandBufferObject.device == bufferObject.device)
-
-    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdBindVertexBuffers(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstBinding,
-        u32                                         bindingCount,
-        const VkBuffer*                             pBuffers,
-        const VkDeviceSize*                         pOffsets) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    // TODO: check if not [firstBinding:firstBinding+bindingCount]
-    buffers := pBuffers[0:bindingCount]
-    offsets := pOffsets[0:bindingCount]
-    for i in (0 .. bindingCount) {
-        buffer := buffers[i]
-        offset := offsets[i]
-        bufferObject := GetBuffer(buffer)
-        assert(commandBufferObject.device == bufferObject.device)
-
-        bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
-    }
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDraw(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         vertexCount,
-        u32                                         instanceCount,
-        u32                                         firstVertex,
-        u32                                         firstInstance) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDrawIndexed(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         indexCount,
-        u32                                         instanceCount,
-        u32                                         firstIndex,
-        s32                                         vertexOffset,
-        u32                                         firstInstance) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDrawIndirect(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        u32                                         drawCount,
-        u32                                         stride) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    bufferObject := GetBuffer(buffer)
-    assert(commandBufferObject.device == bufferObject.device)
-
-    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDrawIndexedIndirect(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        u32                                         drawCount,
-        u32                                         stride) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    bufferObject := GetBuffer(buffer)
-    assert(commandBufferObject.device == bufferObject.device)
-
-    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDispatch(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         groupCountX,
-        u32                                         groupCountY,
-        u32                                         groupCountZ) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_COMPUTE_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdDispatchIndirect(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    bufferObject := GetBuffer(buffer)
-    assert(commandBufferObject.device == bufferObject.device)
-
-    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_COMPUTE_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdCopyBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    srcBuffer,
-        VkBuffer                                    dstBuffer,
-        u32                                         regionCount,
-        const VkBufferCopy*                         pRegions) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcBufferObject := GetBuffer(srcBuffer)
-    dstBufferObject := GetBuffer(dstBuffer)
-    assert(commandBufferObject.device == srcBufferObject.device)
-    assert(commandBufferObject.device == dstBufferObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcBuffer, srcBufferObject.memory)
-    bindCommandBuffer(commandBuffer, dstBuffer, dstBufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdCopyImage(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     srcImage,
-        VkImageLayout                               srcImageLayout,
-        VkImage                                     dstImage,
-        VkImageLayout                               dstImageLayout,
-        u32                                         regionCount,
-        const VkImageCopy*                          pRegions) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcImageObject := GetImage(srcImage)
-    dstImageObject := GetImage(dstImage)
-    assert(commandBufferObject.device == srcImageObject.device)
-    assert(commandBufferObject.device == dstImageObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
-    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdBlitImage(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     srcImage,
-        VkImageLayout                               srcImageLayout,
-        VkImage                                     dstImage,
-        VkImageLayout                               dstImageLayout,
-        u32                                         regionCount,
-        const VkImageBlit*                          pRegions,
-        VkFilter                                    filter) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcImageObject := GetImage(srcImage)
-    dstImageObject := GetImage(dstImage)
-    assert(commandBufferObject.device == srcImageObject.device)
-    assert(commandBufferObject.device == dstImageObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
-    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdCopyBufferToImage(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    srcBuffer,
-        VkImage                                     dstImage,
-        VkImageLayout                               dstImageLayout,
-        u32                                         regionCount,
-        const VkBufferImageCopy*                    pRegions) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcBufferObject := GetBuffer(srcBuffer)
-    dstImageObject := GetImage(dstImage)
-    assert(commandBufferObject.device == srcBufferObject.device)
-    assert(commandBufferObject.device == dstImageObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcBuffer, srcBufferObject.memory)
-    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdCopyImageToBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     srcImage,
-        VkImageLayout                               srcImageLayout,
-        VkBuffer                                    dstBuffer,
-        u32                                         regionCount,
-        const VkBufferImageCopy*                    pRegions) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcImageObject := GetImage(srcImage)
-    dstBufferObject := GetBuffer(dstBuffer)
-    assert(commandBufferObject.device == srcImageObject.device)
-    assert(commandBufferObject.device == dstBufferObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
-    bindCommandBuffer(commandBuffer, dstBuffer, dstBufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdUpdateBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    dstBuffer,
-        VkDeviceSize                                dstOffset,
-        VkDeviceSize                                dataSize,
-        const void*                                 pData) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    dstBufferObject := GetBuffer(dstBuffer)
-    assert(commandBufferObject.device == dstBufferObject.device)
-
-    data := pData[0:dataSize]
-
-    bindCommandBuffer(commandBuffer, dstBuffer, dstBufferObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdFillBuffer(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    dstBuffer,
-        VkDeviceSize                                dstOffset,
-        VkDeviceSize                                size,
-        u32                                         data) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    dstBufferObject := GetBuffer(dstBuffer)
-    assert(commandBufferObject.device == dstBufferObject.device)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdClearColorImage(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     image,
-        VkImageLayout                               imageLayout,
-        const VkClearColorValue*                    pColor,
-        u32                                         rangeCount,
-        const VkImageSubresourceRange*              pRanges) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    imageObject := GetImage(image)
-    assert(commandBufferObject.device == imageObject.device)
-
-    ranges := pRanges[0:rangeCount]
-    for i in (0 .. rangeCount) {
-        range := ranges[i]
-    }
-
-    bindCommandBuffer(commandBuffer, image, imageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdClearDepthStencilImage(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     image,
-        VkImageLayout                               imageLayout,
-        const VkClearDepthStencilValue*             pDepthStencil,
-        u32                                         rangeCount,
-        const VkImageSubresourceRange*              pRanges) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    imageObject := GetImage(image)
-    assert(commandBufferObject.device == imageObject.device)
-
-    ranges := pRanges[0:rangeCount]
-    for i in (0 .. rangeCount) {
-        range := ranges[i]
-    }
-
-    bindCommandBuffer(commandBuffer, image, imageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdClearAttachments(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         attachmentCount,
-        const VkClearAttachment*                    pAttachments,
-        u32                                         rectCount,
-        const VkClearRect*                          pRects) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    rects := pRects[0:rectCount]
-    for i in (0 .. rectCount) {
-        rect := rects[i]
-    }
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdResolveImage(
-        VkCommandBuffer                             commandBuffer,
-        VkImage                                     srcImage,
-        VkImageLayout                               srcImageLayout,
-        VkImage                                     dstImage,
-        VkImageLayout                               dstImageLayout,
-        u32                                         regionCount,
-        const VkImageResolve*                       pRegions) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    srcImageObject := GetImage(srcImage)
-    dstImageObject := GetImage(dstImage)
-    assert(commandBufferObject.device == srcImageObject.device)
-    assert(commandBufferObject.device == dstImageObject.device)
-
-    regions := pRegions[0:regionCount]
-    for i in (0 .. regionCount) {
-        region := regions[i]
-    }
-
-    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
-    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-@threadSafety("app")
-cmd void vkCmdSetEvent(
-        VkCommandBuffer                             commandBuffer,
-        VkEvent                                     event,
-        VkPipelineStageFlags                        stageMask) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    eventObject := GetEvent(event)
-    assert(commandBufferObject.device == eventObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdResetEvent(
-        VkCommandBuffer                             commandBuffer,
-        VkEvent                                     event,
-        VkPipelineStageFlags                        stageMask) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    eventObject := GetEvent(event)
-    assert(commandBufferObject.device == eventObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdWaitEvents(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         eventCount,
-        const VkEvent*                              pEvents,
-        VkPipelineStageFlags                        srcStageMask,
-        VkPipelineStageFlags                        dstStageMask,
-        u32                                         memoryBarrierCount,
-        const VkMemoryBarrier*                      pMemoryBarriers,
-        u32                                         bufferMemoryBarrierCount,
-        const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
-        u32                                         imageMemoryBarrierCount,
-        const VkImageMemoryBarrier*                 pImageMemoryBarriers) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    events := pEvents[0:eventCount]
-    for i in (0 .. eventCount) {
-        event := events[i]
-        eventObject := GetEvent(event)
-        assert(commandBufferObject.device == eventObject.device)
-    }
-
-    memoryBarriers := pMemoryBarriers[0:memoryBarrierCount]
-    for i in (0 .. memoryBarrierCount) {
-        memoryBarrier := memoryBarriers[i]
-    }
-    bufferMemoryBarriers := pBufferMemoryBarriers[0:bufferMemoryBarrierCount]
-    for i in (0 .. bufferMemoryBarrierCount) {
-        bufferMemoryBarrier := bufferMemoryBarriers[i]
-        bufferObject := GetBuffer(bufferMemoryBarrier.buffer)
-        assert(bufferObject.device == commandBufferObject.device)
-    }
-    imageMemoryBarriers := pImageMemoryBarriers[0:imageMemoryBarrierCount]
-    for i in (0 .. imageMemoryBarrierCount) {
-        imageMemoryBarrier := imageMemoryBarriers[i]
-        imageObject := GetImage(imageMemoryBarrier.image)
-        assert(imageObject.device == commandBufferObject.device)
-    }
-}
-
-@threadSafety("app")
-cmd void vkCmdPipelineBarrier(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineStageFlags                        srcStageMask,
-        VkPipelineStageFlags                        dstStageMask,
-        VkDependencyFlags                           dependencyFlags,
-        u32                                         memoryBarrierCount,
-        const VkMemoryBarrier*                      pMemoryBarriers,
-        u32                                         bufferMemoryBarrierCount,
-        const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
-        u32                                         imageMemoryBarrierCount,
-        const VkImageMemoryBarrier*                 pImageMemoryBarriers) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    memoryBarriers := pMemoryBarriers[0:memoryBarrierCount]
-    for i in (0 .. memoryBarrierCount) {
-        memoryBarrier := memoryBarriers[i]
-    }
-    bufferMemoryBarriers := pBufferMemoryBarriers[0:bufferMemoryBarrierCount]
-    for i in (0 .. bufferMemoryBarrierCount) {
-        bufferMemoryBarrier := bufferMemoryBarriers[i]
-        bufferObject := GetBuffer(bufferMemoryBarrier.buffer)
-        assert(bufferObject.device == commandBufferObject.device)
-    }
-    imageMemoryBarriers := pImageMemoryBarriers[0:imageMemoryBarrierCount]
-    for i in (0 .. imageMemoryBarrierCount) {
-        imageMemoryBarrier := imageMemoryBarriers[i]
-        imageObject := GetImage(imageMemoryBarrier.image)
-        assert(imageObject.device == commandBufferObject.device)
-    }
-}
-
-@threadSafety("app")
-cmd void vkCmdBeginQuery(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         query,
-        VkQueryControlFlags                         flags) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(commandBufferObject.device == queryPoolObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdEndQuery(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         query) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(commandBufferObject.device == queryPoolObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdResetQueryPool(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         firstQuery,
-        u32                                         queryCount) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(commandBufferObject.device == queryPoolObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdWriteTimestamp(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineStageFlagBits                     pipelineStage,
-        VkQueryPool                                 queryPool,
-        u32                                         query) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    queryPoolObject := GetQueryPool(queryPool)
-    assert(commandBufferObject.device == queryPoolObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdCopyQueryPoolResults(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         firstQuery,
-        u32                                         queryCount,
-        VkBuffer                                    dstBuffer,
-        VkDeviceSize                                dstOffset,
-        VkDeviceSize                                stride,
-        VkQueryResultFlags                          flags) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    queryPoolObject := GetQueryPool(queryPool)
-    dstBufferObject := GetBuffer(dstBuffer)
-    assert(commandBufferObject.device == queryPoolObject.device)
-    assert(commandBufferObject.device == dstBufferObject.device)
-}
-
-cmd void vkCmdPushConstants(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineLayout                            layout,
-        VkShaderStageFlags                          stageFlags,
-        u32                                         offset,
-        u32                                         size,
-        const void*                                 pValues) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    layoutObject := GetPipelineLayout(layout)
-    assert(commandBufferObject.device == layoutObject.device)
-}
-
-@threadSafety("app")
-cmd void vkCmdBeginRenderPass(
-        VkCommandBuffer                             commandBuffer,
-        const VkRenderPassBeginInfo*                pRenderPassBegin,
-        VkSubpassContents                           contents) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-    renderPassObject := GetRenderPass(pRenderPassBegin.renderPass)
-    framebufferObject := GetFramebuffer(pRenderPassBegin.framebuffer)
-    assert(commandBufferObject.device == renderPassObject.device)
-    assert(commandBufferObject.device == framebufferObject.device)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-cmd void vkCmdNextSubpass(
-        VkCommandBuffer                             commandBuffer,
-        VkSubpassContents                           contents) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-}
-
-@threadSafety("app")
-cmd void vkCmdEndRenderPass(
-        VkCommandBuffer                             commandBuffer) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
-}
-
-cmd void vkCmdExecuteCommands(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         commandBufferCount,
-        const VkCommandBuffer*                      pCommandBuffers) {
-    commandBufferObject := GetCommandBuffer(commandBuffer)
-
-    commandBuffers := pCommandBuffers[0:commandBufferCount]
-    for i in (0 .. commandBufferCount) {
-        secondaryCommandBuffer := commandBuffers[i]
-        secondaryCommandBufferObject := GetCommandBuffer(secondaryCommandBuffer)
-        assert(commandBufferObject.device == secondaryCommandBufferObject.device)
-    }
-}
-
-//@vulkan1_1 functions
-
-@vulkan1_1
-cmd VkResult vkEnumerateInstanceVersion(
-        u32*                                            pApiVersion) {
-    return ?
-}
-
-@vulkan1_1
-cmd VkResult vkBindBufferMemory2(
-        VkDevice                                        device,
-        u32                                             bindInfoCount,
-        const VkBindBufferMemoryInfo*                   pBindInfos) {
-    return ?
-}
-
-@vulkan1_1
-cmd VkResult vkBindImageMemory2(
-        VkDevice                                        device,
-        u32                                             bindInfoCount,
-        const VkBindImageMemoryInfo*                    pBindInfos) {
-    return ?
-}
-
-@vulkan1_1
-cmd void vkGetDeviceGroupPeerMemoryFeatures(
-        VkDevice                                    device,
-        u32                                         heapIndex,
-        u32                                         localDeviceIndex,
-        u32                                         remoteDeviceIndex,
-        VkPeerMemoryFeatureFlags*                   pPeerMemoryFeatures) {
-}
-
-@vulkan1_1
-cmd void vkCmdSetDeviceMask(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         deviceMask) {
-}
-
-@vulkan1_1
-cmd void vkCmdDispatchBase(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         baseGroupX,
-        u32                                         baseGroupY,
-        u32                                         baseGroupZ,
-        u32                                         groupCountX,
-        u32                                         groupCountY,
-        u32                                         groupCountZ) {
-}
-
-@threadSafety("system")
-@vulkan1_1
-cmd VkResult vkEnumeratePhysicalDeviceGroups(
-        VkInstance                                  instance,
-        u32*                                        pPhysicalDeviceGroupCount,
-        VkPhysicalDeviceGroupProperties*            pPhysicalDeviceGroupProperties) {
-    instanceObject := GetInstance(instance)
-
-    physicalDeviceGroupCount := as!u32(?)
-    pPhysicalDeviceGroupCount[0] = physicalDeviceGroupCount
-    physicalDevices := pPhysicalDeviceGroupProperties[0:physicalDeviceGroupCount]
-
-    for i in (0 .. physicalDeviceGroupCount) {
-        physicalDevice := ?
-        physicalDevices[i] = physicalDevice
-        if !(physicalDevice in State.PhysicalDevices) {
-            State.PhysicalDevices[physicalDevice] = new!PhysicalDeviceObject(instance: instance)
-        }
-    }
-
-    return ?
-}
-
-@vulkan1_1
-cmd void vkGetImageMemoryRequirements2(
-        VkDevice                                    device,
-        const VkImageMemoryRequirementsInfo2*       pInfo,
-        VkMemoryRequirements2*                      pMemoryRequirements) {
-}
-
-@vulkan1_1
-cmd void vkGetBufferMemoryRequirements2(
-        VkDevice                                    device,
-        const VkBufferMemoryRequirementsInfo2*      pInfo,
-        VkMemoryRequirements2*                      pMemoryRequirements) {
-}
-
-@vulkan1_1
-cmd void vkGetImageSparseMemoryRequirements2(
-        VkDevice                                        device,
-        const VkImageSparseMemoryRequirementsInfo2*     pInfo,
-        u32*                                            pSparseMemoryRequirementCount,
-        VkSparseImageMemoryRequirements2*               pSparseMemoryRequirements) {
-}
-
-@vulkan1_1
-cmd void vkGetPhysicalDeviceFeatures2(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceFeatures2*                  pFeatures) {
-}
-
-@vulkan1_1
-cmd void vkGetPhysicalDeviceProperties2(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceProperties2*                pProperties) {
-}
-
-@vulkan1_1
-cmd void vkGetPhysicalDeviceFormatProperties2(
-        VkPhysicalDevice                            physicalDevice,
-        VkFormat                                    format,
-        VkFormatProperties2*                        pFormatProperties) {
-}
-
-@vulkan1_1
-cmd VkResult vkGetPhysicalDeviceImageFormatProperties2(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceImageFormatInfo2*     pImageFormatInfo,
-        VkImageFormatProperties2*                   pImageFormatProperties) {
-    return ?
-}
-
-@vulkan1_1
-cmd void vkGetPhysicalDeviceQueueFamilyProperties2(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pQueueFamilyPropertyCount,
-        VkQueueFamilyProperties2*                   pQueueFamilyProperties) {
-}
-
-@vulkan1_1
-cmd void vkGetPhysicalDeviceMemoryProperties2(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceMemoryProperties2*          pMemoryProperties) {
-}
-
-@vulkan1_1
-cmd void vkGetPhysicalDeviceSparseImageFormatProperties2(
-        VkPhysicalDevice                                    physicalDevice,
-        const VkPhysicalDeviceSparseImageFormatInfo2*       pFormatInfo,
-        u32*                                                pPropertyCount,
-        VkSparseImageFormatProperties2*                     pProperties) {
-}
-
-@vulkan1_1
-cmd void vkTrimCommandPool(
-        VkDevice                                    device,
-        VkCommandPool                               commandPool,
-        VkCommandPoolTrimFlags                      flags) {
-}
-
-
-@vulkan1_1
-cmd void vkGetDeviceQueue2(
-        VkDevice                                    device,
-        const VkDeviceQueueInfo2*                   pQueueInfo,
-        VkQueue*                                    pQueue) {
-    deviceObject := GetDevice(device)
-
-    queue := ?
-    pQueue[0] = queue
-
-    if !(queue in State.Queues) {
-        State.Queues[queue] = new!QueueObject(device: device)
-    }
-}
-
-@vulkan1_1
-cmd VkResult vkCreateSamplerYcbcrConversion(
-        VkDevice                                        device,
-        const VkSamplerYcbcrConversionCreateInfo*       pCreateInfo,
-        const VkAllocationCallbacks*                    pAllocator,
-        VkSamplerYcbcrConversion*                       pYcbcrConversion) {
-    return ?
-}
-
-@vulkan1_1
-cmd void vkDestroySamplerYcbcrConversion(
-        VkDevice                                        device,
-        VkSamplerYcbcrConversion                        ycbcrConversion,
-        const VkAllocationCallbacks*                    pAllocator) {
-}
-
-@vulkan1_1
-cmd VkResult vkCreateDescriptorUpdateTemplate(
-        VkDevice                                    device,
-        const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDescriptorUpdateTemplate*                 pDescriptorUpdateTemplate) {
-    return ?
-}
-
-@vulkan1_1
-cmd void vkDestroyDescriptorUpdateTemplate(
-        VkDevice                                    device,
-        VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@vulkan1_1
-cmd void vkUpdateDescriptorSetWithTemplate(
-        VkDevice                                    device,
-        VkDescriptorSet                             descriptorSet,
-        VkDescriptorUpdateTemplate                  descriptorUpdateTemplate,
-        const void*                                 pData) {
-}
-
-@vulkan1_1
-cmd void vkGetPhysicalDeviceExternalBufferProperties(
-        VkPhysicalDevice                                physicalDevice,
-        const VkPhysicalDeviceExternalBufferInfo*       pExternalBufferInfo,
-        VkExternalBufferProperties*                     pExternalBufferProperties) {
-}
-
-@vulkan1_1
-cmd void vkGetPhysicalDeviceExternalFenceProperties(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceExternalFenceInfo*    pExternalFenceInfo,
-        VkExternalFenceProperties*                  pExternalFenceProperties) {
-}
-
-@vulkan1_1
-cmd void vkGetPhysicalDeviceExternalSemaphoreProperties(
-        VkPhysicalDevice                                physicalDevice,
-        const VkPhysicalDeviceExternalSemaphoreInfo*    pExternalSemaphoreInfo,
-        VkExternalSemaphoreProperties*                  pExternalSemaphoreProperties) {
-}
-
-@vulkan1_1
-cmd void vkGetDescriptorSetLayoutSupport(
-        VkDevice                                    device,
-        const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
-        VkDescriptorSetLayoutSupport*               pSupport) {
-}
-
-
-@extension("VK_KHR_surface") // 1
-cmd void vkDestroySurfaceKHR(
-        VkInstance                                  instance,
-        VkSurfaceKHR                                surface,
-        const VkAllocationCallbacks*                pAllocator) {
-    instanceObject := GetInstance(instance)
-    surfaceObject := GetSurface(surface)
-    assert(surfaceObject.instance == instance)
-
-    State.Surfaces[surface] = null
-}
-
-@extension("VK_KHR_surface") // 1
-cmd VkResult vkGetPhysicalDeviceSurfaceSupportKHR(
-        VkPhysicalDevice                            physicalDevice,
-        u32                                         queueFamilyIndex,
-        VkSurfaceKHR                                surface,
-        VkBool32*                                   pSupported) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    return ?
-}
-
-@extension("VK_KHR_surface") // 1
-cmd VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkSurfaceKHR                                surface,
-        VkSurfaceCapabilitiesKHR*                   pSurfaceCapabilities) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    surfaceCapabilities := ?
-    pSurfaceCapabilities[0] = surfaceCapabilities
-
-    return ?
-}
-
-@extension("VK_KHR_surface") // 1
-cmd VkResult vkGetPhysicalDeviceSurfaceFormatsKHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkSurfaceKHR                                surface,
-        u32*                                        pSurfaceFormatCount,
-        VkSurfaceFormatKHR*                         pSurfaceFormats) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    count := as!u32(?)
-    pSurfaceFormatCount[0] = count
-    surfaceFormats := pSurfaceFormats[0:count]
-
-    for i in (0 .. count) {
-        surfaceFormat := ?
-        surfaceFormats[i] = surfaceFormat
-    }
-
-    return ?
-}
-
-@extension("VK_KHR_surface") // 1
-cmd VkResult vkGetPhysicalDeviceSurfacePresentModesKHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkSurfaceKHR                                surface,
-        u32*                                        pPresentModeCount,
-        VkPresentModeKHR*                           pPresentModes) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-
-    count := as!u32(?)
-    pPresentModeCount[0] = count
-    presentModes := pPresentModes[0:count]
-
-    for i in (0 .. count) {
-        presentMode := ?
-        presentModes[i] = presentMode
-    }
-
-    return ?
-}
-
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkCreateSwapchainKHR(
-        VkDevice                                 device,
-        const VkSwapchainCreateInfoKHR*          pCreateInfo,
-        const VkAllocationCallbacks*             pAllocator,
-        VkSwapchainKHR*                          pSwapchain) {
-    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR)
-    deviceObject := GetDevice(device)
-
-    swapchain := ?
-    pSwapchain[0] = swapchain
-    State.Swapchains[swapchain] = new!SwapchainObject(device: device)
-
-    return ?
-}
-
-@extension("VK_KHR_swapchain") // 2
-cmd void vkDestroySwapchainKHR(
-        VkDevice                                 device,
-        VkSwapchainKHR                           swapchain,
-        const VkAllocationCallbacks*             pAllocator) {
-    deviceObject := GetDevice(device)
-    swapchainObject := GetSwapchain(swapchain)
-    assert(swapchainObject.device == device)
-
-    State.Swapchains[swapchain] = null
-}
-
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkGetSwapchainImagesKHR(
-        VkDevice                                 device,
-        VkSwapchainKHR                           swapchain,
-        u32*                                     pSwapchainImageCount,
-        VkImage*                                 pSwapchainImages) {
-    deviceObject := GetDevice(device)
-
-    count := as!u32(?)
-    pSwapchainImageCount[0] = count
-    swapchainImages := pSwapchainImages[0:count]
-
-    for i in (0 .. count) {
-        swapchainImage := ?
-        swapchainImages[i] = swapchainImage
-        State.Images[swapchainImage] = new!ImageObject(device: device)
-    }
-
-    return ?
-}
-
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkAcquireNextImageKHR(
-        VkDevice                                 device,
-        VkSwapchainKHR                           swapchain,
-        u64                                      timeout,
-        VkSemaphore                              semaphore,
-        VkFence                                  fence,
-        u32*                                     pImageIndex) {
-    deviceObject := GetDevice(device)
-    swapchainObject := GetSwapchain(swapchain)
-
-    imageIndex := ?
-    pImageIndex[0] = imageIndex
-
-    return ?
-}
-
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkQueuePresentKHR(
-        VkQueue                                  queue,
-        const VkPresentInfoKHR*                  pPresentInfo) {
-    queueObject := GetQueue(queue)
-
-    presentInfo := ?
-    pPresentInfo[0] = presentInfo
-
-    return ?
-}
-
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkGetDeviceGroupPresentCapabilitiesKHR(
-        VkDevice                                    device,
-        VkDeviceGroupPresentCapabilitiesKHR*        pDeviceGroupPresentCapabilities) {
-    return ?
-}
-
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkGetDeviceGroupSurfacePresentModesKHR(
-        VkDevice                                    device,
-        VkSurfaceKHR                                surface,
-        VkDeviceGroupPresentModeFlagsKHR*           pModes) {
-    return ?
-}
-
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkGetPhysicalDevicePresentRectanglesKHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkSurfaceKHR                                surface,
-        u32*                                        pRectCount,
-        VkRect2D*                                   pRects) {
-    return ?
-}
-
-@vulkan1_1
-@extension("VK_KHR_swapchain") // 2
-cmd VkResult vkAcquireNextImage2KHR(
-        VkDevice                                    device,
-        const VkAcquireNextImageInfoKHR*            pAcquireInfo,
-        u32*                                        pImageIndex) {
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkGetPhysicalDeviceDisplayPropertiesKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32*                                    pPropertyCount,
-        VkDisplayPropertiesKHR*                 pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkGetPhysicalDeviceDisplayPlanePropertiesKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32*                                    pPropertyCount,
-        VkDisplayPlanePropertiesKHR*            pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkGetDisplayPlaneSupportedDisplaysKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32                                     planeIndex,
-        u32*                                    pDisplayCount,
-        VkDisplayKHR*                           pDisplays) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkGetDisplayModePropertiesKHR(
-        VkPhysicalDevice                        physicalDevice,
-        VkDisplayKHR                            display,
-        u32*                                    pPropertyCount,
-        VkDisplayModePropertiesKHR*             pProperties) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkCreateDisplayModeKHR(
-        VkPhysicalDevice                        physicalDevice,
-        VkDisplayKHR                            display,
-        const VkDisplayModeCreateInfoKHR*       pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkDisplayModeKHR*                       pMode) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkGetDisplayPlaneCapabilitiesKHR(
-        VkPhysicalDevice                        physicalDevice,
-        VkDisplayModeKHR                        mode,
-        u32                                     planeIndex,
-        VkDisplayPlaneCapabilitiesKHR*          pCapabilities) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_display") // 3
-cmd VkResult vkCreateDisplayPlaneSurfaceKHR(
-        VkInstance                              instance,
-        const VkDisplaySurfaceCreateInfoKHR*    pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    return ?
-}
-
-@extension("VK_KHR_display_swapchain") // 4
-cmd VkResult vkCreateSharedSwapchainsKHR(
-        VkDevice                                device,
-        u32                                     swapchainCount,
-        const VkSwapchainCreateInfoKHR*         pCreateInfos,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSwapchainKHR*                         pSwapchains) {
-    return ?
-}
-
-@extension("VK_KHR_xlib_surface") // 5
-cmd VkResult vkCreateXlibSurfaceKHR(
-        VkInstance                              instance,
-        const VkXlibSurfaceCreateInfoKHR*       pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    instanceObject := GetInstance(instance)
-    return ?
-}
-
-@extension("VK_KHR_xlib_surface") // 5
-cmd VkBool32 vkGetPhysicalDeviceXlibPresentationSupportKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32                                     queueFamilyIndex,
-        platform.Display*                       dpy,
-        platform.VisualID                       visualID) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_xcb_surface") // 6
-cmd VkResult vkCreateXcbSurfaceKHR(
-        VkInstance                              instance,
-        const VkXcbSurfaceCreateInfoKHR*        pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    instanceObject := GetInstance(instance)
-    return ?
-}
-
-@extension("VK_KHR_xcb_surface") // 6
-cmd VkBool32 vkGetPhysicalDeviceXcbPresentationSupportKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32                                     queueFamilyIndex,
-        platform.xcb_connection_t*              connection,
-        platform.xcb_visualid_t                 visual_id) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_wayland_surface") // 7
-cmd VkResult vkCreateWaylandSurfaceKHR(
-        VkInstance                              instance,
-        const VkWaylandSurfaceCreateInfoKHR*    pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    instanceObject := GetInstance(instance)
-    return ?
-}
-
-@extension("VK_KHR_wayland_surface") // 7
-cmd VkBool32 vkGetPhysicalDeviceWaylandPresentationSupportKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32                                     queueFamilyIndex,
-        platform.wl_display*                    display) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_KHR_android_surface") // 9
-cmd VkResult vkCreateAndroidSurfaceKHR(
-        VkInstance                              instance,
-        const VkAndroidSurfaceCreateInfoKHR*    pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    instanceObject := GetInstance(instance)
-    return ?
-}
-
-@extension("VK_KHR_win32_surface") // 10
-cmd VkResult vkCreateWin32SurfaceKHR(
-        VkInstance                              instance,
-        const VkWin32SurfaceCreateInfoKHR*      pCreateInfo,
-        const VkAllocationCallbacks*            pAllocator,
-        VkSurfaceKHR*                           pSurface) {
-    instanceObject := GetInstance(instance)
-    return ?
-}
-
-@extension("VK_KHR_win32_surface") // 10
-cmd VkResult vkGetPhysicalDeviceWin32PresentationSupportKHR(
-        VkPhysicalDevice                        physicalDevice,
-        u32                                     queueFamilyIndex) {
-    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
-    return ?
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-@optional
-cmd VkResult vkGetSwapchainGrallocUsageANDROID(
-        VkDevice                                device,
-        VkFormat                                format,
-        VkImageUsageFlags                       imageUsage,
-        s32*                                    grallocUsage) {
-    return ?
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-@optional
-cmd VkResult vkGetSwapchainGrallocUsage2ANDROID(
-        VkDevice                                device,
-        VkFormat                                format,
-        VkImageUsageFlags                       imageUsage,
-        VkSwapchainImageUsageFlagsANDROID       swapchainImageUsage,
-        u64*                                    grallocConsumerUsage,
-        u64*                                    grallocProducerUsage) {
-    return ?
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-cmd VkResult vkAcquireImageANDROID(
-        VkDevice                                device,
-        VkImage                                 image,
-        int                                     nativeFenceFd,
-        VkSemaphore                             semaphore,
-        VkFence                                 fence) {
-    return ?
-}
-
-@extension("VK_ANDROID_native_buffer") // 11
-cmd VkResult vkQueueSignalReleaseImageANDROID(
-        VkQueue                                 queue,
-        u32                                     waitSemaphoreCount,
-        const VkSemaphore*                      pWaitSemaphores,
-        VkImage                                 image,
-        int*                                    pNativeFenceFd) {
-    return ?
-}
-
-@extension("VK_EXT_debug_report") // 12
-@external type void* PFN_vkDebugReportCallbackEXT
-@extension("VK_EXT_debug_report") // 12
-@pfn cmd VkBool32 vkDebugReportCallbackEXT(
-        VkDebugReportFlagsEXT                   flags,
-        VkDebugReportObjectTypeEXT              objectType,
-        u64                                     object,
-        platform.size_t                         location,
-        s32                                     messageCode,
-        const char*                             pLayerPrefix,
-        const char*                             pMessage,
-        void*                                   pUserData) {
-    return ?
-}
-
-@extension("VK_EXT_debug_report") // 12
-cmd VkResult vkCreateDebugReportCallbackEXT(
-        VkInstance                                  instance,
-        const VkDebugReportCallbackCreateInfoEXT*   pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDebugReportCallbackEXT*                   pCallback) {
-    return ?
-}
-
-@extension("VK_EXT_debug_report") // 12
-cmd void vkDestroyDebugReportCallbackEXT(
-        VkInstance                                  instance,
-        VkDebugReportCallbackEXT                    callback,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_EXT_debug_report") // 12
-cmd void vkDebugReportMessageEXT(
-        VkInstance                                  instance,
-        VkDebugReportFlagsEXT                       flags,
-        VkDebugReportObjectTypeEXT                  objectType,
-        u64                                         object,
-        platform.size_t                             location,
-        s32                                         messageCode,
-        const char*                                 pLayerPrefix,
-        const char*                                 pMessage) {
-}
-
-@extension("VK_EXT_debug_marker") // 23
-cmd VkResult vkDebugMarkerSetObjectTagEXT(
-        VkDevice                                    device,
-        const VkDebugMarkerObjectTagInfoEXT*        pTagInfo) {
-    return ?
-}
-
-@extension("VK_EXT_debug_marker") // 23
-cmd VkResult vkDebugMarkerSetObjectNameEXT(
-        VkDevice                                    device,
-        const VkDebugMarkerObjectNameInfoEXT*       pNameInfo) {
-    return ?
-}
-
-@extension("VK_EXT_debug_marker") // 23
-cmd void vkCmdDebugMarkerBeginEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkDebugMarkerMarkerInfoEXT*           pMarkerInfo) {
-}
-
-@extension("VK_EXT_debug_marker") // 23
-cmd void vkCmdDebugMarkerEndEXT(
-        VkCommandBuffer                             commandBuffer) {
-}
-
-@extension("VK_EXT_debug_marker") // 23
-cmd void vkCmdDebugMarkerInsertEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkDebugMarkerMarkerInfoEXT*           pMarkerInfo) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdBindTransformFeedbackBuffersEXT(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstBinding,
-        u32                                         bindingCount,
-        const VkBuffer*                             pBuffers,
-        const VkDeviceSize*                         pOffsets,
-        const VkDeviceSize*                         pSizes) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdBeginTransformFeedbackEXT(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstCounterBuffer,
-        u32                                         counterBufferCount,
-        const VkBuffer*                             pCounterBuffers,
-        const VkDeviceSize*                         pCounterBufferOffsets) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdEndTransformFeedbackEXT(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstCounterBuffer,
-        u32                                         counterBufferCount,
-        const VkBuffer*                             pCounterBuffers,
-        const VkDeviceSize*                         pCounterBufferOffsets) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdBeginQueryIndexedEXT(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         query,
-        VkQueryControlFlags                         flags,
-        u32                                         index) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdEndQueryIndexedEXT(
-        VkCommandBuffer                             commandBuffer,
-        VkQueryPool                                 queryPool,
-        u32                                         query,
-        u32                                         index) {
-}
-
-@extension("VK_EXT_transform_feedback") // 29
-cmd void vkCmdDrawIndirectByteCountEXT(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         instanceCount,
-        u32                                         firstInstance,
-        VkBuffer                                    counterBuffer,
-        VkDeviceSize                                counterBufferOffset,
-        u32                                         counterOffset,
-        u32                                         vertexStride) {
-}
-
-@extension("VK_AMD_draw_indirect_count") // 34
-cmd void vkCmdDrawIndirectCountAMD(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkBuffer                                    countBuffer,
-        VkDeviceSize                                countBufferOffset,
-        u32                                         maxDrawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_AMD_draw_indirect_count") // 34
-cmd void vkCmdDrawIndexedIndirectCountAMD(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkBuffer                                    countBuffer,
-        VkDeviceSize                                countBufferOffset,
-        u32                                         maxDrawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_AMD_shader_info") // 43
-cmd VkResult vkGetShaderInfoAMD(
-        VkDevice                                    device,
-        VkPipeline                                  pipeline,
-        VkShaderStageFlagBits                       shaderStage,
-        VkShaderInfoTypeAMD                         infoType,
-        platform.size_t*                            pInfoSize,
-        void*                                       pInfo) {
-    return ?
-}
-
-@extension("VK_NV_external_memory_capabilities") // 56
-cmd VkResult vkGetPhysicalDeviceExternalImageFormatPropertiesNV(
-        VkPhysicalDevice                            physicalDevice,
-        VkFormat                                    format,
-        VkImageType                                 type,
-        VkImageTiling                               tiling,
-        VkImageUsageFlags                           usage,
-        VkImageCreateFlags                          flags,
-        VkExternalMemoryHandleTypeFlagsNV           externalHandleType,
-        VkExternalImageFormatPropertiesNV*          pExternalImageFormatProperties) {
-    return ?
-}
-
-@extension("VK_NV_external_memory_win32") // 58
-cmd VkResult vkGetMemoryWin32HandleNV(
-        VkDevice                                    device,
-        VkDeviceMemory                              memory,
-        VkExternalMemoryHandleTypeFlagsNV           handleType,
-        platform.HANDLE*                            pHandle) {
-    return ?
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceFeatures2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceFeatures2KHR*               pFeatures) {
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceProperties2KHR*             pProperties) {
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceFormatProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkFormat                                    format,
-        VkFormatProperties2KHR*                     pFormatProperties) {
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd VkResult vkGetPhysicalDeviceImageFormatProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceImageFormatInfo2KHR*  pImageFormatInfo,
-        VkImageFormatProperties2KHR*                pImageFormatProperties) {
-    return ?
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceQueueFamilyProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pQueueFamilyPropertyCount,
-        VkQueueFamilyProperties2KHR*                pQueueFamilyProperties) {
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceMemoryProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkPhysicalDeviceMemoryProperties2KHR*       pMemoryProperties) {
-}
-
-@extension("VK_KHR_get_physical_device_properties2") // 60
-cmd void vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
-        VkPhysicalDevice                                    physicalDevice,
-        const VkPhysicalDeviceSparseImageFormatInfo2KHR*    pFormatInfo,
-        u32*                                                pPropertyCount,
-        VkSparseImageFormatProperties2KHR*                  pProperties) {
-}
-
-@extension("VK_KHR_device_group") // 61
-cmd void vkGetDeviceGroupPeerMemoryFeaturesKHR(
-        VkDevice                                    device,
-        u32                                         heapIndex,
-        u32                                         localDeviceIndex,
-        u32                                         remoteDeviceIndex,
-        VkPeerMemoryFeatureFlagsKHR*                pPeerMemoryFeatures) {
-}
-
-@extension("VK_KHR_device_group") // 61
-cmd void vkCmdSetDeviceMaskKHR(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         deviceMask) {
-}
-
-
-@extension("VK_KHR_device_group") // 61
-cmd void vkCmdDispatchBaseKHR(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         baseGroupX,
-        u32                                         baseGroupY,
-        u32                                         baseGroupZ,
-        u32                                         groupCountX,
-        u32                                         groupCountY,
-        u32                                         groupCountZ) {
-}
-
-@extension("VK_NN_vi_surface") // 63
-cmd VkResult vkCreateViSurfaceNN(
-        VkInstance                                  instance,
-        const VkViSurfaceCreateInfoNN*              pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSurfaceKHR*                               pSurface) {
-    return ?
-}
-
-@extension("VK_KHR_maintenance1") // 70
-cmd void vkTrimCommandPoolKHR(
-        VkDevice                                    device,
-        VkCommandPool                               commandPool,
-        VkCommandPoolTrimFlagsKHR                   flags) {
-}
-
-@extension("VK_KHR_device_group_creation") // 71
-@threadSafety("system")
-cmd VkResult vkEnumeratePhysicalDeviceGroupsKHR(
-        VkInstance                                  instance,
-        u32*                                        pPhysicalDeviceGroupCount,
-        VkPhysicalDeviceGroupPropertiesKHR*         pPhysicalDeviceGroupProperties) {
-    instanceObject := GetInstance(instance)
-
-    physicalDeviceGroupCount := as!u32(?)
-    pPhysicalDeviceGroupCount[0] = physicalDeviceGroupCount
-    physicalDevices := pPhysicalDeviceGroupProperties[0:physicalDeviceGroupCount]
-
-    for i in (0 .. physicalDeviceGroupCount) {
-        physicalDevice := ?
-        physicalDevices[i] = physicalDevice
-        if !(physicalDevice in State.PhysicalDevices) {
-            State.PhysicalDevices[physicalDevice] = new!PhysicalDeviceObject(instance: instance)
-        }
-    }
-
-    return ?
-}
-
-@extension("VK_KHR_external_memory_capabilities") // 72
-cmd void vkGetPhysicalDeviceExternalBufferPropertiesKHR(
-        VkPhysicalDevice                                physicalDevice,
-        const VkPhysicalDeviceExternalBufferInfoKHR*    pExternalBufferInfo,
-        VkExternalBufferPropertiesKHR*                  pExternalBufferProperties) {
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-cmd VkResult vkGetMemoryWin32HandleKHR(
-        VkDevice                                    device,
-        const VkMemoryGetWin32HandleInfoKHR*        pGetWin32HandleInfo,
-        platform.HANDLE*                            pHandle) {
-    return ?
-}
-
-@extension("VK_KHR_external_memory_win32") // 74
-cmd VkResult vkGetMemoryWin32HandlePropertiesKHR(
-        VkDevice                                    device,
-        VkExternalMemoryHandleTypeFlagBitsKHR       handleType,
-        platform.HANDLE                             handle,
-        VkMemoryWin32HandlePropertiesKHR*           pMemoryWin32HandleProperties) {
-    return ?
-}
-
-@extension("VK_KHR_external_memory_fd") // 75
-cmd VkResult vkGetMemoryFdKHR(
-        VkDevice                                    device,
-        const VkMemoryGetFdInfoKHR*                 pGetFdInfo,
-        s32*                                        pFd) {
-    return ?
-}
-
-@extension("VK_KHR_external_memory_fd") // 75
-cmd VkResult vkGetMemoryFdPropertiesKHR(
-        VkDevice                                    device,
-        VkExternalMemoryHandleTypeFlagBitsKHR       handleType,
-        s32                                         fd,
-        VkMemoryFdPropertiesKHR*                    pMemoryFdProperties) {
-    return ?
-}
-
-@extension("VK_KHR_external_semaphore_capabilities") // 77
-cmd void vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo,
-        VkExternalSemaphorePropertiesKHR*           pExternalSemaphoreProperties) {
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-cmd VkResult vkImportSemaphoreWin32HandleKHR(
-        VkDevice                                    device,
-        const VkImportSemaphoreWin32HandleInfoKHR*  pImportSemaphoreWin32HandleInfo) {
-    return ?
-}
-
-@extension("VK_KHR_external_semaphore_win32") // 79
-cmd VkResult vkGetSemaphoreWin32HandleKHR(
-        VkDevice                                    device,
-        const VkSemaphoreGetWin32HandleInfoKHR*     pGetWin32HandleInfo,
-        platform.HANDLE*                            pHandle) {
-    return ?
-}
-
-@extension("VK_KHR_external_semaphore_fd") // 80
-cmd VkResult vkImportSemaphoreFdKHR(
-        VkDevice                                    device,
-        const VkImportSemaphoreFdInfoKHR*           pImportSemaphoreFdInfo) {
-    return ?
-}
-
-@extension("VK_KHR_external_semaphore_fd") // 80
-cmd VkResult vkGetSemaphoreFdKHR(
-        VkDevice                                    device,
-        const VkSemaphoreGetFdInfoKHR*              pGetFdInfo,
-        s32*                                        pFd) {
-    return ?
-}
-
-@extension("VK_KHR_push_descriptor") // 81
-cmd void vkCmdPushDescriptorSetKHR(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineBindPoint                         pipelineBindPoint,
-        VkPipelineLayout                            layout,
-        u32                                         set,
-        u32                                         descriptorWriteCount,
-        const VkWriteDescriptorSet*                 pDescriptorWrites) {
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-cmd void vkCmdBeginConditionalRenderingEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkConditionalRenderingBeginInfoEXT*   pConditionalRenderingBegin) {
-}
-
-@extension("VK_EXT_conditional_rendering") // 82
-cmd void vkCmdEndConditionalRenderingEXT(
-        VkCommandBuffer                             commandBuffer) {
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-cmd VkResult vkCreateDescriptorUpdateTemplateKHR(
-        VkDevice                                    device,
-        const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDescriptorUpdateTemplateKHR*              pDescriptorUpdateTemplate) {
-    return ?
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-cmd void vkDestroyDescriptorUpdateTemplateKHR(
-        VkDevice                                    device,
-        VkDescriptorUpdateTemplateKHR               descriptorUpdateTemplate,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-cmd void vkUpdateDescriptorSetWithTemplateKHR(
-        VkDevice                                    device,
-        VkDescriptorSet                             descriptorSet,
-        VkDescriptorUpdateTemplateKHR               descriptorUpdateTemplate,
-        const void*                                 pData) {
-}
-
-@extension("VK_KHR_descriptor_update_template") // 86
-cmd void vkCmdPushDescriptorSetWithTemplateKHR(
-        VkCommandBuffer                             commandBuffer,
-        VkDescriptorUpdateTemplateKHR               descriptorUpdateTemplate,
-        VkPipelineLayout                            layout,
-        u32                                         set,
-        const void*                                 pData) {
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd void vkCmdProcessCommandsNVX(
-        VkCommandBuffer                             commandBuffer,
-        const VkCmdProcessCommandsInfoNVX*          pProcessCommandsInfo) {
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd void vkCmdReserveSpaceForCommandsNVX(
-        VkCommandBuffer                             commandBuffer,
-        const VkCmdReserveSpaceForCommandsInfoNVX*  pReserveSpaceInfo) {
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd VkResult vkCreateIndirectCommandsLayoutNVX(
-        VkDevice                                    device,
-        const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkIndirectCommandsLayoutNVX*                pIndirectCommandsLayout) {
-    return ?
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd void vkDestroyIndirectCommandsLayoutNVX(
-        VkDevice                                    device,
-        VkIndirectCommandsLayoutNVX                 indirectCommandsLayout,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd VkResult vkCreateObjectTableNVX(
-        VkDevice                                    device,
-        const VkObjectTableCreateInfoNVX*           pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkObjectTableNVX*                           pObjectTable) {
-    return ?
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd void vkDestroyObjectTableNVX(
-        VkDevice                                    device,
-        VkObjectTableNVX                            objectTable,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd VkResult vkRegisterObjectsNVX(
-        VkDevice                                    device,
-        VkObjectTableNVX                            objectTable,
-        u32                                         objectCount,
-        const VkObjectTableEntryNVX* const*         ppObjectTableEntries,
-        const u32*                                  pObjectIndices) {
-    return ?
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd VkResult vkUnregisterObjectsNVX(
-        VkDevice                                    device,
-        VkObjectTableNVX                            objectTable,
-        u32                                         objectCount,
-        const VkObjectEntryTypeNVX*                 pObjectEntryTypes,
-        const u32*                                  pObjectIndices) {
-    return ?
-}
-
-@extension("VK_NVX_device_generated_commands") // 87
-cmd void vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX(
-        VkPhysicalDevice                            physicalDevice,
-        VkDeviceGeneratedCommandsFeaturesNVX*       pFeatures,
-        VkDeviceGeneratedCommandsLimitsNVX*         pLimits) {
-}
-
-@extension("VK_NV_clip_space_w_scaling") // 88
-cmd void vkCmdSetViewportWScalingNV(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstViewport,
-        u32                                         viewportCount,
-        const VkViewportWScalingNV*                 pViewportWScalings) {
-}
-
-@extension("VK_EXT_direct_mode_display") // 89
-cmd VkResult vkReleaseDisplayEXT(
-        VkPhysicalDevice                            physicalDevice,
-        VkDisplayKHR                                display) {
-    return ?
-}
-
-@extension("VK_EXT_acquire_xlib_display") // 90
-cmd VkResult vkAcquireXlibDisplayEXT(
-        VkPhysicalDevice                            physicalDevice,
-        platform.Display*                           dpy,
-        VkDisplayKHR                                display) {
-    return ?
-}
-
-@extension("VK_EXT_acquire_xlib_display") // 90
-cmd VkResult vkGetRandROutputDisplayEXT(
-        VkPhysicalDevice                            physicalDevice,
-        platform.Display*                           dpy,
-        platform.RROutput                           rrOutput,
-        VkDisplayKHR*                               pDisplay) {
-    return ?
-}
-
-@extension("VK_EXT_display_surface_counter") // 91
-cmd VkResult vkGetPhysicalDeviceSurfaceCapabilities2EXT(
-        VkPhysicalDevice                            physicalDevice,
-        VkSurfaceKHR                                surface,
-        VkSurfaceCapabilities2EXT*                  pSurfaceCapabilities) {
-    return ?
-}
-
-@extension("VK_EXT_display_control") // 92
-cmd VkResult vkDisplayPowerControlEXT(
-        VkDevice                                    device,
-        VkDisplayKHR                                display,
-        const VkDisplayPowerInfoEXT*                pDisplayPowerInfo) {
-    return ?
-}
-
-@extension("VK_EXT_display_control") // 92
-cmd VkResult vkRegisterDeviceEventEXT(
-        VkDevice                                    device,
-        const VkDeviceEventInfoEXT*                 pDeviceEventInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkFence*                                    pFence) {
-    return ?
-}
-
-@extension("VK_EXT_display_control") // 92
-cmd VkResult vkRegisterDisplayEventEXT(
-        VkDevice                                    device,
-        VkDisplayKHR                                display,
-        const VkDisplayEventInfoEXT*                pDisplayEventInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkFence*                                    pFence) {
-    return ?
-}
-
-@extension("VK_EXT_display_control") // 92
-cmd VkResult vkGetSwapchainCounterEXT(
-        VkDevice                                    device,
-        VkSwapchainKHR                              swapchain,
-        VkSurfaceCounterFlagBitsEXT                 counter,
-        u64*                                        pCounterValue) {
-    return ?
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-cmd VkResult vkGetRefreshCycleDurationGOOGLE(
-        VkDevice                                    device,
-        VkSwapchainKHR                              swapchain,
-        VkRefreshCycleDurationGOOGLE*               pDisplayTimingProperties) {
-    deviceObject := GetDevice(device)
-    swapchainObject := GetSwapchain(swapchain)
-
-    displayTimingProperties := ?
-    pDisplayTimingProperties[0] = displayTimingProperties
-
-    return ?
-}
-
-@extension("VK_GOOGLE_display_timing") // 93
-cmd VkResult vkGetPastPresentationTimingGOOGLE(
-        VkDevice                                    device,
-        VkSwapchainKHR                              swapchain,
-        u32*                                        pPresentationTimingCount,
-        VkPastPresentationTimingGOOGLE*             pPresentationTimings) {
-    return ?
-}
-
-@extension("VK_EXT_discard_rectangles") // 100
-cmd void vkCmdSetDiscardRectangleEXT(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstDiscardRectangle,
-        u32                                         discardRectangleCount,
-        const VkRect2D*                             pDiscardRectangles) {
-}
-
-@extension("VK_EXT_hdr_metadata") // 106
-cmd void vkSetHdrMetadataEXT(
-        VkDevice                                    device,
-        u32                                         swapchainCount,
-        const VkSwapchainKHR*                       pSwapchains,
-        const VkHdrMetadataEXT*                     pMetadata) {
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-cmd VkResult vkCreateRenderPass2KHR(
-        VkDevice                                    device,
-        const VkRenderPassCreateInfo2KHR*           pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkRenderPass*                               pRenderPass) {
-    return ?
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-cmd void vkCmdBeginRenderPass2KHR(
-        VkCommandBuffer                             commandBuffer,
-        const VkRenderPassBeginInfo*                pRenderPassBegin,
-        const VkSubpassBeginInfoKHR*                pSubpassBeginInfo) {
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-cmd void vkCmdNextSubpass2KHR(
-        VkCommandBuffer                             commandBuffer,
-        const VkSubpassBeginInfoKHR*                pSubpassBeginInfo,
-        const VkSubpassEndInfoKHR*                  pSubpassEndInfo) {
-}
-
-@extension("VK_KHR_create_renderpass2") // 110
-cmd void vkCmdEndRenderPass2KHR(
-        VkCommandBuffer                             commandBuffer,
-        const VkSubpassEndInfoKHR*                  pSubpassEndInfo) {
-}
-
-@extension("VK_KHR_shared_presentable_image") // 112
-cmd VkResult vkGetSwapchainStatusKHR(
-        VkDevice                                    device,
-        VkSwapchainKHR                              swapchain) {
-    return ?
-}
-
-@extension("VK_KHR_external_fence_capabilities") // 113
-cmd void vkGetPhysicalDeviceExternalFencePropertiesKHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo,
-        VkExternalFencePropertiesKHR*               pExternalFenceProperties) {
-}
-
-@extension("VK_KHR_external_fence_win32") // 115
-cmd VkResult vkImportFenceWin32HandleKHR(
-        VkDevice                                    device,
-        const VkImportFenceWin32HandleInfoKHR*      pImportFenceWin32HandleInfo) {
-    return ?
-}
-
-@extension("VK_KHR_external_fence_win32") // 115
-cmd VkResult vkGetFenceWin32HandleKHR(
-        VkDevice                                    device,
-        const VkFenceGetWin32HandleInfoKHR*         pGetWin32HandleInfo,
-        platform.HANDLE*                            pHandle) {
-    return ?
-}
-
-@extension("VK_KHR_external_fence_fd") // 116
-cmd VkResult vkImportFenceFdKHR(
-        VkDevice                                    device,
-        const VkImportFenceFdInfoKHR*               pImportFenceFdInfo) {
-    return ?
-}
-
-@extension("VK_KHR_external_fence_fd") // 116
-cmd VkResult vkGetFenceFdKHR(
-        VkDevice                                    device,
-        const VkFenceGetFdInfoKHR*                  pGetFdInfo,
-        int*                                        pFd) {
-    return ?
-}
-
-@extension("VK_KHR_get_surface_capabilities2") // 120
-cmd VkResult vkGetPhysicalDeviceSurfaceCapabilities2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
-        VkSurfaceCapabilities2KHR*                  pSurfaceCapabilities) {
-    return ?
-}
-
-@extension("VK_KHR_get_surface_capabilities2") // 120
-cmd VkResult vkGetPhysicalDeviceSurfaceFormats2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
-        u32*                                        pSurfaceFormatCount,
-        VkSurfaceFormat2KHR*                        pSurfaceFormats) {
-    return ?
-}
-
-@extension("VK_KHR_display_properties2") // 122
-cmd VkResult vkGetPhysicalDeviceDisplayProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pPropertyCount,
-        VkDisplayProperties2KHR*                    pProperties) {
-    return ?
-}
-
-@extension("VK_KHR_display_properties2") // 122
-cmd VkResult vkGetPhysicalDeviceDisplayPlaneProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pPropertyCount,
-        VkDisplayPlaneProperties2KHR*               pProperties) {
-    return ?
-}
-
-@extension("VK_KHR_display_properties2") // 122
-cmd VkResult vkGetDisplayModeProperties2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        VkDisplayKHR                                display,
-        u32*                                        pPropertyCount,
-        VkDisplayModeProperties2KHR*                pProperties) {
-    return ?
-}
-
-@extension("VK_KHR_display_properties2") // 122
-cmd VkResult vkGetDisplayPlaneCapabilities2KHR(
-        VkPhysicalDevice                            physicalDevice,
-        const VkDisplayPlaneInfo2KHR*               pDisplayPlaneInfo,
-        VkDisplayPlaneCapabilities2KHR*             pCapabilities) {
-    return ?
-}
-
-@extension("VK_MVK_ios_surface") // 123
-cmd VkResult vkCreateIOSSurfaceMVK(
-        VkInstance                                  instance,
-        const VkIOSSurfaceCreateInfoMVK*            pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSurfaceKHR*                               pSurface) {
-    return ?
-}
-
-@extension("VK_MVK_macos_surface") // 124
-cmd VkResult vkCreateMacOSSurfaceMVK(
-        VkInstance                                  instance,
-        const VkMacOSSurfaceCreateInfoMVK*          pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSurfaceKHR*                               pSurface) {
-    return ?
-}
-
-@extension("VK_EXT_debug_utils") // 129
-@external type void* PFN_vkDebugUtilsMessengerCallbackEXT
-@extension("VK_EXT_debug_utils") // 129
-@pfn cmd VkBool32 vkDebugUtilsMessengerCallbackEXT(
-        VkDebugUtilsMessageSeverityFlagBitsEXT      messageSeverity,
-        VkDebugUtilsMessageTypeFlagsEXT             messageType,
-        const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
-        void*                                       pUserData) {
-    return ?
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd VkResult vkSetDebugUtilsObjectNameEXT(
-        VkDevice                                    device,
-        const VkDebugUtilsObjectNameInfoEXT*        pNameInfo) {
-    return ?
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd VkResult vkSetDebugUtilsObjectTagEXT(
-        VkDevice                                    device,
-        const VkDebugUtilsObjectTagInfoEXT*         pTagInfo) {
-    return ?
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkQueueBeginDebugUtilsLabelEXT(
-        VkQueue                                     queue,
-        const VkDebugUtilsLabelEXT*                 pLabelInfo) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkQueueEndDebugUtilsLabelEXT(VkQueue       queue) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkQueueInsertDebugUtilsLabelEXT(
-        VkQueue                                     queue,
-        const VkDebugUtilsLabelEXT*                 pLabelInfo) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkCmdBeginDebugUtilsLabelEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkDebugUtilsLabelEXT*                 pLabelInfo) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkCmdEndDebugUtilsLabelEXT(VkCommandBuffer commandBuffer) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkCmdInsertDebugUtilsLabelEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkDebugUtilsLabelEXT*                 pLabelInfo) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd VkResult vkCreateDebugUtilsMessengerEXT(
-        VkInstance                                  instance,
-        const VkDebugUtilsMessengerCreateInfoEXT*   pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkDebugUtilsMessengerEXT*                   pMessenger) {
-    return ?
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkDestroyDebugUtilsMessengerEXT(
-        VkInstance                                  instance,
-        VkDebugUtilsMessengerEXT                    messenger,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_EXT_debug_utils") // 129
-cmd void vkSubmitDebugUtilsMessageEXT(
-        VkInstance                                  instance,
-        VkDebugUtilsMessageSeverityFlagBitsEXT      messageSeverity,
-        VkDebugUtilsMessageTypeFlagsEXT             messageTypes,
-        const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData) {
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-@vulkan1_1 // extension requires 1.1, and should become non-optional when 1.1 does
-cmd VkResult vkGetAndroidHardwareBufferPropertiesANDROID(
-        VkDevice                                    device,
-        const platform.AHardwareBuffer*             buffer,
-        VkAndroidHardwareBufferPropertiesANDROID*   pProperties) {
-    return ?
-}
-
-@extension("VK_ANDROID_external_memory_android_hardware_buffer") // 130
-@vulkan1_1 // extension requires 1.1, and should become non-optional when 1.1 does
-cmd VkResult vkGetMemoryAndroidHardwareBufferANDROID(
-        VkDevice                                            device,
-        const VkMemoryGetAndroidHardwareBufferInfoANDROID*  pInfo,
-        platform.AHardwareBuffer**                          pBuffer) {
-    return ?
-}
-
-@extension("VK_EXT_sample_locations") // 144
-cmd void vkCmdSetSampleLocationsEXT(
-        VkCommandBuffer                             commandBuffer,
-        const VkSampleLocationsInfoEXT*             pSampleLocationsInfo) {
-}
-
-@extension("VK_EXT_sample_locations") // 144
-cmd void vkGetPhysicalDeviceMultisamplePropertiesEXT(
-        VkPhysicalDevice                            physicalDevice,
-        VkSampleCountFlagBits                       samples,
-        VkMultisamplePropertiesEXT*                 pMultisampleProperties) {
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-cmd void vkGetImageMemoryRequirements2KHR(
-        VkDevice                                    device,
-        const VkImageMemoryRequirementsInfo2KHR*    pInfo,
-        VkMemoryRequirements2KHR*                   pMemoryRequirements) {
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-cmd void vkGetBufferMemoryRequirements2KHR(
-        VkDevice                                    device,
-        const VkBufferMemoryRequirementsInfo2KHR*   pInfo,
-        VkMemoryRequirements2KHR*                   pMemoryRequirements) {
-}
-
-@extension("VK_KHR_get_memory_requirements2") // 147
-cmd void vkGetImageSparseMemoryRequirements2KHR(
-        VkDevice                                        device,
-        const VkImageSparseMemoryRequirementsInfo2KHR*  pInfo,
-        u32*                                            pSparseMemoryRequirementCount,
-        VkSparseImageMemoryRequirements2KHR*            pSparseMemoryRequirements) {
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-cmd VkResult vkCreateSamplerYcbcrConversionKHR(
-        VkDevice                                        device,
-        const VkSamplerYcbcrConversionCreateInfoKHR*    pCreateInfo,
-        const VkAllocationCallbacks*                    pAllocator,
-        VkSamplerYcbcrConversionKHR*                    pYcbcrConversion) {
-    return ?
-}
-
-@extension("VK_KHR_sampler_ycbcr_conversion") // 157
-cmd void vkDestroySamplerYcbcrConversionKHR(
-        VkDevice                                        device,
-        VkSamplerYcbcrConversionKHR                     ycbcrConversion,
-        const VkAllocationCallbacks*                    pAllocator) {
-}
-
-@extension("VK_KHR_bind_memory2") // 158
-cmd VkResult vkBindBufferMemory2KHR(
-        VkDevice                                        device,
-        u32                                             bindInfoCount,
-        const VkBindBufferMemoryInfoKHR*                pBindInfos) {
-    return ?
-}
-
-@extension("VK_KHR_bind_memory2") // 158
-cmd VkResult vkBindImageMemory2KHR(
-        VkDevice                                        device,
-        u32                                             bindInfoCount,
-        const VkBindImageMemoryInfoKHR*                 pBindInfos) {
-    return ?
-}
-
-@extension("VK_EXT_image_drm_format_modifier") // 159
-cmd VkResult vkGetImageDrmFormatModifierPropertiesEXT(
-        VkDevice                                        device,
-        VkImage                                         image,
-        VkImageDrmFormatModifierPropertiesEXT*          pProperties) {
-    return ?
-}
-
-@extension("VK_EXT_validation_cache") // 161
-cmd VkResult vkCreateValidationCacheEXT(
-        VkDevice                                    device,
-        const VkValidationCacheCreateInfoEXT*       pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkValidationCacheEXT*                       pValidationCache) {
-    return ?
-}
-
-@extension("VK_EXT_validation_cache") // 161
-cmd void vkDestroyValidationCacheEXT(
-        VkDevice                                    device,
-        VkValidationCacheEXT                        validationCache,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_EXT_validation_cache") // 161
-cmd VkResult vkMergeValidationCachesEXT(
-        VkDevice                                    device,
-        VkValidationCacheEXT                        dstCache,
-        u32                                         srcCacheCount,
-        const VkValidationCacheEXT*                 pSrcCaches) {
-    return ?
-}
-
-@extension("VK_EXT_validation_cache") // 161
-cmd VkResult vkGetValidationCacheDataEXT(
-        VkDevice                                    device,
-        VkValidationCacheEXT                        validationCache,
-        platform.size_t*                            pDataSize,
-        void*                                       pData) {
-    return ?
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-cmd void vkCmdBindShadingRateImageNV(
-        VkCommandBuffer                             commandBuffer,
-        VkImageView                                 imageView,
-        VkImageLayout                               imageLayout) {
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-cmd void vkCmdSetViewportShadingRatePaletteNV(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstViewport,
-        u32                                         viewportCount,
-        const VkShadingRatePaletteNV*               pShadingRatePalettes) {
-}
-
-@extension("VK_NV_shading_rate_image") // 165
-cmd void vkCmdSetCoarseSampleOrderNV(
-        VkCommandBuffer                             commandBuffer,
-        VkCoarseSampleOrderTypeNV                   sampleOrderType,
-        u32                                         customSampleOrderCount,
-        const VkCoarseSampleOrderCustomNV*          pCustomSampleOrders) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkCreateAccelerationStructureNV(
-        VkDevice                                    device,
-        const VkAccelerationStructureCreateInfoNV*  pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkAccelerationStructureNV*                  pAccelerationStructure) {
-    return ?
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkDestroyAccelerationStructureNV(
-        VkDevice                                    device,
-        VkAccelerationStructureNV                   accelerationStructure,
-        const VkAllocationCallbacks*                pAllocator) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkGetAccelerationStructureMemoryRequirementsNV(
-        VkDevice                                                device,
-        const VkAccelerationStructureMemoryRequirementsInfoNV*  pInfo,
-        VkMemoryRequirements2KHR*                               pMemoryRequirements) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkBindAccelerationStructureMemoryNV(
-        VkDevice                                        device,
-        u32                                             bindInfoCount,
-        const VkBindAccelerationStructureMemoryInfoNV*  pBindInfos) {
-    return ?
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkCmdBuildAccelerationStructureNV(
-        VkCommandBuffer                             commandBuffer,
-        const VkAccelerationStructureInfoNV*        pInfo,
-        VkBuffer                                    instanceData,
-        VkDeviceSize                                instanceOffset,
-        VkBool32                                    update,
-        VkAccelerationStructureNV                   dst,
-        VkAccelerationStructureNV                   src,
-        VkBuffer                                    scratch,
-        VkDeviceSize                                scratchOffset) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkCmdCopyAccelerationStructureNV(
-        VkCommandBuffer                             commandBuffer,
-        VkAccelerationStructureNV                   dst,
-        VkAccelerationStructureNV                   src,
-        VkCopyAccelerationStructureModeNV           mode) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkCmdTraceRaysNV(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    raygenShaderBindingTableBuffer,
-        VkDeviceSize                                raygenShaderBindingOffset,
-        VkBuffer                                    missShaderBindingTableBuffer,
-        VkDeviceSize                                missShaderBindingOffset,
-        VkDeviceSize                                missShaderBindingStride,
-        VkBuffer                                    hitShaderBindingTableBuffer,
-        VkDeviceSize                                hitShaderBindingOffset,
-        VkDeviceSize                                hitShaderBindingStride,
-        VkBuffer                                    callableShaderBindingTableBuffer,
-        VkDeviceSize                                callableShaderBindingOffset,
-        VkDeviceSize                                callableShaderBindingStride,
-        u32                                         width,
-        u32                                         height,
-        u32                                         depth) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkCreateRaytracingPipelinesNV(
-        VkDevice                                    device,
-        VkPipelineCache                             pipelineCache,
-        u32                                         createInfoCount,
-        const VkRayTracingPipelineCreateInfoNV*     pCreateInfos,
-        const VkAllocationCallbacks*                pAllocator,
-        VkPipeline*                                 pPipelines) {
-    return ?
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkGetRaytracingShaderHandlesNV(
-        VkDevice                                    device,
-        VkPipeline                                  pipeline,
-        u32                                         firstGroup,
-        u32                                         groupCount,
-        platform.size_t                             dataSize,
-        void*                                       pData) {
-    return ?
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkGetAccelerationStructureHandleNV(
-        VkDevice                                    device,
-        VkAccelerationStructureNV                   accelerationStructure,
-        platform.size_t                             dataSize,
-        void*                                       pData) {
-    return ?
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd void vkCmdWriteAccelerationStructurePropertiesNV(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         accelerationStructureCount,
-        const VkAccelerationStructureNV*            pAccelerationStructures,
-        VkQueryType                                 queryType,
-        VkQueryPool                                 queryPool,
-        u32                                         firstQuery) {
-}
-
-@extension("VK_NV_ray_tracing") // 166
-cmd VkResult vkCompileDeferredNV(
-        VkDevice                                    device,
-        VkPipeline                                  pipeline,
-        u32                                         shader) {
-    return ?
-}
-
-@extension("VK_KHR_maintenance3") // 169
-cmd void vkGetDescriptorSetLayoutSupportKHR(
-        VkDevice                                    device,
-        const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
-        VkDescriptorSetLayoutSupportKHR*            pSupport) {
-}
-
-@extension("VK_KHR_draw_indirect_count") // 170
-cmd void vkCmdDrawIndirectCountKHR(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkBuffer                                    countBuffer,
-        VkDeviceSize                                countBufferOffset,
-        u32                                         maxDrawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_KHR_draw_indirect_count") // 170
-cmd void vkCmdDrawIndexedIndirectCountKHR(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkBuffer                                    countBuffer,
-        VkDeviceSize                                countBufferOffset,
-        u32                                         maxDrawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_EXT_external_memory_host") // 179
-cmd VkResult vkGetMemoryHostPointerPropertiesEXT(
-        VkDevice                                    device,
-        VkExternalMemoryHandleTypeFlagBits          handleType,
-        const void*                                 pHostPointer,
-        VkMemoryHostPointerPropertiesEXT*           pMemoryHostPointerProperties) {
-    return ?
-}
-
-@extension("VK_AMD_buffer_marker") // 180
-cmd void vkCmdWriteBufferMarkerAMD(
-        VkCommandBuffer                             commandBuffer,
-        VkPipelineStageFlagBits                     pipelineStage,
-        VkBuffer                                    dstBuffer,
-        VkDeviceSize                                dstOffset,
-        u32                                         marker) {
-}
-
-@extension("VK_EXT_calibrated_timestamps") // 185
-cmd VkResult vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(
-        VkPhysicalDevice                            physicalDevice,
-        u32*                                        pTimeDomainCount,
-        VkTimeDomainEXT*                            pTimeDomains) {
-    return ?
-}
-
-@extension("VK_EXT_calibrated_timestamps") // 185
-cmd VkResult vkGetCalibratedTimestampsEXT(
-        VkDevice                                    device,
-        u32                                         timestampCount,
-        const VkCalibratedTimestampInfoEXT*         pTimestampInfos,
-        u64*                                        pTimestamps,
-        u64*                                        pMaxDeviation) {
-    return ?
-}
-
-@extension("VK_NV_mesh_shader") // 203
-cmd void vkCmdDrawMeshTasksNV(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         taskCount,
-        u32                                         firstTask) {
-}
-
-@extension("VK_NV_mesh_shader") // 203
-cmd void vkCmdDrawMeshTasksIndirectNV(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        u32                                         drawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_NV_mesh_shader") // 203
-cmd void vkCmdDrawMeshTasksIndirectCountNV(
-        VkCommandBuffer                             commandBuffer,
-        VkBuffer                                    buffer,
-        VkDeviceSize                                offset,
-        VkBuffer                                    countBuffer,
-        VkDeviceSize                                countBufferOffset,
-        u32                                         maxDrawCount,
-        u32                                         stride) {
-}
-
-@extension("VK_NV_scissor_exclusive") // 206
-cmd void vkCmdSetExclusiveScissorNV(
-        VkCommandBuffer                             commandBuffer,
-        u32                                         firstExclusiveScissor,
-        u32                                         exclusiveScissorCount,
-        const VkRect2D*                             pExclusiveScissors) {
-}
-
-@extension("VK_NV_device_diagnostic_checkpoints") // 207
-cmd void vkCmdSetCheckpointNV(
-        VkCommandBuffer                             commandBuffer,
-        const void*                                 pCheckpointMarker) {
-}
-
-@extension("VK_NV_device_diagnostic_checkpoints") // 207
-cmd void vkGetQueueCheckpointDataNV(
-        VkQueue                                     queue,
-        u32*                                        pCheckpointDataCount,
-        VkCheckpointDataNV*                         pCheckpointData) {
-}
-
-@extension("VK_FUCHSIA_imagepipe_surface") // 215
-cmd VkResult vkCreateImagePipeSurfaceFUCHSIA(
-        VkInstance                                  instance,
-        const VkImagePipeSurfaceCreateInfoFUCHSIA*  pCreateInfo,
-        const VkAllocationCallbacks*                pAllocator,
-        VkSurfaceKHR*                               pSurface) {
-    return ?
-}
-
-
-////////////////
-// Validation //
-////////////////
-
-extern void validate(string layerName, bool condition, string message)
-
-
-/////////////////////////////
-// Internal State Tracking //
-/////////////////////////////
-
-StateObject State
-
-@internal class StateObject {
-    // Dispatchable objects.
-    map!(VkInstance,       ref!InstanceObject)       Instances
-    map!(VkPhysicalDevice, ref!PhysicalDeviceObject) PhysicalDevices
-    map!(VkDevice,         ref!DeviceObject)         Devices
-    map!(VkQueue,          ref!QueueObject)          Queues
-    map!(VkCommandBuffer,  ref!CommandBufferObject)  CommandBuffers
-
-    // Non-dispatchable objects.
-    map!(VkDeviceMemory,             ref!DeviceMemoryObject)             DeviceMemories
-    map!(VkBuffer,                   ref!BufferObject)                   Buffers
-    map!(VkBufferView,               ref!BufferViewObject)               BufferViews
-    map!(VkImage,                    ref!ImageObject)                    Images
-    map!(VkImageView,                ref!ImageViewObject)                ImageViews
-    map!(VkShaderModule,             ref!ShaderModuleObject)             ShaderModules
-    map!(VkPipeline,                 ref!PipelineObject)                 Pipelines
-    map!(VkPipelineLayout,           ref!PipelineLayoutObject)           PipelineLayouts
-    map!(VkSampler,                  ref!SamplerObject)                  Samplers
-    map!(VkDescriptorSet,            ref!DescriptorSetObject)            DescriptorSets
-    map!(VkDescriptorSetLayout,      ref!DescriptorSetLayoutObject)      DescriptorSetLayouts
-    map!(VkDescriptorPool,           ref!DescriptorPoolObject)           DescriptorPools
-    map!(VkFence,                    ref!FenceObject)                    Fences
-    map!(VkSemaphore,                ref!SemaphoreObject)                Semaphores
-    map!(VkEvent,                    ref!EventObject)                    Events
-    map!(VkQueryPool,                ref!QueryPoolObject)                QueryPools
-    map!(VkFramebuffer,              ref!FramebufferObject)              Framebuffers
-    map!(VkRenderPass,               ref!RenderPassObject)               RenderPasses
-    map!(VkPipelineCache,            ref!PipelineCacheObject)            PipelineCaches
-    map!(VkCommandPool,              ref!CommandPoolObject)              CommandPools
-    map!(VkSurfaceKHR,               ref!SurfaceObject)                  Surfaces
-    map!(VkSwapchainKHR,             ref!SwapchainObject)                Swapchains
-}
-
-@internal class InstanceObject {
-}
-
-@internal class PhysicalDeviceObject {
-    VkInstance instance
-}
-
-@internal class DeviceObject {
-    VkPhysicalDevice physicalDevice
-}
-
-@internal class QueueObject {
-    VkDevice      device
-    VkQueueFlags  flags
-}
-
-@internal class CommandBufferObject {
-    VkDevice                  device
-    map!(u64, VkDeviceMemory) boundObjects
-    VkQueueFlags              queueFlags
-}
-
-@internal class DeviceMemoryObject {
-    VkDevice                                device
-    VkDeviceSize                            allocationSize
-    map!(u64, VkDeviceSize)                 boundObjects
-    map!(VkCommandBuffer, VkCommandBuffer)  boundCommandBuffers
-}
-
-@internal class BufferObject {
-    VkDevice              device
-    VkDeviceMemory        memory
-    VkDeviceSize          memoryOffset
-}
-
-@internal class BufferViewObject {
-    VkDevice      device
-    VkBuffer      buffer
-}
-
-@internal class ImageObject {
-    VkDevice              device
-    VkDeviceMemory        memory
-    VkDeviceSize          memoryOffset
-}
-
-@internal class ImageViewObject {
-    VkDevice      device
-    VkImage       image
-}
-
-@internal class ShaderObject {
-    VkDevice      device
-}
-
-@internal class ShaderModuleObject {
-    VkDevice      device
-}
-
-@internal class PipelineObject {
-    VkDevice      device
-}
-
-@internal class PipelineLayoutObject {
-    VkDevice      device
-}
-
-@internal class SamplerObject {
-    VkDevice      device
-}
-
-@internal class DescriptorSetObject {
-    VkDevice      device
-}
-
-@internal class DescriptorSetLayoutObject {
-    VkDevice      device
-}
-
-@internal class DescriptorPoolObject {
-    VkDevice      device
-}
-
-@internal class FenceObject {
-    VkDevice      device
-    bool          signaled
-}
-
-@internal class SemaphoreObject {
-    VkDevice      device
-}
-
-@internal class EventObject {
-    VkDevice      device
-}
-
-@internal class QueryPoolObject {
-    VkDevice      device
-}
-
-@internal class FramebufferObject {
-    VkDevice      device
-}
-
-@internal class RenderPassObject {
-    VkDevice      device
-}
-
-@internal class PipelineCacheObject {
-    VkDevice      device
-}
-
-@internal class CommandPoolObject {
-    VkDevice      device
-}
-
-@internal class SurfaceObject {
-    VkInstance    instance
-}
-
-@internal class SwapchainObject {
-    VkDevice      device
-}
-
-macro ref!InstanceObject GetInstance(VkInstance instance) {
-    assert(instance in State.Instances)
-    return State.Instances[instance]
-}
-
-macro ref!PhysicalDeviceObject GetPhysicalDevice(VkPhysicalDevice physicalDevice) {
-    assert(physicalDevice in State.PhysicalDevices)
-    return State.PhysicalDevices[physicalDevice]
-}
-
-macro ref!DeviceObject GetDevice(VkDevice device) {
-    assert(device in State.Devices)
-    return State.Devices[device]
-}
-
-macro ref!QueueObject GetQueue(VkQueue queue) {
-    assert(queue in State.Queues)
-    return State.Queues[queue]
-}
-
-macro ref!CommandBufferObject GetCommandBuffer(VkCommandBuffer commandBuffer) {
-    assert(commandBuffer in State.CommandBuffers)
-    return State.CommandBuffers[commandBuffer]
-}
-
-macro ref!DeviceMemoryObject GetDeviceMemory(VkDeviceMemory memory) {
-    assert(memory in State.DeviceMemories)
-    return State.DeviceMemories[memory]
-}
-
-macro ref!BufferObject GetBuffer(VkBuffer buffer) {
-    assert(buffer in State.Buffers)
-    return State.Buffers[buffer]
-}
-
-macro ref!BufferViewObject GetBufferView(VkBufferView bufferView) {
-    assert(bufferView in State.BufferViews)
-    return State.BufferViews[bufferView]
-}
-
-macro ref!ImageObject GetImage(VkImage image) {
-    assert(image in State.Images)
-    return State.Images[image]
-}
-
-macro ref!ImageViewObject GetImageView(VkImageView imageView) {
-    assert(imageView in State.ImageViews)
-    return State.ImageViews[imageView]
-}
-
-macro ref!ShaderModuleObject GetShaderModule(VkShaderModule shaderModule) {
-    assert(shaderModule in State.ShaderModules)
-    return State.ShaderModules[shaderModule]
-}
-
-macro ref!PipelineObject GetPipeline(VkPipeline pipeline) {
-    assert(pipeline in State.Pipelines)
-    return State.Pipelines[pipeline]
-}
-
-macro ref!PipelineLayoutObject GetPipelineLayout(VkPipelineLayout pipelineLayout) {
-    assert(pipelineLayout in State.PipelineLayouts)
-    return State.PipelineLayouts[pipelineLayout]
-}
-
-macro ref!SamplerObject GetSampler(VkSampler sampler) {
-    assert(sampler in State.Samplers)
-    return State.Samplers[sampler]
-}
-
-macro ref!DescriptorSetObject GetDescriptorSet(VkDescriptorSet descriptorSet) {
-    assert(descriptorSet in State.DescriptorSets)
-    return State.DescriptorSets[descriptorSet]
-}
-
-macro ref!DescriptorSetLayoutObject GetDescriptorSetLayout(VkDescriptorSetLayout descriptorSetLayout) {
-    assert(descriptorSetLayout in State.DescriptorSetLayouts)
-    return State.DescriptorSetLayouts[descriptorSetLayout]
-}
-
-macro ref!DescriptorPoolObject GetDescriptorPool(VkDescriptorPool descriptorPool) {
-    assert(descriptorPool in State.DescriptorPools)
-    return State.DescriptorPools[descriptorPool]
-}
-
-macro ref!FenceObject GetFence(VkFence fence) {
-    assert(fence in State.Fences)
-    return State.Fences[fence]
-}
-
-macro ref!SemaphoreObject GetSemaphore(VkSemaphore semaphore) {
-    assert(semaphore in State.Semaphores)
-    return State.Semaphores[semaphore]
-}
-
-macro ref!EventObject GetEvent(VkEvent event) {
-    assert(event in State.Events)
-    return State.Events[event]
-}
-
-macro ref!QueryPoolObject GetQueryPool(VkQueryPool queryPool) {
-    assert(queryPool in State.QueryPools)
-    return State.QueryPools[queryPool]
-}
-
-macro ref!FramebufferObject GetFramebuffer(VkFramebuffer framebuffer) {
-    assert(framebuffer in State.Framebuffers)
-    return State.Framebuffers[framebuffer]
-}
-
-macro ref!RenderPassObject GetRenderPass(VkRenderPass renderPass) {
-    assert(renderPass in State.RenderPasses)
-    return State.RenderPasses[renderPass]
-}
-
-macro ref!PipelineCacheObject GetPipelineCache(VkPipelineCache pipelineCache) {
-    assert(pipelineCache in State.PipelineCaches)
-    return State.PipelineCaches[pipelineCache]
-}
-
-macro ref!CommandPoolObject GetCommandPool(VkCommandPool commandPool) {
-    assert(commandPool in State.CommandPools)
-    return State.CommandPools[commandPool]
-}
-
-macro ref!SurfaceObject GetSurface(VkSurfaceKHR surface) {
-    assert(surface in State.Surfaces)
-    return State.Surfaces[surface]
-}
-
-macro ref!SwapchainObject GetSwapchain(VkSwapchainKHR swapchain) {
-    assert(swapchain in State.Swapchains)
-    return State.Swapchains[swapchain]
-}
-
-macro VkQueueFlags AddQueueFlag(VkQueueFlags flags, VkQueueFlagBits bit) {
-    return as!VkQueueFlags(as!u32(flags) | as!u32(bit))
-}
diff --git a/vulkan/include/vulkan/vk_android_native_buffer.h b/vulkan/include/vulkan/vk_android_native_buffer.h
index 23006fa..9ffe83b 100644
--- a/vulkan/include/vulkan/vk_android_native_buffer.h
+++ b/vulkan/include/vulkan/vk_android_native_buffer.h
@@ -62,6 +62,11 @@
 typedef VkFlags VkSwapchainImageUsageFlagsANDROID;
 
 typedef struct {
+    uint64_t consumer;
+    uint64_t producer;
+} VkNativeBufferUsage2ANDROID;
+
+typedef struct {
     VkStructureType             sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
     const void*                 pNext;
 
@@ -73,10 +78,7 @@
     int                         format;
     int                         usage; // DEPRECATED in SPEC_VERSION 6
     // -- Added in SPEC_VERSION 6 --
-    struct {
-        uint64_t                consumer;
-        uint64_t                producer;
-    } usage2;
+    VkNativeBufferUsage2ANDROID usage2;
 } VkNativeBufferANDROID;
 
 typedef struct {
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 71048db..368130d 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -664,6 +664,12 @@
         return VK_ERROR_LAYER_NOT_PRESENT;
     }
 
+    if (!layer.ref.GetGetInstanceProcAddr()) {
+        ALOGW("Failed to locate vkGetInstanceProcAddr in layer %s", name);
+        layer.ref.~LayerRef();
+        return VK_ERROR_LAYER_NOT_PRESENT;
+    }
+
     ALOGI("Loaded layer %s", name);
 
     return VK_SUCCESS;
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index df86af0..37b5368 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -16,12 +16,11 @@
 
 // WARNING: This file is generated. See ../README.md for instructions.
 
+#include <log/log.h>
 #include <string.h>
 
 #include <algorithm>
 
-#include <log/log.h>
-
 // to catch mismatches between vulkan.h and this file
 #undef VK_NO_PROTOTYPES
 #include "api.h"
@@ -55,6 +54,11 @@
 
 // clang-format off
 
+VKAPI_ATTR VkResult disabledCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*) {
+    driver::Logger(instance).Err(instance, "VK_KHR_android_surface not enabled. Exported vkCreateAndroidSurfaceKHR not executed.");
+    return VK_SUCCESS;
+}
+
 VKAPI_ATTR void disabledDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR, const VkAllocationCallbacks*) {
     driver::Logger(instance).Err(instance, "VK_KHR_surface not enabled. Exported vkDestroySurfaceKHR not executed.");
 }
@@ -113,18 +117,13 @@
     return VK_SUCCESS;
 }
 
-VKAPI_ATTR VkResult disabledGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR, uint32_t*, VkRect2D*) {
-    driver::Logger(physicalDevice).Err(physicalDevice, "VK_KHR_swapchain not enabled. Exported vkGetPhysicalDevicePresentRectanglesKHR not executed.");
-    return VK_SUCCESS;
-}
-
 VKAPI_ATTR VkResult disabledAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR*, uint32_t*) {
     driver::Logger(device).Err(device, "VK_KHR_swapchain not enabled. Exported vkAcquireNextImage2KHR not executed.");
     return VK_SUCCESS;
 }
 
-VKAPI_ATTR VkResult disabledCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*) {
-    driver::Logger(instance).Err(instance, "VK_KHR_android_surface not enabled. Exported vkCreateAndroidSurfaceKHR not executed.");
+VKAPI_ATTR VkResult disabledGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR, uint32_t*, VkRect2D*) {
+    driver::Logger(physicalDevice).Err(physicalDevice, "VK_KHR_swapchain not enabled. Exported vkGetPhysicalDevicePresentRectanglesKHR not executed.");
     return VK_SUCCESS;
 }
 
@@ -162,7 +161,12 @@
     INIT_PROC(true, instance, CreateDevice);
     INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
     INIT_PROC(true, instance, GetPhysicalDeviceSparseImageFormatProperties);
-    INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
+    INIT_PROC_EXT(KHR_android_surface, true, instance, CreateAndroidSurfaceKHR);
+    INIT_PROC_EXT(KHR_surface, true, instance, DestroySurfaceKHR);
+    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceSupportKHR);
+    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
+    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceFormatsKHR);
+    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfacePresentModesKHR);
     INIT_PROC(false, instance, GetPhysicalDeviceFeatures2);
     INIT_PROC(false, instance, GetPhysicalDeviceProperties2);
     INIT_PROC(false, instance, GetPhysicalDeviceFormatProperties2);
@@ -171,15 +175,10 @@
     INIT_PROC(false, instance, GetPhysicalDeviceMemoryProperties2);
     INIT_PROC(false, instance, GetPhysicalDeviceSparseImageFormatProperties2);
     INIT_PROC(false, instance, GetPhysicalDeviceExternalBufferProperties);
-    INIT_PROC(false, instance, GetPhysicalDeviceExternalFenceProperties);
     INIT_PROC(false, instance, GetPhysicalDeviceExternalSemaphoreProperties);
-    INIT_PROC_EXT(KHR_surface, true, instance, DestroySurfaceKHR);
-    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceSupportKHR);
-    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
-    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceFormatsKHR);
-    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfacePresentModesKHR);
+    INIT_PROC(false, instance, GetPhysicalDeviceExternalFenceProperties);
+    INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
     INIT_PROC_EXT(KHR_swapchain, false, instance, GetPhysicalDevicePresentRectanglesKHR);
-    INIT_PROC_EXT(KHR_android_surface, true, instance, CreateAndroidSurfaceKHR);
     // clang-format on
 
     return success;
@@ -314,32 +313,32 @@
     INIT_PROC(true, dev, CmdNextSubpass);
     INIT_PROC(true, dev, CmdEndRenderPass);
     INIT_PROC(true, dev, CmdExecuteCommands);
-    INIT_PROC(false, dev, BindBufferMemory2);
-    INIT_PROC(false, dev, BindImageMemory2);
-    INIT_PROC(false, dev, GetDeviceGroupPeerMemoryFeatures);
-    INIT_PROC(false, dev, CmdSetDeviceMask);
-    INIT_PROC(false, dev, CmdDispatchBase);
-    INIT_PROC(false, dev, GetImageMemoryRequirements2);
-    INIT_PROC(false, dev, GetBufferMemoryRequirements2);
-    INIT_PROC(false, dev, GetImageSparseMemoryRequirements2);
-    INIT_PROC(false, dev, TrimCommandPool);
-    INIT_PROC(false, dev, GetDeviceQueue2);
-    INIT_PROC(false, dev, CreateSamplerYcbcrConversion);
-    INIT_PROC(false, dev, DestroySamplerYcbcrConversion);
-    INIT_PROC(false, dev, CreateDescriptorUpdateTemplate);
-    INIT_PROC(false, dev, DestroyDescriptorUpdateTemplate);
-    INIT_PROC(false, dev, UpdateDescriptorSetWithTemplate);
-    INIT_PROC(false, dev, GetDescriptorSetLayoutSupport);
     INIT_PROC_EXT(KHR_swapchain, true, dev, CreateSwapchainKHR);
     INIT_PROC_EXT(KHR_swapchain, true, dev, DestroySwapchainKHR);
     INIT_PROC_EXT(KHR_swapchain, true, dev, GetSwapchainImagesKHR);
     INIT_PROC_EXT(KHR_swapchain, true, dev, AcquireNextImageKHR);
     INIT_PROC_EXT(KHR_swapchain, true, dev, QueuePresentKHR);
+    INIT_PROC(false, dev, TrimCommandPool);
+    INIT_PROC(false, dev, GetDeviceGroupPeerMemoryFeatures);
+    INIT_PROC(false, dev, BindBufferMemory2);
+    INIT_PROC(false, dev, BindImageMemory2);
+    INIT_PROC(false, dev, CmdSetDeviceMask);
     INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupPresentCapabilitiesKHR);
     INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupSurfacePresentModesKHR);
     INIT_PROC_EXT(KHR_swapchain, false, dev, AcquireNextImage2KHR);
-    INIT_PROC_EXT(ANDROID_external_memory_android_hardware_buffer, false, dev, GetAndroidHardwareBufferPropertiesANDROID);
-    INIT_PROC_EXT(ANDROID_external_memory_android_hardware_buffer, false, dev, GetMemoryAndroidHardwareBufferANDROID);
+    INIT_PROC(false, dev, CmdDispatchBase);
+    INIT_PROC(false, dev, CreateDescriptorUpdateTemplate);
+    INIT_PROC(false, dev, DestroyDescriptorUpdateTemplate);
+    INIT_PROC(false, dev, UpdateDescriptorSetWithTemplate);
+    INIT_PROC(false, dev, GetBufferMemoryRequirements2);
+    INIT_PROC(false, dev, GetImageMemoryRequirements2);
+    INIT_PROC(false, dev, GetImageSparseMemoryRequirements2);
+    INIT_PROC(false, dev, CreateSamplerYcbcrConversion);
+    INIT_PROC(false, dev, DestroySamplerYcbcrConversion);
+    INIT_PROC(false, dev, GetDeviceQueue2);
+    INIT_PROC(false, dev, GetDescriptorSetLayoutSupport);
+    INIT_PROC_EXT(ANDROID_external_memory_android_hardware_buffer, true, dev, GetAndroidHardwareBufferPropertiesANDROID);
+    INIT_PROC_EXT(ANDROID_external_memory_android_hardware_buffer, true, dev, GetMemoryAndroidHardwareBufferANDROID);
     // clang-format on
 
     return success;
@@ -479,33 +478,7 @@
 VKAPI_ATTR void CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents);
 VKAPI_ATTR void CmdEndRenderPass(VkCommandBuffer commandBuffer);
 VKAPI_ATTR void CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
-VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
-VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
-VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
-VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask);
-VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
-VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
-VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
-VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
-VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
-VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
-VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
-VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
-VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
-VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
-VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
-VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
-VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
-VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
-VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
-VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
-VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
-VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
-VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
-VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
-VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
-VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
-VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
+VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
 VKAPI_ATTR void DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator);
 VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported);
 VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities);
@@ -516,11 +489,37 @@
 VKAPI_ATTR VkResult GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages);
 VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex);
 VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo);
+VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
+VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask);
 VKAPI_ATTR VkResult GetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities);
 VKAPI_ATTR VkResult GetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes);
-VKAPI_ATTR VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
 VKAPI_ATTR VkResult AcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex);
-VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+VKAPI_ATTR VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
+VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
+VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
 VKAPI_ATTR VkResult GetAndroidHardwareBufferPropertiesANDROID(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties);
 VKAPI_ATTR VkResult GetMemoryAndroidHardwareBufferANDROID(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer);
 
@@ -622,9 +621,9 @@
     // global functions
     if (instance == VK_NULL_HANDLE) {
         if (strcmp(pName, "vkCreateInstance") == 0) return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
+        if (strcmp(pName, "vkEnumerateInstanceVersion") == 0) return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceVersion);
         if (strcmp(pName, "vkEnumerateInstanceLayerProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties);
         if (strcmp(pName, "vkEnumerateInstanceExtensionProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties);
-        if (strcmp(pName, "vkEnumerateInstanceVersion") == 0) return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceVersion);
 
         ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \"%s\") call", pName);
         return nullptr;
@@ -1313,112 +1312,8 @@
     GetData(commandBuffer).dispatch.CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers);
 }
 
-VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos) {
-    return GetData(device).dispatch.BindBufferMemory2(device, bindInfoCount, pBindInfos);
-}
-
-VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
-    return GetData(device).dispatch.BindImageMemory2(device, bindInfoCount, pBindInfos);
-}
-
-VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
-    GetData(device).dispatch.GetDeviceGroupPeerMemoryFeatures(device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
-}
-
-VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
-    GetData(commandBuffer).dispatch.CmdSetDeviceMask(commandBuffer, deviceMask);
-}
-
-VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
-    GetData(commandBuffer).dispatch.CmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
-}
-
-VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
-    return GetData(instance).dispatch.EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
-}
-
-VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
-    GetData(device).dispatch.GetImageMemoryRequirements2(device, pInfo, pMemoryRequirements);
-}
-
-VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
-    GetData(device).dispatch.GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
-}
-
-VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
-    GetData(device).dispatch.GetImageSparseMemoryRequirements2(device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
-}
-
-VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures) {
-    GetData(physicalDevice).dispatch.GetPhysicalDeviceFeatures2(physicalDevice, pFeatures);
-}
-
-VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties) {
-    GetData(physicalDevice).dispatch.GetPhysicalDeviceProperties2(physicalDevice, pProperties);
-}
-
-VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties) {
-    GetData(physicalDevice).dispatch.GetPhysicalDeviceFormatProperties2(physicalDevice, format, pFormatProperties);
-}
-
-VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) {
-    return GetData(physicalDevice).dispatch.GetPhysicalDeviceImageFormatProperties2(physicalDevice, pImageFormatInfo, pImageFormatProperties);
-}
-
-VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties) {
-    GetData(physicalDevice).dispatch.GetPhysicalDeviceQueueFamilyProperties2(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
-}
-
-VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
-    GetData(physicalDevice).dispatch.GetPhysicalDeviceMemoryProperties2(physicalDevice, pMemoryProperties);
-}
-
-VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
-    GetData(physicalDevice).dispatch.GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice, pFormatInfo, pPropertyCount, pProperties);
-}
-
-VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
-    GetData(device).dispatch.TrimCommandPool(device, commandPool, flags);
-}
-
-VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
-    GetData(device).dispatch.GetDeviceQueue2(device, pQueueInfo, pQueue);
-}
-
-VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
-    return GetData(device).dispatch.CreateSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
-}
-
-VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) {
-    GetData(device).dispatch.DestroySamplerYcbcrConversion(device, ycbcrConversion, pAllocator);
-}
-
-VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
-    return GetData(device).dispatch.CreateDescriptorUpdateTemplate(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
-}
-
-VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator) {
-    GetData(device).dispatch.DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator);
-}
-
-VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
-    GetData(device).dispatch.UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData);
-}
-
-VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
-    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
-}
-
-VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
-    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
-}
-
-VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
-    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
-}
-
-VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
-    GetData(device).dispatch.GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
+VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
+    return GetData(instance).dispatch.CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
 }
 
 VKAPI_ATTR void DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator) {
@@ -1461,6 +1356,70 @@
     return GetData(queue).dispatch.QueuePresentKHR(queue, pPresentInfo);
 }
 
+VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceFeatures2(physicalDevice, pFeatures);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceProperties2(physicalDevice, pProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceFormatProperties2(physicalDevice, format, pFormatProperties);
+}
+
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) {
+    return GetData(physicalDevice).dispatch.GetPhysicalDeviceImageFormatProperties2(physicalDevice, pImageFormatInfo, pImageFormatProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceQueueFamilyProperties2(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceMemoryProperties2(physicalDevice, pMemoryProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice, pFormatInfo, pPropertyCount, pProperties);
+}
+
+VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
+    GetData(device).dispatch.TrimCommandPool(device, commandPool, flags);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
+    GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
+}
+
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+    return GetData(instance).dispatch.EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+}
+
+VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
+    GetData(device).dispatch.GetDeviceGroupPeerMemoryFeatures(device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
+}
+
+VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos) {
+    return GetData(device).dispatch.BindBufferMemory2(device, bindInfoCount, pBindInfos);
+}
+
+VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+    return GetData(device).dispatch.BindImageMemory2(device, bindInfoCount, pBindInfos);
+}
+
+VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
+    GetData(commandBuffer).dispatch.CmdSetDeviceMask(commandBuffer, deviceMask);
+}
+
 VKAPI_ATTR VkResult GetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
     return GetData(device).dispatch.GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
 }
@@ -1469,16 +1428,56 @@
     return GetData(device).dispatch.GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
 }
 
-VKAPI_ATTR VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects) {
-    return GetData(physicalDevice).dispatch.GetPhysicalDevicePresentRectanglesKHR(physicalDevice, surface, pRectCount, pRects);
-}
-
 VKAPI_ATTR VkResult AcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex) {
     return GetData(device).dispatch.AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex);
 }
 
-VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
-    return GetData(instance).dispatch.CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
+VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
+    GetData(commandBuffer).dispatch.CmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
+}
+
+VKAPI_ATTR VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects) {
+    return GetData(physicalDevice).dispatch.GetPhysicalDevicePresentRectanglesKHR(physicalDevice, surface, pRectCount, pRects);
+}
+
+VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+    return GetData(device).dispatch.CreateDescriptorUpdateTemplate(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+}
+
+VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator) {
+    GetData(device).dispatch.DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator);
+}
+
+VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
+    GetData(device).dispatch.UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData);
+}
+
+VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+    GetData(device).dispatch.GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+    GetData(device).dispatch.GetImageMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+    GetData(device).dispatch.GetImageSparseMemoryRequirements2(device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
+    return GetData(device).dispatch.CreateSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
+}
+
+VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) {
+    GetData(device).dispatch.DestroySamplerYcbcrConversion(device, ycbcrConversion, pAllocator);
+}
+
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+    GetData(device).dispatch.GetDeviceQueue2(device, pQueueInfo, pQueue);
+}
+
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
+    GetData(device).dispatch.GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
 }
 
 VKAPI_ATTR VkResult GetAndroidHardwareBufferPropertiesANDROID(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
@@ -1565,6 +1564,11 @@
 }
 
 __attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateInstanceVersion(uint32_t* pApiVersion) {
+    return vulkan::api::EnumerateInstanceVersion(pApiVersion);
+}
+
+__attribute__((visibility("default")))
 VKAPI_ATTR VkResult vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
     return vulkan::api::EnumerateInstanceLayerProperties(pPropertyCount, pProperties);
 }
@@ -2185,143 +2189,8 @@
 }
 
 __attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkEnumerateInstanceVersion(uint32_t* pApiVersion) {
-    return vulkan::api::EnumerateInstanceVersion(pApiVersion);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkBindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos) {
-    return vulkan::api::BindBufferMemory2(device, bindInfoCount, pBindInfos);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
-    return vulkan::api::BindImageMemory2(device, bindInfoCount, pBindInfos);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
-    vulkan::api::GetDeviceGroupPeerMemoryFeatures(device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
-    vulkan::api::CmdSetDeviceMask(commandBuffer, deviceMask);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
-    vulkan::api::CmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkEnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
-    return vulkan::api::EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
-    vulkan::api::GetImageMemoryRequirements2(device, pInfo, pMemoryRequirements);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
-    vulkan::api::GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
-    vulkan::api::GetImageSparseMemoryRequirements2(device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures) {
-    vulkan::api::GetPhysicalDeviceFeatures2(physicalDevice, pFeatures);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties) {
-    vulkan::api::GetPhysicalDeviceProperties2(physicalDevice, pProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties) {
-    vulkan::api::GetPhysicalDeviceFormatProperties2(physicalDevice, format, pFormatProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) {
-    return vulkan::api::GetPhysicalDeviceImageFormatProperties2(physicalDevice, pImageFormatInfo, pImageFormatProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties) {
-    vulkan::api::GetPhysicalDeviceQueueFamilyProperties2(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
-    vulkan::api::GetPhysicalDeviceMemoryProperties2(physicalDevice, pMemoryProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
-    vulkan::api::GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice, pFormatInfo, pPropertyCount, pProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkTrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
-    vulkan::api::TrimCommandPool(device, commandPool, flags);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
-    vulkan::api::GetDeviceQueue2(device, pQueueInfo, pQueue);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
-    return vulkan::api::CreateSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) {
-    vulkan::api::DestroySamplerYcbcrConversion(device, ycbcrConversion, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
-    return vulkan::api::CreateDescriptorUpdateTemplate(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkDestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator) {
-    vulkan::api::DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkUpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
-    vulkan::api::UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
-    vulkan::api::GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
-    vulkan::api::GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
-    vulkan::api::GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
-}
-
-__attribute__((visibility("default")))
-VKAPI_ATTR void vkGetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
-    vulkan::api::GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
+VKAPI_ATTR VkResult vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
+    return vulkan::api::CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
 }
 
 __attribute__((visibility("default")))
@@ -2375,6 +2244,86 @@
 }
 
 __attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures) {
+    vulkan::api::GetPhysicalDeviceFeatures2(physicalDevice, pFeatures);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties) {
+    vulkan::api::GetPhysicalDeviceProperties2(physicalDevice, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties) {
+    vulkan::api::GetPhysicalDeviceFormatProperties2(physicalDevice, format, pFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) {
+    return vulkan::api::GetPhysicalDeviceImageFormatProperties2(physicalDevice, pImageFormatInfo, pImageFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties) {
+    vulkan::api::GetPhysicalDeviceQueueFamilyProperties2(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
+    vulkan::api::GetPhysicalDeviceMemoryProperties2(physicalDevice, pMemoryProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
+    vulkan::api::GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice, pFormatInfo, pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkTrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
+    vulkan::api::TrimCommandPool(device, commandPool, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
+    vulkan::api::GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
+    vulkan::api::GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
+    vulkan::api::GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+    return vulkan::api::EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
+    vulkan::api::GetDeviceGroupPeerMemoryFeatures(device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos) {
+    return vulkan::api::BindBufferMemory2(device, bindInfoCount, pBindInfos);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+    return vulkan::api::BindImageMemory2(device, bindInfoCount, pBindInfos);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
+    vulkan::api::CmdSetDeviceMask(commandBuffer, deviceMask);
+}
+
+__attribute__((visibility("default")))
 VKAPI_ATTR VkResult vkGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
     return vulkan::api::GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
 }
@@ -2385,18 +2334,68 @@
 }
 
 __attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects) {
-    return vulkan::api::GetPhysicalDevicePresentRectanglesKHR(physicalDevice, surface, pRectCount, pRects);
-}
-
-__attribute__((visibility("default")))
 VKAPI_ATTR VkResult vkAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex) {
     return vulkan::api::AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex);
 }
 
 __attribute__((visibility("default")))
-VKAPI_ATTR VkResult vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
-    return vulkan::api::CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
+VKAPI_ATTR void vkCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
+    vulkan::api::CmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects) {
+    return vulkan::api::GetPhysicalDevicePresentRectanglesKHR(physicalDevice, surface, pRectCount, pRects);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+    return vulkan::api::CreateDescriptorUpdateTemplate(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkUpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
+    vulkan::api::UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+    vulkan::api::GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+    vulkan::api::GetImageMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+    vulkan::api::GetImageSparseMemoryRequirements2(device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
+    return vulkan::api::CreateSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::DestroySamplerYcbcrConversion(device, ycbcrConversion, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+    vulkan::api::GetDeviceQueue2(device, pQueueInfo, pQueue);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
+    vulkan::api::GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
 }
 
 __attribute__((visibility("default")))
diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h
index 4bedbeb..2195845 100644
--- a/vulkan/libvulkan/api_gen.h
+++ b/vulkan/libvulkan/api_gen.h
@@ -20,7 +20,9 @@
 #define LIBVULKAN_API_GEN_H
 
 #include <vulkan/vulkan.h>
+
 #include <bitset>
+
 #include "driver_gen.h"
 
 namespace vulkan {
@@ -40,7 +42,12 @@
     PFN_vkCreateDevice CreateDevice;
     PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
     PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
-    PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
+    PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
+    PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
+    PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
+    PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
+    PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
+    PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
     PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2;
     PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
     PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2;
@@ -49,15 +56,10 @@
     PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysicalDeviceMemoryProperties2;
     PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysicalDeviceSparseImageFormatProperties2;
     PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties;
-    PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties;
     PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties;
-    PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
-    PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
-    PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
-    PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
-    PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
+    PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties;
+    PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
     PFN_vkGetPhysicalDevicePresentRectanglesKHR GetPhysicalDevicePresentRectanglesKHR;
-    PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
     // clang-format on
 };
 
@@ -184,30 +186,30 @@
     PFN_vkCmdNextSubpass CmdNextSubpass;
     PFN_vkCmdEndRenderPass CmdEndRenderPass;
     PFN_vkCmdExecuteCommands CmdExecuteCommands;
-    PFN_vkBindBufferMemory2 BindBufferMemory2;
-    PFN_vkBindImageMemory2 BindImageMemory2;
-    PFN_vkGetDeviceGroupPeerMemoryFeatures GetDeviceGroupPeerMemoryFeatures;
-    PFN_vkCmdSetDeviceMask CmdSetDeviceMask;
-    PFN_vkCmdDispatchBase CmdDispatchBase;
-    PFN_vkGetImageMemoryRequirements2 GetImageMemoryRequirements2;
-    PFN_vkGetBufferMemoryRequirements2 GetBufferMemoryRequirements2;
-    PFN_vkGetImageSparseMemoryRequirements2 GetImageSparseMemoryRequirements2;
-    PFN_vkTrimCommandPool TrimCommandPool;
-    PFN_vkGetDeviceQueue2 GetDeviceQueue2;
-    PFN_vkCreateSamplerYcbcrConversion CreateSamplerYcbcrConversion;
-    PFN_vkDestroySamplerYcbcrConversion DestroySamplerYcbcrConversion;
-    PFN_vkCreateDescriptorUpdateTemplate CreateDescriptorUpdateTemplate;
-    PFN_vkDestroyDescriptorUpdateTemplate DestroyDescriptorUpdateTemplate;
-    PFN_vkUpdateDescriptorSetWithTemplate UpdateDescriptorSetWithTemplate;
-    PFN_vkGetDescriptorSetLayoutSupport GetDescriptorSetLayoutSupport;
     PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
     PFN_vkDestroySwapchainKHR DestroySwapchainKHR;
     PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
     PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
     PFN_vkQueuePresentKHR QueuePresentKHR;
+    PFN_vkTrimCommandPool TrimCommandPool;
+    PFN_vkGetDeviceGroupPeerMemoryFeatures GetDeviceGroupPeerMemoryFeatures;
+    PFN_vkBindBufferMemory2 BindBufferMemory2;
+    PFN_vkBindImageMemory2 BindImageMemory2;
+    PFN_vkCmdSetDeviceMask CmdSetDeviceMask;
     PFN_vkGetDeviceGroupPresentCapabilitiesKHR GetDeviceGroupPresentCapabilitiesKHR;
     PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR;
     PFN_vkAcquireNextImage2KHR AcquireNextImage2KHR;
+    PFN_vkCmdDispatchBase CmdDispatchBase;
+    PFN_vkCreateDescriptorUpdateTemplate CreateDescriptorUpdateTemplate;
+    PFN_vkDestroyDescriptorUpdateTemplate DestroyDescriptorUpdateTemplate;
+    PFN_vkUpdateDescriptorSetWithTemplate UpdateDescriptorSetWithTemplate;
+    PFN_vkGetBufferMemoryRequirements2 GetBufferMemoryRequirements2;
+    PFN_vkGetImageMemoryRequirements2 GetImageMemoryRequirements2;
+    PFN_vkGetImageSparseMemoryRequirements2 GetImageSparseMemoryRequirements2;
+    PFN_vkCreateSamplerYcbcrConversion CreateSamplerYcbcrConversion;
+    PFN_vkDestroySamplerYcbcrConversion DestroySamplerYcbcrConversion;
+    PFN_vkGetDeviceQueue2 GetDeviceQueue2;
+    PFN_vkGetDescriptorSetLayoutSupport GetDescriptorSetLayoutSupport;
     PFN_vkGetAndroidHardwareBufferPropertiesANDROID GetAndroidHardwareBufferPropertiesANDROID;
     PFN_vkGetMemoryAndroidHardwareBufferANDROID GetMemoryAndroidHardwareBufferANDROID;
     // clang-format on
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
deleted file mode 100644
index bdd3573..0000000
--- a/vulkan/libvulkan/code-generator.tmpl
+++ /dev/null
@@ -1,1196 +0,0 @@
-{{define "Copyright"}}
-/*
-•* Copyright 2016 The Android Open Source Project
-•*
-•* Licensed under the Apache License, Version 2.0 (the "License");
-•* you may not use this file except in compliance with the License.
-•* You may obtain a copy of the License at
-•*
-•*      http://www.apache.org/licenses/LICENSE-2.0
-•*
-•* Unless required by applicable law or agreed to in writing, software
-•* distributed under the License is distributed on an "AS IS" BASIS,
-•* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-•* See the License for the specific language governing permissions and
-•* limitations under the License.
-•*/
-¶{{end}}
-
-{{Include "../api/templates/vulkan_common.tmpl"}}
-{{Global "clang-format" (Strings "clang-format" "-style=file")}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "api_gen.h"   | Format (Global "clang-format") | Write "api_gen.h"  }}
-{{$ | Macro "api_gen.cpp" | Format (Global "clang-format") | Write "api_gen.cpp"}}
-{{$ | Macro "driver_gen.h" | Format (Global "clang-format") | Write "driver_gen.h"}}
-{{$ | Macro "driver_gen.cpp" | Format (Global "clang-format") | Write "driver_gen.cpp"}}
-
-{{/*
--------------------------------------------------------------------------------
-  api_gen.h
--------------------------------------------------------------------------------
-*/}}
-{{define "api_gen.h"}}
-{{Macro "Copyright"}}

-// WARNING: This file is generated. See ../README.md for instructions.

-#ifndef LIBVULKAN_API_GEN_H
-#define LIBVULKAN_API_GEN_H

-#include <bitset>
-#include <vulkan/vulkan.h>
-#include "driver_gen.h"

-namespace vulkan {«
-namespace api {«

-struct InstanceDispatchTable {
-  // clang-format off
-  {{range $f := AllCommands $}}
-    {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
-      {{Macro "C++.DeclareTableEntry" $f}};
-    {{end}}
-  {{end}}
-  // clang-format on
-};

-struct DeviceDispatchTable {
-  // clang-format off
-  {{range $f := AllCommands $}}
-    {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
-      {{Macro "C++.DeclareTableEntry" $f}};
-    {{end}}
-  {{end}}
-  // clang-format on
-};

-bool InitDispatchTable(
-    VkInstance instance,
-    PFN_vkGetInstanceProcAddr get_proc,
-    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);
-bool InitDispatchTable(
-    VkDevice dev,
-    PFN_vkGetDeviceProcAddr get_proc,
-    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);

-»} // namespace api
-»} // namespace vulkan

-#endif // LIBVULKAN_API_GEN_H
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  api_gen.cpp
--------------------------------------------------------------------------------
-*/}}
-{{define "api_gen.cpp"}}
-{{Macro "Copyright"}}

-// WARNING: This file is generated. See ../README.md for instructions.

-#include <string.h>

-#include <algorithm>

-#include <log/log.h>

-// to catch mismatches between vulkan.h and this file
-#undef VK_NO_PROTOTYPES
-#include "api.h"

-namespace vulkan {«
-namespace api {«

-{{Macro "C++.DefineInitProcMacro" "dispatch"}}

-{{Macro "api.C++.DefineInitProcExtMacro"}}

-namespace {«

-// clang-format off

-{{range $f := AllCommands $}}
-  {{Macro "api.C++.DefineExtensionStub" $f}}
-{{end}}
-// clang-format on

-»} // anonymous

-bool InitDispatchTable(
-    VkInstance instance,
-    PFN_vkGetInstanceProcAddr get_proc,
-    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
-    auto& data = GetData(instance);
-    bool success = true;
-    ¶
-    // clang-format off
-    {{range $f := AllCommands $}}
-      {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
-        {{Macro "C++.InitProc" $f}}
-      {{end}}
-    {{end}}
-    // clang-format on
-    ¶
-    return success;
-}

-bool InitDispatchTable(
-    VkDevice dev,
-    PFN_vkGetDeviceProcAddr get_proc,
-    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
-    auto& data = GetData(dev);
-    bool success = true;
-    ¶
-    // clang-format off
-    {{range $f := AllCommands $}}
-      {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
-        {{Macro "C++.InitProc" $f}}
-      {{end}}
-    {{end}}
-    // clang-format on
-    ¶
-    return success;
-}

-// clang-format off

-namespace {«

-// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr
-{{range $f := AllCommands $}}
-  {{if and (Macro "IsFunctionExported" $f) (not (Macro "api.IsIntercepted" $f))}}
-    VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}});
-  {{end}}
-{{end}}

-{{range $f := AllCommands $}}
-  {{if and (Macro "IsFunctionExported" $f) (not (Macro "api.IsIntercepted" $f))}}
-    VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{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}}

-»}  // anonymous namespace

-// clang-format on

-»} // 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 not (IsVoid $f.Return.Type)}}return §{{end}}
-      vulkan::api::{{Macro "BaseName" $f}}({{Macro "Arguments" $f}});
-    }
-    ¶
-  {{end}}
-{{end}}

-// clang-format on
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  driver_gen.h
--------------------------------------------------------------------------------
-*/}}
-{{define "driver_gen.h"}}
-{{Macro "Copyright"}}

-// WARNING: This file is generated. See ../README.md for instructions.

-#ifndef LIBVULKAN_DRIVER_GEN_H
-#define LIBVULKAN_DRIVER_GEN_H

-#include <bitset>
-#include <vulkan/vulkan.h>
-#include <vulkan/vk_android_native_buffer.h>

-namespace vulkan {«
-namespace driver {«

-{{Macro "driver.C++.DefineProcHookType"}}

-struct InstanceDriverTable {
-  // clang-format off
-  {{range $f := AllCommands $}}
-    {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
-      {{Macro "C++.DeclareTableEntry" $f}};
-    {{end}}
-  {{end}}
-  // clang-format on
-};

-struct DeviceDriverTable {
-  // clang-format off
-  {{range $f := AllCommands $}}
-    {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
-      {{Macro "C++.DeclareTableEntry" $f}};
-    {{end}}
-  {{end}}
-  // clang-format on
-};

-const ProcHook* GetProcHook(const char* name);
-ProcHook::Extension GetProcHookExtension(const char* name);

-bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
-                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
-bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
-                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);

-»} // namespace driver
-»} // namespace vulkan

-#endif // LIBVULKAN_DRIVER_TABLE_H
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  driver_gen.cpp
--------------------------------------------------------------------------------
-*/}}
-{{define "driver_gen.cpp"}}
-{{Macro "Copyright"}}

-// WARNING: This file is generated. See ../README.md for instructions.

-#include <string.h>

-#include <algorithm>

-#include <log/log.h>

-#include "driver.h"

-namespace vulkan {«
-namespace driver {«

-namespace {«

-// clang-format off

-{{range $f := AllCommands $}}
-  {{Macro "driver.C++.DefineProcHookStub" $f}}
-{{end}}
-// clang-format on

-const ProcHook g_proc_hooks[] = {
-  // clang-format off
-  {{range $f := SortBy (AllCommands $) "FunctionName"}}
-    {{if (Macro "driver.IsIntercepted" $f)}}
-      {{     if (Macro "IsGloballyDispatched" $f)}}
-        {{Macro "driver.C++.DefineGlobalProcHook" $f}}
-      {{else if (Macro "IsInstanceDispatched" $f)}}
-        {{Macro "driver.C++.DefineInstanceProcHook" $f}}
-      {{else if (Macro "IsDeviceDispatched" $f)}}
-        {{Macro "driver.C++.DefineDeviceProcHook" $f}}
-      {{end}}
-    {{end}}
-  {{end}}
-  // clang-format on
-};

-»} // anonymous

-const ProcHook* GetProcHook(const char* name) {
-    const auto& begin = g_proc_hooks;
-    const auto& end = g_proc_hooks +
-      sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
-    const auto hook = std::lower_bound(begin, end, name,
-        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
-    return (hook <  end && strcmp(hook->name, name) == 0) ? hook : nullptr;
-}

-ProcHook::Extension GetProcHookExtension(const char* name) {
-  {{$exts := Strings (Macro "driver.KnownExtensions") | SplitOn "\n"}}
-  // clang-format off
-  {{range $e := $exts}}
-    if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
-  {{end}}
-  // clang-format on
-  return ProcHook::EXTENSION_UNKNOWN;
-}

-{{Macro "C++.DefineInitProcMacro" "driver"}}

-{{Macro "driver.C++.DefineInitProcExtMacro"}}

-bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
-                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
-{
-    auto& data = GetData(instance);
-    bool success = true;
-    ¶
-    // clang-format off
-    {{range $f := AllCommands $}}
-      {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
-        {{Macro "C++.InitProc" $f}}
-      {{end}}
-    {{end}}
-    // clang-format on
-    ¶
-    return success;
-}

-bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
-                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
-{
-    auto& data = GetData(dev);
-    bool success = true;
-    ¶
-    // clang-format off
-    {{range $f := AllCommands $}}
-      {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
-        {{Macro "C++.InitProc" $f}}
-      {{end}}
-    {{end}}
-    // clang-format on
-    ¶
-    return success;
-}

-»} // namespace driver
-»} // namespace vulkan

-// clang-format on
-¶{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits a declaration of a dispatch/driver table entry.
-------------------------------------------------------------------------------
-*/}}
-{{define "C++.DeclareTableEntry"}}
-  {{AssertType $ "Function"}}
-
-  {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits INIT_PROC macro.
--------------------------------------------------------------------------------
-*/}}
-{{define "C++.DefineInitProcMacro"}}
-  #define UNLIKELY(expr) __builtin_expect((expr), 0)
-  ¶
-  #define INIT_PROC(required, obj, proc) do {                   \
-      data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>(       \
-              get_proc(obj, "vk" # proc));                      \
-      if (UNLIKELY(required && !data.{{$}}.proc)) {             \
-          ALOGE("missing " # obj " proc: vk" # proc);           \
-          success = false;                                      \
-      }                                                         \
-  } while(0)
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits code to invoke INIT_PROC or INIT_PROC_EXT.
--------------------------------------------------------------------------------
-*/}}
-{{define "C++.InitProc"}}
-  {{AssertType $ "Function"}}
-
-  {{$ext := GetAnnotation $ "extension"}}
-  {{if $ext}}
-    INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
-  {{else}}
-    INIT_PROC(§
-  {{end}}
-
-  {{if GetAnnotation $ "optional"}}false{{else if GetAnnotation $ "vulkan1_1"}}false{{else}}true{{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" $)}}
-    {{/* deprecated and unused internally */}}
-    {{if not (eq $.Name "vkEnumerateDeviceLayerProperties")}}
-      true
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if a function is exported and device-dispatched.
-------------------------------------------------------------------------------
-*/}}
-{{define "api.IsDeviceDispatchTableEntry"}}
-  {{AssertType $ "Function"}}
-
-  {{if and (Macro "IsFunctionExported" $) (Macro "IsDeviceDispatched" $)}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if a function is intercepted by vulkan::api.
-------------------------------------------------------------------------------
-*/}}
-{{define "api.IsIntercepted"}}
-  {{AssertType $ "Function"}}
-
-  {{if (Macro "IsFunctionSupported" $)}}
-    {{/* Global functions cannot be dispatched at all */}}
-    {{     if (Macro "IsGloballyDispatched" $)}}true
-
-    {{/* VkPhysicalDevice functions that manage device layers */}}
-    {{else if eq $.Name "vkCreateDevice"}}true
-    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
-    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
-
-    {{/* Destroy functions of dispatchable objects */}}
-    {{else if eq $.Name "vkDestroyInstance"}}true
-    {{else if eq $.Name "vkDestroyDevice"}}true
-
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits INIT_PROC_EXT macro for vulkan::api.
--------------------------------------------------------------------------------
-*/}}
-{{define "api.C++.DefineInitProcExtMacro"}}
-  // Exported extension functions may be invoked even when their extensions
-  // are disabled.  Dispatch to stubs when that happens.
-  #define INIT_PROC_EXT(ext, required, obj, proc) do {          \
-      if (extensions[driver::ProcHook::ext])                    \
-        INIT_PROC(required, obj, proc);                         \
-      else                                                      \
-        data.dispatch.proc = disabled ## proc;                  \
-  } while(0)
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a stub for an exported extension function.
--------------------------------------------------------------------------------
-*/}}
-{{define "api.C++.DefineExtensionStub"}}
-  {{AssertType $ "Function"}}
-
-  {{$ext := GetAnnotation $ "extension"}}
-  {{if and $ext (Macro "IsFunctionExported" $)}}
-    {{$ext_name := index $ext.Arguments 0}}
-
-    {{$base := (Macro "BaseName" $)}}
-
-    {{$p0 := (index $.CallParameters 0)}}
-    {{$ptail := (Tail 1 $.CallParameters)}}
-
-    {{$first_type := (Macro "Parameter" $p0)}}
-    {{$tail_types := (ForEach $ptail "ParameterType" | JoinWith ", ")}}
-
-    VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$first_type}}, {{$tail_types}}) {
-      driver::Logger({{$p0.Name}}).Err({{$p0.Name}}, §
-        "{{$ext_name}} not enabled. Exported {{$.Name}} not executed.");
-      {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
-    }
-    ¶
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits code for vkGetInstanceProcAddr for function interception.
-------------------------------------------------------------------------------
-*/}}
-{{define "api.C++.InterceptInstanceProcAddr"}}
-  {{AssertType $ "API"}}
-
-  // global functions
-  if (instance == VK_NULL_HANDLE) {
-    {{range $f := AllCommands $}}
-      {{if (Macro "IsGloballyDispatched" $f)}}
-        if (strcmp(pName, "{{$f.Name}}") == 0) return §
-          reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}});
-      {{end}}
-    {{end}}
-    ¶
-    ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \"%s\") call", 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>(§
-            {{Macro "BaseName" $f}}) },
-
-        {{/* redirect vkGetInstanceProcAddr to itself */}}
-        {{else if eq $f.Name "vkGetInstanceProcAddr"}}
-          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}}) },
-
-        {{/* 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>({{Macro "BaseName" $f}}) },
-
-        {{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) {
-      vulkan::driver::Logger(instance).Err(
-        instance, "invalid vkGetInstanceProcAddr(%p, \"%s\") call",
-        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("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
-    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); })) {
-    vulkan::driver::Logger(device).Err(§
-      device, "invalid vkGetDeviceProcAddr(%p, \"%s\") call", device,§
-      (pName) ? pName : "(null)");
-    return nullptr;
-  }
-  // clang-format off
-  ¶
-  {{range $f := AllCommands $}}
-    {{if (Macro "IsDeviceDispatched" $f)}}
-      {{     if (Macro "api.IsIntercepted" $f)}}
-        if (strcmp(pName, "{{$f.Name}}") == 0) return §
-          reinterpret_cast<PFN_vkVoidFunction>(§
-            {{Macro "BaseName" $f}});
-      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
-        if (strcmp(pName, "{{$f.Name}}") == 0) return §
-          reinterpret_cast<PFN_vkVoidFunction>(§
-            {{Macro "BaseName" $f}});
-      {{end}}
-    {{end}}
-  {{end}}
-  ¶
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits code to dispatch a function.
-------------------------------------------------------------------------------
-*/}}
-{{define "api.C++.Dispatch"}}
-  {{AssertType $ "Function"}}
-  {{if (Macro "api.IsIntercepted" $)}}
-    {{Error "$.Name should not be generated"}}
-  {{end}}
-
-  {{if not (IsVoid $.Return.Type)}}return §{{end}}
-
-  {{$p0 := index $.CallParameters 0}}
-  GetData({{$p0.Name}}).dispatch.§
-  {{Macro "BaseName" $}}({{Macro "Arguments" $}});
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits a list of extensions intercepted by vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.InterceptedExtensions"}}
-VK_ANDROID_native_buffer
-VK_EXT_debug_report
-VK_EXT_hdr_metadata
-VK_EXT_swapchain_colorspace
-VK_GOOGLE_display_timing
-VK_KHR_android_surface
-VK_KHR_incremental_present
-VK_KHR_shared_presentable_image
-VK_KHR_surface
-VK_KHR_swapchain
-VK_KHR_get_surface_capabilities2
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits a list of extensions known to vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.KnownExtensions"}}
-{{Macro "driver.InterceptedExtensions"}}
-VK_KHR_get_physical_device_properties2
-VK_ANDROID_external_memory_android_hardware_buffer
-VK_KHR_bind_memory2
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if an extension is intercepted by vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.IsExtensionIntercepted"}}
-  {{$ext_name := index $.Arguments 0}}
-  {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
-
-  {{range $f := $filters}}
-    {{if eq $ext_name $f}}true{{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if a function is intercepted by vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.IsIntercepted"}}
-  {{AssertType $ "Function"}}
-
-  {{if (Macro "IsFunctionSupported" $)}}
-    {{/* Create functions of dispatchable objects */}}
-    {{     if eq $.Name "vkCreateInstance"}}true
-    {{else if eq $.Name "vkCreateDevice"}}true
-    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
-    {{else if eq $.Name "vkEnumeratePhysicalDeviceGroups"}}true
-    {{else if eq $.Name "vkGetDeviceQueue"}}true
-    {{else if eq $.Name "vkGetDeviceQueue2"}}true
-    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
-
-    {{/* Destroy functions of dispatchable objects */}}
-    {{else if eq $.Name "vkDestroyInstance"}}true
-    {{else if eq $.Name "vkDestroyDevice"}}true
-
-    {{/* Enumeration of extensions */}}
-    {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
-    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
-
-    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
-    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
-
-    {{/* VK_KHR_swapchain v69 requirement */}}
-    {{else if eq $.Name "vkBindImageMemory2"}}true
-    {{else if eq $.Name "vkBindImageMemory2KHR"}}true
-    {{end}}
-
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      {{Macro "driver.IsExtensionIntercepted" $ext}}
-    {{end}}
-
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if a function needs a ProcHook stub.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.NeedProcHookStub"}}
-  {{AssertType $ "Function"}}
-
-  {{if and (Macro "driver.IsIntercepted" $) (Macro "IsDeviceDispatched" $)}}
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits definition of struct ProcHook.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineProcHookType"}}
-  struct ProcHook {
-      enum Type {
-        GLOBAL,
-        INSTANCE,
-        DEVICE,
-      };
-
-      enum Extension {
-        {{$exts := Strings (Macro "driver.KnownExtensions") | SplitOn "\n"}}
-        {{range $e := $exts}}
-          {{TrimPrefix "VK_" $e}},
-        {{end}}
-        ¶
-        EXTENSION_CORE, // valid bit
-        EXTENSION_COUNT,
-        EXTENSION_UNKNOWN,
-      };
-      ¶
-      const char* name;
-      Type type;
-      Extension extension;
-      ¶
-      PFN_vkVoidFunction proc;
-      PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
-  };
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits INIT_PROC_EXT macro for vulkan::driver.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineInitProcExtMacro"}}
-  #define INIT_PROC_EXT(ext, required, obj, proc) do {          \
-      if (extensions[ProcHook::ext])                            \
-        INIT_PROC(required, obj, proc);                         \
-  } while(0)
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a stub for ProcHook::checked_proc.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineProcHookStub"}}
-  {{AssertType $ "Function"}}
-
-  {{if (Macro "driver.NeedProcHookStub" $)}}
-    {{$ext := GetAnnotation $ "extension"}}
-    {{$ext_name := index $ext.Arguments 0}}
-
-    {{$base := (Macro "BaseName" $)}}
-
-    VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
-      {{$p0 := index $.CallParameters 0}}
-      {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
-
-      if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) {
-        {{if not (IsVoid $.Return.Type)}}return §{{end}}
-        {{$base}}({{Macro "Arguments" $}});
-      } else {
-        Logger({{$p0.Name}}).Err({{$p0.Name}}, "{{$ext_name}} not enabled. {{$.Name}} not executed.");
-        {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
-      }
-    }
-    ¶
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits definition of a global ProcHook.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineGlobalProcHook"}}
-  {{AssertType $ "Function"}}
-
-  {{$base := (Macro "BaseName" $)}}
-
-  {{$ext := GetAnnotation $ "extension"}}
-  {{if $ext}}
-    {{Error "invalid global extension"}}
-  {{end}}
-
-  {
-    "{{$.Name}}",
-    ProcHook::GLOBAL,
-    ProcHook::EXTENSION_CORE,
-    reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
-    nullptr,
-  },
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits definition of an instance ProcHook.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineInstanceProcHook"}}
-  {{AssertType $ "Function"}}
-
-  {{$base := (Macro "BaseName" $)}}
-
-  {
-    "{{$.Name}}",
-    ProcHook::INSTANCE,
-
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      ProcHook::{{Macro "BaseName" $ext}},
-
-      {{if (Macro "IsExtensionInternal" $ext)}}
-        nullptr,
-        nullptr,
-      {{else}}
-        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
-        nullptr,
-      {{end}}
-    {{else}}
-      ProcHook::EXTENSION_CORE,
-      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
-      nullptr,
-    {{end}}
-  },
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits definition of a device ProcHook.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.C++.DefineDeviceProcHook"}}
-  {{AssertType $ "Function"}}
-
-  {{$base := (Macro "BaseName" $)}}
-
-  {
-    "{{$.Name}}",
-    ProcHook::DEVICE,
-
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      ProcHook::{{Macro "BaseName" $ext}},
-
-      {{if (Macro "IsExtensionInternal" $ext)}}
-        nullptr,
-        nullptr,
-      {{else}}
-        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
-        reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
-      {{end}}
-    {{else}}
-      ProcHook::EXTENSION_CORE,
-      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
-      nullptr,
-    {{end}}
-  },
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits true if a function is needed by vulkan::driver.
--------------------------------------------------------------------------------
-*/}}
-{{define "driver.IsDriverTableEntry"}}
-  {{AssertType $ "Function"}}
-
-  {{if (Macro "IsFunctionSupported" $)}}
-    {{/* Create functions of dispatchable objects */}}
-    {{     if eq $.Name "vkCreateDevice"}}true
-    {{else if eq $.Name "vkGetDeviceQueue"}}true
-    {{else if eq $.Name "vkGetDeviceQueue2"}}true
-    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
-
-    {{/* Destroy functions of dispatchable objects */}}
-    {{else if eq $.Name "vkDestroyInstance"}}true
-    {{else if eq $.Name "vkDestroyDevice"}}true
-
-    {{/* Enumeration of extensions */}}
-    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
-
-    {{/* We cache physical devices in loader.cpp */}}
-    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
-    {{else if eq $.Name "vkEnumeratePhysicalDeviceGroups"}}true
-
-    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
-    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
-
-    {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
-    {{else if eq $.Name "vkCreateImage"}}true
-    {{else if eq $.Name "vkDestroyImage"}}true
-
-    {{else if eq $.Name "vkGetPhysicalDeviceProperties"}}true
-    {{else if eq $.Name "vkGetPhysicalDeviceProperties2"}}true
-    {{else if eq $.Name "vkGetPhysicalDeviceProperties2KHR"}}true
-
-    {{/* VK_KHR_swapchain v69 requirement */}}
-    {{else if eq $.Name "vkBindImageMemory2"}}true
-    {{else if eq $.Name "vkBindImageMemory2KHR"}}true
-    {{end}}
-
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      {{$ext_name := index $ext.Arguments 0}}
-      {{     if eq $ext_name "VK_ANDROID_native_buffer"}}true
-      {{else if eq $ext_name "VK_EXT_debug_report"}}true
-      {{end}}
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if an instance-dispatched function is needed by vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.IsInstanceDriverTableEntry"}}
-  {{AssertType $ "Function"}}
-
-  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits true if a device-dispatched function is needed by vulkan::driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "driver.IsDeviceDriverTableEntry"}}
-  {{AssertType $ "Function"}}
-
-  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a function/extension name without the "vk"/"VK_" prefix.
--------------------------------------------------------------------------------
-*/}}
-{{define "BaseName"}}
-  {{     if IsFunction $}}{{TrimPrefix "vk" $.Name}}
-  {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
-  {{else}}{{Error "invalid use of BaseName"}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a comma-separated list of C parameter names for the given command.
--------------------------------------------------------------------------------
-*/}}
-{{define "Arguments"}}
-  {{AssertType $ "Function"}}
-
-  {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-*/}}
-{{define "IsGloballyDispatched"}}
-  {{AssertType $ "Function"}}
-  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emit "true" for supported functions that undergo table dispatch. Only global
-  functions and functions handled in the loader top without calling into
-  lower layers are not dispatched.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsInstanceDispatched"}}
-  {{AssertType $ "Function"}}
-  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emit "true" for supported functions that can have device-specific dispatch.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsDeviceDispatched"}}
-  {{AssertType $ "Function"}}
-  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emit "true" if a function is core or from a supportable extension.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsFunctionSupported"}}
-  {{AssertType $ "Function"}}
-  {{if not (GetAnnotation $ "pfn")}}
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if not $ext}}true
-    {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Decides whether a function should be exported from the Android Vulkan
-  library. Functions in the core API and in loader extensions are exported.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsFunctionExported"}}
-  {{AssertType $ "Function"}}
-
-  {{if (Macro "IsFunctionSupported" $)}}
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      {{Macro "IsExtensionExported" $ext}}
-    {{else}}
-      true
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emit "true" if an extension is unsupportable on Android.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsExtensionBlacklisted"}}
-  {{$ext := index $.Arguments 0}}
-  {{     if eq $ext "VK_KHR_display"}}true
-  {{else if eq $ext "VK_KHR_display_swapchain"}}true
-  {{else if eq $ext "VK_KHR_mir_surface"}}true
-  {{else if eq $ext "VK_KHR_xcb_surface"}}true
-  {{else if eq $ext "VK_KHR_xlib_surface"}}true
-  {{else if eq $ext "VK_KHR_wayland_surface"}}true
-  {{else if eq $ext "VK_KHR_win32_surface"}}true
-  {{else if eq $ext "VK_KHR_external_memory_win32"}}true
-  {{else if eq $ext "VK_KHR_win32_keyed_mutex"}}true
-  {{else if eq $ext "VK_KHR_external_semaphore_win32"}}true
-  {{else if eq $ext "VK_KHR_external_fence_win32"}}true
-  {{else if eq $ext "VK_EXT_acquire_xlib_display"}}true
-  {{else if eq $ext "VK_EXT_direct_mode_display"}}true
-  {{else if eq $ext "VK_EXT_display_surface_counter"}}true
-  {{else if eq $ext "VK_EXT_display_control"}}true
-  {{else if eq $ext "VK_FUCHSIA_imagepipe_surface"}}true
-  {{else if eq $ext "VK_MVK_ios_surface"}}true
-  {{else if eq $ext "VK_MVK_macos_surface"}}true
-  {{else if eq $ext "VK_NN_vi_surface"}}true
-  {{else if eq $ext "VK_NV_external_memory_win32"}}true
-  {{else if eq $ext "VK_NV_win32_keyed_mutex"}}true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Reports whether an extension has functions exported by the loader.
-  E.g. applications can directly link to an extension function.
-------------------------------------------------------------------------------
-*/}}
-{{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
-  {{else if eq $ext "VK_ANDROID_external_memory_android_hardware_buffer"}}true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Reports whether an extension is internal to the loader and drivers,
-  so the loader should not enumerate it.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsExtensionInternal"}}
-  {{$ext := index $.Arguments 0}}
-  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
-  {{end}}
-{{end}}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 23506ba..f596086 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -16,30 +16,29 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
+#include "driver.h"
+
+#include <dlfcn.h>
 #include <malloc.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/prctl.h>
-
-#include <dlfcn.h>
-#include <algorithm>
-#include <array>
-#include <new>
-
-#include <log/log.h>
 
 #include <android/dlext.h>
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android-base/properties.h>
 #include <configstore/Utils.h>
 #include <cutils/properties.h>
 #include <graphicsenv/GraphicsEnv.h>
+#include <log/log.h>
+#include <sys/prctl.h>
 #include <utils/Timers.h>
 #include <utils/Trace.h>
-#include <utils/Vector.h>
 
-#include "android-base/properties.h"
+#include <algorithm>
+#include <array>
+#include <new>
+#include <vector>
 
-#include "driver.h"
 #include "stubhal.h"
 
 using namespace android::hardware::configstore;
@@ -212,7 +211,7 @@
     if (!ns)
         return -ENOENT;
     android::GraphicsEnv::getInstance().setDriverToLoad(
-        android::GraphicsEnv::Driver::VULKAN);
+        android::GpuStatsInfo::Driver::VULKAN);
     return LoadDriver(ns, module);
 }
 
@@ -223,7 +222,7 @@
     if (!ns)
         return -ENOENT;
     android::GraphicsEnv::getInstance().setDriverToLoad(
-        android::GraphicsEnv::Driver::VULKAN_UPDATED);
+        android::GpuStatsInfo::Driver::VULKAN_UPDATED);
     return LoadDriver(ns, module);
 }
 
@@ -258,7 +257,7 @@
     }
     if (result != 0) {
         android::GraphicsEnv::getInstance().setDriverLoaded(
-            android::GraphicsEnv::Api::API_VK, false, systemTime() - openTime);
+            android::GpuStatsInfo::Api::API_VK, false, systemTime() - openTime);
         ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
         return true;
     }
@@ -272,7 +271,7 @@
     ATRACE_END();
     if (result != 0) {
         android::GraphicsEnv::getInstance().setDriverLoaded(
-            android::GraphicsEnv::Api::API_VK, false, systemTime() - openTime);
+            android::GpuStatsInfo::Api::API_VK, false, systemTime() - openTime);
         // Any device with a Vulkan HAL should be able to open the device.
         ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
               result);
@@ -284,7 +283,7 @@
     hal_.InitDebugReportIndex();
 
     android::GraphicsEnv::getInstance().setDriverLoaded(
-        android::GraphicsEnv::Api::API_VK, true, systemTime() - openTime);
+        android::GpuStatsInfo::Api::API_VK, true, systemTime() - openTime);
 
     return true;
 }
@@ -809,8 +808,7 @@
     const char* pLayerName,
     uint32_t* pPropertyCount,
     VkExtensionProperties* pProperties) {
-
-    android::Vector<VkExtensionProperties> loader_extensions;
+    std::vector<VkExtensionProperties> loader_extensions;
     loader_extensions.push_back({
         VK_KHR_SURFACE_EXTENSION_NAME,
         VK_KHR_SURFACE_SPEC_VERSION});
@@ -833,7 +831,7 @@
         uint32_t count = std::min(
             *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
 
-        std::copy_n(loader_extensions.begin(), count, pProperties);
+        std::copy_n(loader_extensions.data(), count, pProperties);
 
         if (count < loader_extensions.size()) {
             *pPropertyCount = count;
@@ -879,8 +877,7 @@
 
 bool QueryPresentationProperties(
     VkPhysicalDevice physicalDevice,
-    VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties)
-{
+    VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties) {
     const InstanceData& data = GetData(physicalDevice);
 
     // GPDP2 must be present and enabled on the instance.
@@ -920,7 +917,7 @@
     VkExtensionProperties* pProperties) {
     const InstanceData& data = GetData(physicalDevice);
     // extensions that are unconditionally exposed by the loader
-    android::Vector<VkExtensionProperties> loader_extensions;
+    std::vector<VkExtensionProperties> loader_extensions;
     loader_extensions.push_back({
         VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
         VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
@@ -956,7 +953,7 @@
         uint32_t count = std::min(
             *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
 
-        std::copy_n(loader_extensions.begin(), count, pProperties);
+        std::copy_n(loader_extensions.data(), count, pProperties);
 
         if (count < loader_extensions.size()) {
             *pPropertyCount = count;
@@ -1176,7 +1173,8 @@
 
     if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
         // Log that the app is hitting software Vulkan implementation
-        android::GraphicsEnv::getInstance().setCpuVulkanInUse();
+        android::GraphicsEnv::getInstance().setTargetStats(
+            android::GpuStatsInfo::Stats::CPU_VULKAN_IN_USE);
     }
 
     data->driver_device = dev;
@@ -1245,11 +1243,10 @@
         if (!device_count)
             return VK_INCOMPLETE;
 
-        android::Vector<VkPhysicalDevice> devices;
-        devices.resize(device_count);
+        std::vector<VkPhysicalDevice> devices(device_count);
         *pPhysicalDeviceGroupCount = device_count;
-        result = EnumeratePhysicalDevices(instance, &device_count,
-                                          devices.editArray());
+        result =
+            EnumeratePhysicalDevices(instance, &device_count, devices.data());
         if (result < 0)
             return result;
 
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 574c327..3495861 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -16,12 +16,11 @@
 
 // WARNING: This file is generated. See ../README.md for instructions.
 
+#include <log/log.h>
 #include <string.h>
 
 #include <algorithm>
 
-#include <log/log.h>
-
 #include "driver.h"
 
 namespace vulkan {
@@ -75,6 +74,15 @@
     }
 }
 
+VKAPI_ATTR VkResult checkedBindImageMemory2KHR(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+    if (GetData(device).hook_extensions[ProcHook::KHR_bind_memory2]) {
+        return BindImageMemory2KHR(device, bindInfoCount, pBindInfos);
+    } else {
+        Logger(device).Err(device, "VK_KHR_bind_memory2 not enabled. vkBindImageMemory2KHR not executed.");
+        return VK_SUCCESS;
+    }
+}
+
 VKAPI_ATTR VkResult checkedGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
     if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
         return GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
@@ -102,24 +110,6 @@
     }
 }
 
-VKAPI_ATTR VkResult checkedGetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
-    if (GetData(device).hook_extensions[ProcHook::GOOGLE_display_timing]) {
-        return GetRefreshCycleDurationGOOGLE(device, swapchain, pDisplayTimingProperties);
-    } else {
-        Logger(device).Err(device, "VK_GOOGLE_display_timing not enabled. vkGetRefreshCycleDurationGOOGLE not executed.");
-        return VK_SUCCESS;
-    }
-}
-
-VKAPI_ATTR VkResult checkedGetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings) {
-    if (GetData(device).hook_extensions[ProcHook::GOOGLE_display_timing]) {
-        return GetPastPresentationTimingGOOGLE(device, swapchain, pPresentationTimingCount, pPresentationTimings);
-    } else {
-        Logger(device).Err(device, "VK_GOOGLE_display_timing not enabled. vkGetPastPresentationTimingGOOGLE not executed.");
-        return VK_SUCCESS;
-    }
-}
-
 VKAPI_ATTR void checkedSetHdrMetadataEXT(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata) {
     if (GetData(device).hook_extensions[ProcHook::EXT_hdr_metadata]) {
         SetHdrMetadataEXT(device, swapchainCount, pSwapchains, pMetadata);
@@ -137,11 +127,20 @@
     }
 }
 
-VKAPI_ATTR VkResult checkedBindImageMemory2KHR(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfoKHR* pBindInfos) {
-    if (GetData(device).hook_extensions[ProcHook::KHR_bind_memory2]) {
-        return BindImageMemory2KHR(device, bindInfoCount, pBindInfos);
+VKAPI_ATTR VkResult checkedGetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
+    if (GetData(device).hook_extensions[ProcHook::GOOGLE_display_timing]) {
+        return GetRefreshCycleDurationGOOGLE(device, swapchain, pDisplayTimingProperties);
     } else {
-        Logger(device).Err(device, "VK_KHR_bind_memory2 not enabled. vkBindImageMemory2KHR not executed.");
+        Logger(device).Err(device, "VK_GOOGLE_display_timing not enabled. vkGetRefreshCycleDurationGOOGLE not executed.");
+        return VK_SUCCESS;
+    }
+}
+
+VKAPI_ATTR VkResult checkedGetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings) {
+    if (GetData(device).hook_extensions[ProcHook::GOOGLE_display_timing]) {
+        return GetPastPresentationTimingGOOGLE(device, swapchain, pPresentationTimingCount, pPresentationTimings);
+    } else {
+        Logger(device).Err(device, "VK_GOOGLE_display_timing not enabled. vkGetPastPresentationTimingGOOGLE not executed.");
         return VK_SUCCESS;
     }
 }
@@ -517,12 +516,12 @@
     INIT_PROC(true, instance, GetPhysicalDeviceProperties);
     INIT_PROC(true, instance, CreateDevice);
     INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
-    INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
-    INIT_PROC(false, instance, GetPhysicalDeviceProperties2);
     INIT_PROC_EXT(EXT_debug_report, true, instance, CreateDebugReportCallbackEXT);
     INIT_PROC_EXT(EXT_debug_report, true, instance, DestroyDebugReportCallbackEXT);
     INIT_PROC_EXT(EXT_debug_report, true, instance, DebugReportMessageEXT);
+    INIT_PROC(false, instance, GetPhysicalDeviceProperties2);
     INIT_PROC_EXT(KHR_get_physical_device_properties2, true, instance, GetPhysicalDeviceProperties2KHR);
+    INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
     // clang-format on
 
     return success;
@@ -542,12 +541,12 @@
     INIT_PROC(true, dev, DestroyImage);
     INIT_PROC(true, dev, AllocateCommandBuffers);
     INIT_PROC(false, dev, BindImageMemory2);
+    INIT_PROC_EXT(KHR_bind_memory2, true, dev, BindImageMemory2KHR);
     INIT_PROC(false, dev, GetDeviceQueue2);
     INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsageANDROID);
-    INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsage2ANDROID);
     INIT_PROC_EXT(ANDROID_native_buffer, true, dev, AcquireImageANDROID);
     INIT_PROC_EXT(ANDROID_native_buffer, true, dev, QueueSignalReleaseImageANDROID);
-    INIT_PROC_EXT(KHR_bind_memory2, true, dev, BindImageMemory2KHR);
+    INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsage2ANDROID);
     // clang-format on
 
     return success;
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 3faf6c0..79f070c 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -21,6 +21,7 @@
 
 #include <vulkan/vk_android_native_buffer.h>
 #include <vulkan/vulkan.h>
+
 #include <bitset>
 
 namespace vulkan {
@@ -69,12 +70,12 @@
     PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
     PFN_vkCreateDevice CreateDevice;
     PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
-    PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
-    PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
     PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
     PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
     PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
+    PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
     PFN_vkGetPhysicalDeviceProperties2KHR GetPhysicalDeviceProperties2KHR;
+    PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
     // clang-format on
 };
 
@@ -87,12 +88,12 @@
     PFN_vkDestroyImage DestroyImage;
     PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
     PFN_vkBindImageMemory2 BindImageMemory2;
+    PFN_vkBindImageMemory2KHR BindImageMemory2KHR;
     PFN_vkGetDeviceQueue2 GetDeviceQueue2;
     PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
-    PFN_vkGetSwapchainGrallocUsage2ANDROID GetSwapchainGrallocUsage2ANDROID;
     PFN_vkAcquireImageANDROID AcquireImageANDROID;
     PFN_vkQueueSignalReleaseImageANDROID QueueSignalReleaseImageANDROID;
-    PFN_vkBindImageMemory2KHR BindImageMemory2KHR;
+    PFN_vkGetSwapchainGrallocUsage2ANDROID GetSwapchainGrallocUsage2ANDROID;
     // clang-format on
 };
 
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index a8949d3..d60eaa7 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -18,13 +18,13 @@
 
 #include <android/hardware/graphics/common/1.0/types.h>
 #include <grallocusage/GrallocUsageConversion.h>
+#include <graphicsenv/GraphicsEnv.h>
 #include <log/log.h>
 #include <sync/sync.h>
 #include <system/window.h>
 #include <ui/BufferQueueDefs.h>
 #include <utils/StrongPointer.h>
 #include <utils/Trace.h>
-#include <utils/Vector.h>
 
 #include <algorithm>
 #include <unordered_set>
@@ -34,10 +34,6 @@
 
 using android::hardware::graphics::common::V1_0::BufferUsage;
 
-// TODO(jessehall): Currently we don't have a good error code for when a native
-// window operation fails. Just returning INITIALIZATION_FAILED for now. Later
-// versions (post SDK 0.9) of the API/extension have a better error code.
-// When updating to that version, audit all error returns.
 namespace vulkan {
 namespace driver {
 
@@ -48,29 +44,12 @@
     VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
     VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR |
     VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR |
-    // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
     VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
 
-int TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform) {
-    switch (transform) {
-        // TODO: See TODO in TranslateNativeToVulkanTransform
-        case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
-            return NATIVE_WINDOW_TRANSFORM_ROT_90;
-        case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
-            return NATIVE_WINDOW_TRANSFORM_ROT_180;
-        case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
-            return NATIVE_WINDOW_TRANSFORM_ROT_270;
-        case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
-        case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
-        default:
-            return 0;
-    }
-}
-
 VkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) {
     // Native and Vulkan transforms are isomorphic, but are represented
     // differently. Vulkan transforms are built up of an optional horizontal
@@ -78,27 +57,22 @@
     // transforms are built up from a horizontal flip, vertical flip, and
     // 90-degree rotation, all optional but always in that order.
 
-    // TODO(jessehall): For now, only support pure rotations, not
-    // flip or flip-and-rotate, until I have more time to test them and build
-    // sample code. As far as I know we never actually use anything besides
-    // pure rotations anyway.
-
     switch (native) {
-        case 0:  // 0x0
+        case 0:
             return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_H:  // 0x1
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_V:  // 0x2
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
-        case NATIVE_WINDOW_TRANSFORM_ROT_180:  // FLIP_H | FLIP_V
+        case NATIVE_WINDOW_TRANSFORM_FLIP_H:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_FLIP_V:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_ROT_180:
             return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR;
-        case NATIVE_WINDOW_TRANSFORM_ROT_90:  // 0x4
+        case NATIVE_WINDOW_TRANSFORM_ROT_90:
             return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90:
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90:
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR;
-        case NATIVE_WINDOW_TRANSFORM_ROT_270:  // FLIP_H | FLIP_V | ROT_90
+        case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_ROT_270:
             return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR;
         case NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY:
         default:
@@ -106,6 +80,31 @@
     }
 }
 
+int TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform) {
+    switch (transform) {
+        case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_180;
+        case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_270;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
+        case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
+        default:
+            return 0;
+    }
+}
+
 int InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) {
     switch (transform) {
         case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
@@ -114,17 +113,16 @@
             return NATIVE_WINDOW_TRANSFORM_ROT_180;
         case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
             return NATIVE_WINDOW_TRANSFORM_ROT_90;
-        // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H;
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H |
-        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V;
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V |
-        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
         case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
         case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
         default:
@@ -134,7 +132,6 @@
 
 class TimingInfo {
    public:
-    TimingInfo() = default;
     TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId)
         : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
           native_frame_id_(nativeFrameId) {}
@@ -201,8 +198,6 @@
             { NATIVE_WINDOW_TIMESTAMP_PENDING };
 };
 
-// ----------------------------------------------------------------------------
-
 struct Surface {
     android::sp<ANativeWindow> window;
     VkSwapchainKHR swapchain_handle;
@@ -270,7 +265,7 @@
         bool dequeued;
     } images[android::BufferQueueDefs::NUM_BUFFER_SLOTS];
 
-    android::Vector<TimingInfo> timing;
+    std::vector<TimingInfo> timing;
 };
 
 VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) {
@@ -285,6 +280,8 @@
                            ANativeWindow* window,
                            int release_fence,
                            Swapchain::Image& image) {
+    ATRACE_CALL();
+
     ALOG_ASSERT(release_fence == -1 || image.dequeued,
                 "ReleaseSwapchainImage: can't provide a release fence for "
                 "non-dequeued images");
@@ -323,7 +320,9 @@
     }
 
     if (image.image) {
+        ATRACE_BEGIN("DestroyImage");
         GetData(device).driver.DestroyImage(device, image.image, nullptr);
+        ATRACE_END();
         image.image = VK_NULL_HANDLE;
     }
 
@@ -349,7 +348,7 @@
     uint32_t num_ready = 0;
     const size_t num_timings = swapchain.timing.size() - MIN_NUM_FRAMES_AGO + 1;
     for (uint32_t i = 0; i < num_timings; i++) {
-        TimingInfo& ti = swapchain.timing.editItemAt(i);
+        TimingInfo& ti = swapchain.timing[i];
         if (ti.ready()) {
             // This TimingInfo is ready to be reported to the user.  Add it
             // to the num_ready.
@@ -371,9 +370,6 @@
             nullptr,  //&first_composition_start_time,
             nullptr,  //&last_composition_start_time,
             nullptr,  //&composition_finish_time,
-            // TODO(ianelliott): Maybe ask if this one is
-            // supported, at startup time (since it may not be
-            // supported):
             &actual_present_time,
             nullptr,  //&dequeue_ready_time,
             nullptr /*&reads_done_time*/);
@@ -400,7 +396,6 @@
     return num_ready;
 }
 
-// TODO(ianelliott): DEAL WITH RETURN VALUE (e.g. VK_INCOMPLETE)!!!
 void copy_ready_timings(Swapchain& swapchain,
                         uint32_t* count,
                         VkPastPresentationTimingGOOGLE* timings) {
@@ -419,7 +414,7 @@
     }
 
     uint32_t num_copied = 0;
-    size_t num_to_remove = 0;
+    int32_t num_to_remove = 0;
     for (uint32_t i = 0; i <= last_ready && num_copied < *count; i++) {
         const TimingInfo& ti = swapchain.timing[i];
         if (ti.ready()) {
@@ -431,7 +426,8 @@
 
     // Discard old frames that aren't ready if newer frames are ready.
     // We don't expect to get the timing info for those old frames.
-    swapchain.timing.removeItemsAt(0, num_to_remove);
+    swapchain.timing.erase(swapchain.timing.begin(),
+                           swapchain.timing.begin() + num_to_remove);
 
     *count = num_copied;
 }
@@ -539,15 +535,12 @@
               strerror(-err), err);
         surface->~Surface();
         allocator->pfnFree(allocator->pUserData, surface);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
-    // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN.
     err =
         native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err),
               err);
         surface->~Surface();
@@ -656,7 +649,6 @@
         return VK_ERROR_SURFACE_LOST_KHR;
     }
 
-    // TODO(jessehall): Figure out what the min/max values should be.
     int max_buffer_count;
     err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &max_buffer_count);
     if (err != 0) {
@@ -670,8 +662,7 @@
     capabilities->currentExtent =
         VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
 
-    // TODO(jessehall): Figure out what the max extent should be. Maximum
-    // texture dimension maybe?
+    // TODO(http://b/134182502): Figure out what the max extent should be.
     capabilities->minImageExtent = VkExtent2D{1, 1};
     capabilities->maxImageExtent = VkExtent2D{4096, 4096};
 
@@ -685,11 +676,6 @@
     // associated with the bufferqueue. It can't be changed from here.
     capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
 
-    // TODO(jessehall): I think these are right, but haven't thought hard about
-    // it. Do we need to query the driver for support of any of these?
-    // Currently not included:
-    // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not
-    // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not
     capabilities->supportedUsageFlags =
         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
@@ -729,8 +715,7 @@
     int err = native_window_get_wide_color_support(surface.window.get(),
                                                    &wide_color_support);
     if (err) {
-        // Not allowed to return a more sensible error code, so do this
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
     ALOGV("wide_color_support is: %d", wide_color_support);
     wide_color_support =
@@ -828,11 +813,10 @@
     } else {
         // temp vector for forwarding; we'll marshal it into the pSurfaceFormats
         // after the call.
-        android::Vector<VkSurfaceFormatKHR> surface_formats;
-        surface_formats.resize(*pSurfaceFormatCount);
+        std::vector<VkSurfaceFormatKHR> surface_formats(*pSurfaceFormatCount);
         VkResult result = GetPhysicalDeviceSurfaceFormatsKHR(
             physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount,
-            &surface_formats.editItemAt(0));
+            surface_formats.data());
 
         if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
             // marshal results individually due to stride difference.
@@ -874,7 +858,7 @@
     }
     uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
 
-    android::Vector<VkPresentModeKHR> present_modes;
+    std::vector<VkPresentModeKHR> present_modes;
     if (min_undequeued_buffers + 1 < max_buffer_count)
         present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
     present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
@@ -894,7 +878,7 @@
         if (*count < num_modes)
             result = VK_INCOMPLETE;
         *count = std::min(*count, num_modes);
-        std::copy(present_modes.begin(), present_modes.begin() + int(*count), modes);
+        std::copy_n(present_modes.data(), *count, modes);
     } else {
         *count = num_modes;
     }
@@ -978,6 +962,40 @@
     return VK_SUCCESS;
 }
 
+static void DestroySwapchainInternal(VkDevice device,
+                                     VkSwapchainKHR swapchain_handle,
+                                     const VkAllocationCallbacks* allocator) {
+    ATRACE_CALL();
+
+    const auto& dispatch = GetData(device).driver;
+    Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
+    if (!swapchain) {
+        return;
+    }
+
+    bool active = swapchain->surface.swapchain_handle == swapchain_handle;
+    ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
+
+    if (window && swapchain->frame_timestamps_enabled) {
+        native_window_enable_frame_timestamps(window, false);
+    }
+
+    for (uint32_t i = 0; i < swapchain->num_images; i++) {
+        ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
+    }
+
+    if (active) {
+        swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
+    }
+
+    if (!allocator) {
+        allocator = &GetData(device).allocator;
+    }
+
+    swapchain->~Swapchain();
+    allocator->pfnFree(allocator->pUserData, swapchain);
+}
+
 VKAPI_ATTR
 VkResult CreateSwapchainKHR(VkDevice device,
                             const VkSwapchainCreateInfoKHR* create_info,
@@ -1052,6 +1070,8 @@
     // non-FREE state at any given time. Disconnecting and re-connecting
     // orphans the previous buffers, getting us back to the state where we can
     // dequeue all buffers.
+    //
+    // TODO(http://b/134186185) recycle swapchain images more efficiently
     err = native_window_api_disconnect(surface.window.get(),
                                        NATIVE_WINDOW_API_EGL);
     ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)",
@@ -1072,8 +1092,6 @@
         create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
     err = surface.window->setSwapInterval(surface.window.get(), swap_interval);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1100,8 +1118,6 @@
     err = native_window_set_buffers_format(surface.window.get(),
                                            native_pixel_format);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)",
               native_pixel_format, strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1109,8 +1125,6 @@
     err = native_window_set_buffers_data_space(surface.window.get(),
                                                native_dataspace);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)",
               native_dataspace, strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1120,8 +1134,6 @@
         surface.window.get(), static_cast<int>(create_info->imageExtent.width),
         static_cast<int>(create_info->imageExtent.height));
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
               create_info->imageExtent.width, create_info->imageExtent.height,
               strerror(-err), err);
@@ -1140,8 +1152,6 @@
         surface.window.get(),
         InvertTransformToNative(create_info->preTransform));
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
               InvertTransformToNative(create_info->preTransform),
               strerror(-err), err);
@@ -1151,8 +1161,6 @@
     err = native_window_set_scaling_mode(
         surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)",
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1182,8 +1190,6 @@
                                 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
                                 &query_value);
     if (err != 0 || query_value < 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
               query_value);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1201,8 +1207,6 @@
     // can't actually use!).
     err = native_window_set_buffer_count(surface.window.get(), std::max(2u, num_images));
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1211,7 +1215,7 @@
     int32_t legacy_usage = 0;
     if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
         uint64_t consumer_usage, producer_usage;
-        ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsage2ANDROID");
+        ATRACE_BEGIN("GetSwapchainGrallocUsage2ANDROID");
         result = dispatch.GetSwapchainGrallocUsage2ANDROID(
             device, create_info->imageFormat, create_info->imageUsage,
             swapchain_image_usage, &consumer_usage, &producer_usage);
@@ -1223,7 +1227,7 @@
         legacy_usage =
             android_convertGralloc1To0Usage(producer_usage, consumer_usage);
     } else if (dispatch.GetSwapchainGrallocUsageANDROID) {
-        ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsageANDROID");
+        ATRACE_BEGIN("GetSwapchainGrallocUsageANDROID");
         result = dispatch.GetSwapchainGrallocUsageANDROID(
             device, create_info->imageFormat, create_info->imageUsage,
             &legacy_usage);
@@ -1242,12 +1246,19 @@
     }
     err = native_window_set_usage(surface.window.get(), native_usage);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
 
+    int transform_hint;
+    err = surface.window->query(surface.window.get(),
+                                NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint);
+    if (err != 0) {
+        ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_SURFACE_LOST_KHR;
+    }
+
     // -- Allocate our Swapchain object --
     // After this point, we must deallocate the swapchain on error.
 
@@ -1301,8 +1312,6 @@
         err = surface.window->dequeueBuffer(surface.window.get(), &buffer,
                                             &img.dequeue_fence);
         if (err != 0) {
-            // TODO(jessehall): Improve error reporting. Can we enumerate
-            // possible errors and translate them to valid Vulkan result codes?
             ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
             result = VK_ERROR_SURFACE_LOST_KHR;
             break;
@@ -1322,7 +1331,7 @@
             &image_native_buffer.usage2.producer,
             &image_native_buffer.usage2.consumer);
 
-        ATRACE_BEGIN("dispatch.CreateImage");
+        ATRACE_BEGIN("CreateImage");
         result =
             dispatch.CreateImage(device, &image_create, nullptr, &img.image);
         ATRACE_END();
@@ -1335,9 +1344,6 @@
     // -- Cancel all buffers, returning them to the queue --
     // If an error occurred before, also destroy the VkImage and release the
     // buffer reference. Otherwise, we retain a strong reference to the buffer.
-    //
-    // TODO(jessehall): The error path here is the same as DestroySwapchain,
-    // but not the non-error path. Should refactor/unify.
     for (uint32_t i = 0; i < num_images; i++) {
         Swapchain::Image& img = swapchain->images[i];
         if (img.dequeued) {
@@ -1348,21 +1354,20 @@
                 img.dequeued = false;
             }
         }
-        if (result != VK_SUCCESS) {
-            if (img.image) {
-                ATRACE_BEGIN("dispatch.DestroyImage");
-                dispatch.DestroyImage(device, img.image, nullptr);
-                ATRACE_END();
-            }
-        }
     }
 
     if (result != VK_SUCCESS) {
-        swapchain->~Swapchain();
-        allocator->pfnFree(allocator->pUserData, swapchain);
+        DestroySwapchainInternal(device, HandleFromSwapchain(swapchain),
+                                 allocator);
         return result;
     }
 
+    if (transform_hint != swapchain->pre_transform) {
+        // Log that the app is not doing pre-rotation.
+        android::GraphicsEnv::getInstance().setTargetStats(
+            android::GpuStatsInfo::Stats::FALSE_PREROTATION);
+    }
+
     surface.swapchain_handle = HandleFromSwapchain(swapchain);
     *swapchain_handle = surface.swapchain_handle;
     return VK_SUCCESS;
@@ -1374,24 +1379,7 @@
                          const VkAllocationCallbacks* allocator) {
     ATRACE_CALL();
 
-    const auto& dispatch = GetData(device).driver;
-    Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
-    if (!swapchain)
-        return;
-    bool active = swapchain->surface.swapchain_handle == swapchain_handle;
-    ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
-
-    if (swapchain->frame_timestamps_enabled) {
-        native_window_enable_frame_timestamps(window, false);
-    }
-    for (uint32_t i = 0; i < swapchain->num_images; i++)
-        ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
-    if (active)
-        swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
-    if (!allocator)
-        allocator = &GetData(device).allocator;
-    swapchain->~Swapchain();
-    allocator->pfnFree(allocator->pUserData, swapchain);
+    DestroySwapchainInternal(device, swapchain_handle, allocator);
 }
 
 VKAPI_ATTR
@@ -1457,8 +1445,6 @@
     int fence_fd;
     err = window->dequeueBuffer(window, &buffer, &fence_fd);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
@@ -1513,8 +1499,6 @@
                               uint32_t* pImageIndex) {
     ATRACE_CALL();
 
-    // TODO: this should actually be the other way around and this function
-    // should handle any additional structures that get passed in
     return AcquireNextImageKHR(device, pAcquireInfo->swapchain,
                                pAcquireInfo->timeout, pAcquireInfo->semaphore,
                                pAcquireInfo->fence, pImageIndex);
@@ -1673,9 +1657,9 @@
 
                     // Add a new timing record with the user's presentID and
                     // the nativeFrameId.
-                    swapchain.timing.push_back(TimingInfo(time, nativeFrameId));
+                    swapchain.timing.emplace_back(time, nativeFrameId);
                     while (swapchain.timing.size() > MAX_TIMING_INFOS) {
-                        swapchain.timing.removeAt(0);
+                        swapchain.timing.erase(swapchain.timing.begin());
                     }
                     if (time->desiredPresentTime) {
                         // Set the desiredPresentTime:
@@ -1692,17 +1676,16 @@
                 err = window->queueBuffer(window, img.buffer.get(), fence);
                 // queueBuffer always closes fence, even on error
                 if (err != 0) {
-                    // TODO(jessehall): What now? We should probably cancel the
-                    // buffer, I guess?
                     ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
                     swapchain_result = WorstPresentResult(
                         swapchain_result, VK_ERROR_OUT_OF_DATE_KHR);
+                } else {
+                    if (img.dequeue_fence >= 0) {
+                        close(img.dequeue_fence);
+                        img.dequeue_fence = -1;
+                    }
+                    img.dequeued = false;
                 }
-                if (img.dequeue_fence >= 0) {
-                    close(img.dequeue_fence);
-                    img.dequeue_fence = -1;
-                }
-                img.dequeued = false;
 
                 // If the swapchain is in shared mode, immediately dequeue the
                 // buffer so it can be presented again without an intervening
@@ -1729,7 +1712,6 @@
                 }
             }
             if (swapchain_result != VK_SUCCESS) {
-                ReleaseSwapchainImage(device, window, fence, img);
                 OrphanSwapchain(device, &swapchain);
             }
             int window_transform_hint;
@@ -1787,6 +1769,10 @@
     ATRACE_CALL();
 
     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
+    if (swapchain.surface.swapchain_handle != swapchain_handle) {
+        return VK_ERROR_OUT_OF_DATE_KHR;
+    }
+
     ANativeWindow* window = swapchain.surface.window.get();
     VkResult result = VK_SUCCESS;
 
@@ -1797,8 +1783,15 @@
     }
 
     if (timings) {
-        // TODO(ianelliott): plumb return value (e.g. VK_INCOMPLETE)
+        // Get the latest ready timing count before copying, since the copied
+        // timing info will be erased in copy_ready_timings function.
+        uint32_t n = get_num_ready_timings(swapchain);
         copy_ready_timings(swapchain, count, timings);
+        // Check the *count here against the recorded ready timing count, since
+        // *count can be overwritten per spec describes.
+        if (*count < n) {
+            result = VK_INCOMPLETE;
+        }
     } else {
         *count = get_num_ready_timings(swapchain);
     }
diff --git a/vulkan/nulldrv/null_driver.tmpl b/vulkan/nulldrv/null_driver.tmpl
deleted file mode 100644
index ce15517..0000000
--- a/vulkan/nulldrv/null_driver.tmpl
+++ /dev/null
@@ -1,210 +0,0 @@
-{{/*
- * Copyright 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */}}
-
-{{Include "../api/templates/vulkan_common.tmpl"}}
-{{Global "clang-format" (Strings "clang-format" "-style=file")}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "null_driver_gen.h"   | Format (Global "clang-format") | Write "null_driver_gen.h"  }}
-{{$ | Macro "null_driver_gen.cpp" | Format (Global "clang-format") | Write "null_driver_gen.cpp"}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  null_driver_gen.h
--------------------------------------------------------------------------------
-*/}}
-{{define "null_driver_gen.h"}}
-/*
-•* Copyright 2015 The Android Open Source Project
-•*
-•* Licensed under the Apache License, Version 2.0 (the "License");
-•* you may not use this file except in compliance with the License.
-•* You may obtain a copy of the License at
-•*
-•*      http://www.apache.org/licenses/LICENSE-2.0
-•*
-•* Unless required by applicable law or agreed to in writing, software
-•* distributed under the License is distributed on an "AS IS" BASIS,
-•* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-•* See the License for the specific language governing permissions and
-•* limitations under the License.
-•*/

-// WARNING: This file is generated. See ../README.md for instructions.

-#ifndef NULLDRV_NULL_DRIVER_H
-#define NULLDRV_NULL_DRIVER_H 1

-#include <vulkan/vk_android_native_buffer.h>
-#include <vulkan/vulkan.h>

-namespace null_driver {«

-PFN_vkVoidFunction GetGlobalProcAddr(const char* name);
-PFN_vkVoidFunction GetInstanceProcAddr(const char* name);

-// clang-format off
-  {{range $f := AllCommands $}}
-    {{if (Macro "IsDriverFunction" $f)}}
-VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}});
-    {{end}}
-  {{end}}
-VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
-VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
-VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
-// clang-format on

-»}  // namespace null_driver

-#endif  // NULLDRV_NULL_DRIVER_H
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  null_driver_gen.cpp
--------------------------------------------------------------------------------
-*/}}
-{{define "null_driver_gen.cpp"}}
-/*
-•* Copyright 2015 The Android Open Source Project
-•*
-•* Licensed under the Apache License, Version 2.0 (the "License");
-•* you may not use this file except in compliance with the License.
-•* You may obtain a copy of the License at
-•*
-•*      http://www.apache.org/licenses/LICENSE-2.0
-•*
-•* Unless required by applicable law or agreed to in writing, software
-•* distributed under the License is distributed on an "AS IS" BASIS,
-•* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-•* See the License for the specific language governing permissions and
-•* limitations under the License.
-•*/

-// WARNING: This file is generated. See ../README.md for instructions.

-#include "null_driver_gen.h"
-#include <algorithm>

-using namespace null_driver;

-namespace {

-struct NameProc {
-    const char* name;
-    PFN_vkVoidFunction proc;
-};

-PFN_vkVoidFunction Lookup(const char* name,
-                          const NameProc* begin,
-                          const NameProc* end) {
-    const auto& entry = std::lower_bound(
-        begin, end, name,
-        [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
-    if (entry == end || strcmp(entry->name, name) != 0)
-        return nullptr;
-    return entry->proc;
-}

-template <size_t N>
-PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
-    return Lookup(name, procs, procs + N);
-}

-const NameProc kGlobalProcs[] = {«
-  // clang-format off
-  {{range $f := SortBy (AllCommands $) "FunctionName"}}
-    {{if and (Macro "IsDriverFunction" $f) (eq (Macro "Vtbl" $f) "Global")}}
-      {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
-        static_cast<{{Macro "FunctionPtrName" $f}}>(§
-          {{Macro "BaseName" $f}}))},
-    {{end}}
-  {{end}}
-  // clang-format on
-»};

-const NameProc kInstanceProcs[] = {«
-  // clang-format off
-  {{range $f := SortBy (AllCommands $) "FunctionName"}}
-    {{if (Macro "IsDriverFunction" $f)}}
-      {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
-        static_cast<{{Macro "FunctionPtrName" $f}}>(§
-          {{Macro "BaseName" $f}}))},
-    {{end}}
-  {{end}}
-  // clang-format on
-»};

-} // namespace

-namespace null_driver {

-PFN_vkVoidFunction GetGlobalProcAddr(const char* name) {
-    return Lookup(name, kGlobalProcs);
-}

-PFN_vkVoidFunction GetInstanceProcAddr(const char* name) {«
-    return Lookup(name, kInstanceProcs);
-»}

-} // namespace null_driver

-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a function name without the "vk" prefix.
--------------------------------------------------------------------------------
-*/}}
-{{define "BaseName"}}
-  {{AssertType $ "Function"}}
-  {{TrimPrefix "vk" $.Name}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Emits 'true' if the API function is implemented by the driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsDriverFunction"}}
-  {{AssertType $ "Function"}}
-
-  {{if not (GetAnnotation $ "pfn")}}
-    {{$ext := GetAnnotation $ "extension"}}
-    {{if $ext}}
-      {{Macro "IsDriverExtension" $ext}}
-    {{else}}
-      true
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
-  Reports whether an extension is implemented by the driver.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsDriverExtension"}}
-  {{$ext := index $.Arguments 0}}
-  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
-  {{else if eq $ext "VK_EXT_debug_report"}}true
-  {{else if eq $ext "VK_KHR_get_physical_device_properties2"}}true
-  {{end}}
-{{end}}
diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp
index 92b7468..7c9b0c0 100644
--- a/vulkan/nulldrv/null_driver_gen.cpp
+++ b/vulkan/nulldrv/null_driver_gen.cpp
@@ -16,9 +16,10 @@
 
 // WARNING: This file is generated. See ../README.md for instructions.
 
-#include <algorithm>
 #include "null_driver_gen.h"
 
+#include <algorithm>
+
 using namespace null_driver;
 
 namespace {
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
index c6ad537..70ef340 100644
--- a/vulkan/nulldrv/null_driver_gen.h
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -41,6 +41,7 @@
 VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties);
 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 EnumerateInstanceVersion(uint32_t* pApiVersion);
 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);
@@ -165,48 +166,47 @@
 VKAPI_ATTR void CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents);
 VKAPI_ATTR void CmdEndRenderPass(VkCommandBuffer commandBuffer);
 VKAPI_ATTR void CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
-VKAPI_ATTR VkResult EnumerateInstanceVersion(uint32_t* pApiVersion);
-VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
-VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
-VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
-VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask);
-VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
-VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
-VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
-VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
-VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
-VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
-VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
-VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
-VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
-VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
-VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
-VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
-VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
-VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
-VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
-VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
-VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
-VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
-VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
-VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
-VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
-VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
-VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
-VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int32_t* grallocUsage);
-VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage);
-VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
-VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
 VKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
 VKAPI_ATTR void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
 VKAPI_ATTR void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
-VKAPI_ATTR void GetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR* pFeatures);
-VKAPI_ATTR void GetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2KHR* pProperties);
-VKAPI_ATTR void GetPhysicalDeviceFormatProperties2KHR(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2KHR* pFormatProperties);
-VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo, VkImageFormatProperties2KHR* pImageFormatProperties);
-VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR* pQueueFamilyProperties);
-VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties);
-VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2KHR* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+VKAPI_ATTR void GetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2KHR(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
+VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
+VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
+VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
+VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
+VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
+VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage);
 VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
 VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
 VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
diff --git a/vulkan/scripts/api_generator.py b/vulkan/scripts/api_generator.py
new file mode 100644
index 0000000..a0c648c
--- /dev/null
+++ b/vulkan/scripts/api_generator.py
@@ -0,0 +1,346 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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 provides the functions required for generating the
+# vulkan api framework directly from the vulkan registry (vk.xml)
+
+import os
+import generator_common as gencom
+
+def isInstanceDispatchTableEntry(functionName):
+  if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
+    return False
+  if gencom.gencom.isFunctionExported(functionName) and gencom.isInstanceDispatched(functionName):
+    return True
+  return False
+
+def isDeviceDispatchTableEntry(functionName):
+  if gencom.gencom.isFunctionExported(functionName) and gencom.gencom.isDeviceDispatched(functionName):
+    return True
+  return False
+
+def api_genh():
+
+  header = """#ifndef LIBVULKAN_API_GEN_H
+#define LIBVULKAN_API_GEN_H
+
+#include <vulkan/vulkan.h>
+
+#include <bitset>
+
+#include "driver_gen.h"
+
+namespace vulkan {
+namespace api {
+
+"""
+
+  tail = """
+bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions);
+bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions);
+
+}  // namespace api
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_API_GEN_H
+"""
+  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.h')
+  with open(genfile, 'w') as f:
+    instanceDispatchTableEntries = []
+    deviceDispatchTableEntries = []
+    for commands in gencom.allCommandsList:
+      if commands not in gencom.aliasDict:
+        if gencom.isInstanceDispatchTableEntry(commands):
+          instanceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
+        elif gencom.isDeviceDispatchTableEntry(commands):
+          deviceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
+
+    f.write (gencom.copyright)
+    f.write (gencom.warning)
+    f.write (header)
+    f.write ('struct InstanceDispatchTable {\n')
+    gencom.clang_off(f,1)
+    for functions in instanceDispatchTableEntries:
+      f.write(gencom.clang_off_spaces + functions + '\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n\n')
+
+    f.write ('struct DeviceDispatchTable {\n')
+    gencom.clang_off(f,1)
+    for functions in deviceDispatchTableEntries:
+      f.write(gencom.clang_off_spaces + functions + '\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n')
+
+    f.write (tail)
+    f.close()
+  gencom.runClangFormat(genfile)
+
+def defineInitProc(name, f):
+  f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
+  f.write ('\n')
+  f.write ("""#define INIT_PROC(required, obj, proc)                                 \\
+    do {                                                               \\
+        data.""" + name + """.proc =                                           \\
+            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
+        if (UNLIKELY(required && !data.""" + name + """.proc)) {               \\
+            ALOGE("missing " #obj " proc: vk" #proc);                  \\
+            success = false;                                           \\
+        }                                                              \\
+    } while (0)\n\n""")
+
+def defineInitProcExt(f):
+  f.write ('// Exported extension functions may be invoked even when their extensions\n')
+  f.write ('// are disabled.  Dispatch to stubs when that happens.\n')
+  f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc)  \\
+    do {                                         \\
+        if (extensions[driver::ProcHook::ext])   \\
+            INIT_PROC(required, obj, proc);      \\
+        else                                     \\
+            data.dispatch.proc = disabled##proc; \\
+    } while (0)\n\n""")
+
+def defineExtensionStub(functionName, f):
+  if functionName in gencom.extensionsDict and gencom.isFunctionExported(functionName):
+    extname = gencom.extensionsDict[functionName]
+    base_name = functionName[2:]
+    pList = gencom.paramDict[functionName]
+    firstParam = pList[0][0] + pList[0][1]
+    tailParams = [x[0][:-1] for x in pList[1:]]
+    tailP = ', '.join(tailParams)
+    f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' disabled' + base_name + '(' + firstParam + ', ' + tailP + ') {\n')
+    f.write (gencom.clang_off_spaces)
+    f.write ('driver::Logger(' + pList[0][1] + ').Err(' + pList[0][1] + ', \"' + extname + ' not enabled. Exported ' + functionName + ' not executed.\");\n')
+    if gencom.returnTypeDict[functionName] != 'void':
+      f.write(gencom.clang_off_spaces + 'return VK_SUCCESS;\n')
+    f.write ('}\n\n')
+
+def isIntercepted(functionName):
+  if gencom.isFunctionSupported(functionName):
+    if gencom.isGloballyDispatched(functionName):
+      return True
+    elif functionName == 'vkCreateDevice':
+      return True
+    elif functionName == 'vkEnumerateDeviceLayerProperties':
+      return True
+    elif functionName == 'vkEnumerateDeviceExtensionProperties':
+      return True
+    elif functionName == 'vkDestroyInstance':
+      return True
+    elif functionName == 'vkDestroyDevice':
+      return True
+  return False
+
+def interceptInstanceProcAddr(functionName, f):
+  indent = 1
+  f.write (gencom.clang_off_spaces*indent + '// global functions\n' + gencom.clang_off_spaces*indent+ 'if (instance == VK_NULL_HANDLE) {\n')
+  indent = indent + 1
+  for cmds in gencom.allCommandsList:
+    if gencom.isGloballyDispatched(cmds):
+      f.write(gencom.clang_off_spaces*indent + 'if (strcmp(pName, \"' + cmds + '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
+
+  f.write ('\n')
+  f.write ("""        ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName);
+        return nullptr;
+    }
+
+    static const struct Hook {
+        const char* name;
+        PFN_vkVoidFunction proc;
+    } hooks[] = {\n""")
+  sortedCommandsList = sorted(gencom.allCommandsList)
+  for cmds in sortedCommandsList:
+    if gencom.isFunctionExported(cmds):
+      if gencom.isGloballyDispatched(cmds):
+        f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", nullptr },\n')
+      elif isIntercepted(cmds) or cmds == 'vkGetInstanceProcAddr' or gencom.isDeviceDispatched(cmds):
+        f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ') },\n')
+  f.write (gencom.clang_off_spaces + """};
+    // 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) {
+            vulkan::driver::Logger(instance).Err(
+                instance, "invalid vkGetInstanceProcAddr(%p, \\\"%s\\\") call",
+                instance, pName);
+        }
+        return hook->proc;
+    }
+    // clang-format off\n\n""")
+
+def interceptDeviceProcAddr(functionName, f):
+  f.write (gencom.clang_off_spaces + """if (device == VK_NULL_HANDLE) {
+        ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
+        return nullptr;
+    }\n\n""")
+  f.write (gencom.clang_off_spaces + 'static const char* const known_non_device_names[] = {\n')
+  sortedCommandsList = sorted(gencom.allCommandsList)
+  for cmds in sortedCommandsList:
+    if gencom.isFunctionSupported(cmds):
+      if not gencom.isDeviceDispatched(cmds):
+        f.write(gencom.clang_off_spaces*2 + '\"' + cmds + '\",\n')
+  f.write(gencom.clang_off_spaces + '};\n')
+  f.write(gencom.clang_off_spaces + """// 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); })) {
+        vulkan::driver::Logger(device).Err(
+            device, "invalid vkGetDeviceProcAddr(%p, \\\"%s\\\") call", device,
+            (pName) ? pName : "(null)");
+        return nullptr;
+    }
+    // clang-format off\n\n""")
+  for cmds in gencom.allCommandsList:
+    if gencom.isDeviceDispatched(cmds):
+      if isIntercepted(cmds) or cmds == 'vkGetDeviceProcAddr':
+        f.write (gencom.clang_off_spaces + 'if (strcmp(pName, "' + cmds + '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
+  f.write ('\n')
+
+def apiDispatch(functionName, f):
+  assert not isIntercepted(functionName)
+
+  f.write (gencom.clang_off_spaces)
+  if gencom.returnTypeDict[functionName] != 'void':
+    f.write ('return ')
+
+  paramList = gencom.paramDict[functionName]
+  p0 = paramList[0][1]
+  f.write('GetData(' + p0 + ').dispatch.' + functionName[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
+
+
+def api_gencpp():
+  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.cpp')
+  header = """#include <log/log.h>
+#include <string.h>
+
+#include <algorithm>
+
+// to catch mismatches between vulkan.h and this file
+#undef VK_NO_PROTOTYPES
+#include "api.h"
+
+namespace vulkan {
+namespace api {
+
+"""
+  with open(genfile, 'w') as f:
+    f.write (gencom.copyright)
+    f.write (gencom.warning)
+    f.write ("""#include <log/log.h>
+#include <string.h>
+
+#include <algorithm>
+
+// to catch mismatches between vulkan.h and this file
+#undef VK_NO_PROTOTYPES
+#include "api.h"
+
+namespace vulkan {
+namespace api {\n\n""")
+    defineInitProc('dispatch',f)
+    defineInitProcExt(f)
+    f.write ('namespace {\n\n')
+    gencom.clang_off(f,0)
+    f.write ('\n')
+    for cmds in gencom.allCommandsList:
+      defineExtensionStub(cmds,f)
+    gencom.clang_on(f,0)
+    f.write ('\n}  // namespace\n\n')
+    f.write ("""bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(instance);
+    bool success = true;\n\n""")
+    gencom.clang_off(f,1)
+    for cmds in gencom.allCommandsList:
+      if gencom.isInstanceDispatchTableEntry(cmds):
+        gencom.initProc(cmds, f)
+    gencom.clang_on(f,1)
+    f.write ('\n')
+    f.write ('    return success;\n}\n\n')
+    f.write ("""bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(dev);
+    bool success = true;\n\n""")
+
+    gencom.clang_off(f,1)
+    for cmds in gencom.allCommandsList:
+      if gencom.isDeviceDispatchTableEntry(cmds):
+        gencom.initProc(cmds, f)
+    gencom.clang_on(f,1)
+    f.write ('\n')
+    f.write ('    return success;\n}\n\n')
+
+    gencom.clang_off(f,0)
+
+    f.write ('\nnamespace {\n\n')
+    f.write('// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr\n')
+    for cmds in gencom.allCommandsList:
+      if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
+        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
+        f.write ('VKAPI_ATTR '+gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ');\n')
+
+    f.write ('\n')
+
+    for cmds in gencom.allCommandsList:
+      if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
+        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
+        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ') {\n')
+        if cmds == 'vkGetInstanceProcAddr':
+          interceptInstanceProcAddr(cmds, f)
+        elif cmds == 'vkGetDeviceProcAddr':
+          interceptDeviceProcAddr(cmds, f)
+        apiDispatch(cmds, f)
+        f.write('}\n\n')
+    f.write ("""\n}  // anonymous namespace
+
+// clang-format on
+
+}  // namespace api
+}  // namespace vulkan
+
+// clang-format off\n\n""")
+
+    for cmds in gencom.allCommandsList:
+      if gencom.isFunctionExported(cmds):
+        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
+        f.write ('__attribute__((visibility("default")))\n')
+        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds + '(' + ', '.join(paramList) + ') {\n')
+        f.write (gencom.clang_off_spaces)
+        if gencom.returnTypeDict[cmds] != 'void':
+          f.write ('return ')
+        paramList = gencom.paramDict[cmds]
+        f.write ('vulkan::api::' + cmds[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
+        f.write ('}\n\n')
+
+    gencom.clang_on(f, 0)
+    f.close()
+  gencom.runClangFormat(genfile)
diff --git a/vulkan/scripts/code_generator.py b/vulkan/scripts/code_generator.py
new file mode 100755
index 0000000..39fedf4
--- /dev/null
+++ b/vulkan/scripts/code_generator.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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 provides the main function for generating
+# vulkan framework directly from the vulkan registry (vk.xml).
+
+import generator_common as gencom
+import api_generator as apigen
+import driver_generator as drivergen
+import null_generator as nullgen
+
+if __name__ == '__main__':
+  gencom.parseVulkanRegistry()
+  apigen.api_genh()
+  apigen.api_gencpp()
+  drivergen.driver_genh()
+  drivergen.driver_gencpp()
+  nullgen.null_driver_genh()
+  nullgen.null_driver_gencpp()
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
new file mode 100644
index 0000000..04d9f23
--- /dev/null
+++ b/vulkan/scripts/driver_generator.py
@@ -0,0 +1,396 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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 provides the functions for generating the
+# vulkan driver framework directly from the vulkan registry (vk.xml).
+
+import generator_common as gencom
+import os
+
+interceptedExtensions = [
+  'VK_ANDROID_native_buffer',
+  'VK_EXT_debug_report',
+  'VK_EXT_hdr_metadata',
+  'VK_EXT_swapchain_colorspace',
+  'VK_GOOGLE_display_timing',
+  'VK_KHR_android_surface',
+  'VK_KHR_incremental_present',
+  'VK_KHR_shared_presentable_image',
+  'VK_KHR_surface',
+  'VK_KHR_swapchain',
+  'VK_KHR_get_surface_capabilities2'
+]
+
+knownExtensions = interceptedExtensions + [
+  'VK_KHR_get_physical_device_properties2',
+  'VK_ANDROID_external_memory_android_hardware_buffer',
+  'VK_KHR_bind_memory2'
+]
+
+def defineProcHookType(f):
+  f.write ("""struct ProcHook {
+    enum Type {
+        GLOBAL,
+        INSTANCE,
+        DEVICE,
+    };
+    enum Extension {\n""")
+  for exts in knownExtensions:
+    f.write (gencom.clang_off_spaces*2 + exts[3:] + ',\n')
+  f.write ('\n')
+  f.write (gencom.clang_off_spaces*2 + """EXTENSION_CORE,  // valid bit
+        EXTENSION_COUNT,
+        EXTENSION_UNKNOWN,
+    };
+
+    const char* name;
+    Type type;
+    Extension extension;
+
+    PFN_vkVoidFunction proc;
+    PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
+};\n\n""")
+
+def isExtensionIntercepted(extensionName):
+  if extensionName in interceptedExtensions:
+    return True
+  return False
+
+def isDriverTableEntry(functionName):
+  switchCase = {
+    # Create functions of dispatchable objects
+    'vkCreateDevice' : True,
+    'vkGetDeviceQueue' : True,
+    'vkGetDeviceQueue2' : True,
+    'vkAllocateCommandBuffers' : True,
+
+    # Destroy functions of dispatchable objects
+    'vkDestroyInstance' : True,
+    'vkDestroyDevice' : True,
+
+    # Enumeration of extensions
+    'vkEnumerateDeviceExtensionProperties' : True,
+
+    # We cache physical devices in loader.cpp
+    'vkEnumeratePhysicalDevices' : True,
+    'vkEnumeratePhysicalDeviceGroups' : True,
+
+    'vkGetInstanceProcAddr' : True,
+    'vkGetDeviceProcAddr' : True,
+
+    # VK_KHR_swapchain->VK_ANDROID_native_buffer translation
+    'vkCreateImage' : True,
+    'vkDestroyImage' : True,
+
+    'vkGetPhysicalDeviceProperties' : True,
+    'vkGetPhysicalDeviceProperties2' : True,
+    'vkGetPhysicalDeviceProperties2KHR' : True,
+
+    # VK_KHR_swapchain v69 requirement
+    'vkBindImageMemory2' : True,
+    'vkBindImageMemory2KHR' : True
+  }
+  if gencom.isFunctionSupported(functionName):
+    if functionName in switchCase:
+      return True
+    if functionName in gencom.extensionsDict:
+      if gencom.extensionsDict[functionName] == 'VK_ANDROID_native_buffer' or gencom.extensionsDict[functionName] == 'VK_EXT_debug_report':
+        return True
+  return False
+
+def isInstanceDriverTableEntry(functionName):
+  if isDriverTableEntry(functionName) and gencom.isInstanceDispatched(functionName):
+    return True
+  return False
+
+def isDeviceDriverTableEntry(functionName):
+  if isDriverTableEntry(functionName) and gencom.isDeviceDispatched(functionName):
+    return True
+  return False
+
+def driver_genh():
+  header = """#ifndef LIBVULKAN_DRIVER_GEN_H
+#define LIBVULKAN_DRIVER_GEN_H
+
+#include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vulkan.h>
+
+#include <bitset>
+
+namespace vulkan {
+namespace driver {\n\n"""
+  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.h')
+  with open(genfile, 'w') as f:
+    f.write (gencom.copyright)
+    f.write (gencom.warning)
+    f.write (header)
+    defineProcHookType(f)
+    f.write ('struct InstanceDriverTable {\n')
+    gencom.clang_off(f, 1)
+    for cmds in gencom.allCommandsList:
+      if isInstanceDriverTableEntry(cmds):
+        f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
+    gencom.clang_on(f, 1)
+    f.write ('};\n\n')
+    f.write ('struct DeviceDriverTable {\n')
+    gencom.clang_off(f,1)
+    for cmds in gencom.allCommandsList:
+      if isDeviceDriverTableEntry(cmds):
+        f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n\n')
+    f.write ("""const ProcHook* GetProcHook(const char* name);
+ProcHook::Extension GetProcHookExtension(const char* name);
+
+bool InitDriverTable(VkInstance instance,
+                     PFN_vkGetInstanceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
+bool InitDriverTable(VkDevice dev,
+                     PFN_vkGetDeviceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
+
+}  // namespace driver
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_DRIVER_TABLE_H\n""")
+    f.close()
+  gencom.runClangFormat(genfile)
+
+def isIntercepted(functionName):
+  switchCase = {
+    # Create functions of dispatchable objects
+    'vkCreateInstance' : True,
+    'vkCreateDevice' : True,
+    'vkEnumeratePhysicalDevices' : True,
+    'vkEnumeratePhysicalDeviceGroups' : True,
+    'vkGetDeviceQueue' : True,
+    'vkGetDeviceQueue2' : True,
+    'vkAllocateCommandBuffers' : True,
+
+    # Destroy functions of dispatchable objects
+    'vkDestroyInstance' : True,
+    'vkDestroyDevice' : True,
+
+    # Enumeration of extensions
+    'vkEnumerateInstanceExtensionProperties' : True,
+    'vkEnumerateDeviceExtensionProperties' : True,
+
+    'vkGetInstanceProcAddr' : True,
+    'vkGetDeviceProcAddr' : True,
+
+    # VK_KHR_swapchain v69 requirement
+    'vkBindImageMemory2' : True,
+    'vkBindImageMemory2KHR' : True
+  }
+  if gencom.isFunctionSupported(functionName):
+    if functionName in switchCase:
+      return switchCase[functionName]
+
+    if functionName in gencom.extensionsDict:
+      return isExtensionIntercepted(gencom.extensionsDict[functionName])
+  return False
+
+def needProcHookStub(functionName):
+  if isIntercepted(functionName) and gencom.isDeviceDispatched(functionName):
+    if functionName in gencom.extensionsDict:
+      if not gencom.isExtensionInternal(gencom.extensionsDict[functionName]):
+        return True
+  return False
+
+def defineInitProc(name, f):
+  f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
+  f.write ('\n')
+  f.write ("""#define INIT_PROC(required, obj, proc)                                 \\
+    do {                                                               \\
+        data.""" + name + """.proc =                                             \\
+            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
+        if (UNLIKELY(required && !data.""" + name + """.proc)) {                 \\
+            ALOGE("missing " #obj " proc: vk" #proc);                  \\
+            success = false;                                           \\
+        }                                                              \\
+    } while (0)\n\n""")
+
+def defineInitProcExt(f):
+  f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc) \\
+    do {                                        \\
+        if (extensions[ProcHook::ext])          \\
+            INIT_PROC(required, obj, proc);     \\
+    } while (0)\n\n""")
+
+def defineProcHookStub(functionName, f):
+  if needProcHookStub(functionName):
+    ext_name = gencom.extensionsDict[functionName]
+    base_name = functionName[2:]
+    paramList = [''.join(i) for i in gencom.paramDict[functionName]]
+    p0 = gencom.paramDict[functionName][0][1]
+    f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' checked' + base_name + '(' + ', '.join(paramList) + ') {\n')
+    ext_hook = 'ProcHook::' + ext_name[3:]
+
+    f.write (gencom.clang_off_spaces + 'if (GetData(' + p0 + ').hook_extensions[' + ext_hook + ']) {\n')
+    f.write (gencom.clang_off_spaces *2)
+    if gencom.returnTypeDict[functionName] != 'void':
+      f.write ('return ')
+    paramNames = [''.join(i[1]) for i in gencom.paramDict[functionName]]
+    f.write (base_name + '(' + ', '.join(paramNames) + ');\n')
+    f.write (gencom.clang_off_spaces + '} else {\n')
+    f.write (gencom.clang_off_spaces*2 + 'Logger(' + p0 + ').Err(' + p0 + ', \"' + ext_name + ' not enabled. ' + functionName + ' not executed.\");\n')
+    if gencom.returnTypeDict[functionName] != 'void':
+      f.write (gencom.clang_off_spaces*2 + 'return VK_SUCCESS;\n')
+    f.write (gencom.clang_off_spaces + '}\n')
+    f.write ('}\n\n')
+
+def defineGlobalProcHook(functionName, f):
+  base_name = functionName[2:]
+  assert (functionName not in gencom.extensionsDict)
+  f.write (gencom.clang_off_spaces + '{\n' + gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n' + gencom.clang_off_spaces*2)
+  f.write ("""ProcHook::GLOBAL,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(""" + base_name  + """),
+        nullptr,
+    },\n""")
+
+def defineInstanceProcHook(functionName, f):
+  base_name = functionName[2:]
+  f.write (gencom.clang_off_spaces + '{\n')
+  f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
+  f.write (gencom.clang_off_spaces*2 + 'ProcHook::INSTANCE,\n')
+
+  if functionName in gencom.extensionsDict:
+    ext_name = gencom.extensionsDict[functionName]
+    f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
+    if gencom.isExtensionInternal(ext_name):
+      f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+    else:
+      f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+
+  else:
+    f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+        nullptr,\n""")
+
+  f.write (gencom.clang_off_spaces + '},\n')
+
+def defineDeviceProcHook(functionName, f):
+  base_name = functionName[2:]
+  f.write (gencom.clang_off_spaces + '{\n')
+  f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
+  f.write (gencom.clang_off_spaces*2 + 'ProcHook::DEVICE,\n')
+
+  if functionName in gencom.extensionsDict:
+    ext_name = gencom.extensionsDict[functionName]
+    f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
+    if gencom.isExtensionInternal(ext_name):
+      f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+    else:
+      f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(checked' + base_name + '),\n')
+
+  else:
+    f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+        nullptr,\n""")
+
+  f.write (gencom.clang_off_spaces + '},\n')
+
+def driver_gencpp():
+  header = """#include <log/log.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include "driver.h"
+
+namespace vulkan {
+namespace driver {
+
+namespace {
+
+// clang-format off\n\n"""
+
+  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.cpp')
+
+  with open(genfile, 'w') as f:
+    f.write (gencom.copyright)
+    f.write (gencom.warning)
+    f.write (header)
+
+    for cmds in gencom.allCommandsList:
+      defineProcHookStub(cmds, f)
+    gencom.clang_on(f, 0)
+    f.write ('\n')
+
+    f.write ('const ProcHook g_proc_hooks[] = {\n')
+    gencom.clang_off(f, 1)
+    sortedCommandsList = sorted(gencom.allCommandsList)
+    for cmds in sortedCommandsList:
+      if isIntercepted(cmds):
+        if gencom.isGloballyDispatched(cmds):
+          defineGlobalProcHook(cmds, f)
+        elif gencom.isInstanceDispatched(cmds):
+          defineInstanceProcHook(cmds, f)
+        elif gencom.isDeviceDispatched(cmds):
+          defineDeviceProcHook(cmds, f)
+    gencom.clang_on(f, 1)
+    f.write ('};\n\n}  // namespace\n\n')
+
+    f.write ("""const ProcHook* GetProcHook(const char* name) {
+    const auto& begin = g_proc_hooks;
+    const auto& end =
+        g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
+    const auto hook = std::lower_bound(
+        begin, end, name,
+        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
+    return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
+}\n\n""")
+
+    f.write ('ProcHook::Extension GetProcHookExtension(const char* name) {\n')
+    gencom.clang_off(f, 1)
+    for exts in knownExtensions:
+      f.write (gencom.clang_off_spaces + 'if (strcmp(name, \"' + exts + '\") == 0) return ProcHook::' + exts[3:] + ';\n')
+    gencom.clang_on(f, 1)
+    f.write (gencom.clang_off_spaces + 'return ProcHook::EXTENSION_UNKNOWN;\n')
+    f.write ('}\n\n')
+
+    defineInitProc('driver', f)
+    defineInitProcExt(f)
+
+    f.write ("""bool InitDriverTable(VkInstance instance,
+                     PFN_vkGetInstanceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(instance);
+    bool success = true;\n\n""")
+    gencom.clang_off(f, 1)
+    for cmds in gencom.allCommandsList:
+      if isInstanceDriverTableEntry(cmds):
+        gencom.initProc(cmds, f)
+    gencom.clang_on(f, 1)
+    f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
+    f.write ('}\n\n')
+
+    f.write ("""bool InitDriverTable(VkDevice dev,
+                     PFN_vkGetDeviceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(dev);
+    bool success = true;\n\n""")
+    gencom.clang_off(f, 1)
+    for cmds in gencom.allCommandsList:
+      if isDeviceDriverTableEntry(cmds):
+        gencom.initProc(cmds, f)
+    gencom.clang_on(f, 1)
+    f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
+    f.write ('}\n\n}  // namespace driver\n}  // namespace vulkan\n\n')
+    gencom.clang_on(f, 0)
+    f.close()
+  gencom.runClangFormat(genfile)
diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py
new file mode 100644
index 0000000..d9f97e1
--- /dev/null
+++ b/vulkan/scripts/generator_common.py
@@ -0,0 +1,269 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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 provides the common functions for generating the
+# vulkan framework directly from the vulkan registry (vk.xml).
+
+from subprocess import check_call
+
+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.
+ */
+
+"""
+
+warning = '// WARNING: This file is generated. See ../README.md for instructions.\n\n'
+
+blacklistedExtensions = [
+    'VK_KHR_display',
+    'VK_KHR_display_swapchain',
+    'VK_KHR_mir_surface',
+    'VK_KHR_xcb_surface',
+    'VK_KHR_xlib_surface',
+    'VK_KHR_wayland_surface',
+    'VK_KHR_win32_surface',
+    'VK_KHR_external_memory_win32',
+    'VK_KHR_win32_keyed_mutex',
+    'VK_KHR_external_semaphore_win32',
+    'VK_KHR_external_fence_win32',
+    'VK_EXT_acquire_xlib_display',
+    'VK_EXT_direct_mode_display',
+    'VK_EXT_display_surface_counter',
+    'VK_EXT_display_control',
+    'VK_FUCHSIA_imagepipe_surface',
+    'VK_MVK_ios_surface',
+    'VK_MVK_macos_surface',
+    'VK_NN_vi_surface',
+    'VK_NV_external_memory_win32',
+    'VK_NV_win32_keyed_mutex',
+    'VK_EXT_metal_surface', #not present in vulkan.api
+    'VK_NVX_image_view_handle', #not present in vulkan.api
+    'VK_NV_cooperative_matrix', #not present in vulkan.api
+    'VK_EXT_headless_surface', #not present in vulkan.api
+    'VK_GGP_stream_descriptor_surface', #not present in vulkan.api
+    'VK_NV_coverage_reduction_mode', #not present in vulkan.api
+    'VK_EXT_full_screen_exclusive' #not present in vulkan.api
+]
+
+exportedExtensions = [
+    'VK_KHR_surface',
+    'VK_KHR_swapchain',
+    'VK_KHR_android_surface',
+    'VK_ANDROID_external_memory_android_hardware_buffer'
+]
+
+def runClangFormat(args):
+  clang_call = ["clang-format", "--style", "file", "-i", args]
+  check_call (clang_call)
+
+def isExtensionInternal(extensionName):
+  if extensionName == 'VK_ANDROID_native_buffer':
+    return True
+  return False
+
+def isFunctionSupported(functionName):
+  if functionName not in extensionsDict:
+    return True
+  else:
+    if extensionsDict[functionName] not in blacklistedExtensions:
+      return True
+  return False
+
+def isInstanceDispatched(functionName):
+  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Instance'
+
+def isDeviceDispatched(functionName):
+  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Device'
+
+def isGloballyDispatched(functionName):
+  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Global'
+
+def isExtensionExported(extensionName):
+  if extensionName in exportedExtensions:
+    return True
+  return False
+
+def isFunctionExported(functionName):
+  if isFunctionSupported(functionName):
+    if functionName in extensionsDict:
+      return isExtensionExported(extensionsDict[functionName])
+    return True
+  return False
+
+def getDispatchTableType(functionName):
+  if functionName not in paramDict:
+    return None
+
+  switchCase = {
+      'VkInstance ' : 'Instance',
+      'VkPhysicalDevice ' : 'Instance',
+      'VkDevice ' : 'Device',
+      'VkQueue ' : 'Device',
+      'VkCommandBuffer ' : 'Device'
+  }
+
+  if len(paramDict[functionName])>0:
+    return switchCase.get(paramDict[functionName][0][0], 'Global')
+  return 'Global'
+
+def isInstanceDispatchTableEntry(functionName):
+  if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
+    return False
+  if isFunctionExported(functionName) and isInstanceDispatched(functionName):
+    return True
+  return False
+
+def isDeviceDispatchTableEntry(functionName):
+  if isFunctionExported(functionName) and isDeviceDispatched(functionName):
+    return True
+  return False
+
+
+def clang_on(f, indent):
+  f.write (clang_off_spaces * indent + '// clang-format on\n')
+
+def clang_off(f, indent):
+  f.write (clang_off_spaces * indent + '// clang-format off\n')
+
+clang_off_spaces = ' '*4
+
+parametersList = []
+paramDict = {}
+allCommandsList = []
+extensionsDict = {}
+returnTypeDict = {}
+versionDict = {}
+aliasDict = {}
+
+def parseVulkanRegistry():
+  import xml.etree.ElementTree as ET
+  import os
+  vulkan_registry = os.path.join(os.path.dirname(__file__),'..','..','..','..','external','vulkan-headers','registry','vk.xml')
+  tree = ET.parse(vulkan_registry)
+  root = tree.getroot()
+  protoset = False
+  fnName = ""
+  fnType = ""
+  for commands in root.iter('commands'):
+    for command in commands:
+      if command.tag == 'command':
+        if protoset == True:
+          paramDict[fnName] = parametersList.copy()
+        parametersList.clear()
+        protoset = False
+        if command.get('alias') != None:
+          alias = command.get('alias')
+          fnName = command.get('name')
+          aliasDict[fnName] = alias
+          allCommandsList.append(fnName)
+          paramDict[fnName] = paramDict[alias].copy()
+          returnTypeDict[fnName] = returnTypeDict[alias]
+        for params in command:
+          if(params.tag == 'param'):
+            paramtype = ""
+            if params.text!=None:
+              paramtype = params.text
+            typeval = params.find('type')
+            paramtype = paramtype + typeval.text
+            if typeval.tail!=None:
+              paramtype = paramtype + typeval.tail
+            pname = params.find('name')
+            paramname = pname.text
+            if pname.tail != None:
+              parametersList.append((paramtype,paramname,pname.tail))
+            else:
+              parametersList.append((paramtype,paramname))
+          if params.tag == 'proto':
+            for c in params:
+              if c.tag == 'type':
+                fnType = c.text
+              if c.tag == 'name':
+                fnName = c.text
+                protoset = True
+                allCommandsList.append(fnName)
+                returnTypeDict[fnName] = fnType
+
+  for exts in root.iter('extensions'):
+    for extension in exts:
+      apiversion = ""
+      if extension.tag == 'extension':
+        extname = extension.get('name')
+        for req in extension:
+          if req.get('feature')!=None:
+            apiversion = req.get('feature')
+          for commands in req:
+            if commands.tag == 'command':
+              commandname = commands.get('name')
+              if commandname not in extensionsDict:
+                extensionsDict[commandname] = extname
+                if apiversion != "":
+                  versionDict[commandname] = apiversion
+
+  # TODO(adsrini): http://b/136570819
+  extensionsDict['vkGetSwapchainGrallocUsage2ANDROID'] = 'VK_ANDROID_native_buffer'
+  allCommandsList.append('vkGetSwapchainGrallocUsage2ANDROID')
+  returnTypeDict['vkGetSwapchainGrallocUsage2ANDROID'] = 'VkResult'
+  paramDict['vkGetSwapchainGrallocUsage2ANDROID'] = [
+    ('VkDevice ', 'device'),
+    ('VkFormat ', 'format'),
+    ('VkImageUsageFlags ', 'imageUsage'),
+    ('VkSwapchainImageUsageFlagsANDROID ', 'swapchainImageUsage'),
+    ('uint64_t* ', 'grallocConsumerUsage'),
+    ('uint64_t* ', 'grallocProducerUsage')
+  ]
+
+  for feature in root.iter('feature'):
+    apiversion = feature.get('name')
+    for req in feature:
+      for command in req:
+        if command.tag == 'command':
+          cmdName = command.get('name')
+          if cmdName in allCommandsList:
+            versionDict[cmdName] = apiversion
+
+
+def initProc(name, f):
+  if name in extensionsDict:
+    f.write ('    INIT_PROC_EXT(' + extensionsDict[name][3:] + ', ')
+  else:
+    f.write ('    INIT_PROC(')
+
+  if name in versionDict and versionDict[name] == 'VK_VERSION_1_1':
+    f.write('false, ')
+  elif name == 'vkGetSwapchainGrallocUsageANDROID' or name == 'vkGetSwapchainGrallocUsage2ANDROID': # optional in vulkan.api
+    f.write('false, ')
+  else:
+    f.write('true, ')
+
+  if isInstanceDispatched(name):
+    f.write('instance, ')
+  else:
+    f.write('dev, ')
+
+  f.write(name[2:] + ');\n')
+
diff --git a/vulkan/scripts/null_generator.py b/vulkan/scripts/null_generator.py
new file mode 100644
index 0000000..ee8762e
--- /dev/null
+++ b/vulkan/scripts/null_generator.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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 provides the functions for generating the null driver
+# framework directly from the vulkan registry (vk.xml).
+
+import generator_common as gencom
+import os
+
+copyright = """/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+"""
+
+def isDriverExtension(extensionName):
+  switchCase = {
+    'VK_ANDROID_native_buffer' : True,
+    'VK_EXT_debug_report' : True,
+    'VK_KHR_get_physical_device_properties2' : True
+  }
+
+  if extensionName in switchCase:
+    return switchCase[extensionName]
+  return False
+
+def isDriverFunction(functionName):
+  if functionName in gencom.extensionsDict:
+    return isDriverExtension(gencom.extensionsDict[functionName])
+  return True
+
+def null_driver_genh():
+  header = """#ifndef NULLDRV_NULL_DRIVER_H
+#define NULLDRV_NULL_DRIVER_H 1
+
+#include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vulkan.h>
+
+namespace null_driver {
+
+PFN_vkVoidFunction GetGlobalProcAddr(const char* name);
+PFN_vkVoidFunction GetInstanceProcAddr(const char* name);
+
+"""
+  genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.h')
+  with open(genfile, 'w') as f:
+    f.write (copyright)
+    f.write (gencom.warning)
+    f.write (header)
+    gencom.clang_off(f,0)
+
+    for cmds in gencom.allCommandsList:
+      if isDriverFunction(cmds):
+        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
+        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' +', '.join(paramList) + ');\n')
+    f.write ("""VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
+VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
+VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);\n""")
+    gencom.clang_on(f,0)
+
+    f.write ('\n}  // namespace null_driver\n')
+    f.write ('\n#endif  // NULLDRV_NULL_DRIVER_H\n')
+    f.close()
+  gencom.runClangFormat(genfile)
+
+def null_driver_gencpp():
+  header = """#include <algorithm>
+
+#include "null_driver_gen.h"
+
+using namespace null_driver;
+
+namespace {
+
+struct NameProc {
+    const char* name;
+    PFN_vkVoidFunction proc;
+};
+
+PFN_vkVoidFunction Lookup(const char* name,
+                          const NameProc* begin,
+                          const NameProc* end) {
+    const auto& entry = std::lower_bound(
+        begin, end, name,
+        [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
+    if (entry == end || strcmp(entry->name, name) != 0)
+        return nullptr;
+    return entry->proc;
+}
+
+template <size_t N>
+PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
+    return Lookup(name, procs, procs + N);
+}
+
+const NameProc kGlobalProcs[] = {
+"""
+  genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.cpp')
+  with open(genfile, 'w') as f:
+    f.write (copyright)
+    f.write (gencom.warning)
+    f.write (header)
+    gencom.clang_off(f,1)
+
+    sortedCommandsList = sorted(gencom.allCommandsList)
+    for cmds in sortedCommandsList:
+      if isDriverFunction(cmds) and gencom.getDispatchTableType(cmds) == 'Global':
+        f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n\n')
+
+    f.write ('const NameProc kInstanceProcs[] = {\n')
+    gencom.clang_off(f,1)
+    for cmds in sortedCommandsList:
+      if isDriverFunction(cmds):
+        f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n\n}  // namespace\n\n')
+
+    f.write ("""namespace null_driver {
+
+PFN_vkVoidFunction GetGlobalProcAddr(const char* name) {
+    return Lookup(name, kGlobalProcs);
+}
+
+PFN_vkVoidFunction GetInstanceProcAddr(const char* name) {
+    return Lookup(name, kInstanceProcs);
+}
+
+}  // namespace null_driver\n""")
+    f.close()
+  gencom.runClangFormat(genfile)
+
diff --git a/vulkan/vkjson/vkjson.cc b/vulkan/vkjson/vkjson.cc
index 3da4336..6204779 100644
--- a/vulkan/vkjson/vkjson.cc
+++ b/vulkan/vkjson/vkjson.cc
@@ -21,11 +21,14 @@
 #include "vkjson.h"
 
 #include <assert.h>
-#include <string.h>
 #include <stdlib.h>
+#include <string.h>
 
-#include <cmath>
+#include <json/json.h>
+
+#include <algorithm>
 #include <cinttypes>
+#include <cmath>
 #include <cstdio>
 #include <limits>
 #include <memory>
@@ -33,8 +36,6 @@
 #include <type_traits>
 #include <utility>
 
-#include <json/json.h>
-
 namespace {
 
 inline bool IsIntegral(double value) {
@@ -46,6 +47,14 @@
 #endif
 }
 
+// Floating point fields of Vulkan structure use single precision. The string
+// output of max double value in c++ will be larger than Java double's infinity
+// value. Below fake double max/min values are only to serve the safe json text
+// parsing in between C++ and Java, becasue Java json library simply cannot
+// handle infinity.
+static const double SAFE_DOUBLE_MAX = 0.99 * std::numeric_limits<double>::max();
+static const double SAFE_DOUBLE_MIN = 0.99 * std::numeric_limits<double>::min();
+
 template <typename T> struct EnumTraits;
 template <> struct EnumTraits<VkPhysicalDeviceType> {
   static uint32_t min() { return VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE; }
@@ -851,7 +860,8 @@
 
 template <typename T, typename = EnableForArithmetic<T>>
 inline Json::Value ToJsonValue(const T& value) {
-  return Json::Value(static_cast<double>(value));
+  return Json::Value(
+      std::clamp(static_cast<double>(value), SAFE_DOUBLE_MIN, SAFE_DOUBLE_MAX));
 }
 
 inline Json::Value ToJsonValue(const uint64_t& value) {