diff --git a/pkg/opengl/Buffer.zig b/pkg/opengl/Buffer.zig index 6093429588..3dbfe21ab6 100644 --- a/pkg/opengl/Buffer.zig +++ b/pkg/opengl/Buffer.zig @@ -226,7 +226,6 @@ pub const Target = enum(c_uint) { array = c.GL_ARRAY_BUFFER, element_array = c.GL_ELEMENT_ARRAY_BUFFER, uniform = c.GL_UNIFORM_BUFFER, - storage = c.GL_SHADER_STORAGE_BUFFER, _, }; diff --git a/pkg/opengl/Texture.zig b/pkg/opengl/Texture.zig index 03e7948559..d04107a9f7 100644 --- a/pkg/opengl/Texture.zig +++ b/pkg/opengl/Texture.zig @@ -70,6 +70,7 @@ pub const InternalFormat = enum(c_int) { red = c.GL_RED, rgb = c.GL_RGB8, rgba = c.GL_RGBA8, + r32ui = c.GL_R32UI, srgb = c.GL_SRGB8, srgba = c.GL_SRGB8_ALPHA8, @@ -147,6 +148,19 @@ pub const Binding = struct { try errors.getError(); } + pub fn buffer( + b: Binding, + internal_format: InternalFormat, + id: c.GLuint, + ) errors.Error!void { + glad.context.TexBuffer.?( + @intFromEnum(b.target), + @intCast(@intFromEnum(internal_format)), + id, + ); + try errors.getError(); + } + pub fn image2D( b: Binding, level: c.GLint, diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 6c7432d210..ff0f837733 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -275,7 +275,6 @@ pub inline fn bufferOptions(self: Metal) bufferpkg.Options { }; } -pub const instanceBufferOptions = bufferOptions; pub const uniformBufferOptions = bufferOptions; pub const fgBufferOptions = bufferOptions; pub const bgBufferOptions = bufferOptions; diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index 4b01da0c5b..48b7157030 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -344,7 +344,6 @@ pub inline fn bufferOptions(self: OpenGL) bufferpkg.Options { }; } -pub const instanceBufferOptions = bufferOptions; pub const uniformBufferOptions = bufferOptions; pub const fgBufferOptions = bufferOptions; pub const bgBufferOptions = bufferOptions; diff --git a/src/renderer/generic.zig b/src/renderer/generic.zig index f57339893f..5630411240 100644 --- a/src/renderer/generic.zig +++ b/src/renderer/generic.zig @@ -1619,7 +1619,6 @@ pub fn Renderer(comptime GraphicsAPI: type) type { pass.step(.{ .pipeline = self.shaders.pipelines.bg_color, .uniforms = frame.uniforms.buffer, - .buffers = &.{ null, frame.cells_bg.buffer }, .draw = .{ .type = .triangle, .vertex_count = 3 }, }); } diff --git a/src/renderer/opengl/Pipeline.zig b/src/renderer/opengl/Pipeline.zig index 2469f45bc2..a9f7222636 100644 --- a/src/renderer/opengl/Pipeline.zig +++ b/src/renderer/opengl/Pipeline.zig @@ -20,6 +20,14 @@ pub const Options = struct { /// Whether to enable blending. blending_enabled: bool = true, + /// Texture buffer binding for `buffers[1]`. + buffer_texture: ?BufferTexture = null, + + pub const BufferTexture = struct { + unit: gl.c.GLuint, + internal_format: gl.Texture.InternalFormat, + }; + pub const StepFunction = enum { constant, per_vertex, @@ -27,6 +35,12 @@ pub const Options = struct { }; }; +const BufferTextureBinding = struct { + texture: gl.Texture, + unit: gl.c.GLuint, + internal_format: gl.Texture.InternalFormat, +}; + program: gl.Program, fbo: gl.Framebuffer, @@ -37,6 +51,8 @@ stride: usize, blending_enabled: bool, +buffer_texture: ?BufferTextureBinding = null, + pub fn init(comptime VertexAttributes: ?type, opts: Options) !Self { // Load and compile our shaders. const program = try gl.Program.createVF( @@ -60,16 +76,32 @@ pub fn init(comptime VertexAttributes: ?type, opts: Options) !Self { if (VertexAttributes) |VA| try autoAttribute(VA, vaobind, opts.step_fn); + const buffer_texture: ?BufferTextureBinding = if (opts.buffer_texture) |cfg| texture: { + const texture = try gl.Texture.create(); + errdefer texture.destroy(); + + break :texture .{ + .texture = texture, + .unit = cfg.unit, + .internal_format = cfg.internal_format, + }; + } else null; + return .{ .program = program, .fbo = fbo, .vao = vao, .stride = if (VertexAttributes) |VA| @sizeOf(VA) else 0, .blending_enabled = opts.blending_enabled, + .buffer_texture = buffer_texture, }; } pub fn deinit(self: *const Self) void { + if (self.buffer_texture) |tbo| { + tbo.texture.destroy(); + } + self.program.destroy(); } diff --git a/src/renderer/opengl/RenderPass.zig b/src/renderer/opengl/RenderPass.zig index 1806649420..063bceddfc 100644 --- a/src/renderer/opengl/RenderPass.zig +++ b/src/renderer/opengl/RenderPass.zig @@ -9,7 +9,6 @@ const Sampler = @import("Sampler.zig"); const Target = @import("Target.zig"); const Texture = @import("Texture.zig"); const Pipeline = @import("Pipeline.zig"); -const Buffer = @import("buffer.zig").Buffer; /// Options for beginning a render pass. pub const Options = struct { @@ -101,13 +100,19 @@ pub fn step(self: *Self, s: Step) void { _ = tex.texture.bind(tex.target) catch return; }; + // Bind `buffers[1]` as a texture buffer if this pipeline uses one. + if (s.pipeline.buffer_texture) |tbo| { + gl.Texture.active(tbo.unit) catch return; + const tbind = tbo.texture.bind(.Buffer) catch return; + tbind.buffer(tbo.internal_format, s.buffers[1].?.id) catch return; + } + // Bind relevant samplers. for (s.samplers, 0..) |s_, i| if (s_) |sampler| { _ = sampler.sampler.bind(@intCast(i)) catch return; }; - // Bind 0th buffer as the vertex buffer, - // and bind the rest as storage buffers. + // Bind the 0th buffer as the vertex buffer. if (s.buffers.len > 0) { if (s.buffers[0]) |vbo| vaobind.bindVertexBuffer( 0, @@ -115,10 +120,6 @@ pub fn step(self: *Self, s: Step) void { 0, @intCast(s.pipeline.stride), ) catch return; - - for (s.buffers[1..], 1..) |b, i| if (b) |buf| { - _ = buf.bindBase(.storage, @intCast(i)) catch return; - }; } if (s.pipeline.blending_enabled) { diff --git a/src/renderer/opengl/shaders.zig b/src/renderer/opengl/shaders.zig index 68c1f36a34..da58e1e799 100644 --- a/src/renderer/opengl/shaders.zig +++ b/src/renderer/opengl/shaders.zig @@ -18,6 +18,10 @@ const pipeline_descs: []const struct { [:0]const u8, PipelineDescription } = .vertex_fn = loadShaderCode("../shaders/glsl/full_screen.v.glsl"), .fragment_fn = loadShaderCode("../shaders/glsl/cell_bg.f.glsl"), .blending_enabled = true, + .buffer_texture = .{ + .unit = 2, + .internal_format = .r32ui, + }, } }, .{ "cell_text", .{ .vertex_attributes = CellText, @@ -25,6 +29,10 @@ const pipeline_descs: []const struct { [:0]const u8, PipelineDescription } = .fragment_fn = loadShaderCode("../shaders/glsl/cell_text.f.glsl"), .step_fn = .per_instance, .blending_enabled = true, + .buffer_texture = .{ + .unit = 2, + .internal_format = .r32ui, + }, } }, .{ "image", .{ .vertex_attributes = Image, @@ -50,6 +58,7 @@ const PipelineDescription = struct { fragment_fn: [:0]const u8, step_fn: Pipeline.Options.StepFunction = .per_vertex, blending_enabled: bool = true, + buffer_texture: ?Pipeline.Options.BufferTexture = null, fn initPipeline(self: PipelineDescription) !Pipeline { return try .init(self.vertex_attributes, .{ @@ -57,6 +66,7 @@ const PipelineDescription = struct { .fragment_fn = self.fragment_fn, .step_fn = self.step_fn, .blending_enabled = self.blending_enabled, + .buffer_texture = self.buffer_texture, }); } }; @@ -81,7 +91,7 @@ const PipelineCollection = t: { } }); }; -/// This contains the state for the shaders used by the Metal renderer. +/// This contains the state for the shaders used by the OpenGL renderer. pub const Shaders = struct { /// Collection of available render pipelines. pipelines: PipelineCollection, diff --git a/src/renderer/shaders/glsl/cell_bg.f.glsl b/src/renderer/shaders/glsl/cell_bg.f.glsl index fa48c6736f..b2bec6da9a 100644 --- a/src/renderer/shaders/glsl/cell_bg.f.glsl +++ b/src/renderer/shaders/glsl/cell_bg.f.glsl @@ -6,9 +6,7 @@ layout(origin_upper_left) in vec4 gl_FragCoord; // Must declare this output for some versions of OpenGL. layout(location = 0) out vec4 out_FragColor; -layout(binding = 1, std430) readonly buffer bg_cells { - uint cells[]; -}; +layout(binding = 2) uniform usamplerBuffer cells; vec4 cell_bg() { uvec2 grid_size = unpack2u16(grid_size_packed_2u16); @@ -48,10 +46,11 @@ vec4 cell_bg() { } // Load the color for the cell. - vec4 cell_color = load_color( - unpack4u8(cells[grid_pos.y * grid_size.x + grid_pos.x]), - use_linear_blending - ); + uint cell = texelFetch( + cells, + grid_pos.y * int(grid_size.x) + grid_pos.x + ).r; + vec4 cell_color = load_color(unpack4u8(cell), use_linear_blending); return cell_color; } diff --git a/src/renderer/shaders/glsl/cell_text.v.glsl b/src/renderer/shaders/glsl/cell_text.v.glsl index 7e38e2f0c0..40a7c304a2 100644 --- a/src/renderer/shaders/glsl/cell_text.v.glsl +++ b/src/renderer/shaders/glsl/cell_text.v.glsl @@ -36,9 +36,7 @@ out CellTextVertexOut { vec2 tex_coord; } out_data; -layout(binding = 1, std430) readonly buffer bg_cells { - uint bg_colors[]; -}; +layout(binding = 2) uniform usamplerBuffer bg_colors; void main() { uvec2 grid_size = unpack2u16(grid_size_packed_2u16); @@ -116,10 +114,11 @@ void main() { // make it easier to handle minimum contrast calculations. out_data.color = load_color(color, true); // Get the BG color - out_data.bg_color = load_color( - unpack4u8(bg_colors[grid_pos.y * grid_size.x + grid_pos.x]), - true - ); + uint bg_color = texelFetch( + bg_colors, + int(grid_pos.y * grid_size.x + grid_pos.x) + ).r; + out_data.bg_color = load_color(unpack4u8(bg_color), true); // Blend it with the global bg color vec4 global_bg = load_color( unpack4u8(bg_color_packed_4u8),