Skip to content
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

Using with sokol? #21

Closed
tomas opened this issue May 8, 2024 · 12 comments
Closed

Using with sokol? #21

tomas opened this issue May 8, 2024 · 12 comments

Comments

@tomas
Copy link

tomas commented May 8, 2024

Hi! I just tried using portableGL with one of the examples in the sokol repository (app + gfx), but the compiler whines about missing functions:

Expand
/usr/bin/ld: /tmp/ccBE58hl.o: in function `_sg_gl_init_caps_glcore33':
triangle-sapp.c:(.text+0x3061d): undefined reference to `glGetStringi'
/usr/bin/ld: /tmp/ccBE58hl.o: in function `_sg_gl_reset_state_cache':
triangle-sapp.c:(.text+0x31259): undefined reference to `glColorMask'
/usr/bin/ld: /tmp/ccBE58hl.o: in function `_sg_gl_create_image':
triangle-sapp.c:(.text+0x31d0c): undefined reference to `glRenderbufferStorageMultisample'
/usr/bin/ld: triangle-sapp.c:(.text+0x31df1): undefined reference to `glRenderbufferStorageMultisample'
/usr/bin/ld: triangle-sapp.c:(.text+0x322bc): undefined reference to `glTexParameterf'
/usr/bin/ld: triangle-sapp.c:(.text+0x322ea): undefined reference to `glTexParameterf'
/usr/bin/ld: triangle-sapp.c:(.text+0x32445): undefined reference to `glCompressedTexImage2D'
/usr/bin/ld: triangle-sapp.c:(.text+0x32561): undefined reference to `glCompressedTexImage3D'
/usr/bin/ld: /tmp/ccBE58hl.o: in function `_sg_gl_create_pass':
triangle-sapp.c:(.text+0x33f40): undefined reference to `glFramebufferTextureLayer'
/usr/bin/ld: triangle-sapp.c:(.text+0x34067): undefined reference to `glDrawBuffers'
/usr/bin/ld: triangle-sapp.c:(.text+0x34212): undefined reference to `glFramebufferTextureLayer'
/usr/bin/ld: triangle-sapp.c:(.text+0x3426e): undefined reference to `glDrawBuffers'
/usr/bin/ld: /tmp/ccBE58hl.o: in function `_sg_gl_begin_pass':
triangle-sapp.c:(.text+0x34814): undefined reference to `glColorMask'
/usr/bin/ld: triangle-sapp.c:(.text+0x349fc): undefined reference to `glClearBufferfv'
/usr/bin/ld: triangle-sapp.c:(.text+0x34a62): undefined reference to `glClearBufferfi'
/usr/bin/ld: triangle-sapp.c:(.text+0x34a89): undefined reference to `glClearBufferfv'
/usr/bin/ld: triangle-sapp.c:(.text+0x34aba): undefined reference to `glClearBufferiv'
/usr/bin/ld: /tmp/ccBE58hl.o: in function `_sg_gl_end_pass':
triangle-sapp.c:(.text+0x34d29): undefined reference to `glReadBuffer'
/usr/bin/ld: triangle-sapp.c:(.text+0x34d65): undefined reference to `glBlitFramebuffer'
/usr/bin/ld: /tmp/ccBE58hl.o: in function `_sg_gl_apply_pipeline':
triangle-sapp.c:(.text+0x35738): undefined reference to `glColorMaski'
/usr/bin/ld: /tmp/ccBE58hl.o: in function `init':

That's with the SOKOL_GLCORE33 option. Using SOKOL_GLES2 gets us closer but still no workie:

Expand
/usr/bin/ld: /tmp/cc03flIg.o: in function `_sg_gl_reset_state_cache':
triangle-sapp.c:(.text+0x2ff93): undefined reference to `glColorMask'
/usr/bin/ld: /tmp/cc03flIg.o: in function `_sg_gl_create_image':
triangle-sapp.c:(.text+0x30c7c): undefined reference to `glCompressedTexImage2D'
/usr/bin/ld: /tmp/cc03flIg.o: in function `_sg_gl_begin_pass':
triangle-sapp.c:(.text+0x32dd0): undefined reference to `glColorMask'
/usr/bin/ld: triangle-sapp.c:(.text+0x32ef9): undefined reference to `glClearDepthf'
/usr/bin/ld: /tmp/cc03flIg.o: in function `_sg_gl_apply_pipeline':
triangle-sapp.c:(.text+0x33990): undefined reference to `glColorMask'
/usr/bin/ld: /tmp/cc03flIg.o: in function `init':

Am I missing some specific flag or #define, or is it simply because PortableGL doesn't implement those functions (yet)?

Thanks in advance!

@rswinkle
Copy link
Owner

rswinkle commented May 8, 2024

Am I missing some specific flag or #define, or it it simply because PortableGL doesn't implement those functions (yet)?

You're not missing any flag or define, those are just functions that I've never used or run into in any of my ports and so have never implemented or added to gl_stubs.h and gl_stubs.c.

Some of those, like glColorMask wouldn't be too hard to implement, and I probably will even if they're hardly ever used and have a small performance cost (so many extra branches for all the features in the fragment processing pipeline...I sometimes wonder if I should have even bothered implementing stenciling for example).

Some like TexParameterfv and GetStringi aren't really useful for PortableGL (there are no "extensions" to give GetStringi a point to exist), and PortableGL doesn't support texture border colors which is the only thing I've ever seen TexParameterfv used for. So those would definitely stay as stubs unless/until I think of a use for them. Same with compressed textures. Most people have far more RAM than VRAM and it's not worth complicating PGL to add support for compressed textures, let alone all the different kinds. I don't even support more than RGBA32 internally so far..

On the other hand, anything related to RenderBuffers/FrameBuffers/DrawBuffers is definitely a stub only as PGL doesn't (yet) have any support for multiple frame buffers or different types of frame buffers or even rendering to a texture directly (have to do a wasteful copy manually (see swrenderer demo). Those features (at least in some form) have long been on the TODO list to complete before 1.0 but they require a lot of time to think of the best way to implement them, taking into account PGL's goals/priorities and weighing that against what the spec says.

TL;DR I'll add all of those to stubs for a possible quick fix (hopefully neither your use case nor sokol internally actually needs those things implemented to work. I'm assuming sokol just calls them in some non-default code paths). Longer term, when I have a little time I'll implement color masking.

Actually looking at some of these functions, I just realized I have to decide whether to keep the API's with parameters specified using GLclampf/d as in 3.3 or change them to GLfloat/GLdouble

@tomas
Copy link
Author

tomas commented May 8, 2024

Wow, thank you for the quick and very detailed response!

If it helps, this is the sokol_gfx.h header where all those functions are being called, and this is the example app I'm trying to build.

The reason why I was testing this is because I want to run my GIF player (which is based on sokol) on an old laptop that doesn't support OpenGL 2+, which sokol depends on. I think I could make it work using mesa, but I'd much rather use PortableGL, in the spirit of staying lean. ;)

@rswinkle
Copy link
Owner

rswinkle commented May 9, 2024

Try it now. I tried to add every function mentioned in your compile error but I was in a hurry and I might have missed one.

Also, I didn't have time to actually clone and try out your GIF player but it looks cool. You can definitely use PGL to play GIFS, possibly using a 2D texture array like I do for the texturing demo here with these shaders..

Let me know if you run into any more issues. I'll leave this open for another few days at least.

@tomas
Copy link
Author

tomas commented May 9, 2024

Great! You only missed one function (glClearBufferfi), which I added manually and now the thing builds!

However, now I don't have a clue how to bind portableGL's context to to the actual one used by sokol...

Anyway, thanks for the help!

@rswinkle
Copy link
Owner

rswinkle commented May 10, 2024

Great! You only missed one function (glClearBufferfi), which I added manually and now the thing builds!

Darn! I knew I probably missed one. I added a lot more than were listed because I figured I might as well add whole "families" of functions and it just got lost in the shuffle.

EDIT: Ah, it was a typo, I added "glClearBufferi", sigh. Moving to fast, coding in the middle of the night smh.

However, now I don't have a clue how to bind portableGL's context to to the actual one used by sokol...

PortableGL doesn't have a "real" GL context and doesn't have any reason to talk directly to a real one.

Maybe I'm misunderstanding what you're trying to do, but there are only two uses I can think of. Either PortableGL becomes a backend of sokol which makes sense if it doesn't already have a software rendering backend, or it's used offscreen and the PGL framebuffer is just used as a texture in sokol/real OpenGL. Not sure if the latter even makes sense because if you already have access to real OpenGL you could just use that to render to an offscreen texture with HW acceleration.

In the first case, integrating PGL into sokol_gfx.h could be quite a lot of work depending on how you do it. I didn't spend enough time looking through it to be able to give you any solid direction but I'm sure it's possible one way or another. Since your app uses X11 directly, PGL would blit to X11 and that whole process would be wrapped in sokol as I understand it.

@tomas
Copy link
Author

tomas commented May 10, 2024

Either PortableGL becomes a backend of sokol which makes sense if it doesn't already have a software rendering backend, or it's used offscreen and the PGL framebuffer is just used as a texture in sokol/real OpenGL.

Yup, it's the first scenario, and it does seem like a major challenge because there's a lot of stuff going on in sokol_gfx.h. I thought I could use PortableGL as a semi-drop-in replacement for -lGL and it would just work...

I guess a quicker test would be to try and use PortableGL with something like GLFW (which exposes the GL stuff instead of wrapping everything up like sokol). Have you tried using PortableGL with GLFW or a similar library?

@rswinkle
Copy link
Owner

Yup, it's the first scenario, and it does seem like a major challenge because there's a lot of stuff going on in sokol_gfx.h. I thought I could use PortableGL as a semi-drop-in replacement for -lGL and it would just work...

Yeah this is a semi-common misconception. I need to add more to the README to clear up the confusion. PortableGL is not a real OpenGL implementation and it is definitely not a drop in replacement for libGL.so or similar. If you want that, Mesa is probably your best bet, though there are other options (often derived from Mesa or that used to be included in Mesa).

I guess a quicker test would be to try and use PortableGL with something like GLFW (which exposes the GL stuff instead of wrapping everything up like sokol). Have you tried using PortableGL with GLFW or a similar library?

This in another perfect example of the confusion. GLFW is a windowing and input library expressly made to work with OpenGL. It creates an OpenGL context with the window. There is no way to do software rendering with GLFW for that reason. This is why all the demos use SDL2, because you can do software rendering, ie just blitting a framebuffer to the screen, with SDL2. There is no way to do the same with GLFW short of ripping into the guts and hacking it to work but that would be ugly and very platform specific which defeats the purpose of using something like GLFW.

PGL is designed to be compiled statically into your project. You can make it a library (either dynamic/shared or static) but there's really no point to the former, and the only point to the latter is to save compilation time if you were compiling many individual PGL projects at the same time with the same configuration (IOW, I might be able to save a little time doing that when compiling all my demos, but not enough to make it worth it to me so far).

So, this gives PGL the two main use cases we talked about before:

  1. Using it with an existing project/library that lets you blit framebuffers in some fashion where PGL is just an extra feature/capability, like with pntr_portablegl but not necessarily used for the whole screen. You could do the same thing with many GUI toolkits that have the "render arbitrary pixels here" widget.
  2. As a software rendering backend (probably a fallback) for some application or library as long as the underlying windowing system supports it. For example Raylib when used with SDL2, but not with GLFW. This is much more complicated. Here's my direct port of the imguy OpenGL3 backend. There's also a header file. It works but it's very slow because it wastes a lot of time doing mostly unnecessary junk. On the other hand simply using PGL with the sdl_renderer backend has perfect performance. This is why I want to add something like SDL_RenderGeometry() directly to PGL.

The third rarer use case is just having PGL as a way to get OpenGL/3D rendering on platforms where Mesa won't work or is too much trouble to bother with. This is the advantage of PGL, it's so small and easy to adapt to someone's specific needs, like a hobby OS project or similar. Large complicated projects like Mesa or SoftGLRender are far less approachable/hackable and effectively, less portable.

@tomas
Copy link
Author

tomas commented May 13, 2024

GLFW is a windowing and input library expressly made to work with OpenGL. It creates an OpenGL context with the window. There is no way to do software rendering with GLFW for that reason.

Yes I see what you mean. I know this won't be a 100% drop in replacemente for -lGL, but it would be great to be able to use PortableGL in those scenarios where a "real" modern OpenGL context isn't available without having to rewrite the whole app. I was thinking something along these lines:

int main() {
  #ifdef USE_PORTABLE_GL
    // custom init 
  #else
    glfwInit();
  #endif
  
  GLFWwindow* w = glfwCreateWindow(...);

  while (!glfwWindowShouldClose(w)) {
    // draw stuff (glClear, glViewport, etc)

    #ifdef USE_PORTABLE_GL
      // render portable GL surface
    #else
      glfwSwapBuffers(w);
    #endif

    glfwPollEvents();
  }

  glfwTerminate();
  // etc
}

In other words, to be able to use the windowing/input logic from GLFW or sokol, and reuse the same OpenGL drawing logic, but swapping the glfwSwapBuffers/glxSwapBuffers with the blitting-to-screen logic. SDL2 is obviously an option but I was looking for something lighter...

Anyway, the examples you linked seem very helpful! Thanks again.

@tomas
Copy link
Author

tomas commented May 13, 2024

This might be a solution. :)

@rswinkle
Copy link
Owner

Yes I see what you mean. I know this won't be a 100% drop in replacemente for -lGL, but it would be great to be able to use PortableGL in those scenarios where a "real" modern OpenGL context isn't available without having to rewrite the whole app.

But your premise is flawed. You wouldn't/couldn't be using GLFW in a place where there is no real OpenGL. And again how are you going to get PortableGL's framebuffer to the screen with GLFW? SDL2 is a bigger dependency for sure, but there's a reason for that. It runs on far far more platforms than GLFW and provides more functionality, most importantly in this case, cross-platform framebuffer support.

Sokol itself doesn't actually depend on GLFW as far as I can tell, it is windowing system agnostic. Other than using something like SDL2 I don't know any other ways to achieve your goal of a single cross-platform code base that can use software rendering with PGL where OpenGL isn't available. If you were willing to go platform specific, you could use something like X11 or Windows GDI (or whatever they have now) directly, but again that's not ideal. Actually I think there are thin wrappers around platform specific windowing/input systems that might work if they expose the necessary features. They usually only support the majors (windows, linux, mac) but that's all GLFW supports already so you're not really losing anything they're a far smaller dependency than SDL2 or GLFW. I'd have to do some research.

Here are some references you might find interesting:
A really old question
A more recent thread about software rendering in GLFW

EDIT: I wrote everything above before your last comment. RGFW is exactly the type of minimal wrapper I was talking about. There are definitely several floating around. I'll take some time to look at that thread when I get a chance.

@tomas
Copy link
Author

tomas commented May 14, 2024

Yes, the RGFW example is what I was looking for. I only gave GLFW as an example because it seemed more plausible than with sokol. But you're right -- GLFW is too coupled with OpenGL to use PortableGL without having to crack it open.

@rswinkle
Copy link
Owner

I'm going to go ahead and close this since it seems we found your answer. Feel free to open another issue if you run into any more issues/questions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants