/*
 * 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::vkAcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence) {
    GAPID_DEBUG("vkAcquireImageANDROID(%p, %" PRIu64 ", %d, %" PRIu64 ", %" PRIu64 ")", device, image, nativeFenceFd, semaphore, fence);

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

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


    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::VkAcquireImageANDROID coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< uint64_t >(image, mScratch), nativeFenceFd, toEncoder< uint64_t >(semaphore, mScratch), toEncoder< uint64_t >(fence, 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::vkQueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd) {
    GAPID_DEBUG("vkQueueSignalReleaseImageANDROID(%p, %" PRIu32 ", %p, %" PRIu64 ", %p)", queue, waitSemaphoreCount, pWaitSemaphores, image, pNativeFenceFd);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, queue, waitSemaphoreCount, pWaitSemaphores, image, pNativeFenceFd] {
        called = true;
        observeReads();
        result = mImports.mDeviceFunctions[mImports.mQueuesToDevices[queue]].vkQueueSignalReleaseImageANDROID(queue, waitSemaphoreCount, pWaitSemaphores, image, pNativeFenceFd);
    };


    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::VkQueueSignalReleaseImageANDROID coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkQueue >(queue, mScratch), waitSemaphoreCount, toEncoder< gapic::coder::vulkan::VkSemaphore__CP >(pWaitSemaphores, mScratch), toEncoder< uint64_t >(image, mScratch), toEncoder< gapic::coder::vulkan::Int__P >(pNativeFenceFd, 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::vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) {
    GAPID_DEBUG("vkGetPhysicalDeviceFeatures(%p, %p)", physicalDevice, pFeatures);

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

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


    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::VkGetPhysicalDeviceFeatures coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkPhysicalDevice >(physicalDevice, mScratch), toEncoder< gapic::coder::vulkan::VkPhysicalDeviceFeatures__P >(pFeatures, 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);

}

PFN_vkVoidFunction VulkanSpy::vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
    GAPID_DEBUG("vkGetInstanceProcAddr(%p, %s)", instance, pName);

    PFN_vkVoidFunction result = nullptr;
    bool called = false;
    auto call = [this, &called, &result, instance, pName] {
        called = true;
        observeReads();
        result = SpyOverride_vkGetInstanceProcAddr(instance, pName);
    };


    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::VkGetInstanceProcAddr coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkInstance >(instance, mScratch), toEncoder< const char* >(pName, mScratch), toEncoder< gapic::coder::vulkan::PFN_vkVoidFunction >(result, 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);


    return result;
}

uint32_t VulkanSpy::vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) {
    GAPID_DEBUG("vkEnumerateDeviceExtensionProperties(%p, %s, %p, %p)", physicalDevice, pLayerName, pPropertyCount, pProperties);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, physicalDevice, pLayerName, pPropertyCount, pProperties] {
        called = true;
        observeReads();
        result = mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkEnumerateDeviceExtensionProperties(physicalDevice, pLayerName, 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::VkEnumerateDeviceExtensionProperties coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkPhysicalDevice >(physicalDevice, mScratch), toEncoder< const char* >(pLayerName, mScratch), toEncoder< gapic::coder::vulkan::U32__P >(pPropertyCount, mScratch), toEncoder< gapic::coder::vulkan::VkExtensionProperties__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::vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
    GAPID_DEBUG("vkEnumerateDeviceLayerProperties(%p, %p, %p)", physicalDevice, pPropertyCount, pProperties);

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, physicalDevice, pPropertyCount, pProperties] {
        called = true;
        observeReads();
        result = SpyOverride_vkEnumerateDeviceLayerProperties(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::VkEnumerateDeviceLayerProperties 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::VkLayerProperties__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::vkQueueWaitIdle(VkQueue queue) {
    GAPID_DEBUG("vkQueueWaitIdle(%p)", queue);

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

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


    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::VkQueueWaitIdle coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkQueue >(queue, 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::vkAllocateMemory(VkDevice device, VkMemoryAllocateInfo* pAllocateInfo, VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) {
    GAPID_DEBUG("vkAllocateMemory(%p, %p, %p, %p)", device, pAllocateInfo, pAllocator, pMemory);

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

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


    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::VkAllocateMemory coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< gapic::coder::vulkan::VkMemoryAllocateInfo__CP >(pAllocateInfo, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch), toEncoder< gapic::coder::vulkan::VkDeviceMemory__P >(pMemory, 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::vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, VkBindSparseInfo* pBindInfo, VkFence fence) {
    GAPID_DEBUG("vkQueueBindSparse(%p, %" PRIu32 ", %p, %" PRIu64 ")", queue, bindInfoCount, pBindInfo, fence);

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

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


    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::VkQueueBindSparse coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkQueue >(queue, mScratch), bindInfoCount, toEncoder< gapic::coder::vulkan::VkBindSparseInfo__CP >(pBindInfo, mScratch), toEncoder< uint64_t >(fence, 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::vkSetEvent(VkDevice device, VkEvent event) {
    GAPID_DEBUG("vkSetEvent(%p, %" PRIu64 ")", device, event);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, device, event] {
        called = true;
        observeReads();
        result = mImports.mDeviceFunctions[device].vkSetEvent(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::VkSetEvent 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;
}

uint32_t VulkanSpy::vkCreatePipelineCache(VkDevice device, VkPipelineCacheCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache) {
    GAPID_DEBUG("vkCreatePipelineCache(%p, %p, %p, %p)", device, pCreateInfo, pAllocator, pPipelineCache);

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

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


    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::VkCreatePipelineCache coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< gapic::coder::vulkan::VkPipelineCacheCreateInfo__CP >(pCreateInfo, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch), toEncoder< gapic::coder::vulkan::VkPipelineCache__P >(pPipelineCache, 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::vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData) {
    GAPID_DEBUG("vkGetPipelineCacheData(%p, %" PRIu64 ", %p, %p)", device, pipelineCache, pDataSize, pData);

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

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


    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::VkGetPipelineCacheData coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< uint64_t >(pipelineCache, mScratch), toEncoder< gapic::coder::vulkan::Size_t__P >(pDataSize, mScratch), toEncoder< gapic::coder::vulkan::Void__P >(pData, 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::vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, VkComputePipelineCreateInfo* pCreateInfos, VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) {
    GAPID_DEBUG("vkCreateComputePipelines(%p, %" PRIu64 ", %" PRIu32 ", %p, %p, %p)", device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines] {
        called = true;
        observeReads();
        result = mImports.mDeviceFunctions[device].vkCreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
    };


    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::VkCreateComputePipelines coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkDevice >(device, mScratch), toEncoder< uint64_t >(pipelineCache, mScratch), createInfoCount, toEncoder< gapic::coder::vulkan::VkComputePipelineCreateInfo__CP >(pCreateInfos, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch), toEncoder< gapic::coder::vulkan::VkPipeline__P >(pPipelines, 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::vkCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) {
    GAPID_DEBUG("vkCmdSetDepthBounds(%p, %f, %f)", commandBuffer, minDepthBounds, maxDepthBounds);

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

    bool called = false;
    auto call = [this, &called, commandBuffer, minDepthBounds, maxDepthBounds] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
    };


    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::VkCmdSetDepthBounds coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, mScratch), minDepthBounds, maxDepthBounds);
    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::vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, uint32_t srcImageLayout, VkImage dstImage, uint32_t dstImageLayout, uint32_t regionCount, VkImageBlit* pRegions, uint32_t filter) {
    GAPID_DEBUG("vkCmdBlitImage(%p, %" PRIu64 ", %u, %" PRIu64 ", %u, %" PRIu32 ", %p, %u)", commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);

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

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


    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::VkCmdBlitImage coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, mScratch), toEncoder< uint64_t >(srcImage, mScratch), srcImageLayout, toEncoder< uint64_t >(dstImage, mScratch), dstImageLayout, regionCount, toEncoder< gapic::coder::vulkan::VkImageBlit__CP >(pRegions, mScratch), filter);
    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::vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
    GAPID_DEBUG("vkCmdSetEvent(%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]].vkCmdSetEvent == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCmdSetEvent");
        return;
    }

    bool called = false;
    auto call = [this, &called, commandBuffer, event, stageMask] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdSetEvent(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::VkCmdSetEvent 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::vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, VkImageMemoryBarrier* pImageMemoryBarriers) {
    GAPID_DEBUG("vkCmdWaitEvents(%p, %" PRIu32 ", %p, %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %p, %" PRIu32 ", %p, %" PRIu32 ", %p)", commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, 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]].vkCmdWaitEvents == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCmdWaitEvents");
        return;
    }

    bool called = false;
    auto call = [this, &called, commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdWaitEvents(commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, 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::VkCmdWaitEvents coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, mScratch), eventCount, toEncoder< gapic::coder::vulkan::VkEvent__CP >(pEvents, mScratch), toEncoder< uint32_t >(srcStageMask, mScratch), toEncoder< uint32_t >(dstStageMask, 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::vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, VkRenderPassBeginInfo* pRenderPassBegin, uint32_t contents) {
    GAPID_DEBUG("vkCmdBeginRenderPass(%p, %p, %u)", commandBuffer, pRenderPassBegin, contents);

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

    bool called = false;
    auto call = [this, &called, commandBuffer, pRenderPassBegin, contents] {
        called = true;
        observeReads();
        mImports.mDeviceFunctions[mImports.mCommandBuffersToDevices[commandBuffer]].vkCmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
    };


    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::VkCmdBeginRenderPass coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, mScratch), toEncoder< gapic::coder::vulkan::VkRenderPassBeginInfo__CP >(pRenderPassBegin, mScratch), contents);
    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::vkCmdEndRenderPass(VkCommandBuffer commandBuffer) {
    GAPID_DEBUG("vkCmdEndRenderPass(%p)", commandBuffer);

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

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


    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::VkCmdEndRenderPass coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkCommandBuffer >(commandBuffer, 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::vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, VkAllocationCallbacks* pAllocator) {
    GAPID_DEBUG("vkDestroySurfaceKHR(%p, %" PRIu64 ", %p)", instance, surface, pAllocator);

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

    bool called = false;
    auto call = [this, &called, instance, surface, pAllocator] {
        called = true;
        observeReads();
        mImports.mInstanceFunctions[instance].vkDestroySurfaceKHR(instance, surface, 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::VkDestroySurfaceKHR coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkInstance >(instance, mScratch), toEncoder< uint64_t >(surface, 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::vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported) {
    GAPID_DEBUG("vkGetPhysicalDeviceSurfaceSupportKHR(%p, %" PRIu32 ", %" PRIu64 ", %p)", physicalDevice, queueFamilyIndex, surface, pSupported);

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

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


    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::VkGetPhysicalDeviceSurfaceSupportKHR coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkPhysicalDevice >(physicalDevice, mScratch), queueFamilyIndex, toEncoder< uint64_t >(surface, mScratch), toEncoder< gapic::coder::vulkan::VkBool32__P >(pSupported, 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::vkGetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays) {
    GAPID_DEBUG("vkGetDisplayPlaneSupportedDisplaysKHR(%p, %" PRIu32 ", %p, %p)", physicalDevice, planeIndex, pDisplayCount, pDisplays);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, physicalDevice, planeIndex, pDisplayCount, pDisplays] {
        called = true;
        observeReads();
        result = mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkGetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount, pDisplays);
    };


    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::VkGetDisplayPlaneSupportedDisplaysKHR coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkPhysicalDevice >(physicalDevice, mScratch), planeIndex, toEncoder< gapic::coder::vulkan::U32__P >(pDisplayCount, mScratch), toEncoder< gapic::coder::vulkan::VkDisplayKHR__P >(pDisplays, 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::vkCreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, VkDisplayModeCreateInfoKHR* pCreateInfo, VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode) {
    GAPID_DEBUG("vkCreateDisplayModeKHR(%p, %" PRIu64 ", %p, %p, %p)", physicalDevice, display, pCreateInfo, pAllocator, pMode);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, &called, &result, physicalDevice, display, pCreateInfo, pAllocator, pMode] {
        called = true;
        observeReads();
        result = mImports.mInstanceFunctions[mImports.mPhysicalDevicesToInstances[physicalDevice]].vkCreateDisplayModeKHR(physicalDevice, display, pCreateInfo, pAllocator, pMode);
    };


    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::VkCreateDisplayModeKHR coder(mScratch.vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::VkPhysicalDevice >(physicalDevice, mScratch), toEncoder< uint64_t >(display, mScratch), toEncoder< gapic::coder::vulkan::VkDisplayModeCreateInfoKHR__CP >(pCreateInfo, mScratch), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, mScratch), toEncoder< gapic::coder::vulkan::VkDisplayModeKHR__P >(pMode, 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