vulkan: suppress sampler field of VkDescriptorImageInfo (guest)

when in the immutable sampler case.

Test: vulkanhal_unittests (needs host side CL)
dEQP-VK.ycbcr* in 64 bit mode
dEQP-VK.binding_model*

bug: 145153816
Merged-In: Id501fc5a383d5519dd99886b5dd43b6057034b15
Change-Id: I84fd8b4f2630b86e80da987b3e010824392599c3
diff --git a/system/vulkan/func_table.cpp b/system/vulkan/func_table.cpp
index 4e02b93..3f77e85 100644
--- a/system/vulkan/func_table.cpp
+++ b/system/vulkan/func_table.cpp
@@ -845,7 +845,8 @@
     AEMU_SCOPED_TRACE("vkCreateDescriptorSetLayout");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkCreateDescriptorSetLayout_VkResult_return = (VkResult)0;
-    vkCreateDescriptorSetLayout_VkResult_return = vkEnc->vkCreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
+    auto resources = ResourceTracker::get();
+    vkCreateDescriptorSetLayout_VkResult_return = resources->on_vkCreateDescriptorSetLayout(vkEnc, VK_SUCCESS, device, pCreateInfo, pAllocator, pSetLayout);
     return vkCreateDescriptorSetLayout_VkResult_return;
 }
 static void entry_vkDestroyDescriptorSetLayout(
@@ -926,7 +927,8 @@
 {
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSets");
     auto vkEnc = HostConnection::get()->vkEncoder();
-    vkEnc->vkUpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
+    auto resources = ResourceTracker::get();
+    resources->on_vkUpdateDescriptorSets(vkEnc, device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
 }
 static VkResult entry_vkCreateFramebuffer(
     VkDevice device,
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index 077ea3c..7fa35b9 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -335,6 +335,11 @@
 
     struct VkDescriptorSet_Info {
         VkDescriptorPool pool;
+        std::vector<bool> bindingIsImmutableSampler;
+    };
+
+    struct VkDescriptorSetLayout_Info {
+        std::vector<VkDescriptorSetLayoutBinding> bindings;
     };
 
 #define HANDLE_REGISTER_IMPL_IMPL(type) \
@@ -499,7 +504,12 @@
         unregister_VkDescriptorSet_locked(set);
     }
 
-    void addAllocedDescriptorSetsToPoolLocked(const VkDescriptorSetAllocateInfo* ci, const VkDescriptorSet* sets) {
+    void unregister_VkDescriptorSetLayout(VkDescriptorSetLayout setLayout) {
+        AutoLock lock(mLock);
+        info_VkDescriptorSetLayout.erase(setLayout);
+    }
+
+    void initDescriptorSetStateLocked(const VkDescriptorSetAllocateInfo* ci, const VkDescriptorSet* sets) {
         auto it = info_VkDescriptorPool.find(ci->descriptorPool);
         if (it == info_VkDescriptorPool.end()) return;
 
@@ -512,9 +522,67 @@
 
             auto& setInfo = setIt->second;
             setInfo.pool = ci->descriptorPool;
+
+            VkDescriptorSetLayout setLayout = ci->pSetLayouts[i];
+            auto layoutIt = info_VkDescriptorSetLayout.find(setLayout);
+            if (layoutIt == info_VkDescriptorSetLayout.end()) continue;
+
+            const auto& layoutInfo = layoutIt->second;
+            for (size_t i = 0; i < layoutInfo.bindings.size(); ++i) {
+                // Bindings can be sparsely defined
+                const auto& binding = layoutInfo.bindings[i];
+                uint32_t bindingIndex = binding.binding;
+                if (setInfo.bindingIsImmutableSampler.size() <= bindingIndex) {
+                    setInfo.bindingIsImmutableSampler.resize(bindingIndex + 1, false);
+                }
+                setInfo.bindingIsImmutableSampler[bindingIndex] =
+                    binding.descriptorCount > 0 &&
+                     (binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
+                      binding.descriptorType ==
+                          VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
+                    binding.pImmutableSamplers;
+            }
         }
     }
 
+    VkWriteDescriptorSet
+    createImmutableSamplersFilteredWriteDescriptorSetLocked(
+        const VkWriteDescriptorSet* descriptorWrite,
+        std::vector<VkDescriptorImageInfo>* imageInfoArray) {
+
+        VkWriteDescriptorSet res = *descriptorWrite;
+
+        if  (descriptorWrite->descriptorCount == 0) return res;
+
+        if  (descriptorWrite->descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER &&
+             descriptorWrite->descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) return res;
+
+        VkDescriptorSet set = descriptorWrite->dstSet;
+        auto descSetIt = info_VkDescriptorSet.find(set);
+        if (descSetIt == info_VkDescriptorSet.end()) {
+            ALOGE("%s: error: descriptor set 0x%llx not found\n", __func__,
+                  (unsigned long long)set);
+            return res;
+        }
+
+        const auto& descInfo = descSetIt->second;
+        uint32_t binding = descriptorWrite->dstBinding;
+
+        bool immutableSampler = descInfo.bindingIsImmutableSampler[binding];
+
+        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);
+        }
+
+        res.pImageInfo = imageInfoArray->data();
+
+        return res;
+    }
+
     // Also unregisters underlying descriptor sets
     // and deletes their guest-side wrapped handles.
     void clearDescriptorPoolLocked(VkDescriptorPool pool) {
@@ -3150,7 +3218,7 @@
         if (res != VK_SUCCESS) return res;
 
         AutoLock lock(mLock);
-        addAllocedDescriptorSetsToPoolLocked(pAllocateInfo, pDescriptorSets);
+        initDescriptorSetStateLocked(pAllocateInfo, pDescriptorSets);
         return res;
     }
 
@@ -3191,6 +3259,64 @@
             toActuallyFree.data());
     }
 
+    VkResult on_vkCreateDescriptorSetLayout(
+        void* context,
+        VkResult,
+        VkDevice device,
+        const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkDescriptorSetLayout* pSetLayout) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+
+        VkResult res = enc->vkCreateDescriptorSetLayout(
+            device, pCreateInfo, pAllocator, pSetLayout);
+
+        if (res != VK_SUCCESS) return res;
+
+        AutoLock lock(mLock);
+
+        auto it = info_VkDescriptorSetLayout.find(*pSetLayout);
+        if (it == info_VkDescriptorSetLayout.end()) return res;
+
+        auto& info = it->second;
+        for (uint32_t i = 0; i < pCreateInfo->bindingCount; ++i) {
+            info.bindings.push_back(pCreateInfo->pBindings[i]);
+        }
+
+        return res;
+    }
+
+    void on_vkUpdateDescriptorSets(
+        void* context,
+        VkDevice device,
+        uint32_t descriptorWriteCount,
+        const VkWriteDescriptorSet* pDescriptorWrites,
+        uint32_t descriptorCopyCount,
+        const VkCopyDescriptorSet* pDescriptorCopies) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+
+        std::vector<std::vector<VkDescriptorImageInfo>> imageInfosPerWrite(
+            descriptorWriteCount);
+
+        std::vector<VkWriteDescriptorSet> writesWithSuppressedSamplers;
+
+        {
+            AutoLock lock(mLock);
+            for (uint32_t i = 0; i < descriptorWriteCount; ++i) {
+                writesWithSuppressedSamplers.push_back(
+                    createImmutableSamplersFilteredWriteDescriptorSetLocked(
+                        pDescriptorWrites + i,
+                        imageInfosPerWrite.data() + i));
+            }
+        }
+
+        enc->vkUpdateDescriptorSets(
+            device, descriptorWriteCount, writesWithSuppressedSamplers.data(),
+            descriptorCopyCount, pDescriptorCopies);
+    }
+
     void on_vkDestroyImage(
         void* context,
         VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
@@ -4977,6 +5103,28 @@
         context, input_result, device, descriptorPool, descriptorSetCount, pDescriptorSets);
 }
 
+VkResult ResourceTracker::on_vkCreateDescriptorSetLayout(
+    void* context,
+    VkResult input_result,
+    VkDevice device,
+    const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkDescriptorSetLayout* pSetLayout) {
+    return mImpl->on_vkCreateDescriptorSetLayout(
+        context, input_result, device, pCreateInfo, pAllocator, pSetLayout);
+}
+
+void ResourceTracker::on_vkUpdateDescriptorSets(
+    void* context,
+    VkDevice device,
+    uint32_t descriptorWriteCount,
+    const VkWriteDescriptorSet* pDescriptorWrites,
+    uint32_t descriptorCopyCount,
+    const VkCopyDescriptorSet* pDescriptorCopies) {
+    return mImpl->on_vkUpdateDescriptorSets(
+        context, device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
+}
+
 VkResult ResourceTracker::on_vkMapMemoryIntoAddressSpaceGOOGLE_pre(
     void* context,
     VkResult input_result,
diff --git a/system/vulkan_enc/ResourceTracker.h b/system/vulkan_enc/ResourceTracker.h
index 97abb0f..9a72bdf 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -399,6 +399,22 @@
         uint32_t                                    descriptorSetCount,
         const VkDescriptorSet*                      pDescriptorSets);
 
+    VkResult on_vkCreateDescriptorSetLayout(
+        void* context,
+        VkResult input_result,
+        VkDevice device,
+        const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkDescriptorSetLayout* pSetLayout);
+
+    void on_vkUpdateDescriptorSets(
+        void* context,
+        VkDevice device,
+        uint32_t descriptorWriteCount,
+        const VkWriteDescriptorSet* pDescriptorWrites,
+        uint32_t descriptorCopyCount,
+        const VkCopyDescriptorSet* pDescriptorCopies);
+
     VkResult on_vkMapMemoryIntoAddressSpaceGOOGLE_pre(
         void* context,
         VkResult input_result,
diff --git a/system/vulkan_enc/VulkanHandles.h b/system/vulkan_enc/VulkanHandles.h
index 3a0f4eb..376f2fc 100644
--- a/system/vulkan_enc/VulkanHandles.h
+++ b/system/vulkan_enc/VulkanHandles.h
@@ -30,7 +30,6 @@
     f(VkBufferView) \
     f(VkImageView) \
     f(VkShaderModule) \
-    f(VkDescriptorSetLayout) \
     f(VkSampler) \
     f(VkPipeline) \
     f(VkPipelineCache) \
@@ -60,6 +59,7 @@
     f(VkFence) \
     f(VkDescriptorPool) \
     f(VkDescriptorSet) \
+    f(VkDescriptorSetLayout) \
     GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f) \
 
 #define GOLDFISH_VK_LIST_HANDLE_TYPES(f) \