-
Notifications
You must be signed in to change notification settings - Fork 541
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add callbacks for default gl framebuffer. #899
Conversation
Ok looks like I'll have to edit gen_zig.py to fix the GitHub action error...before I invest more time in this, does this seem like you'll merge this PR once the tests pass? |
I don't like this solution because it adds yet another fairly random backend-specific public API function. I think it's better to put this stuff as callbacks into the |
Ok, I think you misunderstood my PR message. This PR actually does reintroduce |
sokol_gfx.h
Outdated
@@ -7037,6 +7044,8 @@ _SOKOL_PRIVATE void _sg_gl_reset_state_cache(void) { | |||
|
|||
_SOKOL_PRIVATE void _sg_gl_setup_backend(const sg_desc* desc) { | |||
_SOKOL_UNUSED(desc); | |||
SOKOL_ASSERT(desc->context.gl.default_framebuffer_cb == NULL || desc->context.gl.default_framebuffer_userdata_cb == NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can omit the == NULL
, or at least replace the NULL
with 0
(yeah I know theoretically a NULL pointer doesn't have to be zero, but that's a very esoteric assumption).
(I would prefer removing the == NULL
alltogether.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removing == NULL
changes the meaning. I think you're thinking of != NULL
being removable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah right... I was confused because in other places I have asserts like this:
SOKOL_ASSERT(desc->context.d3d11.render_target_view_cb || desc->context.d3d11.render_target_view_userdata_cb);
...but in this case, one of the two callbacks must be set.
TL;DR: just replace the NULL with 0 and it's fine ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced NULL with 0. I noticed there are 19 other places that NULL is used in sokol_gfx.h, how do you decide when to use NULL and when to use 0?
Ah right, I didn't look at the actual changes, only saw that function. The simplified PR looks alright (but please check out my request above). (PS: I probably shouldn't review PRs in the middle of the night lol) Cheers! |
I'll let you revisit this PR after a full night's rest before I dig into making changes to gen_zig.py :) |
Hmm, from what I'm seeing, this shouldn't be necessary any longer with that setter function removed (this had a GLuint type, which the bindings generator scripts would reject - but in any case, the correct solution in that case would be to remove the GLuint with an uint32_t, since no backend specific types must show up in the public API). PS: CI is still failing though, weird. Anyway, I'm off for today :) |
(note to self: PS: was thinking about getting rid of associating resource objects with 'sokol-gfx contexts', but this would break the previous "one GL context per sokol-gfx context" behaviour, since AFAIK not all GL object types can be shared between GL contexts. ...could probably add a config flag to sg_desc though, and then we could use the existing context functions to switch between different sets of callbacks and swapchain attributes (pixel formats and sample count). Requires quite a bit of reworking the internals though :/ |
The PR as of right now does not have GLuint in the public API. The CI is failing because gen_zig.py doesn't support function pointers that return uint32_t, as is required by |
I like this idea. Much nicer than callbacks. |
I need to think about this idea a bit more, but unrelated to that change, if we would make the association of resource objects with sg_contexts optional, would that help your use case? In that situation, a context would basically just describe a separate default framebuffer by pixel formats, sample count and a separate set of callback functions and would only need to be set before a default pass (although that assumption might be a bit optimistic, and may require more untangling in the sokol-gfx implementation). You would then create an sg_context for every 'output view' and switch to it right before the default pass: sg_activate_context(ctx);
sg_begin_default_pass(...);
...
sg_end_pass(); ...unlike the GLFW multiwindow-sample there should only be a single The sg_begin_default_pass_with_context() would then just be 'API sugar' which would take an sg_context handle instead, and just get rid of the But TBH, this might require more internal changes than I'm currently ready to integrate ;) So I'd actually first like to go with a 'minimally invasive' procedure that works for your use case, and after that maybe continue working on a cleaner overall structure. (e.g. another thing that popped into my mind was having a single sg_begin_pass(&(sg_pass_options){
.pass = pass_object,
.action = { ... },
}); A vanilla default pass would look like this: sg_begin_pass(&(sg_pass_options){
.width = sapp_width(),
.height = sapp_height(),
.action = { ... },
}); ...and a default pass into a specific context would look like this: sg_begin_pass(&(sg_pass_options){
.width = sapp_width(),
.height = sapp_height(),
.action = { ... },
.context = ctx,
}); Also, a better name for These are big API changes that I don't want to do in a random 'drive-by' PR though, but I feel like this is would provide a much cleaner overall structure. ...btw, on GL, are you actually using a single GL context? If yes how does that work in the window system glue, what I've seen so far is that each 'view' has its own GL context (like in GLFW for instance). |
If you want a minimally invasive approach that handles my use case, the changes in this PR as it stands now is that, and brings the GL API in line with the others (in terms of all having callbacks). If we want to go with a more meaningful change, I think a single "begin pass" function that can be used for both offscreen and default passes is the nicest solution. That would allow user functions to accept a I think altering the behavior of sokol_gfx's contexts is less appealing because drawing to a different destination is conceptually more like a pass and less like GL's concept of a context. And like you said, contexts are sort of an old idea that doesn't fit well with newer apis, so you don't really want to invest more in that concept. Rendering to multiple destinations is something that I want to do with Metal too. So in summery, (Depending on how much you want to alter the API) we could do one of these 3:
Yes, I use a single GL context. I overrode this function in CAOpenGLLayer to return the same global // from CAOpenGLLayer.h
/* Called by the CAOpenGLLayer implementation when a rendering context
* is needed by the layer. Should return an OpenGL context with
* renderers from pixel format 'pf'. The default implementation
* allocates a new context with a null share context. */
- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pf; Later I get called in
Given that each CAOpenGLLayer calls me when it needs redrawing, I'd have to find a way to run sg_commit() at the end of the current event loop in order to guarantee it is called after any/all windows did their drawing. Sort of messy, but I don't see a way to share mutable sg resources between windows without that requirement. On another note, thanks for taking my feedback seriously and wanting to get this right. |
Oki doki, then let's do this as the first step! I guess I'll take another week for catching up on PRs and issues, before going back to the WebGPU backend. Thanks for your input btw, it helps me to look differently at old ideas that had been baked into the API from the start. Thinking back I never was quite happy with the |
Looking into this now... |
...and merged! I also upated a small blurb to the changelog. |
...oops, something broke in the Rust bindings, need to figure out why this doesn't trigger in the regular tests. I'm on it... |
...ok, this was just a missing |
...heh ok the |
Thanks for accepting the PR! Looking forward to helping with #904 next! |
fixes #892
There is a simpler fix of adding this function, but I figured you might not want to add backend-specific public apis.
This is nicer for the end user than the callback approach, because you don't have to create the callback and a global. and set the global before calling sg_begin_default_pass.