private void Initialize(VertexInputLayoutBinding[] bindings, VertexInputLayoutAttribute[] attributes)
        {
            var glBindingAttribs = new List <GLVertexInputLayoutAttribute> [bindings.Length];

            foreach (var attrib in attributes)
            {
                var bindingIndex = Array.FindIndex(bindings, binding => binding.Slot == attrib.Slot);
                if (bindingIndex < 0)
                {
                    continue;
                }
                GLHelper.GetGLVertexAttribFormat(attrib.Format, out var glType, out var glSize, out var glNormalized);
                if (glBindingAttribs[bindingIndex] == null)
                {
                    glBindingAttribs[bindingIndex] = new List <GLVertexInputLayoutAttribute>();
                }
                glBindingAttribs[bindingIndex].Add(new GLVertexInputLayoutAttribute {
                    Index      = attrib.Location,
                    Offset     = attrib.Offset,
                    Type       = glType,
                    Size       = glSize,
                    Normalized = glNormalized
                });
            }
            var glBindings = new List <GLVertexInputLayoutBinding>();

            for (var i = 0; i < bindings.Length; i++)
            {
                var glAttribs = glBindingAttribs[i];
                if (glAttribs != null)
                {
                    glBindings.Add(new GLVertexInputLayoutBinding {
                        Slot       = bindings[i].Slot,
                        Stride     = bindings[i].Stride,
                        Attributes = glAttribs.ToArray()
                    });
                }
            }
            GLBindings = glBindings.ToArray();
            foreach (var binding in GLBindings)
            {
                BindingMask |= 1L << binding.Slot;
                foreach (var attrib in binding.Attributes)
                {
                    AttributeMask |= 1L << attrib.Index;
                }
            }
        }