/*
 * 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::vkEnumerateInstanceLayerProperties(CallObserver* observer, uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
    GAPID_DEBUG("vkEnumerateInstanceLayerProperties(%p, %p)", pPropertyCount, pProperties);

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, pPropertyCount, pProperties] {
        called = true;
        observer->observeReads();
        result = SpyOverride_vkEnumerateInstanceLayerProperties(pPropertyCount, pProperties);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            subQueryLayerProperties(observer, call, pPropertyCount, pProperties);
            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::VkEnumerateInstanceLayerProperties coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::vulkan::U32__P >(pPropertyCount, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkLayerProperties__P >(pProperties, *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::vkDestroyFence(CallObserver* observer, VkDevice device, VkFence fence, VkAllocationCallbacks* pAllocator) {
    GAPID_DEBUG("vkDestroyFence(%zu, %" PRIu64 ", %p)", device, fence, pAllocator);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            this->State.mFences.erase(fence);
            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::VkDestroyFence coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< uint64_t >(fence, *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::vkGetImageSubresourceLayout(CallObserver* observer, VkDevice device, VkImage image, VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) {
    GAPID_DEBUG("vkGetImageSubresourceLayout(%zu, %" PRIu64 ", %p, %p)", device, image, pSubresource, pLayout);

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

    bool called = false;
    auto call = [this, observer, &called, device, image, pSubresource, pLayout] {
        called = true;
        observer->observeReads();
        mImports.mVkDeviceFunctions[device].vkGetImageSubresourceLayout(device, image, pSubresource, pLayout);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            (void)observer->read(slice(pSubresource, 0ULL, 1ULL), 0ULL);
            call();
            observer->write<VkSubresourceLayout>(slice(pLayout, 0ULL, 1ULL), 0ULL, slice(pLayout, 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::VkGetImageSubresourceLayout coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< uint64_t >(image, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkImageSubresource__CP >(pSubresource, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkSubresourceLayout__P >(pLayout, *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::vkCreateDescriptorPool(CallObserver* observer, VkDevice device, VkDescriptorPoolCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool) {
    GAPID_DEBUG("vkCreateDescriptorPool(%zu, %p, %p, %p)", device, pCreateInfo, pAllocator, pDescriptorPool);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            VkDescriptorPoolCreateInfo l_info = observer->read(slice(pCreateInfo, 0ULL, 1ULL), 0ULL);
            observer->read(slice(l_info.mpPoolSizes, (uint64_t)(0UL), (uint64_t)(l_info.mpoolSizeCount)));
            call();
            auto l_handle = slice(pDescriptorPool, 0ULL, 1ULL)[0ULL];
            observer->write<VkDescriptorPool>(slice(pDescriptorPool, 0ULL, 1ULL), 0ULL, l_handle);
            this->State.mDescriptorPools[l_handle] = std::shared_ptr<DescriptorPoolObject>(new DescriptorPoolObject(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::VkCreateDescriptorPool coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkDescriptorPoolCreateInfo__CP >(pCreateInfo, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkDescriptorPool__P >(pDescriptorPool, *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::vkCreateCommandPool(CallObserver* observer, VkDevice device, VkCommandPoolCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool) {
    GAPID_DEBUG("vkCreateCommandPool(%zu, %p, %p, %p)", device, pCreateInfo, pAllocator, pCommandPool);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            std::shared_ptr<CommandPoolObject> l_commandPool = subCreateCommandPoolObject(observer, call, pCreateInfo);
            checkNotNull(l_commandPool).mDevice = device;
            call();
            auto l_handle = slice(pCommandPool, 0ULL, 1ULL)[0ULL];
            observer->write<VkCommandPool>(slice(pCommandPool, 0ULL, 1ULL), 0ULL, l_handle);
            this->State.mCommandPools[l_handle] = l_commandPool;
            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::VkCreateCommandPool coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(device, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkCommandPoolCreateInfo__CP >(pCreateInfo, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkAllocationCallbacks__CP >(pAllocator, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkCommandPool__P >(pCommandPool, *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::vkCmdBindIndexBuffer(CallObserver* observer, VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t indexType) {
    GAPID_DEBUG("vkCmdBindIndexBuffer(%zu, %" PRIu64 ", %" PRIu64 ", %u)", commandBuffer, buffer, offset, indexType);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            CmdBindBuffer l_bindBuffer = CmdBindBuffer(U32ToBoundBuffer());
            l_bindBuffer.mBuffers[0UL] = BoundBuffer(buffer, offset);
            addCmd(observer, commandBuffer, l_bindBuffer, &VulkanSpy::subDoCmdBindBuffers);
            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::VkCmdBindIndexBuffer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(commandBuffer, *observer->getScratch()), toEncoder< uint64_t >(buffer, *observer->getScratch()), toEncoder< uint64_t >(offset, *observer->getScratch()), indexType);
    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::vkCmdCopyBuffer(CallObserver* observer, VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, VkBufferCopy* pRegions) {
    GAPID_DEBUG("vkCmdCopyBuffer(%zu, %" PRIu64 ", %" PRIu64 ", %" PRIu32 ", %p)", commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            observer->read(slice(pRegions, (uint64_t)(0UL), (uint64_t)(regionCount)));
            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::VkCmdCopyBuffer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(commandBuffer, *observer->getScratch()), toEncoder< uint64_t >(srcBuffer, *observer->getScratch()), toEncoder< uint64_t >(dstBuffer, *observer->getScratch()), regionCount, toEncoder< gapic::coder::vulkan::VkBufferCopy__CP >(pRegions, *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::vkCmdCopyBufferToImage(CallObserver* observer, VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, uint32_t dstImageLayout, uint32_t regionCount, VkBufferImageCopy* pRegions) {
    GAPID_DEBUG("vkCmdCopyBufferToImage(%zu, %" PRIu64 ", %" PRIu64 ", %u, %" PRIu32 ", %p)", commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);

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

    bool called = false;
    auto call = [this, observer, &called, commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions] {
        called = true;
        observer->observeReads();
        mImports.mVkDeviceFunctions[State.mCommandBuffers[commandBuffer]->mDevice].vkCmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            Slice<VkBufferImageCopy> l_regions = slice(pRegions, (uint64_t)(0UL), (uint64_t)(regionCount));
            observer->read(l_regions);
            CmdCopyBufferToImage l_copyArgs = CmdCopyBufferToImage(srcBuffer, dstImage, U64ToVkBufferImageCopy());
            for (uint32_t l_i = 0UL; l_i < regionCount; ++l_i) {
                l_copyArgs.mRegions[(uint64_t)(l_i)] = observer->read(l_regions, (uint64_t)(l_i));
            }
            addCmd(observer, commandBuffer, l_copyArgs, &VulkanSpy::subDoCmdCopyBufferToImage);
            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::VkCmdCopyBufferToImage coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(commandBuffer, *observer->getScratch()), toEncoder< uint64_t >(srcBuffer, *observer->getScratch()), toEncoder< uint64_t >(dstImage, *observer->getScratch()), dstImageLayout, regionCount, toEncoder< gapic::coder::vulkan::VkBufferImageCopy__CP >(pRegions, *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::vkCmdClearDepthStencilImage(CallObserver* observer, VkCommandBuffer commandBuffer, VkImage image, uint32_t imageLayout, VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, VkImageSubresourceRange* pRanges) {
    GAPID_DEBUG("vkCmdClearDepthStencilImage(%zu, %" PRIu64 ", %u, %p, %" PRIu32 ", %p)", commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);

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

    bool called = false;
    auto call = [this, observer, &called, commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges] {
        called = true;
        observer->observeReads();
        mImports.mVkDeviceFunctions[State.mCommandBuffers[commandBuffer]->mDevice].vkCmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
        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::VkCmdClearDepthStencilImage coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(commandBuffer, *observer->getScratch()), toEncoder< uint64_t >(image, *observer->getScratch()), imageLayout, toEncoder< gapic::coder::vulkan::VkClearDepthStencilValue__CP >(pDepthStencil, *observer->getScratch()), rangeCount, toEncoder< gapic::coder::vulkan::VkImageSubresourceRange__CP >(pRanges, *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::vkCmdBeginQuery(CallObserver* observer, VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags) {
    GAPID_DEBUG("vkCmdBeginQuery(%zu, %" PRIu64 ", %" PRIu32 ", %" PRIu32 ")", commandBuffer, queryPool, query, 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].vkCmdBeginQuery == nullptr) {
        GAPID_WARNING("Application called unsupported function vkCmdBeginQuery");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, commandBuffer, queryPool, query, flags] {
        called = true;
        observer->observeReads();
        mImports.mVkDeviceFunctions[State.mCommandBuffers[commandBuffer]->mDevice].vkCmdBeginQuery(commandBuffer, queryPool, query, flags);
        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::VkCmdBeginQuery coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(commandBuffer, *observer->getScratch()), toEncoder< uint64_t >(queryPool, *observer->getScratch()), query, toEncoder< uint32_t >(flags, *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::vkCmdEndQuery(CallObserver* observer, VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query) {
    GAPID_DEBUG("vkCmdEndQuery(%zu, %" PRIu64 ", %" PRIu32 ")", commandBuffer, queryPool, query);

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

    bool called = false;
    auto call = [this, observer, &called, commandBuffer, queryPool, query] {
        called = true;
        observer->observeReads();
        mImports.mVkDeviceFunctions[State.mCommandBuffers[commandBuffer]->mDevice].vkCmdEndQuery(commandBuffer, queryPool, query);
        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::VkCmdEndQuery coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(commandBuffer, *observer->getScratch()), toEncoder< uint64_t >(queryPool, *observer->getScratch()), query);
    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::vkCmdResetQueryPool(CallObserver* observer, VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
    GAPID_DEBUG("vkCmdResetQueryPool(%zu, %" PRIu64 ", %" PRIu32 ", %" PRIu32 ")", commandBuffer, queryPool, firstQuery, queryCount);

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

    bool called = false;
    auto call = [this, observer, &called, commandBuffer, queryPool, firstQuery, queryCount] {
        called = true;
        observer->observeReads();
        mImports.mVkDeviceFunctions[State.mCommandBuffers[commandBuffer]->mDevice].vkCmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
        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::VkCmdResetQueryPool coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(commandBuffer, *observer->getScratch()), toEncoder< uint64_t >(queryPool, *observer->getScratch()), firstQuery, queryCount);
    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::vkGetDisplayModePropertiesKHR(CallObserver* observer, VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties) {
    GAPID_DEBUG("vkGetDisplayModePropertiesKHR(%zu, %" PRIu64 ", %p, %p)", physicalDevice, display, pPropertyCount, 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].vkGetDisplayModePropertiesKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function vkGetDisplayModePropertiesKHR");
        return 0;
    }

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            (void)observer->read(slice(pPropertyCount, 0ULL, 1ULL), 0ULL);
            call();
            if ((pProperties) == (nullptr)) {
                observer->write<uint32_t>(slice(pPropertyCount, 0ULL, 1ULL), 0ULL, slice(pPropertyCount, 0ULL, 1ULL)[0ULL]);
            } else {
                uint32_t l_count = (uint32_t)(slice(pPropertyCount, 0ULL, 1ULL)[0ULL]);
                Slice<VkDisplayModePropertiesKHR> l_properties = slice(pProperties, (uint64_t)(0UL), (uint64_t)(l_count));
                for (uint32_t l_i = 0UL; l_i < l_count; ++l_i) {
                    observer->write<VkDisplayModePropertiesKHR>(l_properties, (uint64_t)(l_i), slice(pProperties, (uint64_t)(0UL), (uint64_t)(l_count))[(uint64_t)(l_i)]);
                }
                observer->write<uint32_t>(slice(pPropertyCount, 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::VkGetDisplayModePropertiesKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(physicalDevice, *observer->getScratch()), toEncoder< uint64_t >(display, *observer->getScratch()), toEncoder< gapic::coder::vulkan::U32__P >(pPropertyCount, *observer->getScratch()), toEncoder< gapic::coder::vulkan::VkDisplayModePropertiesKHR__P >(pProperties, *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::vkDebugReportMessageEXT(CallObserver* observer, VkInstance instance, VkDebugReportFlagsEXT flags, uint32_t objectType, uint64_t object, size_val location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage) {
    GAPID_DEBUG("vkDebugReportMessageEXT(%zu, %" PRIu32 ", %u, %" PRIu64 ", %zu, %" PRId32 ", %s, %s)", instance, flags, objectType, object, location, messageCode, pLayerPrefix, pMessage);

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

    bool called = false;
    auto call = [this, observer, &called, instance, flags, objectType, object, location, messageCode, pLayerPrefix, pMessage] {
        called = true;
        observer->observeReads();
        mImports.mVkInstanceFunctions[instance].vkDebugReportMessageEXT(instance, flags, objectType, object, location, messageCode, pLayerPrefix, pMessage);
        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::VkDebugReportMessageEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< size_val >(instance, *observer->getScratch()), toEncoder< uint32_t >(flags, *observer->getScratch()), objectType, object, location, messageCode, toEncoder< const char* >(pLayerPrefix, *observer->getScratch()), toEncoder< const char* >(pMessage, *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);

}
} // namespace gapii