Merge "Use GLint from client state parameters in glGetBooleanv"
diff --git a/shared/OpenglCodecCommon/GLClientState.cpp b/shared/OpenglCodecCommon/GLClientState.cpp
index 93f9d5d..edaa363 100644
--- a/shared/OpenglCodecCommon/GLClientState.cpp
+++ b/shared/OpenglCodecCommon/GLClientState.cpp
@@ -1481,7 +1481,7 @@
     return GL_NO_ERROR;
 }
 
-void GLClientState::setBoundEGLImage(GLenum target, GLeglImageOES image) {
+void GLClientState::setBoundEGLImage(GLenum target, GLeglImageOES image, int width, int height) {
     (void)image;
 
     if (target == GL_RENDERBUFFER) {
@@ -1489,7 +1489,7 @@
         setBoundRenderbufferEGLImageBacked();
         setBoundRenderbufferFormat(GL_RGBA);
         setBoundRenderbufferSamples(0);
-        setBoundRenderbufferDimensions(1, 1);
+        setBoundRenderbufferDimensions(width, height);
     } else {
         GLuint texture = getBoundTexture(target);
         TextureRec* texrec = getTextureRec(texture);
@@ -1499,7 +1499,7 @@
         setBoundTextureFormat(target, GL_RGBA);
         setBoundTextureType(target, GL_UNSIGNED_BYTE);
         setBoundTextureSamples(target, 0);
-        setBoundTextureDims(target, target, 0, 1, 1, 1);
+        setBoundTextureDims(target, target, 0, width, height, 1);
     }
 }
 
diff --git a/shared/OpenglCodecCommon/GLClientState.h b/shared/OpenglCodecCommon/GLClientState.h
index c0ca53a..ff20287 100644
--- a/shared/OpenglCodecCommon/GLClientState.h
+++ b/shared/OpenglCodecCommon/GLClientState.h
@@ -414,7 +414,7 @@
     // For accurate error detection, bindTexture should be called for *all*
     // targets, not just 2D and EXTERNAL_OES.
     GLenum bindTexture(GLenum target, GLuint texture, GLboolean* firstUse);
-    void setBoundEGLImage(GLenum target, GLeglImageOES image);
+    void setBoundEGLImage(GLenum target, GLeglImageOES image, int width, int height);
 
     // Return the texture currently bound to GL_TEXTURE_(2D|EXTERNAL_OES).
     GLuint getBoundTexture(GLenum target) const;
diff --git a/shared/OpenglCodecCommon/GLSharedGroup.h b/shared/OpenglCodecCommon/GLSharedGroup.h
index 807a006..9832378 100755
--- a/shared/OpenglCodecCommon/GLSharedGroup.h
+++ b/shared/OpenglCodecCommon/GLSharedGroup.h
@@ -30,6 +30,7 @@
 #include <GLES2/gl2ext.h>
 
 #include <map>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -39,7 +40,6 @@
 #include <utils/threads.h>
 #include "auto_goldfish_dma_context.h"
 #include "IndexRangeCache.h"
-#include "SmartPtr.h"
 #include "StateTrackingSupport.h"
 
 struct BufferData {
@@ -258,6 +258,6 @@
     int getActiveAttributesCountForProgram(GLuint program);
 };
 
-typedef SmartPtr<GLSharedGroup> GLSharedGroupPtr; 
+typedef std::shared_ptr<GLSharedGroup> GLSharedGroupPtr;
 
 #endif //_GL_SHARED_GROUP_H_
diff --git a/shared/OpenglCodecCommon/SmartPtr.h b/shared/OpenglCodecCommon/SmartPtr.h
deleted file mode 100644
index 3d821c8..0000000
--- a/shared/OpenglCodecCommon/SmartPtr.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
-* Copyright (C) 2011 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-#ifndef __SMART_PTR_H
-#define __SMART_PTR_H
-
-#include <PortableMutex.h>
-
-#include <cutils/atomic.h>
-
-template <class T, bool threadSafe = false>
-class SmartPtr
-{
-public:
-    explicit SmartPtr(T* ptr = (T*)NULL) {
-        if (threadSafe) {
-            m_lock = new mutex_t;
-            mutex_init(m_lock);
-        }
-        else m_lock = NULL;
-
-        m_ptr = ptr;
-        if (ptr)
-           m_pRefCount = new int32_t(1);
-        else
-           m_pRefCount = NULL;
-    }
-
-    SmartPtr<T,threadSafe>(const SmartPtr<T,false>& rhs) {
-        if (threadSafe) {
-            m_lock = new mutex_t;
-            mutex_init(m_lock);
-        }
-        else m_lock = NULL;
-
-        m_pRefCount = rhs.m_pRefCount;
-        m_ptr       = rhs.m_ptr;
-        use();
-    }
-
-    SmartPtr<T,threadSafe>(SmartPtr<T,true>& rhs) {
-        if (threadSafe) {
-            m_lock = new mutex_t;
-            mutex_init(m_lock);
-        }
-        else m_lock = NULL;
-
-        if (rhs.m_lock) mutex_lock(rhs.m_lock);
-        m_pRefCount = rhs.m_pRefCount;
-        m_ptr       = rhs.m_ptr;
-        use();
-        if (rhs.m_lock) mutex_unlock(rhs.m_lock);
-    }
-
-    ~SmartPtr() {
-        if (m_lock) mutex_lock(m_lock);
-        release();
-        if (m_lock)
-        {
-            mutex_unlock(m_lock);
-            mutex_destroy(m_lock);
-            delete m_lock;
-        }
-    }
-
-    T* Ptr() const {
-        return m_ptr;
-    }
-
-    const T* constPtr() const
-    {
-        return m_ptr;
-    }
-
-    T* operator->() const {
-        return m_ptr;
-    }
-
-    T& operator*() const {
-        return *m_ptr;
-    }
-
-    operator void*() const {
-        return (void *)m_ptr;
-    }
-
-    // This gives STL lists something to compare.
-    bool operator <(const SmartPtr<T>& t1) const {
-        return m_ptr < t1.m_ptr;
-    }
-
-    SmartPtr<T,threadSafe>& operator=(const SmartPtr<T,false>& rhs)
-    {
-        if (m_ptr == rhs.m_ptr)
-            return *this;
-
-        if (m_lock) mutex_lock(m_lock);
-        release();
-        m_pRefCount = rhs.m_pRefCount;
-        m_ptr       = rhs.m_ptr;
-        use();
-        if (m_lock) mutex_unlock(m_lock);
-
-        return *this;
-    }
-
-    SmartPtr<T,threadSafe>& operator=(SmartPtr<T,true>& rhs)
-    {
-        if (m_ptr == rhs.m_ptr)
-            return *this;
-
-        if (m_lock) mutex_lock(m_lock);
-        release();
-        if (rhs.m_lock) mutex_lock(rhs.m_lock);
-        m_pRefCount = rhs.m_pRefCount;
-        m_ptr       = rhs.m_ptr;
-        use();
-        if (rhs.m_lock) mutex_unlock(rhs.m_lock);
-        if (m_lock) mutex_unlock(m_lock);
-
-        return *this;
-    }
-
-private:
-    int32_t  *m_pRefCount;
-    mutex_t  *m_lock;
-    T* m_ptr;
-
-    // Increment the reference count on this pointer by 1.
-    int use() {
-        if (!m_pRefCount) return 0;
-        return android_atomic_inc(m_pRefCount) + 1;
-    }
-
-    // Decrement the reference count on the pointer by 1.
-    // If the reference count goes to (or below) 0, the pointer is deleted.
-    int release() {
-        if (!m_pRefCount) return 0;
-
-        int iVal = android_atomic_dec(m_pRefCount);
-        if (iVal > 1)
-            return iVal - 1;
-
-        delete m_pRefCount;
-        m_pRefCount = NULL;
-
-        if (m_ptr) {
-            delete m_ptr;
-            m_ptr = NULL;
-        }
-        return 0;
-    }
-
-};
-
-#endif // of  __SMART_PTR_H
diff --git a/system/GLESv1_enc/GLEncoder.h b/system/GLESv1_enc/GLEncoder.h
index a26636c..7837838 100644
--- a/system/GLESv1_enc/GLEncoder.h
+++ b/system/GLESv1_enc/GLEncoder.h
@@ -33,7 +33,7 @@
     }
     void setSharedGroup(GLSharedGroupPtr shared) {
         m_shared = shared;
-        if (m_state && m_shared.Ptr())
+        if (m_state && m_shared)
             m_state->setTextureData(m_shared->getTextureData());
     }
     void flush() { m_stream->flush(); }
diff --git a/system/GLESv2/gl2.cpp b/system/GLESv2/gl2.cpp
index 1c5ece7..9598a30 100644
--- a/system/GLESv2/gl2.cpp
+++ b/system/GLESv2/gl2.cpp
@@ -79,7 +79,7 @@
         DEFINE_AND_VALIDATE_HOST_CONNECTION();
 
         ctx->override2DTextureTarget(target);
-        ctx->associateEGLImage(target, hostImage);
+        ctx->associateEGLImage(target, hostImage, image->width, image->height);
         rcEnc->rcBindTexture(rcEnc,
                 grallocHelper->getHostHandle(native_buffer->handle));
         ctx->restore2DTextureTarget(target);
@@ -87,7 +87,7 @@
     else if (image->target == EGL_GL_TEXTURE_2D_KHR) {
         GET_CONTEXT;
         ctx->override2DTextureTarget(target);
-        ctx->associateEGLImage(target, hostImage);
+        ctx->associateEGLImage(target, hostImage, image->width, image->height);
         ctx->m_glEGLImageTargetTexture2DOES_enc(self, GL_TEXTURE_2D, hostImage);
         ctx->restore2DTextureTarget(target);
     }
@@ -116,7 +116,7 @@
 
         DEFINE_AND_VALIDATE_HOST_CONNECTION();
         GET_CONTEXT;
-        ctx->associateEGLImage(target, hostImage);
+        ctx->associateEGLImage(target, hostImage, image->width, image->height);
         rcEnc->rcBindRenderbuffer(rcEnc,
                 grallocHelper->getHostHandle(native_buffer->handle));
     } else {
diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp
index add8425..ecc0495 100755
--- a/system/GLESv2_enc/GL2Encoder.cpp
+++ b/system/GLESv2_enc/GL2Encoder.cpp
@@ -41,7 +41,7 @@
 static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external ";
 
 #define SET_ERROR_IF(condition, err) if((condition)) { \
-        ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
+        ALOGE("%s:%s:%d GL error 0x%x condition [%s]\n", __FILE__, __FUNCTION__, __LINE__, err, #condition); \
         ctx->setError(err); \
         return; \
     }
@@ -74,6 +74,7 @@
     m_currMajorVersion = 2;
     m_currMinorVersion = 0;
     m_hasAsyncUnmapBuffer = false;
+    m_hasSyncBufferData = false;
     m_initialized = false;
     m_noHostError = false;
     m_state = NULL;
@@ -668,7 +669,11 @@
 
     ctx->m_shared->updateBufferData(bufferId, size, data);
     ctx->m_shared->setBufferUsage(bufferId, usage);
-    ctx->m_glBufferData_enc(self, target, size, data, usage);
+    if (ctx->m_hasSyncBufferData) {
+        ctx->glBufferDataSyncAEMU(self, target, size, data, usage);
+    } else {
+        ctx->m_glBufferData_enc(self, target, size, data, usage);
+    }
 }
 
 void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
@@ -2851,8 +2856,8 @@
     }
 }
 
-void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage) {
-    m_state->setBoundEGLImage(target, eglImage);
+void GL2Encoder::associateEGLImage(GLenum target, GLeglImageOES eglImage, int width, int height) {
+    m_state->setBoundEGLImage(target, eglImage, width, height);
 }
 
 
@@ -6110,6 +6115,18 @@
     GLuint tex = ctx->m_state->getBoundTexture(target);
     GLsizei neededWidth = xoffset + width;
     GLsizei neededHeight = yoffset + height;
+    ALOGD("%s: tex %u needed width height %d %d xoff %d width %d yoff %d height %d (texture width %d height %d) level %d\n", __func__,
+            tex,
+            neededWidth,
+            neededHeight,
+            xoffset,
+            width,
+            yoffset,
+            height,
+            ctx->m_state->queryTexWidth(level, tex),
+            ctx->m_state->queryTexWidth(level, tex),
+            level);
+
     SET_ERROR_IF(tex &&
                  (neededWidth > ctx->m_state->queryTexWidth(level, tex) ||
                   neededHeight > ctx->m_state->queryTexHeight(level, tex)),
diff --git a/system/GLESv2_enc/GL2Encoder.h b/system/GLESv2_enc/GL2Encoder.h
index 93108eb..90978be 100644
--- a/system/GLESv2_enc/GL2Encoder.h
+++ b/system/GLESv2_enc/GL2Encoder.h
@@ -35,6 +35,9 @@
     void setHasAsyncUnmapBuffer(int version) {
         m_hasAsyncUnmapBuffer = version;
     }
+    void setHasSyncBufferData(bool value) {
+        m_hasSyncBufferData = value;
+    }
     void setNoHostError(bool noHostError) {
         m_noHostError = noHostError;
     }
@@ -62,7 +65,7 @@
     }
     void setSharedGroup(GLSharedGroupPtr shared) {
         m_shared = shared;
-        if (m_state && m_shared.Ptr()) {
+        if (m_state && m_shared) {
             m_state->setTextureData(m_shared->getTextureData());
             m_state->setRenderbufferInfo(m_shared->getRenderbufferInfo());
             m_state->setSamplerInfo(m_shared->getSamplerInfo());
@@ -94,7 +97,7 @@
 
     void override2DTextureTarget(GLenum target);
     void restore2DTextureTarget(GLenum target);
-    void associateEGLImage(GLenum target, GLeglImageOES eglImage);
+    void associateEGLImage(GLenum target, GLeglImageOES eglImage, int width, int height);
 
     // Convenience functions for buffers
     GLuint boundBuffer(GLenum target) const;
@@ -113,6 +116,7 @@
     std::vector<std::string> m_currExtensionsArray;
 
     bool    m_hasAsyncUnmapBuffer;
+    bool    m_hasSyncBufferData;
     bool    m_initialized;
     bool    m_noHostError;
     GLClientState *m_state;
diff --git a/system/GLESv2_enc/gl2_client_context.cpp b/system/GLESv2_enc/gl2_client_context.cpp
index aaa0325..49b52a7 100644
--- a/system/GLESv2_enc/gl2_client_context.cpp
+++ b/system/GLESv2_enc/gl2_client_context.cpp
@@ -436,6 +436,7 @@
 	glDrawElementsDataNullAEMU = (glDrawElementsDataNullAEMU_client_proc_t) getProc("glDrawElementsDataNullAEMU", userData);
 	glUnmapBufferAsyncAEMU = (glUnmapBufferAsyncAEMU_client_proc_t) getProc("glUnmapBufferAsyncAEMU", userData);
 	glFlushMappedBufferRangeAEMU2 = (glFlushMappedBufferRangeAEMU2_client_proc_t) getProc("glFlushMappedBufferRangeAEMU2", userData);
+	glBufferDataSyncAEMU = (glBufferDataSyncAEMU_client_proc_t) getProc("glBufferDataSyncAEMU", userData);
 	return 0;
 }
 
diff --git a/system/GLESv2_enc/gl2_client_context.h b/system/GLESv2_enc/gl2_client_context.h
index 575395a..b3d5f70 100644
--- a/system/GLESv2_enc/gl2_client_context.h
+++ b/system/GLESv2_enc/gl2_client_context.h
@@ -436,6 +436,7 @@
 	glDrawElementsDataNullAEMU_client_proc_t glDrawElementsDataNullAEMU;
 	glUnmapBufferAsyncAEMU_client_proc_t glUnmapBufferAsyncAEMU;
 	glFlushMappedBufferRangeAEMU2_client_proc_t glFlushMappedBufferRangeAEMU2;
+	glBufferDataSyncAEMU_client_proc_t glBufferDataSyncAEMU;
 	virtual ~gl2_client_context_t() {}
 
 	typedef gl2_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/system/GLESv2_enc/gl2_client_proc.h b/system/GLESv2_enc/gl2_client_proc.h
index 615b123..268cb99 100644
--- a/system/GLESv2_enc/gl2_client_proc.h
+++ b/system/GLESv2_enc/gl2_client_proc.h
@@ -438,6 +438,7 @@
 typedef void (gl2_APIENTRY *glDrawElementsDataNullAEMU_client_proc_t) (void * ctx, GLenum, GLsizei, GLenum, void*, GLuint);
 typedef void (gl2_APIENTRY *glUnmapBufferAsyncAEMU_client_proc_t) (void * ctx, GLenum, GLintptr, GLsizeiptr, GLbitfield, void*, GLboolean*);
 typedef void (gl2_APIENTRY *glFlushMappedBufferRangeAEMU2_client_proc_t) (void * ctx, GLenum, GLintptr, GLsizeiptr, GLbitfield, void*);
+typedef GLboolean (gl2_APIENTRY *glBufferDataSyncAEMU_client_proc_t) (void * ctx, GLenum, GLsizeiptr, const GLvoid*, GLenum);
 
 
 #endif
diff --git a/system/GLESv2_enc/gl2_enc.cpp b/system/GLESv2_enc/gl2_enc.cpp
index d997f29..e610c86 100644
--- a/system/GLESv2_enc/gl2_enc.cpp
+++ b/system/GLESv2_enc/gl2_enc.cpp
@@ -11918,6 +11918,52 @@
 
 }
 
+GLboolean glBufferDataSyncAEMU_enc(void *self , GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+{
+	AEMU_SCOPED_TRACE("glBufferDataSyncAEMU encode");
+
+	gl2_encoder_context_t *ctx = (gl2_encoder_context_t *)self;
+	IOStream *stream = ctx->m_stream;
+	ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+	bool useChecksum = checksumCalculator->getVersion() > 0;
+
+	const unsigned int __size_data = ((data != NULL) ?  size : 0);
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 4 + 4 + __size_data + 4 + 1*4;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_glBufferDataSyncAEMU;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+		memcpy(ptr, &target, 4); ptr += 4;
+		memcpy(ptr, &size, 4); ptr += 4;
+	memcpy(ptr, &__size_data, 4); ptr += 4;
+	if (data != NULL) memcpy(ptr, data, __size_data);ptr += __size_data;
+		memcpy(ptr, &usage, 4); ptr += 4;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+
+	GLboolean retval;
+	stream->readback(&retval, 1);
+	if (useChecksum) checksumCalculator->addBuffer(&retval, 1);
+	if (useChecksum) {
+		unsigned char *checksumBufPtr = NULL;
+		unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
+		if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
+		stream->readback(checksumBufPtr, checksumSize);
+		if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
+			ALOGE("glBufferDataSyncAEMU: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+	return retval;
+}
+
 }  // namespace
 
 gl2_encoder_context_t::gl2_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -12351,5 +12397,6 @@
 	this->glDrawElementsDataNullAEMU = &glDrawElementsDataNullAEMU_enc;
 	this->glUnmapBufferAsyncAEMU = &glUnmapBufferAsyncAEMU_enc;
 	this->glFlushMappedBufferRangeAEMU2 = &glFlushMappedBufferRangeAEMU2_enc;
+	this->glBufferDataSyncAEMU = &glBufferDataSyncAEMU_enc;
 }
 
diff --git a/system/GLESv2_enc/gl2_entry.cpp b/system/GLESv2_enc/gl2_entry.cpp
index a5d6c87..5ea44c2 100644
--- a/system/GLESv2_enc/gl2_entry.cpp
+++ b/system/GLESv2_enc/gl2_entry.cpp
@@ -431,6 +431,7 @@
 	void glDrawElementsDataNullAEMU(GLenum mode, GLsizei count, GLenum type, void* data, GLuint datalen);
 	void glUnmapBufferAsyncAEMU(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void* guest_buffer, GLboolean* out_res);
 	void glFlushMappedBufferRangeAEMU2(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void* guest_buffer);
+	GLboolean glBufferDataSyncAEMU(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
 };
 
 #ifndef GET_CONTEXT
@@ -3032,3 +3033,9 @@
 	ctx->glFlushMappedBufferRangeAEMU2(ctx, target, offset, length, access, guest_buffer);
 }
 
+GLboolean glBufferDataSyncAEMU(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+{
+	GET_CONTEXT;
+	return ctx->glBufferDataSyncAEMU(ctx, target, size, data, usage);
+}
+
diff --git a/system/GLESv2_enc/gl2_opcodes.h b/system/GLESv2_enc/gl2_opcodes.h
index 9c619e1..25ab3e7 100644
--- a/system/GLESv2_enc/gl2_opcodes.h
+++ b/system/GLESv2_enc/gl2_opcodes.h
@@ -429,7 +429,8 @@
 #define OP_glDrawElementsDataNullAEMU 					2471
 #define OP_glUnmapBufferAsyncAEMU 					2472
 #define OP_glFlushMappedBufferRangeAEMU2 					2473
-#define OP_last 					2474
+#define OP_glBufferDataSyncAEMU 					2474
+#define OP_last 					2475
 
 
 #endif
diff --git a/system/OpenglSystemCommon/EGLImage.h b/system/OpenglSystemCommon/EGLImage.h
index a83e1ad..8a1eb6d 100644
--- a/system/OpenglSystemCommon/EGLImage.h
+++ b/system/OpenglSystemCommon/EGLImage.h
@@ -36,6 +36,8 @@
 {
     EGLDisplay dpy;
     EGLenum target;
+    int width;
+    int height;
 
     union
     {
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index f4467bb..f6d8ce5 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -125,6 +125,10 @@
 
 // Queue submit with commands
 static const char kVulkanQueueSubmitWithCommands[] = "ANDROID_EMU_vulkan_queue_submit_with_commands";
+//
+// Synchronized glBufferData call
+static const char kSyncBufferData[] = "ANDROID_EMU_sync_buffer_data";
+
 
 // Batched descriptor set update
 static const char kVulkanBatchedDescriptorSetUpdate[] = "ANDROID_EMU_vulkan_batched_descriptor_set_update";
@@ -154,7 +158,8 @@
         hasHostSideTracing(false),
         hasAsyncFrameCommands(false),
         hasVulkanQueueSubmitWithCommands(false),
-        hasVulkanBatchedDescriptorSetUpdate(false)
+        hasVulkanBatchedDescriptorSetUpdate(false),
+        hasSyncBufferData(false)
     { }
 
     SyncImpl syncImpl;
@@ -179,6 +184,7 @@
     bool hasAsyncFrameCommands;
     bool hasVulkanQueueSubmitWithCommands;
     bool hasVulkanBatchedDescriptorSetUpdate;
+    bool hasSyncBufferData;
 };
 
 enum HostConnectionType {
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index 1ad93b8..7610efc 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -40,6 +40,7 @@
     void setNoHostError(bool) { }
     void setDrawCallFlushInterval(uint32_t) { }
     void setHasAsyncUnmapBuffer(int) { }
+    void setHasSyncBufferData(int) { }
 };
 #else
 #include "GLEncoder.h"
@@ -620,6 +621,7 @@
         m_gl2Enc->setDrawCallFlushInterval(
             getDrawCallFlushIntervalFromProperty());
         m_gl2Enc->setHasAsyncUnmapBuffer(m_rcEnc->hasAsyncUnmapBuffer());
+        m_gl2Enc->setHasSyncBufferData(m_rcEnc->hasSyncBufferData());
     }
     return m_gl2Enc.get();
 }
@@ -664,6 +666,8 @@
         queryAndSetAsyncFrameCommands(rcEnc);
         queryAndSetVulkanQueueSubmitWithCommandsSupport(rcEnc);
         queryAndSetVulkanBatchedDescriptorSetUpdateSupport(rcEnc);
+        queryAndSetSyncBufferData(rcEnc);
+        queryVersion(rcEnc);
         if (m_processPipe) {
             m_processPipe->processPipeInit(m_connectionType, rcEnc);
         }
@@ -954,3 +958,15 @@
         rcEnc->featureInfo()->hasVulkanBatchedDescriptorSetUpdate = true;
     }
 }
+
+void HostConnection::queryAndSetSyncBufferData(ExtendedRCEncoderContext* rcEnc) {
+    std::string glExtensions = queryGLExtensions(rcEnc);
+    if (glExtensions.find(kSyncBufferData) != std::string::npos) {
+        rcEnc->featureInfo()->hasSyncBufferData = true;
+    }
+}
+
+GLint HostConnection::queryVersion(ExtendedRCEncoderContext* rcEnc) {
+    GLint version = m_rcEnc->rcGetRendererVersion(m_rcEnc.get());
+    return version;
+}
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index c1c3f40..7c55629 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -75,6 +75,8 @@
     bool hasAsyncFrameCommands() const {
         return m_featureInfo.hasAsyncFrameCommands;
     }
+    bool hasSyncBufferData() const {
+        return m_featureInfo.hasSyncBufferData; }
     DmaImpl getDmaVersion() const { return m_featureInfo.dmaImpl; }
     void bindDmaContext(struct goldfish_dma_context* cxt) { m_dmaCxt = cxt; }
     void bindDmaDirectly(void* dmaPtr, uint64_t dmaPhysAddr) {
@@ -239,6 +241,8 @@
     void queryAndSetAsyncFrameCommands(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetVulkanQueueSubmitWithCommandsSupport(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetVulkanBatchedDescriptorSetUpdateSupport(ExtendedRCEncoderContext *rcEnc);
+    void queryAndSetSyncBufferData(ExtendedRCEncoderContext *rcEnc);
+    GLint queryVersion(ExtendedRCEncoderContext* rcEnc);
 
 private:
     HostConnectionType m_connectionType;
diff --git a/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp b/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp
index 15b90d4..f445244 100644
--- a/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp
+++ b/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp
@@ -304,14 +304,14 @@
 
         zx_signals_t observed = ZX_SIGNAL_NONE;
         zx_status_t status = m_event.wait_one(
-            fuchsia_hardware_goldfish::wire::SIGNAL_READABLE |
-                fuchsia_hardware_goldfish::wire::SIGNAL_HANGUP,
+            fuchsia_hardware_goldfish::wire::kSignalReadable |
+                fuchsia_hardware_goldfish::wire::kSignalHangup,
             zx::time::infinite(), &observed);
         if (status != ZX_OK) {
             ALOGD("%s: wait_one failed: %d", __FUNCTION__, status);
             return nullptr;
         }
-        if (observed & fuchsia_hardware_goldfish::wire::SIGNAL_HANGUP) {
+        if (observed & fuchsia_hardware_goldfish::wire::kSignalHangup) {
             ALOGD("%s: Remote end hungup", __FUNCTION__);
             return nullptr;
         }
diff --git a/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp b/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp
index 1a9368a..a65ce67 100644
--- a/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp
+++ b/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp
@@ -512,8 +512,6 @@
     return true;
 }
 
-bool C2GoldfishAvcDec::getVuiParams() { return true; }
-
 status_t C2GoldfishAvcDec::setFlushMode() {
     if (mContext) {
         mContext->flush();
@@ -703,7 +701,41 @@
     }
 }
 
+void C2GoldfishAvcDec::getVuiParams(h264_image_t &img) {
+
+    VuiColorAspects vuiColorAspects;
+    vuiColorAspects.primaries = img.color_primaries;
+    vuiColorAspects.transfer = img.color_trc;
+    vuiColorAspects.coeffs = img.colorspace;
+    vuiColorAspects.fullRange = img.color_range == 2 ? true : false;
+
+    // convert vui aspects to C2 values if changed
+    if (!(vuiColorAspects == mBitstreamColorAspects)) {
+        mBitstreamColorAspects = vuiColorAspects;
+        ColorAspects sfAspects;
+        C2StreamColorAspectsInfo::input codedAspects = {0u};
+        ColorUtils::convertIsoColorAspectsToCodecAspects(
+            vuiColorAspects.primaries, vuiColorAspects.transfer,
+            vuiColorAspects.coeffs, vuiColorAspects.fullRange, sfAspects);
+        if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) {
+            codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED;
+        }
+        if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) {
+            codedAspects.range = C2Color::RANGE_UNSPECIFIED;
+        }
+        if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) {
+            codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED;
+        }
+        if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) {
+            codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED;
+        }
+        std::vector<std::unique_ptr<C2SettingResult>> failures;
+        (void)mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
+    }
+}
+
 void C2GoldfishAvcDec::copyImageData(uint8_t *pBuffer, h264_image_t &img) {
+    getVuiParams(img);
     if (mEnableAndroidNativeBuffers)
         return;
     int myStride = mWidth;
@@ -843,7 +875,6 @@
             //            (void) ivdec_api_function(mDecHandle, &s_decode_ip,
             //            &s_decode_op);
         }
-        (void)getVuiParams();
         if (mImg.data != nullptr) {
             DDD("got data %" PRIu64,  mPts2Index[mImg.pts]);
             hasPicture = true;
diff --git a/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.h b/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.h
index 57b1d69..f97b2b0 100644
--- a/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.h
+++ b/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.h
@@ -65,7 +65,6 @@
     status_t initDecoder();
     bool setDecodeArgs(C2ReadView *inBuffer, C2GraphicView *outBuffer,
                        size_t inOffset, size_t inSize, uint32_t tsMarker);
-    bool getVuiParams();
     c2_status_t ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool);
     void finishWork(uint64_t index, const std::unique_ptr<C2Work> &work);
     status_t setFlushMode();
@@ -98,6 +97,7 @@
 
     int mHostColorBufferId{-1};
 
+    void getVuiParams(h264_image_t &img);
     void copyImageData(uint8_t *pBuffer, h264_image_t &img);
 
     uint8_t *mByteBuffer{nullptr};
diff --git a/system/codecs/c2/decoders/vpxdec/C2GoldfishVpxDec.cpp b/system/codecs/c2/decoders/vpxdec/C2GoldfishVpxDec.cpp
index b33ce2e..7df99ff 100644
--- a/system/codecs/c2/decoders/vpxdec/C2GoldfishVpxDec.cpp
+++ b/system/codecs/c2/decoders/vpxdec/C2GoldfishVpxDec.cpp
@@ -89,8 +89,8 @@
             DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
                 .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
                 .withFields({
-                    C2F(mSize, width).inRange(2, 2048, 2),
-                    C2F(mSize, height).inRange(2, 2048, 2),
+                    C2F(mSize, width).inRange(2, 4096, 2),
+                    C2F(mSize, height).inRange(2, 4096, 2),
                 })
                 .withSetter(SizeSetter)
                 .build());
@@ -178,8 +178,8 @@
                          .withDefault(new C2StreamMaxPictureSizeTuning::output(
                              0u, 320, 240))
                          .withFields({
-                             C2F(mSize, width).inRange(2, 2048, 2),
-                             C2F(mSize, height).inRange(2, 2048, 2),
+                             C2F(mSize, width).inRange(2, 4096, 2),
+                             C2F(mSize, height).inRange(2, 4096, 2),
                          })
                          .withSetter(MaxPictureSizeSetter, mSize)
                          .build());
@@ -242,17 +242,25 @@
                           const C2P<C2StreamPictureSizeInfo::output> &oldMe,
                           C2P<C2StreamPictureSizeInfo::output> &me) {
         (void)mayBlock;
-        DDD("calling sizesetter now %d", oldMe.v.height);
-        DDD("new calling sizesetter now %d", me.v.height);
+        DDD("calling sizesetter old w %d", oldMe.v.width);
+        DDD("calling sizesetter old h %d", oldMe.v.height);
+        DDD("calling sizesetter change to w %d", me.v.width);
+        DDD("calling sizesetter change to h %d", me.v.height);
         C2R res = C2R::Ok();
-        if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
+        auto mewidth = me.F(me.v.width);
+        auto meheight = me.F(me.v.height);
+
+        if (!mewidth.supportsAtAll(me.v.width)) {
             res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
+            DDD("override width with oldMe value");
             me.set().width = oldMe.v.width;
+            DDD("something wrong here %s %d", __func__, __LINE__);
         }
-        if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
+        if (!meheight.supportsAtAll(me.v.height)) {
             res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
-            DDD("override with oldMe value");
+            DDD("override height with oldMe value");
             me.set().height = oldMe.v.height;
+            DDD("something wrong here %s %d", __func__, __LINE__);
         }
         return res;
     }
@@ -264,8 +272,8 @@
         (void)mayBlock;
         // TODO: get max width/height from the size's field helpers vs.
         // hardcoding
-        me.set().width = c2_min(c2_max(me.v.width, size.v.width), 2048u);
-        me.set().height = c2_min(c2_max(me.v.height, size.v.height), 2048u);
+        me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
+        me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
         return C2R::Ok();
     }
 
diff --git a/system/egl/egl.cpp b/system/egl/egl.cpp
index bfe0db6..c204899 100644
--- a/system/egl/egl.cpp
+++ b/system/egl/egl.cpp
@@ -1216,6 +1216,7 @@
     }
 
     int attribs_size = 0;
+    EGLint backup_attribs[1];
     if (attrib_list) {
         const EGLint * attrib_p = attrib_list;
         while (attrib_p[0] != EGL_NONE) {
@@ -1223,6 +1224,10 @@
             attrib_p += 2;
         }
         attribs_size++; //for the terminating EGL_NONE
+    } else {
+        attribs_size = 1;
+        backup_attribs[0] = EGL_NONE;
+        attrib_list = backup_attribs;
     }
 
     // API 19 passes EGL_SWAP_BEHAVIOR_PRESERVED_BIT to surface type,
@@ -2275,6 +2280,8 @@
         image->dpy = dpy;
         image->target = target;
         image->native_buffer = native_buffer;
+        image->width = native_buffer->width;
+        image->height = native_buffer->width;
 
         return (EGLImageKHR)image;
     }
@@ -2291,6 +2298,8 @@
         image->dpy = dpy;
         image->target = target;
         image->host_egl_image = img;
+        image->width = context->getClientState()->queryTexWidth(0, texture);
+        image->height = context->getClientState()->queryTexHeight(0, texture);
 
         return (EGLImageKHR)image;
     }
@@ -2376,17 +2385,17 @@
 
         // Validate and input attribs
         for (int i = 0; i < num_actual_attribs; i += 2) {
-            if (attrib_list[i] == EGL_SYNC_TYPE_KHR) {
-                DPRINT("ERROR: attrib key = EGL_SYNC_TYPE_KHR");
-            }
-            if (attrib_list[i] == EGL_SYNC_STATUS_KHR) {
-                DPRINT("ERROR: attrib key = EGL_SYNC_STATUS_KHR");
-            }
-            if (attrib_list[i] == EGL_SYNC_CONDITION_KHR) {
-                DPRINT("ERROR: attrib key = EGL_SYNC_CONDITION_KHR");
-            }
             EGLint attrib_key = attrib_list[i];
             EGLint attrib_val = attrib_list[i + 1];
+            switch (attrib_key) {
+                case EGL_SYNC_TYPE_KHR:
+                case EGL_SYNC_STATUS_KHR:
+                case EGL_SYNC_CONDITION_KHR:
+                case EGL_SYNC_NATIVE_FENCE_FD_ANDROID:
+                    break;
+                default:
+                    setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
+            }
             if (attrib_key == EGL_SYNC_NATIVE_FENCE_FD_ANDROID) {
                 if (attrib_val != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
                     inputFenceFd = attrib_val;
@@ -2455,8 +2464,8 @@
     (void)dpy;
 
     if (!eglsync) {
-        DPRINT("WARNING: null sync object")
-        return EGL_TRUE;
+        ALOGE("%s: null sync object!", __FUNCTION__);
+        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
     }
 
     EGLSync_t* sync = static_cast<EGLSync_t*>(eglsync);
@@ -2487,8 +2496,8 @@
     (void)dpy;
 
     if (!eglsync) {
-        DPRINT("WARNING: null sync object");
-        return EGL_CONDITION_SATISFIED_KHR;
+        ALOGE("%s: null sync object!", __FUNCTION__);
+        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
     }
 
     EGLSync_t* sync = (EGLSync_t*)eglsync;
@@ -2527,6 +2536,14 @@
 
     EGLSync_t* sync = (EGLSync_t*)eglsync;
 
+    if (!sync) {
+        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    if (!value) {
+        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
     switch (attribute) {
     case EGL_SYNC_TYPE_KHR:
         *value = sync->type;
@@ -2574,12 +2591,12 @@
 
     if (!eglsync) {
         ALOGE("%s: null sync object!", __FUNCTION__);
-        return EGL_FALSE;
+        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
     }
 
     if (flags) {
         ALOGE("%s: flags must be 0, got 0x%x", __FUNCTION__, flags);
-        return EGL_FALSE;
+        setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
     }
 
     DEFINE_HOST_CONNECTION;
diff --git a/system/hwc2/Android.mk b/system/hwc2/Android.mk
index 2254d2f..4d207ff 100644
--- a/system/hwc2/Android.mk
+++ b/system/hwc2/Android.mk
@@ -100,4 +100,7 @@
 LOCAL_C_INCLUDES += external/drm_hwcomposer
 LOCAL_C_INCLUDES += external/minigbm/cros_gralloc
 LOCAL_MODULE := emulatorDrmTest
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../LICENSE
 include $(BUILD_EXECUTABLE)
diff --git a/system/hwc2/Device.cpp b/system/hwc2/Device.cpp
index 3e32a50..24df956 100644
--- a/system/hwc2/Device.cpp
+++ b/system/hwc2/Device.cpp
@@ -525,7 +525,9 @@
   }
   if (connected) {
     createDisplay(id, width, height, dpiX, dpiY, refreshRate);
-    ALOGD("callback hotplugConnect display %" PRIu32, id);
+    ALOGD("callback hotplugConnect display %" PRIu32 " width %" PRIu32
+          " height %" PRIu32 " dpiX %" PRIu32 " dpiY %" PRIu32
+          "fps %" PRIu32, id, width, height, dpiX, dpiY, refreshRate);
     hotplug(mCallbacks[HWC2::Callback::Hotplug].data, id, hotplugConnect);
   };
 
diff --git a/system/hwc2/Display.cpp b/system/hwc2/Display.cpp
index 2faa947..99a7c01 100644
--- a/system/hwc2/Display.cpp
+++ b/system/hwc2/Display.cpp
@@ -69,10 +69,11 @@
 Display::~Display() {}
 
 HWC2::Error Display::init(uint32_t width, uint32_t height, uint32_t dpiX,
-                          uint32_t dpiY, uint32_t refreshRateHz) {
-  DEBUG_LOG("%s initializing display:%" PRIu64
-            " width:%d height:%d dpiX:%d dpiY:%d refreshRateHz:%d",
-            __FUNCTION__, mId, width, height, dpiX, dpiY, refreshRateHz);
+                          uint32_t dpiY, uint32_t refreshRateHz,
+                          const std::optional<std::vector<uint8_t>>& edid) {
+  ALOGD("%s initializing display:%" PRIu64
+        " width:%d height:%d dpiX:%d dpiY:%d refreshRateHz:%d",
+        __FUNCTION__, mId, width, height, dpiX, dpiY, refreshRateHz);
 
   std::unique_lock<std::recursive_mutex> lock(mStateMutex);
 
@@ -92,13 +93,15 @@
   mActiveConfigId = configId;
   mActiveColorMode = HAL_COLOR_MODE_NATIVE;
   mColorModes.emplace((android_color_mode_t)HAL_COLOR_MODE_NATIVE);
+  mEdid = edid;
 
   return HWC2::Error::None;
 }
 
 HWC2::Error Display::updateParameters(uint32_t width, uint32_t height,
                                       uint32_t dpiX, uint32_t dpiY,
-                                      uint32_t refreshRateHz) {
+                                      uint32_t refreshRateHz,
+                                      const std::optional<std::vector<uint8_t>>& edid) {
   DEBUG_LOG("%s updating display:%" PRIu64
             " width:%d height:%d dpiX:%d dpiY:%d refreshRateHz:%d",
             __FUNCTION__, mId, width, height, dpiX, dpiY, refreshRateHz);
@@ -118,6 +121,8 @@
   it->second.setAttribute(HWC2::Attribute::DpiX, dpiX * 1000);
   it->second.setAttribute(HWC2::Attribute::DpiY, dpiY * 1000);
 
+  mEdid = edid;
+
   return HWC2::Error::None;
 }
 
@@ -301,7 +306,7 @@
 
   // we only support HAL_COLOR_MODE_NATIVE so far
   uint32_t numModes =
-      std::min(*outNumModes, static_cast<uint32_t>(mColorModes.size()));
+      std::min<uint32_t>(*outNumModes, static_cast<uint32_t>(mColorModes.size()));
   std::copy_n(mColorModes.cbegin(), numModes, outModes);
   *outNumModes = numModes;
   return HWC2::Error::None;
@@ -760,6 +765,18 @@
     return HWC2::Error::BadParameter;
   }
 
+  if (mEdid) {
+    if (outData) {
+      *outDataSize = std::min<uint32_t>(*outDataSize, (*mEdid).size());
+      memcpy(outData, (*mEdid).data(), *outDataSize);
+    } else {
+      *outDataSize = (*mEdid).size();
+    }
+    *outPort = mId;
+    return HWC2::Error::None;
+  }
+
+  // fallback to legacy EDID implementation
   uint32_t len = std::min(*outDataSize, (uint32_t)ARRAY_SIZE(sEDID0));
   if (outData != nullptr && len < (uint32_t)ARRAY_SIZE(sEDID0)) {
     ALOGW("%s: display:%" PRIu64 " small buffer size: %u is specified",
diff --git a/system/hwc2/Display.h b/system/hwc2/Display.h
index 277933a..418e26c 100644
--- a/system/hwc2/Display.h
+++ b/system/hwc2/Display.h
@@ -47,10 +47,13 @@
   Display& operator=(Display&& display) = delete;
 
   HWC2::Error init(uint32_t width, uint32_t height, uint32_t dpiX,
-                   uint32_t dpiY, uint32_t refreshRateHz);
+                   uint32_t dpiY, uint32_t refreshRateHz,
+                   const std::optional<std::vector<uint8_t>>& edid = std::nullopt);
 
   HWC2::Error updateParameters(uint32_t width, uint32_t height, uint32_t dpiX,
-                               uint32_t dpiY, uint32_t refreshRateHz);
+                               uint32_t dpiY, uint32_t refreshRateHz,
+                               const std::optional<std::vector<uint8_t>>& edid
+                                   = std::nullopt);
 
   hwc2_display_t getId() const { return mId; }
 
@@ -226,6 +229,7 @@
   std::set<android_color_mode_t> mColorModes;
   android_color_mode_t mActiveColorMode;
   bool mSetColorTransform = false;
+  std::optional<std::vector<uint8_t>> mEdid;
 };
 
 }  // namespace android
diff --git a/system/hwc2/DrmPresenter.cpp b/system/hwc2/DrmPresenter.cpp
index 22bd08c..4d63c58 100644
--- a/system/hwc2/DrmPresenter.cpp
+++ b/system/hwc2/DrmPresenter.cpp
@@ -222,6 +222,8 @@
             mFd.get(), connectorProps->props[connectorPropIndex]);
         if (!strcmp(connectorProp->name, "CRTC_ID")) {
           connector.mCrtcPropertyId = connectorProp->prop_id;
+        } else if (!strcmp(connectorProp->name, "EDID")) {
+          connector.mEdidBlobId = connectorProps->prop_values[connectorPropIndex];
         }
         drmModeFreeProperty(connectorProp);
       }
@@ -244,11 +246,11 @@
 
         // Dots per 1000 inches
         connector.dpiX =
-            c->mmWidth ? (c->mmWidth * kUmPerInch * 10) / c->modes[0].hdisplay
+            c->mmWidth ? (c->modes[0].hdisplay * kUmPerInch) / (c->mmWidth)
                        : -1;
         // Dots per 1000 inches
         connector.dpiY =
-            c->mmHeight ? (c->mmHeight * kUmPerInch * 10) / c->modes[0].vdisplay
+            c->mmHeight ? (c->modes[0].vdisplay * kUmPerInch) / (c->mmHeight)
                         : -1;
       }
       ALOGD("%s connector %" PRIu32 " dpiX %" PRIi32 " dpiY %" PRIi32
@@ -492,6 +494,29 @@
   return error;
 }
 
+std::optional<std::vector<uint8_t>> DrmPresenter::getEdid(uint32_t id) {
+  AutoReadLock lock(mStateMutex);
+
+  if (mConnectors[id].mEdidBlobId == -1) {
+    ALOGW("%s: EDID not supported", __func__);
+    return std::nullopt;
+  }
+  drmModePropertyBlobPtr blob = drmModeGetPropertyBlob(mFd.get(),
+                                                       mConnectors[id].mEdidBlobId);
+  if (!blob) {
+    ALOGE("%s: fail to read EDID from DRM", __func__);
+    return std::nullopt;
+  }
+
+  std::vector<uint8_t> edid;
+  uint8_t* start = static_cast<uint8_t*>(blob->data);
+  edid.insert(edid.begin(), start, start + blob->length);
+
+  drmModeFreePropertyBlob(blob);
+
+  return edid;
+}
+
 DrmBuffer::DrmBuffer(const native_handle_t* handle, DrmPresenter& DrmPresenter)
     : mDrmPresenter(DrmPresenter), mBo({}) {
   if (!convertBoInfo(handle)) {
diff --git a/system/hwc2/DrmPresenter.h b/system/hwc2/DrmPresenter.h
index 6fbb4c7..7f9edb2 100644
--- a/system/hwc2/DrmPresenter.h
+++ b/system/hwc2/DrmPresenter.h
@@ -78,6 +78,8 @@
 
   HWC2::Error flushToDisplay(int display, hwc_drm_bo_t& fb, int* outSyncFd);
 
+  std::optional<std::vector<uint8_t>> getEdid(uint32_t id);
+
  private:
   // Grant visibility for getDrmFB and clearDrmFB to DrmBuffer.
   friend class DrmBuffer;
@@ -136,6 +138,7 @@
     uint32_t mModeBlobId = 0;
     float mRefreshRateAsFloat;
     uint32_t mRefreshRateAsInteger;
+    uint64_t mEdidBlobId = -1;
   };
   std::vector<DrmConnector> mConnectors;
 
diff --git a/system/hwc2/HostComposer.cpp b/system/hwc2/HostComposer.cpp
index a4ab183..c55eccd 100644
--- a/system/hwc2/HostComposer.cpp
+++ b/system/hwc2/HostComposer.cpp
@@ -152,7 +152,6 @@
 const native_handle_t* AllocateDisplayColorBuffer(int width, int height) {
   const uint32_t layerCount = 1;
   const uint64_t graphicBufferId = 0;  // not used
-
   buffer_handle_t h;
   uint32_t stride;
 
@@ -266,13 +265,17 @@
     hostCon->unlock();
     return HWC2::Error::NoResources;
   }
-  if (rcEnc->rcSetDisplayPose(rcEnc, displayId, -1, -1, width, height)) {
+  if (rcEnc->rcSetDisplayPoseDpi(rcEnc, displayId, -1, -1, width, height, dpiX/1000)) {
     ALOGE("%s host failed to set display %" PRIu32, __func__, displayId);
     hostCon->unlock();
     return HWC2::Error::NoResources;
   }
   hostCon->unlock();
 
+  std::optional<std::vector<uint8_t>> edid;
+  if (mIsMinigbm) {
+    edid = mDrmPresenter.getEdid(displayId);
+  }
   if (!display) {
     auto newDisplay = std::make_unique<Display>(*device, this, displayId);
     if (newDisplay == nullptr) {
@@ -280,7 +283,8 @@
       return HWC2::Error::NoResources;
     }
 
-    error = newDisplay->init(width, height, dpiX, dpiY, refreshRateHz);
+
+    error = newDisplay->init(width, height, dpiX, dpiY, refreshRateHz, edid);
     if (error != HWC2::Error::None) {
       ALOGE("%s failed to initialize display:%" PRIu32, __FUNCTION__,
             displayId);
@@ -303,7 +307,8 @@
   } else {
     display->lock();
     // update display parameters
-    error = display->updateParameters(width, height, dpiX, dpiY, refreshRateHz);
+    error = display->updateParameters(width, height, dpiX, dpiY,
+                                      refreshRateHz, edid);
     if (error != HWC2::Error::None) {
       ALOGE("%s failed to update display:%" PRIu32, __FUNCTION__, displayId);
       display->unlock();
@@ -568,6 +573,7 @@
     if (display->hasColorTransform()) {
       fallBack = true;
     }
+
     if (fallBack) {
       for (auto& layer : layers) {
         if (layer->getCompositionType() == HWC2::Composition::Invalid) {
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index c160259..21780a8 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -338,7 +338,7 @@
     };
 
     struct VkQueue_Info {
-        uint32_t placeholder;
+        VkDevice device;
     };
 
     // custom guest-side structs for images/buffers because of AHardwareBuffer :((
@@ -419,6 +419,10 @@
         uint32_t unused;
     };
 
+    struct VkSampler_Info {
+        uint32_t unused;
+    };
+
     struct VkBufferCollectionFUCHSIA_Info {
 #ifdef VK_USE_PLATFORM_FUCHSIA
         android::base::Optional<
@@ -478,6 +482,13 @@
         info_VkCommandPool.erase(pool);
     }
 
+    void unregister_VkSampler(VkSampler sampler) {
+        if (!sampler) return;
+
+        AutoLock lock(mLock);
+        info_VkSampler.erase(sampler);
+    }
+
     void unregister_VkCommandBuffer(VkCommandBuffer commandBuffer) {
         resetCommandBufferStagingInfo(commandBuffer, true /* also reset primaries */, true /* also clear pending descriptor sets */);
 
@@ -709,34 +720,32 @@
         return res;
     }
 
-    VkWriteDescriptorSet
-    createImmutableSamplersFilteredWriteDescriptorSetLocked(
-        const VkWriteDescriptorSet* descriptorWrite,
-        std::vector<VkDescriptorImageInfo>* imageInfoArray) {
+    bool descriptorBindingIsImmutableSampler(
+        VkDescriptorSet dstSet,
+        uint32_t dstBinding) {
 
-        VkWriteDescriptorSet res = *descriptorWrite;
+        return as_goldfish_VkDescriptorSet(dstSet)->reified->bindingIsImmutableSampler[dstBinding];
+    }
 
-        if  (descriptorWrite->descriptorCount == 0) return res;
+    VkDescriptorImageInfo
+    filterNonexistentSampler(
+        const VkDescriptorImageInfo& inputInfo) {
 
-        if  (descriptorWrite->descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER &&
-             descriptorWrite->descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) return res;
+        VkSampler sampler =
+            inputInfo.sampler;
 
-        bool immutableSampler =
-            as_goldfish_VkDescriptorSet(descriptorWrite->dstSet)->reified->bindingIsImmutableSampler[descriptorWrite->dstBinding];
+        VkDescriptorImageInfo res = inputInfo;
 
-        if (!immutableSampler) return res;
-
-        for (uint32_t i = 0; i < descriptorWrite->descriptorCount; ++i) {
-            VkDescriptorImageInfo imageInfo = descriptorWrite->pImageInfo[i];
-            imageInfo.sampler = 0;
-            imageInfoArray->push_back(imageInfo);
+        if (sampler) {
+            auto it = info_VkSampler.find(sampler);
+            bool samplerExists = it != info_VkSampler.end();
+            if (!samplerExists) res.sampler = 0;
         }
 
-        res.pImageInfo = imageInfoArray->data();
-
         return res;
     }
 
+
     void freeDescriptorSetsIfHostAllocated(VkEncoder* enc, VkDevice device, uint32_t descriptorSetCount, const VkDescriptorSet* sets) {
         for (uint32_t i = 0; i < descriptorSetCount; ++i) {
             struct goldfish_VkDescriptorSet* ds = as_goldfish_VkDescriptorSet(sets[i]);
@@ -1578,6 +1587,23 @@
         }
     }
 
+    void on_vkGetDeviceQueue(void*,
+                             VkDevice device,
+                             uint32_t,
+                             uint32_t,
+                             VkQueue* pQueue) {
+        AutoLock lock(mLock);
+        info_VkQueue[*pQueue].device = device;
+    }
+
+    void on_vkGetDeviceQueue2(void*,
+                              VkDevice device,
+                              const VkDeviceQueueInfo2*,
+                              VkQueue* pQueue) {
+        AutoLock lock(mLock);
+        info_VkQueue[*pQueue].device = device;
+    }
+
     VkResult on_vkCreateInstance(
         void* context,
         VkResult input_result,
@@ -1742,8 +1768,8 @@
         VkExternalMemoryHandleTypeFlagBits handleType,
         uint32_t handle,
         VkMemoryZirconHandlePropertiesFUCHSIA* pProperties) {
-        using fuchsia_hardware_goldfish::wire::MEMORY_PROPERTY_DEVICE_LOCAL;
-        using fuchsia_hardware_goldfish::wire::MEMORY_PROPERTY_HOST_VISIBLE;
+        using fuchsia_hardware_goldfish::wire::kMemoryPropertyDeviceLocal;
+        using fuchsia_hardware_goldfish::wire::kMemoryPropertyHostVisible;
 
         if (handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA &&
             handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA) {
@@ -1791,7 +1817,7 @@
             // If an VMO is allocated while ColorBuffer/Buffer is not created,
             // it must be a device-local buffer, since for host-visible buffers,
             // ColorBuffer/Buffer is created at sysmem allocation time.
-            memoryProperty = MEMORY_PROPERTY_DEVICE_LOCAL;
+            memoryProperty = kMemoryPropertyDeviceLocal;
         } else {
             // Importing read-only host memory into the Vulkan driver should not
             // work, but it is not an error to try to do so. Returning a
@@ -1805,10 +1831,10 @@
 
         pProperties->memoryTypeBits = 0;
         for (uint32_t i = 0; i < info.memProps.memoryTypeCount; ++i) {
-            if (((memoryProperty & MEMORY_PROPERTY_DEVICE_LOCAL) &&
+            if (((memoryProperty & kMemoryPropertyDeviceLocal) &&
                  (info.memProps.memoryTypes[i].propertyFlags &
                   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) ||
-                ((memoryProperty & MEMORY_PROPERTY_HOST_VISIBLE) &&
+                ((memoryProperty & kMemoryPropertyHostVisible) &&
                  (info.memProps.memoryTypes[i].propertyFlags &
                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))) {
                 pProperties->memoryTypeBits |= 1ull << i;
@@ -2002,9 +2028,9 @@
         buffer_constraints.inaccessible_domain_supported = true;
         buffer_constraints.heap_permitted_count = 2;
         buffer_constraints.heap_permitted[0] =
-            fuchsia_sysmem::wire::HeapType::GOLDFISH_DEVICE_LOCAL;
+            fuchsia_sysmem::wire::HeapType::kGoldfishDeviceLocal;
         buffer_constraints.heap_permitted[1] =
-            fuchsia_sysmem::wire::HeapType::GOLDFISH_HOST_VISIBLE;
+            fuchsia_sysmem::wire::HeapType::kGoldfishHostVisible;
 
         return constraints;
     }
@@ -2014,15 +2040,15 @@
         uint32_t usage = 0u;
         VkImageUsageFlags imageUsage = pImageInfo->usage;
 
-#define SetUsageBit(USAGE)                                           \
-    if (imageUsage & VK_IMAGE_USAGE_##USAGE##_BIT) {                 \
-        usage |= fuchsia_sysmem::wire::VULKAN_IMAGE_USAGE_##USAGE; \
+#define SetUsageBit(BIT, VALUE)                                           \
+    if (imageUsage & VK_IMAGE_USAGE_##BIT##_BIT) {                 \
+        usage |= fuchsia_sysmem::wire::kVulkanImageUsage##VALUE; \
     }
 
-        SetUsageBit(COLOR_ATTACHMENT);
-        SetUsageBit(TRANSFER_SRC);
-        SetUsageBit(TRANSFER_DST);
-        SetUsageBit(SAMPLED);
+        SetUsageBit(COLOR_ATTACHMENT, ColorAttachment);
+        SetUsageBit(TRANSFER_SRC, TransferSrc);
+        SetUsageBit(TRANSFER_DST, TransferDst);
+        SetUsageBit(SAMPLED, Sampled);
 
 #undef SetUsageBit
         return usage;
@@ -2034,20 +2060,20 @@
         VkBufferUsageFlags bufferUsage =
             pBufferConstraintsInfo->pBufferCreateInfo->usage;
 
-#define SetUsageBit(USAGE)                                            \
-    if (bufferUsage & VK_BUFFER_USAGE_##USAGE##_BIT) {                \
-        usage |= fuchsia_sysmem::wire::VULKAN_BUFFER_USAGE_##USAGE; \
+#define SetUsageBit(BIT, VALUE)                                            \
+    if (bufferUsage & VK_BUFFER_USAGE_##BIT##_BIT) {                \
+        usage |= fuchsia_sysmem::wire::kVulkanBufferUsage##VALUE; \
     }
 
-        SetUsageBit(TRANSFER_SRC);
-        SetUsageBit(TRANSFER_DST);
-        SetUsageBit(UNIFORM_TEXEL_BUFFER);
-        SetUsageBit(STORAGE_TEXEL_BUFFER);
-        SetUsageBit(UNIFORM_BUFFER);
-        SetUsageBit(STORAGE_BUFFER);
-        SetUsageBit(INDEX_BUFFER);
-        SetUsageBit(VERTEX_BUFFER);
-        SetUsageBit(INDIRECT_BUFFER);
+        SetUsageBit(TRANSFER_SRC, TransferSrc);
+        SetUsageBit(TRANSFER_DST, TransferDst);
+        SetUsageBit(UNIFORM_TEXEL_BUFFER, UniformTexelBuffer);
+        SetUsageBit(STORAGE_TEXEL_BUFFER, StorageTexelBuffer);
+        SetUsageBit(UNIFORM_BUFFER, UniformBuffer);
+        SetUsageBit(STORAGE_BUFFER, StorageBuffer);
+        SetUsageBit(INDEX_BUFFER, IndexBuffer);
+        SetUsageBit(VERTEX_BUFFER, VertexBuffer);
+        SetUsageBit(INDIRECT_BUFFER, IndirectBuffer);
 
 #undef SetUsageBit
         return usage;
@@ -2062,14 +2088,14 @@
             case VK_FORMAT_B8G8R8A8_SNORM:
             case VK_FORMAT_B8G8R8A8_SSCALED:
             case VK_FORMAT_B8G8R8A8_USCALED:
-                return fuchsia_sysmem::wire::PixelFormatType::BGRA32;
+                return fuchsia_sysmem::wire::PixelFormatType::kBgra32;
             case VK_FORMAT_R8G8B8A8_SINT:
             case VK_FORMAT_R8G8B8A8_UNORM:
             case VK_FORMAT_R8G8B8A8_SRGB:
             case VK_FORMAT_R8G8B8A8_SNORM:
             case VK_FORMAT_R8G8B8A8_SSCALED:
             case VK_FORMAT_R8G8B8A8_USCALED:
-                return fuchsia_sysmem::wire::PixelFormatType::R8G8B8A8;
+                return fuchsia_sysmem::wire::PixelFormatType::kR8G8B8A8;
             case VK_FORMAT_R8_UNORM:
             case VK_FORMAT_R8_UINT:
             case VK_FORMAT_R8_USCALED:
@@ -2077,7 +2103,7 @@
             case VK_FORMAT_R8_SINT:
             case VK_FORMAT_R8_SSCALED:
             case VK_FORMAT_R8_SRGB:
-                return fuchsia_sysmem::wire::PixelFormatType::R8;
+                return fuchsia_sysmem::wire::PixelFormatType::kR8;
             case VK_FORMAT_R8G8_UNORM:
             case VK_FORMAT_R8G8_UINT:
             case VK_FORMAT_R8G8_USCALED:
@@ -2085,9 +2111,9 @@
             case VK_FORMAT_R8G8_SINT:
             case VK_FORMAT_R8G8_SSCALED:
             case VK_FORMAT_R8G8_SRGB:
-                return fuchsia_sysmem::wire::PixelFormatType::R8G8;
+                return fuchsia_sysmem::wire::PixelFormatType::kR8G8;
             default:
-                return fuchsia_sysmem::wire::PixelFormatType::INVALID;
+                return fuchsia_sysmem::wire::PixelFormatType::kInvalid;
         }
     }
 
@@ -2102,7 +2128,7 @@
             case VK_FORMAT_B8G8R8A8_SSCALED:
             case VK_FORMAT_B8G8R8A8_USCALED:
                 return sysmemFormat ==
-                       fuchsia_sysmem::wire::PixelFormatType::BGRA32;
+                       fuchsia_sysmem::wire::PixelFormatType::kBgra32;
             case VK_FORMAT_R8G8B8A8_SINT:
             case VK_FORMAT_R8G8B8A8_UNORM:
             case VK_FORMAT_R8G8B8A8_SRGB:
@@ -2110,7 +2136,7 @@
             case VK_FORMAT_R8G8B8A8_SSCALED:
             case VK_FORMAT_R8G8B8A8_USCALED:
                 return sysmemFormat ==
-                       fuchsia_sysmem::wire::PixelFormatType::R8G8B8A8;
+                       fuchsia_sysmem::wire::PixelFormatType::kR8G8B8A8;
             case VK_FORMAT_R8_UNORM:
             case VK_FORMAT_R8_UINT:
             case VK_FORMAT_R8_USCALED:
@@ -2119,9 +2145,9 @@
             case VK_FORMAT_R8_SSCALED:
             case VK_FORMAT_R8_SRGB:
                 return sysmemFormat ==
-                           fuchsia_sysmem::wire::PixelFormatType::R8 ||
+                           fuchsia_sysmem::wire::PixelFormatType::kR8 ||
                        sysmemFormat ==
-                           fuchsia_sysmem::wire::PixelFormatType::L8;
+                           fuchsia_sysmem::wire::PixelFormatType::kL8;
             case VK_FORMAT_R8G8_UNORM:
             case VK_FORMAT_R8G8_UINT:
             case VK_FORMAT_R8G8_USCALED:
@@ -2130,7 +2156,7 @@
             case VK_FORMAT_R8G8_SSCALED:
             case VK_FORMAT_R8G8_SRGB:
                 return sysmemFormat ==
-                       fuchsia_sysmem::wire::PixelFormatType::R8G8;
+                       fuchsia_sysmem::wire::PixelFormatType::kR8G8;
             default:
                 return false;
         }
@@ -2139,14 +2165,14 @@
     static VkFormat sysmemPixelFormatTypeToVk(
         fuchsia_sysmem::wire::PixelFormatType format) {
         switch (format) {
-            case fuchsia_sysmem::wire::PixelFormatType::BGRA32:
+            case fuchsia_sysmem::wire::PixelFormatType::kBgra32:
                 return VK_FORMAT_B8G8R8A8_SRGB;
-            case fuchsia_sysmem::wire::PixelFormatType::R8G8B8A8:
+            case fuchsia_sysmem::wire::PixelFormatType::kR8G8B8A8:
                 return VK_FORMAT_R8G8B8A8_SRGB;
-            case fuchsia_sysmem::wire::PixelFormatType::L8:
-            case fuchsia_sysmem::wire::PixelFormatType::R8:
+            case fuchsia_sysmem::wire::PixelFormatType::kL8:
+            case fuchsia_sysmem::wire::PixelFormatType::kR8:
                 return VK_FORMAT_R8_UNORM;
-            case fuchsia_sysmem::wire::PixelFormatType::R8G8:
+            case fuchsia_sysmem::wire::PixelFormatType::kR8G8:
                 return VK_FORMAT_R8G8_UNORM;
             default:
                 return VK_FORMAT_UNDEFINED;
@@ -2265,7 +2291,7 @@
         } else {
             auto pixel_format = vkFormatTypeToSysmem(createInfo->format);
             if (pixel_format ==
-                fuchsia_sysmem::wire::PixelFormatType::INVALID) {
+                fuchsia_sysmem::wire::PixelFormatType::kInvalid) {
                 ALOGW("%s: Unsupported VkFormat %u", __func__,
                       static_cast<uint32_t>(createInfo->format));
                 return VK_ERROR_FORMAT_NOT_SUPPORTED;
@@ -2276,7 +2302,7 @@
         if (!formatConstraints || formatConstraints->colorSpaceCount == 0u) {
             imageConstraints.color_spaces_count = 1;
             imageConstraints.color_space[0].type =
-                fuchsia_sysmem::wire::ColorSpaceType::SRGB;
+                fuchsia_sysmem::wire::ColorSpaceType::kSrgb;
         } else {
             imageConstraints.color_spaces_count =
                 formatConstraints->colorSpaceCount;
@@ -2318,9 +2344,8 @@
         imageConstraints.pixel_format.has_format_modifier = true;
         imageConstraints.pixel_format.format_modifier.value =
             (tiling == VK_IMAGE_TILING_LINEAR)
-                ? fuchsia_sysmem::wire::FORMAT_MODIFIER_LINEAR
-                : fuchsia_sysmem::wire::
-                      FORMAT_MODIFIER_GOOGLE_GOLDFISH_OPTIMAL;
+                ? fuchsia_sysmem::wire::kFormatModifierLinear
+                : fuchsia_sysmem::wire::kFormatModifierGoogleGoldfishOptimal;
 
         constraints->image_format_constraints
             [constraints->image_format_constraints_count++] =
@@ -2416,13 +2441,13 @@
         // and flags.
         VkImageConstraintsInfoFlagsFUCHSIA flags = pImageConstraintsInfo->flags;
         if (flags & VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA)
-            constraints.usage.cpu |= fuchsia_sysmem::wire::cpuUsageRead;
+            constraints.usage.cpu |= fuchsia_sysmem::wire::kCpuUsageRead;
         if (flags & VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA)
-            constraints.usage.cpu |= fuchsia_sysmem::wire::cpuUsageReadOften;
+            constraints.usage.cpu |= fuchsia_sysmem::wire::kCpuUsageReadOften;
         if (flags & VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA)
-            constraints.usage.cpu |= fuchsia_sysmem::wire::cpuUsageWrite;
+            constraints.usage.cpu |= fuchsia_sysmem::wire::kCpuUsageWrite;
         if (flags & VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA)
-            constraints.usage.cpu |= fuchsia_sysmem::wire::cpuUsageWriteOften;
+            constraints.usage.cpu |= fuchsia_sysmem::wire::kCpuUsageWriteOften;
 
         constraints.has_buffer_memory_constraints = true;
         auto& memory_constraints = constraints.buffer_memory_constraints;
@@ -2438,13 +2463,13 @@
         if (memory_constraints.inaccessible_domain_supported) {
             memory_constraints.heap_permitted_count = 2;
             memory_constraints.heap_permitted[0] =
-                fuchsia_sysmem::wire::HeapType::GOLDFISH_DEVICE_LOCAL;
+                fuchsia_sysmem::wire::HeapType::kGoldfishDeviceLocal;
             memory_constraints.heap_permitted[1] =
-                fuchsia_sysmem::wire::HeapType::GOLDFISH_HOST_VISIBLE;
+                fuchsia_sysmem::wire::HeapType::kGoldfishHostVisible;
         } else {
             memory_constraints.heap_permitted_count = 1;
             memory_constraints.heap_permitted[0] =
-                fuchsia_sysmem::wire::HeapType::GOLDFISH_HOST_VISIBLE;
+                fuchsia_sysmem::wire::HeapType::kGoldfishHostVisible;
         }
 
         if (constraints.image_format_constraints_count == 0) {
@@ -2580,7 +2605,7 @@
 
     VkResult getBufferCollectionImageCreateInfoIndexLocked(
         VkBufferCollectionFUCHSIA collection,
-        fuchsia_sysmem::wire::BufferCollectionInfo_2& info,
+        fuchsia_sysmem::wire::BufferCollectionInfo2& info,
         uint32_t* outCreateInfoIndex) {
         if (!info_VkBufferCollectionFUCHSIA[collection]
                  .constraints.hasValue()) {
@@ -2665,13 +2690,13 @@
                   GET_STATUS_SAFE(result, status));
             return VK_ERROR_INITIALIZATION_FAILED;
         }
-        fuchsia_sysmem::wire::BufferCollectionInfo_2 info =
+        fuchsia_sysmem::wire::BufferCollectionInfo2 info =
             std::move(result.Unwrap()->buffer_collection_info);
 
         bool is_host_visible = info.settings.buffer_settings.heap ==
-                               fuchsia_sysmem::wire::HeapType::GOLDFISH_HOST_VISIBLE;
+                               fuchsia_sysmem::wire::HeapType::kGoldfishHostVisible;
         bool is_device_local = info.settings.buffer_settings.heap ==
-                               fuchsia_sysmem::wire::HeapType::GOLDFISH_DEVICE_LOCAL;
+                               fuchsia_sysmem::wire::HeapType::kGoldfishDeviceLocal;
         if (!is_host_visible && !is_device_local) {
             ALOGE("buffer collection uses a non-goldfish heap (type 0x%lu)",
                 static_cast<uint64_t>(info.settings.buffer_settings.heap));
@@ -3189,7 +3214,7 @@
                       GET_STATUS_SAFE(result, status));
                 return VK_ERROR_INITIALIZATION_FAILED;
             }
-            fuchsia_sysmem::wire::BufferCollectionInfo_2& info =
+            fuchsia_sysmem::wire::BufferCollectionInfo2& info =
                 result.Unwrap()->buffer_collection_info;
             uint32_t index = importBufferCollectionInfoPtr->index;
             if (info.buffer_count < index) {
@@ -3328,7 +3353,7 @@
                 {
                     auto result = collection.WaitForBuffersAllocated();
                     if (result.ok() && result.Unwrap()->status == ZX_OK) {
-                        fuchsia_sysmem::wire::BufferCollectionInfo_2& info =
+                        fuchsia_sysmem::wire::BufferCollectionInfo2& info =
                             result.Unwrap()->buffer_collection_info;
                         if (!info.buffer_count) {
                             ALOGE(
@@ -3374,7 +3399,7 @@
                             case VK_FORMAT_B8G8R8A8_SSCALED:
                             case VK_FORMAT_B8G8R8A8_USCALED:
                                 format = fuchsia_hardware_goldfish::wire::
-                                    ColorBufferFormatType::BGRA;
+                                    ColorBufferFormatType::kBgra;
                                 break;
                             case VK_FORMAT_R8G8B8A8_SINT:
                             case VK_FORMAT_R8G8B8A8_UNORM:
@@ -3383,7 +3408,7 @@
                             case VK_FORMAT_R8G8B8A8_SSCALED:
                             case VK_FORMAT_R8G8B8A8_USCALED:
                                 format = fuchsia_hardware_goldfish::wire::
-                                    ColorBufferFormatType::RGBA;
+                                    ColorBufferFormatType::kRgba;
                                 break;
                             case VK_FORMAT_R8_UNORM:
                             case VK_FORMAT_R8_UINT:
@@ -3393,7 +3418,7 @@
                             case VK_FORMAT_R8_SSCALED:
                             case VK_FORMAT_R8_SRGB:
                                 format = fuchsia_hardware_goldfish::wire::
-                                    ColorBufferFormatType::LUMINANCE;
+                                    ColorBufferFormatType::kLuminance;
                                 break;
                             case VK_FORMAT_R8G8_UNORM:
                             case VK_FORMAT_R8G8_UINT:
@@ -3403,7 +3428,7 @@
                             case VK_FORMAT_R8G8_SSCALED:
                             case VK_FORMAT_R8G8_SRGB:
                                 format = fuchsia_hardware_goldfish::wire::
-                                    ColorBufferFormatType::RG;
+                                    ColorBufferFormatType::kRg;
                                 break;
                             default:
                                 ALOGE("Unsupported format: %d",
@@ -3418,7 +3443,7 @@
                             .set_height(allocator, pImageCreateInfo->extent.height)
                             .set_format(allocator, format)
                             .set_memory_property(allocator,
-                                fuchsia_hardware_goldfish::wire::MEMORY_PROPERTY_DEVICE_LOCAL);
+                                fuchsia_hardware_goldfish::wire::kMemoryPropertyDeviceLocal);
 
                         auto result = mControlDevice->CreateColorBuffer2(
                             std::move(vmo_copy), std::move(createParams));
@@ -3444,7 +3469,7 @@
                     createParams.set_size(allocator,
                             pBufferConstraintsInfo->pBufferCreateInfo->size)
                         .set_memory_property(allocator,
-                            fuchsia_hardware_goldfish::wire::MEMORY_PROPERTY_DEVICE_LOCAL);
+                            fuchsia_hardware_goldfish::wire::kMemoryPropertyDeviceLocal);
 
                     auto result =
                         mControlDevice->CreateBuffer2(std::move(vmo_copy), std::move(createParams));
@@ -3478,7 +3503,7 @@
                 uint32_t buffer_handle = result.Unwrap()->id;
 
                 if (handle_type == fuchsia_hardware_goldfish::wire::
-                                       BufferHandleType::BUFFER) {
+                                       BufferHandleType::kBuffer) {
                     importBufferInfo.buffer = buffer_handle;
                     vk_append_struct(&structChainIter, &importBufferInfo);
                 } else {
@@ -3922,7 +3947,7 @@
             uint32_t index = extBufferCollectionPtr->index;
             zx::vmo vmo;
 
-            fuchsia_sysmem::wire::BufferCollectionInfo_2 info;
+            fuchsia_sysmem::wire::BufferCollectionInfo2 info;
 
             auto result = collection->WaitForBuffersAllocated();
             if (result.ok() && result.Unwrap()->status == ZX_OK) {
@@ -3953,7 +3978,7 @@
                     // Buffer handle already exists.
                     // If it is a ColorBuffer, no-op; Otherwise return error.
                     if (buffer_handle_result.value().type !=
-                        fuchsia_hardware_goldfish::wire::BufferHandleType::COLOR_BUFFER) {
+                        fuchsia_hardware_goldfish::wire::BufferHandleType::kColorBuffer) {
                         ALOGE("%s: BufferHandle %u is not a ColorBuffer", __func__,
                               buffer_handle_result.value().id);
                         return VK_ERROR_OUT_OF_HOST_MEMORY;
@@ -3962,15 +3987,15 @@
                     // Buffer handle not found. Create ColorBuffer based on buffer settings.
                     auto format =
                         info.settings.image_format_constraints.pixel_format.type ==
-                                fuchsia_sysmem::wire::PixelFormatType::R8G8B8A8
-                            ? fuchsia_hardware_goldfish::wire::ColorBufferFormatType::RGBA
-                            : fuchsia_hardware_goldfish::wire::ColorBufferFormatType::BGRA;
+                                fuchsia_sysmem::wire::PixelFormatType::kR8G8B8A8
+                            ? fuchsia_hardware_goldfish::wire::ColorBufferFormatType::kRgba
+                            : fuchsia_hardware_goldfish::wire::ColorBufferFormatType::kBgra;
 
                     uint32_t memory_property =
                         info.settings.buffer_settings.heap ==
-                                fuchsia_sysmem::wire::HeapType::GOLDFISH_DEVICE_LOCAL
-                            ? fuchsia_hardware_goldfish::wire::MEMORY_PROPERTY_DEVICE_LOCAL
-                            : fuchsia_hardware_goldfish::wire::MEMORY_PROPERTY_HOST_VISIBLE;
+                                fuchsia_sysmem::wire::HeapType::kGoldfishDeviceLocal
+                            ? fuchsia_hardware_goldfish::wire::kMemoryPropertyDeviceLocal
+                            : fuchsia_hardware_goldfish::wire::kMemoryPropertyHostVisible;
 
                     fidl::FidlAllocator allocator;
                     fuchsia_hardware_goldfish::wire::CreateColorBuffer2Params createParams(
@@ -3991,7 +4016,7 @@
                 }
 
                 if (info.settings.buffer_settings.heap ==
-                    fuchsia_sysmem::wire::HeapType::GOLDFISH_HOST_VISIBLE) {
+                    fuchsia_sysmem::wire::HeapType::kGoldfishHostVisible) {
                     ALOGD(
                         "%s: Image uses host visible memory heap; set tiling "
                         "to linear to match host ImageCreateInfo",
@@ -4782,25 +4807,62 @@
 
         VkEncoder* enc = (VkEncoder*)context;
 
-        std::vector<std::vector<VkDescriptorImageInfo>> imageInfosPerWrite(
-                descriptorWriteCount);
+        std::vector<VkDescriptorImageInfo> transformedImageInfos;
+        std::vector<VkWriteDescriptorSet> transformedWrites(descriptorWriteCount);
 
-        std::vector<VkWriteDescriptorSet> writesWithSuppressedSamplers;
+        memcpy(transformedWrites.data(), pDescriptorWrites, sizeof(VkWriteDescriptorSet) * descriptorWriteCount);
+
+        size_t imageInfosNeeded = 0;
+        for (uint32_t i = 0; i < descriptorWriteCount; ++i) {
+            if (!isDescriptorTypeImageInfo(transformedWrites[i].descriptorType)) continue;
+            if (!transformedWrites[i].pImageInfo) continue;
+
+            imageInfosNeeded += transformedWrites[i].descriptorCount;
+        }
+
+        transformedImageInfos.resize(imageInfosNeeded);
+
+        size_t imageInfoIndex = 0;
+        for (uint32_t i = 0; i < descriptorWriteCount; ++i) {
+            if (!isDescriptorTypeImageInfo(transformedWrites[i].descriptorType)) continue;
+            if (!transformedWrites[i].pImageInfo) continue;
+
+            for (uint32_t j = 0; j < transformedWrites[i].descriptorCount; ++j) {
+                transformedImageInfos[imageInfoIndex] = transformedWrites[i].pImageInfo[j];
+                ++imageInfoIndex;
+            }
+            transformedWrites[i].pImageInfo = &transformedImageInfos[imageInfoIndex - transformedWrites[i].descriptorCount];
+        }
 
         {
+            // Validate and filter samplers
             AutoLock lock(mLock);
+            size_t imageInfoIndex = 0;
             for (uint32_t i = 0; i < descriptorWriteCount; ++i) {
-                writesWithSuppressedSamplers.push_back(
-                        createImmutableSamplersFilteredWriteDescriptorSetLocked(
-                            pDescriptorWrites + i,
-                            imageInfosPerWrite.data() + i));
+
+                if (!isDescriptorTypeImageInfo(transformedWrites[i].descriptorType)) continue;
+                if (!transformedWrites[i].pImageInfo) continue;
+
+                bool isImmutableSampler =
+                    descriptorBindingIsImmutableSampler(
+                        transformedWrites[i].dstSet,
+                        transformedWrites[i].dstBinding);
+
+                for (uint32_t j = 0; j < transformedWrites[i].descriptorCount; ++j) {
+                    if (isImmutableSampler) {
+                        transformedImageInfos[imageInfoIndex].sampler = 0;
+                    }
+                    transformedImageInfos[imageInfoIndex] =
+                        filterNonexistentSampler(transformedImageInfos[imageInfoIndex]);
+                    ++imageInfoIndex;
+                }
             }
         }
 
         if (mFeatureInfo->hasVulkanBatchedDescriptorSetUpdate) {
             for (uint32_t i = 0; i < descriptorWriteCount; ++i) {
-                VkDescriptorSet set = writesWithSuppressedSamplers[i].dstSet;
-                doEmulatedDescriptorWrite(&writesWithSuppressedSamplers[i],
+                VkDescriptorSet set = transformedWrites[i].dstSet;
+                doEmulatedDescriptorWrite(&transformedWrites[i],
                         as_goldfish_VkDescriptorSet(set)->reified);
             }
 
@@ -4811,7 +4873,7 @@
             }
         } else {
             enc->vkUpdateDescriptorSets(
-                    device, descriptorWriteCount, writesWithSuppressedSamplers.data(),
+                    device, descriptorWriteCount, transformedWrites.data(),
                     descriptorCopyCount, pDescriptorCopies, true /* do lock */);
         }
     }
@@ -4963,7 +5025,7 @@
                 fuchsia_hardware_goldfish::wire::CreateBuffer2Params createParams(allocator);
                 createParams.set_size(allocator, pCreateInfo->size)
                     .set_memory_property(allocator,
-                        fuchsia_hardware_goldfish::wire::MEMORY_PROPERTY_DEVICE_LOCAL);
+                        fuchsia_hardware_goldfish::wire::kMemoryPropertyDeviceLocal);
 
                 auto result =
                     mControlDevice->CreateBuffer2(std::move(*vmo), std::move(createParams));
@@ -5137,6 +5199,10 @@
 
         if (exportEvent) {
             finalCreateInfo.pNext = nullptr;
+            // If we have timeline semaphores externally, leave it there.
+            const VkSemaphoreTypeCreateInfo* typeCi =
+                vk_find_struct<VkSemaphoreTypeCreateInfo>(pCreateInfo);
+            if (typeCi) finalCreateInfo.pNext = typeCi;
         }
 #endif
 
@@ -5147,6 +5213,10 @@
 
         if (exportSyncFd) {
             finalCreateInfo.pNext = nullptr;
+            // If we have timeline semaphores externally, leave it there.
+            const VkSemaphoreTypeCreateInfo* typeCi =
+                vk_find_struct<VkSemaphoreTypeCreateInfo>(pCreateInfo);
+            if (typeCi) finalCreateInfo.pNext = typeCi;
         }
 #endif
         input_result = enc->vkCreateSemaphore(
@@ -6440,6 +6510,14 @@
         struct goldfish_VkCommandBuffer* cb = as_goldfish_VkCommandBuffer(commandBuffer);
         cb->flags = pBeginInfo->flags;
 
+        VkCommandBufferBeginInfo modifiedBeginInfo;
+
+        if (pBeginInfo->pInheritanceInfo && !cb->isSecondary) {
+            modifiedBeginInfo = *pBeginInfo;
+            modifiedBeginInfo.pInheritanceInfo = nullptr;
+            pBeginInfo = &modifiedBeginInfo;
+        }
+
         if (!supportsDeferredCommands()) {
             return enc->vkBeginCommandBuffer(commandBuffer, pBeginInfo, true /* do lock */);
         }
@@ -6601,6 +6679,27 @@
         decDescriptorSetLayoutRef(context, device, descriptorSetLayout, pAllocator);
     }
 
+    VkResult on_vkAllocateCommandBuffers(
+        void* context,
+        VkResult input_result,
+        VkDevice device,
+        const VkCommandBufferAllocateInfo* pAllocateInfo,
+        VkCommandBuffer* pCommandBuffers) {
+
+        (void)input_result;
+
+        VkEncoder* enc = (VkEncoder*)context;
+        VkResult res = enc->vkAllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers, true /* do lock */);
+        if (VK_SUCCESS != res) return res;
+
+        for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; ++i) {
+            struct goldfish_VkCommandBuffer* cb = as_goldfish_VkCommandBuffer(pCommandBuffers[i]);
+            cb->isSecondary = pAllocateInfo->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY;
+        }
+
+        return res;
+    }
+
     uint32_t getApiVersionFromInstance(VkInstance instance) const {
         AutoLock lock(mLock);
         uint32_t api = kDefaultApiVersion;
@@ -6970,6 +7069,22 @@
         context, physicalDevice, pMemoryProperties);
 }
 
+void ResourceTracker::on_vkGetDeviceQueue(void* context,
+                                          VkDevice device,
+                                          uint32_t queueFamilyIndex,
+                                          uint32_t queueIndex,
+                                          VkQueue* pQueue) {
+    mImpl->on_vkGetDeviceQueue(context, device, queueFamilyIndex, queueIndex,
+                               pQueue);
+}
+
+void ResourceTracker::on_vkGetDeviceQueue2(void* context,
+                                           VkDevice device,
+                                           const VkDeviceQueueInfo2* pQueueInfo,
+                                           VkQueue* pQueue) {
+    mImpl->on_vkGetDeviceQueue2(context, device, pQueueInfo, pQueue);
+}
+
 VkResult ResourceTracker::on_vkCreateInstance(
     void* context,
     VkResult input_result,
@@ -7717,6 +7832,15 @@
     mImpl->on_vkDestroyDescriptorSetLayout(context, device, descriptorSetLayout, pAllocator);
 }
 
+VkResult ResourceTracker::on_vkAllocateCommandBuffers(
+    void* context,
+    VkResult input_result,
+    VkDevice device,
+    const VkCommandBufferAllocateInfo* pAllocateInfo,
+    VkCommandBuffer* pCommandBuffers) {
+    return mImpl->on_vkAllocateCommandBuffers(context, input_result, device, pAllocateInfo, pCommandBuffers);
+}
+
 void ResourceTracker::deviceMemoryTransform_tohost(
     VkDeviceMemory* memory, uint32_t memoryCount,
     VkDeviceSize* offset, uint32_t offsetCount,
diff --git a/system/vulkan_enc/ResourceTracker.h b/system/vulkan_enc/ResourceTracker.h
index cd5aa13..86e4dde 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -107,6 +107,15 @@
         void* context,
         VkPhysicalDevice physicalDevice,
         VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+    void on_vkGetDeviceQueue(void* context,
+                             VkDevice device,
+                             uint32_t queueFamilyIndex,
+                             uint32_t queueIndex,
+                             VkQueue* pQueue);
+    void on_vkGetDeviceQueue2(void* context,
+                              VkDevice device,
+                              const VkDeviceQueueInfo2* pQueueInfo,
+                              VkQueue* pQueue);
 
     VkResult on_vkCreateInstance(
         void* context,
@@ -559,6 +568,13 @@
         VkDescriptorSetLayout descriptorSetLayout,
         const VkAllocationCallbacks* pAllocator);
 
+    VkResult on_vkAllocateCommandBuffers(
+        void* context,
+        VkResult input_result,
+        VkDevice device,
+        const VkCommandBufferAllocateInfo* pAllocateInfo,
+        VkCommandBuffer* pCommandBuffers);
+
     bool isMemoryTypeHostVisible(VkDevice device, uint32_t typeIndex) const;
     uint8_t* getMappedPointer(VkDeviceMemory memory);
     VkDeviceSize getMappedSize(VkDeviceMemory memory);
diff --git a/system/vulkan_enc/Resources.h b/system/vulkan_enc/Resources.h
index 74f41ee..67c498e 100644
--- a/system/vulkan_enc/Resources.h
+++ b/system/vulkan_enc/Resources.h
@@ -83,7 +83,7 @@
 #define GOLDFISH_VK_GET_HOST_U64_DECL(type) \
     uint64_t get_host_u64_##type(type);
 
-GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DEFINE_DISPATCHABLE_HANDLE_STRUCT)
+GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DEFINE_DISPATCHABLE_HANDLE_STRUCT)
 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_FROM_HOST_DECL)
 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_AS_GOLDFISH_DECL)
 GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_DECL)
@@ -116,6 +116,21 @@
     goldfish_vk::DescriptorSetLayoutInfo* layoutInfo;
 };
 
+struct goldfish_VkCommandBuffer {
+    hwvulkan_dispatch_t dispatch;
+    uint64_t underlying;
+    goldfish_vk::VkEncoder* lastUsedEncoder;
+    uint32_t sequenceNumber;
+    goldfish_vk::VkEncoder* privateEncoder;
+    IOStream* privateStream;
+    uint32_t flags;
+    struct goldfish_vk_object_list* poolObjects;
+    struct goldfish_vk_object_list* subObjects;
+    struct goldfish_vk_object_list* superObjects;
+    void* userPtr;
+    bool isSecondary;
+};
+
 } // extern "C"
 
 namespace goldfish_vk {
diff --git a/system/vulkan_enc/VkEncoder.cpp b/system/vulkan_enc/VkEncoder.cpp
index 27564ca..5660460 100644
--- a/system/vulkan_enc/VkEncoder.cpp
+++ b/system/vulkan_enc/VkEncoder.cpp
@@ -1629,6 +1629,8 @@
     stream->read((uint64_t*)&cgen_var_2, 8);
     stream->handleMapping()->mapHandles_u64_VkQueue(&cgen_var_2, (VkQueue*)pQueue, 1);
     stream->unsetHandleMapping();
+    sResourceTracker->on_vkGetDeviceQueue(this, device, queueFamilyIndex,
+                                          queueIndex, pQueue);
     ++encodeCount;;
     if (0 == encodeCount % POOL_CLEAR_INTERVAL)
     {
@@ -12209,6 +12211,7 @@
     uint64_t cgen_var_2;
     stream->read((uint64_t*)&cgen_var_2, 8);
     stream->handleMapping()->mapHandles_u64_VkQueue(&cgen_var_2, (VkQueue*)pQueue, 1);
+    sResourceTracker->on_vkGetDeviceQueue2(this, device, pQueueInfo, pQueue);
     ++encodeCount;;
     if (0 == encodeCount % POOL_CLEAR_INTERVAL)
     {
diff --git a/system/vulkan_enc/VulkanHandles.h b/system/vulkan_enc/VulkanHandles.h
index a233408..b0f4f6c 100644
--- a/system/vulkan_enc/VulkanHandles.h
+++ b/system/vulkan_enc/VulkanHandles.h
@@ -86,7 +86,6 @@
     f(VkBufferView) \
     f(VkImageView) \
     f(VkShaderModule) \
-    f(VkSampler) \
     f(VkPipeline) \
     f(VkPipelineCache) \
     f(VkPipelineLayout) \
@@ -118,6 +117,7 @@
     f(VkDescriptorSet) \
     f(VkDescriptorSetLayout) \
     f(VkCommandPool) \
+    f(VkSampler) \
     __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_FUCHSIA(f) \
     GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f) \
 
@@ -129,6 +129,12 @@
     GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f) \
     GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f)
 
+#define GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_DISPATCHABLE_HANDLE_TYPES(f) \
+    f(VkInstance) \
+    f(VkDevice) \
+    f(VkQueue) \
+    GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f)
+
 #define GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_NON_DISPATCHABLE_HANDLE_TYPES(f) \
     f(VkDeviceMemory) \
     f(VkBuffer) \
@@ -137,6 +143,7 @@
     f(VkFence) \
     f(VkDescriptorUpdateTemplate) \
     f(VkCommandPool) \
+    f(VkSampler) \
     __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_FUCHSIA(f) \
     GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f) \
 
diff --git a/system/vulkan_enc/func_table.cpp b/system/vulkan_enc/func_table.cpp
index b1b11b5..dc3f66d 100644
--- a/system/vulkan_enc/func_table.cpp
+++ b/system/vulkan_enc/func_table.cpp
@@ -1025,7 +1025,8 @@
     AEMU_SCOPED_TRACE("vkAllocateCommandBuffers");
     auto vkEnc = ResourceTracker::getThreadLocalEncoder();
     VkResult vkAllocateCommandBuffers_VkResult_return = (VkResult)0;
-    vkAllocateCommandBuffers_VkResult_return = vkEnc->vkAllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers, true /* do lock */);
+    auto resources = ResourceTracker::get();
+    vkAllocateCommandBuffers_VkResult_return = resources->on_vkAllocateCommandBuffers(vkEnc, VK_SUCCESS, device, pAllocateInfo, pCommandBuffers);
     if (vkAllocateCommandBuffers_VkResult_return == VK_SUCCESS) {
         ResourceTracker::get()->addToCommandPool(pAllocateInfo->commandPool, pAllocateInfo->commandBufferCount, pCommandBuffers);
     }
diff --git a/system/vulkan_enc/vk_struct_id.h b/system/vulkan_enc/vk_struct_id.h
index 33e15f3..5cfb795 100644
--- a/system/vulkan_enc/vk_struct_id.h
+++ b/system/vulkan_enc/vk_struct_id.h
@@ -55,5 +55,6 @@
 REGISTER_VK_STRUCT_ID(VkExternalImageFormatProperties, VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
 REGISTER_VK_STRUCT_ID(VkPhysicalDeviceImageFormatInfo2, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2);
 REGISTER_VK_STRUCT_ID(VkPhysicalDeviceExternalImageFormatInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO);
+REGISTER_VK_STRUCT_ID(VkSemaphoreTypeCreateInfo, VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO);
 
 #undef REGISTER_VK_STRUCT_ID