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


#include "abort_exception.h"
#include "vulkan_imports.h"
#include "vulkan_types.h"

#include "vulkan_spy.h"

#include <gapic/log.h>
#include <gapic/coder/memory.h>
#include <gapic/coder/atom.h>
#include <gapic/coder/vulkan.h>

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

#include <stdint.h>

#include <memory>
#include <string>

namespace gapii {

uint32_t VulkanSpy::vkCreateAndroidSurfaceKHR(VkInstance instance, VkAndroidSurfaceCreateInfoKHR* pCreateInfo, VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
    GAPID_DEBUG("vkCreateAndroidSurfaceKHR(%p, %p, %p, %p)", instance, pCreateInfo, pAllocator, pSurface);

    if (mImports.mInstanceFunctions.find(instance) == mImports.mInstanceFunctions.end() ||
    mImports.mInstanceFunctions[instance].vkCreateAndroidSurfaceKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCreateAndroidSurfaceKHR");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, instance, pCreateInfo, pAllocator, pSurface] {
        called = true;
        observeReads();
        result = mImports.mInstanceFunctions[instance].vkCreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCreateAndroidSurfaceKHR coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkInstance >(instance, mScratch), toEncoder< gapic::coder::vulkan::VkAndroidSurfaceCreateInfoKHR__CP >(pCreateInfo, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch), toEncoder< gapic::coder::vulkan::VkSurfaceKHR__P >(pSurface, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}

void VulkanSpy::vkDestroyInstance(VkInstance instance, VkAllocationCallbacks* pAllocator) {
    GAPID_DEBUG("vkDestroyInstance(%p, %p)", instance, pAllocator);

    bool called = false;
    auto call = [this, &called, instance, pAllocator] {
        called = true;
        observeReads();
        SpyOverride_vkDestroyInstance(instance, pAllocator);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkDestroyInstance coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkInstance >(instance, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

void VulkanSpy::vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, uint32_t format, VkFormatProperties* pFormatProperties) {
    GAPID_DEBUG("vkGetPhysicalDeviceFormatProperties(%p, %u, %p)", physicalDevice, format, pFormatProperties);

    if (mImports.mPhysicalDevicesToInstances.find(physicalDevice) == mImports.mPhysicalDevicesToInstances.end()  ||
    mImports.mInstanceFunctions.find(mImports.mPhysicalDevicesToInstances[physicalDevice]) == mImports.mInstanceFunctions.end() ||
    mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkGetPhysicalDeviceFormatProperties == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetPhysicalDeviceFormatProperties");
        return;
    }

    bool called = false;
    auto call = [this, &called, physicalDevice, format, pFormatProperties] {
        called = true;
        observeReads();
        mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkGetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatProperties);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkGetPhysicalDeviceFormatProperties coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkPhysicalDevice >(physicalDevice, mScratch), format, toEncoder< gapic::coder::vulkan::VkFormatProperties__P >(pFormatProperties, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

void VulkanSpy::vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
    GAPID_DEBUG("vkGetPhysicalDeviceMemoryProperties(%p, %p)", physicalDevice, pMemoryProperties);

    if (mImports.mPhysicalDevicesToInstances.find(physicalDevice) == mImports.mPhysicalDevicesToInstances.end()  ||
    mImports.mInstanceFunctions.find(mImports.mPhysicalDevicesToInstances[physicalDevice]) == mImports.mInstanceFunctions.end() ||
    mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkGetPhysicalDeviceMemoryProperties == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetPhysicalDeviceMemoryProperties");
        return;
    }

    bool called = false;
    auto call = [this, &called, physicalDevice, pMemoryProperties] {
        called = true;
        observeReads();
        mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkGetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkGetPhysicalDeviceMemoryProperties coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkPhysicalDevice >(physicalDevice, mScratch), toEncoder< gapic::coder::vulkan::VkPhysicalDeviceMemoryProperties__P >(pMemoryProperties, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

uint32_t VulkanSpy::vkDeviceWaitIdle(VkDevice device) {
    GAPID_DEBUG("vkDeviceWaitIdle(%p)", device);

    if (mImports.mDeviceFunctions.find(device) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[device].vkDeviceWaitIdle == nullptr) {
        GAPID_WARNING("Application called unsupported function vkDeviceWaitIdle");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, device] {
        called = true;
        observeReads();
        result = mImports.mDeviceFunctions[device].vkDeviceWaitIdle(device);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkDeviceWaitIdle coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}

void VulkanSpy::vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements) {
    GAPID_DEBUG("vkGetBufferMemoryRequirements(%p, %" PRIu64 ", %p)", device, buffer, pMemoryRequirements);

    if (mImports.mDeviceFunctions.find(device) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[device].vkGetBufferMemoryRequirements == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetBufferMemoryRequirements");
        return;
    }

    bool called = false;
    auto call = [this, &called, device, buffer, pMemoryRequirements] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[device].vkGetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkGetBufferMemoryRequirements coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< uint64_t >(buffer, mScratch), toEncoder< gapic::coder::vulkan::VkMemoryRequirements__P >(pMemoryRequirements, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

uint32_t VulkanSpy::vkCreateFence(VkDevice device, VkFenceCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkFence* pFence) {
    GAPID_DEBUG("vkCreateFence(%p, %p, %p, %p)", device, pCreateInfo, pAllocator, pFence);

    if (mImports.mDeviceFunctions.find(device) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[device].vkCreateFence == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCreateFence");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, device, pCreateInfo, pAllocator, pFence] {
        called = true;
        observeReads();
        result = mImports.mDeviceFunctions[device].vkCreateFence(device, pCreateInfo, pAllocator, pFence);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCreateFence coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< gapic::coder::vulkan::VkFenceCreateInfo__CP >(pCreateInfo, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch), toEncoder< gapic::coder::vulkan::VkFence__P >(pFence, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}

uint32_t VulkanSpy::vkResetEvent(VkDevice device, VkEvent event) {
    GAPID_DEBUG("vkResetEvent(%p, %" PRIu64 ")", device, event);

    if (mImports.mDeviceFunctions.find(device) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[device].vkResetEvent == nullptr) {
        GAPID_WARNING("Application called unsupported function vkResetEvent");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, device, event] {
        called = true;
        observeReads();
        result = mImports.mDeviceFunctions[device].vkResetEvent(device, event);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkResetEvent coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< uint64_t >(event, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}

void VulkanSpy::vkDestroyBufferView(VkDevice device, VkBufferView bufferView, VkAllocationCallbacks* pAllocator) {
    GAPID_DEBUG("vkDestroyBufferView(%p, %" PRIu64 ", %p)", device, bufferView, pAllocator);

    if (mImports.mDeviceFunctions.find(device) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[device].vkDestroyBufferView == nullptr) {
        GAPID_WARNING("Application called unsupported function vkDestroyBufferView");
        return;
    }

    bool called = false;
    auto call = [this, &called, device, bufferView, pAllocator] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[device].vkDestroyBufferView(device, bufferView, pAllocator);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkDestroyBufferView coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< uint64_t >(bufferView, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

uint32_t VulkanSpy::vkCreateShaderModule(VkDevice device, VkShaderModuleCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule) {
    GAPID_DEBUG("vkCreateShaderModule(%p, %p, %p, %p)", device, pCreateInfo, pAllocator, pShaderModule);

    if (mImports.mDeviceFunctions.find(device) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[device].vkCreateShaderModule == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCreateShaderModule");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, device, pCreateInfo, pAllocator, pShaderModule] {
        called = true;
        observeReads();
        result = mImports.mDeviceFunctions[device].vkCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCreateShaderModule coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< gapic::coder::vulkan::VkShaderModuleCreateInfo__CP >(pCreateInfo, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch), toEncoder< gapic::coder::vulkan::VkShaderModule__P >(pShaderModule, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}

void VulkanSpy::vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkAllocationCallbacks* pAllocator) {
    GAPID_DEBUG("vkDestroyDescriptorPool(%p, %" PRIu64 ", %p)", device, descriptorPool, pAllocator);

    if (mImports.mDeviceFunctions.find(device) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[device].vkDestroyDescriptorPool == nullptr) {
        GAPID_WARNING("Application called unsupported function vkDestroyDescriptorPool");
        return;
    }

    bool called = false;
    auto call = [this, &called, device, descriptorPool, pAllocator] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[device].vkDestroyDescriptorPool(device, descriptorPool, pAllocator);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkDestroyDescriptorPool coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< uint64_t >(descriptorPool, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

void VulkanSpy::vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, VkCopyDescriptorSet* pDescriptorCopies) {
    GAPID_DEBUG("vkUpdateDescriptorSets(%p, %" PRIu32 ", %p, %" PRIu32 ", %p)", device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);

    if (mImports.mDeviceFunctions.find(device) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[device].vkUpdateDescriptorSets == nullptr) {
        GAPID_WARNING("Application called unsupported function vkUpdateDescriptorSets");
        return;
    }

    bool called = false;
    auto call = [this, &called, device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[device].vkUpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkUpdateDescriptorSets coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), descriptorWriteCount, toEncoder< gapic::coder::vulkan::VkWriteDescriptorSet__CP >(pDescriptorWrites, mScratch), descriptorCopyCount, toEncoder< gapic::coder::vulkan::VkCopyDescriptorSet__CP >(pDescriptorCopies, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

uint32_t VulkanSpy::vkCreateRenderPass(VkDevice device, VkRenderPassCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass) {
    GAPID_DEBUG("vkCreateRenderPass(%p, %p, %p, %p)", device, pCreateInfo, pAllocator, pRenderPass);

    if (mImports.mDeviceFunctions.find(device) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[device].vkCreateRenderPass == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCreateRenderPass");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, device, pCreateInfo, pAllocator, pRenderPass] {
        called = true;
        observeReads();
        result = mImports.mDeviceFunctions[device].vkCreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCreateRenderPass coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< gapic::coder::vulkan::VkRenderPassCreateInfo__CP >(pCreateInfo, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch), toEncoder< gapic::coder::vulkan::VkRenderPass__P >(pRenderPass, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}

void VulkanSpy::vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
    GAPID_DEBUG("vkCmdDrawIndexedIndirect(%p, %" PRIu64 ", %" PRIu64 ", %" PRIu32 ", %" PRIu32 ")", commandBuffer, buffer, offset, drawCount, stride);

    if (mImports.mCommandBuffersToDevices.find(commandBuffer) == mImports.mCommandBuffersToDevices.end()  ||
    mImports.mDeviceFunctions.find(mImports.mCommandBuffersToDevices[commandBuffer]) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdDrawIndexedIndirect == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCmdDrawIndexedIndirect");
        return;
    }

    bool called = false;
    auto call = [this, &called, commandBuffer, buffer, offset, drawCount, stride] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCmdDrawIndexedIndirect coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, mScratch), toEncoder< uint64_t >(buffer, mScratch), toEncoder< uint64_t >(offset, mScratch), drawCount, stride);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

void VulkanSpy::vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, uint32_t srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, VkBufferImageCopy* pRegions) {
    GAPID_DEBUG("vkCmdCopyImageToBuffer(%p, %" PRIu64 ", %u, %" PRIu64 ", %" PRIu32 ", %p)", commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);

    if (mImports.mCommandBuffersToDevices.find(commandBuffer) == mImports.mCommandBuffersToDevices.end()  ||
    mImports.mDeviceFunctions.find(mImports.mCommandBuffersToDevices[commandBuffer]) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdCopyImageToBuffer == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCmdCopyImageToBuffer");
        return;
    }

    bool called = false;
    auto call = [this, &called, commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCmdCopyImageToBuffer coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, mScratch), toEncoder< uint64_t >(srcImage, mScratch), srcImageLayout, toEncoder< uint64_t >(dstBuffer, mScratch), regionCount, toEncoder< gapic::coder::vulkan::VkBufferImageCopy__CP >(pRegions, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

void VulkanSpy::vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, uint32_t imageLayout, VkClearColorValue* pColor, uint32_t rangeCount, VkImageSubresourceRange* pRanges) {
    GAPID_DEBUG("vkCmdClearColorImage(%p, %" PRIu64 ", %u, %p, %" PRIu32 ", %p)", commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);

    if (mImports.mCommandBuffersToDevices.find(commandBuffer) == mImports.mCommandBuffersToDevices.end()  ||
    mImports.mDeviceFunctions.find(mImports.mCommandBuffersToDevices[commandBuffer]) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdClearColorImage == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCmdClearColorImage");
        return;
    }

    bool called = false;
    auto call = [this, &called, commandBuffer, image, imageLayout, pColor, rangeCount, pRanges] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCmdClearColorImage coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, mScratch), toEncoder< uint64_t >(image, mScratch), imageLayout, toEncoder< gapic::coder::vulkan::VkClearColorValue__CP >(pColor, mScratch), rangeCount, toEncoder< gapic::coder::vulkan::VkImageSubresourceRange__CP >(pRanges, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

void VulkanSpy::vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
    GAPID_DEBUG("vkCmdResetEvent(%p, %" PRIu64 ", %" PRIu32 ")", commandBuffer, event, stageMask);

    if (mImports.mCommandBuffersToDevices.find(commandBuffer) == mImports.mCommandBuffersToDevices.end()  ||
    mImports.mDeviceFunctions.find(mImports.mCommandBuffersToDevices[commandBuffer]) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdResetEvent == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCmdResetEvent");
        return;
    }

    bool called = false;
    auto call = [this, &called, commandBuffer, event, stageMask] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdResetEvent(commandBuffer, event, stageMask);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCmdResetEvent coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, mScratch), toEncoder< uint64_t >(event, mScratch), toEncoder< uint32_t >(stageMask, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

void VulkanSpy::vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, VkImageMemoryBarrier* pImageMemoryBarriers) {
    GAPID_DEBUG("vkCmdPipelineBarrier(%p, %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %p, %" PRIu32 ", %p, %" PRIu32 ", %p)", commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);

    if (mImports.mCommandBuffersToDevices.find(commandBuffer) == mImports.mCommandBuffersToDevices.end()  ||
    mImports.mDeviceFunctions.find(mImports.mCommandBuffersToDevices[commandBuffer]) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdPipelineBarrier == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCmdPipelineBarrier");
        return;
    }

    bool called = false;
    auto call = [this, &called, commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCmdPipelineBarrier coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, mScratch), toEncoder< uint32_t >(srcStageMask, mScratch), toEncoder< uint32_t >(dstStageMask, mScratch), toEncoder< uint32_t >(dependencyFlags, mScratch), memoryBarrierCount, toEncoder< gapic::coder::vulkan::VkMemoryBarrier__CP >(pMemoryBarriers, mScratch), bufferMemoryBarrierCount, toEncoder< gapic::coder::vulkan::VkBufferMemoryBarrier__CP >(pBufferMemoryBarriers, mScratch), imageMemoryBarrierCount, toEncoder< gapic::coder::vulkan::VkImageMemoryBarrier__CP >(pImageMemoryBarriers, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

void VulkanSpy::vkCmdWriteTimestamp(VkCommandBuffer commandBuffer, uint32_t pipelineStage, VkQueryPool queryPool, uint32_t query) {
    GAPID_DEBUG("vkCmdWriteTimestamp(%p, %u, %" PRIu64 ", %" PRIu32 ")", commandBuffer, pipelineStage, queryPool, query);

    if (mImports.mCommandBuffersToDevices.find(commandBuffer) == mImports.mCommandBuffersToDevices.end()  ||
    mImports.mDeviceFunctions.find(mImports.mCommandBuffersToDevices[commandBuffer]) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdWriteTimestamp == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCmdWriteTimestamp");
        return;
    }

    bool called = false;
    auto call = [this, &called, commandBuffer, pipelineStage, queryPool, query] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, query);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCmdWriteTimestamp coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, mScratch), pipelineStage, toEncoder< uint64_t >(queryPool, mScratch), query);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

void VulkanSpy::vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, VkCommandBuffer* pCommandBuffers) {
    GAPID_DEBUG("vkCmdExecuteCommands(%p, %" PRIu32 ", %p)", commandBuffer, commandBufferCount, pCommandBuffers);

    if (mImports.mCommandBuffersToDevices.find(commandBuffer) == mImports.mCommandBuffersToDevices.end()  ||
    mImports.mDeviceFunctions.find(mImports.mCommandBuffersToDevices[commandBuffer]) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdExecuteCommands == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCmdExecuteCommands");
        return;
    }

    bool called = false;
    auto call = [this, &called, commandBuffer, commandBufferCount, pCommandBuffers] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCmdExecuteCommands coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, mScratch), commandBufferCount, toEncoder< gapic::coder::vulkan::VkCommandBuffer__CP >(pCommandBuffers, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

uint32_t VulkanSpy::vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats) {
    GAPID_DEBUG("vkGetPhysicalDeviceSurfaceFormatsKHR(%p, %" PRIu64 ", %p, %p)", physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);

    if (mImports.mPhysicalDevicesToInstances.find(physicalDevice) == mImports.mPhysicalDevicesToInstances.end()  ||
    mImports.mInstanceFunctions.find(mImports.mPhysicalDevicesToInstances[physicalDevice]) == mImports.mInstanceFunctions.end() ||
    mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkGetPhysicalDeviceSurfaceFormatsKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetPhysicalDeviceSurfaceFormatsKHR");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats] {
        called = true;
        observeReads();
        result = mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkGetPhysicalDeviceSurfaceFormatsKHR coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkPhysicalDevice >(physicalDevice, mScratch), toEncoder< uint64_t >(surface, mScratch), toEncoder< gapic::coder::vulkan::U32__P >(pSurfaceFormatCount, mScratch), toEncoder< gapic::coder::vulkan::VkSurfaceFormatKHR__P >(pSurfaceFormats, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}

void VulkanSpy::vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, VkAllocationCallbacks* pAllocator) {
    GAPID_DEBUG("vkDestroySwapchainKHR(%p, %" PRIu64 ", %p)", device, swapchain, pAllocator);

    if (mImports.mDeviceFunctions.find(device) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[device].vkDestroySwapchainKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function vkDestroySwapchainKHR");
        return;
    }

    bool called = false;
    auto call = [this, &called, device, swapchain, pAllocator] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[device].vkDestroySwapchainKHR(device, swapchain, pAllocator);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkDestroySwapchainKHR coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< uint64_t >(swapchain, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch));
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);

}

uint32_t VulkanSpy::vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) {
    GAPID_DEBUG("vkGetSwapchainImagesKHR(%p, %" PRIu64 ", %p, %p)", device, swapchain, pSwapchainImageCount, pSwapchainImages);

    if (mImports.mDeviceFunctions.find(device) == mImports.mDeviceFunctions.end() ||
    mImports.mDeviceFunctions[device].vkGetSwapchainImagesKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetSwapchainImagesKHR");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, device, swapchain, pSwapchainImageCount, pSwapchainImages] {
        called = true;
        observeReads();
        result = mImports.mDeviceFunctions[device].vkGetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkGetSwapchainImagesKHR coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< uint64_t >(swapchain, mScratch), toEncoder< gapic::coder::vulkan::U32__P >(pSwapchainImageCount, mScratch), toEncoder< gapic::coder::vulkan::VkImage__P >(pSwapchainImages, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}

uint32_t VulkanSpy::vkQueuePresentKHR(VkQueue queue, VkPresentInfoKHR* pPresentInfo) {
    GAPID_DEBUG("vkQueuePresentKHR(%p, %p)", queue, pPresentInfo);

    if (mImports.mQueuesToDevices.find(queue) == mImports.mQueuesToDevices.end()  ||
    mImports.mDeviceFunctions.find(mImports.mQueuesToDevices[queue]) == mImports.mDeviceFunctions.end()  ||
    mImports.mDeviceFunctions[mImports.mQueuesToDevices[queue]].vkQueuePresentKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function vkQueuePresentKHR");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, queue, pPresentInfo] {
        called = true;
        observeReads();
        result = mImports.mDeviceFunctions[mImports.mQueuesToDevices[queue]].vkQueuePresentKHR(queue, pPresentInfo);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkQueuePresentKHR coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkQueue >(queue, mScratch), toEncoder< gapic::coder::vulkan::VkPresentInfoKHR__CP >(pPresentInfo, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}

uint32_t VulkanSpy::vkGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties) {
    GAPID_DEBUG("vkGetPhysicalDeviceDisplayPropertiesKHR(%p, %p, %p)", physicalDevice, pPropertyCount, pProperties);

    if (mImports.mPhysicalDevicesToInstances.find(physicalDevice) == mImports.mPhysicalDevicesToInstances.end()  ||
    mImports.mInstanceFunctions.find(mImports.mPhysicalDevicesToInstances[physicalDevice]) == mImports.mInstanceFunctions.end() ||
    mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkGetPhysicalDeviceDisplayPropertiesKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetPhysicalDeviceDisplayPropertiesKHR");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, physicalDevice, pPropertyCount, pProperties] {
        called = true;
        observeReads();
        result = mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkGetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, pPropertyCount, pProperties);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkGetPhysicalDeviceDisplayPropertiesKHR coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkPhysicalDevice >(physicalDevice, mScratch), toEncoder< gapic::coder::vulkan::U32__P >(pPropertyCount, mScratch), toEncoder< gapic::coder::vulkan::VkDisplayPropertiesKHR__P >(pProperties, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}

uint32_t VulkanSpy::vkGetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties) {
    GAPID_DEBUG("vkGetPhysicalDeviceDisplayPlanePropertiesKHR(%p, %p, %p)", physicalDevice, pPropertyCount, pProperties);

    if (mImports.mPhysicalDevicesToInstances.find(physicalDevice) == mImports.mPhysicalDevicesToInstances.end()  ||
    mImports.mInstanceFunctions.find(mImports.mPhysicalDevicesToInstances[physicalDevice]) == mImports.mInstanceFunctions.end() ||
    mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkGetPhysicalDeviceDisplayPlanePropertiesKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, physicalDevice, pPropertyCount, pProperties] {
        called = true;
        observeReads();
        result = mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkGetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, pPropertyCount, pProperties);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkGetPhysicalDeviceDisplayPlanePropertiesKHR coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkPhysicalDevice >(physicalDevice, mScratch), toEncoder< gapic::coder::vulkan::U32__P >(pPropertyCount, mScratch), toEncoder< gapic::coder::vulkan::VkDisplayPlanePropertiesKHR__P >(pProperties, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}

uint32_t VulkanSpy::vkCreateDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackCreateInfoEXT* pCreateInfo, VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback) {
    GAPID_DEBUG("vkCreateDebugReportCallbackEXT(%p, %p, %p, %p)", instance, pCreateInfo, pAllocator, pCallback);

    if (mImports.mInstanceFunctions.find(instance) == mImports.mInstanceFunctions.end() ||
    mImports.mInstanceFunctions[instance].vkCreateDebugReportCallbackEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCreateDebugReportCallbackEXT");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, instance, pCreateInfo, pAllocator, pCallback] {
        called = true;
        observeReads();
        result = mImports.mInstanceFunctions[instance].vkCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observeWrites();

    gapic::coder::vulkan::VkCreateDebugReportCallbackEXT coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkInstance >(instance, mScratch), toEncoder< gapic::coder::vulkan::VkDebugReportCallbackCreateInfoEXT__CP >(pCreateInfo, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch), toEncoder< gapic::coder::vulkan::VkDebugReportCallbackEXT__P >(pCallback, mScratch), result);
    coder.mextras.append(&mObservations);

    if (counter_at_end > counter_at_begin + 1 ||
    counter_at_begin != mExpectedNextCommandStartCounterValue) {
        coder.mextras.append(&counter_value_encodable);
    }
    mExpectedNextCommandStartCounterValue = counter_at_end + 1;

    addExtras(coder);
    mEncoder->Variant(&coder);


    return result;
}
} // namespace gapii