/*
 * 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 {

VkBool32 VulkanSpy::vkGetPhysicalDeviceXlibPresentationSupportKHR(CallObserver* observer, VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID) {
    GAPID_DEBUG("vkGetPhysicalDeviceXlibPresentationSupportKHR(%zu, %" PRIu32 ", %p, %zu)", physicalDevice, queueFamilyIndex, dpy, visualID);

    if (State.mPhysicalDevices.find(physicalDevice) == State.mPhysicalDevices.end() ||
    mImports.mVkInstanceFunctions.find(State.mPhysicalDevices[physicalDevice]->mInstance) == mImports.mVkInstanceFunctions.end() ||
    mImports.mVkInstanceFunctions[State.mPhysicalDevices[physicalDevice]->mInstance].vkGetPhysicalDeviceXlibPresentationSupportKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetPhysicalDeviceXlibPresentationSupportKHR");
        return 0;
    }

    VkBool32 result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, physicalDevice, queueFamilyIndex, dpy, visualID] {
        called = true;
        observer->observeReads();
        result = mImports.mVkInstanceFunctions[State.mPhysicalDevices[physicalDevice]->mInstance].vkGetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, dpy, visualID);
        onPostFence(observer);
    };


    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(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkGetPhysicalDeviceXlibPresentationSupportKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(physicalDevice, *observer->getScratch()), queueFamilyIndex, toEncoder< gapic::coder::vulkan::Display__P >(dpy, *observer->getScratch()), toEncoder< size_val >(visualID, *observer->getScratch()), toEncoder< uint32_t >(result, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

void VulkanSpy::replayUnregisterVkInstance(CallObserver* observer, VkInstance instance) {
    GAPID_DEBUG("replayUnregisterVkInstance(%zu)", instance);

    bool called = false;
    auto call = [this, observer, &called, instance] {
        called = true;
        observer->observeReads();
        onPostFence(observer);
    };


    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(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::ReplayUnregisterVkInstance coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(instance, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void VulkanSpy::replayRegisterVkCommandBuffers(CallObserver* observer, VkDevice device, uint32_t count, VkCommandBuffer* commandBuffers) {
    GAPID_DEBUG("replayRegisterVkCommandBuffers(%zu, %" PRIu32 ", %p)", device, count, commandBuffers);

    bool called = false;
    auto call = [this, observer, &called, device, count, commandBuffers] {
        called = true;
        observer->observeReads();
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::vulkan::ReplayRegisterVkCommandBuffers coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), count, toEncoder< gapic::coder::vulkan::VkCommandBuffer__P >(commandBuffers, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

uint32_t VulkanSpy::vkGetPhysicalDeviceImageFormatProperties(CallObserver* observer, VkPhysicalDevice physicalDevice, uint32_t format, uint32_t type, uint32_t tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties) {
    GAPID_DEBUG("vkGetPhysicalDeviceImageFormatProperties(%zu, %u, %u, %u, %" PRIu32 ", %" PRIu32 ", %p)", physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);

    if (State.mPhysicalDevices.find(physicalDevice) == State.mPhysicalDevices.end() ||
    mImports.mVkInstanceFunctions.find(State.mPhysicalDevices[physicalDevice]->mInstance) == mImports.mVkInstanceFunctions.end() ||
    mImports.mVkInstanceFunctions[State.mPhysicalDevices[physicalDevice]->mInstance].vkGetPhysicalDeviceImageFormatProperties == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetPhysicalDeviceImageFormatProperties");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties] {
        called = true;
        observer->observeReads();
        result = mImports.mVkInstanceFunctions[State.mPhysicalDevices[physicalDevice]->mInstance].vkGetPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            observer->write<VkImageFormatProperties>(slice(pImageFormatProperties, 0ULL, 1ULL), 0ULL, slice(pImageFormatProperties, 0ULL, 1ULL)[0ULL]);
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkGetPhysicalDeviceImageFormatProperties coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(physicalDevice, *observer->getScratch()), format, type, tiling, toEncoder< uint32_t >(usage, *observer->getScratch()), toEncoder< uint32_t >(flags, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkImageFormatProperties__P >(pImageFormatProperties, *observer->getScratch()), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

void VulkanSpy::vkGetPhysicalDeviceProperties(CallObserver* observer, VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties) {
    GAPID_DEBUG("vkGetPhysicalDeviceProperties(%zu, %p)", physicalDevice, pProperties);

    if (State.mPhysicalDevices.find(physicalDevice) == State.mPhysicalDevices.end() ||
    mImports.mVkInstanceFunctions.find(State.mPhysicalDevices[physicalDevice]->mInstance) == mImports.mVkInstanceFunctions.end() ||
    mImports.mVkInstanceFunctions[State.mPhysicalDevices[physicalDevice]->mInstance].vkGetPhysicalDeviceProperties == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetPhysicalDeviceProperties");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, physicalDevice, pProperties] {
        called = true;
        observer->observeReads();
        mImports.mVkInstanceFunctions[State.mPhysicalDevices[physicalDevice]->mInstance].vkGetPhysicalDeviceProperties(physicalDevice, pProperties);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            observer->write<VkPhysicalDeviceProperties>(slice(pProperties, 0ULL, 1ULL), 0ULL, slice(pProperties, 0ULL, 1ULL)[0ULL]);
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkGetPhysicalDeviceProperties coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(physicalDevice, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkPhysicalDeviceProperties__P >(pProperties, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

uint32_t VulkanSpy::vkCreateDevice(CallObserver* observer, VkPhysicalDevice physicalDevice, VkDeviceCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkDevice* pDevice) {
    GAPID_DEBUG("vkCreateDevice(%zu, %p, %p, %p)", physicalDevice, pCreateInfo, pAllocator, pDevice);

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, physicalDevice, pCreateInfo, pAllocator, pDevice] {
        called = true;
        observer->observeReads();
        result = SpyOverride_vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            std::shared_ptr<DeviceObject> l_device = subCreateDeviceObject(observer, call, pCreateInfo);
            checkNotNull(l_device).mPhysicalDevice = physicalDevice;
            call();
            auto l_handle = slice(pDevice, 0ULL, 1ULL)[0ULL];
            observer->write<VkDevice>(slice(pDevice, 0ULL, 1ULL), 0ULL, l_handle);
            this->State.mDevices[l_handle] = l_device;
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkCreateDevice coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(physicalDevice, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkDeviceCreateInfo__CP >(pCreateInfo, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkDevice__P >(pDevice, *observer->getScratch()), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

uint32_t VulkanSpy::vkBindBufferMemory(CallObserver* observer, VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) {
    GAPID_DEBUG("vkBindBufferMemory(%zu, %" PRIu64 ", %" PRIu64 ", %" PRIu64 ")", device, buffer, memory, memoryOffset);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, device, buffer, memory, memoryOffset] {
        called = true;
        observer->observeReads();
        result = mImports.mVkDeviceFunctions[device].vkBindBufferMemory(device, buffer, memory, memoryOffset);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            checkNotNull(findOrZero(this->State.mBuffers, buffer)).mMemory = memory;
            checkNotNull(findOrZero(this->State.mBuffers, buffer)).mMemoryOffset = memoryOffset;
            checkNotNull(findOrZero(this->State.mDeviceMemories, memory)).mBoundObjects[(uint64_t)(buffer)] = memoryOffset;
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkBindBufferMemory coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< uint64_t >(buffer, *observer->getScratch()), toEncoder< uint64_t >(memory, *observer->getScratch()), toEncoder< uint64_t >(memoryOffset, *observer->getScratch()), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

uint32_t VulkanSpy::vkCreateSemaphore(CallObserver* observer, VkDevice device, VkSemaphoreCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore) {
    GAPID_DEBUG("vkCreateSemaphore(%zu, %p, %p, %p)", device, pCreateInfo, pAllocator, pSemaphore);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, device, pCreateInfo, pAllocator, pSemaphore] {
        called = true;
        observer->observeReads();
        result = mImports.mVkDeviceFunctions[device].vkCreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            std::shared_ptr<SemaphoreObject> l_semaphore = subCreateSemaphoreObject(observer, call, pCreateInfo);
            checkNotNull(l_semaphore).mDevice = device;
            call();
            auto l_handle = slice(pSemaphore, 0ULL, 1ULL)[0ULL];
            observer->write<VkSemaphore>(slice(pSemaphore, 0ULL, 1ULL), 0ULL, l_handle);
            this->State.mSemaphores[l_handle] = l_semaphore;
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkCreateSemaphore coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkSemaphoreCreateInfo__CP >(pCreateInfo, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkSemaphore__P >(pSemaphore, *observer->getScratch()), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

void VulkanSpy::vkDestroyEvent(CallObserver* observer, VkDevice device, VkEvent event, VkAllocationCallbacks* pAllocator) {
    GAPID_DEBUG("vkDestroyEvent(%zu, %" PRIu64 ", %p)", device, event, pAllocator);

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

    bool called = false;
    auto call = [this, observer, &called, device, event, pAllocator] {
        called = true;
        observer->observeReads();
        mImports.mVkDeviceFunctions[device].vkDestroyEvent(device, event, pAllocator);
        onPostFence(observer);
    };


    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(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkDestroyEvent coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< uint64_t >(event, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

uint32_t VulkanSpy::vkGetEventStatus(CallObserver* observer, VkDevice device, VkEvent event) {
    GAPID_DEBUG("vkGetEventStatus(%zu, %" PRIu64 ")", device, event);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, device, event] {
        called = true;
        observer->observeReads();
        result = mImports.mVkDeviceFunctions[device].vkGetEventStatus(device, event);
        onPostFence(observer);
    };


    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(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkGetEventStatus coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< uint64_t >(event, *observer->getScratch()), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

uint32_t VulkanSpy::vkCreateQueryPool(CallObserver* observer, VkDevice device, VkQueryPoolCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool) {
    GAPID_DEBUG("vkCreateQueryPool(%zu, %p, %p, %p)", device, pCreateInfo, pAllocator, pQueryPool);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, device, pCreateInfo, pAllocator, pQueryPool] {
        called = true;
        observer->observeReads();
        result = mImports.mVkDeviceFunctions[device].vkCreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            (void)observer->read(slice(pCreateInfo, 0ULL, 1ULL), 0ULL);
            call();
            auto l_handle = slice(pQueryPool, 0ULL, 1ULL)[0ULL];
            this->State.mQueryPools[l_handle] = std::shared_ptr<QueryPoolObject>(new QueryPoolObject(device));
            observer->write<VkQueryPool>(slice(pQueryPool, 0ULL, 1ULL), 0ULL, l_handle);
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkCreateQueryPool coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkQueryPoolCreateInfo__CP >(pCreateInfo, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkQueryPool__P >(pQueryPool, *observer->getScratch()), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

uint32_t VulkanSpy::vkCreateBuffer(CallObserver* observer, VkDevice device, VkBufferCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer) {
    GAPID_DEBUG("vkCreateBuffer(%zu, %p, %p, %p)", device, pCreateInfo, pAllocator, pBuffer);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, device, pCreateInfo, pAllocator, pBuffer] {
        called = true;
        observer->observeReads();
        result = mImports.mVkDeviceFunctions[device].vkCreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            VkBufferCreateInfo l_buffer_create_info = observer->read(slice(pCreateInfo, 0ULL, 1ULL), 0ULL);
            std::shared_ptr<BufferObject> l_bufferObject = std::shared_ptr<BufferObject>(new BufferObject(0, 0, 0, 0));
            checkNotNull(l_bufferObject).mDevice = device;
            checkNotNull(l_bufferObject).mMemory = (VkDeviceMemory)(0ULL);
            checkNotNull(l_bufferObject).mMemoryOffset = (VkDeviceSize)(0ULL);
            checkNotNull(l_bufferObject).mMemorySize = l_buffer_create_info.msize;
            if ((l_buffer_create_info.mpNext) != (nullptr)) {
                uint32_t l_t = observer->read(slice((uint32_t*)(l_buffer_create_info.mpNext), 0ULL, 1ULL), 0ULL);
                switch (l_t) {
                    case VkStructureType::VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV: {
                        (void)observer->read(slice((VkDedicatedAllocationBufferCreateInfoNV*)(l_buffer_create_info.mpNext), 0ULL, 1ULL), 0ULL);
                        break;
                    }
                }
            }
            observer->read(slice(l_buffer_create_info.mpQueueFamilyIndices, (uint64_t)(0UL), (uint64_t)(l_buffer_create_info.mqueueFamilyIndexCount)));
            call();
            auto l_buffer = slice(pBuffer, 0ULL, 1ULL)[0ULL];
            this->State.mBuffers[l_buffer] = l_bufferObject;
            observer->write<VkBuffer>(slice(pBuffer, 0ULL, 1ULL), 0ULL, l_buffer);
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkCreateBuffer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkBufferCreateInfo__CP >(pCreateInfo, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkBuffer__P >(pBuffer, *observer->getScratch()), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

void VulkanSpy::vkDestroyPipelineCache(CallObserver* observer, VkDevice device, VkPipelineCache pipelineCache, VkAllocationCallbacks* pAllocator) {
    GAPID_DEBUG("vkDestroyPipelineCache(%zu, %" PRIu64 ", %p)", device, pipelineCache, pAllocator);

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

    bool called = false;
    auto call = [this, observer, &called, device, pipelineCache, pAllocator] {
        called = true;
        observer->observeReads();
        mImports.mVkDeviceFunctions[device].vkDestroyPipelineCache(device, pipelineCache, pAllocator);
        onPostFence(observer);
    };


    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(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkDestroyPipelineCache coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< uint64_t >(pipelineCache, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void VulkanSpy::vkDestroySampler(CallObserver* observer, VkDevice device, VkSampler sampler, VkAllocationCallbacks* pAllocator) {
    GAPID_DEBUG("vkDestroySampler(%zu, %" PRIu64 ", %p)", device, sampler, pAllocator);

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

    bool called = false;
    auto call = [this, observer, &called, device, sampler, pAllocator] {
        called = true;
        observer->observeReads();
        mImports.mVkDeviceFunctions[device].vkDestroySampler(device, sampler, pAllocator);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::vulkan::VkDestroySampler coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< uint64_t >(sampler, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

uint32_t VulkanSpy::vkFreeDescriptorSets(CallObserver* observer, VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, VkDescriptorSet* pDescriptorSets) {
    GAPID_DEBUG("vkFreeDescriptorSets(%zu, %" PRIu64 ", %" PRIu32 ", %p)", device, descriptorPool, descriptorSetCount, pDescriptorSets);

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, device, descriptorPool, descriptorSetCount, pDescriptorSets] {
        called = true;
        observer->observeReads();
        result = mImports.mVkDeviceFunctions[device].vkFreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            Slice<VkDescriptorSet> l_sets = slice(pDescriptorSets, (uint64_t)(0UL), (uint64_t)(descriptorSetCount));
            for (uint32_t l_i = 0UL; l_i < descriptorSetCount; ++l_i) {
                this->State.mDescriptorSets.erase(observer->read(l_sets, (uint64_t)(l_i)));
            }
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkFreeDescriptorSets coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< uint64_t >(descriptorPool, *observer->getScratch()), descriptorSetCount, toEncoder< gapic::coder::vulkan::VkDescriptorSet__CP >(pDescriptorSets, *observer->getScratch()), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

uint32_t VulkanSpy::vkResetCommandBuffer(CallObserver* observer, VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
    GAPID_DEBUG("vkResetCommandBuffer(%zu, %" PRIu32 ")", commandBuffer, flags);

    if (State.mCommandBuffers.find(commandBuffer) == State.mCommandBuffers.end() ||
    mImports.mVkDeviceFunctions.find(State.mCommandBuffers[commandBuffer]->mDevice) == mImports.mVkDeviceFunctions.end() ||
    mImports.mVkDeviceFunctions[State.mCommandBuffers[commandBuffer]->mDevice].vkResetCommandBuffer == nullptr) {
        GAPID_WARNING("Application called unsupported function vkResetCommandBuffer");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, commandBuffer, flags] {
        called = true;
        observer->observeReads();
        result = mImports.mVkDeviceFunctions[State.mCommandBuffers[commandBuffer]->mDevice].vkResetCommandBuffer(commandBuffer, flags);
        onPostFence(observer);
    };


    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(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkResetCommandBuffer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(commandBuffer, *observer->getScratch()), toEncoder< uint32_t >(flags, *observer->getScratch()), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

void VulkanSpy::vkCmdSetLineWidth(CallObserver* observer, VkCommandBuffer commandBuffer, float lineWidth) {
    GAPID_DEBUG("vkCmdSetLineWidth(%zu, %f)", commandBuffer, lineWidth);

    if (State.mCommandBuffers.find(commandBuffer) == State.mCommandBuffers.end() ||
    mImports.mVkDeviceFunctions.find(State.mCommandBuffers[commandBuffer]->mDevice) == mImports.mVkDeviceFunctions.end() ||
    mImports.mVkDeviceFunctions[State.mCommandBuffers[commandBuffer]->mDevice].vkCmdSetLineWidth == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCmdSetLineWidth");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, commandBuffer, lineWidth] {
        called = true;
        observer->observeReads();
        mImports.mVkDeviceFunctions[State.mCommandBuffers[commandBuffer]->mDevice].vkCmdSetLineWidth(commandBuffer, lineWidth);
        onPostFence(observer);
    };


    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(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkCmdSetLineWidth coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(commandBuffer, *observer->getScratch()), lineWidth);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

uint32_t VulkanSpy::vkGetPhysicalDeviceSurfacePresentModesKHR(CallObserver* observer, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, uint32_t* pPresentModes) {
    GAPID_DEBUG("vkGetPhysicalDeviceSurfacePresentModesKHR(%zu, %" PRIu64 ", %p, %p)", physicalDevice, surface, pPresentModeCount, pPresentModes);

    if (State.mPhysicalDevices.find(physicalDevice) == State.mPhysicalDevices.end() ||
    mImports.mVkInstanceFunctions.find(State.mPhysicalDevices[physicalDevice]->mInstance) == mImports.mVkInstanceFunctions.end() ||
    mImports.mVkInstanceFunctions[State.mPhysicalDevices[physicalDevice]->mInstance].vkGetPhysicalDeviceSurfacePresentModesKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetPhysicalDeviceSurfacePresentModesKHR");
        return 0;
    }

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, physicalDevice, surface, pPresentModeCount, pPresentModes] {
        called = true;
        observer->observeReads();
        result = mImports.mVkInstanceFunctions[State.mPhysicalDevices[physicalDevice]->mInstance].vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, pPresentModes);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            (void)observer->read(slice(pPresentModeCount, 0ULL, 1ULL), 0ULL);
            call();
            if ((pPresentModes) == (nullptr)) {
                observer->write<uint32_t>(slice(pPresentModeCount, 0ULL, 1ULL), 0ULL, slice(pPresentModeCount, 0ULL, 1ULL)[0ULL]);
            } else {
                uint32_t l_count = (uint32_t)(slice(pPresentModeCount, 0ULL, 1ULL)[0ULL]);
                Slice<uint32_t> l_modes = slice(pPresentModes, (uint64_t)(0UL), (uint64_t)(l_count));
                for (uint32_t l_i = 0UL; l_i < l_count; ++l_i) {
                    observer->write<uint32_t>(l_modes, (uint64_t)(l_i), slice(pPresentModes, (uint64_t)(0UL), (uint64_t)(l_count))[(uint64_t)(l_i)]);
                }
                observer->write<uint32_t>(slice(pPresentModeCount, 0ULL, 1ULL), 0ULL, l_count);
            }
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::vulkan::VkGetPhysicalDeviceSurfacePresentModesKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(physicalDevice, *observer->getScratch()), toEncoder< uint64_t >(surface, *observer->getScratch()), toEncoder< gapic::coder::vulkan::U32__P >(pPresentModeCount, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkPresentModeKHR__P >(pPresentModes, *observer->getScratch()), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}
} // namespace gapii