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

Add OpenGL renderer #53150

Closed
wants to merge 33 commits into from
Closed

Conversation

Calinou
Copy link
Member

@Calinou Calinou commented Sep 27, 2021

Based on @lawnjelly's efforts on the GLES2 renderer here: #44399 🙂

Despite the news article stating that OpenGL support will return in Godot 4.1, this pull request is targeting a merge for Godot 4.0. However, we don't expect this OpenGL renderer to be fully complete (especially on the 3D side) when Godot 4.0 is released. Nonetheless, it may still be sufficient for many 2D games and non-game applications that want to maximize compatibility.

Commits are unsquashed for now to ease troubleshooting and tracking regressions. Most of them should be squashed before merging this PR.

This closes godotengine/godot-proposals#877.

OpenGL renderer's advantages over Vulkan

  • Much better compatibility with old devices (desktop, mobile).
  • Can run on HTML5 using WebGL 2.0 once the platform layer is reimplemented.
  • Faster startup times thanks to simpler shaders (even with the lack of shader caching).

When targeting desktop platforms, using Vulkan is still recommended for several reasons:

Vulkan renderer's advantages over OpenGL

  • Better visuals and performance in complex scenes.
    • If you need a lower base cost for integrated graphics or low-end dedicated GPUs, this can be achieved by using the Vulkan Mobile backend on desktop platforms.
  • No issues with AMD GPU performance on Windows (due to subpar OpenGL implementation).

Nonetheless, for mobile platforms, I expect OpenGL to be more prevalent for a while.

Differences from lawnjelly's pull request

  • OpenGL 3.3 / OpenGL ES 3.0 / WebGL 2.0 is now used as a baseline. The renderer will still follow a low-end-friendly approach to maximize performance and compatibility on low-end devices.
  • Removed the gles_common abstraction as there will only be one OpenGL renderer.
  • "GLES2" renderer renamed to "OpenGL" for consistency with the Vulkan renderer, which does not specify a version in its name. Use --rendering-driver opengl to force a project to start with the OpenGL renderer, or use the dropdown in the top-right corner of the editor.

Current limitations

  • 2D only. No 3D rendering support for now.
    • Getting 2D rendering support to be reliable for daily use is the current priority, as it'll unblock contributors who don't have a GPU that supports Vulkan.
  • Only the Linux/X11 context is currently implemented. Due to this, the OpenGL renderer can't be used on Windows, macOS, Android, iOS and HTML5 yet.

TODO

  • 2D editor viewport rendering is currently broken, but the running project displays correctly.
  • The OpenGL Core profile should be used instead of the Compatibility profile. The compatibility profile was temporarily enabled to allow Godot to render correctly after switching from a GLES2 context to a GLES3 context.
  • Shaders should be ported from GLSL ES 1.0 to GLSL ES 3.0 using the Vulkan GLSL shaders as a base.
  • Some texture functions need to be reimplemented.
  • The buildsystem code should be checked to make sure OpenGL and Vulkan can be disabled individually at compile-time. This lets people build smaller binaries when needed.
  • The shader compiler needs to be rewritten to use a modern approach. Ubershaders and asynchronous compilation will likely be used to avoid stutters during gameplay. This will be handled by @reduz and @RandomShaper.
  • Decide what to do with the GLES_ENABLED and OPENGL_BACKEND_ENABLED defines. Should we merge them with OPENGL_ENABLED to be consistent with VULKAN_ENABLED?
  • rasterizer_array.h should be replaced with LocalVector: https://github.com/Calinou/godot/blob/add-opengl-renderer/drivers/opengl/rasterizer_array.h#L37

Preview

Godot editor running on OpenGL

@clayjohn
Copy link
Member

A couple notes:

  1. Have you tested on Windows? I had GLES3 working in Windows on Lawnjelly's branch earlier, I imagine that it should be working or close to working still
  2. The rasterizer should not depend on the dummy rasterizer at all. For now, it should be enough to copy-paste the relevant sections of the dummy into the relevant files in drivers/GLES3

@qarmin
Copy link
Contributor

qarmin commented Sep 28, 2021

I think that it should be temporary to CI to see progress by adding --rendering-driver opengl to this commands(of course with removing swiftshader part)

# Editor is quite complicated piece of software, so it is easy to introduce bug here
- name: Open and close editor
if: ${{ matrix.proj-test }}
run: |
VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy -e -q --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt
# Run test project
- name: Run project
if: ${{ matrix.proj-test }}
run: |
VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} 40 --audio-driver Dummy --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt

@qarmin
Copy link
Contributor

qarmin commented Sep 28, 2021

On Intel HD 3000 and Mesa 21.3, I see empty screen in both project manager and editor
Zrzut ekranu z 2021-09-28 08-46-27
and also I see this errors

Mesa: User error: GL_INVALID_VALUE in glTexImage2D(internalFormat=GL_LUMINANCE)
Mesa: User error: GL_INVALID_ENUM in glEnable(GL_POINT_SPRITE)
Mesa: User error: GL_INVALID_ENUM in glGetString(GL_EXTENSIONS)
Mesa: User error: GL_INVALID_OPERATION in glDrawArrays
Mesa: User error: GL_INVALID_OPERATION in glVertexAttribPointer(no array object bound)
Mesa: User error: GL_INVALID_OPERATION in glDrawArrays
Mesa: User error: GL_INVALID_OPERATION in glVertexAttribPointer(no array object bound)
Mesa: User error: GL_INVALID_OPERATION in glVertexAttribPointer(no array object bound)
Mesa: User error: GL_INVALID_OPERATION in glVertexAttribPointer(no array object bound)
Mesa: User error: GL_INVALID_OPERATION in glDrawElements
Mesa: User error: GL_INVALID_OPERATION in glVertexAttribPointer(no array object bound)
Mesa: User error: GL_INVALID_OPERATION in glDrawArrays
Mesa: User error: GL_INVALID_VALUE in glTexImage2D(internalFormat=GL_LUMINANCE_ALPHA)
Mesa: User error: GL_INVALID_VALUE in glTexImage2D(internalFormat=GL_LUMINANCE_ALPHA)

@Calinou
Copy link
Member Author

Calinou commented Sep 28, 2021

On Intel HD 3000 and Mesa 21.3, I see empty screen in both project manager and editor

That's likely because of one of two reasons:

  • Mesa doesn't implement the OpenGL compatibility profile fully (or at all).
  • The NVIDIA driver I use for development is more permissive and allows Godot to render correctly in compatibility mode, but Intel's driver isn't as permissive.

The renderer will be modified to use core profile eventually, but this will take a while.

Also, remember that Sandy Bridge IGPs don't have fully functional OpenGL 3.3 support. It's nonexistent on Windows and very limited on Linux (to the point of being unusable).

@jordo
Copy link
Contributor

jordo commented Sep 28, 2021

Is Godot 4.0 launching without html5/web support then?

@Calinou
Copy link
Member Author

Calinou commented Sep 28, 2021

Is Godot 4.0 launching without html5/web support then?

It depends on whether we can finish this OpenGL renderer (+ the WebGL platform port) in time for 4.0's release. We can't promise anything yet. Either way, 3.x will remain supported until 4.1 is released.

WebGPU isn't likely to be implemented until 4.1 at least, so OpenGL via WebGL is our only option for HTML5 in the short term.

@jordo
Copy link
Contributor

jordo commented Sep 28, 2021

It depends on whether we can finish this OpenGL renderer (+ the WebGL platform port) in time for 4.0's release. We can't promise anything yet. Either way, 3.x will remain supported until 4.1 is released.

WebGPU isn't likely to be implemented until 4.1 at least, so OpenGL via WebGL is our only option for HTML5 in the short term.

Would love a concise answer. I understand 3.x is supported, but my question was specific to 4.0. I'm not looking for promises, it would just be nice to be clear about this so developers can plan accordingly. From other contributer comments, it seems Vulkan is going to be the only supported initial backend for 4.0. Connecting the dots would therefore mean that web export won't be supported in 4.0 correct? WebGPU isn't a viable option right now, nor the relatively near future.

I think this is an important platform to confirm this one way or the other.

@jordo
Copy link
Contributor

jordo commented Sep 28, 2021

I guess the PR of the actual renderer impl isn't the best place to ask these questions, but it would be nice to know if the plan is to have this available in 4.0 or not. It's fine either way, just nice to know so people can plan and adjust accordingly.

@Calinou
Copy link
Member Author

Calinou commented Sep 28, 2021

Connecting the dots would therefore mean that web export won't be supported in 4.0 correct?

Indeed, the HTML5 export and web editor won't be available in 4.x until some way to render graphics is implemented in the master branch. This means it's not likely to happen for 4.0, unless this OpenGL renderer becomes mature enough in a short amount of time.

@Calinou
Copy link
Member Author

Calinou commented Oct 4, 2021

  1. Have you tested on Windows? I had GLES3 working in Windows on Lawnjelly's branch earlier, I imagine that it should be working or close to working still

The Windows build (compiled with MinGW) seems to crash on startup, but Vulkan also crashes in the same branch anyway. I haven't investigated this yet.

I tested X11 again today and it still works as expected, both with OpenGL and Vulkan (from the same binary).

@clayjohn
Copy link
Member

clayjohn commented Oct 4, 2021

This is a good start! I was able to get it running on Windows (PR here Calinou#6)

A couple of things we need to take a look at still:

  1. It looks like viewports are not working
  2. The renderer is still using deprecated functionality not available in OpenGL 3.3, we should transition to OpenGL 3.3 fully before merging (can can likely copy-paste a lot from the GLES3 drivers)
  3. Multiple windows are not working (and single window mode is broken because of 1)

@clayjohn
Copy link
Member

clayjohn commented Oct 4, 2021

I think the next step should be to remove our usage of the GLES2 API. That will allow us to use renderdoc and diagnose why viewports are not working correctly.

@kisg
Copy link
Contributor

kisg commented Oct 16, 2021

Just a question: Wouldn't it be feasible to implement the OpenGL backend as a RenderingDevice? For example wgpu-rs is implementing the same interface in their GLES implementation as Vulkan (and DX12, Metal ... etc.):
https://github.com/gfx-rs/wgpu/tree/master/wgpu-hal/src/gles

Yes, there are a lot of quirks they also list in their mod.rs, but it could still be worth it if the rest of the renderer (probably only the mobile version) could be reused. Shaders are of course an issue, but they could be handled by e.g. SPIRV-Cross.
What do you think?

@Calinou
Copy link
Member Author

Calinou commented Oct 17, 2021

@kisg There are several issues I can see with using RenderingDevice for an OpenGL (ES) renderer:

  • RenderingDevice is clearly designed with modern APIs in mind (Vulkan, Direct3D 12, Metal, WebGPU).
  • SPIR-V is poorly supported in OpenGL (even on desktop platforms that support OpenGL 4.6). The SPIR-V OpenGL extension support is very inconsistent – even the top-end emulators struggle with it. Relying it on a mandatory baseline seems to be a recipe for disaster. At this point, I don't even want to think what it looks like on mobile and web platforms 🙂
  • This renderer will target low-end usage, so code duplication isn't as much of a concern since it will have fewer features. However, getting all those features to work reliably across platforms is paramount.

@clayjohn
Copy link
Member

Okay, I've submitted a pull request that removes much of the deprecated GLES2 functions (enough to get core profile working anyway). I have also fixed the bug that made viewports not display. Calinou#7

So right now we have a minimal 2D renderer in OpenGL 3.3 on Windows. @Calinou If you can set the X11 platform to core profile and verify that it works there as well then I think we have a minimal working example here!

@Calinou
Copy link
Member Author

Calinou commented Oct 26, 2021

@clayjohn's pull request was merged, which means the 2D editor now works as expected:

image

Using single-window mode is still recommended for now, as the main window will currently appear to freeze when a subwindow is open (at least on Linux).

Edit: Rebased against the latest master branch.

@clayjohn
Copy link
Member

@Calinou What is needed to get this out of draft? Perhaps just removing rasterizer_array?

In my opinion, we should be merging this sooner rather than later, even in its incomplete state so that we can unblock contributors.

@akien-mga
Copy link
Member

Build fix:

diff --git a/drivers/opengl/shader_compiler_opengl.cpp b/drivers/opengl/shader_compiler_opengl.cpp
index 9638626d78..3b4ea1d30c 100644
--- a/drivers/opengl/shader_compiler_opengl.cpp
+++ b/drivers/opengl/shader_compiler_opengl.cpp
@@ -860,7 +860,7 @@ Error ShaderCompilerOpenGL::compile(RS::ShaderMode p_mode, const String &p_code,
                        print_line(itos(i + 1) + " " + shader[i]);
                }
 
-               _err_print_error(NULL, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER);
+               _err_print_error(NULL, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
                return err;
        }
 

Could also be true if we want it shown in the toaster, but if it's a full shader dump probably not :P

@Calinou
Copy link
Member Author

Calinou commented Oct 26, 2021

What is needed to get this out of draft? Perhaps just removing rasterizer_array?

Sounds good to me. We should see if we can hide the 3D editor (and use 2D as the default editor) when using OpenGL, but this can be done in a future PR.

@clayjohn
Copy link
Member

Sounds good to me. We should see if we can hide the 3D editor (and use 2D as the default editor) when using OpenGL, but this can be done in a future PR.

I don't think we need to worry. We won't expose OpenGL as an option under the "New Project" menu until we add the 3D renderer (which shouldn't take long as we will mostly be copying the GLES2 renderer).

@akien-mga
Copy link
Member

Yeah I think it's fine if there are obvious broken things in 3D, no need to work it around. Bugs in WIP features are expected :) That can be an incentive for contributors to help fix some of the issues if they're interested.

@@ -31,6 +31,2833 @@
#include "export.h"

#include "export_plugin.h"
//#include "core/config/project_settings.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im guessing we can get rid of all the commented out code?

@@ -31,6 +31,1929 @@
#include "export.h"

#include "export_plugin.h"
//#include "core/config/project_settings.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above? Should we really be adding thousands of lines of commented out code?

@@ -32,6 +32,678 @@

#include "export_plugin.h"

/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am seeing a theme. Perhaps @lawnjelly knows why this code is included but is commented out

Copy link
Member

@lawnjelly lawnjelly Oct 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bear in mind this is originally from a very WIP branch. I've a feeling I copied these files either from the existing 4.x branch or 3.x and the compiler was complaining about them, so I just commented them out - had no idea whether they were still needed so keeping them commented allowed examining them later. I know very little about the exporters.

Actually I think they were during the rebase, so it may have represented changes in the exporters that had happened in the 6 months in between when I originally wrote it, so if the comments are the only difference in the diff, they are probably safe to delete.

@AaronRecord
Copy link
Contributor

AaronRecord commented Oct 26, 2021

It'd be nice if (maybe in a future PR) OpenGL could automatically be used if Vulkan isn't supported instead of having to manually specify to use OpenGL with the --rendering-driver OpenGL command line argument.

The renderer can still be changed in the Project Settings or using
the `--rendering-driver opengl` command line argument.
@Calinou
Copy link
Member Author

Calinou commented Oct 27, 2021

I removed commented out code and some OpenGL debugging prints. The renderer dropdown is also temporarily hidden until OpenGL support is more mature. You can still change the rendering driver in the advanced Project Settings or using --rendering-driver opengl.

There's still an issue with errors appearing on startup on a brand new project:

Vulkan

❯ bin/godot.linuxbsd.tools.64.llvm /tmp/4/project.godot --rendering-driver vulkan
Godot Engine v4.0.dev.custom_build.34bf39023 - https://godotengine.org
Vulkan API 1.2.189 - Using Vulkan Device #0: NVIDIA - NVIDIA GeForce GTX 1080

OpenGL

❯ bin/godot.linuxbsd.tools.64.llvm /tmp/4/project.godot --rendering-driver opengl
Godot Engine v4.0.dev.custom_build.34bf39023 - https://godotengine.org
ERROR: BUG: Unreferenced static string to 0: interface_added
   at: unref (core/string/string_name.cpp:116)
ERROR: BUG: Unreferenced static string to 0: interface_added
   at: unref (core/string/string_name.cpp:116)
ERROR: Property not found: rendering/quality/2d/use_nvidia_rect_flicker_workaround
   at: _get (core/config/project_settings.cpp:246)
ERROR: Property not found: rendering/quality/shading/force_lambert_over_burley
   at: _get (core/config/project_settings.cpp:246)
ERROR: Property not found: rendering/quality/shading/force_blinn_over_ggx
   at: _get (core/config/project_settings.cpp:246)
OpenGL Renderer: NVIDIA GeForce GTX 1080/PCIe/SSE2
ERROR: Condition "!props.has(p_prop)" is true.
   at: set_custom_property_info (core/config/project_settings.cpp:977)
ERROR: Condition "!props.has(p_prop)" is true.
   at: set_custom_property_info (core/config/project_settings.cpp:977)
ERROR: Property not found: rendering/quality/2d/use_software_skinning
   at: _get (core/config/project_settings.cpp:246)
ERROR: Property not found: rendering/quality/2d/ninepatch_mode
   at: _get (core/config/project_settings.cpp:246)

The interface_added StringName error in particular is a bit puzzling to me.

@Calinou
Copy link
Member Author

Calinou commented Oct 27, 2021

Superseded by #54307.

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

Successfully merging this pull request may close these issues.

Use OpenGL 3.3 for the low-end rendering backend
9 participants