opengl: bound buffers

This commit is contained in:
Mitchell Hashimoto
2022-04-01 18:00:15 -07:00
parent 63673287f6
commit a5a2196d52
2 changed files with 60 additions and 52 deletions

View File

@ -55,8 +55,8 @@ pub fn main() !void {
const vbo = try gl.Buffer.create();
defer vbo.destroy();
try vao.bind();
try vbo.bind(c.GL_ARRAY_BUFFER);
try vbo.setData(c.GL_ARRAY_BUFFER, vertices, c.GL_STATIC_DRAW);
var binding = try vbo.bind(c.GL_ARRAY_BUFFER);
try binding.setData(&vertices, c.GL_STATIC_DRAW);
c.glVertexAttribPointer(
0,
@ -68,7 +68,7 @@ pub fn main() !void {
);
c.glEnableVertexAttribArray(0);
try gl.Buffer.unbind(c.GL_ARRAY_BUFFER);
binding.unbind();
try gl.VertexArray.unbind();
// Wait for the user to close the window.

View File

@ -6,6 +6,61 @@ const errors = @import("errors.zig");
id: c.GLuint,
/// Binding is a bound buffer. By using this for functions that operate
/// on bound buffers, you can easily defer unbinding and in safety-enabled
/// modes verify that unbound buffers are never accessed.
pub const Binding = struct {
target: c.GLenum,
/// Sets the data of this bound buffer. The data can be any array-like
/// type. The size of the data is automatically determined based on the type.
pub inline fn setData(
b: Binding,
data: anytype,
usage: c.GLenum,
) !void {
// Determine the size and pointer to the given data.
const info: struct {
size: isize,
ptr: *const anyopaque,
} = switch (@typeInfo(@TypeOf(data))) {
.Array => |ary| .{
.size = @sizeOf(ary.child) * ary.len,
.ptr = &data,
},
.Pointer => |ptr| switch (ptr.size) {
.One => .{
.size = @sizeOf(ptr.child) * data.len,
.ptr = data,
},
.Slice => .{
.size = @sizeOf(ptr.child) * data.len,
.ptr = data.ptr,
},
else => {
std.log.err("invalid buffer data pointer size: {}", .{ptr.size});
unreachable;
},
},
else => {
std.log.err("invalid buffer data type: {s}", .{@tagName(@typeInfo(@TypeOf(data)))});
unreachable;
},
};
c.glBufferData(b.target, info.size, info.ptr, usage);
try errors.getError();
}
pub inline fn unbind(b: *Binding) void {
c.glBindBuffer(b.target, 0);
// By setting this to undefined, this ensures that any future calls
// error in safe build modes.
b.* = undefined;
}
};
/// Create a single buffer.
pub inline fn create() !Buffer {
var vbo: c.GLuint = undefined;
@ -13,57 +68,10 @@ pub inline fn create() !Buffer {
return Buffer{ .id = vbo };
}
// Unbind any active vertex array.
pub inline fn unbind(target: c.GLenum) !void {
c.glBindBuffer(target, 0);
}
/// glBindBuffer
pub inline fn bind(v: Buffer, target: c.GLenum) !void {
pub inline fn bind(v: Buffer, target: c.GLenum) !Binding {
c.glBindBuffer(target, v.id);
}
pub inline fn setData(
v: Buffer,
target: c.GLenum,
data: anytype,
usage: c.GLenum,
) !void {
// Maybe one day in debug mode we can validate that this buffer
// is currently bound.
_ = v;
// Determine the size and pointer to the given data.
const info: struct {
size: isize,
ptr: *const anyopaque,
} = switch (@typeInfo(@TypeOf(data))) {
.Array => |ary| .{
.size = @sizeOf(ary.child) * ary.len,
.ptr = &data,
},
.Pointer => |ptr| switch (ptr.size) {
.One => .{
.size = @sizeOf(ptr.child) * data.len,
.ptr = data,
},
.Slice => .{
.size = @sizeOf(ptr.child) * data.len,
.ptr = data.ptr,
},
else => {
std.log.err("invalid buffer data pointer size: {}", .{ptr.size});
unreachable;
},
},
else => {
std.log.err("invalid buffer data type: {s}", .{@tagName(@typeInfo(@TypeOf(data)))});
unreachable;
},
};
c.glBufferData(target, info.size, info.ptr, usage);
try errors.getError();
return Binding{ .target = target };
}
pub inline fn destroy(v: Buffer) void {