func NewVertexBuffer(data interface{}, f BufferFlags) VertexBuffer {
	p, s, st, err := pointerSizeAndStrideOf(data)
	if err != nil {
		setErr(internal.Wrap("gl vertex buffer creation", err))
		return VertexBuffer{}
	}
	var vb VertexBuffer
	vb.object = C.NewBuffer(C.GLsizeiptr(s), p, C.GLbitfield(f))
	vb.stride = st
	return vb
}
NewVertexBuffer asks the GPU to allocate a new block of memory.

If data is a uinptr, it is interpreted as the desired size for the buffer (in
bytes), and the content is not initialized. Otherwise data must be a slice of
pure values (no nested references). In all cases the size of the buffer is
fixed at creation.
package gl
import (
	"fmt"
	"reflect"
	"unsafe"
	"github.com/cozely/cozely/internal"
)
import "C"
type UniformBuffer struct {
	object C.GLuint
}
func NewUniformBuffer(data interface{}, f BufferFlags) UniformBuffer {
	p, s, err := pointerAndSizeOf(data)
	if err != nil {
		setErr(internal.Wrap("gl uniform buffer creation", err))
		return UniformBuffer{}
	}
	var ub UniformBuffer
	ub.object = C.NewBuffer(C.GLsizeiptr(s), p, C.GLbitfield(f))
	return ub
}
func (ub *UniformBuffer) SubData(data interface{}, atOffset uintptr) {
	p, s, err := pointerAndSizeOf(data)
	if err != nil {
		setErr(internal.Wrap("gl uniform buffer update", err))
		return
	}
	C.BufferSubData(ub.object, C.GLintptr(atOffset), C.GLsizei(s), p)
}
func (ub *UniformBuffer) Bind(binding uint32) {
	C.BindUniform(C.GLuint(binding), ub.object)
}
func (ub *UniformBuffer) Delete() {
	C.DeleteBuffer(C.GLuint(ub.object))
}
type StorageBuffer struct {
	object C.GLuint
}
func NewStorageBuffer(data interface{}, f BufferFlags) StorageBuffer {
	p, s, err := pointerAndSizeOf(data)
	if err != nil {
		setErr(internal.Wrap("gl storage buffer creation", err))
		return StorageBuffer{}
	}
	var sb StorageBuffer
	sb.object = C.NewBuffer(C.GLsizeiptr(s), p, C.GLbitfield(f))
	return sb
}
func (sb *StorageBuffer) SubData(data interface{}, atOffset uintptr) {
	p, s, err := pointerAndSizeOf(data)
	if err != nil {
		setErr(internal.Wrap("gl storage buffer update", err))
		return
	}
	C.BufferSubData(sb.object, C.GLintptr(atOffset), C.GLsizei(s), p)
}
func (sb *StorageBuffer) ClearUint32(data uint32) {
	C.ClearBuffer(C.GLuint(sb.object), C.GL_R32UI, C.GL_RED, C.GL_UNSIGNED_INT, unsafe.Pointer(&data))
}
func (sb *StorageBuffer) Bind(binding uint32) {
	C.BindStorage(C.GLuint(binding), sb.object)
}
func (sb *StorageBuffer) Delete() {
	if sb != nil {
		C.DeleteBuffer(C.GLuint(sb.object))
	}
}
type CounterBuffer struct {
	object C.GLuint
}
func NewCounterBuffer(nb int, f BufferFlags) CounterBuffer {
	var sb CounterBuffer
	sb.object = C.NewBuffer(C.GLsizeiptr(4*nb), nil, C.GLbitfield(f))
	return sb
}
func (sb *CounterBuffer) SubData(data []uint32, atOffset uintptr) {
	C.BufferSubData(sb.object, C.GLintptr(atOffset), C.GLsizei(4*len(data)), unsafe.Pointer(&data[0]))
}
func (sb *CounterBuffer) Bind(binding uint32) {
	C.BindCounter(C.GLuint(binding), sb.object)
}
func (sb *CounterBuffer) Delete() {
	if sb != nil {
		C.DeleteBuffer(C.GLuint(sb.object))
	}
}
type VertexBuffer struct {
	object C.GLuint
	stride uintptr
}