[vulkan] properly encode descriptor update template API (guest)

bug: 129149853

Guest side changes; takes codegen, arranges data to be consumed
by vkUpdateDescriptorSetWithTemplateSizedGOOGLE.

Change-Id: I1acc2ec7aae76dcd7a00ac1053df200a075d230e
diff --git a/system/vulkan/func_table.cpp b/system/vulkan/func_table.cpp
index d5ebf2d..1c74ac8 100644
--- a/system/vulkan/func_table.cpp
+++ b/system/vulkan/func_table.cpp
@@ -1754,7 +1754,8 @@
 {
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplate");
     auto vkEnc = HostConnection::get()->vkEncoder();
-    vkEnc->vkUpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData);
+    auto resources = ResourceTracker::get();
+    resources->on_vkUpdateDescriptorSetWithTemplate(vkEnc, device, descriptorSet, descriptorUpdateTemplate, pData);
 }
 static void entry_vkGetPhysicalDeviceExternalBufferProperties(
     VkPhysicalDevice physicalDevice,
@@ -3704,6 +3705,26 @@
     return vkRegisterBufferColorBufferGOOGLE_VkResult_return;
 }
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+static void entry_vkUpdateDescriptorSetWithTemplateSizedGOOGLE(
+    VkDevice device,
+    VkDescriptorSet descriptorSet,
+    VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+    uint32_t imageInfoCount,
+    uint32_t bufferInfoCount,
+    uint32_t bufferViewCount,
+    const uint32_t* pImageInfoEntryIndices,
+    const uint32_t* pBufferInfoEntryIndices,
+    const uint32_t* pBufferViewEntryIndices,
+    const VkDescriptorImageInfo* pImageInfos,
+    const VkDescriptorBufferInfo* pBufferInfos,
+    const VkBufferView* pBufferViews)
+{
+    AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateSizedGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    vkEnc->vkUpdateDescriptorSetWithTemplateSizedGOOGLE(device, descriptorSet, descriptorUpdateTemplate, imageInfoCount, bufferInfoCount, bufferViewCount, pImageInfoEntryIndices, pBufferInfoEntryIndices, pBufferViewEntryIndices, pImageInfos, pBufferInfos, pBufferViews);
+}
+#endif
 void* goldfish_vulkan_get_proc_address(const char* name){
 #ifdef VK_VERSION_1_0
     if (!strcmp(name, "vkCreateInstance"))
@@ -5115,6 +5136,12 @@
         return nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+    if (!strcmp(name, "vkUpdateDescriptorSetWithTemplateSizedGOOGLE"))
+    {
+        return nullptr;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name){
@@ -6685,6 +6712,13 @@
         return hasExt ? (void*)entry_vkRegisterBufferColorBufferGOOGLE : nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+    if (!strcmp(name, "vkUpdateDescriptorSetWithTemplateSizedGOOGLE"))
+    {
+        bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_sized_descriptor_update_template");
+        return hasExt ? (void*)entry_vkUpdateDescriptorSetWithTemplateSizedGOOGLE : nullptr;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name){
@@ -8255,6 +8289,13 @@
         return hasExt ? (void*)entry_vkRegisterBufferColorBufferGOOGLE : nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+    if (!strcmp(name, "vkUpdateDescriptorSetWithTemplateSizedGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_sized_descriptor_update_template");
+        return hasExt ? (void*)entry_vkUpdateDescriptorSetWithTemplateSizedGOOGLE : nullptr;
+    }
+#endif
     return nullptr;
 }
 
diff --git a/system/vulkan/func_table.h b/system/vulkan/func_table.h
index 3dbca4c..565b12a 100644
--- a/system/vulkan/func_table.h
+++ b/system/vulkan/func_table.h
@@ -280,6 +280,8 @@
 #endif
 #ifdef VK_GOOGLE_color_buffer
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+#endif
 void* goldfish_vulkan_get_proc_address(const char* name);
 void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name);
 void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name);
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index af1db37..24a46e1 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -288,6 +288,17 @@
         int syncFd = -1;
     };
 
+    struct VkDescriptorUpdateTemplate_Info {
+        std::vector<VkDescriptorUpdateTemplateEntry> templateEntries;
+
+        // Flattened versions
+        std::vector<uint32_t> imageInfoEntryIndices;
+        std::vector<uint32_t> bufferInfoEntryIndices;
+        std::vector<uint32_t> bufferViewEntryIndices;
+        std::vector<VkDescriptorImageInfo> imageInfos;
+        std::vector<VkDescriptorBufferInfo> bufferInfos;
+        std::vector<VkBufferView> bufferViews;
+    };
 
 #define HANDLE_REGISTER_IMPL_IMPL(type) \
     std::unordered_map<type, type##_Info> info_##type; \
@@ -398,6 +409,10 @@
         info_VkSemaphore.erase(sem);
     }
 
+    void unregister_VkDescriptorUpdateTemplate(VkDescriptorUpdateTemplate templ) {
+        info_VkDescriptorUpdateTemplate.erase(templ);
+    }
+
     // TODO: Upgrade to 1.1
     static constexpr uint32_t kMaxApiVersion = VK_MAKE_VERSION(1, 1, 0);
     static constexpr uint32_t kMinApiVersion = VK_MAKE_VERSION(1, 0, 0);
@@ -2788,6 +2803,185 @@
         return input_result;
     }
 
+    bool isDescriptorTypeImageInfo(VkDescriptorType descType) {
+        return (descType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
+               (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
+               (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
+               (descType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
+               (descType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
+    }
+
+    bool isDescriptorTypeBufferInfo(VkDescriptorType descType) {
+        return (descType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
+               (descType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
+               (descType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
+               (descType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC);
+    }
+
+    bool isDescriptorTypeBufferView(VkDescriptorType descType) {
+        return (descType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||
+               (descType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
+    }
+
+    VkResult initDescriptorUpdateTemplateBuffers(
+        const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+        VkDescriptorUpdateTemplate descriptorUpdateTemplate) {
+
+        AutoLock lock(mLock);
+
+        auto it = info_VkDescriptorUpdateTemplate.find(descriptorUpdateTemplate);
+        if (it == info_VkDescriptorUpdateTemplate.end()) {
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+
+        auto& info = it->second;
+
+        size_t imageInfosNeeded = 0;
+        size_t bufferInfosNeeded = 0;
+        size_t bufferViewsNeeded = 0;
+
+        for (uint32_t i = 0; i < pCreateInfo->descriptorUpdateEntryCount; ++i) {
+            const auto& entry = pCreateInfo->pDescriptorUpdateEntries[i];
+            uint32_t descCount = entry.descriptorCount;
+            VkDescriptorType descType = entry.descriptorType;
+
+            info.templateEntries.push_back(entry);
+
+            for (uint32_t j = 0; j < descCount; ++j) {
+                if (isDescriptorTypeImageInfo(descType)) {
+                    ++imageInfosNeeded;
+                    info.imageInfoEntryIndices.push_back(i);
+                } else if (isDescriptorTypeBufferInfo(descType)) {
+                    ++bufferInfosNeeded;
+                    info.bufferInfoEntryIndices.push_back(i);
+                } else if (isDescriptorTypeBufferView(descType)) {
+                    ++bufferViewsNeeded;
+                    info.bufferViewEntryIndices.push_back(i);
+                } else {
+                    ALOGE("%s: FATAL: Unknown descriptor type %d\n", __func__, descType);
+                    abort();
+                }
+            }
+        }
+
+        // To be filled in later (our flat structure)
+        info.imageInfos.resize(imageInfosNeeded);
+        info.bufferInfos.resize(bufferInfosNeeded);
+        info.bufferViews.resize(bufferViewsNeeded);
+
+        return VK_SUCCESS;
+    }
+
+    VkResult on_vkCreateDescriptorUpdateTemplate(
+        void* context, VkResult input_result,
+        VkDevice device,
+        const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+
+        (void)context;
+        (void)device;
+        (void)pAllocator;
+
+        if (input_result != VK_SUCCESS) return input_result;
+
+        return initDescriptorUpdateTemplateBuffers(pCreateInfo, *pDescriptorUpdateTemplate);
+    }
+
+    VkResult on_vkCreateDescriptorUpdateTemplateKHR(
+        void* context, VkResult input_result,
+        VkDevice device,
+        const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+
+        (void)context;
+        (void)device;
+        (void)pAllocator;
+
+        if (input_result != VK_SUCCESS) return input_result;
+
+        return initDescriptorUpdateTemplateBuffers(pCreateInfo, *pDescriptorUpdateTemplate);
+    }
+
+    void on_vkUpdateDescriptorSetWithTemplate(
+        void* context,
+        VkDevice device,
+        VkDescriptorSet descriptorSet,
+        VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+        const void* pData) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+
+        uint8_t* userBuffer = (uint8_t*)pData;
+        if (!userBuffer) return;
+
+        AutoLock lock(mLock);
+
+        auto it = info_VkDescriptorUpdateTemplate.find(descriptorUpdateTemplate);
+        if (it == info_VkDescriptorUpdateTemplate.end()) {
+            return;
+        }
+
+        auto& info = it->second;
+
+        size_t currImageInfoOffset = 0;
+        size_t currBufferInfoOffset = 0;
+        size_t currBufferViewOffset = 0;
+
+        for (const auto& entry : info.templateEntries) {
+            VkDescriptorType descType = entry.descriptorType;
+
+            auto offset = entry.offset;
+            auto stride = entry.stride;
+
+            uint32_t descCount = entry.descriptorCount;
+
+            if (isDescriptorTypeImageInfo(descType)) {
+                if (!stride) stride = sizeof(VkDescriptorImageInfo);
+                for (uint32_t j = 0; j < descCount; ++j) {
+                    memcpy(((uint8_t*)info.imageInfos.data()) + currImageInfoOffset,
+                           userBuffer + offset + j * stride,
+                           sizeof(VkDescriptorImageInfo));
+                    currImageInfoOffset += sizeof(VkDescriptorImageInfo);
+                }
+            } else if (isDescriptorTypeBufferInfo(descType)) {
+                if (!stride) stride = sizeof(VkDescriptorBufferInfo);
+                for (uint32_t j = 0; j < descCount; ++j) {
+                    memcpy(((uint8_t*)info.bufferInfos.data()) + currBufferInfoOffset,
+                           userBuffer + offset + j * stride,
+                           sizeof(VkDescriptorBufferInfo));
+                    currBufferInfoOffset += sizeof(VkDescriptorBufferInfo);
+                }
+            } else if (isDescriptorTypeBufferView(descType)) {
+                if (!stride) stride = sizeof(VkBufferView);
+                for (uint32_t j = 0; j < descCount; ++j) {
+                    memcpy(((uint8_t*)info.bufferViews.data()) + currBufferViewOffset,
+                           userBuffer + offset + j * stride,
+                           sizeof(VkBufferView));
+                    currBufferViewOffset += sizeof(VkBufferView);
+                }
+            } else {
+                ALOGE("%s: FATAL: Unknown descriptor type %d\n", __func__, descType);
+                abort();
+            }
+        }
+
+        enc->vkUpdateDescriptorSetWithTemplateSizedGOOGLE(
+            device,
+            descriptorSet,
+            descriptorUpdateTemplate,
+            (uint32_t)info.imageInfos.size(),
+            (uint32_t)info.bufferInfos.size(),
+            (uint32_t)info.bufferViews.size(),
+            info.imageInfoEntryIndices.data(),
+            info.bufferInfoEntryIndices.data(),
+            info.bufferViewEntryIndices.data(),
+            info.imageInfos.data(),
+            info.bufferInfos.data(),
+            info.bufferViews.data());
+    }
+
     uint32_t getApiVersionFromInstance(VkInstance instance) const {
         AutoLock lock(mLock);
         uint32_t api = kMinApiVersion;
@@ -3353,6 +3547,39 @@
         context, input_result, device, memory, pAddress);
 }
 
+VkResult ResourceTracker::on_vkCreateDescriptorUpdateTemplate(
+    void* context, VkResult input_result,
+    VkDevice device,
+    const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+    return mImpl->on_vkCreateDescriptorUpdateTemplate(
+        context, input_result,
+        device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+}
+
+VkResult ResourceTracker::on_vkCreateDescriptorUpdateTemplateKHR(
+    void* context, VkResult input_result,
+    VkDevice device,
+    const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+    return mImpl->on_vkCreateDescriptorUpdateTemplateKHR(
+        context, input_result,
+        device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+}
+
+void ResourceTracker::on_vkUpdateDescriptorSetWithTemplate(
+    void* context,
+    VkDevice device,
+    VkDescriptorSet descriptorSet,
+    VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+    const void* pData) {
+    mImpl->on_vkUpdateDescriptorSetWithTemplate(
+        context, device, descriptorSet,
+        descriptorUpdateTemplate, pData);
+}
+
 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 a26c3a2..830537f 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -288,6 +288,27 @@
         VkDeviceMemory memory,
         uint64_t* pAddress);
 
+    VkResult on_vkCreateDescriptorUpdateTemplate(
+        void* context, VkResult input_result,
+        VkDevice device,
+        const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+
+    VkResult on_vkCreateDescriptorUpdateTemplateKHR(
+        void* context, VkResult input_result,
+        VkDevice device,
+        const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+
+    void on_vkUpdateDescriptorSetWithTemplate(
+        void* context,
+        VkDevice device,
+        VkDescriptorSet descriptorSet,
+        VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+        const void* pData);
+
     bool isMemoryTypeHostVisible(VkDevice device, uint32_t typeIndex) const;
     uint8_t* getMappedPointer(VkDeviceMemory memory);
     VkDeviceSize getMappedSize(VkDeviceMemory memory);
diff --git a/system/vulkan_enc/VkEncoder.cpp b/system/vulkan_enc/VkEncoder.cpp
index 4261d71..8f38e54 100644
--- a/system/vulkan_enc/VkEncoder.cpp
+++ b/system/vulkan_enc/VkEncoder.cpp
@@ -11086,6 +11086,7 @@
     countingStream->clearPool();
     stream->clearPool();
     pool->freeAll();
+    mImpl->resources()->on_vkCreateDescriptorUpdateTemplate(this, vkCreateDescriptorUpdateTemplate_VkResult_return, device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
     mImpl->log("finish vkCreateDescriptorUpdateTemplate");;
     return vkCreateDescriptorUpdateTemplate_VkResult_return;
 }
@@ -15676,6 +15677,7 @@
     countingStream->clearPool();
     stream->clearPool();
     pool->freeAll();
+    mImpl->resources()->on_vkCreateDescriptorUpdateTemplateKHR(this, vkCreateDescriptorUpdateTemplateKHR_VkResult_return, device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
     mImpl->log("finish vkCreateDescriptorUpdateTemplateKHR");;
     return vkCreateDescriptorUpdateTemplateKHR_VkResult_return;
 }
@@ -22261,5 +22263,243 @@
 }
 
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+void VkEncoder::vkUpdateDescriptorSetWithTemplateSizedGOOGLE(
+    VkDevice device,
+    VkDescriptorSet descriptorSet,
+    VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+    uint32_t imageInfoCount,
+    uint32_t bufferInfoCount,
+    uint32_t bufferViewCount,
+    const uint32_t* pImageInfoEntryIndices,
+    const uint32_t* pBufferInfoEntryIndices,
+    const uint32_t* pBufferViewEntryIndices,
+    const VkDescriptorImageInfo* pImageInfos,
+    const VkDescriptorBufferInfo* pBufferInfos,
+    const VkBufferView* pBufferViews)
+{
+    AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateSizedGOOGLE encode");
+    mImpl->log("start vkUpdateDescriptorSetWithTemplateSizedGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkDevice local_device;
+    VkDescriptorSet local_descriptorSet;
+    VkDescriptorUpdateTemplate local_descriptorUpdateTemplate;
+    uint32_t local_imageInfoCount;
+    uint32_t local_bufferInfoCount;
+    uint32_t local_bufferViewCount;
+    uint32_t* local_pImageInfoEntryIndices;
+    uint32_t* local_pBufferInfoEntryIndices;
+    uint32_t* local_pBufferViewEntryIndices;
+    VkDescriptorImageInfo* local_pImageInfos;
+    VkDescriptorBufferInfo* local_pBufferInfos;
+    VkBufferView* local_pBufferViews;
+    local_device = device;
+    local_descriptorSet = descriptorSet;
+    local_descriptorUpdateTemplate = descriptorUpdateTemplate;
+    local_imageInfoCount = imageInfoCount;
+    local_bufferInfoCount = bufferInfoCount;
+    local_bufferViewCount = bufferViewCount;
+    local_pImageInfoEntryIndices = nullptr;
+    if (pImageInfoEntryIndices)
+    {
+        local_pImageInfoEntryIndices = (uint32_t*)pool->dupArray(pImageInfoEntryIndices, ((imageInfoCount)) * sizeof(const uint32_t));
+    }
+    local_pBufferInfoEntryIndices = nullptr;
+    if (pBufferInfoEntryIndices)
+    {
+        local_pBufferInfoEntryIndices = (uint32_t*)pool->dupArray(pBufferInfoEntryIndices, ((bufferInfoCount)) * sizeof(const uint32_t));
+    }
+    local_pBufferViewEntryIndices = nullptr;
+    if (pBufferViewEntryIndices)
+    {
+        local_pBufferViewEntryIndices = (uint32_t*)pool->dupArray(pBufferViewEntryIndices, ((bufferViewCount)) * sizeof(const uint32_t));
+    }
+    local_pImageInfos = nullptr;
+    if (pImageInfos)
+    {
+        local_pImageInfos = (VkDescriptorImageInfo*)pool->alloc(((imageInfoCount)) * sizeof(const VkDescriptorImageInfo));
+        for (uint32_t i = 0; i < (uint32_t)((imageInfoCount)); ++i)
+        {
+            deepcopy_VkDescriptorImageInfo(pool, pImageInfos + i, (VkDescriptorImageInfo*)(local_pImageInfos + i));
+        }
+    }
+    local_pBufferInfos = nullptr;
+    if (pBufferInfos)
+    {
+        local_pBufferInfos = (VkDescriptorBufferInfo*)pool->alloc(((bufferInfoCount)) * sizeof(const VkDescriptorBufferInfo));
+        for (uint32_t i = 0; i < (uint32_t)((bufferInfoCount)); ++i)
+        {
+            deepcopy_VkDescriptorBufferInfo(pool, pBufferInfos + i, (VkDescriptorBufferInfo*)(local_pBufferInfos + i));
+        }
+    }
+    local_pBufferViews = nullptr;
+    if (pBufferViews)
+    {
+        local_pBufferViews = (VkBufferView*)pool->dupArray(pBufferViews, ((bufferViewCount)) * sizeof(const VkBufferView));
+    }
+    if (local_pImageInfos)
+    {
+        for (uint32_t i = 0; i < (uint32_t)((imageInfoCount)); ++i)
+        {
+            transform_tohost_VkDescriptorImageInfo(mImpl->resources(), (VkDescriptorImageInfo*)(local_pImageInfos + i));
+        }
+    }
+    if (local_pBufferInfos)
+    {
+        for (uint32_t i = 0; i < (uint32_t)((bufferInfoCount)); ++i)
+        {
+            transform_tohost_VkDescriptorBufferInfo(mImpl->resources(), (VkDescriptorBufferInfo*)(local_pBufferInfos + i));
+        }
+    }
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1488;
+        countingStream->handleMapping()->mapHandles_VkDevice_u64(&local_device, &cgen_var_1488, 1);
+        countingStream->write((uint64_t*)&cgen_var_1488, 1 * 8);
+        uint64_t cgen_var_1489;
+        countingStream->handleMapping()->mapHandles_VkDescriptorSet_u64(&local_descriptorSet, &cgen_var_1489, 1);
+        countingStream->write((uint64_t*)&cgen_var_1489, 1 * 8);
+        uint64_t cgen_var_1490;
+        countingStream->handleMapping()->mapHandles_VkDescriptorUpdateTemplate_u64(&local_descriptorUpdateTemplate, &cgen_var_1490, 1);
+        countingStream->write((uint64_t*)&cgen_var_1490, 1 * 8);
+        countingStream->write((uint32_t*)&local_imageInfoCount, sizeof(uint32_t));
+        countingStream->write((uint32_t*)&local_bufferInfoCount, sizeof(uint32_t));
+        countingStream->write((uint32_t*)&local_bufferViewCount, sizeof(uint32_t));
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1491 = (uint64_t)(uintptr_t)local_pImageInfoEntryIndices;
+        countingStream->putBe64(cgen_var_1491);
+        if (local_pImageInfoEntryIndices)
+        {
+            countingStream->write((uint32_t*)local_pImageInfoEntryIndices, ((imageInfoCount)) * sizeof(uint32_t));
+        }
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1492 = (uint64_t)(uintptr_t)local_pBufferInfoEntryIndices;
+        countingStream->putBe64(cgen_var_1492);
+        if (local_pBufferInfoEntryIndices)
+        {
+            countingStream->write((uint32_t*)local_pBufferInfoEntryIndices, ((bufferInfoCount)) * sizeof(uint32_t));
+        }
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1493 = (uint64_t)(uintptr_t)local_pBufferViewEntryIndices;
+        countingStream->putBe64(cgen_var_1493);
+        if (local_pBufferViewEntryIndices)
+        {
+            countingStream->write((uint32_t*)local_pBufferViewEntryIndices, ((bufferViewCount)) * sizeof(uint32_t));
+        }
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1494 = (uint64_t)(uintptr_t)local_pImageInfos;
+        countingStream->putBe64(cgen_var_1494);
+        if (local_pImageInfos)
+        {
+            for (uint32_t i = 0; i < (uint32_t)((imageInfoCount)); ++i)
+            {
+                marshal_VkDescriptorImageInfo(countingStream, (VkDescriptorImageInfo*)(local_pImageInfos + i));
+            }
+        }
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1495 = (uint64_t)(uintptr_t)local_pBufferInfos;
+        countingStream->putBe64(cgen_var_1495);
+        if (local_pBufferInfos)
+        {
+            for (uint32_t i = 0; i < (uint32_t)((bufferInfoCount)); ++i)
+            {
+                marshal_VkDescriptorBufferInfo(countingStream, (VkDescriptorBufferInfo*)(local_pBufferInfos + i));
+            }
+        }
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1496 = (uint64_t)(uintptr_t)local_pBufferViews;
+        countingStream->putBe64(cgen_var_1496);
+        if (local_pBufferViews)
+        {
+            if (((bufferViewCount)))
+            {
+                uint64_t* cgen_var_1497;
+                countingStream->alloc((void**)&cgen_var_1497, ((bufferViewCount)) * 8);
+                countingStream->handleMapping()->mapHandles_VkBufferView_u64(local_pBufferViews, cgen_var_1497, ((bufferViewCount)));
+                countingStream->write((uint64_t*)cgen_var_1497, ((bufferViewCount)) * 8);
+            }
+        }
+    }
+    uint32_t packetSize_vkUpdateDescriptorSetWithTemplateSizedGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkUpdateDescriptorSetWithTemplateSizedGOOGLE = OP_vkUpdateDescriptorSetWithTemplateSizedGOOGLE;
+    stream->write(&opcode_vkUpdateDescriptorSetWithTemplateSizedGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkUpdateDescriptorSetWithTemplateSizedGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1498;
+    stream->handleMapping()->mapHandles_VkDevice_u64(&local_device, &cgen_var_1498, 1);
+    stream->write((uint64_t*)&cgen_var_1498, 1 * 8);
+    uint64_t cgen_var_1499;
+    stream->handleMapping()->mapHandles_VkDescriptorSet_u64(&local_descriptorSet, &cgen_var_1499, 1);
+    stream->write((uint64_t*)&cgen_var_1499, 1 * 8);
+    uint64_t cgen_var_1500;
+    stream->handleMapping()->mapHandles_VkDescriptorUpdateTemplate_u64(&local_descriptorUpdateTemplate, &cgen_var_1500, 1);
+    stream->write((uint64_t*)&cgen_var_1500, 1 * 8);
+    stream->write((uint32_t*)&local_imageInfoCount, sizeof(uint32_t));
+    stream->write((uint32_t*)&local_bufferInfoCount, sizeof(uint32_t));
+    stream->write((uint32_t*)&local_bufferViewCount, sizeof(uint32_t));
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1501 = (uint64_t)(uintptr_t)local_pImageInfoEntryIndices;
+    stream->putBe64(cgen_var_1501);
+    if (local_pImageInfoEntryIndices)
+    {
+        stream->write((uint32_t*)local_pImageInfoEntryIndices, ((imageInfoCount)) * sizeof(uint32_t));
+    }
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1502 = (uint64_t)(uintptr_t)local_pBufferInfoEntryIndices;
+    stream->putBe64(cgen_var_1502);
+    if (local_pBufferInfoEntryIndices)
+    {
+        stream->write((uint32_t*)local_pBufferInfoEntryIndices, ((bufferInfoCount)) * sizeof(uint32_t));
+    }
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1503 = (uint64_t)(uintptr_t)local_pBufferViewEntryIndices;
+    stream->putBe64(cgen_var_1503);
+    if (local_pBufferViewEntryIndices)
+    {
+        stream->write((uint32_t*)local_pBufferViewEntryIndices, ((bufferViewCount)) * sizeof(uint32_t));
+    }
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1504 = (uint64_t)(uintptr_t)local_pImageInfos;
+    stream->putBe64(cgen_var_1504);
+    if (local_pImageInfos)
+    {
+        for (uint32_t i = 0; i < (uint32_t)((imageInfoCount)); ++i)
+        {
+            marshal_VkDescriptorImageInfo(stream, (VkDescriptorImageInfo*)(local_pImageInfos + i));
+        }
+    }
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1505 = (uint64_t)(uintptr_t)local_pBufferInfos;
+    stream->putBe64(cgen_var_1505);
+    if (local_pBufferInfos)
+    {
+        for (uint32_t i = 0; i < (uint32_t)((bufferInfoCount)); ++i)
+        {
+            marshal_VkDescriptorBufferInfo(stream, (VkDescriptorBufferInfo*)(local_pBufferInfos + i));
+        }
+    }
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1506 = (uint64_t)(uintptr_t)local_pBufferViews;
+    stream->putBe64(cgen_var_1506);
+    if (local_pBufferViews)
+    {
+        if (((bufferViewCount)))
+        {
+            uint64_t* cgen_var_1507;
+            stream->alloc((void**)&cgen_var_1507, ((bufferViewCount)) * 8);
+            stream->handleMapping()->mapHandles_VkBufferView_u64(local_pBufferViews, cgen_var_1507, ((bufferViewCount)));
+            stream->write((uint64_t*)cgen_var_1507, ((bufferViewCount)) * 8);
+        }
+    }
+    AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateSizedGOOGLE readParams");
+    AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateSizedGOOGLE returnUnmarshal");
+    mImpl->log("finish vkUpdateDescriptorSetWithTemplateSizedGOOGLE");;
+}
+
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/VkEncoder.h b/system/vulkan_enc/VkEncoder.h
index 2e72833..36b768c 100644
--- a/system/vulkan_enc/VkEncoder.h
+++ b/system/vulkan_enc/VkEncoder.h
@@ -1757,6 +1757,21 @@
         VkBuffer buffer,
         uint32_t colorBuffer);
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+    void vkUpdateDescriptorSetWithTemplateSizedGOOGLE(
+    VkDevice device,
+        VkDescriptorSet descriptorSet,
+        VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+        uint32_t imageInfoCount,
+        uint32_t bufferInfoCount,
+        uint32_t bufferViewCount,
+        const uint32_t* pImageInfoEntryIndices,
+        const uint32_t* pBufferInfoEntryIndices,
+        const uint32_t* pBufferViewEntryIndices,
+        const VkDescriptorImageInfo* pImageInfos,
+        const VkDescriptorBufferInfo* pBufferInfos,
+        const VkBufferView* pBufferViews);
+#endif
 
 private:
     class Impl;
diff --git a/system/vulkan_enc/VulkanHandles.h b/system/vulkan_enc/VulkanHandles.h
index 2320072..481e601 100644
--- a/system/vulkan_enc/VulkanHandles.h
+++ b/system/vulkan_enc/VulkanHandles.h
@@ -44,7 +44,6 @@
     f(VkEvent) \
     f(VkQueryPool) \
     f(VkSamplerYcbcrConversion) \
-    f(VkDescriptorUpdateTemplate) \
     f(VkSurfaceKHR) \
     f(VkSwapchainKHR) \
     f(VkDisplayKHR) \
@@ -60,6 +59,7 @@
     f(VkBuffer) \
     f(VkImage) \
     f(VkSemaphore) \
+    f(VkDescriptorUpdateTemplate) \
     GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f) \
 
 #define GOLDFISH_VK_LIST_HANDLE_TYPES(f) \
diff --git a/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp b/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
index 0478e91..962a6be 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
@@ -6380,6 +6380,8 @@
 }
 
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+#endif
 void deepcopy_extension_struct(
     Pool* pool,
     const void* structExtension,
diff --git a/system/vulkan_enc/goldfish_vk_deepcopy_guest.h b/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
index 6b73d1f..fbddca8 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
@@ -2022,5 +2022,7 @@
     VkImportPhysicalAddressGOOGLE* to);
 
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp b/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
index 0457642..ffe1af5 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
@@ -278,6 +278,8 @@
 #endif
 #ifdef VK_GOOGLE_color_buffer
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+#endif
 uint32_t goldfish_vk_struct_type(
     const void* structExtension)
 {
diff --git a/system/vulkan_enc/goldfish_vk_extension_structs_guest.h b/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
index 9d09bb8..1d9c327 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
@@ -295,5 +295,7 @@
 #endif
 #ifdef VK_GOOGLE_color_buffer
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp b/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
index 0bc0419..3110cb5 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
@@ -4744,6 +4744,8 @@
 }
 
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+#endif
 void handlemap_extension_struct(
     VulkanHandleMapping* handlemap,
     void* structExtension_out)
diff --git a/system/vulkan_enc/goldfish_vk_handlemap_guest.h b/system/vulkan_enc/goldfish_vk_handlemap_guest.h
index c9678d4..8fc6584 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.h
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.h
@@ -1675,5 +1675,7 @@
     VkImportPhysicalAddressGOOGLE* toMap);
 
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp b/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
index 0c12dfb..77d3be3 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
@@ -13329,6 +13329,8 @@
 }
 
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+#endif
 void marshal_extension_struct(
     VulkanStreamGuest* vkStream,
     const void* structExtension)
diff --git a/system/vulkan_enc/goldfish_vk_marshaling_guest.h b/system/vulkan_enc/goldfish_vk_marshaling_guest.h
index 5d04b41..0a908d9 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.h
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.h
@@ -3381,5 +3381,8 @@
 #define OP_vkRegisterImageColorBufferGOOGLE 20318
 #define OP_vkRegisterBufferColorBufferGOOGLE 20319
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+#define OP_vkUpdateDescriptorSetWithTemplateSizedGOOGLE 20320
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/goldfish_vk_private_defs.h b/system/vulkan_enc/goldfish_vk_private_defs.h
index 9ace1d1..89a355e 100644
--- a/system/vulkan_enc/goldfish_vk_private_defs.h
+++ b/system/vulkan_enc/goldfish_vk_private_defs.h
@@ -400,6 +400,20 @@
 
 #endif // __Fuchsia__
 
+#define VK_GOOGLE_sized_descriptor_update_template 1
+
+typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateSizedGOOGLE)(
+    VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+    uint32_t imageInfoCount,
+    uint32_t bufferInfoCount,
+    uint32_t bufferViewCount,
+    const uint32_t* pImageInfoEntryIndices,
+    const uint32_t* pBufferInfoEntryIndices,
+    const uint32_t* pBufferViewEntryIndices,
+    const VkDescriptorImageInfo* pImageInfos,
+    const VkDescriptorBufferInfo* pBufferInfos,
+    const VkBufferView* pBufferViews);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/system/vulkan_enc/goldfish_vk_transform_guest.cpp b/system/vulkan_enc/goldfish_vk_transform_guest.cpp
index 9ef029b..2c651db 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.cpp
@@ -8941,6 +8941,8 @@
 }
 
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+#endif
 void transform_tohost_extension_struct(
     ResourceTracker* resourceTracker,
     void* structExtension_out)
diff --git a/system/vulkan_enc/goldfish_vk_transform_guest.h b/system/vulkan_enc/goldfish_vk_transform_guest.h
index c7fb7d0..0f7aea5 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.h
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.h
@@ -3063,5 +3063,7 @@
     VkImportPhysicalAddressGOOGLE* toTransform);
 
 #endif
+#ifdef VK_GOOGLE_sized_descriptor_update_template
+#endif
 
 } // namespace goldfish_vk