diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-01-26 19:49:25 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-01-26 19:49:25 +0000 |
| commit | 885a8652cb8a433a18811d90048d11c1ec67b60e (patch) | |
| tree | 52b845a825c91ec878983eb1078b4bd48f27ec73 /src/gl.zig | |
| parent | remove offset default uniform (diff) | |
| download | glsl-view-885a8652cb8a433a18811d90048d11c1ec67b60e.tar.gz glsl-view-885a8652cb8a433a18811d90048d11c1ec67b60e.zip | |
break OSC in favor of uniform caching
Diffstat (limited to 'src/gl.zig')
| -rw-r--r-- | src/gl.zig | 401 |
1 files changed, 365 insertions, 36 deletions
@@ -2,6 +2,292 @@ const std = @import("std"); const c_allocator = @import("std").heap.c_allocator; const panic = @import("std").debug.panic; const c = @import("c.zig"); +const cfg = @import("config.zig"); + +const UniformType = enum(c.GLint) { + FLOAT = c.GL_FLOAT, + FLOAT_VEC2 = c.GL_FLOAT_VEC2, + FLOAT_VEC3 = c.GL_FLOAT_VEC3, + FLOAT_VEC4 = c.GL_FLOAT_VEC4, + DOUBLE = c.GL_DOUBLE, + DOUBLE_VEC2 = c.GL_DOUBLE_VEC2, + DOUBLE_VEC3 = c.GL_DOUBLE_VEC3, + DOUBLE_VEC4 = c.GL_DOUBLE_VEC4, + INT = c.GL_INT, + INT_VEC2 = c.GL_INT_VEC2, + INT_VEC3 = c.GL_INT_VEC3, + INT_VEC4 = c.GL_INT_VEC4, + UNSIGNED_INT = c.GL_UNSIGNED_INT, + UNSIGNED_INT_VEC2 = c.GL_UNSIGNED_INT_VEC2, + UNSIGNED_INT_VEC3 = c.GL_UNSIGNED_INT_VEC3, + UNSIGNED_INT_VEC4 = c.GL_UNSIGNED_INT_VEC4, + BOOL = c.GL_BOOL, + BOOL_VEC2 = c.GL_BOOL_VEC2, + BOOL_VEC3 = c.GL_BOOL_VEC3, + BOOL_VEC4 = c.GL_BOOL_VEC4, + FLOAT_MAT2 = c.GL_FLOAT_MAT2, + FLOAT_MAT3 = c.GL_FLOAT_MAT3, + FLOAT_MAT4 = c.GL_FLOAT_MAT4, + FLOAT_MAT2x3 = c.GL_FLOAT_MAT2x3, + FLOAT_MAT2x4 = c.GL_FLOAT_MAT2x4, + FLOAT_MAT3x2 = c.GL_FLOAT_MAT3x2, + FLOAT_MAT3x4 = c.GL_FLOAT_MAT3x4, + FLOAT_MAT4x2 = c.GL_FLOAT_MAT4x2, + FLOAT_MAT4x3 = c.GL_FLOAT_MAT4x3, + DOUBLE_MAT2 = c.GL_DOUBLE_MAT2, + DOUBLE_MAT3 = c.GL_DOUBLE_MAT3, + DOUBLE_MAT4 = c.GL_DOUBLE_MAT4, + DOUBLE_MAT2x3 = c.GL_DOUBLE_MAT2x3, + DOUBLE_MAT2x4 = c.GL_DOUBLE_MAT2x4, + DOUBLE_MAT3x2 = c.GL_DOUBLE_MAT3x2, + DOUBLE_MAT3x4 = c.GL_DOUBLE_MAT3x4, + DOUBLE_MAT4x2 = c.GL_DOUBLE_MAT4x2, + DOUBLE_MAT4x3 = c.GL_DOUBLE_MAT4x3, + SAMPLER_1D = c.GL_SAMPLER_1D, + SAMPLER_2D = c.GL_SAMPLER_2D, + SAMPLER_3D = c.GL_SAMPLER_3D, + SAMPLER_CUBE = c.GL_SAMPLER_CUBE, + SAMPLER_1D_SHADOW = c.GL_SAMPLER_1D_SHADOW, + SAMPLER_2D_SHADOW = c.GL_SAMPLER_2D_SHADOW, + SAMPLER_1D_ARRAY = c.GL_SAMPLER_1D_ARRAY, + SAMPLER_2D_ARRAY = c.GL_SAMPLER_2D_ARRAY, + SAMPLER_1D_ARRAY_SHADOW = c.GL_SAMPLER_1D_ARRAY_SHADOW, + SAMPLER_2D_ARRAY_SHADOW = c.GL_SAMPLER_2D_ARRAY_SHADOW, + SAMPLER_2D_MULTISAMPLE = c.GL_SAMPLER_2D_MULTISAMPLE, + SAMPLER_2D_MULTISAMPLE_ARRAY = c.GL_SAMPLER_2D_MULTISAMPLE_ARRAY, + SAMPLER_CUBE_SHADOW = c.GL_SAMPLER_CUBE_SHADOW, + SAMPLER_BUFFER = c.GL_SAMPLER_BUFFER, + SAMPLER_2D_RECT = c.GL_SAMPLER_2D_RECT, + SAMPLER_2D_RECT_SHADOW = c.GL_SAMPLER_2D_RECT_SHADOW, + INT_SAMPLER_1D = c.GL_INT_SAMPLER_1D, + INT_SAMPLER_2D = c.GL_INT_SAMPLER_2D, + INT_SAMPLER_3D = c.GL_INT_SAMPLER_3D, + INT_SAMPLER_CUBE = c.GL_INT_SAMPLER_CUBE, + INT_SAMPLER_1D_ARRAY = c.GL_INT_SAMPLER_1D_ARRAY, + INT_SAMPLER_2D_ARRAY = c.GL_INT_SAMPLER_2D_ARRAY, + INT_SAMPLER_2D_MULTISAMPLE = c.GL_INT_SAMPLER_2D_MULTISAMPLE, + INT_SAMPLER_2D_MULTISAMPLE_ARRAY = c.GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, + INT_SAMPLER_BUFFER = c.GL_INT_SAMPLER_BUFFER, + INT_SAMPLER_2D_RECT = c.GL_INT_SAMPLER_2D_RECT, + UNSIGNED_INT_SAMPLER_1D = c.GL_UNSIGNED_INT_SAMPLER_1D, + UNSIGNED_INT_SAMPLER_2D = c.GL_UNSIGNED_INT_SAMPLER_2D, + UNSIGNED_INT_SAMPLER_3D = c.GL_UNSIGNED_INT_SAMPLER_3D, + UNSIGNED_INT_SAMPLER_CUBE = c.GL_UNSIGNED_INT_SAMPLER_CUBE, + UNSIGNED_INT_SAMPLER_1D_ARRAY = c.GL_UNSIGNED_INT_SAMPLER_1D_ARRAY, + UNSIGNED_INT_SAMPLER_2D_ARRAY = c.GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, + UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE = c.GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, + UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY = c.GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, + UNSIGNED_INT_SAMPLER_BUFFER = c.GL_UNSIGNED_INT_SAMPLER_BUFFER, + UNSIGNED_INT_SAMPLER_2D_RECT = c.GL_UNSIGNED_INT_SAMPLER_2D_RECT, +}; + +const UniformValue = union(UniformType) { + FLOAT: f32, + FLOAT_VEC2: [2]f32, + FLOAT_VEC3: [3]f32, + FLOAT_VEC4: [4]f32, + DOUBLE: f64, + DOUBLE_VEC2: [2]f64, + DOUBLE_VEC3: [3]f64, + DOUBLE_VEC4: [4]f64, + INT: c_int, // i32 but bug + INT_VEC2: [2]c_int, + INT_VEC3: [3]c_int, + INT_VEC4: [4]c_int, + UNSIGNED_INT: c_uint, + UNSIGNED_INT_VEC2: [2]c_uint, + UNSIGNED_INT_VEC3: [3]c_uint, + UNSIGNED_INT_VEC4: [4]c_uint, + BOOL: c_uint, + BOOL_VEC2: [2]c_uint, + BOOL_VEC3: [3]c_uint, + BOOL_VEC4: [4]c_uint, + FLOAT_MAT2: [2 * 2]f32, + FLOAT_MAT3: [3 * 3]f32, + FLOAT_MAT4: [4 * 4]f32, + FLOAT_MAT2x3: [2 * 3]f32, + FLOAT_MAT2x4: [2 * 4]f32, + FLOAT_MAT3x2: [3 * 2]f32, + FLOAT_MAT3x4: [3 * 4]f32, + FLOAT_MAT4x2: [4 * 2]f32, + FLOAT_MAT4x3: [4 * 3]f32, + DOUBLE_MAT2: [2 * 2]f64, + DOUBLE_MAT3: [3 * 3]f64, + DOUBLE_MAT4: [4 * 4]f64, + DOUBLE_MAT2x3: [2 * 3]f64, + DOUBLE_MAT2x4: [2 * 4]f64, + DOUBLE_MAT3x2: [3 * 2]f64, + DOUBLE_MAT3x4: [3 * 4]f64, + DOUBLE_MAT4x2: [4 * 2]f64, + DOUBLE_MAT4x3: [4 * 3]f64, + SAMPLER_1D: c_int, + SAMPLER_2D: c_int, + SAMPLER_3D: c_int, + SAMPLER_CUBE: c_int, + SAMPLER_1D_SHADOW: c_int, + SAMPLER_2D_SHADOW: c_int, + SAMPLER_1D_ARRAY: c_int, + SAMPLER_2D_ARRAY: c_int, + SAMPLER_1D_ARRAY_SHADOW: c_int, + SAMPLER_2D_ARRAY_SHADOW: c_int, + SAMPLER_2D_MULTISAMPLE: c_int, + SAMPLER_2D_MULTISAMPLE_ARRAY: c_int, + SAMPLER_CUBE_SHADOW: c_int, + SAMPLER_BUFFER: c_int, + SAMPLER_2D_RECT: c_int, + SAMPLER_2D_RECT_SHADOW: c_int, + INT_SAMPLER_1D: c_int, + INT_SAMPLER_2D: c_int, + INT_SAMPLER_3D: c_int, + INT_SAMPLER_CUBE: c_int, + INT_SAMPLER_1D_ARRAY: c_int, + INT_SAMPLER_2D_ARRAY: c_int, + INT_SAMPLER_2D_MULTISAMPLE: c_int, + INT_SAMPLER_2D_MULTISAMPLE_ARRAY: c_int, + INT_SAMPLER_BUFFER: c_int, + INT_SAMPLER_2D_RECT: c_int, + UNSIGNED_INT_SAMPLER_1D: c_int, + UNSIGNED_INT_SAMPLER_2D: c_int, + UNSIGNED_INT_SAMPLER_3D: c_int, + UNSIGNED_INT_SAMPLER_CUBE: c_int, + UNSIGNED_INT_SAMPLER_1D_ARRAY: c_int, + UNSIGNED_INT_SAMPLER_2D_ARRAY: c_int, + UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: c_int, + UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: c_int, + UNSIGNED_INT_SAMPLER_BUFFER: c_int, + UNSIGNED_INT_SAMPLER_2D_RECT: c_int, + + pub fn init(utype: UniformType) UniformValue { + inline for (@typeInfo(UniformType).Enum.fields) |field| { + if (@intToEnum(UniformType, field.value) == utype) + return @unionInit(UniformValue, field.name, undefined); + } + + unreachable; + } +}; + +const CachedUniform = struct { + value: UniformValue, + location: c.GLint, + + pub fn init(shader: ShaderProgram, name: [*]const u8) !CachedUniform { + var index: c.GLuint = undefined; + + c.glGetUniformIndices(shader.program_id, 1, &name, &index); + if (index == c.GL_INVALID_INDEX) + return error.invalidUniform; + + var utype: c.GLint = undefined; + c.glGetActiveUniformsiv(shader.program_id, 1, &index, c.GL_UNIFORM_TYPE, &utype); + + var self = CachedUniform{ + .value = UniformValue.init(@intToEnum(UniformType, utype)), + .location = try shader.uniformLocation(name), + }; + + self.getShaderValue(shader); + return self; + } + + // zig fmt: off + pub fn setShaderValue(self: *const CachedUniform, shader: ShaderProgram) void { + const program = shader.program_id; + const location = self.location; + + switch (self.value) { + .FLOAT => |*value| c.glProgramUniform1fv(program, location, 1, value), + .FLOAT_VEC2 => |*value| c.glProgramUniform2fv(program, location, 1, value), + .FLOAT_VEC3 => |*value| c.glProgramUniform3fv(program, location, 1, value), + .FLOAT_VEC4 => |*value| c.glProgramUniform4fv(program, location, 1, value), + .DOUBLE => |*value| c.glProgramUniform1dv(program, location, 1, value), + .DOUBLE_VEC2 => |*value| c.glProgramUniform1dv(program, location, 1, value), + .DOUBLE_VEC3 => |*value| c.glProgramUniform2dv(program, location, 1, value), + .DOUBLE_VEC4 => |*value| c.glProgramUniform3dv(program, location, 1, value), + .INT => |*value| c.glProgramUniform1iv(program, location, 1, value), + .INT_VEC2 => |*value| c.glProgramUniform2iv(program, location, 1, value), + .INT_VEC3 => |*value| c.glProgramUniform3iv(program, location, 1, value), + .INT_VEC4 => |*value| c.glProgramUniform4iv(program, location, 1, value), + .UNSIGNED_INT => |*value| c.glProgramUniform1uiv(program, location, 1, value), + .UNSIGNED_INT_VEC2 => |*value| c.glProgramUniform2uiv(program, location, 1, value), + .UNSIGNED_INT_VEC3 => |*value| c.glProgramUniform3uiv(program, location, 1, value), + .UNSIGNED_INT_VEC4 => |*value| c.glProgramUniform4uiv(program, location, 1, value), + .BOOL => |*value| c.glProgramUniform1uiv(program, location, 1, value), + .BOOL_VEC2 => |*value| c.glProgramUniform2uiv(program, location, 1, value), + .BOOL_VEC3 => |*value| c.glProgramUniform3uiv(program, location, 1, value), + .BOOL_VEC4 => |*value| c.glProgramUniform4uiv(program, location, 1, value), + .FLOAT_MAT2 => |*value| c.glProgramUniformMatrix2fv(program, location, 1, c.GL_FALSE, value), + .FLOAT_MAT3 => |*value| c.glProgramUniformMatrix3fv(program, location, 1, c.GL_FALSE, value), + .FLOAT_MAT4 => |*value| c.glProgramUniformMatrix4fv(program, location, 1, c.GL_FALSE, value), + .FLOAT_MAT2x3 => |*value| c.glProgramUniformMatrix2x3fv(program, location, 1, c.GL_FALSE, value), + .FLOAT_MAT2x4 => |*value| c.glProgramUniformMatrix2x4fv(program, location, 1, c.GL_FALSE, value), + .FLOAT_MAT3x2 => |*value| c.glProgramUniformMatrix3x2fv(program, location, 1, c.GL_FALSE, value), + .FLOAT_MAT3x4 => |*value| c.glProgramUniformMatrix3x4fv(program, location, 1, c.GL_FALSE, value), + .FLOAT_MAT4x2 => |*value| c.glProgramUniformMatrix4x2fv(program, location, 1, c.GL_FALSE, value), + .FLOAT_MAT4x3 => |*value| c.glProgramUniformMatrix4x3fv(program, location, 1, c.GL_FALSE, value), + .DOUBLE_MAT2 => |*value| c.glProgramUniformMatrix2dv(program, location, 1, c.GL_FALSE, value), + .DOUBLE_MAT3 => |*value| c.glProgramUniformMatrix3dv(program, location, 1, c.GL_FALSE, value), + .DOUBLE_MAT4 => |*value| c.glProgramUniformMatrix4dv(program, location, 1, c.GL_FALSE, value), + .DOUBLE_MAT2x3 => |*value| c.glProgramUniformMatrix2x3dv(program, location, 1, c.GL_FALSE, value), + .DOUBLE_MAT2x4 => |*value| c.glProgramUniformMatrix2x4dv(program, location, 1, c.GL_FALSE, value), + .DOUBLE_MAT3x2 => |*value| c.glProgramUniformMatrix3x2dv(program, location, 1, c.GL_FALSE, value), + .DOUBLE_MAT3x4 => |*value| c.glProgramUniformMatrix3x4dv(program, location, 1, c.GL_FALSE, value), + .DOUBLE_MAT4x2 => |*value| c.glProgramUniformMatrix4x2dv(program, location, 1, c.GL_FALSE, value), + .DOUBLE_MAT4x3 => |*value| c.glProgramUniformMatrix4x3dv(program, location, 1, c.GL_FALSE, value), + .SAMPLER_1D, .SAMPLER_2D, .SAMPLER_3D, .SAMPLER_CUBE, .SAMPLER_1D_SHADOW, .SAMPLER_2D_SHADOW, .SAMPLER_1D_ARRAY, .SAMPLER_2D_ARRAY, .SAMPLER_1D_ARRAY_SHADOW, .SAMPLER_2D_ARRAY_SHADOW, .SAMPLER_2D_MULTISAMPLE, .SAMPLER_2D_MULTISAMPLE_ARRAY, .SAMPLER_CUBE_SHADOW, .SAMPLER_BUFFER, .SAMPLER_2D_RECT, .SAMPLER_2D_RECT_SHADOW, .INT_SAMPLER_1D, .INT_SAMPLER_2D, .INT_SAMPLER_3D, .INT_SAMPLER_CUBE, .INT_SAMPLER_1D_ARRAY, .INT_SAMPLER_2D_ARRAY, .INT_SAMPLER_2D_MULTISAMPLE, .INT_SAMPLER_2D_MULTISAMPLE_ARRAY, .INT_SAMPLER_BUFFER, .INT_SAMPLER_2D_RECT, .UNSIGNED_INT_SAMPLER_1D, .UNSIGNED_INT_SAMPLER_2D, .UNSIGNED_INT_SAMPLER_3D, .UNSIGNED_INT_SAMPLER_CUBE, .UNSIGNED_INT_SAMPLER_1D_ARRAY, .UNSIGNED_INT_SAMPLER_2D_ARRAY, .UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, .UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, .UNSIGNED_INT_SAMPLER_BUFFER, .UNSIGNED_INT_SAMPLER_2D_RECT => |value| c.glProgramUniform1i(program, location, value), + else => unreachable, + } + } + + pub fn getShaderValue(self: *CachedUniform, shader: ShaderProgram) void { + const program = shader.program_id; + const location = self.location; + + switch (self.value) { + .FLOAT => |*value| c.glGetnUniformfv(program, location, @sizeOf(@TypeOf(value.*)), value), + .FLOAT_VEC2 => |*value| c.glGetnUniformfv(program, location, @sizeOf(@TypeOf(value.*)), value), + .FLOAT_VEC3 => |*value| c.glGetnUniformfv(program, location, @sizeOf(@TypeOf(value.*)), value), + .FLOAT_VEC4 => |*value| c.glGetnUniformfv(program, location, @sizeOf(@TypeOf(value.*)), value), + .DOUBLE => |*value| c.glGetnUniformdv(program, location, @sizeOf(@TypeOf(value.*)), value), + .DOUBLE_VEC2 => |*value| c.glGetnUniformdv(program, location, @sizeOf(@TypeOf(value.*)), value), + .DOUBLE_VEC3 => |*value| c.glGetnUniformdv(program, location, @sizeOf(@TypeOf(value.*)), value), + .DOUBLE_VEC4 => |*value| c.glGetnUniformdv(program, location, @sizeOf(@TypeOf(value.*)), value), + .INT => |*value| c.glGetnUniformiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .INT_VEC2 => |*value| c.glGetnUniformiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .INT_VEC3 => |*value| c.glGetnUniformiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .INT_VEC4 => |*value| c.glGetnUniformiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .UNSIGNED_INT => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .UNSIGNED_INT_VEC2 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .UNSIGNED_INT_VEC3 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .UNSIGNED_INT_VEC4 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .BOOL => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .BOOL_VEC2 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .BOOL_VEC3 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .BOOL_VEC4 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value), + .FLOAT_MAT2 => |*value| c.glGetUniformfv(program, location, value), + .FLOAT_MAT3 => |*value| c.glGetUniformfv(program, location, value), + .FLOAT_MAT4 => |*value| c.glGetUniformfv(program, location, value), + .FLOAT_MAT2x3 => |*value| c.glGetUniformfv(program, location, value), + .FLOAT_MAT2x4 => |*value| c.glGetUniformfv(program, location, value), + .FLOAT_MAT3x2 => |*value| c.glGetUniformfv(program, location, value), + .FLOAT_MAT3x4 => |*value| c.glGetUniformfv(program, location, value), + .FLOAT_MAT4x2 => |*value| c.glGetUniformfv(program, location, value), + .FLOAT_MAT4x3 => |*value| c.glGetUniformfv(program, location, value), + .DOUBLE_MAT2 => |*value| c.glGetUniformdv(program, location, value), + .DOUBLE_MAT3 => |*value| c.glGetUniformdv(program, location, value), + .DOUBLE_MAT4 => |*value| c.glGetUniformdv(program, location, value), + .DOUBLE_MAT2x3 => |*value| c.glGetUniformdv(program, location, value), + .DOUBLE_MAT2x4 => |*value| c.glGetUniformdv(program, location, value), + .DOUBLE_MAT3x2 => |*value| c.glGetUniformdv(program, location, value), + .DOUBLE_MAT3x4 => |*value| c.glGetUniformdv(program, location, value), + .DOUBLE_MAT4x2 => |*value| c.glGetUniformdv(program, location, value), + .DOUBLE_MAT4x3 => |*value| c.glGetUniformdv(program, location, value), + .SAMPLER_1D, .SAMPLER_2D, .SAMPLER_3D, .SAMPLER_CUBE, .SAMPLER_1D_SHADOW, .SAMPLER_2D_SHADOW, .SAMPLER_1D_ARRAY, .SAMPLER_2D_ARRAY, .SAMPLER_1D_ARRAY_SHADOW, .SAMPLER_2D_ARRAY_SHADOW, .SAMPLER_2D_MULTISAMPLE, .SAMPLER_2D_MULTISAMPLE_ARRAY, .SAMPLER_CUBE_SHADOW, .SAMPLER_BUFFER, .SAMPLER_2D_RECT, .SAMPLER_2D_RECT_SHADOW, .INT_SAMPLER_1D, .INT_SAMPLER_2D, .INT_SAMPLER_3D, .INT_SAMPLER_CUBE, .INT_SAMPLER_1D_ARRAY, .INT_SAMPLER_2D_ARRAY, .INT_SAMPLER_2D_MULTISAMPLE, .INT_SAMPLER_2D_MULTISAMPLE_ARRAY, .INT_SAMPLER_BUFFER, .INT_SAMPLER_2D_RECT, .UNSIGNED_INT_SAMPLER_1D, .UNSIGNED_INT_SAMPLER_2D, .UNSIGNED_INT_SAMPLER_3D, .UNSIGNED_INT_SAMPLER_CUBE, .UNSIGNED_INT_SAMPLER_1D_ARRAY, .UNSIGNED_INT_SAMPLER_2D_ARRAY, .UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, .UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, .UNSIGNED_INT_SAMPLER_BUFFER, .UNSIGNED_INT_SAMPLER_2D_RECT => |*value| c.glGetnUniformiv(program, location, @sizeOf(@TypeOf(value.*)), value), + else => unreachable, + } + } + // zig fmt: on +}; pub const ShaderProgram = struct { program_id: c.GLuint, @@ -27,30 +313,6 @@ pub const ShaderProgram = struct { return id; } - pub fn setUniform1i(self: ShaderProgram, uniform_id: c.GLint, value: c_int) void { - c.glUniform1i(uniform_id, value); - } - - pub fn setUniform1f(self: ShaderProgram, uniform_id: c.GLint, value: f32) void { - c.glUniform1f(uniform_id, value); - } - - pub fn setUniform2f(self: ShaderProgram, uniform_id: c.GLint, x: f32, y: f32) void { - c.glUniform2f(uniform_id, x, y); - } - - pub fn setUniform3f(self: ShaderProgram, uniform_id: c.GLint, x: f32, y: f32, z: f32) void { - c.glUniform3f(uniform_id, x, y, z); - } - - pub fn setUniform4f(self: ShaderProgram, uniform_id: c.GLint, x: f32, y: f32, z: f32, w: f32) void { - c.glUniform4f(uniform_id, x, y, z, w); - } - - pub fn setUniformMat4x4(self: ShaderProgram, uniform_id: c.GLint, value: [4][4]f32) void { - c.glUniformMatrix4fv(uniform_id, 1, c.GL_FALSE, &value[0][0]); - } - pub fn create(vert_source: []const u8, frag_source: []const u8) !ShaderProgram { var self: ShaderProgram = undefined; @@ -92,6 +354,69 @@ pub const ShaderProgram = struct { } }; +pub const UniformCache = struct { + uniforms: std.AutoHashMap([*]const u8, CachedUniform), + shader: *ShaderProgram, + + pub fn init(allocator: *std.mem.Allocator, shader: *ShaderProgram) UniformCache { + return UniformCache{ + .uniforms = std.AutoHashMap([*]const u8, CachedUniform).init(allocator), + .shader = shader, + }; + } + + pub fn deinit(self: *UniformCache) void { + self.uniforms.deinit(); + } + + pub fn refresh(self: *UniformCache) !void { + var uniform_count: c.GLint = undefined; + c.glGetProgramiv(self.shader.program_id, c.GL_ACTIVE_UNIFORMS, &uniform_count); + + const count = self.uniforms.count(); + var existing_names = try c_allocator.alloc([*]const u8, count); + defer c_allocator.free(existing_names); + var existing_indices = try c_allocator.alloc(c.GLuint, count); + defer c_allocator.free(existing_indices); + + { + var it = self.uniforms.iterator(); + var i: usize = 0; + while (it.next()) |entry| { + existing_names[i] = entry.key; + i += 1; + } + } + + c.glGetUniformIndices(self.shader.program_id, @intCast(c.GLsizei, count), existing_names.ptr, existing_indices.ptr); + + for (existing_indices) |index, i| { + const name = existing_names[i]; + if (index == c.GL_INVALID_INDEX) { + _ = self.uniforms.remove(name); + // @TODO: remove OSC link + } else { + var uniform = self.uniforms.get(name).?.value; + uniform.location = self.shader.uniformLocation(name) catch unreachable; + uniform.setShaderValue(self.shader.*); + } + } + } + + pub fn get(self: *UniformCache, name: [*]const u8) !?*CachedUniform { + var result = try self.uniforms.getOrPut(name); + if (!result.found_existing) { + result.kv.value = CachedUniform.init(self.shader.*, name) catch { + _ = self.uniforms.remove(name); + return null; + }; + // @TODO: add OSC link + } + + return &result.kv.value; + } +}; + fn initGlShader(source: []const u8, name: []const u8, kind: c.GLenum) !c.GLuint { const shader_id = c.glCreateShader(kind); errdefer c.glDeleteShader(shader_id); @@ -179,7 +504,7 @@ pub const VertexObject = struct { c.glGenBuffers(1, &self.buffer_id); c.glBindBuffer(c.GL_ARRAY_BUFFER, self.buffer_id); - c.glBufferData(c.GL_ARRAY_BUFFER, @intCast(c_long, @sizeOf(T) * vertices.len), @ptrCast(*const c_void, &vertices[0]), c.GL_STATIC_DRAW); + c.glBufferData(c.GL_ARRAY_BUFFER, @intCast(c_long, @sizeOf(T) * vertices.len), @ptrCast(*const c_void, vertices.ptr), c.GL_STATIC_DRAW); return self; } @@ -191,17 +516,16 @@ pub const VertexObject = struct { }; pub const Constants = struct { - textureShader: ShaderProgram, - normalizedQuad: VertexObject, + texture_shader: ShaderProgram, + normalized_quad: VertexObject, main_window: *c.GLFWwindow, + aspect: f32, + config: *cfg.Config, - pub fn create(main_window: *c.GLFWwindow) !Constants { - var self: Constants = undefined; - + pub fn create(main_window: *c.GLFWwindow, config: *cfg.Config) !Constants { c.glfwMakeContextCurrent(main_window); - self.main_window = main_window; - self.textureShader = try ShaderProgram.create( + const shader = try ShaderProgram.create( \\#version 330 core \\ \\layout(location = 0) in vec2 position; @@ -230,13 +554,18 @@ pub const Constants = struct { 1.0, -1.0, 1.0, 1.0, }; - self.normalizedQuad = VertexObject.create(f32, vertices[0..], 2); - return self; + return Constants{ + .main_window = main_window, + .texture_shader = shader, + .normalized_quad = VertexObject.create(f32, vertices[0..], 2), + .config = config, + .aspect = @intToFloat(f32, config.width) / @intToFloat(f32, config.height), + }; } pub fn destroy(self: *Constants) void { - self.normalizedQuad.destroy(); - self.textureShader.destroy(); + self.normalized_quad.destroy(); + self.texture_shader.destroy(); } }; |
