Hello! I went back to a project of porting old versions of minecraft to zig and am trying to update it to 0.16.0. It's been successful so far, progress was slightly annoying as I learned all the new Io interactions, but generally ok. Minecraft used GL 1.1 + GLU for its rendering. The GLU import seems to break, unfortunately, and I don't know why. Info below.
#GLU cImport segfaults
1 messages · Page 1 of 1 (latest)
Crash
Segmentation fault at address 0x1378ac0
???:?:?: 0x1378ac0 in ??? (???)
Unwind error at address `???:0x1378ac0` (unwind info unavailable), remaining frames may be incorrect
???:?:?: 0x7fabe3af60e3 in ??? (/lib/x86_64-linux-gnu/libGLU.so.1)
/home/createsource/git/Minecraft-Zig/src/Textures.zig:43:30: 0x128f05f in loadTexture (RubyDung.zig)
_ = GLU.gluBuild2DMipmaps(gl.TEXTURE_2D, gl.RGBA, w, h, gl.RGBA, gl.UNSIGNED_BYTE, data);
^
/home/createsource/git/Minecraft-Zig/src/level/Chunk.zig:35:41: 0x1275a85 in new (RubyDung.zig)
c.texture = Textures.loadTexture(io, file_alloc, "/terrain.png", gl.NEAREST);
^
/home/createsource/git/Minecraft-Zig/src/level/LevelRenderer.zig:56:56: 0x1276938 in new (RubyDung.zig)
const chunk: *Chunk = try Chunk.new(
^
/home/createsource/git/Minecraft-Zig/src/RubyDung.zig:162:51: 0x1277da6 in init (RubyDung.zig)
self.levelRenderer = try LevelRenderer.new(alloc, self.io, self.file_alloc, self.level);
^
/home/createsource/git/Minecraft-Zig/src/RubyDung.zig:326:27: 0x1279d93 in main (RubyDung.zig)
rd = try RubyDung.init(alloc);
^
/home/createsource/.cache/zig/p/N-V-__8AAFFSVRWqblwBIcA-Yqv-u7sbjsJoww8K0mWaHbmJ/lib/std/start.zig:698:59: 0x127a2d5 in callMain (std.zig)
if (fn_info.params.len == 0) return wrapMain(root.main());
^
../sysdeps/nptl/libc_start_call_main.h:58:16: 0x7fabe382a1c9 in __libc_start_call_main (../sysdeps/x86/libc-start.c)
../csu/libc-start.c:360:3: 0x7fabe382a28a in __libc_start_main_impl (../sysdeps/x86/libc-start.c)
???:?:?: 0x12b6944 in ??? (???)
Aborted (core dumped)```
GLU usage
const GLU = @cImport({
@cInclude("GL/glu.h");
});
...
const w: c_int = @intCast(img.width);
const h: c_int = @intCast(img.height);
const data: *u8 = &img.data[0];
_ = GLU.gluBuild2DMipmaps(gl.TEXTURE_2D, gl.RGBA, w, h, gl.RGBA, gl.UNSIGNED_BYTE, data);
build.zig
const exe = b.addExecutable(.{
.name = "minecraft_zig",
.root_module = b.createModule(.{
.root_source_file = b.path("src/RubyDung.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
// Here "foo" is the name you will use in your source code to
// import this module (e.g. `@import("foo")`). The name is
// repeated because you are allowed to rename your imports, which
// can be extremely useful in case of collisions (which can happen
// importing modules from different packages).
.{ .name = "zstbi", .module = b.dependency("zstbi", .{}).module("root") },
.{ .name = "zgl", .module = b.dependency("zopengl", .{}).module("root") },
.{ .name = "zglfw", .module = b.dependency("zglfw", .{}).module("glfw") },
},
.link_libc = true,
}),
});
if (target.result.os.tag == .windows) {
exe.root_module.addIncludePath(b.path("./include/"));
exe.root_module.addLibraryPath(b.path("./lib/"));
const glu = b.addTranslateC(.{
.root_source_file = b.path("include/GL/glu.h"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
exe.root_module.addImport("glu", glu.createModule());
exe.root_module.linkSystemLibrary("glfw3", .{});
exe.root_module.linkSystemLibrary("opengl32", .{});
exe.root_module.linkSystemLibrary("glu32", .{});
exe.root_module.linkSystemLibrary("gdi32", .{});
exe.root_module.linkSystemLibrary("shlwapi", .{});
} else {
exe.root_module.linkSystemLibrary("GLU", .{});
exe.root_module.linkSystemLibrary("GL", .{});
exe.root_module.linkSystemLibrary("glfw3", .{});
}
im on linux so anything to do with windows isnt the focus atm. i wrote this originally on windows but have since moved to linux
your issue is probably with the image data pointer (likely incorrect size), not the translated headers (although, @cImport is deprecated, and TranslateC in the build system should be used instead )
in general, when working with OpenGL (or GLU in this case, which uses OpenGL), when there is a segmentation fault it is likely due to invalid state or bad pointers being passed in. I suggest you turn on OpenGL's debugging features if possible as they will often give you more information on what exactly you did wrong
rgba (gl.RGBA/GL_RGBA) images have four channels, and unsigned byte (gl.UNSIGNED_BYTE/GL_UNSIGNED_BYTE) means that each of those channels has one byte per pixel. This means that each pixel takes four bytes, and if you have w*h pixels, that implies your pointer should be 4*w*h in size. if it is smaller, this will cause a segfault when the driver attempts to read back the image (it will look out of the bounds of the array, which is illegal)
i tried using @cImport but it doesnt allow me to use root for a path
you already have the header importing properly, otherwise the code wouldn't compile...
yeah
but yes, imports can't go out of the root module path, but you're supposed to use the build system instead of @cImport now anyways
ok i followed that tutorial
it shouldnt be segfaulting because of this because i use zstbi to get the image
i make sure to load the file with 4 components which is RGBA
you bring up an interesting point because
its the only allocator i use thats different from the normal one
i pass that in as the io allocator
maybe it should just be the normal heap allocator
io allocator should be good
well zsdtb.init passes in both io and alloc
actually where exactly are you getting this allocator?
well unfortunately that didnt work
so i was basically doing the std.threaded thing
and then stored both the allocator and the io of what i generated
and then used those as the inputs to init
but i just swapped that out for the heap alloc and that didnt work either
this
var threaded = std.Io.Threaded.init(alloc, .{});
self.file_alloc = threaded.allocator;
self.io = threaded.io();
idk if i should do it like that or not
i mean i just use the one passed in by init from the main function
i tried that too but no dice
do you have any way to check the length of that pointer?
woah woah woah
w * h != img.data.len
what?
oh ok it does equal 4 * w * h
ok thats intended that works
there's no allocation issue
how do i enable opengl debugging?
is GL_TEXTURE_2D bound
yes
does opengl 1.1 have debugging?
if you can request a newer debug context (for testing purposes) then you will definitely be able to enable debugging
i can do that
unless you have to use an older extension (forgive me, I'm familiar with much newer versions of gl than 1.1, i don't know if the proper methods are covered by the debugging extension), once you request a context with KHR_debug you should be able to glEnable GL_DEBUG_OUTPUT and GL_DEBUG_OUTPUT_SYNCHRONOUS, and then add a callback using glDebugMessageCallback, then finally use glDebugMessageControl to enable all of the messages
unsure if it will catch your error though
i see debugMessageCallbackKHR
im using zopengl btw
oh it supports khrdebug
oh i see a few errors
the only thing i see thats relevant is
ERROR: GL_INVALID_ENUM error generated. Cannot enable <cap> in the current profile.
source: 33350, type: 33356, id: 1280, severity: 37190, length: 76
you're using gl 1.1 functions right? make sure to enable the compatibility profile
bleh messing up my text
i did do that yeah
are there any other calls to glEnable?
this is probably unrelated to your texture issue though
yeah there's plenty