From d3f0664da6f8306893290d5f19d9c7376c560232 Mon Sep 17 00:00:00 2001 From: sergeypdev Date: Thu, 15 Feb 2024 04:23:18 +0400 Subject: [PATCH] Almost working compressed textures --- assets/plane.obj | 8 +- assets/shaders/mesh.glsl | 4 +- build.zig | 14 +- src/AssetManager.zig | 117 +++++++++++++- src/game.zig | 20 ++- src/gen/asset_manifest.zig | 1 + src/gl.zig | 307 ++++++++++++++++++++++++++++++------- tools/asset_compiler.zig | 3 +- 8 files changed, 403 insertions(+), 71 deletions(-) diff --git a/assets/plane.obj b/assets/plane.obj index b362916..b03a8a3 100644 --- a/assets/plane.obj +++ b/assets/plane.obj @@ -7,9 +7,9 @@ v 1.000000 0.000000 1.000000 v -1.000000 0.000000 -1.000000 v 1.000000 0.000000 -1.000000 vn -0.0000 1.0000 -0.0000 -vt 0.000000 0.000000 -vt 1.000000 0.000000 -vt 1.000000 1.000000 -vt 0.000000 1.000000 +vt 0.999900 0.999900 +vt 0.000100 0.999900 +vt 0.000100 0.000100 +vt 0.999900 0.000100 s 0 f 1/1/1 2/2/1 4/3/1 3/4/1 diff --git a/assets/shaders/mesh.glsl b/assets/shaders/mesh.glsl index e16aa2b..53fca73 100644 --- a/assets/shaders/mesh.glsl +++ b/assets/shaders/mesh.glsl @@ -1,3 +1,4 @@ +#extension GL_ARB_bindless_texture : enable // Keep in sync with cpu #define MAX_POINT_LIGHTS 8 @@ -21,6 +22,7 @@ layout(std140, binding = 1) uniform Lights { // Uniforms layout(location = 1) uniform mat4 model; layout(location = 2) uniform vec3 color; +layout(location = 3, bindless_sampler) uniform sampler2D diffuse; // Input, output blocks @@ -50,7 +52,7 @@ void main() { out vec4 FragColor; void main() { - vec3 diffuseColor = color; + vec3 diffuseColor = texture(diffuse, VertexOut.uv).rgb; vec3 finalColor = vec3(0); for (int i = 0; i < lights_count; i++) { diff --git a/build.zig b/build.zig index 4236584..98debe9 100644 --- a/build.zig +++ b/build.zig @@ -22,6 +22,13 @@ pub fn build(b: *Build) void { "Prioritize performance, safety, or binary size for build time tools", ) orelse .Debug; + const basisu_optimize = b.option(std.builtin.OptimizeMode, "basisu_optimize", "Optimization level for basisu. ReleaseSafe or faster is recommented, otherwise it's slow or can crash due to ubsan.") orelse .ReleaseFast; + + const basisu_dep = b.dependency("mach-basisu", .{ + .target = target, + .optimize = basisu_optimize, + }); + const zalgebra_dep = b.dependency("zalgebra", .{}); const assets_mod = b.addModule("assets", .{ .root_source_file = .{ .path = "src/assets/root.zig" } }); @@ -31,7 +38,7 @@ pub fn build(b: *Build) void { const assets_step = b.step("assets", "Build and install assets"); b.getInstallStep().dependOn(assets_step); - const assetc = buildAssetCompiler(b, assets_step, buildOptimize); + const assetc = buildAssetCompiler(b, basisu_optimize, assets_step, buildOptimize); assetc.root_module.addImport("assets", assets_mod); assetc.root_module.addImport("asset_manifest", asset_manifest_mod); @@ -61,6 +68,8 @@ pub fn build(b: *Build) void { l.root_module.addImport("zalgebra", zalgebra_dep.module("zalgebra")); l.root_module.addImport("assets", assets_mod); l.root_module.addImport("asset_manifest", asset_manifest_mod); + l.linkLibrary(basisu_dep.artifact("mach-basisu")); + l.root_module.addImport("mach-basisu", basisu_dep.module("mach-basisu")); } const install_lib = b.addInstallArtifact(lib, .{ .dest_dir = .{ .override = .prefix } }); @@ -362,7 +371,7 @@ fn writeAssetManifest( return manifest_path; } -fn buildAssetCompiler(b: *Build, assets_step: *Step, optimize: std.builtin.OptimizeMode) *Step.Compile { +fn buildAssetCompiler(b: *Build, basisu_optimize: std.builtin.OptimizeMode, assets_step: *Step, optimize: std.builtin.OptimizeMode) *Step.Compile { const assimp_dep = b.dependency("zig-assimp", .{ .target = b.host, .optimize = optimize, @@ -370,7 +379,6 @@ fn buildAssetCompiler(b: *Build, assets_step: *Step, optimize: std.builtin.Optim .formats = @as([]const u8, "Obj"), }); - const basisu_optimize = b.option(std.builtin.OptimizeMode, "basisu_optimize", "Optimization level for basisu. ReleaseSafe or faster is recommented, otherwise it's unbearable.") orelse .ReleaseFast; const basisu_dep = b.dependency("mach-basisu", .{ .target = b.host, .optimize = basisu_optimize, diff --git a/src/AssetManager.zig b/src/AssetManager.zig index 997f9a4..054a21f 100644 --- a/src/AssetManager.zig +++ b/src/AssetManager.zig @@ -20,20 +20,19 @@ const fs_utils = @import("fs/utils.zig"); const formats = @import("formats.zig"); const asset_manifest = @import("asset_manifest"); const assets = @import("assets"); +const basisu = @import("mach-basisu"); pub const AssetId = assets.AssetId; pub const Handle = assets.Handle; pub const AssetManager = @This(); -// const ShaderProgramHandle = struct { id: gl.GLuint }; -// const handle: ShaderProgramHandle = assets.loadShaderProgram(.{ .vertex = "shaders/vertex.glsl", .fragment = "shaders/fragment.glsl" }); -// assets.unloadShaderProgram(handle); - const AssetIdList = std.SegmentedList(AssetId, 4); +const PowerOfTwo = u16; const SHADER_MAX_BYTES = 1024 * 1024 * 50; const MESH_MAX_BYTES = 1024 * 1024 * 500; +const TEXTURE_MAX_BYTES = 1024 * 1024 * 500; allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, @@ -49,6 +48,8 @@ dependees: std.AutoHashMapUnmanaged(AssetId, std.SegmentedList(AssetId, 4)) = .{ loaded_assets: std.AutoHashMapUnmanaged(AssetId, LoadedAsset) = .{}, pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator) AssetManager { + basisu.init_transcoder(); + var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; const exe_dir_path = std.fs.selfExeDirPath(&buf) catch @panic("can't find self exe dir path"); const exe_dir = std.fs.openDirAbsolute(exe_dir_path, .{}) catch @panic("can't open self exe dir path"); @@ -102,6 +103,19 @@ pub fn resolveMesh(self: *AssetManager, handle: Handle.Mesh) *const LoadedMesh { return self.loadMesh(handle.id); } +pub fn resolveTexture(self: *AssetManager, handle: Handle.Texture) *const LoadedTexture { + if (self.loaded_assets.getPtr(handle.id)) |asset| { + switch (asset.*) { + .texture => |*texture| { + return texture; + }, + else => unreachable, + } + } + + return self.loadTexture(handle.id); +} + // TODO: proper watching pub fn watchChanges(self: *AssetManager) void { var iter = self.loaded_assets.iterator(); @@ -227,6 +241,12 @@ const NullMesh = LoadedMesh{ }, }; +// TODO: create empty texture instead, this will crash +const NullTexture = LoadedTexture{ + .name = 0, + .handle = 0, +}; + pub fn loadMesh(self: *AssetManager, id: AssetId) *const LoadedMesh { return self.loadMeshErr(id) catch |err| { std.log.err("Error: {} loading mesh at path: {s}", .{ err, asset_manifest.getPath(id) }); @@ -308,10 +328,90 @@ fn loadMeshErr(self: *AssetManager, id: AssetId) !*const LoadedMesh { return &self.loaded_assets.getPtr(id).?.mesh; } +fn loadTexture(self: *AssetManager, id: AssetId) *const LoadedTexture { + return self.loadTextureErr(id) catch |err| { + std.log.err("Error: {} loading texture at path {s}\n", .{ err, asset_manifest.getPath(id) }); + + return &NullTexture; + }; +} + +fn loadTextureErr(self: *AssetManager, id: AssetId) !*const LoadedTexture { + const path = asset_manifest.getPath(id); + const data = try self.loadFile(self.frame_arena, path, TEXTURE_MAX_BYTES); + + const transcoder = try basisu.Transcoder.init(data.bytes); + defer transcoder.deinit(); + + std.debug.assert(transcoder.getImageCount() == 1); // Not supporting multiple textures yet + + const mip_level_count = transcoder.getImageLevelCount(0); + const mip_0_desc = transcoder.getImageLevelDescriptor(0, 0) catch unreachable; + + var name: gl.GLuint = 0; + gl.createTextures(gl.TEXTURE_2D, 1, &name); + if (name == 0) { + return error.GLCreateTexture; + } + errdefer gl.deleteTextures(1, &name); + + // TODO: query supported formats first in the future + const format = basisu.Transcoder.TextureFormat.bc7_rgba; + + gl.textureStorage2D( + name, + @intCast(mip_level_count), + gl.COMPRESSED_SRGB_ALPHA_BPTC_UNORM, + @intCast(mip_0_desc.original_width), + @intCast(mip_0_desc.original_height), + ); + + for (0..mip_level_count) |mip_level| { + const desc = transcoder.getImageLevelDescriptor(0, 0) catch unreachable; + const out_buf = try self.frame_arena.alloc( + u8, + @intCast(try transcoder.calcTranscodedSize(0, @intCast(mip_level), format)), + ); + + try transcoder.transcode(out_buf, 0, @intCast(mip_level), format, .{}); + + gl.compressedTextureSubImage2D( + name, + @intCast(mip_level), + 0, + 0, + @intCast(desc.original_width), + @intCast(desc.original_height), + gl.COMPRESSED_SRGB_ALPHA_BPTC_UNORM, + @intCast(out_buf.len), + @ptrCast(out_buf.ptr), + ); + } + + const handle = gl.GL_ARB_bindless_texture.getTextureHandleARB(name); + gl.GL_ARB_bindless_texture.makeTextureHandleResidentARB(handle); + errdefer gl.GL_ARB_bindless_texture.makeTextureHandleNonResidentARB(handle); + + try self.loaded_assets.put( + self.allocator, + id, + .{ + .texture = LoadedTexture{ + .name = name, + .handle = handle, + }, + }, + ); + try self.modified_times.put(self.allocator, id, data.modified); + + return &self.loaded_assets.getPtr(id).?.texture; +} + const LoadedAsset = union(enum) { shader: LoadedShader, shaderProgram: LoadedShaderProgram, mesh: LoadedMesh, + texture: LoadedTexture, }; const LoadedShader = struct { @@ -329,6 +429,11 @@ const LoadedMesh = struct { indices: IndexSlice, }; +const LoadedTexture = struct { + name: gl.GLuint, + handle: gl.GLuint64, +}; + pub const BufferSlice = struct { buffer: gl.GLuint, offset: gl.GLintptr, @@ -473,6 +578,10 @@ fn unloadAssetWithDependees(self: *AssetManager, id: AssetId) void { .shaderProgram => |*program| { gl.deleteProgram(program.program); }, + .texture => |*texture| { + gl.GL_ARB_bindless_texture.makeTextureHandleNonResidentARB(texture.handle); + gl.deleteTextures(1, &texture.name); + }, } } _ = self.loaded_assets.remove(id); diff --git a/src/game.zig b/src/game.zig index 9899e1a..794f623 100644 --- a/src/game.zig +++ b/src/game.zig @@ -1,6 +1,5 @@ const std = @import("std"); const c = @import("sdl.zig"); -const manymouse = @import("manymouse.zig"); const gl = @import("gl.zig"); const AssetManager = @import("AssetManager.zig"); const formats = @import("formats.zig"); @@ -293,15 +292,20 @@ export fn game_init_window(global_allocator: *std.mem.Allocator) void { } fn loadGL() void { - gl.load(null, struct { + const getProcAddress = struct { fn getProcAddress(ctx: @TypeOf(null), proc: [:0]const u8) ?gl.FunctionPointer { _ = ctx; return @ptrCast(c.SDL_GL_GetProcAddress(proc)); } - }.getProcAddress) catch |err| { + }.getProcAddress; + gl.load(null, getProcAddress) catch |err| { std.log.debug("Failed to load gl funcs {}\n", .{err}); @panic("gl.load"); }; + gl.GL_ARB_bindless_texture.load(null, getProcAddress) catch |err| { + std.log.debug("Failed to load gl funcs GL_ARB_bindless_texture {}\n", .{err}); + @panic("gl.load"); + }; } fn checkGLError() void { @@ -377,15 +381,15 @@ export fn game_init(global_allocator: *std.mem.Allocator) void { // normals // gl.vertexArrayVertexBuffer(vao, 1, normals, 0, @sizeOf(formats.Vector3)); + gl.enableVertexArrayAttrib(vao, Attrib.Normal.value()); gl.vertexArrayAttribBinding(vao, Attrib.Normal.value(), 1); gl.vertexArrayAttribFormat(vao, Attrib.Normal.value(), 3, gl.FLOAT, gl.FALSE, 0); - gl.enableVertexArrayAttrib(vao, Attrib.Normal.value()); // uvs // gl.vertexArrayVertexBuffer(vao, 1, normals, 0, @sizeOf(formats.Vector3)); - gl.vertexArrayAttribBinding(vao, Attrib.UV.value(), 1); - gl.vertexArrayAttribFormat(vao, Attrib.UV.value(), 2, gl.FLOAT, gl.FALSE, 0); gl.enableVertexArrayAttrib(vao, Attrib.UV.value()); + gl.vertexArrayAttribBinding(vao, Attrib.UV.value(), 2); + gl.vertexArrayAttribFormat(vao, Attrib.UV.value(), 2, gl.FLOAT, gl.FALSE, 0); const PERSISTENT_BUFFER_FLAGS: gl.GLbitfield = gl.MAP_PERSISTENT_BIT | gl.MAP_WRITE_BIT | gl.MAP_COHERENT_BIT; @@ -732,6 +736,10 @@ export fn game_update() bool { const color = if (ent.flags.mesh) ent.mesh.color else ent.point_light.color(); gl.uniformMatrix4fv(1, 1, gl.FALSE, @ptrCast(&ent.transform.matrix().data)); gl.uniform3fv(2, 1, @ptrCast(&color.data)); + gl.GL_ARB_bindless_texture.uniformHandleui64ARB( + 3, + g_assetman.resolveTexture(a.Textures.@"test").handle, + ); const mesh_handle = if (ent.flags.mesh) ent.mesh.handle else a.Meshes.sphere; const mesh = g_assetman.resolveMesh(mesh_handle); diff --git a/src/gen/asset_manifest.zig b/src/gen/asset_manifest.zig index 39ddc43..f12ed60 100644 --- a/src/gen/asset_manifest.zig +++ b/src/gen/asset_manifest.zig @@ -3,6 +3,7 @@ pub const manifest = @import("asset_manifest_gen"); pub const Meshes = manifest.Meshes; pub const Shaders = manifest.Shaders; pub const ShaderPrograms = manifest.ShaderPrograms; +pub const Textures = manifest.Textures; pub fn getPath(asset_id: u32) []const u8 { if (asset_id == 0) return ""; diff --git a/src/gl.zig b/src/gl.zig index 4eef366..0731a58 100644 --- a/src/gl.zig +++ b/src/gl.zig @@ -7,68 +7,68 @@ // Generation parameters: // API: GL_VERSION_4_5 // Profile: core -// Extensions: +// Extensions: GL_ARB_bindless_texture // // // This file was generated with the following command line: -// generator C:\Users\Серега\git\zig-opengl\bin\Debug\net7.0\generator.dll OpenGL-Registry/xml/gl.xml gl.zig GL_VERSION_4_5 +// generator C:\git\zig-opengl\bin\Debug\net7.0\generator.dll OpenGL-Registry\xml\gl.xml gl.zig GL_VERSION_4_5 GL_ARB_bindless_texture // const std = @import("std"); const builtin = @import("builtin"); const log = std.log.scoped(.OpenGL); -pub const FunctionPointer: type = *align(@alignOf(fn (u32) callconv(.C) u32)) const anyopaque; - -pub const GLenum = c_uint; -pub const GLboolean = u8; -pub const GLbitfield = c_uint; -pub const GLbyte = i8; -pub const GLubyte = u8; -pub const GLshort = i16; -pub const GLushort = u16; -pub const GLint = c_int; -pub const GLuint = c_uint; -pub const GLclampx = i32; -pub const GLsizei = c_int; -pub const GLfloat = f32; -pub const GLclampf = f32; -pub const GLdouble = f64; -pub const GLclampd = f64; -pub const GLeglClientBufferEXT = void; -pub const GLeglImageOES = void; -pub const GLchar = u8; -pub const GLcharARB = u8; - -pub const GLhandleARB = if (builtin.os.tag == .macos) *anyopaque else c_uint; - -pub const GLhalf = u16; -pub const GLhalfARB = u16; -pub const GLfixed = i32; -pub const GLintptr = usize; -pub const GLintptrARB = usize; -pub const GLsizeiptr = isize; -pub const GLsizeiptrARB = isize; -pub const GLint64 = i64; -pub const GLint64EXT = i64; -pub const GLuint64 = u64; -pub const GLuint64EXT = u64; - -pub const GLsync = *opaque {}; - -pub const _cl_context = opaque {}; -pub const _cl_event = opaque {}; - -pub const GLDEBUGPROC = *const fn (source: GLenum, _type: GLenum, id: GLuint, severity: GLenum, length: GLsizei, message: [*:0]const u8, userParam: ?*anyopaque) callconv(.C) void; -pub const GLDEBUGPROCARB = *const fn (source: GLenum, _type: GLenum, id: GLuint, severity: GLenum, length: GLsizei, message: [*:0]const u8, userParam: ?*anyopaque) callconv(.C) void; -pub const GLDEBUGPROCKHR = *const fn (source: GLenum, _type: GLenum, id: GLuint, severity: GLenum, length: GLsizei, message: [*:0]const u8, userParam: ?*anyopaque) callconv(.C) void; - -pub const GLDEBUGPROCAMD = *const fn (id: GLuint, category: GLenum, severity: GLenum, length: GLsizei, message: [*:0]const u8, userParam: ?*anyopaque) callconv(.C) void; - -pub const GLhalfNV = u16; -pub const GLvdpauSurfaceNV = GLintptr; -pub const GLVULKANPROCNV = *const fn () callconv(.C) void; +pub const FunctionPointer: type = *align(@alignOf(fn (u32) callconv(.C) u32)) const anyopaque; + +pub const GLenum = c_uint; +pub const GLboolean = u8; +pub const GLbitfield = c_uint; +pub const GLbyte = i8; +pub const GLubyte = u8; +pub const GLshort = i16; +pub const GLushort = u16; +pub const GLint = c_int; +pub const GLuint = c_uint; +pub const GLclampx = i32; +pub const GLsizei = c_int; +pub const GLfloat = f32; +pub const GLclampf = f32; +pub const GLdouble = f64; +pub const GLclampd = f64; +pub const GLeglClientBufferEXT = void; +pub const GLeglImageOES = void; +pub const GLchar = u8; +pub const GLcharARB = u8; + +pub const GLhandleARB = if (builtin.os.tag == .macos) *anyopaque else c_uint; + +pub const GLhalf = u16; +pub const GLhalfARB = u16; +pub const GLfixed = i32; +pub const GLintptr = usize; +pub const GLintptrARB = usize; +pub const GLsizeiptr = isize; +pub const GLsizeiptrARB = isize; +pub const GLint64 = i64; +pub const GLint64EXT = i64; +pub const GLuint64 = u64; +pub const GLuint64EXT = u64; + +pub const GLsync = *opaque {}; + +pub const _cl_context = opaque {}; +pub const _cl_event = opaque {}; + +pub const GLDEBUGPROC = *const fn (source: GLenum, _type: GLenum, id: GLuint, severity: GLenum, length: GLsizei, message: [*:0]const u8, userParam: ?*anyopaque) callconv(.C) void; +pub const GLDEBUGPROCARB = *const fn (source: GLenum, _type: GLenum, id: GLuint, severity: GLenum, length: GLsizei, message: [*:0]const u8, userParam: ?*anyopaque) callconv(.C) void; +pub const GLDEBUGPROCKHR = *const fn (source: GLenum, _type: GLenum, id: GLuint, severity: GLenum, length: GLsizei, message: [*:0]const u8, userParam: ?*anyopaque) callconv(.C) void; + +pub const GLDEBUGPROCAMD = *const fn (id: GLuint, category: GLenum, severity: GLenum, length: GLsizei, message: [*:0]const u8, userParam: ?*anyopaque) callconv(.C) void; + +pub const GLhalfNV = u16; +pub const GLvdpauSurfaceNV = GLintptr; +pub const GLVULKANPROCNV = *const fn () callconv(.C) void; pub const DEPTH_BUFFER_BIT = 0x00000100; @@ -4031,6 +4031,177 @@ pub fn textureBarrier() callconv(.C) void { } // Extensions: +pub const GL_ARB_bindless_texture = struct { +pub const UNSIGNED_INT64_ARB = 0x140F; + + +pub fn getTextureHandleARB(_texture: GLuint) callconv(.C) GLuint64 { + return @call(.always_tail, function_pointers.glGetTextureHandleARB, .{_texture}); +} + +pub fn getTextureSamplerHandleARB(_texture: GLuint, _sampler: GLuint) callconv(.C) GLuint64 { + return @call(.always_tail, function_pointers.glGetTextureSamplerHandleARB, .{_texture, _sampler}); +} + +pub fn makeTextureHandleResidentARB(_handle: GLuint64) callconv(.C) void { + return @call(.always_tail, function_pointers.glMakeTextureHandleResidentARB, .{_handle}); +} + +pub fn makeTextureHandleNonResidentARB(_handle: GLuint64) callconv(.C) void { + return @call(.always_tail, function_pointers.glMakeTextureHandleNonResidentARB, .{_handle}); +} + +pub fn getImageHandleARB(_texture: GLuint, _level: GLint, _layered: GLboolean, _layer: GLint, _format: GLenum) callconv(.C) GLuint64 { + return @call(.always_tail, function_pointers.glGetImageHandleARB, .{_texture, _level, _layered, _layer, _format}); +} + +pub fn makeImageHandleResidentARB(_handle: GLuint64, _access: GLenum) callconv(.C) void { + return @call(.always_tail, function_pointers.glMakeImageHandleResidentARB, .{_handle, _access}); +} + +pub fn makeImageHandleNonResidentARB(_handle: GLuint64) callconv(.C) void { + return @call(.always_tail, function_pointers.glMakeImageHandleNonResidentARB, .{_handle}); +} + +pub fn uniformHandleui64ARB(_location: GLint, _value: GLuint64) callconv(.C) void { + return @call(.always_tail, function_pointers.glUniformHandleui64ARB, .{_location, _value}); +} + +pub fn uniformHandleui64vARB(_location: GLint, _count: GLsizei, _value: [*c]const GLuint64) callconv(.C) void { + return @call(.always_tail, function_pointers.glUniformHandleui64vARB, .{_location, _count, _value}); +} + +pub fn programUniformHandleui64ARB(_program: GLuint, _location: GLint, _value: GLuint64) callconv(.C) void { + return @call(.always_tail, function_pointers.glProgramUniformHandleui64ARB, .{_program, _location, _value}); +} + +pub fn programUniformHandleui64vARB(_program: GLuint, _location: GLint, _count: GLsizei, _values: [*c]const GLuint64) callconv(.C) void { + return @call(.always_tail, function_pointers.glProgramUniformHandleui64vARB, .{_program, _location, _count, _values}); +} + +pub fn isTextureHandleResidentARB(_handle: GLuint64) callconv(.C) GLboolean { + return @call(.always_tail, function_pointers.glIsTextureHandleResidentARB, .{_handle}); +} + +pub fn isImageHandleResidentARB(_handle: GLuint64) callconv(.C) GLboolean { + return @call(.always_tail, function_pointers.glIsImageHandleResidentARB, .{_handle}); +} + +pub fn vertexAttribL1ui64ARB(_index: GLuint, _x: GLuint64EXT) callconv(.C) void { + return @call(.always_tail, function_pointers.glVertexAttribL1ui64ARB, .{_index, _x}); +} + +pub fn vertexAttribL1ui64vARB(_index: GLuint, _v: [*c]const GLuint64EXT) callconv(.C) void { + return @call(.always_tail, function_pointers.glVertexAttribL1ui64vARB, .{_index, _v}); +} + +pub fn getVertexAttribLui64vARB(_index: GLuint, _pname: GLenum, _params: [*c]GLuint64EXT) callconv(.C) void { + return @call(.always_tail, function_pointers.glGetVertexAttribLui64vARB, .{_index, _pname, _params}); +} + +pub fn load(load_ctx: anytype, get_proc_address: fn(@TypeOf(load_ctx), [:0]const u8) ?FunctionPointer) !void { + var success = true; + if(get_proc_address(load_ctx, "glGetTextureHandleARB")) |proc| { + function_pointers.glGetTextureHandleARB = @ptrCast(proc); + } else { + log.err("entry point glGetTextureHandleARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glGetTextureSamplerHandleARB")) |proc| { + function_pointers.glGetTextureSamplerHandleARB = @ptrCast(proc); + } else { + log.err("entry point glGetTextureSamplerHandleARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glMakeTextureHandleResidentARB")) |proc| { + function_pointers.glMakeTextureHandleResidentARB = @ptrCast(proc); + } else { + log.err("entry point glMakeTextureHandleResidentARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glMakeTextureHandleNonResidentARB")) |proc| { + function_pointers.glMakeTextureHandleNonResidentARB = @ptrCast(proc); + } else { + log.err("entry point glMakeTextureHandleNonResidentARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glGetImageHandleARB")) |proc| { + function_pointers.glGetImageHandleARB = @ptrCast(proc); + } else { + log.err("entry point glGetImageHandleARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glMakeImageHandleResidentARB")) |proc| { + function_pointers.glMakeImageHandleResidentARB = @ptrCast(proc); + } else { + log.err("entry point glMakeImageHandleResidentARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glMakeImageHandleNonResidentARB")) |proc| { + function_pointers.glMakeImageHandleNonResidentARB = @ptrCast(proc); + } else { + log.err("entry point glMakeImageHandleNonResidentARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glUniformHandleui64ARB")) |proc| { + function_pointers.glUniformHandleui64ARB = @ptrCast(proc); + } else { + log.err("entry point glUniformHandleui64ARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glUniformHandleui64vARB")) |proc| { + function_pointers.glUniformHandleui64vARB = @ptrCast(proc); + } else { + log.err("entry point glUniformHandleui64vARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glProgramUniformHandleui64ARB")) |proc| { + function_pointers.glProgramUniformHandleui64ARB = @ptrCast(proc); + } else { + log.err("entry point glProgramUniformHandleui64ARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glProgramUniformHandleui64vARB")) |proc| { + function_pointers.glProgramUniformHandleui64vARB = @ptrCast(proc); + } else { + log.err("entry point glProgramUniformHandleui64vARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glIsTextureHandleResidentARB")) |proc| { + function_pointers.glIsTextureHandleResidentARB = @ptrCast(proc); + } else { + log.err("entry point glIsTextureHandleResidentARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glIsImageHandleResidentARB")) |proc| { + function_pointers.glIsImageHandleResidentARB = @ptrCast(proc); + } else { + log.err("entry point glIsImageHandleResidentARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glVertexAttribL1ui64ARB")) |proc| { + function_pointers.glVertexAttribL1ui64ARB = @ptrCast(proc); + } else { + log.err("entry point glVertexAttribL1ui64ARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glVertexAttribL1ui64vARB")) |proc| { + function_pointers.glVertexAttribL1ui64vARB = @ptrCast(proc); + } else { + log.err("entry point glVertexAttribL1ui64vARB not found!", .{}); + success = false; + } + if(get_proc_address(load_ctx, "glGetVertexAttribLui64vARB")) |proc| { + function_pointers.glGetVertexAttribLui64vARB = @ptrCast(proc); + } else { + log.err("entry point glGetVertexAttribLui64vARB not found!", .{}); + success = false; + } + if(!success) + return error.EntryPointNotFound; +} +}; + // Loader API: pub fn load(load_ctx: anytype, get_proc_address: fn(@TypeOf(load_ctx), [:0]const u8) ?FunctionPointer) !void { var success = true; @@ -8610,6 +8781,22 @@ const function_signatures = struct { const glGetnUniformuiv = fn(_program: GLuint, _location: GLint, _bufSize: GLsizei, _params: [*c]GLuint) callconv(.C) void; const glReadnPixels = fn(_x: GLint, _y: GLint, _width: GLsizei, _height: GLsizei, _format: GLenum, _type: GLenum, _bufSize: GLsizei, _data: ?*anyopaque) callconv(.C) void; const glTextureBarrier = fn() callconv(.C) void; + const glGetTextureHandleARB = fn(_texture: GLuint) callconv(.C) GLuint64; + const glGetTextureSamplerHandleARB = fn(_texture: GLuint, _sampler: GLuint) callconv(.C) GLuint64; + const glMakeTextureHandleResidentARB = fn(_handle: GLuint64) callconv(.C) void; + const glMakeTextureHandleNonResidentARB = fn(_handle: GLuint64) callconv(.C) void; + const glGetImageHandleARB = fn(_texture: GLuint, _level: GLint, _layered: GLboolean, _layer: GLint, _format: GLenum) callconv(.C) GLuint64; + const glMakeImageHandleResidentARB = fn(_handle: GLuint64, _access: GLenum) callconv(.C) void; + const glMakeImageHandleNonResidentARB = fn(_handle: GLuint64) callconv(.C) void; + const glUniformHandleui64ARB = fn(_location: GLint, _value: GLuint64) callconv(.C) void; + const glUniformHandleui64vARB = fn(_location: GLint, _count: GLsizei, _value: [*c]const GLuint64) callconv(.C) void; + const glProgramUniformHandleui64ARB = fn(_program: GLuint, _location: GLint, _value: GLuint64) callconv(.C) void; + const glProgramUniformHandleui64vARB = fn(_program: GLuint, _location: GLint, _count: GLsizei, _values: [*c]const GLuint64) callconv(.C) void; + const glIsTextureHandleResidentARB = fn(_handle: GLuint64) callconv(.C) GLboolean; + const glIsImageHandleResidentARB = fn(_handle: GLuint64) callconv(.C) GLboolean; + const glVertexAttribL1ui64ARB = fn(_index: GLuint, _x: GLuint64EXT) callconv(.C) void; + const glVertexAttribL1ui64vARB = fn(_index: GLuint, _v: [*c]const GLuint64EXT) callconv(.C) void; + const glGetVertexAttribLui64vARB = fn(_index: GLuint, _pname: GLenum, _params: [*c]GLuint64EXT) callconv(.C) void; }; const function_pointers = struct { @@ -9266,6 +9453,22 @@ const function_pointers = struct { var glGetnUniformuiv: *const function_signatures.glGetnUniformuiv = undefined; var glReadnPixels: *const function_signatures.glReadnPixels = undefined; var glTextureBarrier: *const function_signatures.glTextureBarrier = undefined; + var glGetTextureHandleARB: *const function_signatures.glGetTextureHandleARB = undefined; + var glGetTextureSamplerHandleARB: *const function_signatures.glGetTextureSamplerHandleARB = undefined; + var glMakeTextureHandleResidentARB: *const function_signatures.glMakeTextureHandleResidentARB = undefined; + var glMakeTextureHandleNonResidentARB: *const function_signatures.glMakeTextureHandleNonResidentARB = undefined; + var glGetImageHandleARB: *const function_signatures.glGetImageHandleARB = undefined; + var glMakeImageHandleResidentARB: *const function_signatures.glMakeImageHandleResidentARB = undefined; + var glMakeImageHandleNonResidentARB: *const function_signatures.glMakeImageHandleNonResidentARB = undefined; + var glUniformHandleui64ARB: *const function_signatures.glUniformHandleui64ARB = undefined; + var glUniformHandleui64vARB: *const function_signatures.glUniformHandleui64vARB = undefined; + var glProgramUniformHandleui64ARB: *const function_signatures.glProgramUniformHandleui64ARB = undefined; + var glProgramUniformHandleui64vARB: *const function_signatures.glProgramUniformHandleui64vARB = undefined; + var glIsTextureHandleResidentARB: *const function_signatures.glIsTextureHandleResidentARB = undefined; + var glIsImageHandleResidentARB: *const function_signatures.glIsImageHandleResidentARB = undefined; + var glVertexAttribL1ui64ARB: *const function_signatures.glVertexAttribL1ui64ARB = undefined; + var glVertexAttribL1ui64vARB: *const function_signatures.glVertexAttribL1ui64vARB = undefined; + var glGetVertexAttribLui64vARB: *const function_signatures.glGetVertexAttribLui64vARB = undefined; }; test { diff --git a/tools/asset_compiler.zig b/tools/asset_compiler.zig index c53f59a..3da3d23 100644 --- a/tools/asset_compiler.zig +++ b/tools/asset_compiler.zig @@ -195,9 +195,10 @@ fn processTexture(allocator: std.mem.Allocator, input: [*:0]const u8, output: [] const img = params.getImageSource(0); img.fill(data, @intCast(x), @intCast(y), @intCast(FORCED_COMPONENTS)); + // TODO: configure per-texture somehow params.setQualityLevel(64); params.setBasisFormat(basisu.BasisTextureFormat.etc1s); - // params.setColorSpace(basisu.ColorSpace.linear); + params.setColorSpace(basisu.ColorSpace.srgb); params.setGenerateMipMaps(true); var compressor = try basisu.Compressor.init(params);