glfw: Force init before using init dependent functions #61
Labels
No labels
CI
all
basisu
blog
bug
build
contributor-friendly
core
correctness
deferred
dev
direct3d-headers
docs
driver-os-issue
duplicate
dxcompiler
editor
examples
experiment
feature-idea
feedback
flac
freetype
gamemode
gkurve
glfw
gpu
gpu-dawn
harfbuzz
help welcome
in-progress
infrastructure
invalid
libmach
linux-audio-headers
long-term
mach
mach.gfx
mach.math
mach.physics
mach.testing
model3d
needs-triage
object
opengl-headers
opus
os/linux
os/macos
os/wasm
os/windows
package-manager
priority
proposal
proposal-accepted
question
roadmap
slipped
stability
sysaudio
sysgpu
sysjs
validating-fix
vulkan-zig-generated
wayland-headers
website
wontfix
wrench
www
x11-headers
xcode-frameworks
zig-update
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
hexops/mach#61
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
glfws order dependent API design makes sense according to glfw implementation, but is quite silly from a glfw user perspective. I'm confident we can improve the API (hopefully without deviating too much from the C API)
My previous suggestion did not turn out well. Now, vulkan is a very big API, but one thing that I realized is that the design of the API makes it impossible to call functions in the wrong order by forcing you to instantiate an
vkInstancethat you then can call functions from. This is again used for later concepts in Vulkan. This concept can be used in the glfw API too!If init expose all functions that require init through a returned struct, then we can make it impossible to end up with the init error scenario, and this pattern can be used for other similar order dependent function (if there are any)
I also have similar issue in my own 2d rendering API: issue 41
If others have feedback here on whether or not they like/dislike this, I'd love to hear it. One thing I struggle with here is:
While this is a clear win, it's also a clear substantial deviation from the current GLFW API. Where we otherwise added methods, enums, etc. you'd have to pass those around regardless. But with this, you need to pass around the API struct too / can't rely on globals. This could make porting existing code harder.
For new APIs such as your 2D rendering API, though, this is a clear win obviously. I'm just not sure if the benefits (relatively small chance you forget to call glfw.init) outweight the costs (harder to port code). Not to say I am against this, just... unsure?
I personally would really like this change, but playing the devil's advocate here: I think it could be argued that something like this would be best made as a separate abstraction on top of the bindings, to remain as consistent as possible with canonical GLFW.
I agree this change would be a deviation from the original API. I am also not sure if the gains are worth it, so feel free to close the issue for now @slimsag 😅
(just clarifying, PR for this is welcome)
I've tried my hand at making a draft of the proposed solution, but it generally always ended up being more cumbersome than what we currently have, being that you can't actually use an instance of a struct to access its public decls, leading to the need to have more C-like
createWindowdeclarations within the returned struct, with a self parameter, to be able to make the guarantees this proposal aims to promise.Though, an alternative occurred to me, working on #81: we could instead try and guarantee function call order via runtime checks when in debug mode, which are disabled when in any other mode. E.g.:
Rough example, obviously could be greatly improved by modularizing/namespacing these things, such that they would be accessible from within all relevant parts of the library, but not outside, but this is the outline. Any thoughts, in favor, in opposition?
Edit: and to clarify, I really did try a slew of ideas before coming to this, such as having
comptimetypefields to limit the access of things likeWindowto the instance, which has its own issues and inconveniences.Oh wow, I hadn't thought of that, I guess we would need stack capturing ala https://github.com/ziglang/zig/issues/6965 in order to make that a nice experience. Very interesting.
I like your proposal a lot. At first, I wasn't sure what benefit it would give us over what GLFW already does internally (after all, it's functions are documented as returning an error if GLFW is not initialized). I see two major benefits:
Sounds like the right path forward to me!
I also like that this reduces my original complaint here: "This could make porting existing code harder."
Righto, if that's the new direction, I'll look into trying to come up with a more elaborated draft proposal in the coming days, 'less someone else makes one first.