From de0f707c96ecb46b4b03836023953555f1f9d635 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 1 Apr 2022 15:34:03 -0700 Subject: [PATCH] opengl: programs --- src/main.zig | 23 +++++--------- src/opengl.zig | 81 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 75 insertions(+), 29 deletions(-) diff --git a/src/main.zig b/src/main.zig index eac21cdc0..351d342ae 100644 --- a/src/main.zig +++ b/src/main.zig @@ -36,20 +36,13 @@ pub fn main() !void { defer fs.destroy(); // Shader program - const program = c.glCreateProgram(); - c.glAttachShader(program, vs.handle); - c.glAttachShader(program, fs.handle); - c.glLinkProgram(program); - var success: c_int = undefined; - c.glGetProgramiv(program, c.GL_LINK_STATUS, &success); - if (success != c.GL_TRUE) { - var msg: [512]u8 = undefined; - c.glGetProgramInfoLog(program, 512, null, &msg); - std.log.err("program fail: {s}\n", .{std.mem.sliceTo(&msg, 0)}); - return; - } - c.glDeleteShader(vs.handle); - c.glDeleteShader(fs.handle); + const program = try gl.Program.create(); + defer program.destroy(); + try program.attachShader(vs); + try program.attachShader(fs); + try program.link(); + vs.destroy(); + fs.destroy(); // Create our bufer or vertices const vertices = [_]f32{ @@ -90,7 +83,7 @@ pub fn main() !void { c.glClearColor(0.2, 0.3, 0.3, 1.0); c.glClear(c.GL_COLOR_BUFFER_BIT); - c.glUseProgram(program); + c.glUseProgram(program.id); c.glBindVertexArray(vao); c.glDrawArrays(c.GL_TRIANGLES, 0, 3); diff --git a/src/opengl.zig b/src/opengl.zig index 15ac6d78f..f6a3e8e3e 100644 --- a/src/opengl.zig +++ b/src/opengl.zig @@ -36,30 +36,30 @@ fn mustError() Error!void { } pub const Shader = struct { - handle: c.GLuint, + id: c.GLuint, pub fn create(typ: c.GLenum) Error!Shader { - const handle = c.glCreateShader(typ); - if (handle == 0) { + const id = c.glCreateShader(typ); + if (id == 0) { try mustError(); unreachable; } - log.debug("shader created id={}", .{handle}); - return Shader{ .handle = handle }; + log.debug("shader created id={}", .{id}); + return Shader{ .id = id }; } /// Set the source and compile a shader. pub fn setSourceAndCompile(s: Shader, source: [:0]const u8) !void { - c.glShaderSource(s.handle, 1, &@ptrCast([*c]const u8, source), null); - c.glCompileShader(s.handle); + c.glShaderSource(s.id, 1, &@ptrCast([*c]const u8, source), null); + c.glCompileShader(s.id); // Check if compilation succeeded var success: c_int = undefined; - c.glGetShaderiv(s.handle, c.GL_COMPILE_STATUS, &success); + c.glGetShaderiv(s.id, c.GL_COMPILE_STATUS, &success); if (success == c.GL_TRUE) return; - log.err("shader compilation failure handle={} message={s}", .{ - s.handle, + log.err("shader compilation failure id={} message={s}", .{ + s.id, std.mem.sliceTo(&s.getInfoLog(), 0), }); return error.CompileFailed; @@ -73,13 +73,66 @@ pub const Shader = struct { // if we ever need it. pub fn getInfoLog(s: Shader) [512]u8 { var msg: [512]u8 = undefined; - c.glGetShaderInfoLog(s.handle, msg.len, null, &msg); + c.glGetShaderInfoLog(s.id, msg.len, null, &msg); return msg; } pub fn destroy(s: Shader) void { - assert(s.handle != 0); - c.glDeleteShader(s.handle); - log.debug("shader destroyed id={}", .{s.handle}); + assert(s.id != 0); + c.glDeleteShader(s.id); + log.debug("shader destroyed id={}", .{s.id}); + } +}; + +pub const Program = struct { + id: c.GLuint, + + pub fn create() !Program { + const id = c.glCreateProgram(); + if (id == 0) try mustError(); + + log.debug("program created id={}", .{id}); + return Program{ .id = id }; + } + + pub fn attachShader(p: Program, s: Shader) !void { + c.glAttachShader(p.id, s.id); + try getError(); + } + + pub fn link(p: Program) !void { + c.glLinkProgram(p.id); + + // Check if linking succeeded + var success: c_int = undefined; + c.glGetProgramiv(p.id, c.GL_LINK_STATUS, &success); + if (success == c.GL_TRUE) { + log.debug("program linked id={}", .{p.id}); + return; + } + + log.err("program link failure id={} message={s}", .{ + p.id, + std.mem.sliceTo(&p.getInfoLog(), 0), + }); + return error.CompileFailed; + } + + /// getInfoLog returns the info log for this program. This attempts to + /// keep the log fully stack allocated and is therefore limited to a max + /// amount of elements. + // + // NOTE(mitchellh): we can add a dynamic version that uses an allocator + // if we ever need it. + pub fn getInfoLog(s: Program) [512]u8 { + var msg: [512]u8 = undefined; + c.glGetProgramInfoLog(s.id, msg.len, null, &msg); + return msg; + } + + pub fn destroy(p: Program) void { + assert(p.id != 0); + c.glDeleteProgram(p.id); + log.debug("program destroyed id={}", .{p.id}); } };