/*
 * 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::glColorMaskiEXT(CallObserver* observer, DrawBufferIndex index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
    GAPID_DEBUG("glColorMaskiEXT(%" PRIu32 ", %" PRIu8 ", %" PRIu8 ", %" PRIu8 ", %" PRIu8 ")", index, r, g, b, a);

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

    bool called = false;
    auto call = [this, observer, &called, index, r, g, b, a] {
        called = true;
        observer->observeReads();
        mImports.glColorMaskiEXT(index, r, g, b, a);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_draw_buffers_indexed);
            subColorMaski(observer, call, index, r, g, b, a);
            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::GlColorMaskiEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< uint8_t >(r, *observer->getScratch()), toEncoder< uint8_t >(g, *observer->getScratch()), toEncoder< uint8_t >(b, *observer->getScratch()), toEncoder< uint8_t >(a, *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::glPrimitiveBoundingBoxEXT(CallObserver* observer, GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW) {
    GAPID_DEBUG("glPrimitiveBoundingBoxEXT(%f, %f, %f, %f, %f, %f, %f, %f)", minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);

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

    bool called = false;
    auto call = [this, observer, &called, minX, minY, minZ, minW, maxX, maxY, maxZ, maxW] {
        called = true;
        observer->observeReads();
        mImports.glPrimitiveBoundingBoxEXT(minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_primitive_bounding_box);
            subPrimitiveBoundingBox(observer, call, minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
            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::GlPrimitiveBoundingBoxEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< float >(minX, *observer->getScratch()), toEncoder< float >(minY, *observer->getScratch()), toEncoder< float >(minZ, *observer->getScratch()), toEncoder< float >(minW, *observer->getScratch()), toEncoder< float >(maxX, *observer->getScratch()), toEncoder< float >(maxY, *observer->getScratch()), toEncoder< float >(maxZ, *observer->getScratch()), toEncoder< float >(maxW, *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::glSamplerParameterIuivEXT(CallObserver* observer, SamplerId sampler, uint32_t pname, GLuint* param) {
    GAPID_DEBUG("glSamplerParameterIuivEXT(%" PRIu32 ", %u, %p)", sampler, pname, param);

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

    bool called = false;
    auto call = [this, observer, &called, sampler, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glSamplerParameterIuivEXT(sampler, pname, param);
        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));
            subSamplerParameterIuiv(observer, call, sampler, pname, param);
            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::GlSamplerParameterIuivEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(sampler, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLuint__CP >(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::glDeleteQueries(CallObserver* observer, GLsizei count, QueryId* queries) {
    GAPID_DEBUG("glDeleteQueries(%" PRId32 ", %p)", count, queries);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            Slice<QueryId> l_q = slice(queries, (uint64_t)((GLsizei)(0L)), (uint64_t)(count));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            for (GLsizei l_i = (GLsizei)(0L); l_i < count; ++l_i) {
                QueryId l_id = observer->read(l_q, (uint64_t)(l_i));
                if ((l_id) != ((QueryId)(0UL))) {
                    checkNotNull(l_ctx).mInstances.mQueries.erase(l_id);
                }
            }
            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::GlDeleteQueries coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::QueryId__CP >(queries, *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::glBindBuffer(CallObserver* observer, uint32_t target, BufferId buffer) {
    GAPID_DEBUG("glBindBuffer(%u, %" PRIu32 ")", target, buffer);

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

    bool called = false;
    auto call = [this, observer, &called, target, buffer] {
        called = true;
        observer->observeReads();
        mImports.glBindBuffer(target, buffer);
        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);
            switch (target) {
                case GLenum::GL_ARRAY_BUFFER: {
                    checkNotNull(l_ctx).mBoundBuffers.mArrayBuffer = buffer;
                    break;
                }
                case GLenum::GL_ELEMENT_ARRAY_BUFFER: {
                    checkNotNull(findOrZero(checkNotNull(l_ctx).mInstances.mVertexArrays, checkNotNull(l_ctx).mBoundVertexArray)).mElementArrayBuffer = buffer;
                    break;
                }
                case GLenum::GL_COPY_READ_BUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    checkNotNull(l_ctx).mBoundBuffers.mCopyReadBuffer = buffer;
                    break;
                }
                case GLenum::GL_COPY_WRITE_BUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    checkNotNull(l_ctx).mBoundBuffers.mCopyWriteBuffer = buffer;
                    break;
                }
                case GLenum::GL_PIXEL_PACK_BUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    checkNotNull(l_ctx).mBoundBuffers.mPixelPackBuffer = buffer;
                    break;
                }
                case GLenum::GL_PIXEL_UNPACK_BUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    checkNotNull(l_ctx).mBoundBuffers.mPixelUnpackBuffer = buffer;
                    break;
                }
                case GLenum::GL_TRANSFORM_FEEDBACK_BUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    checkNotNull(l_ctx).mBoundBuffers.mTransformFeedbackBuffer = buffer;
                    break;
                }
                case GLenum::GL_UNIFORM_BUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    checkNotNull(l_ctx).mBoundBuffers.mUniformBuffer = buffer;
                    break;
                }
                case GLenum::GL_ATOMIC_COUNTER_BUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
                    checkNotNull(l_ctx).mBoundBuffers.mAtomicCounterBuffer = buffer;
                    break;
                }
                case GLenum::GL_DISPATCH_INDIRECT_BUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
                    checkNotNull(l_ctx).mBoundBuffers.mDispatchIndirectBuffer = buffer;
                    break;
                }
                case GLenum::GL_DRAW_INDIRECT_BUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
                    checkNotNull(l_ctx).mBoundBuffers.mDrawIndirectBuffer = buffer;
                    break;
                }
                case GLenum::GL_SHADER_STORAGE_BUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
                    checkNotNull(l_ctx).mBoundBuffers.mShaderStorageBuffer = buffer;
                    break;
                }
                case GLenum::GL_TEXTURE_BUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    checkNotNull(l_ctx).mBoundBuffers.mTextureBuffer = buffer;
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, target);
                }
            }
            if (!(checkNotNull(l_ctx).mInstances.mBuffers.count(buffer) > 0)) {
                checkNotNull(l_ctx).mInstances.mBuffers[buffer] = std::shared_ptr<Buffer>(new Buffer(Slice<uint8_t>(), (GLsizeiptr)(0L), GLenum::GL_STATIC_DRAW, 0, GLbooleanLabels::GL_FALSE, nullptr, (GLintptr)(0L), (GLsizeiptr)(0L), ""));
            }
            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::GlBindBuffer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< uint32_t >(buffer, *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::glGenBuffers(CallObserver* observer, GLsizei count, BufferId* buffers) {
    GAPID_DEBUG("glGenBuffers(%" PRId32 ", %p)", count, buffers);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            if ((count) < ((GLsizei)(0L))) {
                subGlErrorInvalidValue(observer, call);
            }
            Slice<BufferId> l_b = slice(buffers, (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) {
                BufferId l_id = (BufferId)(slice(buffers, (uint64_t)((GLsizei)(0L)), (uint64_t)(count))[(uint64_t)(l_i)]);
                checkNotNull(l_ctx).mInstances.mBuffers[l_id] = std::shared_ptr<Buffer>(new Buffer(Slice<uint8_t>(), (GLsizeiptr)(0L), GLenum::GL_STATIC_DRAW, 0, GLbooleanLabels::GL_FALSE, nullptr, (GLintptr)(0L), (GLsizeiptr)(0L), ""));
                observer->write<BufferId>(l_b, (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::GlGenBuffers coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::BufferId__P >(buffers, *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::glMapBufferRange(CallObserver* observer, uint32_t target, GLintptr offset, GLsizeiptr length, uint32_t access) {
    GAPID_DEBUG("glMapBufferRange(%u, %" PRId32 ", %" PRId32 ", %u)", target, offset, length, access);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            call();
            auto l_ptr = result;
            subMapBufferRange(observer, call, target, offset, length, 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::GlMapBufferRange coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(offset, *observer->getScratch()), toEncoder< int32_t >(length, *observer->getScratch()), 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::glDrawArraysInstanced(CallObserver* observer, uint32_t draw_mode, GLint first_index, GLsizei indices_count, GLsizei instance_count) {
    GAPID_DEBUG("glDrawArraysInstanced(%u, %" PRId32 ", %" PRId32 ", %" PRId32 ")", draw_mode, first_index, indices_count, instance_count);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subDrawArraysInstanced(observer, call, draw_mode, first_index, indices_count, instance_count);
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlDrawArraysInstanced coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), draw_mode, toEncoder< int32_t >(first_index, *observer->getScratch()), toEncoder< int32_t >(indices_count, *observer->getScratch()), toEncoder< int32_t >(instance_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);
    onPostDrawCall();

}

void GlesSpy::glDrawRangeElementsBaseVertex(CallObserver* observer, uint32_t draw_mode, GLuint start, GLuint end, GLsizei indices_count, uint32_t indices_type, IndicesPointer indices, GLint base_vertex) {
    GAPID_DEBUG("glDrawRangeElementsBaseVertex(%u, %" PRIu32 ", %" PRIu32 ", %" PRId32 ", %u, %p, %" PRId32 ")", draw_mode, start, end, indices_count, indices_type, indices, base_vertex);

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

    bool called = false;
    auto call = [this, observer, &called, draw_mode, start, end, indices_count, indices_type, indices, base_vertex] {
        called = true;
        observer->observeReads();
        mImports.glDrawRangeElementsBaseVertex(draw_mode, start, end, indices_count, indices_type, indices, base_vertex);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            subDrawRangeElementsBaseVertex(observer, call, draw_mode, start, end, indices_count, indices_type, indices, base_vertex);
            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::GlDrawRangeElementsBaseVertex coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), draw_mode, toEncoder< uint32_t >(start, *observer->getScratch()), toEncoder< uint32_t >(end, *observer->getScratch()), toEncoder< int32_t >(indices_count, *observer->getScratch()), indices_type, toEncoder< gapic::coder::gles::IndicesPointer >(indices, *observer->getScratch()), toEncoder< int32_t >(base_vertex, *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::eglGetConfigAttrib(CallObserver* observer, EGLDisplay display, EGLConfig config, EGLint attribute, EGLint* value) {
    GAPID_DEBUG("eglGetConfigAttrib(%p, %p, %d, %p)", display, config, attribute, value);

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

    EGLBoolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, display, config, attribute, value] {
        called = true;
        observer->observeReads();
        result = mImports.eglGetConfigAttrib(display, config, attribute, value);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::EglGetConfigAttrib coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::EGLDisplay >(display, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLConfig >(config, *observer->getScratch()), toEncoder< int >(attribute, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLint__P >(value, *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;
}

EGLSyncKHR GlesSpy::eglCreateSyncKHR(CallObserver* observer, EGLDisplay dpy, uint32_t type, EGLint* attrib_list) {
    GAPID_DEBUG("eglCreateSyncKHR(%p, %u, %p)", dpy, type, attrib_list);

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

    EGLSyncKHR result = nullptr;
    bool called = false;
    auto call = [this, observer, &called, &result, dpy, type, attrib_list] {
        called = true;
        observer->observeReads();
        result = mImports.eglCreateSyncKHR(dpy, type, attrib_list);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subObserveAttribList(observer, call, attrib_list);
            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::EglCreateSyncKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::EGLDisplay >(dpy, *observer->getScratch()), type, toEncoder< gapic::coder::gles::EGLint__CP >(attrib_list, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLSyncKHR >(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;
}

EGLBoolean GlesSpy::eglDestroySyncKHR(CallObserver* observer, EGLDisplay dpy, EGLSyncKHR sync) {
    GAPID_DEBUG("eglDestroySyncKHR(%p, %p)", dpy, sync);

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

    EGLBoolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, dpy, sync] {
        called = true;
        observer->observeReads();
        result = mImports.eglDestroySyncKHR(dpy, sync);
        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::EglDestroySyncKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::EGLDisplay >(dpy, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLSyncKHR >(sync, *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;
}

uint32_t GlesSpy::eglQueryAPI(CallObserver* observer) {
    GAPID_DEBUG("eglQueryAPI()");

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

    uint32_t result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result] {
        called = true;
        observer->observeReads();
        result = mImports.eglQueryAPI();
        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::EglQueryAPI coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

EGLBoolean GlesSpy::eglSwapBuffers(CallObserver* observer, EGLDisplay display, void* surface) {
    GAPID_DEBUG("eglSwapBuffers(%p, %p)", display, surface);

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

    EGLBoolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, display, surface] {
        called = true;
        observer->observeReads();
        result = mImports.eglSwapBuffers(display, surface);
        onPostFence(observer);
    };

    onPreEndOfFrame();

    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::EglSwapBuffers coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::EGLDisplay >(display, *observer->getScratch()), toEncoder< gapic::coder::gles::Void__P >(surface, *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;
}

EGLImageKHR GlesSpy::eglCreateImageKHR(CallObserver* observer, EGLDisplay dpy, EGLContext ctx, uint32_t target, EGLClientBuffer buffer, EGLint* attrib_list) {
    GAPID_DEBUG("eglCreateImageKHR(%p, %p, %u, %p, %p)", dpy, ctx, target, buffer, attrib_list);

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

    EGLImageKHR result = nullptr;
    bool called = false;
    auto call = [this, observer, &called, &result, dpy, ctx, target, buffer, attrib_list] {
        called = true;
        observer->observeReads();
        result = mImports.eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::EGL_KHR_image_base);
            subObserveAttribList(observer, call, attrib_list);
            call();
            auto l_img = result;
            if ((target) == (EGLenum::EGL_NATIVE_BUFFER_ANDROID)) {
                this->EGLImages[l_img] = GetAndroidNativeBufferExtra(observer, (void*)(buffer));
            }
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::EglCreateImageKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::EGLDisplay >(dpy, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLContext >(ctx, *observer->getScratch()), target, toEncoder< gapic::coder::gles::EGLClientBuffer >(buffer, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLint__CP >(attrib_list, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLImageKHR >(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;
}

EGLBoolean GlesSpy::eglDestroyImageKHR(CallObserver* observer, EGLDisplay dpy, EGLImageKHR image) {
    GAPID_DEBUG("eglDestroyImageKHR(%p, %p)", dpy, image);

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

    EGLBoolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, dpy, image] {
        called = true;
        observer->observeReads();
        result = mImports.eglDestroyImageKHR(dpy, image);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::EGL_KHR_image_base);
            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::EglDestroyImageKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::EGLDisplay >(dpy, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLImageKHR >(image, *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::glCompressedTexImage3DOES(CallObserver* observer, uint32_t target, GLint level, uint32_t internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei image_size, TexturePointer data) {
    GAPID_DEBUG("glCompressedTexImage3DOES(%u, %" PRId32 ", %u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %p)", target, level, internalformat, width, height, depth, border, image_size, data);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_texture_3D);
            subCompressedTexImage3D(observer, call, target, level, internalformat, width, height, depth, border, image_size, 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::GlCompressedTexImage3DOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(level, *observer->getScratch()), internalformat, toEncoder< int32_t >(width, *observer->getScratch()), toEncoder< int32_t >(height, *observer->getScratch()), toEncoder< int32_t >(depth, *observer->getScratch()), toEncoder< int32_t >(border, *observer->getScratch()), toEncoder< int32_t >(image_size, *observer->getScratch()), 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::glDeleteFencesNV(CallObserver* observer, GLsizei n, GLuint* fences) {
    GAPID_DEBUG("glDeleteFencesNV(%" PRId32 ", %p)", n, fences);

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

    bool called = false;
    auto call = [this, observer, &called, n, fences] {
        called = true;
        observer->observeReads();
        mImports.glDeleteFencesNV(n, fences);
        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::GlDeleteFencesNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(n, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__CP >(fences, *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::glDeletePathsNV(CallObserver* observer, GLuint path, GLsizei range) {
    GAPID_DEBUG("glDeletePathsNV(%" PRIu32 ", %" PRId32 ")", path, range);

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

    bool called = false;
    auto call = [this, observer, &called, path, range] {
        called = true;
        observer->observeReads();
        mImports.glDeletePathsNV(path, range);
        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::GlDeletePathsNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *observer->getScratch()), toEncoder< int32_t >(range, *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::glDrawArraysInstancedNV(CallObserver* observer, uint32_t mode, GLint first, GLsizei count, GLsizei primcount) {
    GAPID_DEBUG("glDrawArraysInstancedNV(%u, %" PRId32 ", %" PRId32 ", %" PRId32 ")", mode, first, count, primcount);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_draw_instanced);
            subDrawArraysInstanced(observer, call, mode, first, count, primcount);
            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::GlDrawArraysInstancedNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), mode, toEncoder< int32_t >(first, *observer->getScratch()), toEncoder< int32_t >(count, *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);
    onPostDrawCall();

}

void GlesSpy::glDrawBuffersNV(CallObserver* observer, GLsizei n, uint32_t* bufs) {
    GAPID_DEBUG("glDrawBuffersNV(%" PRId32 ", %p)", n, bufs);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_draw_buffers);
            subDrawBuffers(observer, call, n, bufs);
            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::GlDrawBuffersNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(n, *observer->getScratch()), toEncoder< gapic::coder::gles::GLenum__CP >(bufs, *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::glDrawElementsBaseVertexOES(CallObserver* observer, uint32_t mode, GLsizei count, uint32_t type, IndicesPointer indices, GLint basevertex) {
    GAPID_DEBUG("glDrawElementsBaseVertexOES(%u, %" PRId32 ", %u, %p, %" PRId32 ")", mode, count, type, indices, basevertex);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_draw_elements_base_vertex);
            subDrawElementsBaseVertex(observer, call, mode, count, type, indices, basevertex);
            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::GlDrawElementsBaseVertexOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), mode, toEncoder< int32_t >(count, *observer->getScratch()), type, toEncoder< gapic::coder::gles::IndicesPointer >(indices, *observer->getScratch()), toEncoder< int32_t >(basevertex, *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();

}

void GlesSpy::glDrawElementsInstancedBaseInstanceEXT(CallObserver* observer, uint32_t mode, GLsizei count, uint32_t type, void* indices, GLsizei instancecount, GLuint baseinstance) {
    GAPID_DEBUG("glDrawElementsInstancedBaseInstanceEXT(%u, %" PRId32 ", %u, %p, %" PRId32 ", %" PRIu32 ")", mode, count, type, indices, instancecount, baseinstance);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_base_instance);
            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::GlDrawElementsInstancedBaseInstanceEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), mode, toEncoder< int32_t >(count, *observer->getScratch()), type, toEncoder< gapic::coder::gles::Void__CP >(indices, *observer->getScratch()), toEncoder< int32_t >(instancecount, *observer->getScratch()), toEncoder< uint32_t >(baseinstance, *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();

}

void GlesSpy::glExtGetFramebuffersQCOM(CallObserver* observer, FramebufferId* framebuffers, GLint maxFramebuffers, GLint* numFramebuffers) {
    GAPID_DEBUG("glExtGetFramebuffersQCOM(%p, %" PRId32 ", %p)", framebuffers, maxFramebuffers, numFramebuffers);

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

    bool called = false;
    auto call = [this, observer, &called, framebuffers, maxFramebuffers, numFramebuffers] {
        called = true;
        observer->observeReads();
        mImports.glExtGetFramebuffersQCOM(framebuffers, maxFramebuffers, numFramebuffers);
        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::GlExtGetFramebuffersQCOM coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::FramebufferId__P >(framebuffers, *observer->getScratch()), toEncoder< int32_t >(maxFramebuffers, *observer->getScratch()), toEncoder< gapic::coder::gles::GLint__P >(numFramebuffers, *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::glExtGetShadersQCOM(CallObserver* observer, ShaderId* shaders, GLint maxShaders, GLint* numShaders) {
    GAPID_DEBUG("glExtGetShadersQCOM(%p, %" PRId32 ", %p)", shaders, maxShaders, numShaders);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_QCOM_extended_get2);
            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::GlExtGetShadersQCOM coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::ShaderId__P >(shaders, *observer->getScratch()), toEncoder< int32_t >(maxShaders, *observer->getScratch()), toEncoder< gapic::coder::gles::GLint__P >(numShaders, *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::glExtGetTexSubImageQCOM(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, void* texels) {
    GAPID_DEBUG("glExtGetTexSubImageQCOM(%u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %u, %u, %p)", target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels);

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

    bool called = false;
    auto call = [this, observer, &called, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels] {
        called = true;
        observer->observeReads();
        mImports.glExtGetTexSubImageQCOM(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels);
        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::GlExtGetTexSubImageQCOM 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::Void__P >(texels, *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::glFragmentCoverageColorNV(CallObserver* observer, GLuint color) {
    GAPID_DEBUG("glFragmentCoverageColorNV(%" PRIu32 ")", color);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_fragment_coverage_to_color);
            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::GlFragmentCoverageColorNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(color, *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::glGenQueriesEXT(CallObserver* observer, GLsizei count, QueryId* queries) {
    GAPID_DEBUG("glGenQueriesEXT(%" PRId32 ", %p)", count, queries);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension2(observer, call, ExtensionId::GL_EXT_disjoint_timer_query, ExtensionId::GL_EXT_occlusion_query_boolean);
            Slice<QueryId> l_q = slice(queries, (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) {
                QueryId l_id = (QueryId)(slice(queries, (uint64_t)((GLsizei)(0L)), (uint64_t)(count))[(uint64_t)(l_i)]);
                checkNotNull(l_ctx).mInstances.mQueries[l_id] = std::shared_ptr<Query>(new Query(""));
                observer->write<QueryId>(l_q, (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::GlGenQueriesEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::QueryId__P >(queries, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

uint32_t GlesSpy::glGetGraphicsResetStatusEXT(CallObserver* observer) {
    GAPID_DEBUG("glGetGraphicsResetStatusEXT()");

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_robustness);
            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::GlGetGraphicsResetStatusEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

uint32_t GlesSpy::glGetGraphicsResetStatusKHR(CallObserver* observer) {
    GAPID_DEBUG("glGetGraphicsResetStatusKHR()");

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_KHR_robustness);
            subGetGraphicsResetStatus(observer, call);
            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::GlGetGraphicsResetStatusKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

void GlesSpy::glGetPathParameterivNV(CallObserver* observer, GLuint path, uint32_t pname, GLint* value) {
    GAPID_DEBUG("glGetPathParameterivNV(%" PRIu32 ", %u, %p)", path, pname, value);

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

    bool called = false;
    auto call = [this, observer, &called, path, pname, value] {
        called = true;
        observer->observeReads();
        mImports.glGetPathParameterivNV(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::GlGetPathParameterivNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLint__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::glGetTranslatedShaderSourceANGLE(CallObserver* observer, ShaderId shader, GLsizei bufsize, GLsizei* length, GLchar* source) {
    GAPID_DEBUG("glGetTranslatedShaderSourceANGLE(%" PRIu32 ", %" PRId32 ", %p, %p)", shader, bufsize, length, source);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_ANGLE_translated_shader_source);
            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::GlGetTranslatedShaderSourceANGLE coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(shader, *observer->getScratch()), toEncoder< int32_t >(bufsize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLsizei__P >(length, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__P >(source, *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::glGetnUniformfvEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei bufSize, GLfloat* params) {
    GAPID_DEBUG("glGetnUniformfvEXT(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, bufSize, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_robustness);
            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::GlGetnUniformfvEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(bufSize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__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::glGetnUniformfvKHR(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei bufSize, GLfloat* params) {
    GAPID_DEBUG("glGetnUniformfvKHR(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, bufSize, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_KHR_robustness);
            call();
            subGetnUniformfv_GLfloat__P(observer, call, program, location, bufSize, 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::GlGetnUniformfvKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(bufSize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__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::glGetnUniformuivKHR(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei bufSize, GLuint* params) {
    GAPID_DEBUG("glGetnUniformuivKHR(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, bufSize, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_KHR_robustness);
            call();
            subGetnUniformuiv(observer, call, program, location, bufSize, 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::GlGetnUniformuivKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(bufSize, *observer->getScratch()), 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::glMakeImageHandleResidentNV(CallObserver* observer, GLuint64 handle, uint32_t access) {
    GAPID_DEBUG("glMakeImageHandleResidentNV(%" PRIu64 ", %u)", handle, access);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_bindless_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::GlMakeImageHandleResidentNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint64_t >(handle, *observer->getScratch()), access);
    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::glMatrixMult3x3fNV(CallObserver* observer, uint32_t matrixMode, GLfloat* m) {
    GAPID_DEBUG("glMatrixMult3x3fNV(%u, %p)", matrixMode, m);

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

    bool called = false;
    auto call = [this, observer, &called, matrixMode, m] {
        called = true;
        observer->observeReads();
        mImports.glMatrixMult3x3fNV(matrixMode, m);
        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::GlMatrixMult3x3fNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), matrixMode, 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::glPathCommandsNV(CallObserver* observer, GLuint path, GLsizei numCommands, GLubyte* commands, GLsizei numCoords, uint32_t coordType, void* coords) {
    GAPID_DEBUG("glPathCommandsNV(%" PRIu32 ", %" PRId32 ", %p, %" PRId32 ", %u, %p)", path, numCommands, commands, numCoords, coordType, coords);

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

    bool called = false;
    auto call = [this, observer, &called, path, numCommands, commands, numCoords, coordType, coords] {
        called = true;
        observer->observeReads();
        mImports.glPathCommandsNV(path, 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::GlPathCommandsNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *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::glPathCoordsNV(CallObserver* observer, GLuint path, GLsizei numCoords, uint32_t coordType, void* coords) {
    GAPID_DEBUG("glPathCoordsNV(%" PRIu32 ", %" PRId32 ", %u, %p)", path, numCoords, coordType, coords);

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

    bool called = false;
    auto call = [this, observer, &called, path, numCoords, coordType, coords] {
        called = true;
        observer->observeReads();
        mImports.glPathCoordsNV(path, 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::GlPathCoordsNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *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::glPathCoverDepthFuncNV(CallObserver* observer, uint32_t func) {
    GAPID_DEBUG("glPathCoverDepthFuncNV(%u)", func);

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

    bool called = false;
    auto call = [this, observer, &called, func] {
        called = true;
        observer->observeReads();
        mImports.glPathCoverDepthFuncNV(func);
        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::GlPathCoverDepthFuncNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), func);
    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::glPathParameteriNV(CallObserver* observer, GLuint path, uint32_t pname, GLint value) {
    GAPID_DEBUG("glPathParameteriNV(%" PRIu32 ", %u, %" PRId32 ")", path, pname, value);

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

    bool called = false;
    auto call = [this, observer, &called, path, pname, value] {
        called = true;
        observer->observeReads();
        mImports.glPathParameteriNV(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::GlPathParameteriNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *observer->getScratch()), 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::glPathStencilDepthOffsetNV(CallObserver* observer, GLfloat factor, GLfloat units) {
    GAPID_DEBUG("glPathStencilDepthOffsetNV(%f, %f)", factor, units);

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

    bool called = false;
    auto call = [this, observer, &called, factor, units] {
        called = true;
        observer->observeReads();
        mImports.glPathStencilDepthOffsetNV(factor, units);
        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::GlPathStencilDepthOffsetNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< float >(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);

}

void GlesSpy::glPolygonModeNV(CallObserver* observer, uint32_t face, uint32_t mode) {
    GAPID_DEBUG("glPolygonModeNV(%u, %u)", face, mode);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_polygon_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::GlPolygonModeNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), face, 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::glProgramParameteriEXT(CallObserver* observer, ProgramId program, uint32_t pname, GLint value) {
    GAPID_DEBUG("glProgramParameteriEXT(%" PRIu32 ", %u, %" PRId32 ")", program, pname, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramParameteri(observer, call, program, 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::GlProgramParameteriEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), 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::glProgramUniform2fvEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLfloat* value) {
    GAPID_DEBUG("glProgramUniform2fvEXT(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniform2fv(observer, call, program, location, count, 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::GlProgramUniform2fvEXT 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::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::glProgramUniform2uivEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLuint* value) {
    GAPID_DEBUG("glProgramUniform2uivEXT(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniform2uiv(observer, call, program, location, count, 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::GlProgramUniform2uivEXT 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 >(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::glProgramUniform3ivEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLint* value) {
    GAPID_DEBUG("glProgramUniform3ivEXT(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniform3iv(observer, call, program, location, count, 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::GlProgramUniform3ivEXT 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::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::glProgramUniformMatrix3fvEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* value) {
    GAPID_DEBUG("glProgramUniformMatrix3fvEXT(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", program, location, count, transpose, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniformMatrix3fv(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::GlProgramUniformMatrix3fvEXT 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::glStencilThenCoverFillPathInstancedNV(CallObserver* observer, GLsizei numPaths, uint32_t pathNameType, void* paths, GLuint pathBase, uint32_t fillMode, GLuint mask, uint32_t coverMode, uint32_t transformType, GLfloat* transformValues) {
    GAPID_DEBUG("glStencilThenCoverFillPathInstancedNV(%" PRId32 ", %u, %p, %" PRIu32 ", %u, %" PRIu32 ", %u, %u, %p)", numPaths, pathNameType, paths, pathBase, fillMode, mask, coverMode, transformType, transformValues);

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

    bool called = false;
    auto call = [this, observer, &called, numPaths, pathNameType, paths, pathBase, fillMode, mask, coverMode, transformType, transformValues] {
        called = true;
        observer->observeReads();
        mImports.glStencilThenCoverFillPathInstancedNV(numPaths, pathNameType, paths, pathBase, fillMode, mask, 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::GlStencilThenCoverFillPathInstancedNV 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()), fillMode, toEncoder< uint32_t >(mask, *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::glStencilThenCoverStrokePathNV(CallObserver* observer, GLuint path, GLint reference, GLuint mask, uint32_t coverMode) {
    GAPID_DEBUG("glStencilThenCoverStrokePathNV(%" PRIu32 ", %" PRId32 ", %" PRIu32 ", %u)", path, reference, mask, coverMode);

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

    bool called = false;
    auto call = [this, observer, &called, path, reference, mask, coverMode] {
        called = true;
        observer->observeReads();
        mImports.glStencilThenCoverStrokePathNV(path, reference, mask, 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::GlStencilThenCoverStrokePathNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(path, *observer->getScratch()), toEncoder< int32_t >(reference, *observer->getScratch()), toEncoder< uint32_t >(mask, *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);

}

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

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

    GLboolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, fence] {
        called = true;
        observer->observeReads();
        result = mImports.glTestFenceNV(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::GlTestFenceNV 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;
}

void GlesSpy::glTexBufferRangeOES(CallObserver* observer, uint32_t target, uint32_t internalformat, BufferId buffer, GLintptr offset, GLsizeiptr size) {
    GAPID_DEBUG("glTexBufferRangeOES(%u, %u, %" PRIu32 ", %" PRId32 ", %" PRId32 ")", target, internalformat, buffer, offset, size);

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

    bool called = false;
    auto call = [this, observer, &called, target, internalformat, buffer, offset, size] {
        called = true;
        observer->observeReads();
        mImports.glTexBufferRangeOES(target, internalformat, buffer, offset, size);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_texture_buffer);
            subTexBufferRange(observer, call, target, internalformat, buffer, offset, size);
            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::GlTexBufferRangeOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, internalformat, toEncoder< uint32_t >(buffer, *observer->getScratch()), toEncoder< int32_t >(offset, *observer->getScratch()), toEncoder< int32_t >(size, *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::glTexParameterIivOES(CallObserver* observer, uint32_t target, uint32_t pname, GLint* params) {
    GAPID_DEBUG("glTexParameterIivOES(%u, %u, %p)", target, pname, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_texture_border_clamp);
            subTexParameterIiv(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::GlTexParameterIivOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, pname, toEncoder< gapic::coder::gles::GLint__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::glTextureStorage2DEXT(CallObserver* observer, TextureId texture, uint32_t target, GLsizei levels, uint32_t internalformat, GLsizei width, GLsizei height) {
    GAPID_DEBUG("glTextureStorage2DEXT(%" PRIu32 ", %u, %" PRId32 ", %u, %" PRId32 ", %" PRId32 ")", texture, target, levels, internalformat, width, height);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_texture_storage);
            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::GlTextureStorage2DEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(texture, *observer->getScratch()), target, toEncoder< int32_t >(levels, *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::glTextureViewEXT(CallObserver* observer, TextureId texture, uint32_t target, GLuint origtexture, uint32_t internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) {
    GAPID_DEBUG("glTextureViewEXT(%" PRIu32 ", %u, %" PRIu32 ", %u, %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);

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

    bool called = false;
    auto call = [this, observer, &called, texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers] {
        called = true;
        observer->observeReads();
        mImports.glTextureViewEXT(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_texture_view);
            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::GlTextureViewEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(texture, *observer->getScratch()), target, toEncoder< uint32_t >(origtexture, *observer->getScratch()), internalformat, toEncoder< uint32_t >(minlevel, *observer->getScratch()), toEncoder< uint32_t >(numlevels, *observer->getScratch()), toEncoder< uint32_t >(minlayer, *observer->getScratch()), toEncoder< uint32_t >(numlayers, *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::glUniformMatrix2x4fvNV(CallObserver* observer, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* value) {
    GAPID_DEBUG("glUniformMatrix2x4fvNV(%" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", location, count, transpose, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_non_square_matrices);
            subUniformMatrix2x4fv(observer, call, 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::GlUniformMatrix2x4fvNV 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 >(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::glUniformMatrix4x2fvNV(CallObserver* observer, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* value) {
    GAPID_DEBUG("glUniformMatrix4x2fvNV(%" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", location, count, transpose, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_non_square_matrices);
            subUniformMatrix4x2fv(observer, call, 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::GlUniformMatrix4x2fvNV 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 >(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::glDrawTransformFeedbackInstancedEXT(CallObserver* observer, uint32_t mode, GLuint id, GLsizei instancecount) {
    GAPID_DEBUG("glDrawTransformFeedbackInstancedEXT(%u, %" PRIu32 ", %" PRId32 ")", mode, id, instancecount);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_draw_transform_feedback);
            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::GlDrawTransformFeedbackInstancedEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), mode, toEncoder< uint32_t >(id, *observer->getScratch()), toEncoder< int32_t >(instancecount, *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::glProgramUniform3ui64vNV(CallObserver* observer, GLuint program, GLint location, GLsizei count, GLuint64EXT* value) {
    GAPID_DEBUG("glProgramUniform3ui64vNV(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_gpu_shader5);
            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::GlProgramUniform3ui64vNV 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::GLuint64EXT__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::glProgramUniform4i64vNV(CallObserver* observer, GLuint program, GLint location, GLsizei count, GLint64EXT* value) {
    GAPID_DEBUG("glProgramUniform4i64vNV(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_gpu_shader5);
            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::GlProgramUniform4i64vNV 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::GLint64EXT__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::glProgramUniformHandleui64IMG(CallObserver* observer, GLuint program, GLint location, GLuint64 value) {
    GAPID_DEBUG("glProgramUniformHandleui64IMG(%" PRIu32 ", %" PRId32 ", %" PRIu64 ")", program, location, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_IMG_bindless_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::GlProgramUniformHandleui64IMG coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< uint64_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::glUniform3ui64NV(CallObserver* observer, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z) {
    GAPID_DEBUG("glUniform3ui64NV(%" PRId32 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ")", location, x, y, z);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_gpu_shader5);
            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::GlUniform3ui64NV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< uint64_t >(x, *observer->getScratch()), toEncoder< uint64_t >(y, *observer->getScratch()), toEncoder< uint64_t >(z, *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::glUniform4i64NV(CallObserver* observer, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w) {
    GAPID_DEBUG("glUniform4i64NV(%" PRId32 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ")", location, x, y, z, w);

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

    bool called = false;
    auto call = [this, observer, &called, location, x, y, z, w] {
        called = true;
        observer->observeReads();
        mImports.glUniform4i64NV(location, x, y, z, w);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_gpu_shader5);
            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::GlUniform4i64NV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int64_t >(x, *observer->getScratch()), toEncoder< int64_t >(y, *observer->getScratch()), toEncoder< int64_t >(z, *observer->getScratch()), toEncoder< int64_t >(w, *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::glWindowRectanglesEXT(CallObserver* observer, uint32_t mode, GLsizei count, GLint* box) {
    GAPID_DEBUG("glWindowRectanglesEXT(%u, %" PRId32 ", %p)", mode, count, box);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_window_rectangles);
            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::GlWindowRectanglesEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), mode, toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::GLint__CP >(box, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

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

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            switch (target) {
                case GLenum::GL_FRAMEBUFFER: {
                    break;
                }
                case GLenum::GL_DRAW_FRAMEBUFFER: // fall-through...
                case GLenum::GL_READ_FRAMEBUFFER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(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::GlCheckFramebufferStatus coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

void GlesSpy::glClear(CallObserver* observer, uint32_t mask) {
    GAPID_DEBUG("glClear(%u)", mask);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            subSupportsBits(observer, call, mask, (GLbitfield::GL_COLOR_BUFFER_BIT) | ((GLbitfield::GL_DEPTH_BUFFER_BIT) | (GLbitfield::GL_STENCIL_BUFFER_BIT)));
            if ((mask & GLbitfield::GL_COLOR_BUFFER_BIT) != 0) {
            }
            if ((mask & GLbitfield::GL_DEPTH_BUFFER_BIT) != 0) {
            }
            if ((mask & GLbitfield::GL_STENCIL_BUFFER_BIT) != 0) {
            }
            if ((mask & GLbitfield::GL_COLOR_BUFFER_BIT) != 0) {
            }
            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::GlClear coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), 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::glClearBufferuiv(CallObserver* observer, uint32_t buffer, GLint drawbuffer, GLuint* value) {
    GAPID_DEBUG("glClearBufferuiv(%u, %" PRId32 ", %p)", buffer, drawbuffer, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            switch (buffer) {
                case GLenum::GL_COLOR: {
                    std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
                    if ((drawbuffer) >= (checkNotNull(l_ctx).mConstants.mMaxDrawBuffers)) {
                        subGlErrorInvalidValue(observer, call);
                    }
                    observer->read(slice(value, 0ULL, 4ULL));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, buffer);
                }
            }
            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::GlClearBufferuiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), buffer, toEncoder< int32_t >(drawbuffer, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__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::glDrawBuffers(CallObserver* observer, GLsizei n, uint32_t* bufs) {
    GAPID_DEBUG("glDrawBuffers(%" PRId32 ", %p)", n, bufs);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subDrawBuffers(observer, call, n, bufs);
            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::GlDrawBuffers coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(n, *observer->getScratch()), toEncoder< gapic::coder::gles::GLenum__CP >(bufs, *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::glFramebufferRenderbuffer(CallObserver* observer, uint32_t framebuffer_target, uint32_t framebuffer_attachment, uint32_t renderbuffer_target, RenderbufferId renderbuffer) {
    GAPID_DEBUG("glFramebufferRenderbuffer(%u, %u, %u, %" PRIu32 ")", framebuffer_target, framebuffer_attachment, renderbuffer_target, renderbuffer);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            switch (framebuffer_attachment) {
                case GLenum::GL_COLOR_ATTACHMENT0: // fall-through...
                case GLenum::GL_DEPTH_ATTACHMENT: // fall-through...
                case GLenum::GL_STENCIL_ATTACHMENT: {
                    break;
                }
                case GLenum::GL_COLOR_ATTACHMENT1: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT10: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT11: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT12: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT13: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT14: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT15: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT2: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT3: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT4: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT5: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT6: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT7: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT8: // fall-through...
                case GLenum::GL_COLOR_ATTACHMENT9: // fall-through...
                case GLenum::GL_DEPTH_STENCIL_ATTACHMENT: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, framebuffer_attachment);
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            if ((renderbuffer_target) != (GLenum::GL_RENDERBUFFER)) {
                subGlErrorInvalidEnum(observer, call, renderbuffer_target);
            }
            if (((renderbuffer) != ((RenderbufferId)(0UL))) && (!(checkNotNull(l_ctx).mInstances.mRenderbuffers.count(renderbuffer) > 0))) {
                subGlErrorInvalidOperation(observer, call);
            }
            FramebufferAttachment l_attachment = FramebufferAttachment(GLenum::GL_NONE, (GLuint)(0UL), (GLint)(0L), GLenum::GL_NONE, (GLint)(0L), GLbooleanLabels::GL_FALSE);
            if ((renderbuffer) != ((RenderbufferId)(0UL))) {
                l_attachment.mObjectType = GLenum::GL_RENDERBUFFER;
                l_attachment.mObjectName = (GLuint)(renderbuffer);
            }
            subSetFramebufferAttachment(observer, call, framebuffer_target, framebuffer_attachment, l_attachment);
            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::GlFramebufferRenderbuffer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), framebuffer_target, framebuffer_attachment, renderbuffer_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::glReadPixels(CallObserver* observer, GLint x, GLint y, GLsizei width, GLsizei height, uint32_t format, uint32_t type, void* data) {
    GAPID_DEBUG("glReadPixels(%" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %u, %u, %p)", x, y, width, height, format, type, data);

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

    bool called = false;
    auto call = [this, observer, &called, x, y, width, height, format, type, data] {
        called = true;
        observer->observeReads();
        mImports.glReadPixels(x, y, width, height, format, type, data);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            subCheckReadPixels(observer, call, width, height, format, type);
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            call();
            if (((checkNotNull(l_ctx).mBoundBuffers.mPixelPackBuffer) == ((BufferId)(0UL))) && ((data) != (nullptr))) {
                uint32_t l_requiredSize = subImageSize(observer, call, (uint32_t)(width), (uint32_t)(height), format, type);
                observer->write(slice(data, (uint64_t)(0UL), (uint64_t)(l_requiredSize)));
            }
        } 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::GlReadPixels coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(x, *observer->getScratch()), toEncoder< int32_t >(y, *observer->getScratch()), toEncoder< int32_t >(width, *observer->getScratch()), toEncoder< int32_t >(height, *observer->getScratch()), format, type, 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::glActiveShaderProgram(CallObserver* observer, PipelineId pipeline, ProgramId program) {
    GAPID_DEBUG("glActiveShaderProgram(%" PRIu32 ", %" PRIu32 ")", pipeline, program);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            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::GlActiveShaderProgram coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(pipeline, *observer->getScratch()), 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);

}

ShaderId GlesSpy::glCreateShader(CallObserver* observer, uint32_t type) {
    GAPID_DEBUG("glCreateShader(%u)", type);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            switch (type) {
                case GLenum::GL_FRAGMENT_SHADER: // fall-through...
                case GLenum::GL_VERTEX_SHADER: {
                    break;
                }
                case GLenum::GL_COMPUTE_SHADER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
                    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, type);
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            call();
            auto l_id = result;
            checkNotNull(l_ctx).mInstances.mShaders[l_id] = std::shared_ptr<Shader>(new Shader(l_id, type, Slice<uint8_t>(), false, false, Slice<GLchar>(), "", 0, "", 0));
            std::shared_ptr<Shader> l_s = findOrZero(checkNotNull(l_ctx).mInstances.mShaders, l_id);
            checkNotNull(l_s).mType = type;
            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::GlCreateShader coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), type, toEncoder< uint32_t >(result, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

void GlesSpy::glDeleteProgram(CallObserver* observer, ProgramId program) {
    GAPID_DEBUG("glDeleteProgram(%" PRIu32 ")", program);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            if ((program) != ((ProgramId)(0UL))) {
                std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
                subCheckProgram(observer, call, l_ctx, program);
                checkNotNull(findOrZero(checkNotNull(l_ctx).mInstances.mPrograms, program)).mDeleteStatus = true;
                if ((checkNotNull(l_ctx).mBoundProgram) != (program)) {
                    subReapProgram(observer, call, l_ctx, program);
                }
            }
            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::GlDeleteProgram coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), 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::glDispatchComputeIndirect(CallObserver* observer, GLintptr indirect) {
    GAPID_DEBUG("glDispatchComputeIndirect(%" PRId32 ")", indirect);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            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::GlDispatchComputeIndirect coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(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);

}

void GlesSpy::glGenProgramPipelines(CallObserver* observer, GLsizei n, PipelineId* pipelines) {
    GAPID_DEBUG("glGenProgramPipelines(%" PRId32 ", %p)", n, pipelines);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            call();
            observer->write(slice(pipelines, (uint64_t)((GLsizei)(0L)), (uint64_t)(n)));
        } 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::GlGenProgramPipelines coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(n, *observer->getScratch()), toEncoder< gapic::coder::gles::PipelineId__P >(pipelines, *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::glGetProgramBinary(CallObserver* observer, ProgramId program, GLsizei bufSize, GLsizei* length, uint32_t* binaryFormat, void* binary) {
    GAPID_DEBUG("glGetProgramBinary(%" PRIu32 ", %" PRId32 ", %p, %p, %p)", program, bufSize, length, binaryFormat, binary);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            call();
            subGetProgramBinary(observer, call, program, bufSize, length, binaryFormat, binary);
        } 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::GlGetProgramBinary coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(bufSize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLsizei__P >(length, *observer->getScratch()), toEncoder< gapic::coder::gles::GLenum__P >(binaryFormat, *observer->getScratch()), toEncoder< gapic::coder::gles::Void__P >(binary, *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::glGetnUniformiv(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei bufSize, GLint* values) {
    GAPID_DEBUG("glGetnUniformiv(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, bufSize, values);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            call();
            subGetnUniformiv(observer, call, program, location, bufSize, values);
        } 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::GlGetnUniformiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(bufSize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLint__P >(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::glProgramUniform1ui(CallObserver* observer, ProgramId program, UniformLocation location, GLuint value0) {
    GAPID_DEBUG("glProgramUniform1ui(%" PRIu32 ", %" PRId32 ", %" PRIu32 ")", program, location, value0);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subProgramUniform1ui(observer, call, program, location, value0);
            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::GlProgramUniform1ui coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), 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::glProgramUniform2iv(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLint* values) {
    GAPID_DEBUG("glProgramUniform2iv(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, values);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subProgramUniform2iv(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::GlProgramUniform2iv 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::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::glProgramUniform3fv(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLfloat* values) {
    GAPID_DEBUG("glProgramUniform3fv(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, values);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subProgramUniform3fv(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::GlProgramUniform3fv 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::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::glProgramUniformMatrix2fv(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* values) {
    GAPID_DEBUG("glProgramUniformMatrix2fv(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", program, location, count, transpose, values);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subProgramUniformMatrix2fv(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::GlProgramUniformMatrix2fv 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::glReleaseShaderCompiler(CallObserver* observer) {
    GAPID_DEBUG("glReleaseShaderCompiler()");

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            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::GlReleaseShaderCompiler 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::glUniform1uiv(CallObserver* observer, UniformLocation location, GLsizei count, GLuint* values) {
    GAPID_DEBUG("glUniform1uiv(%" PRId32 ", %" PRId32 ", %p)", location, count, values);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            Slice<GLuint> l_v = slice(values, (uint64_t)((GLsizei)(0L)), (uint64_t)(count));
            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::GlUniform1uiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), 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::glUniform2i(CallObserver* observer, UniformLocation location, GLint value0, GLint value1) {
    GAPID_DEBUG("glUniform2i(%" PRId32 ", %" PRId32 ", %" PRId32 ")", location, value0, value1);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            Slice<Vec2i> l_v = make<Vec2i>(1ULL);
            observer->write<Vec2i>(l_v, 0ULL, {value0, value1});
            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::GlUniform2i coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), 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::glUniform3f(CallObserver* observer, UniformLocation location, GLfloat value0, GLfloat value1, GLfloat value2) {
    GAPID_DEBUG("glUniform3f(%" PRId32 ", %f, %f, %f)", location, value0, value1, value2);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            Slice<Vec3f> l_v = make<Vec3f>(1ULL);
            observer->write<Vec3f>(l_v, 0ULL, {value0, value1, value2});
            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::GlUniform3f coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), 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::glUniformMatrix2x4fv(CallObserver* observer, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* values) {
    GAPID_DEBUG("glUniformMatrix2x4fv(%" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", location, count, transpose, values);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subUniformMatrix2x4fv(observer, call, 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::GlUniformMatrix2x4fv 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::glUniformMatrix4x2fv(CallObserver* observer, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* values) {
    GAPID_DEBUG("glUniformMatrix4x2fv(%" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", location, count, transpose, values);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subUniformMatrix4x2fv(observer, call, 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::GlUniformMatrix4x2fv 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::glUseProgram(CallObserver* observer, ProgramId program) {
    GAPID_DEBUG("glUseProgram(%" PRIu32 ")", program);

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

    bool called = false;
    auto call = [this, observer, &called, program] {
        called = true;
        observer->observeReads();
        mImports.glUseProgram(program);
        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 ((program) != ((ProgramId)(0UL))) {
                subCheckProgram(observer, call, l_ctx, program);
            }
            if (((program) == ((ProgramId)(0UL))) || (checkNotNull(l_ctx).mInstances.mPrograms.count(program) > 0)) {
                if ((checkNotNull(l_ctx).mBoundProgram) != (program)) {
                    subReapProgram(observer, call, l_ctx, checkNotNull(l_ctx).mBoundProgram);
                }
                checkNotNull(l_ctx).mBoundProgram = program;
            }
            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::GlUseProgram coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), 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::glCullFace(CallObserver* observer, uint32_t mode) {
    GAPID_DEBUG("glCullFace(%u)", mode);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            switch (mode) {
                case GLenum::GL_BACK: // fall-through...
                case GLenum::GL_FRONT: // fall-through...
                case GLenum::GL_FRONT_AND_BACK: {
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, mode);
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            checkNotNull(l_ctx).mRasterization.mCullFaceMode = 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::GlCullFace coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), 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::glGetInternalformativ(CallObserver* observer, uint32_t target, uint32_t internalformat, uint32_t pname, GLsizei bufSize, GLint* params) {
    GAPID_DEBUG("glGetInternalformativ(%u, %u, %u, %" PRId32 ", %p)", target, internalformat, pname, bufSize, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            switch (target) {
                case GLenum::GL_RENDERBUFFER: {
                    break;
                }
                case GLenum::GL_TEXTURE_2D_MULTISAMPLE: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
                    break;
                }
                case GLenum::GL_TEXTURE_2D_MULTISAMPLE_ARRAY: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, target);
                }
            }
            switch (internalformat) {
                case GLenum::GL_DEPTH24_STENCIL8: // fall-through...
                case GLenum::GL_DEPTH32F_STENCIL8: // fall-through...
                case GLenum::GL_DEPTH_COMPONENT16: // fall-through...
                case GLenum::GL_DEPTH_COMPONENT24: // fall-through...
                case GLenum::GL_DEPTH_COMPONENT32F: // fall-through...
                case GLenum::GL_R11F_G11F_B10F: // fall-through...
                case GLenum::GL_R16F: // fall-through...
                case GLenum::GL_R16I: // fall-through...
                case GLenum::GL_R16UI: // fall-through...
                case GLenum::GL_R32F: // fall-through...
                case GLenum::GL_R32I: // fall-through...
                case GLenum::GL_R32UI: // fall-through...
                case GLenum::GL_R8: // fall-through...
                case GLenum::GL_R8I: // fall-through...
                case GLenum::GL_R8UI: // fall-through...
                case GLenum::GL_R8_SNORM: // fall-through...
                case GLenum::GL_RG16F: // fall-through...
                case GLenum::GL_RG16I: // fall-through...
                case GLenum::GL_RG16UI: // fall-through...
                case GLenum::GL_RG32F: // fall-through...
                case GLenum::GL_RG32I: // fall-through...
                case GLenum::GL_RG32UI: // fall-through...
                case GLenum::GL_RG8: // fall-through...
                case GLenum::GL_RG8I: // fall-through...
                case GLenum::GL_RG8UI: // fall-through...
                case GLenum::GL_RG8_SNORM: // fall-through...
                case GLenum::GL_RGB10_A2: // fall-through...
                case GLenum::GL_RGB10_A2UI: // fall-through...
                case GLenum::GL_RGB16F: // fall-through...
                case GLenum::GL_RGB16I: // fall-through...
                case GLenum::GL_RGB16UI: // fall-through...
                case GLenum::GL_RGB32F: // fall-through...
                case GLenum::GL_RGB32I: // fall-through...
                case GLenum::GL_RGB32UI: // fall-through...
                case GLenum::GL_RGB565: // fall-through...
                case GLenum::GL_RGB5_A1: // fall-through...
                case GLenum::GL_RGB8: // fall-through...
                case GLenum::GL_RGB8I: // fall-through...
                case GLenum::GL_RGB8UI: // fall-through...
                case GLenum::GL_RGB8_SNORM: // fall-through...
                case GLenum::GL_RGB9_E5: // fall-through...
                case GLenum::GL_RGBA16F: // fall-through...
                case GLenum::GL_RGBA16I: // fall-through...
                case GLenum::GL_RGBA16UI: // fall-through...
                case GLenum::GL_RGBA32F: // fall-through...
                case GLenum::GL_RGBA32I: // fall-through...
                case GLenum::GL_RGBA32UI: // fall-through...
                case GLenum::GL_RGBA4: // fall-through...
                case GLenum::GL_RGBA8: // fall-through...
                case GLenum::GL_RGBA8I: // fall-through...
                case GLenum::GL_RGBA8UI: // fall-through...
                case GLenum::GL_RGBA8_SNORM: // fall-through...
                case GLenum::GL_SRGB8: // fall-through...
                case GLenum::GL_SRGB8_ALPHA8: {
                    break;
                }
                case GLenum::GL_STENCIL_INDEX8: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, internalformat);
                }
            }
            switch (pname) {
                case GLenum::GL_NUM_SAMPLE_COUNTS: // fall-through...
                case GLenum::GL_SAMPLES: {
                    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::GlGetInternalformativ coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, internalformat, pname, toEncoder< int32_t >(bufSize, *observer->getScratch()), 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);

}

GLubyte* GlesSpy::glGetString(CallObserver* observer, uint32_t param) {
    GAPID_DEBUG("glGetString(%u)", param);

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

    GLubyte* result = nullptr;
    bool called = false;
    auto call = [this, observer, &called, &result, param] {
        called = true;
        observer->observeReads();
        result = mImports.glGetString(param);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            switch (param) {
                case GLenum::GL_EXTENSIONS: // fall-through...
                case GLenum::GL_RENDERER: // fall-through...
                case GLenum::GL_SHADING_LANGUAGE_VERSION: // fall-through...
                case GLenum::GL_VENDOR: // fall-through...
                case GLenum::GL_VERSION: {
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, param);
                }
            }
            call();
            auto l_ret = result;
            (void)observer->string((char*)(l_ret));
            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::GlGetString coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), param, toEncoder< gapic::coder::gles::GLubyte__CP >(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;
}

uint32_t GlesSpy::glClientWaitSync(CallObserver* observer, GLsync sync, uint32_t syncFlags, GLuint64 timeout) {
    GAPID_DEBUG("glClientWaitSync(%p, %u, %" PRIu64 ")", sync, syncFlags, timeout);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subClientWaitSync(observer, call, sync, syncFlags, timeout);
            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::GlClientWaitSync coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::GLsync >(sync, *observer->getScratch()), syncFlags, toEncoder< uint64_t >(timeout, *observer->getScratch()), result);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

void GlesSpy::glActiveTexture(CallObserver* observer, uint32_t unit) {
    GAPID_DEBUG("glActiveTexture(%u)", unit);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            switch (unit) {
                case GLenum::GL_TEXTURE0: // fall-through...
                case GLenum::GL_TEXTURE1: // fall-through...
                case GLenum::GL_TEXTURE10: // fall-through...
                case GLenum::GL_TEXTURE11: // fall-through...
                case GLenum::GL_TEXTURE12: // fall-through...
                case GLenum::GL_TEXTURE13: // fall-through...
                case GLenum::GL_TEXTURE14: // fall-through...
                case GLenum::GL_TEXTURE15: // fall-through...
                case GLenum::GL_TEXTURE16: // fall-through...
                case GLenum::GL_TEXTURE17: // fall-through...
                case GLenum::GL_TEXTURE18: // fall-through...
                case GLenum::GL_TEXTURE19: // fall-through...
                case GLenum::GL_TEXTURE2: // fall-through...
                case GLenum::GL_TEXTURE20: // fall-through...
                case GLenum::GL_TEXTURE21: // fall-through...
                case GLenum::GL_TEXTURE22: // fall-through...
                case GLenum::GL_TEXTURE23: // fall-through...
                case GLenum::GL_TEXTURE24: // fall-through...
                case GLenum::GL_TEXTURE25: // fall-through...
                case GLenum::GL_TEXTURE26: // fall-through...
                case GLenum::GL_TEXTURE27: // fall-through...
                case GLenum::GL_TEXTURE28: // fall-through...
                case GLenum::GL_TEXTURE29: // fall-through...
                case GLenum::GL_TEXTURE3: // fall-through...
                case GLenum::GL_TEXTURE30: // fall-through...
                case GLenum::GL_TEXTURE31: // fall-through...
                case GLenum::GL_TEXTURE4: // fall-through...
                case GLenum::GL_TEXTURE5: // fall-through...
                case GLenum::GL_TEXTURE6: // fall-through...
                case GLenum::GL_TEXTURE7: // fall-through...
                case GLenum::GL_TEXTURE8: // fall-through...
                case GLenum::GL_TEXTURE9: {
                    break;
                }
                default: {
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            if (!(checkNotNull(l_ctx).mTextureUnits.count(unit) > 0)) {
                subGlErrorInvalidEnum(observer, call, unit);
            }
            checkNotNull(l_ctx).mActiveTextureUnit = unit;
            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::GlActiveTexture coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), unit);
    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::glBindSampler(CallObserver* observer, GLuint index, SamplerId sampler) {
    GAPID_DEBUG("glBindSampler(%" PRIu32 ", %" PRIu32 ")", index, sampler);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            uint32_t l_unit = (uint32_t)((index) + ((GLuint)(GLenum::GL_TEXTURE0)));
            checkNotNull(findOrZero(checkNotNull(l_ctx).mTextureUnits, l_unit)).mSamplerBinding = sampler;
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlBindSampler coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< uint32_t >(sampler, *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::glCompressedTexImage2D(CallObserver* observer, uint32_t target, GLint level, uint32_t format, GLsizei width, GLsizei height, GLint border, GLsizei image_size, TexturePointer data) {
    GAPID_DEBUG("glCompressedTexImage2D(%u, %" PRId32 ", %u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %p)", target, level, format, width, height, border, image_size, data);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            switch (target) {
                case GLenum::GL_TEXTURE_2D: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_NEGATIVE_X: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_POSITIVE_X: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_POSITIVE_Y: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_POSITIVE_Z: {
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, target);
                }
            }
            switch (format) {
                case GLenum::GL_COMPRESSED_R11_EAC: // fall-through...
                case GLenum::GL_COMPRESSED_RG11_EAC: // fall-through...
                case GLenum::GL_COMPRESSED_RGB8_ETC2: // fall-through...
                case GLenum::GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA8_ETC2_EAC: // fall-through...
                case GLenum::GL_COMPRESSED_SIGNED_R11_EAC: // fall-through...
                case GLenum::GL_COMPRESSED_SIGNED_RG11_EAC: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ETC2: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    break;
                }
                case GLenum::GL_ATC_RGB_AMD: // fall-through...
                case GLenum::GL_ATC_RGBA_EXPLICIT_ALPHA_AMD: // fall-through...
                case GLenum::GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
                    subRequiresExtension(observer, call, ExtensionId::GL_AMD_compressed_ATC_texture);
                    break;
                }
                case GLenum::GL_ETC1_RGB8_OES: {
                    subRequiresExtension(observer, call, ExtensionId::GL_OES_compressed_ETC1_RGB8_texture);
                    break;
                }
                case GLenum::GL_COMPRESSED_RGBA_ASTC_10x10: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_10x5: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_10x6: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_10x8: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_12x10: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_12x12: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_4x4: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_5x4: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_5x5: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_6x5: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_6x6: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_8x5: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_8x6: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_ASTC_8x8: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6: // fall-through...
                case GLenum::GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    break;
                }
                case GLenum::GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: // fall-through...
                case GLenum::GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
                    subRequiresExtension(observer, call, ExtensionId::GL_EXT_texture_compression_s3tc);
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, format);
                }
            }
            if (((border) != ((GLint)(0L))) || ((image_size) < ((GLsizei)(0L)))) {
                subGlErrorInvalidValue(observer, call);
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            subCheckMaxTextureSize(observer, call, l_ctx, target, level, width, height);
            switch (target) {
                case GLenum::GL_TEXTURE_2D: {
                    std::shared_ptr<Texture> l_t = subGetBoundTextureOrErrorInvalidEnum(observer, call, GLenum::GL_TEXTURE_2D);
                    Image l_l = Image(width, height, Slice<uint8_t>(), (uint32_t)(image_size), format, 0);
                    if (((checkNotNull(l_ctx).mBoundBuffers.mPixelUnpackBuffer) == ((BufferId)(0UL))) && ((data) != (nullptr))) {
                        l_l.mData = observer->clone(slice((uint8_t*)(data), (uint64_t)(0UL), (uint64_t)(l_l.mSize)));
                    }
                    checkNotNull(l_t).mTexture2D[level] = l_l;
                    checkNotNull(l_t).mTexelFormat = format;
                    break;
                }
                case GLenum::GL_TEXTURE_CUBE_MAP_POSITIVE_X: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_POSITIVE_Y: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_POSITIVE_Z: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_NEGATIVE_X: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: {
                    std::shared_ptr<Texture> l_t = subGetBoundTextureOrErrorInvalidEnum(observer, call, GLenum::GL_TEXTURE_CUBE_MAP);
                    Image l_l = Image(width, height, Slice<uint8_t>(), (uint32_t)(image_size), format, 0);
                    if (((checkNotNull(l_ctx).mBoundBuffers.mPixelUnpackBuffer) == ((BufferId)(0UL))) && ((data) != (nullptr))) {
                        l_l.mData = observer->clone(slice((uint8_t*)(data), (uint64_t)(0UL), (uint64_t)(l_l.mSize)));
                    }
                    CubemapLevel l_cube = findOrZero(checkNotNull(l_t).mCubemap, level);
                    l_cube.mFaces[target] = l_l;
                    checkNotNull(l_t).mCubemap[level] = l_cube;
                    checkNotNull(l_t).mTexelFormat = format;
                    break;
                }
            }
            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::GlCompressedTexImage2D coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(level, *observer->getScratch()), format, toEncoder< int32_t >(width, *observer->getScratch()), toEncoder< int32_t >(height, *observer->getScratch()), toEncoder< int32_t >(border, *observer->getScratch()), toEncoder< int32_t >(image_size, *observer->getScratch()), 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::glCopyTexImage2D(CallObserver* observer, uint32_t target, GLint level, uint32_t internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
    GAPID_DEBUG("glCopyTexImage2D(%u, %" PRId32 ", %u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", target, level, internalformat, x, y, width, height, border);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            switch (target) {
                case GLenum::GL_TEXTURE_2D: {
                    break;
                }
                case GLenum::GL_TEXTURE_CUBE_MAP_NEGATIVE_X: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_POSITIVE_X: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_POSITIVE_Y: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_POSITIVE_Z: {
                    if ((width) != (height)) {
                        subGlErrorInvalidValue(observer, call);
                    }
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, target);
                }
            }
            switch (internalformat) {
                case GLenum::GL_ALPHA: // fall-through...
                case GLenum::GL_LUMINANCE: // fall-through...
                case GLenum::GL_LUMINANCE_ALPHA: // fall-through...
                case GLenum::GL_RGB: // fall-through...
                case GLenum::GL_RGBA: {
                    break;
                }
                case GLenum::GL_R16I: // fall-through...
                case GLenum::GL_R16UI: // fall-through...
                case GLenum::GL_R32I: // fall-through...
                case GLenum::GL_R32UI: // fall-through...
                case GLenum::GL_R8: // fall-through...
                case GLenum::GL_R8I: // fall-through...
                case GLenum::GL_R8UI: // fall-through...
                case GLenum::GL_RG16I: // fall-through...
                case GLenum::GL_RG16UI: // fall-through...
                case GLenum::GL_RG32I: // fall-through...
                case GLenum::GL_RG32UI: // fall-through...
                case GLenum::GL_RG8: // fall-through...
                case GLenum::GL_RG8I: // fall-through...
                case GLenum::GL_RG8UI: // fall-through...
                case GLenum::GL_RGB10_A2: // fall-through...
                case GLenum::GL_RGB10_A2UI: // fall-through...
                case GLenum::GL_RGB565: // fall-through...
                case GLenum::GL_RGB5_A1: // fall-through...
                case GLenum::GL_RGB8: // fall-through...
                case GLenum::GL_RGBA16I: // fall-through...
                case GLenum::GL_RGBA16UI: // fall-through...
                case GLenum::GL_RGBA32I: // fall-through...
                case GLenum::GL_RGBA32UI: // fall-through...
                case GLenum::GL_RGBA4: // fall-through...
                case GLenum::GL_RGBA8: // fall-through...
                case GLenum::GL_RGBA8I: // fall-through...
                case GLenum::GL_RGBA8UI: // fall-through...
                case GLenum::GL_SRGB8: // fall-through...
                case GLenum::GL_SRGB8_ALPHA8: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, internalformat);
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            if ((border) != ((GLint)(0L))) {
                subGlErrorInvalidValue(observer, call);
            }
            subCheckMaxTextureSize(observer, call, l_ctx, target, level, 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::GlCopyTexImage2D coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(level, *observer->getScratch()), internalformat, toEncoder< int32_t >(x, *observer->getScratch()), toEncoder< int32_t >(y, *observer->getScratch()), toEncoder< int32_t >(width, *observer->getScratch()), toEncoder< int32_t >(height, *observer->getScratch()), toEncoder< int32_t >(border, *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::glGetTexParameterIuiv(CallObserver* observer, uint32_t target, uint32_t pname, GLuint* params) {
    GAPID_DEBUG("glGetTexParameterIuiv(%u, %u, %p)", target, pname, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            call();
            subGetTexParameterIuiv(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::GlGetTexParameterIuiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, 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::glSamplerParameterIiv(CallObserver* observer, SamplerId sampler, uint32_t pname, GLint* param) {
    GAPID_DEBUG("glSamplerParameterIiv(%" PRIu32 ", %u, %p)", sampler, pname, param);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            subSamplerParameterIiv(observer, call, sampler, pname, param);
            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::GlSamplerParameterIiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(sampler, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLint__CP >(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::glTexStorage3D(CallObserver* observer, uint32_t target, GLsizei levels, uint32_t internalformat, GLsizei width, GLsizei height, GLsizei depth) {
    GAPID_DEBUG("glTexStorage3D(%u, %" PRId32 ", %u, %" PRId32 ", %" PRId32 ", %" PRId32 ")", target, levels, internalformat, width, height, depth);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subTexStorage3D(observer, call, target, levels, internalformat, width, height, depth);
            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::GlTexStorage3D coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(levels, *observer->getScratch()), internalformat, toEncoder< int32_t >(width, *observer->getScratch()), toEncoder< int32_t >(height, *observer->getScratch()), toEncoder< int32_t >(depth, *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::glVertexAttrib1f(CallObserver* observer, AttributeLocation location, GLfloat value0) {
    GAPID_DEBUG("glVertexAttrib1f(%" PRIu32 ", %f)", location, value0);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            subVertexAttribF(observer, call, location, std::move(Vec4f{value0, (GLfloat)(0.f), (GLfloat)(0.f), (GLfloat)(1.f)}));
            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::GlVertexAttrib1f coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(location, *observer->getScratch()), toEncoder< float >(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::glVertexAttribI4ui(CallObserver* observer, AttributeLocation index, GLuint x, GLuint y, GLuint z, GLuint w) {
    GAPID_DEBUG("glVertexAttribI4ui(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", index, x, y, z, w);

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

    bool called = false;
    auto call = [this, observer, &called, index, x, y, z, w] {
        called = true;
        observer->observeReads();
        mImports.glVertexAttribI4ui(index, x, y, z, w);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subVertexAttribI(observer, call, index, std::move(Vec4i{(GLint)(x), (GLint)(y), (GLint)(z), (GLint)(w)}));
            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::GlVertexAttribI4ui coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< uint32_t >(x, *observer->getScratch()), toEncoder< uint32_t >(y, *observer->getScratch()), toEncoder< uint32_t >(z, *observer->getScratch()), toEncoder< uint32_t >(w, *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);

}

GLXContext GlesSpy::glXCreateNewContext(CallObserver* observer, void* display, void* fbconfig, uint32_t type, GLXContext shared, bool direct) {
    GAPID_DEBUG("glXCreateNewContext(%p, %p, %" PRIu32 ", %p, %d)", display, fbconfig, type, shared, direct);

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

    GLXContext result = nullptr;
    bool called = false;
    auto call = [this, observer, &called, &result, display, fbconfig, type, shared, direct] {
        called = true;
        observer->observeReads();
        result = mImports.glXCreateNewContext(display, fbconfig, type, shared, direct);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            auto l_context = result;
            std::shared_ptr<Context> l__res_0 = subCreateContext(observer, call);
            this->GLXContexts[l_context] = 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::GlXCreateNewContext coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::Void__P >(display, *observer->getScratch()), toEncoder< gapic::coder::gles::Void__P >(fbconfig, *observer->getScratch()), type, toEncoder< gapic::coder::gles::GLXContext >(shared, *observer->getScratch()), direct, toEncoder< gapic::coder::gles::GLXContext >(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;
}

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

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

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

    onPreEndOfFrame();

    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::CGLFlushDrawable 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::glBlendEquationSeparateOES(CallObserver* observer, uint32_t modeRGB, uint32_t modeAlpha) {
    GAPID_DEBUG("glBlendEquationSeparateOES(%u, %u)", modeRGB, modeAlpha);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_blend_equation_separate);
            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::GlBlendEquationSeparateOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), modeRGB, modeAlpha);
    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::glBlendFuncSeparateOES(CallObserver* observer, uint32_t srcRGB, uint32_t dstRGB, uint32_t srcAlpha, uint32_t dstAlpha) {
    GAPID_DEBUG("glBlendFuncSeparateOES(%u, %u, %u, %u)", srcRGB, dstRGB, srcAlpha, dstAlpha);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_blend_func_separate);
            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::GlBlendFuncSeparateOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), srcRGB, dstRGB, srcAlpha, dstAlpha);
    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::glClearDepthfOES(CallObserver* observer, GLclampf depth) {
    GAPID_DEBUG("glClearDepthfOES(%f)", depth);

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

    bool called = false;
    auto call = [this, observer, &called, depth] {
        called = true;
        observer->observeReads();
        mImports.glClearDepthfOES(depth);
        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::GlClearDepthfOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< float >(depth, *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::glColor4f(CallObserver* observer, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
    GAPID_DEBUG("glColor4f(%f, %f, %f, %f)", red, green, blue, alpha);

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

    bool called = false;
    auto call = [this, observer, &called, red, green, blue, alpha] {
        called = true;
        observer->observeReads();
        mImports.glColor4f(red, green, blue, alpha);
        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::GlColor4f coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< float >(red, *observer->getScratch()), toEncoder< float >(green, *observer->getScratch()), toEncoder< float >(blue, *observer->getScratch()), toEncoder< float >(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::glDepthRangefOES(CallObserver* observer, GLclampf n, GLclampf f) {
    GAPID_DEBUG("glDepthRangefOES(%f, %f)", n, f);

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

    bool called = false;
    auto call = [this, observer, &called, n, f] {
        called = true;
        observer->observeReads();
        mImports.glDepthRangefOES(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::GlDepthRangefOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), 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::glDrawTexivOES(CallObserver* observer, GLint* coords) {
    GAPID_DEBUG("glDrawTexivOES(%p)", coords);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_draw_texture);
            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::GlDrawTexivOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::GLint__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);
    onPostDrawCall();

}

void GlesSpy::glDrawTexsOES(CallObserver* observer, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) {
    GAPID_DEBUG("glDrawTexsOES(%" PRId16 ", %" PRId16 ", %" PRId16 ", %" PRId16 ", %" PRId16 ")", x, y, z, width, height);

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

    bool called = false;
    auto call = [this, observer, &called, x, y, z, width, height] {
        called = true;
        observer->observeReads();
        mImports.glDrawTexsOES(x, y, z, width, height);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_draw_texture);
            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::GlDrawTexsOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int16_t >(x, *observer->getScratch()), toEncoder< int16_t >(y, *observer->getScratch()), toEncoder< int16_t >(z, *observer->getScratch()), toEncoder< int16_t >(width, *observer->getScratch()), toEncoder< int16_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);
    onPostDrawCall();

}

void GlesSpy::glEnableClientState(CallObserver* observer, uint32_t array) {
    GAPID_DEBUG("glEnableClientState(%u)", array);

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

    bool called = false;
    auto call = [this, observer, &called, array] {
        called = true;
        observer->observeReads();
        mImports.glEnableClientState(array);
        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::GlEnableClientState coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), array);
    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::glFramebufferTexture2DOES(CallObserver* observer, uint32_t target, uint32_t attachment, uint32_t textarget, TextureId texture, GLint level) {
    GAPID_DEBUG("glFramebufferTexture2DOES(%u, %u, %u, %" PRIu32 ", %" PRId32 ")", target, attachment, textarget, texture, level);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_framebuffer_object);
            subFramebufferTexture2D(observer, call, target, attachment, textarget, 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::GlFramebufferTexture2DOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, attachment, textarget, 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::glGetClipPlanexOES(CallObserver* observer, uint32_t plane, GLfixed* equation) {
    GAPID_DEBUG("glGetClipPlanexOES(%u, %p)", plane, equation);

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

    bool called = false;
    auto call = [this, observer, &called, plane, equation] {
        called = true;
        observer->observeReads();
        mImports.glGetClipPlanexOES(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::GlGetClipPlanexOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), plane, toEncoder< gapic::coder::gles::GLfixed__P >(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::glGetMaterialfv(CallObserver* observer, uint32_t face, uint32_t pname, GLfloat* params) {
    GAPID_DEBUG("glGetMaterialfv(%u, %u, %p)", face, pname, params);

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

    bool called = false;
    auto call = [this, observer, &called, face, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glGetMaterialfv(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::GlGetMaterialfv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), face, pname, toEncoder< gapic::coder::gles::GLfloat__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::glLightModelf(CallObserver* observer, uint32_t pname, GLfloat param) {
    GAPID_DEBUG("glLightModelf(%u, %f)", pname, param);

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

    bool called = false;
    auto call = [this, observer, &called, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glLightModelf(pname, param);
        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::GlLightModelf coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< float >(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::glLightxOES(CallObserver* observer, uint32_t light, uint32_t pname, GLfixed param) {
    GAPID_DEBUG("glLightxOES(%u, %u, %" PRId32 ")", light, pname, param);

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

    bool called = false;
    auto call = [this, observer, &called, light, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glLightxOES(light, 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::GlLightxOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), light, 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::glLoadPaletteFromModelViewMatrixOES(CallObserver* observer) {
    GAPID_DEBUG("glLoadPaletteFromModelViewMatrixOES()");

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_matrix_palette);
            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::GlLoadPaletteFromModelViewMatrixOES 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::glMaterialf(CallObserver* observer, uint32_t face, uint32_t pname, GLfloat param) {
    GAPID_DEBUG("glMaterialf(%u, %u, %f)", face, pname, param);

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

    bool called = false;
    auto call = [this, observer, &called, face, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glMaterialf(face, pname, param);
        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::GlMaterialf coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), face, pname, toEncoder< float >(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::glMatrixIndexPointerOES(CallObserver* observer, GLint size, uint32_t type, GLsizei stride, void* pointer) {
    GAPID_DEBUG("glMatrixIndexPointerOES(%" PRId32 ", %u, %" PRId32 ", %p)", size, type, stride, pointer);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_matrix_palette);
            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::GlMatrixIndexPointerOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(size, *observer->getScratch()), type, toEncoder< int32_t >(stride, *observer->getScratch()), toEncoder< gapic::coder::gles::Void__CP >(pointer, *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::glOrthofOES(CallObserver* observer, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) {
    GAPID_DEBUG("glOrthofOES(%f, %f, %f, %f, %f, %f)", l, r, b, t, n, f);

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

    bool called = false;
    auto call = [this, observer, &called, l, r, b, t, n, f] {
        called = true;
        observer->observeReads();
        mImports.glOrthofOES(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::GlOrthofOES 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::glPointParameterf(CallObserver* observer, uint32_t pname, GLfloat param) {
    GAPID_DEBUG("glPointParameterf(%u, %f)", pname, param);

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

    bool called = false;
    auto call = [this, observer, &called, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glPointParameterf(pname, param);
        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::GlPointParameterf coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< float >(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::glPointSizePointerOES(CallObserver* observer, uint32_t type, GLsizei stride, void* pointer) {
    GAPID_DEBUG("glPointSizePointerOES(%u, %" PRId32 ", %p)", type, stride, pointer);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_point_size_array);
            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::GlPointSizePointerOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), type, toEncoder< int32_t >(stride, *observer->getScratch()), toEncoder< gapic::coder::gles::Void__CP >(pointer, *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::glPointSizex(CallObserver* observer, GLfixed size) {
    GAPID_DEBUG("glPointSizex(%" PRId32 ")", size);

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

    bool called = false;
    auto call = [this, observer, &called, size] {
        called = true;
        observer->observeReads();
        mImports.glPointSizex(size);
        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::GlPointSizex coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(size, *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::glPushMatrix(CallObserver* observer) {
    GAPID_DEBUG("glPushMatrix()");

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

    bool called = false;
    auto call = [this, observer, &called] {
        called = true;
        observer->observeReads();
        mImports.glPushMatrix();
        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::GlPushMatrix 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::glRotatex(CallObserver* observer, GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
    GAPID_DEBUG("glRotatex(%" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", angle, x, y, z);

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

    bool called = false;
    auto call = [this, observer, &called, angle, x, y, z] {
        called = true;
        observer->observeReads();
        mImports.glRotatex(angle, x, y, z);
        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::GlRotatex coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(angle, *observer->getScratch()), toEncoder< int32_t >(x, *observer->getScratch()), toEncoder< int32_t >(y, *observer->getScratch()), toEncoder< int32_t >(z, *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::glTexParameterxOES(CallObserver* observer, uint32_t target, uint32_t pname, GLfixed param) {
    GAPID_DEBUG("glTexParameterxOES(%u, %u, %" PRId32 ")", target, pname, param);

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

    bool called = false;
    auto call = [this, observer, &called, target, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glTexParameterxOES(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::GlTexParameterxOES 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::glColorPointerBounds(CallObserver* observer, GLint size, uint32_t type, GLsizei stride, void* pointer, GLsizei count) {
    GAPID_DEBUG("glColorPointerBounds(%" PRId32 ", %u, %" PRId32 ", %p, %" PRId32 ")", size, type, stride, pointer, count);

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

    bool called = false;
    auto call = [this, observer, &called, size, type, stride, pointer, count] {
        called = true;
        observer->observeReads();
        mImports.glColorPointerBounds(size, 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::GlColorPointerBounds coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(size, *observer->getScratch()), 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);

}

void GlesSpy::replayChangeBackbuffer(CallObserver* observer, GLsizei backbuffer_width, GLsizei backbuffer_height, uint32_t backbuffer_color_fmt, uint32_t backbuffer_depth_fmt, uint32_t backbuffer_stencil_fmt, bool reset_viewport_scissor) {
    GAPID_DEBUG("replayChangeBackbuffer(%" PRId32 ", %" PRId32 ", %u, %u, %u, %d)", backbuffer_width, backbuffer_height, backbuffer_color_fmt, backbuffer_depth_fmt, backbuffer_stencil_fmt, reset_viewport_scissor);

    bool called = false;
    auto call = [this, observer, &called, backbuffer_width, backbuffer_height, backbuffer_color_fmt, backbuffer_depth_fmt, backbuffer_stencil_fmt, reset_viewport_scissor] {
        called = true;
        observer->observeReads();
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::ReplayChangeBackbuffer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(backbuffer_width, *observer->getScratch()), toEncoder< int32_t >(backbuffer_height, *observer->getScratch()), backbuffer_color_fmt, backbuffer_depth_fmt, backbuffer_stencil_fmt, reset_viewport_scissor);
    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