Spec PDF: GL ES 3.0.6 (November 1, 2019)
Godbolt with no errors: x86-64 gcc 14.2
-std=c++20
: https://godbolt.org/z/cbYEb939G
(Full Godbolt URL embed: https://godbolt.org/#z:OYLghAFBqd[…])
gles30_state_tables.cpp
//#! cc -std=c++20
// GL ES 3.0.6 (November 1, 2019):
// https://registry.khronos.org/OpenGL/specs/es/3.0/es_spec_3.0.pdf
#include <cstdint>
#include <array>
#include <string>
#include <vector>
using uint = uint32_t; // "Z+"
using ptr = intptr_t; // "Y"
using usize = size_t; // "Z+" with i64 getter.
using ufloat = float; // "R+" (>= 0.0f)
template<uint Possibilities=0, bool OrMore=false> using GLenum = uint32_t;
// (Easier to read array types as N,T instead of T,N)
template<uint N, class T> using arr = std::array<T,N>;
using std::vector;
using std::string;
using bytes = vector<std::byte>;
// -
class Buffer;
class Framebuffer;
class Program;
class Query;
class Renderbuffer;
class Sampler;
class Shader;
class Sync;
class Texture;
class TransformFeedback;
class VertexArray;
template<class T> using id = uint;
extern int WINDOW_WIDTH;
extern int WINDOW_HEIGHT;
extern GLenum<> BACK;
extern GLenum<> CCW;
extern GLenum<> DONT_CARE;
extern GLenum<> TEXTURE0;
extern GLenum<> ALWAYS;
extern GLenum<> KEEP;
extern GLenum<> LESS;
extern GLenum<> ONE;
extern GLenum<> ZERO;
extern GLenum<> FUNC_ADD;
extern GLenum<> STATIC_DRAW;
extern GLenum<> RGBA4;
extern GLenum<> NEAREST_MIPMAP_LINEAR;
extern GLenum<> LINEAR;
extern GLenum<> REPEAT;
extern GLenum<> LEQUAL;
extern GLenum<> SYNC_FENCE;
extern GLenum<> UNSIGNALED;
extern GLenum<> SYNC_GPU_COMMANDS_COMPLETE;
extern GLenum<> RED;
extern GLenum<> GREEN;
extern GLenum<> BLUE;
extern GLenum<> ALPHA;
extern GLenum<> FLOAT;
extern GLenum<> INTERLEAVED_ATTRIBS;
//extern GLenum<> COLOR_ATTACHMENT0;
//extern GLenum<> NONE;
constexpr GLenum<> COLOR_ATTACHMENT0 = 0x8CE0;
constexpr GLenum<> NONE = 0;
struct ImplementationLimits {
// p273: Table 6.28: Implementation Dependent Values
usize MAX_ELEMENT_INDEX = (1 << 24) - 1;
uint SUBPIXEL_BITS = 4;
uint MAX_3D_TEXTURE_SIZE = 256;
uint MAX_TEXTURE_SIZE = 2048;
uint MAX_ARRAY_TEXTURE_LAYERS = 256;
ufloat MAX_TEXTURE_LOD_BIAS = 2.0;
uint MAX_CUBE_MAP_TEXTURE_SIZE = 2048;
uint MAX_RENDERBUFFER_SIZE = 2048;
uint MAX_DRAW_BUFFERS = 4;
uint MAX_COLOR_ATTACHMENTS = 4;
arr<2, uint> MAX_VIEWPORT_DIMS;
arr<2, ufloat> ALIASED_POINT_SIZE_RANGE = {1, 1};
arr<2, ufloat> ALIASED_LINE_WIDTH_RANGE = {1, 1};
// p274: Table 6.29: Implementation Dependent Values (cont.)
uint MAX_ELEMENTS_INDICES = 0;
uint MAX_ELEMENTS_VERTICES = 0;
vector<GLenum<>> COMPRESSED_TEXTURE_FORMATS;
vector<GLenum<>> PROGRAM_BINARY_FORMATS;
vector<GLenum<>> SHADER_BINARY_FORMATS;
bool SHADER_COMPILER = true;
struct PerShaderPrecisionFormat {
arr<2, uint> range;
uint precision;
};
arr<2*2*3, PerShaderPrecisionFormat> shaderPrecisionFormats;
usize MAX_SERVER_WAIT_TIMEOUT = 0;
// p275: Table 6.30: Implementation Dependent Version and Extension Support
vector<string> EXTENSIONS;
uint MAJOR_VERSION = 3;
uint MINOR_VERSION = 0;
string RENDERER;
string SHADER_LANGUAGE_VERSION;
string VENDOR;
string VERSION;
// p276: Table 6.31: Implementation Dependent Vertex Shader Limits
uint MAX_VERTEX_ATTRIBS = 16;
uint MAX_VERTEX_UNIFORM_COMPONENTS = 1024;
uint MAX_VERTEX_UNIFORM_VECTORS = 256;
uint MAX_VERTEX_UNIFORM_BLOCKS = 12;
uint MAX_VERTEX_OUTPUT_COMPONENTS = 64;
uint MAX_VERTEX_TEXTURE_IMAGE_UNITS = 16;
// p277: Table 6.32: Implementation Dependent Fragment Shader Limits
uint MAX_FRAGMENT_UNIFORM_COMPONENTS = 896;
uint MAX_FRAGMENT_UNIFORM_VECTORS = 224;
uint MAX_FRAGMENT_UNIFORM_BLOCKS = 12;
uint MAX_FRAGMENT_INPUT_COMPONENTS = 60;
uint MAX_TEXTURE_IMAGE_UNITS = 16;
int MIN_PROGRAM_TEXEL_OFFSET = -8;
int MAX_PROGRAM_TEXEL_OFFSET = 7;
// p278: Table 6.33: Implementation Dependent Aggregate Shader Limits
uint MAX_UNIFORM_BUFFER_BINDINGS = 24;
usize MAX_UNIFORM_BLOCK_SIZE = 16384;
uint UNIFORM_BUFFER_OFFSET_ALIGNMENT = 256;
uint MAX_COMBINED_UNIFORM_BLOCKS = 24;
constexpr usize MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS() const {
return MAX_VERTEX_UNIFORM_BLOCKS * MAX_UNIFORM_BLOCK_SIZE / 4
+ MAX_VERTEX_UNIFORM_COMPONENTS;
}
constexpr usize MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS() const {
return MAX_FRAGMENT_UNIFORM_BLOCKS * MAX_UNIFORM_BLOCK_SIZE / 4
+ MAX_FRAGMENT_UNIFORM_COMPONENTS;
}
uint MAX_VARYING_COMPONENTS = 60;
uint MAX_VARYING_VECTORS = 15;
uint MAX_COMBINED_TEXTURE_IMAGE_UNITS = 32;
// p279: Table 6.34: Implementation Dependent Transform Feedback Limits:
uint MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS = 64;
uint MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 4;
uint MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS = 4;
// p281: Table 6.36: Miscellaneous
arr<3, id<Query>> CURRENT_QUERY = {0};
id<Buffer> COPY_READ_BUFFER_BINDING = 0;
id<Buffer> COPY_WRITE_BUFFER_BINDING = 0;
// Implied:
usize _MAX_STENCIL_BITS = 8;
};
static constexpr auto LIMITS = ImplementationLimits{};
struct ContextState {
// p248: Table 6.3: Vertex Array Data (not in vertex array objects)
id<Buffer> ARRAY_BUFFER_BINDING = 0;
id<VertexArray> VERTEX_ARRAY_BINDING;
bool PRIMITIVE_RESTART_FIXED_INDEX = false;
// p250: Table 6.5: Transformation State
arr<4, int> VIEWPORT = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
arr<2, ufloat> DEPTH_RANGE = {0, 1};
id<TransformFeedback> TRANSFORM_FEEDBACK_BINDING = 0;
// p251: Table 6.6: Rasterization
bool RASTERIZER_DISCARD = false;
ufloat LINE_WIDTH = 1.0;
bool CULL_FACE = false;
GLenum<3> CULL_FACE_MODE = BACK;
GLenum<2> FRONT_FACE = CCW;
float POLYGON_OFFSET_FACTOR = 0;
float POLYGON_OFFSET_UNITS = 0;
bool POLYGON_OFFSET_FILL = false;
// p252: Table 6.7: Multisampling
bool SAMPLE_ALPHA_TO_COVERAGE = false;
bool SAMPLE_COVERAGE = false;
ufloat SAMPLE_COVERAGE_VALUE = 1.0f;
bool SAMPLE_COVERAGE_INVERT = false;
// p253: Table 6.8: Textures (selector, state per texture unit)
GLenum<32,true> ACTIVE_TEXTURE = TEXTURE0;
arr<LIMITS.MAX_COMBINED_TEXTURE_IMAGE_UNITS, id<Texture>> TEXTURE_BINDING_2D = {0};
arr<LIMITS.MAX_COMBINED_TEXTURE_IMAGE_UNITS, id<Texture>> TEXTURE_BINDING_3D = {0};
arr<LIMITS.MAX_COMBINED_TEXTURE_IMAGE_UNITS, id<Texture>> TEXTURE_BINDING_2D_ARRAY = {0};
arr<LIMITS.MAX_COMBINED_TEXTURE_IMAGE_UNITS, id<Texture>> TEXTURE_BINDING_CUBE_MAP = {0};
arr<LIMITS.MAX_COMBINED_TEXTURE_IMAGE_UNITS, id<Sampler>> SAMPLER_BINDING = {0};
// p256: Table 6.11: Pixel Operations
bool SCISSOR_TEST = false;
arr<4, int> SCISSOR_BOX = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
bool STENCIL_TEST = false;
GLenum<8> STENCIL_FUNC = ALWAYS;
uint STENCIL_VALUE_MASK = (1 << LIMITS._MAX_STENCIL_BITS)-1;
uint STENCIL_REF = 0;
GLenum<8> STENCIL_FAIL = KEEP;
GLenum<8> STENCIL_PASS_DEPTH_FAIL = KEEP;
GLenum<8> STENCIL_PASS_DEPTH_PASS = KEEP;
GLenum<8> STENCIL_BACK_FUNC = ALWAYS;
uint STENCIL_BACK_VALUE_MASK = (1 << LIMITS._MAX_STENCIL_BITS)-1;
uint STENCIL_BACK_REF = 0;
GLenum<8> STENCIL_BACK_FAIL = KEEP;
GLenum<8> STENCIL_BACK_FAIL_PASS_DEPTH_FAIL = KEEP;
GLenum<8> STENCIL_BACK_FAIL_PASS_DEPTH_PASS = KEEP;
bool DEPTH_TEST = false;
GLenum<8> DEPTH_FUNC = LESS;
bool BLEND = false;
GLenum<19> BLEND_SRC_RGB = ONE;
GLenum<19> BLEND_SRC_ALPHA = ONE;
GLenum<19> BLEND_DST_RGB = ZERO;
GLenum<19> BLEND_DST_ALPHA = ZERO;
GLenum<5> BLEND_EQUATION_RGB = FUNC_ADD;
GLenum<5> BLEND_EQUATION_ALPHA = FUNC_ADD;
arr<4, float> BLEND_COLOR = {0,0,0,0};
bool DITHER = true;
// p257: Table 6.12: Framebuffer Control
arr<4, bool> COLOR_WRITEMASK = {true, true, true, true};
bool DPETH_WRITEMASK = true;
uint STENCIL_WRITEMASK = ~0;
uint STENCIL_BACK_WRITEMASK = ~0;
arr<4, float> COLOR_CLEAR_VALUE = {0,0,0,0};
ufloat DEPTH_CLEAR_VALUE = 1.0;
uint STENCIL_CLEAR_VALUE = 0;
id<Framebuffer> DRAW_FRAMEBUFFER_BINDING = 0;
id<Framebuffer> READ_FRAMEBUFFER_BINDING = 0;
id<Renderbuffer> RENDERBUFFER_BINDING = 0;
// p261: Table 6.16: Pixels
uint UNPACK_IMAGE_HEIGHT = 0;
uint UNPACK_SKIP_IMAGES = 0;
uint UNPACK_ROW_LENGTH = 0;
uint UNPACK_SKIP_ROWS = 0;
uint UNPACK_SKIP_PIXELS = 0;
uint UNPACK_ALIGNMENT = 0;
uint PACK_ROW_LENGTH = 0;
uint PACK_SKIP_ROWS = 0;
uint PACK_SKIP_PIXELS = 0;
uint PACK_ALIGNMENT = 0;
id<Buffer> PIXEL_PACK_BUFFER_BINDING = 0;
id<Buffer> PIXEL_UNPACK_BUFFER_BINDING = 0;
// p263: Table 6.18: Program Object State
id<Program> CURRENT_PROGRAM = 0;
// p267: Table 6.22: Vertex Shader State (not part of program objects)
arr<LIMITS.MAX_VERTEX_ATTRIBS, arr<4, float>> CURRENT_VERTEX_ATTRIB = 0;
// p269: Table 6.24: Transform Feedback State
id<Buffer> TRANSFORM_FEEDBACK_BUFFER_BINDING = 0;
// p270: Table 6.25: Uniform Buffer Binding State
id<Buffer> UNIFORM_BUFFER_BINDING = 0;
struct PerUniformBuffer {
id<Buffer> UNIFORM_BUFFER_BINDING = 0;
usize UNIFORM_BUFFER_START = 0;
usize UNIFORM_BUFFER_SIZE = 0;
};
arr<LIMITS.MAX_UNIFORM_BUFFER_BINDINGS, PerUniformBuffer> uniformBuffers;
// p272: Table 6.27: Hints
GLenum<3> GENERATE_MIPMAP_HINT = DONT_CARE;
GLenum<3> FRAGMENT_SHADER_DERIVATIVE_HINT = DONT_CARE;
};
struct BufferState {
// p249: Table 6.4: Buffer Object State
usize BUFFER_SIZE = 0;
GLenum<9> BUFFER_USAGE = STATIC_DRAW;
uint BUFFER_ACCESS_FLAGS = 0;
bool BUFFER_MAPPED = false;
ptr BUFFER_MAP_POINTER = 0;
usize BUFFER_MAP_OFFSET = 0;
usize BUFFER_MAP_LENGTH = 0;
};
struct FramebufferState {
// p258: Table 6.13: Framebuffer (state per framebuffer object)
arr<LIMITS.MAX_DRAW_BUFFERS, GLenum<11,true>> DRAW_BUFFERi = {COLOR_ATTACHMENT0, 0 };
GLenum<11,true> READ_BUFFER; // Queried from READ_FRAMEBUFFER
// p259: Table 6.14: Framebuffer (state per attachment point)
struct PerAttachment {
GLenum<4> FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = NONE;
union {
id<Renderbuffer> rb = 0;
id<Texture> tex;
} FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = {};
uint FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0;
uint FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = NONE;
int FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER = 0; // Errata: uint?
GLenum<2> FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING;
GLenum<4> FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE;
uint FRAMEBUFFER_ATTACHMENT_RED_SIZE;
uint FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
uint FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
uint FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE;
uint FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE;
uint FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE;
};
arr<LIMITS.MAX_COLOR_ATTACHMENTS, PerAttachment> attachments;
// p280: Table 6.35: Framebuffer Dependent Values
uint SAMPLE_BUFFERS = 0;
uint SAMPLES = 0;
uint MAX_SAMPLES = 4;
uint RED_BITS;
uint GREEN_BITS;
uint BLUE_BITS;
uint ALPHA_BITS;
uint DEPTH_BITS;
uint STENCIL_BITS;
GLenum<> IMPLEMENTATION_COLOR_READ_TYPE; // Queried from READ_FRAMEBUFFER.
GLenum<> IMPLEMENTATION_COLOR_READ_FORMAT; // Queried from READ_FRAMEBUFFER.
};
static_assert(FramebufferState{}.DRAW_BUFFERi[0] == COLOR_ATTACHMENT0);
static_assert(FramebufferState{}.DRAW_BUFFERi[1] == 0);
static_assert(FramebufferState{}.DRAW_BUFFERi[2] == 0);
struct ProgramState {
// p263: Table 6.18: Program Object State
bool DELETE_STATUS = false;
bool LINK_STATUS = false;
bool VALIDATE_STATUS = false;
vector<id<Shader>> ATTACHED_SHADERS = {};
string INFO_LOG = "";
struct PerActiveUniform {
int location;
uint size;
GLenum<> type;
string name;
// p265: Table 6.20: Program Object State (cont.)
GLenum<27> UNIFORM_TYPE;
uint UNIFORM_SIZE;
int UNIFORM_BLOCK_INDEX;
int UNIFORM_OFFSET;
// p266: Table 6.21: Program Object State (cont.)
int UNIFORM_ARRAY_STRIDE;
int UNIFORM_MATRIX_STRIDE;
bool UNIFORM_IS_ROW_MAJOR;
};
vector<PerActiveUniform> ACTIVE_UNIFORMS = {};
//vector<PerActiveAttribute> ACTIVE_ATTRIBUTES = {}; // Moved below.
bool PROGRAM_BINARY_RETRIEVABLE_HINT = false;
bytes PROGRAM_BINARY = {};
// p264: Table 6.19: Program Object State (cont.)
struct PerActiveAttribute {
int location;
uint size;
GLenum<> type;
string name;
};
vector<PerActiveAttribute> ACTIVE_ATTRIBUTES = {}; // Actually p263.
GLenum<2> TRANSFORM_FEEDBACK_BUFFER_MODE = INTERLEAVED_ATTRIBS;
struct PerActiveTfVarying {
uint size;
GLenum<> type;
string name;
};
vector<PerActiveTfVarying> TRANSFORM_FEEDBACK_VARYINGS = {};
// p265: Table 6.20: Program Object State (cont.)
//vector<PerActiveUniformBlock> ACTIVE_UNIFORM_BLOCKS = {}; // Moved below.
struct PerActiveUniformBlock {
// p266: Table 6.21: Program Object State (cont.)
uint UNIFORM_BLOCK_BINDING = 0;
uint UNIFORM_BLOCK_DATA_SIZE;
vector<uint> UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES;
bool UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = false;
bool UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = false;
};
vector<PerActiveUniformBlock> ACTIVE_UNIFORM_BLOCKS = {}; // Actually p265.
};
struct QueryState {
// p268: Table 6.23: Query Object State
uint QUERY_RESULT = 0;
bool QUERY_RESULT_AVAILABLE = false;
};
struct RenderbufferState {
// p260: Table 6.15: Renderbuffer (state per renderbuffer object)
uint RENDERBUFFER_WIDTH = 0;
uint RENDERBUFFER_HEIGHT = 0;
GLenum<43> RENDERBUFFER_INTERNAL_FORMAT = RGBA4;
uint RENDERBUFFER_RED_SIZE = 0;
uint RENDERBUFFER_GREEN_SIZE = 0;
uint RENDERBUFFER_BLUE_SIZE = 0;
uint RENDERBUFFER_ALPHA_SIZE = 0;
uint RENDERBUFFER_DEPTH_SIZE = 0;
uint RENDERBUFFER_STENCIL_SIZE = 0;
uint RENDERBUFFER_SAMPLES = 0;
};
struct SamplerState {
// p255: Table 6.10: Textures (state per sampler object)
GLenum<6> TEXTURE_MIN_FILTER = NEAREST_MIPMAP_LINEAR;
GLenum<6> TEXTURE_MAG_FILTER = LINEAR;
GLenum<4> TEXTURE_WRAP_S = REPEAT;
GLenum<4> TEXTURE_WRAP_T = REPEAT;
GLenum<4> TEXTURE_WRAP_R = REPEAT;
float TEXTURE_MIN_LOD = -1000;
float TEXTURE_MAX_LOD = 1000;
GLenum<2> TEXTURE_COMPARE_MODE = NONE;
GLenum<8> TEXTURE_COMPARE_FUNC = LEQUAL;
};
struct ShaderState {
// p262: Table 6.17: Shader Object State
GLenum<3> SHADER_TYPE;
bool DELETE_STATUS = false;
bool COMPILE_STATUS = false;
string ShaderInfoLog = "";
uint INFO_LOG_LENGTH = 0;
string ShaderSource = "";
uint SHADER_SOURCE_LENGTH = 0;
};
struct SyncState {
// p271: Table 6.26: Sync (state per sync object)
GLenum<1> OBJECT_TYPE = SYNC_FENCE;
GLenum<2> SYNC_STATUS = UNSIGNALED;
GLenum<1> SYNC_CONDITION = SYNC_GPU_COMMANDS_COMPLETE;
uint SYNC_FLAGS = 0;
};
struct TextureState {
// p254: Table 6.9: Textures (state per texture object)
GLenum<6> TEXTURE_SWIZZLE_R = RED;
GLenum<6> TEXTURE_SWIZZLE_G = GREEN;
GLenum<6> TEXTURE_SWIZZLE_B = BLUE;
GLenum<6> TEXTURE_SWIZZLE_A = ALPHA;
GLenum<6> TEXTURE_MIN_FILTER = NEAREST_MIPMAP_LINEAR;
GLenum<6> TEXTURE_MAG_FILTER = LINEAR;
GLenum<4> TEXTURE_WRAP_S = REPEAT;
GLenum<4> TEXTURE_WRAP_T = REPEAT;
GLenum<4> TEXTURE_WRAP_R = REPEAT;
float TEXTURE_MIN_LOD = -1000;
float TEXTURE_MAX_LOD = 1000;
uint TEXTURE_BASE_LEVEL = 0;
uint TEXTURE_MAX_LEVEL = 1000;
GLenum<2> TEXTURE_COMPARE_MODE = NONE;
GLenum<8> TEXTURE_COMPARE_FUNC = LEQUAL;
bool TEXTURE_IMMUTABLE_FORMAT = false;
uint TEXTURE_IMMUTABLE_LEVELS = 0;
};
struct TransformFeedbackState {
// p269: Table 6.24: Transform Feedback State
struct PerBinding {
id<Buffer> TRANSFORM_FEEDBACK_BUFFER_BINDING = 0;
usize TRANSFORM_FEEDBACK_BUFFER_START = 0;
usize TRANSFORM_FEEDBACK_BUFFER_SIZE = 0;
};
arr<LIMITS.MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, PerBinding> bindings = {};
bool TRANSFORM_FEEDBACK_PAUSED = false;
bool TRANSFORM_FEEDBACK_ACTIVE = false;
};
struct VertexArrayState {
// p247: Table 6.2: Vertex Array Object State
struct PerAttrib {
bool VERTEX_ATTRIB_ARRAY_ENABLED = false;
GLenum<5> VERTEX_ATTRIB_ARRAY_SIZE = 4;
uint VERTEX_ATTRIB_ARRAY_STRIDE = 0;
GLenum<9> VERTEX_ATTRIB_ARRAY_TYPE = FLOAT;
bool VERTEX_ATTRIB_ARRAY_NORMALIZED = false;
bool VERTEX_ATTRIB_ARRAY_INTEGER = false;
uint VERTEX_ATTRIB_ARRAY_DIVISOR = 0;
ptr VERTEX_ATTRIB_ARRAY_POINTER = 0;
id<Buffer> VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0;
};
arr<LIMITS.MAX_VERTEX_ATTRIBS, PerAttrib> attribs;
id<Buffer> ELEMENT_ARRAY_BUFFER_BINDING = 0;
};