mistodon / gfx-hal-tutorials

A series of small gfx-hal tutorials.
129 stars 20 forks source link

Black window in part-2 with OpenGL backend and x11 #14

Open helmet91 opened 3 years ago

helmet91 commented 3 years ago

Hello,

I have encountered the following issue in part-2 of the tutorial: A black window appears when I'm trying to run the program. There are no errors on the console, neither during compilation, nor during runtime.

Environment: Linux OS with X11

Hardware:

OpenGL vendor string: Intel
OpenGL renderer string: Mesa Intel(R) HD Graphics 5500 (BDW GT2)
OpenGL core profile version string: 4.6 (Core Profile) Mesa 20.2.3
OpenGL core profile shading language version string: 4.60
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 4.6 (Compatibility Profile) Mesa 20.2.3
OpenGL shading language version string: 4.60
OpenGL context flags: (none)
OpenGL profile mask: compatibility profile
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.2 Mesa 20.2.3
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
OpenGL ES profile extensions:
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce 920M/PCIe/SSE2
OpenGL core profile version string: 4.6.0 NVIDIA 418.113
OpenGL core profile shading language version string: 4.60 NVIDIA
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 4.6.0 NVIDIA 418.113
OpenGL shading language version string: 4.60 NVIDIA
OpenGL context flags: (none)
OpenGL profile mask: (none)
OpenGL extensions:

As I have no access to a Vulkan-capable hardware, I switched to the gl backend. Also, I have added the x11 feature to the Cargo.toml file as follows:

[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies.backend]
package = "gfx-backend-gl"
version = "=0.6.1"
features = ["x11"]

With both rendering devices mentioned above, I get a black window, no triangles are shown. The part-1 of the tutorial worked correctly.

I have also tried to upgrade all dependencies in Cargo.toml to the currently available most up-to-date versions. This didn't fix the issue, while part-1 of the tutorial still worked.

Note: after upgrading winit, let dpi = event_loop.primary_monitor().scale_factor(); has to be changed to something like let dpi = event_loop.primary_monitor().unwrap().scale_factor();, as the event_loop.primary_monitor() method now returns an Option.

Now, as I get no errors at all, I have absolutely no clue where to even start with debugging the code.

mistodon commented 3 years ago

Hi!

So these tutorials purposely don't support OpenGL. This is partly because when I started them, the setup for OpenGL was drastically different and it would've complicated the tutorials. But it's also because OpenGL is just less compatible with the gfx/Vulkan API in general. There's a lot of finnicky little differences and (probably) bugs. That's not to say I'll never support OpenGL - I've actually been looking into it for another project - but for now, I can't guarantee that anything in this repo will work with it.

That said, I'll keep this open to at least track the issue. And I can try to help a little.

One thing I ran into when trying to get OpenGL working is that push constants are just not really something it supports. Gfx-hal I believe tries to simulate them with a single shader uniform, but I've not managed to get a push constants struct working in OpenGL. This might be the problem you're seeing. To test this, you could maybe try packing all the data into one field. I'm running on macOS but this seemed to work for me, with the OpenGL backend:

// part-2.vert
#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(push_constant) uniform PushConstants {
    vec4 pos_scale;
} push_constants;

layout(location = 0) out vec4 vertex_color;

vec2 positions[3] = vec2[](
    vec2(0.0, -0.5),
    vec2(-0.5, 0.5),
    vec2(0.5, 0.5)
);

void main() {
    vec2 pos = positions[gl_VertexIndex] * push_constants.pos_scale.zw;
    vertex_color = vec4(1.0, 1.0, 1.0, 1.0);
    gl_Position = vec4((pos + push_constants.pos_scale.xy), 0.0, 1.0);
}
// part-2-push-constants.rs
...
#[repr(C)]
#[derive(Debug, Clone, Copy)]
struct PushConstants {
    pos_scale: [f32; 4],
}
...
                let triangles = &[
                    // Red triangle
                    PushConstants {
                        pos_scale: [-0.5, -0.5, small[0], small[1]],
                    },
                    ...
                };
...

Obviously this is pretty restrictive - hardcoding color etc. You could pack even more information into one field if you use a mat4, but probably it would be a better idea to avoid push constants entirely for OpenGL and use descriptor sets instead. Part 4 will talk about those, but no promises on when I finish that šŸ˜¬.

Still, I hope this explains some things - and maybe unblocks you from playing around with gfx-hal a bit more!

helmet91 commented 3 years ago

Thanks for the heads up!

Initially I thought, gfx-hal was a "one framework to rule them all" kind of thing, and now I'm a bit sad that it's not the case. But it's actually understandable, and thinking about it this way, probably I will be able to make it work.

Thank you again for your help!

Edit: I've made a quick search among the issues of gfx-hal, and there indeed seems to be a potential bug that's affecting this: https://github.com/gfx-rs/gfx/issues/3192

mistodon commented 3 years ago

Yeah, I do think that's the intent for the library - but OpenGL is very different in architecture from the other more modern APIs, so it's gonna take a little longer for it to be fully supported to the same degree maybe?

Good find on that issue - I'll have a read of it. If you run into any other issues - OpenGL or otherwise - let me know and I'll see if I can help!