diff options
| author | s-ol <s+removethis@s-ol.nu> | 2023-11-03 14:56:32 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2023-11-03 15:18:38 +0000 |
| commit | ab68536ec557de90ff074e93f78f608d47d8609a (patch) | |
| tree | fbc659499530898e7274f96cfc2e872956c9eb5e /src | |
| parent | allow indexing uniforms, fix bug (diff) | |
| download | glsl-view-ab68536ec557de90ff074e93f78f608d47d8609a.tar.gz glsl-view-ab68536ec557de90ff074e93f78f608d47d8609a.zip | |
only restore uniform values if type unchanged
Diffstat (limited to 'src')
| -rw-r--r-- | src/gl.zig | 101 |
1 files changed, 51 insertions, 50 deletions
@@ -3,6 +3,13 @@ const c_allocator = @import("std").heap.c_allocator; const c = @import("c.zig"); const cfg = @import("config.zig"); +fn tmpZ(str: []const u8) ![:0]const u8 { + const state = struct { + var buf: [256]u8 = undefined; + }; + return try std.fmt.bufPrintZ(state.buf[0..], "{s}", .{str}); +} + const UniformType = enum(c.GLint) { FLOAT = c.GL_FLOAT, FLOAT_VEC2 = c.GL_FLOAT_VEC2, @@ -194,10 +201,12 @@ pub const CachedUniform = struct { value: UniformValue, location: c.GLint, - pub fn init(allocator: std.mem.Allocator, shader: ShaderProgram, name: [*]const u8) !CachedUniform { + pub fn init(allocator: std.mem.Allocator, shader: ShaderProgram, name: []const u8) !CachedUniform { var index: c.GLuint = undefined; - c.glGetUniformIndices(shader.program_id, 1, &name, &index); + const nameZ = try tmpZ(name); + + c.glGetUniformIndices(shader.program_id, 1, &nameZ.ptr, &index); if (index == c.GL_INVALID_INDEX) return error.invalidUniform; @@ -206,7 +215,7 @@ pub const CachedUniform = struct { switch (@as(UniformType, @enumFromInt(_utype))) { inline else => |utype| { - const location = try shader.uniformLocation(name); + const location = try shader.uniformLocation(nameZ); const value = try UniformValue.init(allocator, utype); errdefer value.deinit(allocator); @@ -219,6 +228,17 @@ pub const CachedUniform = struct { self.value.deinit(allocator); } + pub fn tryCopy(self: *CachedUniform, from: CachedUniform) bool { + if (@as(UniformType, self.value) != from.value) return false; + + switch (self.value) { + inline else => |*val, tag| { + val.*.* = @field(from.value, @tagName(tag)).*; + }, + } + return true; + } + // zig fmt: off pub fn setShaderValue(self: *const CachedUniform, shader: ShaderProgram) void { const program = shader.program_id; @@ -325,10 +345,11 @@ pub const ShaderProgram = struct { c.glUseProgram(self.program_id); } - pub fn uniformLocation(self: ShaderProgram, name: [*]const u8) !c.GLint { - const id = c.glGetUniformLocation(self.program_id, name); + pub fn uniformLocation(self: ShaderProgram, nameZ: [:0]const u8) !c.GLint { + const id = c.glGetUniformLocation(self.program_id, nameZ); if (id == -1) return error.invalidUniform; + return id; } @@ -396,57 +417,14 @@ pub const UniformCache = struct { 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_names_c = try c_allocator.alloc([*]const u8, count); - defer c_allocator.free(existing_names_c); - 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_ptr.*; - existing_names_c[i] = entry.key_ptr.*.ptr; - i += 1; - } - } - - c.glGetUniformIndices( - self.shader.program_id, - @as(c.GLsizei, @intCast(count)), - existing_names_c.ptr, - existing_indices.ptr, - ); - - for (existing_indices, 0..) |index, i| { - const name = existing_names[i]; - if (index == c.GL_INVALID_INDEX) { - if (self.uniforms.remove(name)) { - self.allocator.free(name); - } - } else { - var uniform = self.uniforms.get(name).?; - uniform.location = self.shader.uniformLocation(name.ptr) catch unreachable; - uniform.setShaderValue(self.shader.*); - } - } - } - - pub fn get(self: *UniformCache, name: [:0]u8) !?*CachedUniform { + pub fn get(self: *UniformCache, name: []const u8) !?*CachedUniform { var getValue = false; if (!self.uniforms.contains(name)) { const cloned_name = try self.allocator.dupe(u8, name); errdefer self.allocator.free(cloned_name); - const uniform = CachedUniform.init(self.allocator, self.shader.*, name.ptr) catch return null; + const uniform = CachedUniform.init(self.allocator, self.shader.*, name) catch return null; errdefer uniform.deinit(self.allocator); try self.uniforms.put(cloned_name, uniform); @@ -460,6 +438,29 @@ pub const UniformCache = struct { return null; } + + pub fn refresh(self: *UniformCache) !void { + var old_uniforms = self.uniforms.move(); + defer { + var it = old_uniforms.iterator(); + while (it.next()) |entry| { + self.allocator.free(entry.key_ptr.*); + entry.value_ptr.deinit(self.allocator); + } + old_uniforms.deinit(); + } + + { + var it = old_uniforms.iterator(); + while (it.next()) |old_entry| { + if (try self.get(old_entry.key_ptr.*)) |uniform| { + if (uniform.tryCopy(old_entry.value_ptr.*)) { + uniform.setShaderValue(self.shader.*); + } + } + } + } + } }; fn initGlShader(source: []const u8, name: []const u8, kind: c.GLenum) !c.GLuint { |
