/*
 * 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::glTexBufferRangeEXT(CallObserver* observer, uint32_t target, uint32_t internalformat, BufferId buffer, GLintptr offset, GLsizeiptr size) {
    GAPID_DEBUG("glTexBufferRangeEXT(%u, %u, %" PRIu32 ", %" PRId32 ", %" PRId32 ")", target, internalformat, buffer, offset, size);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_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::GlTexBufferRangeEXT 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::glTexParameterIivEXT(CallObserver* observer, uint32_t target, uint32_t pname, GLint* params) {
    GAPID_DEBUG("glTexParameterIivEXT(%u, %u, %p)", target, pname, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_texture_border_clamp);
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            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::GlTexParameterIivEXT 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::glGetQueryiv(CallObserver* observer, uint32_t target, uint32_t parameter, GLint* value) {
    GAPID_DEBUG("glGetQueryiv(%u, %u, %p)", target, parameter, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            switch (target) {
                case GLenum::GL_ANY_SAMPLES_PASSED: // fall-through...
                case GLenum::GL_ANY_SAMPLES_PASSED_CONSERVATIVE: // fall-through...
                case GLenum::GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: {
                    break;
                }
                case GLenum::GL_PRIMITIVES_GENERATED: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    break;
                }
                case GLenum::GL_TIMESTAMP_EXT: {
                    subRequiresExtension(observer, call, ExtensionId::GL_EXT_disjoint_timer_query);
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, target);
                }
            }
            call();
            switch (parameter) {
                case GLenum::GL_CURRENT_QUERY: {
                    std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
                    if (checkNotNull(l_ctx).mActiveQueries.count(target) > 0) {
                        observer->write<GLint>(slice(value, 0ULL, 1ULL), 0ULL, (GLint)(findOrZero(checkNotNull(l_ctx).mActiveQueries, target)));
                    } else {
                        observer->write<GLint>(slice(value, 0ULL, 1ULL), 0ULL, (GLint)(0L));
                    }
                    break;
                }
                case GLenum::GL_QUERY_COUNTER_BITS_EXT: {
                    subRequiresExtension(observer, call, ExtensionId::GL_EXT_disjoint_timer_query);
                    observer->write<GLint>(slice(value, 0ULL, 1ULL), 0ULL, slice(value, 0ULL, 1ULL)[0ULL]);
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, parameter);
                }
            }
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, 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::GlGetQueryiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, parameter, 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::glCopyBufferSubData(CallObserver* observer, uint32_t readTarget, uint32_t writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
    GAPID_DEBUG("glCopyBufferSubData(%u, %u, %" PRId32 ", %" PRId32 ", %" PRId32 ")", readTarget, writeTarget, readOffset, writeOffset, size);

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

    bool called = false;
    auto call = [this, observer, &called, readTarget, writeTarget, readOffset, writeOffset, size] {
        called = true;
        observer->observeReads();
        mImports.glCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subCopyBufferSubData(observer, call, readTarget, writeTarget, readOffset, writeOffset, 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::GlCopyBufferSubData coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), readTarget, writeTarget, toEncoder< int32_t >(readOffset, *observer->getScratch()), toEncoder< int32_t >(writeOffset, *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::glDebugMessageInsert(CallObserver* observer, uint32_t source, uint32_t type, GLuint id, uint32_t severity, GLsizei length, GLchar* message) {
    GAPID_DEBUG("glDebugMessageInsert(%u, %u, %" PRIu32 ", %u, %" PRId32 ", %p)", source, type, id, severity, length, message);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            subDebugMessageInsert(observer, call, source, type, id, severity, length, message);
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlDebugMessageInsert coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), source, type, toEncoder< uint32_t >(id, *observer->getScratch()), severity, toEncoder< int32_t >(length, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__CP >(message, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glGetObjectPtrLabel(CallObserver* observer, void* ptr, GLsizei bufSize, GLsizei* length, GLchar* label) {
    GAPID_DEBUG("glGetObjectPtrLabel(%p, %" PRId32 ", %p, %p)", ptr, bufSize, length, label);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            call();
            subGetObjectPtrLabel(observer, call, ptr, bufSize, length, label);
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, 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::GlGetObjectPtrLabel coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::Void__CP >(ptr, *observer->getScratch()), toEncoder< int32_t >(bufSize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLsizei__P >(length, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__P >(label, *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::glObjectLabel(CallObserver* observer, uint32_t identifier, GLuint name, GLsizei length, GLchar* label) {
    GAPID_DEBUG("glObjectLabel(%u, %" PRIu32 ", %" PRId32 ", %p)", identifier, name, length, label);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            subObjectLabel(observer, call, identifier, name, length, label);
            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::GlObjectLabel coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), identifier, toEncoder< uint32_t >(name, *observer->getScratch()), toEncoder< int32_t >(length, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__CP >(label, *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);

}

EGLSurface GlesSpy::eglCreatePixmapSurface(CallObserver* observer, EGLDisplay display, EGLConfig config, EGLNativePixmapType native_pixmap, EGLint* attrib_list) {
    GAPID_DEBUG("eglCreatePixmapSurface(%p, %p, %p, %p)", display, config, native_pixmap, attrib_list);

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

    EGLSurface result = nullptr;
    bool called = false;
    auto call = [this, observer, &called, &result, display, config, native_pixmap, attrib_list] {
        called = true;
        observer->observeReads();
        result = mImports.eglCreatePixmapSurface(display, config, native_pixmap, 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::EglCreatePixmapSurface coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::EGLDisplay >(display, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLConfig >(config, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLNativePixmapType >(native_pixmap, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLint__CP >(attrib_list, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLSurface >(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;
}

EGLContext GlesSpy::eglGetCurrentContext(CallObserver* observer) {
    GAPID_DEBUG("eglGetCurrentContext()");

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

    EGLContext result = nullptr;
    bool called = false;
    auto call = [this, observer, &called, &result] {
        called = true;
        observer->observeReads();
        result = mImports.eglGetCurrentContext();
        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::EglGetCurrentContext coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::EGLContext >(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;
}

EGLSurface GlesSpy::eglGetCurrentSurface(CallObserver* observer, EGLint readdraw) {
    GAPID_DEBUG("eglGetCurrentSurface(%d)", readdraw);

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

    EGLSurface result = nullptr;
    bool called = false;
    auto call = [this, observer, &called, &result, readdraw] {
        called = true;
        observer->observeReads();
        result = mImports.eglGetCurrentSurface(readdraw);
        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::EglGetCurrentSurface coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int >(readdraw, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLSurface >(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::eglInitialize(CallObserver* observer, EGLDisplay dpy, EGLint* major, EGLint* minor) {
    GAPID_DEBUG("eglInitialize(%p, %p, %p)", dpy, major, minor);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            call();
            if ((major) != (nullptr)) {
                observer->write<EGLint>(slice(major, 0ULL, 1ULL), 0ULL, slice(major, 0ULL, 1ULL)[0ULL]);
            }
            if ((major) != (nullptr)) {
                observer->write<EGLint>(slice(minor, 0ULL, 1ULL), 0ULL, slice(minor, 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::EglInitialize coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::EGLDisplay >(dpy, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLint__P >(major, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLint__P >(minor, *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;
}

EGLBoolean GlesSpy::eglSwapBuffersWithDamageKHR(CallObserver* observer, EGLDisplay dpy, EGLSurface surface, EGLint* rects, EGLint n_rects) {
    GAPID_DEBUG("eglSwapBuffersWithDamageKHR(%p, %p, %p, %d)", dpy, surface, rects, n_rects);

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

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

    onPreEndOfFrame();

    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            observer->read(slice(rects, (uint64_t)(0L), (uint64_t)((n_rects) * ((EGLint)(4L)))));
            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::EglSwapBuffersWithDamageKHR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::EGLDisplay >(dpy, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLSurface >(surface, *observer->getScratch()), toEncoder< gapic::coder::gles::EGLint__P >(rects, *observer->getScratch()), toEncoder< int >(n_rects, *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;
}

EGLBoolean GlesSpy::eglSwapInterval(CallObserver* observer, EGLDisplay display, EGLint interval) {
    GAPID_DEBUG("eglSwapInterval(%p, %d)", display, interval);

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

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

EGLBoolean GlesSpy::eglWaitGL(CallObserver* observer) {
    GAPID_DEBUG("eglWaitGL()");

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

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

EGLBoolean GlesSpy::eglWaitNative(CallObserver* observer, EGLint engine) {
    GAPID_DEBUG("eglWaitNative(%d)", engine);

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

    EGLBoolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, engine] {
        called = true;
        observer->observeReads();
        result = mImports.eglWaitNative(engine);
        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::EglWaitNative coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int >(engine, *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::glBeginConditionalRenderNV(CallObserver* observer, GLuint id, uint32_t mode) {
    GAPID_DEBUG("glBeginConditionalRenderNV(%" PRIu32 ", %u)", id, mode);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_conditional_render);
            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::GlBeginConditionalRenderNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(id, *observer->getScratch()), mode);
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glBindFragDataLocationEXT(CallObserver* observer, ProgramId program, GLuint color, const char* name) {
    GAPID_DEBUG("glBindFragDataLocationEXT(%" PRIu32 ", %" PRIu32 ", %s)", program, color, name);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_blend_func_extended);
            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::GlBindFragDataLocationEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< uint32_t >(color, *observer->getScratch()), toEncoder< const char* >(name, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glBindVertexArrayOES(CallObserver* observer, VertexArrayId array) {
    GAPID_DEBUG("glBindVertexArrayOES(%" PRIu32 ")", array);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_vertex_array_object);
            subBindVertexArray(observer, call, array);
            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::GlBindVertexArrayOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(array, *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::glClientWaitSyncAPPLE(CallObserver* observer, GLsync sync, uint32_t flag, GLuint64 timeout) {
    GAPID_DEBUG("glClientWaitSyncAPPLE(%p, %u, %" PRIu64 ")", sync, flag, timeout);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_APPLE_sync);
            subClientWaitSync(observer, call, sync, flag, 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::GlClientWaitSyncAPPLE coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::GLsync >(sync, *observer->getScratch()), flag, 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::glCopyBufferSubDataNV(CallObserver* observer, uint32_t readTarget, uint32_t writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
    GAPID_DEBUG("glCopyBufferSubDataNV(%u, %u, %" PRId32 ", %" PRId32 ", %" PRId32 ")", readTarget, writeTarget, readOffset, writeOffset, size);

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

    bool called = false;
    auto call = [this, observer, &called, readTarget, writeTarget, readOffset, writeOffset, size] {
        called = true;
        observer->observeReads();
        mImports.glCopyBufferSubDataNV(readTarget, writeTarget, readOffset, writeOffset, size);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_copy_buffer);
            subCopyBufferSubData(observer, call, readTarget, writeTarget, readOffset, writeOffset, 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::GlCopyBufferSubDataNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), readTarget, writeTarget, toEncoder< int32_t >(readOffset, *observer->getScratch()), toEncoder< int32_t >(writeOffset, *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::glCoverageOperationNV(CallObserver* observer, uint32_t operation) {
    GAPID_DEBUG("glCoverageOperationNV(%u)", operation);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    if (counter_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::glCreatePerfQueryINTEL(CallObserver* observer, GLuint queryId, GLuint* queryHandle) {
    GAPID_DEBUG("glCreatePerfQueryINTEL(%" PRIu32 ", %p)", queryId, queryHandle);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlCreatePerfQueryINTEL coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(queryId, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__P >(queryHandle, *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::glDeletePerfMonitorsAMD(CallObserver* observer, GLsizei n, GLuint* monitors) {
    GAPID_DEBUG("glDeletePerfMonitorsAMD(%" PRId32 ", %p)", n, monitors);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlDeletePerfMonitorsAMD coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(n, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__P >(monitors, *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::glDisableiNV(CallObserver* observer, uint32_t target, GLuint index) {
    GAPID_DEBUG("glDisableiNV(%u, %" PRIu32 ")", target, index);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlDisableiNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< uint32_t >(index, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glDrawElementsBaseVertexEXT(CallObserver* observer, uint32_t mode, GLsizei count, uint32_t type, IndicesPointer indices, GLint basevertex) {
    GAPID_DEBUG("glDrawElementsBaseVertexEXT(%u, %" PRId32 ", %u, %p, %" PRId32 ")", mode, count, type, indices, basevertex);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_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::GlDrawElementsBaseVertexEXT 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::glDrawElementsInstancedANGLE(CallObserver* observer, uint32_t mode, GLsizei count, uint32_t type, IndicesPointer indices, GLsizei primcount) {
    GAPID_DEBUG("glDrawElementsInstancedANGLE(%u, %" PRId32 ", %u, %p, %" PRId32 ")", mode, count, type, indices, primcount);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_ANGLE_instanced_arrays);
            subDrawElementsInstanced(observer, call, mode, count, type, indices, 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::GlDrawElementsInstancedANGLE 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 >(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::glDrawElementsInstancedEXT(CallObserver* observer, uint32_t mode, GLsizei count, uint32_t type, IndicesPointer indices, GLsizei primcount) {
    GAPID_DEBUG("glDrawElementsInstancedEXT(%u, %" PRId32 ", %u, %p, %" PRId32 ")", mode, count, type, indices, primcount);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension2(observer, call, ExtensionId::GL_EXT_draw_instanced, ExtensionId::GL_EXT_instanced_arrays);
            subDrawElementsInstanced(observer, call, mode, count, type, indices, 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::GlDrawElementsInstancedEXT 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 >(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::glEnableiOES(CallObserver* observer, uint32_t target, GLuint index) {
    GAPID_DEBUG("glEnableiOES(%u, %" PRIu32 ")", target, index);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlEnableiOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< uint32_t >(index, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

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

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_conditional_render);
            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::GlEndConditionalRenderNV 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::glExtGetProgramBinarySourceQCOM(CallObserver* observer, ProgramId program, uint32_t shadertype, GLchar* source, GLint* length) {
    GAPID_DEBUG("glExtGetProgramBinarySourceQCOM(%" PRIu32 ", %u, %p, %p)", program, shadertype, source, length);

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

    bool called = false;
    auto call = [this, observer, &called, program, shadertype, source, length] {
        called = true;
        observer->observeReads();
        mImports.glExtGetProgramBinarySourceQCOM(program, shadertype, source, length);
        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::GlExtGetProgramBinarySourceQCOM coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), shadertype, toEncoder< gapic::coder::gles::GLchar__P >(source, *observer->getScratch()), toEncoder< gapic::coder::gles::GLint__P >(length, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glExtTexObjectStateOverrideiQCOM(CallObserver* observer, uint32_t target, uint32_t pname, GLint param) {
    GAPID_DEBUG("glExtTexObjectStateOverrideiQCOM(%u, %u, %" PRId32 ")", target, pname, param);

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

    bool called = false;
    auto call = [this, observer, &called, target, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glExtTexObjectStateOverrideiQCOM(target, pname, param);
        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::GlExtTexObjectStateOverrideiQCOM 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::glFlushMappedBufferRangeEXT(CallObserver* observer, uint32_t target, GLintptr offset, GLsizeiptr length) {
    GAPID_DEBUG("glFlushMappedBufferRangeEXT(%u, %" PRId32 ", %" PRId32 ")", target, offset, length);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_map_buffer_range);
            subFlushMappedBufferRange(observer, call, target, offset, length);
            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::GlFlushMappedBufferRangeEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(offset, *observer->getScratch()), toEncoder< int32_t >(length, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glFramebufferTextureMultiviewOVR(CallObserver* observer, uint32_t target, uint32_t attachment, TextureId texture, GLint level, GLint baseViewIndex, GLsizei numViews) {
    GAPID_DEBUG("glFramebufferTextureMultiviewOVR(%u, %u, %" PRIu32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", target, attachment, texture, level, baseViewIndex, numViews);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OVR_multiview);
            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::GlFramebufferTextureMultiviewOVR coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, attachment, toEncoder< uint32_t >(texture, *observer->getScratch()), toEncoder< int32_t >(level, *observer->getScratch()), toEncoder< int32_t >(baseViewIndex, *observer->getScratch()), toEncoder< int32_t >(numViews, *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::glFramebufferTextureOES(CallObserver* observer, uint32_t target, uint32_t attachment, TextureId texture, GLint level) {
    GAPID_DEBUG("glFramebufferTextureOES(%u, %u, %" PRIu32 ", %" PRId32 ")", target, attachment, texture, level);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlFramebufferTextureOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, attachment, toEncoder< uint32_t >(texture, *observer->getScratch()), toEncoder< int32_t >(level, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glGenVertexArraysOES(CallObserver* observer, GLsizei count, VertexArrayId* arrays) {
    GAPID_DEBUG("glGenVertexArraysOES(%" PRId32 ", %p)", count, arrays);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_vertex_array_object);
            call();
            subGenVertexArrays(observer, call, count, arrays);
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, 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::GlGenVertexArraysOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::VertexArrayId__P >(arrays, *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);

}

GLint GlesSpy::glGetFragDataIndexEXT(CallObserver* observer, ProgramId program, const char* name) {
    GAPID_DEBUG("glGetFragDataIndexEXT(%" PRIu32 ", %s)", program, name);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_blend_func_extended);
            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::GlGetFragDataIndexEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< const char* >(name, *observer->getScratch()), toEncoder< int32_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;
}

GLuint64 GlesSpy::glGetImageHandleNV(CallObserver* observer, TextureId texture, GLint level, GLboolean layered, GLint layer, uint32_t format) {
    GAPID_DEBUG("glGetImageHandleNV(%" PRIu32 ", %" PRId32 ", %" PRIu8 ", %" PRId32 ", %u)", texture, level, layered, layer, format);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlGetImageHandleNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(texture, *observer->getScratch()), toEncoder< int32_t >(level, *observer->getScratch()), toEncoder< uint8_t >(layered, *observer->getScratch()), toEncoder< int32_t >(layer, *observer->getScratch()), format, toEncoder< uint64_t >(result, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

void GlesSpy::glGetInternalformatSampleivNV(CallObserver* observer, uint32_t target, uint32_t internalformat, GLsizei samples, uint32_t pname, GLsizei bufSize, GLint* params) {
    GAPID_DEBUG("glGetInternalformatSampleivNV(%u, %u, %" PRId32 ", %u, %" PRId32 ", %p)", target, internalformat, samples, pname, bufSize, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlGetInternalformatSampleivNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, internalformat, toEncoder< int32_t >(samples, *observer->getScratch()), 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);

}

void GlesSpy::glGetPerfQueryDataINTEL(CallObserver* observer, GLuint queryHandle, GLuint flag, GLsizei dataSize, GLvoid* data, GLuint* bytesWritten) {
    GAPID_DEBUG("glGetPerfQueryDataINTEL(%" PRIu32 ", %" PRIu32 ", %" PRId32 ", %p, %p)", queryHandle, flag, dataSize, data, bytesWritten);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlGetPerfQueryDataINTEL coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(queryHandle, *observer->getScratch()), toEncoder< uint32_t >(flag, *observer->getScratch()), toEncoder< int32_t >(dataSize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLvoid__P >(data, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__P >(bytesWritten, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glGetPerfQueryInfoINTEL(CallObserver* observer, GLuint queryId, GLuint queryNameLength, GLchar* queryName, GLuint* dataSize, GLuint* noCounters, GLuint* noInstances, GLuint* capsMask) {
    GAPID_DEBUG("glGetPerfQueryInfoINTEL(%" PRIu32 ", %" PRIu32 ", %p, %p, %p, %p, %p)", queryId, queryNameLength, queryName, dataSize, noCounters, noInstances, capsMask);

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

    bool called = false;
    auto call = [this, observer, &called, queryId, queryNameLength, queryName, dataSize, noCounters, noInstances, capsMask] {
        called = true;
        observer->observeReads();
        mImports.glGetPerfQueryInfoINTEL(queryId, queryNameLength, queryName, dataSize, noCounters, noInstances, capsMask);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlGetPerfQueryInfoINTEL coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(queryId, *observer->getScratch()), toEncoder< uint32_t >(queryNameLength, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__P >(queryName, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__P >(dataSize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__P >(noCounters, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__P >(noInstances, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__P >(capsMask, *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::glGetProgramPipelineInfoLogEXT(CallObserver* observer, PipelineId pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
    GAPID_DEBUG("glGetProgramPipelineInfoLogEXT(%" PRIu32 ", %" PRId32 ", %p, %p)", pipeline, bufSize, length, infoLog);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlGetProgramPipelineInfoLogEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(pipeline, *observer->getScratch()), toEncoder< int32_t >(bufSize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLsizei__P >(length, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__P >(infoLog, *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::glGetQueryObjectivEXT(CallObserver* observer, QueryId query, uint32_t parameter, GLint* value) {
    GAPID_DEBUG("glGetQueryObjectivEXT(%" PRIu32 ", %u, %p)", query, parameter, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlGetQueryObjectivEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(query, *observer->getScratch()), parameter, 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::glGetSamplerParameterIuivOES(CallObserver* observer, SamplerId sampler, uint32_t pname, GLuint* params) {
    GAPID_DEBUG("glGetSamplerParameterIuivOES(%" PRIu32 ", %u, %p)", sampler, pname, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlGetSamplerParameterIuivOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(sampler, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLuint__P >(params, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

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

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

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

    mEncoder->Variant(&coder);


    return result;
}

GLboolean GlesSpy::glIsQueryEXT(CallObserver* observer, QueryId query) {
    GAPID_DEBUG("glIsQueryEXT(%" PRIu32 ")", query);

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

    GLboolean result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, query] {
        called = true;
        observer->observeReads();
        result = mImports.glIsQueryEXT(query);
        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);
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            call();
            if (UNLIKELY(shouldComputeExpectedReturn())) {
                setExpectedReturn<GLboolean>((GLboolean)(checkNotNull(l_ctx).mInstances.mQueries.count(query) > 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::GlIsQueryEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(query, *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::glMultiDrawElementsIndirectEXT(CallObserver* observer, uint32_t mode, uint32_t type, void* indirect, GLsizei drawcount, GLsizei stride) {
    GAPID_DEBUG("glMultiDrawElementsIndirectEXT(%u, %u, %p, %" PRId32 ", %" PRId32 ")", mode, type, indirect, drawcount, stride);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_multi_draw_indirect);
            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::GlMultiDrawElementsIndirectEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), mode, type, toEncoder< gapic::coder::gles::Void__CP >(indirect, *observer->getScratch()), toEncoder< int32_t >(drawcount, *observer->getScratch()), toEncoder< int32_t >(stride, *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::glPathStencilFuncNV(CallObserver* observer, uint32_t func, GLint ref, GLuint mask) {
    GAPID_DEBUG("glPathStencilFuncNV(%u, %" PRId32 ", %" PRIu32 ")", func, ref, mask);

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

    bool called = false;
    auto call = [this, observer, &called, func, ref, mask] {
        called = true;
        observer->observeReads();
        mImports.glPathStencilFuncNV(func, ref, mask);
        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::GlPathStencilFuncNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), func, toEncoder< int32_t >(ref, *observer->getScratch()), toEncoder< uint32_t >(mask, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

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

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniform1iv(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::GlProgramUniform1ivEXT 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::glProgramUniform2fEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLfloat v0, GLfloat v1) {
    GAPID_DEBUG("glProgramUniform2fEXT(%" PRIu32 ", %" PRId32 ", %f, %f)", program, location, v0, v1);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniform2f(observer, call, program, location, v0, v1);
            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::GlProgramUniform2fEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< float >(v0, *observer->getScratch()), toEncoder< float >(v1, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

    if (counter_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::glProgramUniform2uiEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLuint v0, GLuint v1) {
    GAPID_DEBUG("glProgramUniform2uiEXT(%" PRIu32 ", %" PRId32 ", %" PRIu32 ", %" PRIu32 ")", program, location, v0, v1);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniform2ui(observer, call, program, location, v0, v1);
            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::GlProgramUniform2uiEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< uint32_t >(v0, *observer->getScratch()), toEncoder< uint32_t >(v1, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

    if (counter_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::glProgramUniform3iEXT(CallObserver* observer, ProgramId program, UniformLocation location, GLint v0, GLint v1, GLint v2) {
    GAPID_DEBUG("glProgramUniform3iEXT(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", program, location, v0, v1, v2);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_separate_shader_objects);
            subProgramUniform4uiv(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::GlProgramUniform4uivEXT 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::glRasterSamplesEXT(CallObserver* observer, GLuint samples, GLboolean fixedsamplelocations) {
    GAPID_DEBUG("glRasterSamplesEXT(%" PRIu32 ", %" PRIu8 ")", samples, fixedsamplelocations);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension3(observer, call, ExtensionId::GL_EXT_raster_multisample, ExtensionId::GL_EXT_texture_filter_minmax, ExtensionId::GL_NV_framebuffer_mixed_samples);
            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::GlRasterSamplesEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(samples, *observer->getScratch()), toEncoder< uint8_t >(fixedsamplelocations, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

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

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_sample_locations);
            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::GlResolveDepthValuesNV 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::glScissorArrayvNV(CallObserver* observer, GLuint first, GLsizei count, GLint* v) {
    GAPID_DEBUG("glScissorArrayvNV(%" PRIu32 ", %" PRId32 ", %p)", first, count, v);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_viewport_array);
            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::GlScissorArrayvNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(first, *observer->getScratch()), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::GLint__CP >(v, *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::glScissorIndexedNV(CallObserver* observer, GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height) {
    GAPID_DEBUG("glScissorIndexedNV(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", index, left, bottom, width, height);

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

    bool called = false;
    auto call = [this, observer, &called, index, left, bottom, width, height] {
        called = true;
        observer->observeReads();
        mImports.glScissorIndexedNV(index, left, bottom, width, height);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_viewport_array);
            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::GlScissorIndexedNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< int32_t >(left, *observer->getScratch()), toEncoder< int32_t >(bottom, *observer->getScratch()), 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::glStartTilingQCOM(CallObserver* observer, GLuint x, GLuint y, GLuint width, GLuint height, uint32_t preserveMask) {
    GAPID_DEBUG("glStartTilingQCOM(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %u)", x, y, width, height, preserveMask);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_QCOM_tiled_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::GlStartTilingQCOM coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(x, *observer->getScratch()), toEncoder< uint32_t >(y, *observer->getScratch()), toEncoder< uint32_t >(width, *observer->getScratch()), toEncoder< uint32_t >(height, *observer->getScratch()), preserveMask);
    coder.mextras.append(observer->getExtras());

    if (counter_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::glStencilFillPathInstancedNV(CallObserver* observer, GLsizei numPaths, uint32_t pathNameType, void* paths, GLuint pathBase, uint32_t fillMode, GLuint mask, uint32_t transformType, GLfloat* transformValues) {
    GAPID_DEBUG("glStencilFillPathInstancedNV(%" PRId32 ", %u, %p, %" PRIu32 ", %u, %" PRIu32 ", %u, %p)", numPaths, pathNameType, paths, pathBase, fillMode, mask, transformType, transformValues);

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

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

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

    bool called = false;
    auto call = [this, observer, &called, path, reference, mask] {
        called = true;
        observer->observeReads();
        mImports.glStencilStrokePathNV(path, reference, mask);
        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::GlStencilStrokePathNV 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()));
    coder.mextras.append(observer->getExtras());

    if (counter_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::glSubpixelPrecisionBiasNV(CallObserver* observer, GLuint xbits, GLuint ybits) {
    GAPID_DEBUG("glSubpixelPrecisionBiasNV(%" PRIu32 ", %" PRIu32 ")", xbits, ybits);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_conservative_raster);
            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::GlSubpixelPrecisionBiasNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(xbits, *observer->getScratch()), toEncoder< uint32_t >(ybits, *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::glTexStorage2DEXT(CallObserver* observer, uint32_t target, GLsizei levels, uint32_t internalformat, GLsizei width, GLsizei height) {
    GAPID_DEBUG("glTexStorage2DEXT(%u, %" PRId32 ", %u, %" PRId32 ", %" PRId32 ")", target, levels, internalformat, width, height);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlTexStorage2DEXT 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()));
    coder.mextras.append(observer->getExtras());

    if (counter_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::glVertexAttribDivisorANGLE(CallObserver* observer, AttributeLocation index, GLuint divisor) {
    GAPID_DEBUG("glVertexAttribDivisorANGLE(%" PRIu32 ", %" PRIu32 ")", index, divisor);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_ANGLE_instanced_arrays);
            subVertexAttribDivisor(observer, call, index, divisor);
            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::GlVertexAttribDivisorANGLE coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< uint32_t >(divisor, *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::glVertexAttribDivisorEXT(CallObserver* observer, AttributeLocation index, GLuint divisor) {
    GAPID_DEBUG("glVertexAttribDivisorEXT(%" PRIu32 ", %" PRIu32 ")", index, divisor);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_instanced_arrays);
            subVertexAttribDivisor(observer, call, index, divisor);
            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::GlVertexAttribDivisorEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< uint32_t >(divisor, *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::glViewportArrayvNV(CallObserver* observer, GLuint first, GLsizei count, GLfloat* v) {
    GAPID_DEBUG("glViewportArrayvNV(%" PRIu32 ", %" PRId32 ", %p)", first, count, v);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_viewport_array);
            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::GlViewportArrayvNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(first, *observer->getScratch()), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__CP >(v, *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::glViewportIndexedfvNV(CallObserver* observer, GLuint index, GLfloat* v) {
    GAPID_DEBUG("glViewportIndexedfvNV(%" PRIu32 ", %p)", index, v);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_NV_viewport_array);
            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::GlViewportIndexedfvNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< gapic::coder::gles::GLfloat__CP >(v, *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::glFramebufferPixelLocalStorageSizeEXT(CallObserver* observer, GLuint target, GLsizei size) {
    GAPID_DEBUG("glFramebufferPixelLocalStorageSizeEXT(%" PRIu32 ", %" PRId32 ")", target, size);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_EXT_shader_pixel_local_storage2);
            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::GlFramebufferPixelLocalStorageSizeEXT coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(target, *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::glProgramUniform1ui64NV(CallObserver* observer, GLuint program, GLint location, GLuint64EXT x) {
    GAPID_DEBUG("glProgramUniform1ui64NV(%" PRIu32 ", %" PRId32 ", %" PRIu64 ")", program, location, x);

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

    bool called = false;
    auto call = [this, observer, &called, program, location, x] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniform1ui64NV(program, location, x);
        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::GlProgramUniform1ui64NV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< uint64_t >(x, *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::glProgramUniform2i64vNV(CallObserver* observer, GLuint program, GLint location, GLsizei count, GLint64EXT* value) {
    GAPID_DEBUG("glProgramUniform2i64vNV(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, value);

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

    bool called = false;
    auto call = [this, observer, &called, program, location, count, value] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniform2i64vNV(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::GlProgramUniform2i64vNV 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::glProgramUniformHandleui64vIMG(CallObserver* observer, GLuint program, GLint location, GLsizei count, GLuint64* values) {
    GAPID_DEBUG("glProgramUniformHandleui64vIMG(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, values);

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

    bool called = false;
    auto call = [this, observer, &called, program, location, count, values] {
        called = true;
        observer->observeReads();
        mImports.glProgramUniformHandleui64vIMG(program, location, count, values);
        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::GlProgramUniformHandleui64vIMG 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::GLuint64__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::glUniform1ui64vNV(CallObserver* observer, GLint location, GLsizei count, GLuint64EXT* value) {
    GAPID_DEBUG("glUniform1ui64vNV(%" PRId32 ", %" PRId32 ", %p)", location, count, value);

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

    bool called = false;
    auto call = [this, observer, &called, location, count, value] {
        called = true;
        observer->observeReads();
        mImports.glUniform1ui64vNV(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::GlUniform1ui64vNV coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), 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::glUniform2i64NV(CallObserver* observer, GLint location, GLint64EXT x, GLint64EXT y) {
    GAPID_DEBUG("glUniform2i64NV(%" PRId32 ", %" PRId64 ", %" PRId64 ")", location, x, y);

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

    bool called = false;
    auto call = [this, observer, &called, location, x, y] {
        called = true;
        observer->observeReads();
        mImports.glUniform2i64NV(location, x, y);
        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::GlUniform2i64NV 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()));
    coder.mextras.append(observer->getExtras());

    if (counter_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::glBlendEquationSeparatei(CallObserver* observer, DrawBufferIndex buf, uint32_t modeRGB, uint32_t modeAlpha) {
    GAPID_DEBUG("glBlendEquationSeparatei(%" PRIu32 ", %u, %u)", buf, modeRGB, modeAlpha);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            subBlendEquationSeparatei(observer, call, buf, modeRGB, modeAlpha);
            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::GlBlendEquationSeparatei coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(buf, *observer->getScratch()), 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::glBlendFuncSeparatei(CallObserver* observer, DrawBufferIndex buf, uint32_t srcRGB, uint32_t dstRGB, uint32_t srcAlpha, uint32_t dstAlpha) {
    GAPID_DEBUG("glBlendFuncSeparatei(%" PRIu32 ", %u, %u, %u, %u)", buf, srcRGB, dstRGB, srcAlpha, dstAlpha);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            subBlendFuncSeparatei(observer, call, buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
            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::GlBlendFuncSeparatei coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(buf, *observer->getScratch()), 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::glDepthFunc(CallObserver* observer, uint32_t function) {
    GAPID_DEBUG("glDepthFunc(%u)", function);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            switch (function) {
                case GLenum::GL_ALWAYS: // fall-through...
                case GLenum::GL_EQUAL: // fall-through...
                case GLenum::GL_GEQUAL: // fall-through...
                case GLenum::GL_GREATER: // fall-through...
                case GLenum::GL_LEQUAL: // fall-through...
                case GLenum::GL_LESS: // fall-through...
                case GLenum::GL_NEVER: // fall-through...
                case GLenum::GL_NOTEQUAL: {
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, function);
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            checkNotNull(l_ctx).mFragmentOperations.mDepth.mFunc = function;
            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::GlDepthFunc coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), function);
    coder.mextras.append(observer->getExtras());

    if (counter_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::glStencilFuncSeparate(CallObserver* observer, uint32_t face, uint32_t function, GLint reference_value, GLuint mask) {
    GAPID_DEBUG("glStencilFuncSeparate(%u, %u, %" PRId32 ", %" PRIu32 ")", face, function, reference_value, mask);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlStencilFuncSeparate coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), face, function, toEncoder< int32_t >(reference_value, *observer->getScratch()), toEncoder< uint32_t >(mask, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glFramebufferTextureLayer(CallObserver* observer, uint32_t target, uint32_t attachment, TextureId texture, GLint level, GLint layer) {
    GAPID_DEBUG("glFramebufferTextureLayer(%u, %u, %" PRIu32 ", %" PRId32 ", %" PRId32 ")", target, attachment, texture, level, layer);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            switch (attachment) {
                case GLenum::GL_COLOR_ATTACHMENT0: // fall-through...
                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_ATTACHMENT: // fall-through...
                case GLenum::GL_DEPTH_STENCIL_ATTACHMENT: // fall-through...
                case GLenum::GL_STENCIL_ATTACHMENT: {
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, attachment);
                }
            }
            FramebufferAttachment l_attachment_info = FramebufferAttachment(GLenum::GL_NONE, (GLuint)(0UL), (GLint)(0L), GLenum::GL_NONE, (GLint)(0L), GLbooleanLabels::GL_FALSE);
            if ((texture) != ((TextureId)(0UL))) {
                l_attachment_info.mObjectType = GLenum::GL_TEXTURE;
                l_attachment_info.mObjectName = (GLuint)(texture);
                l_attachment_info.mTextureLevel = level;
                l_attachment_info.mTextureLayer = layer;
            }
            subSetFramebufferAttachment(observer, call, target, attachment, l_attachment_info);
            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::GlFramebufferTextureLayer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, attachment, toEncoder< uint32_t >(texture, *observer->getScratch()), toEncoder< int32_t >(level, *observer->getScratch()), toEncoder< int32_t >(layer, *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::glRenderbufferStorage(CallObserver* observer, uint32_t target, uint32_t internalformat, GLsizei width, GLsizei height) {
    GAPID_DEBUG("glRenderbufferStorage(%u, %u, %" PRId32 ", %" PRId32 ")", target, internalformat, width, height);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            subRenderbufferStorageMultisample(observer, call, target, (GLsizei)(0L), internalformat, width, height);
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlRenderbufferStorage coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, 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::glDisablei(CallObserver* observer, uint32_t capability, GLuint index) {
    GAPID_DEBUG("glDisablei(%u, %" PRIu32 ")", capability, index);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlDisablei coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), capability, toEncoder< uint32_t >(index, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

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

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            subSetCapability(observer, call, capability, false, (GLuint)(0UL), GLbooleanLabels::GL_TRUE);
            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::GlEnable coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), capability);
    coder.mextras.append(observer->getExtras());

    if (counter_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::glFinish(CallObserver* observer) {
    GAPID_DEBUG("glFinish()");

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (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::GlFinish 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::glBindProgramPipeline(CallObserver* observer, PipelineId pipeline) {
    GAPID_DEBUG("glBindProgramPipeline(%" PRIu32 ")", pipeline);

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

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

}

ProgramId GlesSpy::glCreateShaderProgramv(CallObserver* observer, uint32_t type, GLsizei count, GLchar** strings) {
    GAPID_DEBUG("glCreateShaderProgramv(%u, %" PRId32 ", %p)", type, count, strings);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            switch (type) {
                case GLenum::GL_COMPUTE_SHADER: // fall-through...
                case GLenum::GL_FRAGMENT_SHADER: // fall-through...
                case GLenum::GL_VERTEX_SHADER: {
                    break;
                }
                case GLenum::GL_GEOMETRY_SHADER: // fall-through...
                case GLenum::GL_TESS_CONTROL_SHADER: // fall-through...
                case GLenum::GL_TESS_EVALUATION_SHADER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, type);
                }
            }
            Slice<GLchar*> l_sources = slice(strings, (uint64_t)((GLsizei)(0L)), (uint64_t)(count));
            for (GLsizei l_i = (GLsizei)(0L); l_i < count; ++l_i) {
                (void)observer->string((char*)(observer->read(l_sources, (uint64_t)(l_i))));
            }
            call();
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlCreateShaderProgramv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), type, toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__CP__CP >(strings, *observer->getScratch()), toEncoder< uint32_t >(result, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);


    return result;
}

void GlesSpy::glDispatchCompute(CallObserver* observer, GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) {
    GAPID_DEBUG("glDispatchCompute(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", num_groups_x, num_groups_y, num_groups_z);

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

    bool called = false;
    auto call = [this, observer, &called, num_groups_x, num_groups_y, num_groups_z] {
        called = true;
        observer->observeReads();
        mImports.glDispatchCompute(num_groups_x, num_groups_y, num_groups_z);
        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::GlDispatchCompute coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(num_groups_x, *observer->getScratch()), toEncoder< uint32_t >(num_groups_y, *observer->getScratch()), toEncoder< uint32_t >(num_groups_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);

}

GLint GlesSpy::glGetAttribLocation(CallObserver* observer, ProgramId program, const char* name) {
    GAPID_DEBUG("glGetAttribLocation(%" PRIu32 ", %s)", program, name);

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

    GLint result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, program, name] {
        called = true;
        observer->observeReads();
        result = mImports.glGetAttribLocation(program, name);
        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);
            subCheckProgram(observer, call, l_ctx, program);
            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::GlGetAttribLocation coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< const char* >(name, *observer->getScratch()), toEncoder< int32_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;
}

GLint GlesSpy::glGetFragDataLocation(CallObserver* observer, ProgramId program, const char* name) {
    GAPID_DEBUG("glGetFragDataLocation(%" PRIu32 ", %s)", program, name);

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

    GLint result = 0;
    bool called = false;
    auto call = [this, observer, &called, &result, program, name] {
        called = true;
        observer->observeReads();
        result = mImports.glGetFragDataLocation(program, name);
        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);
            subCheckProgram(observer, call, l_ctx, program);
            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::GlGetFragDataLocation coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< const char* >(name, *observer->getScratch()), toEncoder< int32_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::glGetProgramResourceName(CallObserver* observer, ProgramId program, uint32_t programInterface, GLuint index, GLsizei bufSize, GLsizei* length, GLchar* name) {
    GAPID_DEBUG("glGetProgramResourceName(%" PRIu32 ", %u, %" PRIu32 ", %" PRId32 ", %p, %p)", program, programInterface, index, bufSize, length, name);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            switch (programInterface) {
                case GLenum::GL_BUFFER_VARIABLE: // fall-through...
                case GLenum::GL_PROGRAM_INPUT: // fall-through...
                case GLenum::GL_PROGRAM_OUTPUT: // fall-through...
                case GLenum::GL_SHADER_STORAGE_BLOCK: // fall-through...
                case GLenum::GL_TRANSFORM_FEEDBACK_VARYING: // fall-through...
                case GLenum::GL_UNIFORM: // fall-through...
                case GLenum::GL_UNIFORM_BLOCK: {
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, programInterface);
                }
            }
            call();
            subWriteString(observer, call, bufSize, length, name);
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, 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::GlGetProgramResourceName coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), programInterface, toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< int32_t >(bufSize, *observer->getScratch()), toEncoder< gapic::coder::gles::GLsizei__P >(length, *observer->getScratch()), toEncoder< gapic::coder::gles::GLchar__P >(name, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glGetProgramiv(CallObserver* observer, ProgramId program, uint32_t parameter, GLint* value) {
    GAPID_DEBUG("glGetProgramiv(%" PRIu32 ", %u, %p)", program, parameter, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            switch (parameter) {
                case GLenum::GL_ACTIVE_ATTRIBUTES: // fall-through...
                case GLenum::GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: // fall-through...
                case GLenum::GL_ACTIVE_UNIFORMS: // fall-through...
                case GLenum::GL_ACTIVE_UNIFORM_MAX_LENGTH: // fall-through...
                case GLenum::GL_ATTACHED_SHADERS: // fall-through...
                case GLenum::GL_DELETE_STATUS: // fall-through...
                case GLenum::GL_INFO_LOG_LENGTH: // fall-through...
                case GLenum::GL_LINK_STATUS: // fall-through...
                case GLenum::GL_VALIDATE_STATUS: {
                    break;
                }
                case GLenum::GL_ACTIVE_UNIFORM_BLOCKS: // fall-through...
                case GLenum::GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: // fall-through...
                case GLenum::GL_PROGRAM_BINARY_RETRIEVABLE_HINT: // fall-through...
                case GLenum::GL_TRANSFORM_FEEDBACK_BUFFER_MODE: // fall-through...
                case GLenum::GL_TRANSFORM_FEEDBACK_VARYINGS: // fall-through...
                case GLenum::GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    break;
                }
                case GLenum::GL_PROGRAM_BINARY_LENGTH: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    break;
                }
                case GLenum::GL_ACTIVE_ATOMIC_COUNTER_BUFFERS: // fall-through...
                case GLenum::GL_COMPUTE_WORK_GROUP_SIZE: // fall-through...
                case GLenum::GL_PROGRAM_SEPARABLE: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
                    break;
                }
                case GLenum::GL_GEOMETRY_INPUT_TYPE: // fall-through...
                case GLenum::GL_GEOMETRY_OUTPUT_TYPE: // fall-through...
                case GLenum::GL_GEOMETRY_VERTICES_OUT: // fall-through...
                case GLenum::GL_GEOMETRY_SHADER_INVOCATIONS: // fall-through...
                case GLenum::GL_TESS_CONTROL_OUTPUT_VERTICES: // fall-through...
                case GLenum::GL_TESS_GEN_MODE: // fall-through...
                case GLenum::GL_TESS_GEN_POINT_MODE: // fall-through...
                case GLenum::GL_TESS_GEN_SPACING: // fall-through...
                case GLenum::GL_TESS_GEN_VERTEX_ORDER: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, parameter);
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            subCheckProgram(observer, call, l_ctx, program);
            call();
            observer->write<GLint>(slice(value, 0ULL, 1ULL), 0ULL, slice(value, 0ULL, 1ULL)[0ULL]);
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlGetProgramiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), parameter, 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::glProgramUniform1fv(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLfloat* values) {
    GAPID_DEBUG("glProgramUniform1fv(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, values);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subProgramUniform3uiv(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::GlProgramUniform3uiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(program, *observer->getScratch()), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__CP >(values, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glProgramUniform4iv(CallObserver* observer, ProgramId program, UniformLocation location, GLsizei count, GLint* values) {
    GAPID_DEBUG("glProgramUniform4iv(%" PRIu32 ", %" PRId32 ", %" PRId32 ", %p)", program, location, count, values);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            subProgramUniform4iv(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::GlProgramUniform4iv 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::glUniform1f(CallObserver* observer, UniformLocation location, GLfloat value) {
    GAPID_DEBUG("glUniform1f(%" PRId32 ", %f)", location, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            Slice<GLfloat> l_v = make<GLfloat>(1ULL);
            observer->write<GLfloat>(l_v, 0ULL, value);
            subUniformv_GLfloat__S(observer, call, location, l_v, GLenum::GL_FLOAT);
            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::GlUniform1f coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< float >(value, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glUniform3ui(CallObserver* observer, UniformLocation location, GLuint value0, GLuint value1, GLuint value2) {
    GAPID_DEBUG("glUniform3ui(%" PRId32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", location, value0, value1, value2);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            Slice<Vec3u> l_v = make<Vec3u>(1ULL);
            observer->write<Vec3u>(l_v, 0ULL, {value0, value1, value2});
            subUniformv_Vec3u__S(observer, call, location, l_v, GLenum::GL_UNSIGNED_INT_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::GlUniform3ui coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(location, *observer->getScratch()), toEncoder< uint32_t >(value0, *observer->getScratch()), toEncoder< uint32_t >(value1, *observer->getScratch()), toEncoder< uint32_t >(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::glUniform4i(CallObserver* observer, UniformLocation location, GLint value0, GLint value1, GLint value2, GLint value3) {
    GAPID_DEBUG("glUniform4i(%" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", location, value0, value1, value2, value3);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            Slice<Vec4i> l_v = make<Vec4i>(1ULL);
            observer->write<Vec4i>(l_v, 0ULL, {value0, value1, value2, value3});
            subUniformv_Vec4i__S(observer, call, location, l_v, GLenum::GL_INT_VEC4);
            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::GlUniform4i 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()), toEncoder< int32_t >(value2, *observer->getScratch()), toEncoder< int32_t >(value3, *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::glUniformMatrix4fv(CallObserver* observer, UniformLocation location, GLsizei count, GLboolean transpose, GLfloat* values) {
    GAPID_DEBUG("glUniformMatrix4fv(%" PRId32 ", %" PRId32 ", %" PRIu8 ", %p)", location, count, transpose, values);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            Slice<Mat4f> l_v = slice((Mat4f*)(values), (uint64_t)((GLsizei)(0L)), (uint64_t)(count));
            subUniformMatrixv_Mat4f__S(observer, call, location, transpose, l_v, GLenum::GL_FLOAT_MAT4);
            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::GlUniformMatrix4fv 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::glBindImageTexture(CallObserver* observer, GLuint unit, TextureId texture, GLint level, GLboolean layered, GLint layer, uint32_t access, uint32_t format) {
    GAPID_DEBUG("glBindImageTexture(%" PRIu32 ", %" PRIu32 ", %" PRId32 ", %" PRIu8 ", %" PRId32 ", %u, %u)", unit, texture, level, layered, layer, access, format);

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

    bool called = false;
    auto call = [this, observer, &called, unit, texture, level, layered, layer, access, format] {
        called = true;
        observer->observeReads();
        mImports.glBindImageTexture(unit, texture, level, layered, layer, access, format);
        onPostFence(observer);
    };


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            switch (access) {
                case GLenum::GL_READ_ONLY: // fall-through...
                case GLenum::GL_READ_WRITE: // fall-through...
                case GLenum::GL_WRITE_ONLY: {
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, access);
                }
            }
            switch (format) {
                case GLenum::GL_R32F: // fall-through...
                case GLenum::GL_R32I: // fall-through...
                case GLenum::GL_R32UI: // 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_RGBA8: // fall-through...
                case GLenum::GL_RGBA8I: // fall-through...
                case GLenum::GL_RGBA8UI: // fall-through...
                case GLenum::GL_RGBA8_SNORM: {
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, format);
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            checkNotNull(l_ctx).mImageUnits[unit] = ImageUnit(texture, level, layered, layer, access, format);
            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::GlBindImageTexture coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(unit, *observer->getScratch()), toEncoder< uint32_t >(texture, *observer->getScratch()), toEncoder< int32_t >(level, *observer->getScratch()), toEncoder< uint8_t >(layered, *observer->getScratch()), toEncoder< int32_t >(layer, *observer->getScratch()), access, format);
    coder.mextras.append(observer->getExtras());

    if (counter_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::glCompressedTexSubImage2D(CallObserver* observer, uint32_t target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, uint32_t format, GLsizei image_size, TexturePointer data) {
    GAPID_DEBUG("glCompressedTexSubImage2D(%u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %u, %" PRId32 ", %p)", target, level, xoffset, yoffset, width, height, format, image_size, data);

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

    bool called = false;
    auto call = [this, observer, &called, target, level, xoffset, yoffset, width, height, format, image_size, data] {
        called = true;
        observer->observeReads();
        mImports.glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, 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_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_ETC1_RGB8_OES: {
                    subRequiresExtension(observer, call, ExtensionId::GL_OES_compressed_ETC1_RGB8_texture);
                    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);
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            if (((checkNotNull(l_ctx).mBoundBuffers.mPixelUnpackBuffer) == ((BufferId)(0UL))) && ((data) != (nullptr))) {
                observer->read(slice((uint8_t*)(data), (uint64_t)((GLsizei)(0L)), (uint64_t)(image_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::GlCompressedTexSubImage2D 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 >(width, *observer->getScratch()), toEncoder< int32_t >(height, *observer->getScratch()), format, 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::glCopyTexSubImage2D(CallObserver* observer, uint32_t target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
    GAPID_DEBUG("glCopyTexSubImage2D(%u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", target, level, xoffset, yoffset, x, y, width, height);

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

    bool called = false;
    auto call = [this, observer, &called, target, level, xoffset, yoffset, x, y, width, height] {
        called = true;
        observer->observeReads();
        mImports.glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
        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);
                }
            }
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            subCheckMaxTextureSize(observer, call, l_ctx, target, level, width, height);
            if (((xoffset) < ((GLint)(0L))) || ((yoffset) < ((GLint)(0L)))) {
                subGlErrorInvalidValue(observer, call);
            }
            std::shared_ptr<Texture> l_t = subGetBoundTextureOrErrorInvalidEnum(observer, call, target);
            if (!(checkNotNull(l_t).mTexture2D.count(level) > 0)) {
                subGlErrorInvalidValue(observer, call);
            }
            Image l_l = findOrZero(checkNotNull(l_t).mTexture2D, level);
            if (((((GLsizei)(xoffset)) + (width)) > (l_l.mWidth)) || ((((GLsizei)(yoffset)) + (height)) > (l_l.mHeight))) {
                subGlErrorInvalidValue(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::GlCopyTexSubImage2D 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 >(x, *observer->getScratch()), toEncoder< int32_t >(y, *observer->getScratch()), 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::glGenSamplers(CallObserver* observer, GLsizei count, SamplerId* samplers) {
    GAPID_DEBUG("glGenSamplers(%" PRId32 ", %p)", count, samplers);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            Slice<SamplerId> l_s = slice(samplers, (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) {
                SamplerId l_id = (SamplerId)(slice(samplers, (uint64_t)((GLsizei)(0L)), (uint64_t)(count))[(uint64_t)(l_i)]);
                checkNotNull(l_ctx).mInstances.mSamplers[l_id] = std::shared_ptr<Sampler>(new Sampler(std::move(Vec4f{(GLfloat)(0.f), (GLfloat)(0.f), (GLfloat)(0.f), (GLfloat)(0.f)}), GLenum::GL_NEAREST_MIPMAP_LINEAR, GLenum::GL_LINEAR, GLenum::GL_REPEAT, GLenum::GL_REPEAT, GLenum::GL_REPEAT, (GLfloat)(-1000.f), (GLfloat)(1000.f), GLenum::GL_NONE, GLenum::GL_LEQUAL, "", (GLfloat)(1.f)));
                observer->write<SamplerId>(l_s, (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::GlGenSamplers coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::SamplerId__P >(samplers, *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::glGenerateMipmap(CallObserver* observer, uint32_t target) {
    GAPID_DEBUG("glGenerateMipmap(%u)", target);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(2L), (GLint)(0L));
            switch (target) {
                case GLenum::GL_TEXTURE_2D: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP: {
                    break;
                }
                case GLenum::GL_TEXTURE_2D_ARRAY: // fall-through...
                case GLenum::GL_TEXTURE_3D: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
                    break;
                }
                case GLenum::GL_TEXTURE_CUBE_MAP_ARRAY: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, target);
                }
            }
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlGenerateMipmap coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target);
    coder.mextras.append(observer->getExtras());

    if (counter_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::glGetTexLevelParameteriv(CallObserver* observer, uint32_t target, GLint level, uint32_t pname, GLint* params) {
    GAPID_DEBUG("glGetTexLevelParameteriv(%u, %" PRId32 ", %u, %p)", target, level, pname, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            switch (target) {
                case GLenum::GL_TEXTURE_2D: // fall-through...
                case GLenum::GL_TEXTURE_2D_ARRAY: // fall-through...
                case GLenum::GL_TEXTURE_2D_MULTISAMPLE: // fall-through...
                case GLenum::GL_TEXTURE_3D: // 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;
                }
                case GLenum::GL_TEXTURE_2D_MULTISAMPLE_ARRAY: // fall-through...
                case GLenum::GL_TEXTURE_BUFFER: // fall-through...
                case GLenum::GL_TEXTURE_CUBE_MAP_ARRAY: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, target);
                }
            }
            switch (pname) {
                case GLenum::GL_TEXTURE_ALPHA_SIZE: // fall-through...
                case GLenum::GL_TEXTURE_ALPHA_TYPE: // fall-through...
                case GLenum::GL_TEXTURE_BLUE_SIZE: // fall-through...
                case GLenum::GL_TEXTURE_BLUE_TYPE: // fall-through...
                case GLenum::GL_TEXTURE_COMPRESSED: // fall-through...
                case GLenum::GL_TEXTURE_DEPTH: // fall-through...
                case GLenum::GL_TEXTURE_DEPTH_SIZE: // fall-through...
                case GLenum::GL_TEXTURE_DEPTH_TYPE: // fall-through...
                case GLenum::GL_TEXTURE_FIXED_SAMPLE_LOCATIONS: // fall-through...
                case GLenum::GL_TEXTURE_GREEN_SIZE: // fall-through...
                case GLenum::GL_TEXTURE_GREEN_TYPE: // fall-through...
                case GLenum::GL_TEXTURE_HEIGHT: // fall-through...
                case GLenum::GL_TEXTURE_INTERNAL_FORMAT: // fall-through...
                case GLenum::GL_TEXTURE_RED_SIZE: // fall-through...
                case GLenum::GL_TEXTURE_RED_TYPE: // fall-through...
                case GLenum::GL_TEXTURE_SAMPLES: // fall-through...
                case GLenum::GL_TEXTURE_SHARED_SIZE: // fall-through...
                case GLenum::GL_TEXTURE_STENCIL_SIZE: // fall-through...
                case GLenum::GL_TEXTURE_WIDTH: {
                    break;
                }
                case GLenum::GL_TEXTURE_BUFFER_DATA_STORE_BINDING: // fall-through...
                case GLenum::GL_TEXTURE_BUFFER_OFFSET: // fall-through...
                case GLenum::GL_TEXTURE_BUFFER_SIZE: {
                    subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
                    break;
                }
                default: {
                    subGlErrorInvalidEnum(observer, call, pname);
                }
            }
            call();
            observer->write<GLint>(slice(params, 0ULL, 1ULL), 0ULL, slice(params, 0ULL, 1ULL)[0ULL]);
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlGetTexLevelParameteriv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(level, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLint__P >(params, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glGetTexParameteriv(CallObserver* observer, uint32_t target, uint32_t parameter, GLint* values) {
    GAPID_DEBUG("glGetTexParameteriv(%u, %u, %p)", target, parameter, values);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            call();
            subGetTexParameter_GLint(observer, call, target, parameter, 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::GlGetTexParameteriv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, parameter, 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::glSamplerParameterfv(CallObserver* observer, SamplerId sampler, uint32_t pname, GLfloat* param) {
    GAPID_DEBUG("glSamplerParameterfv(%" PRIu32 ", %u, %p)", sampler, pname, param);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            subSamplerParameterv_GLfloat__CP(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::GlSamplerParameterfv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(sampler, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLfloat__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::glTexBuffer(CallObserver* observer, uint32_t target, uint32_t internalformat, BufferId buffer) {
    GAPID_DEBUG("glTexBuffer(%u, %u, %" PRIu32 ")", target, internalformat, buffer);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(2L));
            subTexBuffer(observer, call, target, internalformat, 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::GlTexBuffer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, internalformat, 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::glTexParameteri(CallObserver* observer, uint32_t target, uint32_t parameter, GLint value) {
    GAPID_DEBUG("glTexParameteri(%u, %u, %" PRId32 ")", target, parameter, value);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(1L), (GLint)(0L));
            if ((parameter) == (GLenum::GL_TEXTURE_BORDER_COLOR)) {
                subGlErrorInvalidEnum(observer, call, parameter);
            }
            Vec1i l_params = {value};
            subTexParameterv_Vec1i(observer, call, target, parameter, l_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::GlTexParameteri coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, parameter, 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::glBindVertexBuffer(CallObserver* observer, VertexBufferBindingIndex binding_index, BufferId buffer, GLintptr offset, GLsizei stride) {
    GAPID_DEBUG("glBindVertexBuffer(%" PRIu32 ", %" PRIu32 ", %" PRId32 ", %" PRId32 ")", binding_index, buffer, offset, stride);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            if ((checkNotNull(l_ctx).mBoundVertexArray) == ((VertexArrayId)(0UL))) {
                subGlErrorInvalidOperation(observer, call);
            }
            subBindVertexBuffer(observer, call, l_ctx, binding_index, buffer, offset, stride);
            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::GlBindVertexBuffer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(binding_index, *observer->getScratch()), toEncoder< uint32_t >(buffer, *observer->getScratch()), toEncoder< int32_t >(offset, *observer->getScratch()), toEncoder< int32_t >(stride, *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::glDeleteVertexArrays(CallObserver* observer, GLsizei count, VertexArrayId* arrays) {
    GAPID_DEBUG("glDeleteVertexArrays(%" PRId32 ", %p)", count, arrays);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlDeleteVertexArrays coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(count, *observer->getScratch()), toEncoder< gapic::coder::gles::VertexArrayId__CP >(arrays, *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::glDisableVertexAttribArray(CallObserver* observer, AttributeLocation location) {
    GAPID_DEBUG("glDisableVertexAttribArray(%" PRIu32 ")", location);

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

    bool called = false;
    auto call = [this, observer, &called, location] {
        called = true;
        observer->observeReads();
        mImports.glDisableVertexAttribArray(location);
        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 ((location) >= ((AttributeLocation)(checkNotNull(l_ctx).mConstants.mMaxVertexAttribs))) {
                subGlErrorInvalidValue(observer, call);
            }
            std::shared_ptr<VertexArray> l_vao = findOrZero(checkNotNull(l_ctx).mInstances.mVertexArrays, checkNotNull(l_ctx).mBoundVertexArray);
            checkNotNull(findOrZero(checkNotNull(l_vao).mVertexAttributeArrays, location)).mEnabled = GLbooleanLabels::GL_FALSE;
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlDisableVertexAttribArray coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(location, *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::glGetVertexAttribIuiv(CallObserver* observer, AttributeLocation index, uint32_t pname, GLuint* params) {
    GAPID_DEBUG("glGetVertexAttribIuiv(%" PRIu32 ", %u, %p)", index, pname, params);

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

    bool called = false;
    auto call = [this, observer, &called, index, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glGetVertexAttribIuiv(index, pname, params);
        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);
            if ((index) >= ((AttributeLocation)(checkNotNull(l_ctx).mConstants.mMaxVertexAttribs))) {
                subGlErrorInvalidValue(observer, call);
            }
            call();
            if ((pname) == (GLenum::GL_CURRENT_VERTEX_ATTRIB)) {
                observer->write(slice(params, 0ULL, 4ULL));
            } else {
                uint64_t l__res_0 = subGetVertexAttrib(observer, call, l_ctx, index, pname);
                observer->write<GLuint>(slice(params, 0ULL, 1ULL), 0ULL, (GLuint)(l__res_0));
            }
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlGetVertexAttribIuiv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), pname, toEncoder< gapic::coder::gles::GLuint__P >(params, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

GLboolean GlesSpy::glIsVertexArray(CallObserver* observer, VertexArrayId array) {
    GAPID_DEBUG("glIsVertexArray(%" PRIu32 ")", array);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(0L));
            GLboolean l__res_0 = subIsVertexArray(observer, call, array);
            call();
            if (UNLIKELY(shouldComputeExpectedReturn())) {
                setExpectedReturn<GLboolean>(l__res_0);
            }
            break;
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlIsVertexArray coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(array, *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::glVertexAttrib3f(CallObserver* observer, AttributeLocation location, GLfloat value0, GLfloat value1, GLfloat value2) {
    GAPID_DEBUG("glVertexAttrib3f(%" PRIu32 ", %f, %f, %f)", location, value0, value1, value2);

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

    bool called = false;
    auto call = [this, observer, &called, location, value0, value1, value2] {
        called = true;
        observer->observeReads();
        mImports.glVertexAttrib3f(location, value0, value1, value2);
        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, value1, value2, (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::GlVertexAttrib3f coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_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::glVertexAttribBinding(CallObserver* observer, AttributeLocation index, VertexBufferBindingIndex binding_index) {
    GAPID_DEBUG("glVertexAttribBinding(%" PRIu32 ", %" PRIu32 ")", index, binding_index);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            if ((checkNotNull(l_ctx).mBoundVertexArray) == ((VertexArrayId)(0UL))) {
                subGlErrorInvalidOperation(observer, call);
            }
            subVertexAttribBinding(observer, call, l_ctx, index, binding_index);
            call();
        } while(false);
    } catch (gapii::AbortException& e) {
        if (!called) {
            call(); // abort() was called before the fence.
        }
        handleAbort(observer, e);
    }
    uint64_t counter_at_end = mCommandStartEndCounter++;
    gapic::coder::atom::CommandCounter counter_value_encodable(counter_at_begin, counter_at_end);

    observer->observeWrites();

    gapic::coder::gles::GlVertexAttribBinding coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(index, *observer->getScratch()), toEncoder< uint32_t >(binding_index, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glVertexBindingDivisor(CallObserver* observer, VertexBufferBindingIndex binding_index, GLuint divisor) {
    GAPID_DEBUG("glVertexBindingDivisor(%" PRIu32 ", %" PRIu32 ")", binding_index, divisor);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subMinRequiredVersion(observer, call, (GLint)(3L), (GLint)(1L));
            std::shared_ptr<Context> l_ctx = subGetContext(observer, call);
            if ((binding_index) >= ((VertexBufferBindingIndex)(checkNotNull(l_ctx).mConstants.mMaxVertexAttribBindings))) {
                subGlErrorInvalidValue(observer, call);
            }
            if ((checkNotNull(l_ctx).mBoundVertexArray) == ((VertexArrayId)(0UL))) {
                subGlErrorInvalidOperation(observer, call);
            }
            std::shared_ptr<VertexArray> l_vao = findOrZero(checkNotNull(l_ctx).mInstances.mVertexArrays, checkNotNull(l_ctx).mBoundVertexArray);
            checkNotNull(findOrZero(checkNotNull(l_vao).mVertexBufferBindings, binding_index)).mDivisor = divisor;
            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::GlVertexBindingDivisor coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(binding_index, *observer->getScratch()), toEncoder< uint32_t >(divisor, *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::glXCreateContext(CallObserver* observer, void* dpy, void* vis, GLXContext shareList, bool direct) {
    GAPID_DEBUG("glXCreateContext(%p, %p, %p, %d)", dpy, vis, shareList, direct);

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

    GLXContext result = nullptr;
    bool called = false;
    auto call = [this, observer, &called, &result, dpy, vis, shareList, direct] {
        called = true;
        observer->observeReads();
        result = mImports.glXCreateContext(dpy, vis, shareList, 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::GlXCreateContext coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::Void__P >(dpy, *observer->getScratch()), toEncoder< gapic::coder::gles::Void__P >(vis, *observer->getScratch()), toEncoder< gapic::coder::gles::GLXContext >(shareList, *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;
}

void GlesSpy::glTexStorage1D(CallObserver* observer, uint32_t target, GLsizei levels, uint32_t internalformat, GLsizei width) {
    GAPID_DEBUG("glTexStorage1D(%u, %" PRId32 ", %u, %" PRId32 ")", target, levels, internalformat, width);

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

    bool called = false;
    auto call = [this, observer, &called, target, levels, internalformat, width] {
        called = true;
        observer->observeReads();
        mImports.glTexStorage1D(target, levels, internalformat, width);
        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::GlTexStorage1D coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, toEncoder< int32_t >(levels, *observer->getScratch()), internalformat, toEncoder< int32_t >(width, *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::glClipPlanefOES(CallObserver* observer, uint32_t plane, GLfloat* equation) {
    GAPID_DEBUG("glClipPlanefOES(%u, %p)", plane, equation);

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

    bool called = false;
    auto call = [this, observer, &called, plane, equation] {
        called = true;
        observer->observeReads();
        mImports.glClipPlanefOES(plane, equation);
        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::GlClipPlanefOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), plane, toEncoder< gapic::coder::gles::GLfloat__CP >(equation, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glClipPlanexIMG(CallObserver* observer, uint32_t p, GLfixed* eqn) {
    GAPID_DEBUG("glClipPlanexIMG(%u, %p)", p, eqn);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlClipPlanexIMG coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), p, toEncoder< gapic::coder::gles::GLfixed__CP >(eqn, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glDeleteRenderbuffersOES(CallObserver* observer, GLsizei n, GLuint* renderbuffers) {
    GAPID_DEBUG("glDeleteRenderbuffersOES(%" PRId32 ", %p)", n, renderbuffers);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_framebuffer_object);
            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::GlDeleteRenderbuffersOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(n, *observer->getScratch()), toEncoder< gapic::coder::gles::GLuint__CP >(renderbuffers, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glDrawTexiOES(CallObserver* observer, GLint x, GLint y, GLint z, GLint width, GLint height) {
    GAPID_DEBUG("glDrawTexiOES(%" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", x, y, z, width, height);

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

    bool called = false;
    auto call = [this, observer, &called, x, y, z, width, height] {
        called = true;
        observer->observeReads();
        mImports.glDrawTexiOES(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::GlDrawTexiOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(x, *observer->getScratch()), toEncoder< int32_t >(y, *observer->getScratch()), toEncoder< int32_t >(z, *observer->getScratch()), 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);
    onPostDrawCall();

}

void GlesSpy::glFogxvOES(CallObserver* observer, uint32_t pname, GLfixed* param) {
    GAPID_DEBUG("glFogxvOES(%u, %p)", pname, param);

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

    bool called = false;
    auto call = [this, observer, &called, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glFogxvOES(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::GlFogxvOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< gapic::coder::gles::GLfixed__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::glFrustumxOES(CallObserver* observer, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) {
    GAPID_DEBUG("glFrustumxOES(%" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", l, r, b, t, n, f);

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

    bool called = false;
    auto call = [this, observer, &called, l, r, b, t, n, f] {
        called = true;
        observer->observeReads();
        mImports.glFrustumxOES(l, r, b, t, n, f);
        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::GlFrustumxOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(l, *observer->getScratch()), toEncoder< int32_t >(r, *observer->getScratch()), toEncoder< int32_t >(b, *observer->getScratch()), toEncoder< int32_t >(t, *observer->getScratch()), toEncoder< int32_t >(n, *observer->getScratch()), toEncoder< int32_t >(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::glGetLightxvOES(CallObserver* observer, uint32_t light, uint32_t pname, GLfixed* params) {
    GAPID_DEBUG("glGetLightxvOES(%u, %u, %p)", light, pname, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlGetLightxvOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), light, pname, toEncoder< gapic::coder::gles::GLfixed__P >(params, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glGetRenderbufferParameterivOES(CallObserver* observer, uint32_t target, uint32_t pname, GLint* params) {
    GAPID_DEBUG("glGetRenderbufferParameterivOES(%u, %u, %p)", target, pname, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_framebuffer_object);
            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::GlGetRenderbufferParameterivOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, pname, toEncoder< gapic::coder::gles::GLint__P >(params, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glGetTexParameterxvOES(CallObserver* observer, uint32_t target, uint32_t pname, GLfixed* params) {
    GAPID_DEBUG("glGetTexParameterxvOES(%u, %u, %p)", target, pname, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlGetTexParameterxvOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, pname, toEncoder< gapic::coder::gles::GLfixed__P >(params, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

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

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

    try {
        do {
            subRequiresExtension(observer, call, ExtensionId::GL_OES_framebuffer_object);
            subErrorGLES10notSupported(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::GlIsRenderbufferOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< uint32_t >(renderbuffer, *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::glLightModelxv(CallObserver* observer, uint32_t pname, GLfixed* param) {
    GAPID_DEBUG("glLightModelxv(%u, %p)", pname, param);

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

    bool called = false;
    auto call = [this, observer, &called, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glLightModelxv(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::GlLightModelxv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< gapic::coder::gles::GLfixed__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::glLineWidthxOES(CallObserver* observer, GLfixed width) {
    GAPID_DEBUG("glLineWidthxOES(%" PRId32 ")", width);

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

    bool called = false;
    auto call = [this, observer, &called, width] {
        called = true;
        observer->observeReads();
        mImports.glLineWidthxOES(width);
        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::GlLineWidthxOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< int32_t >(width, *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::glLoadMatrixx(CallObserver* observer, GLfixed* m) {
    GAPID_DEBUG("glLoadMatrixx(%p)", m);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlLoadMatrixx coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::GLfixed__CP >(m, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glMaterialxv(CallObserver* observer, uint32_t face, uint32_t pname, GLfixed* param) {
    GAPID_DEBUG("glMaterialxv(%u, %u, %p)", face, pname, param);

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

    bool called = false;
    auto call = [this, observer, &called, face, pname, param] {
        called = true;
        observer->observeReads();
        mImports.glMaterialxv(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::GlMaterialxv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), face, pname, toEncoder< gapic::coder::gles::GLfixed__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::glMultMatrixf(CallObserver* observer, GLfloat* m) {
    GAPID_DEBUG("glMultMatrixf(%p)", m);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlMultMatrixf coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< gapic::coder::gles::GLfloat__CP >(m, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glMultiTexCoord4x(CallObserver* observer, uint32_t texture, GLfixed v0, GLfixed v1, GLfixed v2, GLfixed v3) {
    GAPID_DEBUG("glMultiTexCoord4x(%u, %" PRId32 ", %" PRId32 ", %" PRId32 ", %" PRId32 ")", texture, v0, v1, v2, v3);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlMultiTexCoord4x coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), texture, toEncoder< int32_t >(v0, *observer->getScratch()), toEncoder< int32_t >(v1, *observer->getScratch()), toEncoder< int32_t >(v2, *observer->getScratch()), toEncoder< int32_t >(v3, *observer->getScratch()));
    coder.mextras.append(observer->getExtras());

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

    mEncoder->Variant(&coder);

}

void GlesSpy::glPointParameterxv(CallObserver* observer, uint32_t pname, GLfixed* params) {
    GAPID_DEBUG("glPointParameterxv(%u, %p)", pname, params);

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

    bool called = false;
    auto call = [this, observer, &called, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glPointParameterxv(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::GlPointParameterxv coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), pname, toEncoder< gapic::coder::gles::GLfixed__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::glPointSize(CallObserver* observer, GLfloat size) {
    GAPID_DEBUG("glPointSize(%f)", size);

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

    bool called = false;
    auto call = [this, observer, &called, size] {
        called = true;
        observer->observeReads();
        mImports.glPointSize(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::GlPointSize coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), toEncoder< float >(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::glTexEnviv(CallObserver* observer, uint32_t target, uint32_t pname, GLint* params) {
    GAPID_DEBUG("glTexEnviv(%u, %u, %p)", target, pname, params);

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

    bool called = false;
    auto call = [this, observer, &called, target, pname, params] {
        called = true;
        observer->observeReads();
        mImports.glTexEnviv(target, 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::GlTexEnviv 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::glTexEnvxvOES(CallObserver* observer, uint32_t target, uint32_t pname, GLfixed* params) {
    GAPID_DEBUG("glTexEnvxvOES(%u, %u, %p)", target, pname, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlTexEnvxvOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), target, pname, toEncoder< gapic::coder::gles::GLfixed__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::glTexGenivOES(CallObserver* observer, uint32_t coord, uint32_t pname, GLint* params) {
    GAPID_DEBUG("glTexGenivOES(%u, %u, %p)", coord, pname, params);

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

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


    uint64_t counter_at_begin = mCommandStartEndCounter++;

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

    observer->observeWrites();

    gapic::coder::gles::GlTexGenivOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), coord, 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::glTranslatexOES(CallObserver* observer, GLfixed x, GLfixed y, GLfixed z) {
    GAPID_DEBUG("glTranslatexOES(%" PRId32 ", %" PRId32 ", %" PRId32 ")", x, y, z);

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

    bool called = false;
    auto call = [this, observer, &called, x, y, z] {
        called = true;
        observer->observeReads();
        mImports.glTranslatexOES(x, y, z);
        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::GlTranslatexOES coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), 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::glVertexPointer(CallObserver* observer, GLint size, uint32_t type, GLsizei stride, void* pointer) {
    GAPID_DEBUG("glVertexPointer(%" PRId32 ", %u, %" PRId32 ", %p)", size, type, stride, pointer);

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

    bool called = false;
    auto call = [this, observer, &called, size, type, stride, pointer] {
        called = true;
        observer->observeReads();
        mImports.glVertexPointer(size, type, stride, pointer);
        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::GlVertexPointer 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::replayCreateRenderer(CallObserver* observer, uint32_t id) {
    GAPID_DEBUG("replayCreateRenderer(%" PRIu32 ")", id);

    bool called = false;
    auto call = [this, observer, &called, id] {
        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::ReplayCreateRenderer coder(observer->getScratch()->vector<gapic::Encodable*>(kMaxExtras), id);
    coder.mextras.append(observer->getExtras());

    if (counter_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::flushPostBuffer(CallObserver* observer) {
    GAPID_DEBUG("flushPostBuffer()");

    bool called = false;
    auto call = [this, observer, &called] {
        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::FlushPostBuffer 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);

}
} // namespace gapii