/*
 * 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 "gles_imports.h"
#include "gles_types.h"

#include "gles_spy.h"

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

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

#include <stdint.h>

#include <memory>
#include <string>

namespace gapii {

void GlesSpy::glBlendBarrierKHR(CallObserver* observer) {
    GAPID_DEBUG("glBlendBarrierKHR()");

    if (mImports.glBlendBarrierKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function glBlendBarrierKHR");
        return;
    }

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_KHR_blend_equation_advanced);
            subBlendBarrier(observer, call);
            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::gles::GlBlendBarrierKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras));
    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 GlesSpy::glEnableiEXT(CallObserver* observer, uint32_t target, GLuint index) {
    GAPID_DEBUG("glEnableiEXT(%u, %" PRIu32 ")", target, index);

    if (mImports.glEnableiEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glEnableiEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, index] {
        called = true;
        observer->observeReads();
        mImports.glEnableiEXT(target, index);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_draw_buffers_indexed);
            subEnablei(observer, call, target, index);
            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::gles::GlEnableiEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< uint32_t >(index, *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 GlesSpy::glFramebufferTextureEXT(CallObserver* observer, uint32_t target, uint32_t attachment, TextureId texture, GLint level) {
    GAPID_DEBUG("glFramebufferTextureEXT(%u, %u, %" PRIu32 ", %" PRId32 ")", target, attachment, texture, level);

    if (mImports.glFramebufferTextureEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glFramebufferTextureEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, attachment, texture, level] {
        called = true;
        observer->observeReads();
        mImports.glFramebufferTextureEXT(target, attachment, texture, level);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_geometry_shader);
            subFramebufferTexture(observer, call, target, attachment, texture, level);
            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::gles::GlFramebufferTextureEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, attachment, toEncoder< uint32_t >(texture, *observer->getScratch()), toEncoder< int32_t >(level, *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 GlesSpy::glGetSamplerParameterIuivEXT(CallObserver* observer, SamplerId sampler, uint32_t pname, GLuint* params) {
    GAPID_DEBUG("glGetSamplerParameterIuivEXT(%" PRIu32 ", %u, %p)", sampler, pname, params);

    if (mImports.glGetSamplerParameterIuivEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetSamplerParameterIuivEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, sampler, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glGetSamplerParameterIuivEXT(sampler, pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_texture_border_clamp);
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            call();
            subGetSamplerParameterIuiv(observer, call, sampler, pname, params);
        } 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::gles::GlGetSamplerParameterIuivEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(sampler, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLuint__P >(params, *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 GlesSpy::glMinSampleShadingOES(CallObserver* observer, GLfloat value) {
    GAPID_DEBUG("glMinSampleShadingOES(%f)", value);

    if (mImports.glMinSampleShadingOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glMinSampleShadingOES");
        return;
    }

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_sample_shading);
            subMinSampleShading(observer, call, value);
            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::gles::GlMinSampleShadingOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< float >(value, *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 GlesSpy::glPushDebugGroupKHR(CallObserver* observer, uint32_t source, GLuint id, GLsizei length, GLchar* message) {
    GAPID_DEBUG("glPushDebugGroupKHR(%u, %" PRIu32 ", %" PRId32 ", %p)", source, id, length, message);

    if (mImports.glPushDebugGroupKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function glPushDebugGroupKHR");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, source, id, length, message] {
        called = true;
        observer->observeReads();
        mImports.glPushDebugGroupKHR(source, id, length, message);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_KHR_debug);
            subPushDebugGroup(observer, call, source, id, length, message);
            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::gles::GlPushDebugGroupKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), source, toEncoder< uint32_t >(id, *observer->getScratch()), toEncoder< int32_t >(length, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__CP >(message, *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 GlesSpy::glTexStorage3DMultisampleOES(CallObserver* observer, uint32_t target, GLsizei samples, uint32_t internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) {
    GAPID_DEBUG("glTexStorage3DMultisampleOES(%u, %" PRId32 ", %u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRIu8 ")", target, samples, internalformat, width, height, depth, fixedsamplelocations);

    if (mImports.glTexStorage3DMultisampleOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glTexStorage3DMultisampleOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, samples, internalformat, width, height, depth, fixedsamplelocations] {
        called = true;
        observer->observeReads();
        mImports.glTexStorage3DMultisampleOES(target, samples, internalformat, width, height, depth, fixedsamplelocations);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_texture_storage_multisample_2d_array);
            subTexStorage3DMultisample(observer, call, target, samples, internalformat, width, height, depth, fixedsamplelocations);
            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::gles::GlTexStorage3DMultisampleOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(samples, *observer->getScratch()), internalformat, toEncoder< int32_t >(width, *observer->getScratch()), toEncoder< int32_t >(height, *observer->getScratch()), toEncoder< int32_t >(depth, *observer->getScratch()), toEncoder< uint8_t >(fixedsamplelocations, *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 GlesSpy::glGetQueryObjectuiv(CallObserver* observer, QueryId query, uint32_t parameter, GLuint* value) {
    GAPID_DEBUG("glGetQueryObjectuiv(%" PRIu32 ", %u, %p)", query, parameter, value);

    if (mImports.glGetQueryObjectuiv == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetQueryObjectuiv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, query, parameter, value] {
        called = true;
        observer->observeReads();
        mImports.glGetQueryObjectuiv(query, parameter, value);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            switch (parameter) {
                case GLenum::GL_QUERY_RESULT: // fall-through...
                case GLenum::GL_QUERY_RESULT_AVAILABLE: {
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, parameter);
                }
            }
            call();
            observer->write<GLuint>(slice(value, 0ULL, 1ULL), 0ULL, slice(value, 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::gles::GlGetQueryObjectuiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(query, *observer->getScratch()), parameter, toEncoder< gapic::coder::gles::GLuint__P >(value, *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);

}

GLboolean GlesSpy::glUnmapBuffer(CallObserver* observer, uint32_t target) {
    GAPID_DEBUG("glUnmapBuffer(%u)", target);

    if (mImports.glUnmapBuffer == nullptr) {
        GAPID_WARNING("Application called unsupported function glUnmapBuffer");
        return 0;
    }

    GLboolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, target] {
        called = true;
        observer->observeReads();
        result = mImports.glUnmapBuffer(target);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subUnmapBuffer(observer, call, target);
            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::gles::GlUnmapBuffer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< uint8_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 GlesSpy::glDebugMessageCallback(CallObserver* observer, GLDEBUGPROC callback, void* userParam) {
    GAPID_DEBUG("glDebugMessageCallback(%p, %p)", callback, userParam);

    if (mImports.glDebugMessageCallback == nullptr) {
        GAPID_WARNING("Application called unsupported function glDebugMessageCallback");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, callback, userParam] {
        called = true;
        observer->observeReads();
        mImports.glDebugMessageCallback(callback, userParam);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            subDebugMessageCallback(observer, call, callback, userParam);
            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::gles::GlDebugMessageCallback coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::GLDEBUGPROC >(callback, *observer->getScratch()), toEncoder< gapic::coder::gles::Void__CP >(userParam, *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 GlesSpy::glGetPointerv(CallObserver* observer, uint32_t pname, void** params) {
    GAPID_DEBUG("glGetPointerv(%u, %p)", pname, params);

    if (mImports.glGetPointerv == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetPointerv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glGetPointerv(pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            call();
            subGetPointerv(observer, call, pname, params);
        } 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::gles::GlGetPointerv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< gapic::coder::gles::Void__P__P >(params, *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 GlesSpy::glPopDebugGroup(CallObserver* observer) {
    GAPID_DEBUG("glPopDebugGroup()");

    if (mImports.glPopDebugGroup == nullptr) {
        GAPID_WARNING("Application called unsupported function glPopDebugGroup");
        return;
    }

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            subPopDebugGroup(observer, call);
            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::gles::GlPopDebugGroup coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras));
    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 GlesSpy::glDrawElementsIndirect(CallObserver* observer, uint32_t draw_mode, uint32_t indices_type, void* indirect) {
    GAPID_DEBUG("glDrawElementsIndirect(%u, %u, %p)", draw_mode, indices_type, indirect);

    if (mImports.glDrawElementsIndirect == nullptr) {
        GAPID_WARNING("Application called unsupported function glDrawElementsIndirect");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, draw_mode, indices_type, indirect] {
        called = true;
        observer->observeReads();
        mImports.glDrawElementsIndirect(draw_mode, indices_type, indirect);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subCheckPrimitiveType(observer, call, draw_mode);
            subCheckIndicesType(observer, call, indices_type);
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            if ((checkNotNull(l_ctx).mBoundVertexArray) == ((VertexArrayId)(0UL))) {
                subGlErrorInvalidOperation(observer, call);
            }
            if ((checkNotNull(l_ctx).mBoundBuffers.mDrawIndirectBuffer) == ((BufferId)(0UL))) {
                subGlErrorInvalidOperation(observer, call);
            }
            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::gles::GlDrawElementsIndirect coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), draw_mode, indices_type, toEncoder< gapic::coder::gles::Void__CP >(indirect, *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);
    onPostDrawCall();

}

EGLBoolean GlesSpy::eglSignalSyncKHR(CallObserver* observer, EGLDisplay dpy, EGLSyncKHR sync, uint32_t mode) {
    GAPID_DEBUG("eglSignalSyncKHR(%p, %p, %u)", dpy, sync, mode);

    if (mImports.eglSignalSyncKHR == nullptr) {
        GAPID_WARNING("Application called unsupported function eglSignalSyncKHR");
        return 0;
    }

    EGLBoolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, dpy, sync, mode] {
        called = true;
        observer->observeReads();
        result = mImports.eglSignalSyncKHR(dpy, sync, mode);
        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::gles::EglSignalSyncKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::EGLDisplay >(dpy, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLSyncKHR >(sync, *observer->getScratch()), mode, toEncoder< int >(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 GlesSpy::glBlendEquationiOES(CallObserver* observer, DrawBufferIndex buf, uint32_t mode) {
    GAPID_DEBUG("glBlendEquationiOES(%" PRIu32 ", %u)", buf, mode);

    if (mImports.glBlendEquationiOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glBlendEquationiOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, buf, mode] {
        called = true;
        observer->observeReads();
        mImports.glBlendEquationiOES(buf, mode);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_draw_buffers_indexed);
            subBlendEquationi(observer, call, buf, mode);
            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::gles::GlBlendEquationiOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(buf, *observer->getScratch()), mode);
    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 GlesSpy::glBlendFunciOES(CallObserver* observer, DrawBufferIndex buf, uint32_t src, uint32_t dst) {
    GAPID_DEBUG("glBlendFunciOES(%" PRIu32 ", %u, %u)", buf, src, dst);

    if (mImports.glBlendFunciOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glBlendFunciOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, buf, src, dst] {
        called = true;
        observer->observeReads();
        mImports.glBlendFunciOES(buf, src, dst);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_draw_buffers_indexed);
            subBlendFunci(observer, call, buf, src, dst);
            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::gles::GlBlendFunciOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(buf, *observer->getScratch()), src, dst);
    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 GlesSpy::glBlendParameteriNV(CallObserver* observer, uint32_t pname, GLint value) {
    GAPID_DEBUG("glBlendParameteriNV(%u, %" PRId32 ")", pname, value);

    if (mImports.glBlendParameteriNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glBlendParameteriNV");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, pname, value] {
        called = true;
        observer->observeReads();
        mImports.glBlendParameteriNV(pname, value);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_blend_equation_advanced);
            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::gles::GlBlendParameteriNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< int32_t >(value, *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 GlesSpy::glBlitFramebufferANGLE(CallObserver* observer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, uint32_t mask, uint32_t filter) {
    GAPID_DEBUG("glBlitFramebufferANGLE(%" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %u, %u)", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);

    if (mImports.glBlitFramebufferANGLE == nullptr) {
        GAPID_WARNING("Application called unsupported function glBlitFramebufferANGLE");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter] {
        called = true;
        observer->observeReads();
        mImports.glBlitFramebufferANGLE(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_ANGLE_framebuffer_blit);
            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::gles::GlBlitFramebufferANGLE coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(srcX0, *observer->getScratch()), toEncoder< int32_t >(srcY0, *observer->getScratch()), toEncoder< int32_t >(srcX1, *observer->getScratch()), toEncoder< int32_t >(srcY1, *observer->getScratch()), toEncoder< int32_t >(dstX0, *observer->getScratch()), toEncoder< int32_t >(dstY0, *observer->getScratch()), toEncoder< int32_t >(dstX1, *observer->getScratch()), toEncoder< int32_t >(dstY1, *observer->getScratch()), mask, filter);
    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 GlesSpy::glCopyImageSubDataOES(CallObserver* observer, GLuint srcName, uint32_t srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, uint32_t dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) {
    GAPID_DEBUG("glCopyImageSubDataOES(%" PRIu32 ", %u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRIu32 ", %u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);

    if (mImports.glCopyImageSubDataOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glCopyImageSubDataOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth] {
        called = true;
        observer->observeReads();
        mImports.glCopyImageSubDataOES(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_copy_image);
            subCopyImageSubData(observer, call, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
            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::gles::GlCopyImageSubDataOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(srcName, *observer->getScratch()), srcTarget, toEncoder< int32_t >(srcLevel, *observer->getScratch()), toEncoder< int32_t >(srcX, *observer->getScratch()), toEncoder< int32_t >(srcY, *observer->getScratch()), toEncoder< int32_t >(srcZ, *observer->getScratch()), toEncoder< uint32_t >(dstName, *observer->getScratch()), dstTarget, toEncoder< int32_t >(dstLevel, *observer->getScratch()), toEncoder< int32_t >(dstX, *observer->getScratch()), toEncoder< int32_t >(dstY, *observer->getScratch()), toEncoder< int32_t >(dstZ, *observer->getScratch()), toEncoder< int32_t >(srcWidth, *observer->getScratch()), toEncoder< int32_t >(srcHeight, *observer->getScratch()), toEncoder< int32_t >(srcDepth, *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 GlesSpy::glCopyTextureLevelsAPPLE(CallObserver* observer, GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount) {
    GAPID_DEBUG("glCopyTextureLevelsAPPLE(%" PRIu32 ", %" PRIu32 ", %" PRId32 ", %" PRId32 ")", destinationTexture, sourceTexture, sourceBaseLevel, sourceLevelCount);

    if (mImports.glCopyTextureLevelsAPPLE == nullptr) {
        GAPID_WARNING("Application called unsupported function glCopyTextureLevelsAPPLE");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, destinationTexture, sourceTexture, sourceBaseLevel, sourceLevelCount] {
        called = true;
        observer->observeReads();
        mImports.glCopyTextureLevelsAPPLE(destinationTexture, sourceTexture, sourceBaseLevel, sourceLevelCount);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_APPLE_copy_texture_levels);
            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::gles::GlCopyTextureLevelsAPPLE coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(destinationTexture, *observer->getScratch()), toEncoder< uint32_t >(sourceTexture, *observer->getScratch()), toEncoder< int32_t >(sourceBaseLevel, *observer->getScratch()), toEncoder< int32_t >(sourceLevelCount, *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 GlesSpy::glCoverFillPathNV(CallObserver* observer, GLuint path, uint32_t coverMode) {
    GAPID_DEBUG("glCoverFillPathNV(%" PRIu32 ", %u)", path, coverMode);

    if (mImports.glCoverFillPathNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glCoverFillPathNV");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, path, coverMode] {
        called = true;
        observer->observeReads();
        mImports.glCoverFillPathNV(path, coverMode);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_path_rendering);
            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::gles::GlCoverFillPathNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *observer->getScratch()), coverMode);
    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 GlesSpy::glCoverStrokePathInstancedNV(CallObserver* observer, GLsizei numPaths, uint32_t pathNameType, void* paths, GLuint pathBase, uint32_t coverMode, uint32_t transformType, GLfloat* transformValues) {
    GAPID_DEBUG("glCoverStrokePathInstancedNV(%" PRId32 ", %u, %p, %" PRIu32 ", %u, %u, %p)", numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues);

    if (mImports.glCoverStrokePathInstancedNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glCoverStrokePathInstancedNV");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues] {
        called = true;
        observer->observeReads();
        mImports.glCoverStrokePathInstancedNV(numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_path_rendering);
            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::gles::GlCoverStrokePathInstancedNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(numPaths, *observer->getScratch()), pathNameType, toEncoder< gapic::coder::gles::Void__CP >(paths, *observer->getScratch()), toEncoder< uint32_t >(pathBase, *observer->getScratch()), coverMode, transformType, toEncoder< gapic::coder::gles::GLfloat__CP >(transformValues, *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 GlesSpy::glDrawBuffersIndexedEXT(CallObserver* observer, GLint n, uint32_t* location, GLint* indices) {
    GAPID_DEBUG("glDrawBuffersIndexedEXT(%" PRId32 ", %p, %p)", n, location, indices);

    if (mImports.glDrawBuffersIndexedEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glDrawBuffersIndexedEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, n, location, indices] {
        called = true;
        observer->observeReads();
        mImports.glDrawBuffersIndexedEXT(n, location, indices);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_multiview_draw_buffers);
            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::gles::GlDrawBuffersIndexedEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(n, *observer->getScratch()), toEncoder< gapic::coder::gles::GLenum__CP >(location, *observer->getScratch()), toEncoder< gapic::coder::gles::GLint__CP >(indices, *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 GlesSpy::glExtGetTexturesQCOM(CallObserver* observer, TextureId* textures, GLint maxTextures, GLint* numTextures) {
    GAPID_DEBUG("glExtGetTexturesQCOM(%p, %" PRId32 ", %p)", textures, maxTextures, numTextures);

    if (mImports.glExtGetTexturesQCOM == nullptr) {
        GAPID_WARNING("Application called unsupported function glExtGetTexturesQCOM");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, textures, maxTextures, numTextures] {
        called = true;
        observer->observeReads();
        mImports.glExtGetTexturesQCOM(textures, maxTextures, numTextures);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_QCOM_extended_get);
            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::gles::GlExtGetTexturesQCOM coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::TextureId__P >(textures, *observer->getScratch()), toEncoder< int32_t >(maxTextures, *observer->getScratch()), toEncoder< gapic::coder::gles::GLint__P >(numTextures, *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 GlesSpy::glGetNextPerfQueryIdINTEL(CallObserver* observer, GLuint queryId, GLuint* nextQueryId) {
    GAPID_DEBUG("glGetNextPerfQueryIdINTEL(%" PRIu32 ", %p)", queryId, nextQueryId);

    if (mImports.glGetNextPerfQueryIdINTEL == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetNextPerfQueryIdINTEL");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, queryId, nextQueryId] {
        called = true;
        observer->observeReads();
        mImports.glGetNextPerfQueryIdINTEL(queryId, nextQueryId);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_INTEL_performance_query);
            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::gles::GlGetNextPerfQueryIdINTEL coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(queryId, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__P >(nextQueryId, *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 GlesSpy::glGetPathCommandsNV(CallObserver* observer, GLuint path, GLubyte* commands) {
    GAPID_DEBUG("glGetPathCommandsNV(%" PRIu32 ", %p)", path, commands);

    if (mImports.glGetPathCommandsNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetPathCommandsNV");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, path, commands] {
        called = true;
        observer->observeReads();
        mImports.glGetPathCommandsNV(path, commands);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_path_rendering);
            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::gles::GlGetPathCommandsNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *observer->getScratch()), toEncoder< gapic::coder::gles::GLubyte__P >(commands, *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 GlesSpy::glGetPathCoordsNV(CallObserver* observer, GLuint path, GLfloat* coords) {
    GAPID_DEBUG("glGetPathCoordsNV(%" PRIu32 ", %p)", path, coords);

    if (mImports.glGetPathCoordsNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetPathCoordsNV");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, path, coords] {
        called = true;
        observer->observeReads();
        mImports.glGetPathCoordsNV(path, coords);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_path_rendering);
            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::gles::GlGetPathCoordsNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__P >(coords, *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 GlesSpy::glGetPerfMonitorCounterDataAMD(CallObserver* observer, GLuint monitor, uint32_t pname, GLsizei dataSize, GLuint* data, GLint* bytesWritten) {
    GAPID_DEBUG("glGetPerfMonitorCounterDataAMD(%" PRIu32 ", %u, %" PRId32 ", %p, %p)", monitor, pname, dataSize, data, bytesWritten);

    if (mImports.glGetPerfMonitorCounterDataAMD == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetPerfMonitorCounterDataAMD");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, monitor, pname, dataSize, data, bytesWritten] {
        called = true;
        observer->observeReads();
        mImports.glGetPerfMonitorCounterDataAMD(monitor, pname, dataSize, data, bytesWritten);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_AMD_performance_monitor);
            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::gles::GlGetPerfMonitorCounterDataAMD coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(monitor, *observer->getScratch()), pname, toEncoder< int32_t >(dataSize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__P >(data, *observer->getScratch()), toEncoder< gapic::coder::gles::GLint__P >(bytesWritten, *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 GlesSpy::glGetPerfMonitorCounterInfoAMD(CallObserver* observer, GLuint group, GLuint counter, uint32_t pname, void* data) {
    GAPID_DEBUG("glGetPerfMonitorCounterInfoAMD(%" PRIu32 ", %" PRIu32 ", %u, %p)", group, counter, pname, data);

    if (mImports.glGetPerfMonitorCounterInfoAMD == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetPerfMonitorCounterInfoAMD");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, group, counter, pname, data] {
        called = true;
        observer->observeReads();
        mImports.glGetPerfMonitorCounterInfoAMD(group, counter, pname, data);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_AMD_performance_monitor);
            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::gles::GlGetPerfMonitorCounterInfoAMD coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(group, *observer->getScratch()), toEncoder< uint32_t >(counter, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::Void__P >(data, *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 GlesSpy::glGetQueryObjecti64vEXT(CallObserver* observer, QueryId query, uint32_t parameter, GLint64* value) {
    GAPID_DEBUG("glGetQueryObjecti64vEXT(%" PRIu32 ", %u, %p)", query, parameter, value);

    if (mImports.glGetQueryObjecti64vEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetQueryObjecti64vEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, query, parameter, value] {
        called = true;
        observer->observeReads();
        mImports.glGetQueryObjecti64vEXT(query, parameter, value);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_disjoint_timer_query);
            call();
            observer->write<GLint64>(slice(value, 0ULL, 1ULL), 0ULL, slice(value, 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::gles::GlGetQueryObjecti64vEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(query, *observer->getScratch()), parameter, toEncoder< gapic::coder::gles::GLint64__P >(value, *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 GlesSpy::glGetTexParameterIivOES(CallObserver* observer, uint32_t target, uint32_t pname, GLint* params) {
    GAPID_DEBUG("glGetTexParameterIivOES(%u, %u, %p)", target, pname, params);

    if (mImports.glGetTexParameterIivOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetTexParameterIivOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glGetTexParameterIivOES(target, pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_texture_border_clamp);
            call();
            subGetTexParameterIiv(observer, call, target, pname, params);
        } 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::gles::GlGetTexParameterIivOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, pname, toEncoder< gapic::coder::gles::GLint__P >(params, *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);

}

GLuint64 GlesSpy::glGetTextureHandleNV(CallObserver* observer, TextureId texture) {
    GAPID_DEBUG("glGetTextureHandleNV(%" PRIu32 ")", texture);

    if (mImports.glGetTextureHandleNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetTextureHandleNV");
        return 0;
    }

    GLuint64 result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, texture] {
        called = true;
        observer->observeReads();
        result = mImports.glGetTextureHandleNV(texture);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_bindless_texture);
            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::gles::GlGetTextureHandleNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(texture, *observer->getScratch()), toEncoder< uint64_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 GlesSpy::glInterpolatePathsNV(CallObserver* observer, GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight) {
    GAPID_DEBUG("glInterpolatePathsNV(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %f)", resultPath, pathA, pathB, weight);

    if (mImports.glInterpolatePathsNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glInterpolatePathsNV");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, resultPath, pathA, pathB, weight] {
        called = true;
        observer->observeReads();
        mImports.glInterpolatePathsNV(resultPath, pathA, pathB, weight);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_path_rendering);
            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::gles::GlInterpolatePathsNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(resultPath, *observer->getScratch()), toEncoder< uint32_t >(pathA, *observer->getScratch()), toEncoder< uint32_t >(pathB, *observer->getScratch()), toEncoder< float >(weight, *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);

}

GLboolean GlesSpy::glIsEnablediOES(CallObserver* observer, uint32_t target, GLuint index) {
    GAPID_DEBUG("glIsEnablediOES(%u, %" PRIu32 ")", target, index);

    if (mImports.glIsEnablediOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glIsEnablediOES");
        return 0;
    }

    GLboolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, target, index] {
        called = true;
        observer->observeReads();
        result = mImports.glIsEnablediOES(target, index);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_draw_buffers_indexed);
            GLboolean l__res_0 = subIsEnabledi(observer, call, target, index);
            call();
            if (UNLIKELY(shouldComputeExpectedReturn())) {
                setExpectedReturn<GLboolean>(l__res_0);
            }
            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::gles::GlIsEnablediOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< uint8_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;
}

GLboolean GlesSpy::glIsFenceNV(CallObserver* observer, GLuint fence) {
    GAPID_DEBUG("glIsFenceNV(%" PRIu32 ")", fence);

    if (mImports.glIsFenceNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glIsFenceNV");
        return 0;
    }

    GLboolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, fence] {
        called = true;
        observer->observeReads();
        result = mImports.glIsFenceNV(fence);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_fence);
            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::gles::GlIsFenceNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(fence, *observer->getScratch()), toEncoder< uint8_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;
}

GLboolean GlesSpy::glIsProgramPipelineEXT(CallObserver* observer, PipelineId pipeline) {
    GAPID_DEBUG("glIsProgramPipelineEXT(%" PRIu32 ")", pipeline);

    if (mImports.glIsProgramPipelineEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glIsProgramPipelineEXT");
        return 0;
    }

    GLboolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, pipeline] {
        called = true;
        observer->observeReads();
        result = mImports.glIsProgramPipelineEXT(pipeline);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            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::gles::GlIsProgramPipelineEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(pipeline, *observer->getScratch()), toEncoder< uint8_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;
}

GLboolean GlesSpy::glIsSyncAPPLE(CallObserver* observer, GLsync sync) {
    GAPID_DEBUG("glIsSyncAPPLE(%p)", sync);

    if (mImports.glIsSyncAPPLE == nullptr) {
        GAPID_WARNING("Application called unsupported function glIsSyncAPPLE");
        return 0;
    }

    GLboolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, sync] {
        called = true;
        observer->observeReads();
        result = mImports.glIsSyncAPPLE(sync);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_APPLE_sync);
            GLboolean l__res_0 = subIsSync(observer, call, sync);
            call();
            if (UNLIKELY(shouldComputeExpectedReturn())) {
                setExpectedReturn<GLboolean>(l__res_0);
            }
            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::gles::GlIsSyncAPPLE coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::GLsync >(sync, *observer->getScratch()), toEncoder< uint8_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;
}

GLboolean GlesSpy::glIsTextureHandleResidentNV(CallObserver* observer, GLuint64 handle) {
    GAPID_DEBUG("glIsTextureHandleResidentNV(%" PRIu64 ")", handle);

    if (mImports.glIsTextureHandleResidentNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glIsTextureHandleResidentNV");
        return 0;
    }

    GLboolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, handle] {
        called = true;
        observer->observeReads();
        result = mImports.glIsTextureHandleResidentNV(handle);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_bindless_texture);
            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::gles::GlIsTextureHandleResidentNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint64_t >(handle, *observer->getScratch()), toEncoder< uint8_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* GlesSpy::glMapBufferOES(CallObserver* observer, uint32_t target, uint32_t access) {
    GAPID_DEBUG("glMapBufferOES(%u, %u)", target, access);

    if (mImports.glMapBufferOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glMapBufferOES");
        return nullptr;
    }

    void* result = nullptr;
    bool called = false;
    auto call = [this, observer, &called, &result, target, access] {
        called = true;
        observer->observeReads();
        result = mImports.glMapBufferOES(target, access);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_mapbuffer);
            call();
            auto l_ptr = result;
            subMapBuffer(observer, call, target, access, (uint8_t*)(l_ptr));
            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::gles::GlMapBufferOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, access, toEncoder< gapic::coder::gles::Void__P >(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 GlesSpy::glMultiDrawElementsEXT(CallObserver* observer, uint32_t mode, GLsizei* count, uint32_t type, void** indices, GLsizei primcount) {
    GAPID_DEBUG("glMultiDrawElementsEXT(%u, %p, %u, %p, %" PRId32 ")", mode, count, type, indices, primcount);

    if (mImports.glMultiDrawElementsEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glMultiDrawElementsEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, mode, count, type, indices, primcount] {
        called = true;
        observer->observeReads();
        mImports.glMultiDrawElementsEXT(mode, count, type, indices, primcount);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_multi_draw_arrays);
            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::gles::GlMultiDrawElementsEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), mode, toEncoder< gapic::coder::gles::GLsizei__CP >(count, *observer->getScratch()), type, toEncoder< gapic::coder::gles::Void__CP__CP >(indices, *observer->getScratch()), toEncoder< int32_t >(primcount, *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 GlesSpy::glPatchParameteriOES(CallObserver* observer, uint32_t pname, GLint value) {
    GAPID_DEBUG("glPatchParameteriOES(%u, %" PRId32 ")", pname, value);

    if (mImports.glPatchParameteriOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glPatchParameteriOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, pname, value] {
        called = true;
        observer->observeReads();
        mImports.glPatchParameteriOES(pname, value);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_tessellation_shader);
            subPatchParameteri(observer, call, pname, value);
            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::gles::GlPatchParameteriOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< int32_t >(value, *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 GlesSpy::glPathParameterivNV(CallObserver* observer, GLuint path, uint32_t pname, GLint* value) {
    GAPID_DEBUG("glPathParameterivNV(%" PRIu32 ", %u, %p)", path, pname, value);

    if (mImports.glPathParameterivNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glPathParameterivNV");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, path, pname, value] {
        called = true;
        observer->observeReads();
        mImports.glPathParameterivNV(path, pname, value);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_path_rendering);
            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::gles::GlPathParameterivNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLint__CP >(value, *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 GlesSpy::glPathSubCommandsNV(CallObserver* observer, GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, GLubyte* commands, GLsizei numCoords, uint32_t coordType, void* coords) {
    GAPID_DEBUG("glPathSubCommandsNV(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %p, %" PRId32 ", %u, %p)", path, commandStart, commandsToDelete, numCommands, commands, numCoords, coordType, coords);

    if (mImports.glPathSubCommandsNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glPathSubCommandsNV");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, path, commandStart, commandsToDelete, numCommands, commands, numCoords, coordType, coords] {
        called = true;
        observer->observeReads();
        mImports.glPathSubCommandsNV(path, commandStart, commandsToDelete, numCommands, commands, numCoords, coordType, coords);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_path_rendering);
            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::gles::GlPathSubCommandsNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *observer->getScratch()), toEncoder< int32_t >(commandStart, *observer->getScratch()), toEncoder< int32_t >(commandsToDelete, *observer->getScratch()), toEncoder< int32_t >(numCommands, *observer->getScratch()), toEncoder< gapic::coder::gles::GLubyte__CP >(commands, *observer->getScratch()), toEncoder< int32_t >(numCoords, *observer->getScratch()), coordType, toEncoder< gapic::coder::gles::Void__CP >(coords, *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 GlesSpy::glPathSubCoordsNV(CallObserver* observer, GLuint path, GLsizei coordStart, GLsizei numCoords, uint32_t coordType, void* coords) {
    GAPID_DEBUG("glPathSubCoordsNV(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %u, %p)", path, coordStart, numCoords, coordType, coords);

    if (mImports.glPathSubCoordsNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glPathSubCoordsNV");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, path, coordStart, numCoords, coordType, coords] {
        called = true;
        observer->observeReads();
        mImports.glPathSubCoordsNV(path, coordStart, numCoords, coordType, coords);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_path_rendering);
            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::gles::GlPathSubCoordsNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *observer->getScratch()), toEncoder< int32_t >(coordStart, *observer->getScratch()), toEncoder< int32_t >(numCoords, *observer->getScratch()), coordType, toEncoder< gapic::coder::gles::Void__CP >(coords, *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 GlesSpy::glProgramPathFragmentInputGenNV(CallObserver* observer, ProgramId program, GLint location, uint32_t genMode, GLint components, GLfloat* coeffs) {
    GAPID_DEBUG("glProgramPathFragmentInputGenNV(%" PRIu32 ", %" PRId32 ", %u, %" PRId32 ", %p)", program, location, genMode, components, coeffs);

    if (mImports.glProgramPathFragmentInputGenNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramPathFragmentInputGenNV");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, location, genMode, components, coeffs] {
        called = true;
        observer->observeReads();
        mImports.glProgramPathFragmentInputGenNV(program, location, genMode, components, coeffs);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_path_rendering);
            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::gles::GlProgramPathFragmentInputGenNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), genMode, toEncoder< int32_t >(components, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__CP >(coeffs, *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 GlesSpy::glProgramUniform1iEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLint v0) {
    GAPID_DEBUG("glProgramUniform1iEXT(%" PRIu32 ", %" PRId32 ", %" PRId32 ")", program, location, v0);

    if (mImports.glProgramUniform1iEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramUniform1iEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, location, v0] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniform1iEXT(program, location, v0);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniform1i(observer, call, program, location, v0);
            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::gles::GlProgramUniform1iEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(v0, *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 GlesSpy::glProgramUniform4fEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
    GAPID_DEBUG("glProgramUniform4fEXT(%" PRIu32 ", %" PRId32 ", %f, %f, %f, %f)", program, location, v0, v1, v2, v3);

    if (mImports.glProgramUniform4fEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramUniform4fEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, location, v0, v1, v2, v3] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniform4fEXT(program, location, v0, v1, v2, v3);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniform4f(observer, call, program, location, v0, v1, v2, v3);
            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::gles::GlProgramUniform4fEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< float >(v0, *observer->getScratch()), toEncoder< float >(v1, *observer->getScratch()), toEncoder< float >(v2, *observer->getScratch()), toEncoder< float >(v3, *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 GlesSpy::glProgramUniform4uiEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
    GAPID_DEBUG("glProgramUniform4uiEXT(%" PRIu32 ", %" PRId32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", program, location, v0, v1, v2, v3);

    if (mImports.glProgramUniform4uiEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramUniform4uiEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, location, v0, v1, v2, v3] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniform4uiEXT(program, location, v0, v1, v2, v3);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniform4ui(observer, call, program, location, v0, v1, v2, v3);
            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::gles::GlProgramUniform4uiEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< uint32_t >(v0, *observer->getScratch()), toEncoder< uint32_t >(v1, *observer->getScratch()), toEncoder< uint32_t >(v2, *observer->getScratch()), toEncoder< uint32_t >(v3, *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 GlesSpy::glProgramUniformMatrix3x4fvEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* value) {
    GAPID_DEBUG("glProgramUniformMatrix3x4fvEXT(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", program, location, count, transpose, value);

    if (mImports.glProgramUniformMatrix3x4fvEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramUniformMatrix3x4fvEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, location, count, transpose, value] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniformMatrix3x4fvEXT(program, location, count, transpose, value);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniformMatrix3x4fv(observer, call, program, location, count, transpose, value);
            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::gles::GlProgramUniformMatrix3x4fvEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< uint8_t >(transpose, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__CP >(value, *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 GlesSpy::glProgramUniformMatrix4x3fvEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* value) {
    GAPID_DEBUG("glProgramUniformMatrix4x3fvEXT(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", program, location, count, transpose, value);

    if (mImports.glProgramUniformMatrix4x3fvEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramUniformMatrix4x3fvEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, location, count, transpose, value] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniformMatrix4x3fvEXT(program, location, count, transpose, value);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniformMatrix4x3fv(observer, call, program, location, count, transpose, value);
            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::gles::GlProgramUniformMatrix4x3fvEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< uint8_t >(transpose, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__CP >(value, *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 GlesSpy::glRenderbufferStorageMultisampleANGLE(CallObserver* observer, uint32_t target, GLsizei samples, uint32_t internalformat, GLsizei width, GLsizei height) {
    GAPID_DEBUG("glRenderbufferStorageMultisampleANGLE(%u, %" PRId32 ", %u, %" PRId32 ", %" PRId32 ")", target, samples, internalformat, width, height);

    if (mImports.glRenderbufferStorageMultisampleANGLE == nullptr) {
        GAPID_WARNING("Application called unsupported function glRenderbufferStorageMultisampleANGLE");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, samples, internalformat, width, height] {
        called = true;
        observer->observeReads();
        mImports.glRenderbufferStorageMultisampleANGLE(target, samples, internalformat, width, height);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_ANGLE_framebuffer_multisample);
            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::gles::GlRenderbufferStorageMultisampleANGLE coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(samples, *observer->getScratch()), internalformat, toEncoder< int32_t >(width, *observer->getScratch()), toEncoder< int32_t >(height, *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 GlesSpy::glRenderbufferStorageMultisampleEXT(CallObserver* observer, uint32_t target, GLsizei samples, uint32_t internalformat, GLsizei width, GLsizei height) {
    GAPID_DEBUG("glRenderbufferStorageMultisampleEXT(%u, %" PRId32 ", %u, %" PRId32 ", %" PRId32 ")", target, samples, internalformat, width, height);

    if (mImports.glRenderbufferStorageMultisampleEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glRenderbufferStorageMultisampleEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, samples, internalformat, width, height] {
        called = true;
        observer->observeReads();
        mImports.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_multisampled_render_to_texture);
            subRenderbufferStorageMultisample(observer, call, target, samples, internalformat, width, height);
            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::gles::GlRenderbufferStorageMultisampleEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(samples, *observer->getScratch()), internalformat, toEncoder< int32_t >(width, *observer->getScratch()), toEncoder< int32_t >(height, *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 GlesSpy::glRenderbufferStorageMultisampleIMG(CallObserver* observer, uint32_t target, GLsizei samples, uint32_t internalformat, GLsizei width, GLsizei height) {
    GAPID_DEBUG("glRenderbufferStorageMultisampleIMG(%u, %" PRId32 ", %u, %" PRId32 ", %" PRId32 ")", target, samples, internalformat, width, height);

    if (mImports.glRenderbufferStorageMultisampleIMG == nullptr) {
        GAPID_WARNING("Application called unsupported function glRenderbufferStorageMultisampleIMG");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, samples, internalformat, width, height] {
        called = true;
        observer->observeReads();
        mImports.glRenderbufferStorageMultisampleIMG(target, samples, internalformat, width, height);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_IMG_multisampled_render_to_texture);
            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::gles::GlRenderbufferStorageMultisampleIMG coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(samples, *observer->getScratch()), internalformat, toEncoder< int32_t >(width, *observer->getScratch()), toEncoder< int32_t >(height, *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 GlesSpy::glSetFenceNV(CallObserver* observer, GLuint fence, uint32_t condition) {
    GAPID_DEBUG("glSetFenceNV(%" PRIu32 ", %u)", fence, condition);

    if (mImports.glSetFenceNV == nullptr) {
        GAPID_WARNING("Application called unsupported function glSetFenceNV");
        return;
    }

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_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::gles::GlSetFenceNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(fence, *observer->getScratch()), condition);
    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 GlesSpy::glUseProgramStagesEXT(CallObserver* observer, PipelineId pipeline, uint32_t stages, ProgramId program) {
    GAPID_DEBUG("glUseProgramStagesEXT(%" PRIu32 ", %u, %" PRIu32 ")", pipeline, stages, program);

    if (mImports.glUseProgramStagesEXT == nullptr) {
        GAPID_WARNING("Application called unsupported function glUseProgramStagesEXT");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, pipeline, stages, program] {
        called = true;
        observer->observeReads();
        mImports.glUseProgramStagesEXT(pipeline, stages, program);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            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::gles::GlUseProgramStagesEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(pipeline, *observer->getScratch()), stages, toEncoder< uint32_t >(program, *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 GlesSpy::glBlendEquation(CallObserver* observer, uint32_t equation) {
    GAPID_DEBUG("glBlendEquation(%u)", equation);

    if (mImports.glBlendEquation == nullptr) {
        GAPID_WARNING("Application called unsupported function glBlendEquation");
        return;
    }

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            subSetBlendEquation(observer, call, (DrawBufferIndex)(0UL), int32_t((checkNotNull(l_ctx).mFragmentOperations.mBlend.size())), equation, equation);
            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::gles::GlBlendEquation coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), equation);
    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 GlesSpy::glBlendFunc(CallObserver* observer, uint32_t src_factor, uint32_t dst_factor) {
    GAPID_DEBUG("glBlendFunc(%u, %u)", src_factor, dst_factor);

    if (mImports.glBlendFunc == nullptr) {
        GAPID_WARNING("Application called unsupported function glBlendFunc");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, src_factor, dst_factor] {
        called = true;
        observer->observeReads();
        mImports.glBlendFunc(src_factor, dst_factor);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            subSetBlendFunc(observer, call, (DrawBufferIndex)(0UL), int32_t((checkNotNull(l_ctx).mFragmentOperations.mBlend.size())), src_factor, dst_factor, src_factor, dst_factor);
            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::gles::GlBlendFunc coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), src_factor, dst_factor);
    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 GlesSpy::glSampleMaski(CallObserver* observer, GLuint maskNumber, uint32_t mask) {
    GAPID_DEBUG("glSampleMaski(%" PRIu32 ", %u)", maskNumber, mask);

    if (mImports.glSampleMaski == nullptr) {
        GAPID_WARNING("Application called unsupported function glSampleMaski");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, maskNumber, mask] {
        called = true;
        observer->observeReads();
        mImports.glSampleMaski(maskNumber, mask);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            checkNotNull(l_ctx).mRasterization.mSampleMaskValue[maskNumber] = mask;
            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::gles::GlSampleMaski coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(maskNumber, *observer->getScratch()), mask);
    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 GlesSpy::glBindRenderbuffer(CallObserver* observer, uint32_t target, RenderbufferId renderbuffer) {
    GAPID_DEBUG("glBindRenderbuffer(%u, %" PRIu32 ")", target, renderbuffer);

    if (mImports.glBindRenderbuffer == nullptr) {
        GAPID_WARNING("Application called unsupported function glBindRenderbuffer");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, renderbuffer] {
        called = true;
        observer->observeReads();
        mImports.glBindRenderbuffer(target, renderbuffer);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            switch (target) {
                case GLenum::GL_RENDERBUFFER: {
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, target);
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            if (!(checkNotNull(l_ctx).mInstances.mRenderbuffers.count(renderbuffer) > 0)) {
                checkNotNull(l_ctx).mInstances.mRenderbuffers[renderbuffer] = std::shared_ptr<Renderbuffer>(new Renderbuffer(Slice<uint8_t>(), (GLsizei)(0L), (GLsizei)(0L), GLenum::GL_RGBA4, ""));
            }
            checkNotNull(l_ctx).mBoundRenderbuffers[target] = renderbuffer;
            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::gles::GlBindRenderbuffer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< uint32_t >(renderbuffer, *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 GlesSpy::glDepthMask(CallObserver* observer, GLboolean enabled) {
    GAPID_DEBUG("glDepthMask(%" PRIu8 ")", enabled);

    if (mImports.glDepthMask == nullptr) {
        GAPID_WARNING("Application called unsupported function glDepthMask");
        return;
    }

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            checkNotNull(l_ctx).mFramebuffer.mDepthWritemask = enabled;
            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::gles::GlDepthMask coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint8_t >(enabled, *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 GlesSpy::glFramebufferParameteri(CallObserver* observer, uint32_t target, uint32_t pname, GLint param) {
    GAPID_DEBUG("glFramebufferParameteri(%u, %u, %" PRId32 ")", target, pname, param);

    if (mImports.glFramebufferParameteri == nullptr) {
        GAPID_WARNING("Application called unsupported function glFramebufferParameteri");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glFramebufferParameteri(target, pname, param);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            std::shared_ptr<Framebuffer> l_framebuffer = subGetBoundFramebufferOrErrorInvalidEnum(observer, call, target);
            bool l__res_0 = subIsDefaultFramebuffer(observer, call, l_framebuffer);
            if (l__res_0) {
                subGlErrorInvalidOperation(observer, call);
            }
            switch (pname) {
                case GLenum::GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS: {
                    checkNotNull(l_framebuffer).mDefaultFixedSampleLocations = (GLboolean)(param);
                    break;
                }
                case GLenum::GL_FRAMEBUFFER_DEFAULT_HEIGHT: {
                    checkNotNull(l_framebuffer).mDefaultHeight = param;
                    break;
                }
                case GLenum::GL_FRAMEBUFFER_DEFAULT_SAMPLES: {
                    checkNotNull(l_framebuffer).mDefaultSamples = param;
                    break;
                }
                case GLenum::GL_FRAMEBUFFER_DEFAULT_WIDTH: {
                    checkNotNull(l_framebuffer).mDefaultWidth = param;
                    break;
                }
                case GLenum::GL_FRAMEBUFFER_DEFAULT_LAYERS: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    checkNotNull(l_framebuffer).mDefaultLayers = param;
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, pname);
                }
            }
            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::gles::GlFramebufferParameteri coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, pname, toEncoder< int32_t >(param, *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 GlesSpy::glGenRenderbuffers(CallObserver* observer, GLsizei count, RenderbufferId* renderbuffers) {
    GAPID_DEBUG("glGenRenderbuffers(%" PRId32 ", %p)", count, renderbuffers);

    if (mImports.glGenRenderbuffers == nullptr) {
        GAPID_WARNING("Application called unsupported function glGenRenderbuffers");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, count, renderbuffers] {
        called = true;
        observer->observeReads();
        mImports.glGenRenderbuffers(count, renderbuffers);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            if ((count) < ((GLsizei)(0L))) {
                subGlErrorInvalidValue(observer, call);
            }
            Slice<RenderbufferId> l_r = slice(renderbuffers, (uint64_t)((GLsizei)(0L)), (uint64_t)(count));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            call();
            for (GLsizei l_i = (GLsizei)(0L); l_i < count; ++l_i) {
                RenderbufferId l_id = (RenderbufferId)(slice(renderbuffers, (uint64_t)((GLsizei)(0L)), (uint64_t)(count))[(uint64_t)(l_i)]);
                checkNotNull(l_ctx).mInstances.mRenderbuffers[l_id] = std::shared_ptr<Renderbuffer>(new Renderbuffer(Slice<uint8_t>(), (GLsizei)(0L), (GLsizei)(0L), GLenum::GL_RGBA4, ""));
                observer->write<RenderbufferId>(l_r, (uint64_t)(l_i), l_id);
            }
        } 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::gles::GlGenRenderbuffers coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::RenderbufferId__P >(renderbuffers, *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 GlesSpy::glGetFramebufferParameteriv(CallObserver* observer, uint32_t target, uint32_t pname, GLint* params) {
    GAPID_DEBUG("glGetFramebufferParameteriv(%u, %u, %p)", target, pname, params);

    if (mImports.glGetFramebufferParameteriv == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetFramebufferParameteriv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glGetFramebufferParameteriv(target, pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            switch (pname) {
                case GLenum::GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS: // fall-through...
                case GLenum::GL_FRAMEBUFFER_DEFAULT_HEIGHT: // fall-through...
                case GLenum::GL_FRAMEBUFFER_DEFAULT_SAMPLES: // fall-through...
                case GLenum::GL_FRAMEBUFFER_DEFAULT_WIDTH: {
                    break;
                }
                case GLenum::GL_FRAMEBUFFER_DEFAULT_LAYERS: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, pname);
                }
            }
            std::shared_ptr<Framebuffer> l_framebuffer = subGetBoundFramebufferOrErrorInvalidEnum(observer, call, target);
            bool l__res_0 = subIsDefaultFramebuffer(observer, call, l_framebuffer);
            if (l__res_0) {
                subGlErrorInvalidOperation(observer, call);
            }
            call();
            observer->write<GLint>(slice(params, 0ULL, 1ULL), 0ULL, /* switch(pname) */
                /* case GLenum::GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS: */(((pname) == (GLenum::GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS))) ? ((GLint)(checkNotNull(l_framebuffer).mDefaultFixedSampleLocations)) :
                /* case GLenum::GL_FRAMEBUFFER_DEFAULT_HEIGHT: */(((pname) == (GLenum::GL_FRAMEBUFFER_DEFAULT_HEIGHT))) ? (checkNotNull(l_framebuffer).mDefaultHeight) :
                /* case GLenum::GL_FRAMEBUFFER_DEFAULT_SAMPLES: */(((pname) == (GLenum::GL_FRAMEBUFFER_DEFAULT_SAMPLES))) ? (checkNotNull(l_framebuffer).mDefaultSamples) :
                /* case GLenum::GL_FRAMEBUFFER_DEFAULT_WIDTH: */(((pname) == (GLenum::GL_FRAMEBUFFER_DEFAULT_WIDTH))) ? (checkNotNull(l_framebuffer).mDefaultWidth) :
                /* case GLenum::GL_FRAMEBUFFER_DEFAULT_LAYERS: */(((pname) == (GLenum::GL_FRAMEBUFFER_DEFAULT_LAYERS))) ? (checkNotNull(l_framebuffer).mDefaultLayers) :
                /* default: */ 0);
        } 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::gles::GlGetFramebufferParameteriv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, pname, toEncoder< gapic::coder::gles::GLint__P >(params, *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 GlesSpy::glStencilMaskSeparate(CallObserver* observer, uint32_t face, GLuint mask) {
    GAPID_DEBUG("glStencilMaskSeparate(%u, %" PRIu32 ")", face, mask);

    if (mImports.glStencilMaskSeparate == nullptr) {
        GAPID_WARNING("Application called unsupported function glStencilMaskSeparate");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, face, mask] {
        called = true;
        observer->observeReads();
        mImports.glStencilMaskSeparate(face, mask);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            switch (face) {
                case GLenum::GL_BACK: {
                    checkNotNull(l_ctx).mFramebuffer.mStencilBackWritemask = mask;
                    break;
                }
                case GLenum::GL_FRONT: {
                    checkNotNull(l_ctx).mFramebuffer.mStencilWritemask = mask;
                    break;
                }
                case GLenum::GL_FRONT_AND_BACK: {
                    checkNotNull(l_ctx).mFramebuffer.mStencilWritemask = mask;
                    checkNotNull(l_ctx).mFramebuffer.mStencilBackWritemask = mask;
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, face);
                }
            }
            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::gles::GlStencilMaskSeparate coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), face, toEncoder< uint32_t >(mask, *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 GlesSpy::glHint(CallObserver* observer, uint32_t target, uint32_t mode) {
    GAPID_DEBUG("glHint(%u, %u)", target, mode);

    if (mImports.glHint == nullptr) {
        GAPID_WARNING("Application called unsupported function glHint");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, mode] {
        called = true;
        observer->observeReads();
        mImports.glHint(target, mode);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            switch (mode) {
                case GLenum::GL_DONT_CARE: // fall-through...
                case GLenum::GL_FASTEST: // fall-through...
                case GLenum::GL_NICEST: {
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, mode);
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            switch (target) {
                case GLenum::GL_GENERATE_MIPMAP_HINT: {
                    subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
                    checkNotNull(l_ctx).mMiscellaneous.mGenerateMipmapHint = mode;
                    break;
                }
                case GLenum::GL_FRAGMENT_SHADER_DERIVATIVE_HINT: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    checkNotNull(l_ctx).mMiscellaneous.mFragmentShaderDerivativeHint = mode;
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, target);
                }
            }
            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::gles::GlHint coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, mode);
    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 GlesSpy::glGetProgramPipelineiv(CallObserver* observer, PipelineId pipeline, uint32_t pname, GLint* params) {
    GAPID_DEBUG("glGetProgramPipelineiv(%" PRIu32 ", %u, %p)", pipeline, pname, params);

    if (mImports.glGetProgramPipelineiv == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetProgramPipelineiv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, pipeline, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glGetProgramPipelineiv(pipeline, pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            switch (pname) {
                case GLenum::GL_ACTIVE_PROGRAM: // fall-through...
                case GLenum::GL_COMPUTE_SHADER: // fall-through...
                case GLenum::GL_FRAGMENT_SHADER: // fall-through...
                case GLenum::GL_INFO_LOG_LENGTH: // fall-through...
                case GLenum::GL_VALIDATE_STATUS: // fall-through...
                case GLenum::GL_VERTEX_SHADER: {
                    break;
                }
                case GLenum::GL_GEOMETRY_SHADER: // fall-through...
                case GLenum::GL_TESS_CONTROL_SHADER: // fall-through...
                case GLenum::GL_TESS_EVALUATION_SHADER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, pname);
                }
            }
            call();
            observer->write<GLint>(slice(params, 0ULL, 1ULL), 0ULL, slice(params, 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::gles::GlGetProgramPipelineiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(pipeline, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLint__P >(params, *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 GlesSpy::glGetShaderInfoLog(CallObserver* observer, ShaderId shader, GLsizei buffer_length, GLsizei* string_length_written, GLchar* info) {
    GAPID_DEBUG("glGetShaderInfoLog(%" PRIu32 ", %" PRId32 ", %p, %p)", shader, buffer_length, string_length_written, info);

    if (mImports.glGetShaderInfoLog == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetShaderInfoLog");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, shader, buffer_length, string_length_written, info] {
        called = true;
        observer->observeReads();
        mImports.glGetShaderInfoLog(shader, buffer_length, string_length_written, info);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            subCheckShader(observer, call, l_ctx, shader);
            if ((buffer_length) < ((GLsizei)(0L))) {
                subGlErrorInvalidValue(observer, call);
            }
            call();
            subWriteString(observer, call, buffer_length, string_length_written, info);
        } 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::gles::GlGetShaderInfoLog coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(shader, *observer->getScratch()), toEncoder< int32_t >(buffer_length, *observer->getScratch()), toEncoder< gapic::coder::gles::GLsizei__P >(string_length_written, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__P >(info, *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 GlesSpy::glGetUniformIndices(CallObserver* observer, ProgramId program, GLsizei uniformCount, GLchar** uniformNames, UniformIndex* uniformIndices) {
    GAPID_DEBUG("glGetUniformIndices(%" PRIu32 ", %" PRId32 ", %p, %p)", program, uniformCount, uniformNames, uniformIndices);

    if (mImports.glGetUniformIndices == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetUniformIndices");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, uniformCount, uniformNames, uniformIndices] {
        called = true;
        observer->observeReads();
        mImports.glGetUniformIndices(program, uniformCount, uniformNames, uniformIndices);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            Slice<GLchar*> l_names = slice(uniformNames, (uint64_t)((GLsizei)(0L)), (uint64_t)(uniformCount));
            for (GLsizei l_i = (GLsizei)(0L); l_i < uniformCount; ++l_i) {
                (void)observer->string((char*)(observer->read(l_names, (uint64_t)(l_i))));
            }
            call();
            observer->write(slice(uniformIndices, (uint64_t)((GLsizei)(0L)), (uint64_t)(uniformCount)));
        } 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::gles::GlGetUniformIndices coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(uniformCount, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__CP__CP >(uniformNames, *observer->getScratch()), toEncoder< gapic::coder::gles::UniformIndex__P >(uniformIndices, *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);

}

GLboolean GlesSpy::glIsShader(CallObserver* observer, ShaderId shader) {
    GAPID_DEBUG("glIsShader(%" PRIu32 ")", shader);

    if (mImports.glIsShader == nullptr) {
        GAPID_WARNING("Application called unsupported function glIsShader");
        return 0;
    }

    GLboolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, shader] {
        called = true;
        observer->observeReads();
        result = mImports.glIsShader(shader);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            call();
            if (UNLIKELY(shouldComputeExpectedReturn())) {
                setExpectedReturn<GLboolean>((GLboolean)(checkNotNull(l_ctx).mInstances.mShaders.count(shader) > 0));
            }
            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::gles::GlIsShader coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(shader, *observer->getScratch()), toEncoder< uint8_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 GlesSpy::glProgramBinary(CallObserver* observer, ProgramId program, uint32_t binaryFormat, void* binary, GLsizei length) {
    GAPID_DEBUG("glProgramBinary(%" PRIu32 ", %u, %p, %" PRId32 ")", program, binaryFormat, binary, length);

    if (mImports.glProgramBinary == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramBinary");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, binaryFormat, binary, length] {
        called = true;
        observer->observeReads();
        mImports.glProgramBinary(program, binaryFormat, binary, length);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            call();
            subProgramBinary(observer, call, program, binaryFormat, binary, length);
        } 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::gles::GlProgramBinary coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), binaryFormat, toEncoder< gapic::coder::gles::Void__CP >(binary, *observer->getScratch()), toEncoder< int32_t >(length, *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 GlesSpy::glProgramUniform1uiv(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLuint* values) {
    GAPID_DEBUG("glProgramUniform1uiv(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, values);

    if (mImports.glProgramUniform1uiv == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramUniform1uiv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, location, count, values] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniform1uiv(program, location, count, values);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subProgramUniform1uiv(observer, call, program, location, count, values);
            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::gles::GlProgramUniform1uiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__CP >(values, *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 GlesSpy::glProgramUniform2i(CallObserver* observer, ProgramId program, UniformLocation location, GLint value0, GLint value1) {
    GAPID_DEBUG("glProgramUniform2i(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", program, location, value0, value1);

    if (mImports.glProgramUniform2i == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramUniform2i");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, location, value0, value1] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniform2i(program, location, value0, value1);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subProgramUniform2i(observer, call, program, location, value0, value1);
            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::gles::GlProgramUniform2i coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(value0, *observer->getScratch()), toEncoder< int32_t >(value1, *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 GlesSpy::glProgramUniform3f(CallObserver* observer, ProgramId program, UniformLocation location, GLfloat value0, GLfloat value1, GLfloat value2) {
    GAPID_DEBUG("glProgramUniform3f(%" PRIu32 ", %" PRId32 ", %f, %f, %f)", program, location, value0, value1, value2);

    if (mImports.glProgramUniform3f == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramUniform3f");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, location, value0, value1, value2] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniform3f(program, location, value0, value1, value2);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subProgramUniform3f(observer, call, program, location, value0, value1, value2);
            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::gles::GlProgramUniform3f coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< float >(value0, *observer->getScratch()), toEncoder< float >(value1, *observer->getScratch()), toEncoder< float >(value2, *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 GlesSpy::glProgramUniformMatrix2x4fv(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* values) {
    GAPID_DEBUG("glProgramUniformMatrix2x4fv(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", program, location, count, transpose, values);

    if (mImports.glProgramUniformMatrix2x4fv == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramUniformMatrix2x4fv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, location, count, transpose, values] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniformMatrix2x4fv(program, location, count, transpose, values);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subProgramUniformMatrix2x4fv(observer, call, program, location, count, transpose, values);
            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::gles::GlProgramUniformMatrix2x4fv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< uint8_t >(transpose, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__CP >(values, *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 GlesSpy::glProgramUniformMatrix4x2fv(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* values) {
    GAPID_DEBUG("glProgramUniformMatrix4x2fv(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", program, location, count, transpose, values);

    if (mImports.glProgramUniformMatrix4x2fv == nullptr) {
        GAPID_WARNING("Application called unsupported function glProgramUniformMatrix4x2fv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, location, count, transpose, values] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniformMatrix4x2fv(program, location, count, transpose, values);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subProgramUniformMatrix4x2fv(observer, call, program, location, count, transpose, values);
            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::gles::GlProgramUniformMatrix4x2fv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< uint8_t >(transpose, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__CP >(values, *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 GlesSpy::glUniform1ui(CallObserver* observer, UniformLocation location, GLuint value0) {
    GAPID_DEBUG("glUniform1ui(%" PRId32 ", %" PRIu32 ")", location, value0);

    if (mImports.glUniform1ui == nullptr) {
        GAPID_WARNING("Application called unsupported function glUniform1ui");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, location, value0] {
        called = true;
        observer->observeReads();
        mImports.glUniform1ui(location, value0);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            Slice<GLuint> l_v = make<GLuint>(1ULL);
            observer->write<GLuint>(l_v, 0ULL, value0);
            subUniformv_GLuint__S(observer, call, location, l_v, GLenum::GL_UNSIGNED_INT);
            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::gles::GlUniform1ui coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< uint32_t >(value0, *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 GlesSpy::glUniform2iv(CallObserver* observer, UniformLocation location, GLsizei count, GLint* values) {
    GAPID_DEBUG("glUniform2iv(%" PRId32 ", %" PRId32 ", %p)", location, count, values);

    if (mImports.glUniform2iv == nullptr) {
        GAPID_WARNING("Application called unsupported function glUniform2iv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, location, count, values] {
        called = true;
        observer->observeReads();
        mImports.glUniform2iv(location, count, values);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            Slice<Vec2i> l_v = slice((Vec2i*)(values), (uint64_t)((GLsizei)(0L)), (uint64_t)(count));
            subUniformv_Vec2i__S(observer, call, location, l_v, GLenum::GL_INT_VEC2);
            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::gles::GlUniform2iv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::GLint__CP >(values, *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 GlesSpy::glUniform3fv(CallObserver* observer, UniformLocation location, GLsizei count, GLfloat* values) {
    GAPID_DEBUG("glUniform3fv(%" PRId32 ", %" PRId32 ", %p)", location, count, values);

    if (mImports.glUniform3fv == nullptr) {
        GAPID_WARNING("Application called unsupported function glUniform3fv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, location, count, values] {
        called = true;
        observer->observeReads();
        mImports.glUniform3fv(location, count, values);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            Slice<Vec3f> l_v = slice((Vec3f*)(values), (uint64_t)((GLsizei)(0L)), (uint64_t)(count));
            subUniformv_Vec3f__S(observer, call, location, l_v, GLenum::GL_FLOAT_VEC3);
            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::gles::GlUniform3fv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__CP >(values, *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 GlesSpy::glUniformMatrix2fv(CallObserver* observer, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* values) {
    GAPID_DEBUG("glUniformMatrix2fv(%" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", location, count, transpose, values);

    if (mImports.glUniformMatrix2fv == nullptr) {
        GAPID_WARNING("Application called unsupported function glUniformMatrix2fv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, location, count, transpose, values] {
        called = true;
        observer->observeReads();
        mImports.glUniformMatrix2fv(location, count, transpose, values);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            Slice<Mat2f> l_v = slice((Mat2f*)(values), (uint64_t)((GLsizei)(0L)), (uint64_t)(count));
            subUniformMatrixv_Mat2f__S(observer, call, location, transpose, l_v, GLenum::GL_FLOAT_MAT2);
            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::gles::GlUniformMatrix2fv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< uint8_t >(transpose, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__CP >(values, *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 GlesSpy::glPolygonOffset(CallObserver* observer, GLfloat scale_factor, GLfloat units) {
    GAPID_DEBUG("glPolygonOffset(%f, %f)", scale_factor, units);

    if (mImports.glPolygonOffset == nullptr) {
        GAPID_WARNING("Application called unsupported function glPolygonOffset");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, scale_factor, units] {
        called = true;
        observer->observeReads();
        mImports.glPolygonOffset(scale_factor, units);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            checkNotNull(l_ctx).mRasterization.mPolygonOffsetUnits = units;
            checkNotNull(l_ctx).mRasterization.mPolygonOffsetFactor = scale_factor;
            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::gles::GlPolygonOffset coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< float >(scale_factor, *observer->getScratch()), toEncoder< float >(units, *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);

}

GLboolean GlesSpy::glIsEnabled(CallObserver* observer, uint32_t capability) {
    GAPID_DEBUG("glIsEnabled(%u)", capability);

    if (mImports.glIsEnabled == nullptr) {
        GAPID_WARNING("Application called unsupported function glIsEnabled");
        return 0;
    }

    GLboolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, capability] {
        called = true;
        observer->observeReads();
        result = mImports.glIsEnabled(capability);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            GLboolean l__res_0 = subGetCapability(observer, call, capability, (GLuint)(0UL));
            call();
            if (UNLIKELY(shouldComputeExpectedReturn())) {
                setExpectedReturn<GLboolean>(l__res_0);
            }
            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::gles::GlIsEnabled coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), capability, toEncoder< uint8_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 GlesSpy::glGetSamplerParameterIiv(CallObserver* observer, SamplerId sampler, uint32_t pname, GLint* params) {
    GAPID_DEBUG("glGetSamplerParameterIiv(%" PRIu32 ", %u, %p)", sampler, pname, params);

    if (mImports.glGetSamplerParameterIiv == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetSamplerParameterIiv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, sampler, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glGetSamplerParameterIiv(sampler, pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            call();
            subGetSamplerParameterIiv(observer, call, sampler, pname, params);
        } 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::gles::GlGetSamplerParameterIiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(sampler, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLint__P >(params, *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 GlesSpy::glTexImage3D(CallObserver* observer, uint32_t target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, uint32_t format, uint32_t type, TexturePointer data) {
    GAPID_DEBUG("glTexImage3D(%u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %u, %u, %p)", target, level, internalformat, width, height, depth, border, format, type, data);

    if (mImports.glTexImage3D == nullptr) {
        GAPID_WARNING("Application called unsupported function glTexImage3D");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, level, internalformat, width, height, depth, border, format, type, data] {
        called = true;
        observer->observeReads();
        mImports.glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, data);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subTexImage3D(observer, call, target, level, internalformat, width, height, depth, border, format, type, data);
            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::gles::GlTexImage3D coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(level, *observer->getScratch()), toEncoder< int32_t >(internalformat, *observer->getScratch()), toEncoder< int32_t >(width, *observer->getScratch()), toEncoder< int32_t >(height, *observer->getScratch()), toEncoder< int32_t >(depth, *observer->getScratch()), toEncoder< int32_t >(border, *observer->getScratch()), format, type, toEncoder< gapic::coder::gles::TexturePointer >(data, *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 GlesSpy::glTexParameterIuiv(CallObserver* observer, uint32_t target, uint32_t pname, GLuint* params) {
    GAPID_DEBUG("glTexParameterIuiv(%u, %u, %p)", target, pname, params);

    if (mImports.glTexParameterIuiv == nullptr) {
        GAPID_WARNING("Application called unsupported function glTexParameterIuiv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glTexParameterIuiv(target, pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            subTexParameterIuiv(observer, call, target, pname, params);
            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::gles::GlTexParameterIuiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, pname, toEncoder< gapic::coder::gles::GLuint__CP >(params, *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 GlesSpy::glTexSubImage3D(CallObserver* observer, uint32_t target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, uint32_t format, uint32_t type, TexturePointer data) {
    GAPID_DEBUG("glTexSubImage3D(%u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %u, %u, %p)", target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);

    if (mImports.glTexSubImage3D == nullptr) {
        GAPID_WARNING("Application called unsupported function glTexSubImage3D");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data] {
        called = true;
        observer->observeReads();
        mImports.glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subTexSubImage3D(observer, call, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
            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::gles::GlTexSubImage3D coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(level, *observer->getScratch()), toEncoder< int32_t >(xoffset, *observer->getScratch()), toEncoder< int32_t >(yoffset, *observer->getScratch()), toEncoder< int32_t >(zoffset, *observer->getScratch()), toEncoder< int32_t >(width, *observer->getScratch()), toEncoder< int32_t >(height, *observer->getScratch()), toEncoder< int32_t >(depth, *observer->getScratch()), format, type, toEncoder< gapic::coder::gles::TexturePointer >(data, *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 GlesSpy::glGetTransformFeedbackVarying(CallObserver* observer, ProgramId program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, uint32_t* type, GLchar* name) {
    GAPID_DEBUG("glGetTransformFeedbackVarying(%" PRIu32 ", %" PRIu32 ", %" PRId32 ", %p, %p, %p, %p)", program, index, bufSize, length, size, type, name);

    if (mImports.glGetTransformFeedbackVarying == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetTransformFeedbackVarying");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, program, index, bufSize, length, size, type, name] {
        called = true;
        observer->observeReads();
        mImports.glGetTransformFeedbackVarying(program, index, bufSize, length, size, type, name);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            call();
            subWriteString(observer, call, bufSize, length, name);
            observer->write<GLsizei>(slice(size, 0ULL, 1ULL), 0ULL, slice(size, 0ULL, 1ULL)[0ULL]);
            observer->write<uint32_t>(slice(type, 0ULL, 1ULL), 0ULL, slice(type, 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::gles::GlGetTransformFeedbackVarying coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< int32_t >(bufSize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLsizei__P >(length, *observer->getScratch()), toEncoder< gapic::coder::gles::GLsizei__P >(size, *observer->getScratch()), toEncoder< gapic::coder::gles::GLenum__P >(type, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__P >(name, *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 GlesSpy::glPauseTransformFeedback(CallObserver* observer) {
    GAPID_DEBUG("glPauseTransformFeedback()");

    if (mImports.glPauseTransformFeedback == nullptr) {
        GAPID_WARNING("Application called unsupported function glPauseTransformFeedback");
        return;
    }

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            std::shared_ptr<TransformFeedback> l__res_0 = subGetBoundTransformFeedback(observer, call);
            checkNotNull(l__res_0).mPaused = (GLboolean)(1U);
            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::gles::GlPauseTransformFeedback coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras));
    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 GlesSpy::glGetVertexAttribiv(CallObserver* observer, AttributeLocation index, uint32_t pname, GLint* params) {
    GAPID_DEBUG("glGetVertexAttribiv(%" PRIu32 ", %u, %p)", index, pname, params);

    if (mImports.glGetVertexAttribiv == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetVertexAttribiv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, index, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glGetVertexAttribiv(index, pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            if ((index) >= ((AttributeLocation)(checkNotNull(l_ctx).mConstants.mMaxVertexAttribs))) {
                subGlErrorInvalidValue(observer, call);
            }
            call();
            if ((pname) == (GLenum::GL_CURRENT_VERTEX_ATTRIB)) {
                observer->write(slice(params, 0ULL, 4ULL));
            } else {
                uint64_t l__res_0 = subGetVertexAttrib(observer, call, l_ctx, index, pname);
                observer->write<GLint>(slice(params, 0ULL, 1ULL), 0ULL, (GLint)(l__res_0));
            }
        } 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::gles::GlGetVertexAttribiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLint__P >(params, *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 GlesSpy::glVertexAttrib1fv(CallObserver* observer, AttributeLocation location, GLfloat* value) {
    GAPID_DEBUG("glVertexAttrib1fv(%" PRIu32 ", %p)", location, value);

    if (mImports.glVertexAttrib1fv == nullptr) {
        GAPID_WARNING("Application called unsupported function glVertexAttrib1fv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, location, value] {
        called = true;
        observer->observeReads();
        mImports.glVertexAttrib1fv(location, value);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            Slice<GLfloat> l_v = slice(value, 0ULL, 1ULL);
            Vec4f l_vec = {observer->read(l_v, 0ULL), (GLfloat)(0.f), (GLfloat)(0.f), (GLfloat)(1.f)};
            subVertexAttribF(observer, call, location, l_vec);
            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::gles::GlVertexAttrib1fv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(location, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__CP >(value, *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 GlesSpy::glVertexAttribFormat(CallObserver* observer, AttributeLocation index, GLint size, uint32_t type, GLboolean normalized, GLuint relativeoffset) {
    GAPID_DEBUG("glVertexAttribFormat(%" PRIu32 ", %" PRId32 ", %u, %" PRIu8 ", %" PRIu32 ")", index, size, type, normalized, relativeoffset);

    if (mImports.glVertexAttribFormat == nullptr) {
        GAPID_WARNING("Application called unsupported function glVertexAttribFormat");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, index, size, type, normalized, relativeoffset] {
        called = true;
        observer->observeReads();
        mImports.glVertexAttribFormat(index, size, type, normalized, relativeoffset);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            if ((checkNotNull(l_ctx).mBoundVertexArray) == ((VertexArrayId)(0UL))) {
                subGlErrorInvalidOperation(observer, call);
            }
            subVertexAttribFormat(observer, call, l_ctx, index, size, type, normalized, relativeoffset, false);
            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::gles::GlVertexAttribFormat coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< int32_t >(size, *observer->getScratch()), type, toEncoder< uint8_t >(normalized, *observer->getScratch()), toEncoder< uint32_t >(relativeoffset, *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 GlesSpy::glVertexAttribI4uiv(CallObserver* observer, AttributeLocation index, GLuint* values) {
    GAPID_DEBUG("glVertexAttribI4uiv(%" PRIu32 ", %p)", index, values);

    if (mImports.glVertexAttribI4uiv == nullptr) {
        GAPID_WARNING("Application called unsupported function glVertexAttribI4uiv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, index, values] {
        called = true;
        observer->observeReads();
        mImports.glVertexAttribI4uiv(index, values);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            Slice<GLuint> l_v = slice(values, 0ULL, 4ULL);
            Vec4i l_vec = {(GLint)(observer->read(l_v, 0ULL)), (GLint)(observer->read(l_v, 1ULL)), (GLint)(observer->read(l_v, 2ULL)), (GLint)(observer->read(l_v, 3ULL))};
            subVertexAttribI(observer, call, index, l_vec);
            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::gles::GlVertexAttribI4uiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__CP >(values, *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);

}

CGLError GlesSpy::CGLSetCurrentContext(CallObserver* observer, CGLContextObj ctx) {
    GAPID_DEBUG("CGLSetCurrentContext(%p)", ctx);

    if (mImports.CGLSetCurrentContext == nullptr) {
        GAPID_WARNING("Application called unsupported function CGLSetCurrentContext");
        return 0;
    }

    CGLError result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, ctx] {
        called = true;
        observer->observeReads();
        result = mImports.CGLSetCurrentContext(ctx);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subSetContext(observer, call, findOrZero(this->CGLContexts, ctx));
            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::gles::CGLSetCurrentContext coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::CGLContextObj >(ctx, *observer->getScratch()), toEncoder< int >(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 GlesSpy::glClearColorxOES(CallObserver* observer, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
    GAPID_DEBUG("glClearColorxOES(%" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", red, green, blue, alpha);

    if (mImports.glClearColorxOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glClearColorxOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, red, green, blue, alpha] {
        called = true;
        observer->observeReads();
        mImports.glClearColorxOES(red, green, blue, alpha);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_fixed_point);
            subErrorGLES10notSupported(observer, call);
            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::gles::GlClearColorxOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(red, *observer->getScratch()), toEncoder< int32_t >(green, *observer->getScratch()), toEncoder< int32_t >(blue, *observer->getScratch()), toEncoder< int32_t >(alpha, *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 GlesSpy::glClipPlanefIMG(CallObserver* observer, uint32_t p, GLfloat* eqn) {
    GAPID_DEBUG("glClipPlanefIMG(%u, %p)", p, eqn);

    if (mImports.glClipPlanefIMG == nullptr) {
        GAPID_WARNING("Application called unsupported function glClipPlanefIMG");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, p, eqn] {
        called = true;
        observer->observeReads();
        mImports.glClipPlanefIMG(p, eqn);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_IMG_user_clip_plane);
            subErrorGLES10notSupported(observer, call);
            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::gles::GlClipPlanefIMG coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), p, toEncoder< gapic::coder::gles::GLfloat__CP >(eqn, *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 GlesSpy::glClipPlanexOES(CallObserver* observer, uint32_t plane, GLfixed* equation) {
    GAPID_DEBUG("glClipPlanexOES(%u, %p)", plane, equation);

    if (mImports.glClipPlanexOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glClipPlanexOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, plane, equation] {
        called = true;
        observer->observeReads();
        mImports.glClipPlanexOES(plane, equation);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_fixed_point);
            subErrorGLES10notSupported(observer, call);
            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::gles::GlClipPlanexOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), plane, toEncoder< gapic::coder::gles::GLfixed__CP >(equation, *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 GlesSpy::glFogxOES(CallObserver* observer, uint32_t pname, GLfixed param) {
    GAPID_DEBUG("glFogxOES(%u, %" PRId32 ")", pname, param);

    if (mImports.glFogxOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glFogxOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glFogxOES(pname, param);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_fixed_point);
            subErrorGLES10notSupported(observer, call);
            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::gles::GlFogxOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< int32_t >(param, *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 GlesSpy::glFrustumfOES(CallObserver* observer, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) {
    GAPID_DEBUG("glFrustumfOES(%f, %f, %f, %f, %f, %f)", l, r, b, t, n, f);

    if (mImports.glFrustumfOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glFrustumfOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, l, r, b, t, n, f] {
        called = true;
        observer->observeReads();
        mImports.glFrustumfOES(l, r, b, t, n, f);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_single_precision);
            subErrorGLES10notSupported(observer, call);
            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::gles::GlFrustumfOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< float >(l, *observer->getScratch()), toEncoder< float >(r, *observer->getScratch()), toEncoder< float >(b, *observer->getScratch()), toEncoder< float >(t, *observer->getScratch()), toEncoder< float >(n, *observer->getScratch()), toEncoder< float >(f, *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 GlesSpy::glGetFixedvOES(CallObserver* observer, uint32_t pname, GLfixed* params) {
    GAPID_DEBUG("glGetFixedvOES(%u, %p)", pname, params);

    if (mImports.glGetFixedvOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glGetFixedvOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glGetFixedvOES(pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_fixed_point);
            subErrorGLES10notSupported(observer, call);
            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::gles::GlGetFixedvOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< gapic::coder::gles::GLfixed__P >(params, *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 GlesSpy::glLightModelfv(CallObserver* observer, uint32_t pname, GLfloat* params) {
    GAPID_DEBUG("glLightModelfv(%u, %p)", pname, params);

    if (mImports.glLightModelfv == nullptr) {
        GAPID_WARNING("Application called unsupported function glLightModelfv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glLightModelfv(pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            subErrorGLES10notSupported(observer, call);
            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::gles::GlLightModelfv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< gapic::coder::gles::GLfloat__CP >(params, *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 GlesSpy::glLoadMatrixf(CallObserver* observer, GLfloat* m) {
    GAPID_DEBUG("glLoadMatrixf(%p)", m);

    if (mImports.glLoadMatrixf == nullptr) {
        GAPID_WARNING("Application called unsupported function glLoadMatrixf");
        return;
    }

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            subErrorGLES10notSupported(observer, call);
            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::gles::GlLoadMatrixf coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::GLfloat__CP >(m, *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 GlesSpy::glLogicOp(CallObserver* observer, uint32_t opcode) {
    GAPID_DEBUG("glLogicOp(%u)", opcode);

    if (mImports.glLogicOp == nullptr) {
        GAPID_WARNING("Application called unsupported function glLogicOp");
        return;
    }

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            subErrorGLES10notSupported(observer, call);
            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::gles::GlLogicOp coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), opcode);
    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 GlesSpy::glMaterialfv(CallObserver* observer, uint32_t face, uint32_t pname, GLfloat* params) {
    GAPID_DEBUG("glMaterialfv(%u, %u, %p)", face, pname, params);

    if (mImports.glMaterialfv == nullptr) {
        GAPID_WARNING("Application called unsupported function glMaterialfv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, face, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glMaterialfv(face, pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            subErrorGLES10notSupported(observer, call);
            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::gles::GlMaterialfv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), face, pname, toEncoder< gapic::coder::gles::GLfloat__CP >(params, *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 GlesSpy::glMultMatrixx(CallObserver* observer, GLfixed* m) {
    GAPID_DEBUG("glMultMatrixx(%p)", m);

    if (mImports.glMultMatrixx == nullptr) {
        GAPID_WARNING("Application called unsupported function glMultMatrixx");
        return;
    }

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            subErrorGLES10notSupported(observer, call);
            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::gles::GlMultMatrixx coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::GLfixed__CP >(m, *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 GlesSpy::glMultiTexCoord4f(CallObserver* observer, uint32_t target, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
    GAPID_DEBUG("glMultiTexCoord4f(%u, %f, %f, %f, %f)", target, v0, v1, v2, v3);

    if (mImports.glMultiTexCoord4f == nullptr) {
        GAPID_WARNING("Application called unsupported function glMultiTexCoord4f");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, v0, v1, v2, v3] {
        called = true;
        observer->observeReads();
        mImports.glMultiTexCoord4f(target, v0, v1, v2, v3);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            subErrorGLES10notSupported(observer, call);
            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::gles::GlMultiTexCoord4f coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< float >(v0, *observer->getScratch()), toEncoder< float >(v1, *observer->getScratch()), toEncoder< float >(v2, *observer->getScratch()), toEncoder< float >(v3, *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 GlesSpy::glNormal3xOES(CallObserver* observer, GLfixed nx, GLfixed ny, GLfixed nz) {
    GAPID_DEBUG("glNormal3xOES(%" PRId32 ", %" PRId32 ", %" PRId32 ")", nx, ny, nz);

    if (mImports.glNormal3xOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glNormal3xOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, nx, ny, nz] {
        called = true;
        observer->observeReads();
        mImports.glNormal3xOES(nx, ny, nz);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_fixed_point);
            subErrorGLES10notSupported(observer, call);
            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::gles::GlNormal3xOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(nx, *observer->getScratch()), toEncoder< int32_t >(ny, *observer->getScratch()), toEncoder< int32_t >(nz, *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 GlesSpy::glPointParameterfv(CallObserver* observer, uint32_t pname, GLfloat* params) {
    GAPID_DEBUG("glPointParameterfv(%u, %p)", pname, params);

    if (mImports.glPointParameterfv == nullptr) {
        GAPID_WARNING("Application called unsupported function glPointParameterfv");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glPointParameterfv(pname, params);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            subErrorGLES10notSupported(observer, call);
            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::gles::GlPointParameterfv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< gapic::coder::gles::GLfloat__CP >(params, *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 GlesSpy::glSampleCoveragexOES(CallObserver* observer, GLclampx value, GLboolean invert) {
    GAPID_DEBUG("glSampleCoveragexOES(%" PRId32 ", %" PRIu8 ")", value, invert);

    if (mImports.glSampleCoveragexOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glSampleCoveragexOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, value, invert] {
        called = true;
        observer->observeReads();
        mImports.glSampleCoveragexOES(value, invert);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_fixed_point);
            subErrorGLES10notSupported(observer, call);
            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::gles::GlSampleCoveragexOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(value, *observer->getScratch()), toEncoder< uint8_t >(invert, *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 GlesSpy::glTexEnvxOES(CallObserver* observer, uint32_t target, uint32_t pname, GLfixed param) {
    GAPID_DEBUG("glTexEnvxOES(%u, %u, %" PRId32 ")", target, pname, param);

    if (mImports.glTexEnvxOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glTexEnvxOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, target, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glTexEnvxOES(target, pname, param);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_fixed_point);
            subErrorGLES10notSupported(observer, call);
            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::gles::GlTexEnvxOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, pname, toEncoder< int32_t >(param, *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 GlesSpy::glTexGeniOES(CallObserver* observer, uint32_t coord, uint32_t pname, GLint param) {
    GAPID_DEBUG("glTexGeniOES(%u, %u, %" PRId32 ")", coord, pname, param);

    if (mImports.glTexGeniOES == nullptr) {
        GAPID_WARNING("Application called unsupported function glTexGeniOES");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, coord, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glTexGeniOES(coord, pname, param);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_texture_cube_map);
            subErrorGLES10notSupported(observer, call);
            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::gles::GlTexGeniOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), coord, pname, toEncoder< int32_t >(param, *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 GlesSpy::glNormalPointerBounds(CallObserver* observer, uint32_t type, GLsizei stride, void* pointer, GLsizei count) {
    GAPID_DEBUG("glNormalPointerBounds(%u, %" PRId32 ", %p, %" PRId32 ")", type, stride, pointer, count);

    if (mImports.glNormalPointerBounds == nullptr) {
        GAPID_WARNING("Application called unsupported function glNormalPointerBounds");
        return;
    }

    bool called = false;
    auto call = [this, observer, &called, type, stride, pointer, count] {
        called = true;
        observer->observeReads();
        mImports.glNormalPointerBounds(type, stride, pointer, count);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            subErrorGLES10notSupported(observer, call);
            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::gles::GlNormalPointerBounds coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), type, toEncoder< int32_t >(stride, *observer->getScratch()), toEncoder< gapic::coder::gles::Void__CP >(pointer, *observer->getScratch()), toEncoder< int32_t >(count, *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