ziglibs / zgl Goto Github PK
View Code? Open in Web Editor NEWZig OpenGL Wrapper
License: MIT License
Zig OpenGL Wrapper
License: MIT License
It will save newbie's life (like me !!!!!)
I'm struggling with zig's build system, and if i make it, i would try to pr.
I have seen the use of the "gl.load" function, but I don't know how to get the required parameters to pass when using SDL.zig. I have seen the other examples with glfw, but I don't understand or know which parameters have to be passed. My project was working fine before, but now it won't run saying that a function isn't bound.
lib/zgl/binding.zig:2722:54: 0x296d3e in createProgram (usg)
return (function_pointers.glCreateProgram orelse @panic("glCreateProgram was not bound."))();
^
lib/zgl/zgl.zig:757:68: 0x263b9c in createProgram (usg)
const program = @intToEnum(types.Program, binding.createProgram());
^
src/Renderer.zig:48:38: 0x2636a3 in init (usg)
const program = gl.Program.create();
...
A recent update to Zig 0.11 (ziglang/zig#16046) has broken a lot of code in zgl with renames like @intToFloat()
to @floatFromInt()
.
In Type
, the OpenGL names are used for types, eg. unsigned_byte
etc.
In ElementType
, the Zig names are used for the same types, eg. u8
etc.
One set of names should be chosen and used consistently throughout zgl.
The global pub fn uniform1i(location: ?u32, value: i32) void
function is conflicting (due to a redefinition error) with Program.uniform1i
which means calling the latter is a compile error.
Since #103 was merged, this change is causing builds to fail:
41eeec2#diff-94b5cd6f42b14d51f9381839d4e395b58e524df837c4d46b4d9def97b8abad8a
Reverting this change seems to fix the problem.
The OpenGL API has a habit of using void pointers for offsets into buffer objects, eg. in glVertexAttribPointer
, glDrawElements
, etc.
The only reason I see for this being done is so pointer arithmetic can be used to remove the need to multiply things by sizeof (T)
, however Zig does not have pointer arithmetic, leaving this as purely confusing and difficult to handle, without any ergonomic benefit.
zgl currently uses ?usize
for the offset parameter to vertexAttribPointer
, and ?*const c_void
for the parameter to glDrawElements
and glDrawElementsInstanced
. The way the former is converted into the C type will cause checked undefined behaviour if 0
is passed in, and the latter is difficult to deal with as discussed above.
I propose changing all of these functions, as well as any future functions making use of this kind of offset, to use usize
, which can be converted into a *allowzero c_void
for passing to C.
currently this repo is not clear nor informative on how to include and use it.
Things that I think should be specified:
For example on point 1, I'm getting segment fault because probably the function pointers are undefined (point to 0).
I know that you need to use the loadExtension
function but I don't know how.
main.zig:
const std = @import("std");
const glfw = @import("glfw");
const gl = @import("zgl");
pub fn main() !void {
try glfw.init(.{});
defer glfw.terminate();
const window = try glfw.Window.create(1024, 576, "Hello World", null, null, .{});
defer window.destroy();
try glfw.makeContextCurrent(window);
while (!window.shouldClose()) {
try glfw.pollEvents();
gl.clear(.{ .color = true, .depth = true, .stencil = false });
}
}
Is there something missing?
I was looking my program output assembly code in release mode and I realized is not removing a check about if an opengl function is loaded or not.
I think it could be possible specify to the compiler that those functions are loaded only in release mode.
Thanks
A null pointer can be used to create an uninitialized buffer, however zgl's wrappers do not support this.
I propose changing the signatures like this:
pub fn bufferData(target: BufferTarget, comptime T: type, count: usize, items: ?[*]align(1) const T, usage: BufferUsage)
(and in the corresponding manner for namedBufferData
)
This allows passing slices using bufferData(target, T, slice.len, slice.ptr, usage)
, and allows creating uninitialized buffers using bufferData(target, T, length, null, usage)
.
This has the disadvantage that the API becomes less clear for the usual case. Another alternative would be to create a separate wrapper function for creating uninitialized buffers, but this seems cluttered to me.
I had mach-glfw and zgl working together nicely, but at some point linking started to fail with the following errors;
LLD Link... ld.lld: error: /lib64/libepoxy.so: undefined reference to dlerror@GLIBC_2.34 [--no-allow-shlib-undefined]
ld.lld: error: /lib64/libepoxy.so: undefined reference to dlopen@GLIBC_2.34 [--no-allow-shlib-undefined]
ld.lld: error: /lib64/libepoxy.so: undefined reference to dlsym@GLIBC_2.34 [--no-allow-shlib-undefined]
error: FileNotFound
zig build --verbose-link
gives
LLD Link... ld.lld -error-limit=0 -O0 -z stack-size=16777216 --gc-sections -znow -m elf_x86_64 -o /home/marten/src/motorsim/zig-cache/o/c9c8140870e3b12f9dc1b339e9fa06f3/motorsim /home/marten/.cache/zig/o/23f7278b09980272ad5975c0fb2e4096/Scrt1.o /home/marten/.cache/zig/o/b32b64a8fb73995fc5135714d247ac2e/crti.o -rpath /home/marten/.local/share/hexops/sdk-linux-x86_64/root/usr/lib/x86_64-linux-gnu -rpath /lib64 -rpath /lib -rpath /usr/lib64 -rpath /usr/lib -L /home/marten/.local/share/hexops/sdk-linux-x86_64/root/usr/lib/x86_64-linux-gnu -L /usr/local/lib64 -L /usr/local/lib -L /usr/lib/x86_64-linux-gnu -L /lib64 -L /lib -L /usr/lib64 -L /usr/lib -L /lib/x86_64-linux-gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 /home/marten/src/motorsim/zig-cache/o/7046d94a8a3c2cbb537d667ce7685374/libglfw.a /home/marten/.local/share/hexops/sdk-linux-x86_64/root/usr/lib/x86_64-linux-gnu/libXau.a /home/marten/.local/share/hexops/sdk-linux-x86_64/root/usr/lib/x86_64-linux-gnu/libXdmcp.a /home/marten/src/motorsim/zig-cache/o/c9c8140870e3b12f9dc1b339e9fa06f3/motorsim.o /home/marten/.cache/zig/o/027e12d25ebee0ab6cb34760a80829ce/libcompiler_rt.a --as-needed -lX11 -lxcb -lepoxy /home/marten/.cache/zig/o/c224969826294d4bdc6cb26db6cc24a8/libm.so.6 /home/marten/.cache/zig/o/c224969826294d4bdc6cb26db6cc24a8/libpthread.so.0 /home/marten/.cache/zig/o/c224969826294d4bdc6cb26db6cc24a8/libc.so.6 /home/marten/.cache/zig/o/c224969826294d4bdc6cb26db6cc24a8/libdl.so.2 /home/marten/.cache/zig/o/c224969826294d4bdc6cb26db6cc24a8/librt.so.1 /home/marten/.cache/zig/o/c224969826294d4bdc6cb26db6cc24a8/libld.so.2 /home/marten/.cache/zig/o/c224969826294d4bdc6cb26db6cc24a8/libutil.so.1 /home/marten/.cache/zig/o/2af95d2dee926e689433b2817020554f/libc_nonshared.a /home/marten/.cache/zig/o/de4ee0f5effa10017ceca863311bedfd/crtn.o
I am using Zig version 0.10.0-dev.3475+b3d463c9e
with the following in my build script
const exe = b.addExecutable("motorsim", "src/main.zig");
exe.setTarget(target);
exe.setBuildMode(mode);
exe.install();
exe.addPackagePath("glfw", "libs/mach-glfw/src/main.zig");
glfw.link(b, exe, .{});
exe.addPackagePath("zgl", "libs/zgl/zgl.zig");
exe.linkSystemLibrary("dl");
exe.linkSystemLibrary("epoxy");
If I understand correctly, my libepoxy version depends on the GLIBC_2.34 symbols, while the included libdl.so.2
file being linked has GLIBC_2.2.5
. I do not understand why the compiler does not grab the available system libraries, which do seem to have to correct symbols in them.
Setting the target with -Dtarget=x86_64-linux-gnu.2.34
, as suggested to someone with the same problem, results in
./libs/zgl/c.zig:6:5: error: C import failed
@cImport({
^
./zig-cache/o/fca946021a1176b5ad82bf37c8570071/cimport.h:1:10: note: 'epoxy/gl.h' file not found
#include <epoxy/gl.h>
^
./libs/zgl/zgl.zig:228:6: error: container '.zgl.c' has no member called 'glClear'
c.glClear(@as(types.BitField, if (mask.color) c.GL_COLOR_BUFFER_BIT else 0) |
I do not know how to proceed right now.
Someone in the Zig discord server had the same issue, and for him bulding libepoxy himself seemed to work. However, it should be able to use the installed system libraries.
Currently, zgl.activeTexture
only allows values from zgl.TextureUnit
. This makes it hard to do something like this:
gl.activeTexture(gl.TextureUnit.texture_0 + texture_unit_count);
This is useful when dynamically enabling texture units (i.e. when rendering with a dynamic amount of textures in a single draw call). Therefore it would be nice to have a version which accepts a GLenum
.
It's not required for the bindings to operate, seems to just be for reference purposes?
Having it submoduled makes things annoying for projects that incorporate zgl as a submodule, since cloning them recursively pulls in almost 180MB(!!) of XML.
Might make more sense to just gitignore it so people can clone it into the zgl dir if they want to.
Mac OpenGl version is stuck on OpenGL 4.1
The following line is using a function that requires 4.5 (glCreateTextures)
Line 1357 in b2c0379
Does this mean that zgl cannot run on mac systems? Is there any workaraound?
zgl.zig contains definitions for both BufferMapTarget
and BufferTarget
with the same contents. And buffer functions aren't consistent with which one to use. Example: mapBuffer()
uses BufferMapTarget
and mapBufferRange()
uses BufferTarget
.
IMO, BufferTarget
seems like the one to keep. It's used more than BufferMapTarget
and existed first and is commented. The usages of BufferMapTarget
in mapBuffer()
and unmapBuffer()
could be changed to use BufferTarget
instead.
"This library is developed incrementally"
This is the correct approach when creating bindings instead of completeness (unless there is an automatic procedure). Make a foundation upon to build, like some types, some adaptor functions, some examples of calling and thats's it.
The benefits
I think your approach should be emphasised.
I don't understand why I'm getting a panic when I call gl.vertexAttribPointer():
const vertex_data = [6]f32{
-0.5, -0.5,
0.0, 0.5,
0.5, -0.5,
};
const buffer = gl.genBuffer();
gl.bindBuffer(buffer, .array_buffer);
gl.bufferData(.array_buffer, f32, &vertex_data, .static_read);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, .float, false, @sizeOf(f32) * 2, 0); // <-- Panics here with "invalid operation"
I have no idea what I am doing wrong here but my guess would be that I am loading the OpenGL functions incorrectly?
fn glGetProcAddress(p: glfw.GLProc, proc: [:0]const u8) ?gl.binding.FunctionPointer {
_ = p;
return glfw.getProcAddress(proc);
}
fn main() !void {
// ...
const proc: glfw.GLProc = undefined;
try gl.loadExtensions(proc, glGetProcAddress);
// ...
}
If it helps, here is my output:
error(OpenGL): OpenGL failure: invalid operation
thread 22924 panic: OpenGL error
...\src\zgl.zig:61:24: 0x29af1d in checkError (App.exe.obj)
.assert => @panic("OpenGL error"),
^
...\src\zgl.zig:428:15: 0x294336 in vertexAttribPointer (App.exe.obj)
checkError();
^
..\App\src\main.zig:72:27: 0x292c84 in main (App.exe.obj)
gl.vertexAttribPointer(0, 2, .float, false, @sizeOf(f32) * 2, 0);
I am 90% sure that I have done something wrong and I would be very grateful if someone could help me.
This is my first time using zgl, and I'm still super new at Zig. But I tried running this super simple example:
const std = @import("std");
const c = @cImport({
@cInclude("SDL.h");
});
const gl = @import("third-party/zgl/zgl.zig");
pub fn main() !void {
_ = c.SDL_Init(c.SDL_INIT_VIDEO);
defer c.SDL_Quit();
var window = c.SDL_CreateWindow("Hello, world!", c.SDL_WINDOWPOS_CENTERED, c.SDL_WINDOWPOS_CENTERED, 640, 400, c.SDL_WINDOW_OPENGL);
defer c.SDL_DestroyWindow(window);
var glContext = c.SDL_GL_CreateContext(window);
defer c.SDL_GL_DeleteContext(glContext);
mainloop: while (true) {
var sdl_event: c.SDL_Event = undefined;
while (c.SDL_PollEvent(&sdl_event) != 0) {
switch (sdl_event.type) {
c.SDL_QUIT => break :mainloop,
else => {},
}
}
// this line will crash!
// Output: Stop reason: signal SIGSEGV: invalid address (fault address: 0x0)
gl.clear(.{.color = true, .depth = true });
c.SDL_GL_SwapWindow(window);
}
}
As soon as it executes the gl.clear()
line I get Stop reason: signal SIGSEGV: invalid address (fault address: 0x0)
Valgrind reports this:
==121080== Jump to the invalid address stated on the next line
==121080== at 0x0: ???
==121080== by 0x20C3D4: main.main (main.zig:30)
==121080== by 0x20C946: callMain (start.zig:609)
==121080== by 0x20C946: initEventLoopAndCallMain (start.zig:543)
==121080== by 0x20C946: callMainWithArgs (start.zig:493)
==121080== by 0x20C946: main (start.zig:508)
==121080== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==121080==
It seems like gl.Clear()
itself (and any other functions I've tried) is somehow null, which seems weird because from looking at the zgl source it's a regular function, not a dynamically loaded function pointer or anything like that.
If I were using GLEW I would assume I didn't call glewInit()
, but I haven't seen a similar zgl function in any of the examples I've found.
Am I missing something simple?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.